Skip to content

Media editor: Tidy the cropper contract before it is exposed - #85429

Draft
ramonjd wants to merge 5 commits into
trunkfrom
refactor/media-editor-cropper-contract
Draft

ramonjd wants to merge 5 commits into
trunkfrom
refactor/media-editor-cropper-contract

Conversation

@ramonjd

@ramonjd ramonjd commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

What

Small clean-ups to the cropper code in @wordpress/media-editor before any of it is made available outside the package. No behaviour change. Nothing is exported from the package yet.

Why

The cropper is the part of the media editor that a plugin, or a site without WordPress, could one day use on its own: the Cropper component, the hook that gives you its controller, and a few pure helpers. Its names, and the list of things it exports, become a commitment the moment anything outside the package imports them. This fixes the ones that would be awkward to change later, while changing them still costs nothing.

What changed

  • useCropperReducer is renamed useCropperController. The old name described how the hook is built: it wraps a reducer. What a caller gets back is the cropper's controller, which is the current state plus the setters such as setZoom and snapRotate90, reset, isDirty and getCroppedImage. Callers never see the reducer. The type is already called CropperController, and useCropper, which reads that same controller from CropperProvider, already calls it the controller. The new name says what you get, matches the type and the provider hook, and lands before anyone outside the package imports the old one.
  • src/image-editor/index.ts is the list of what the cropper exports. It also exported the helpers that only the media editor's own state code uses to drive the cropper through the pure reducer: cropperReducer, enforceContainment, areCropperStatesEqual, applyOperationToState, computeInscribedRect, buildCropperSetters and DEFAULT_STATE. Those move to a new file, src/image-editor/internals.ts, which the state code imports instead. The index keeps useCropperController, Cropper, CropperProvider, useCropper, the types, ORIGINAL_ASPECT_RATIO, getSourceRegion, stateFromPipeline, exportCroppedImage and applyToCanvas.
  • The list of default aspect-ratio presets, with its translated labels, moves out of src/image-editor/core into src/state, next to the rest of the preset handling. The core folder now has no @wordpress/i18n import, so it holds no user-facing text.
  • Two methods on the controller, setVisualSize and adjustCropRectForViewport, exist only so Cropper can report its rendered size and viewport changes. Their doc comments now say so, so nobody reads them as something to call.

The hook is named after its implementation. What it returns is the
cropper controller, and its sibling `useCropper` reads that controller
from the provider. Rename it before anything outside the package imports
it, after which the old name would need a deprecation cycle.
The previous commit moved the hook and its test to their new names; this
one points every import, call, comment and doc at `useCropperController`
and describes the hook as the controller it returns.
`DEFAULT_ASPECT_RATIOS` carried translated labels, the engine's only
user-facing strings and its only `@wordpress/i18n` import. The list now
lives in the session layer, which owns presets. The engine keeps the
`ORIGINAL_ASPECT_RATIO` sentinel and the preset type.
…rnals

`image-editor/index.ts` is the cropper's contract, but it also exported
what the media editor's session needs to delegate cropper actions through
the pure reducer: the reducer, containment, state equality, the setters
factory and the default state. A consumer building a cropper needs none
of that, and anything the barrel exports is a commitment. Those move to
`image-editor/internals`, which the session imports and the contract does
not mention.
`setVisualSize` and `adjustCropRectForViewport` exist for `Cropper`,
which reports its rendered size and viewport-driven reshapes through
them; the pure hook ignores one and aliases the other. On a controller a
consumer holds they read as things to call. Say what they are for.
@ramonjd ramonjd added the [Type] Code Quality Issues or PRs that relate to code quality label Oct 23, 2026
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

🤖 PR meta 🤖

Preview in WordPress Playground

📦 Bundle size

Size Change: 0 B

Total Size: 9.06 MB

0c18df0 Run

⚡ Performance

Show the results

Client side metrics exclude the server response time.

front-end-block-theme

Metric 9113d6a trunk % Change
timeToFirstByte 38.25 ms +3.92% -4.97% 37.3 ms +5.23% -1.74% 2.55%
largestContentfulPaint 68 ms +5.88% -5.88% 64 ms +6.25% -6.25% 6.25%
lcpMinusTtfb 28.25 ms +13.1% -8.85% 25.35 ms +6.31% -4.93% 11.44%
wpBeforeTemplate 19.47 ms +6.78% -1.75% 19.58 ms +3.58% -2.71% -0.56%
wpTemplate 15.18 ms +5.2% -4.94% 15 ms +2.13% -4.53% 1.2%
wpTotal 35.25 ms +4.06% -5.02% 34.38 ms +5.21% -1.77% 2.53%
wpMemoryUsage 7.67 MB +0% -0% 7.64 MB +0% -0% 0.43%
wpDbQueries 16 +0% -0% 16 +0% -0% 0%

front-end-classic-theme

Metric 9113d6a trunk % Change
timeToFirstByte 31.7 ms +2.37% -2.84% 31.3 ms +3.51% -2.88% 1.28%
largestContentfulPaint 72 ms +0% -5.56% 70 ms +2.86% -2.86% 2.86%
lcpMinusTtfb 40 ms +1.62% -5.63% 38.35 ms +6% -1.96% 4.3%
wpBeforeTemplate 17.12 ms +3.21% -1.69% 16.98 ms +2.12% -2.24% 0.82%
wpTemplate 12.11 ms +1.98% -7.76% 11.67 ms +3.43% -4.11% 3.77%
wpTotal 29.24 ms +2.77% -2.94% 28.83 ms +2.91% -2.88% 1.42%
wpMemoryUsage 6.36 MB +0% -0% 6.33 MB +0% -0% 0.53%
wpDbQueries 13 +0% -0% 13 +0% -0% 0%

media-processing

Metric 9113d6a trunk % Change
mediaProcessingJpeg 291.72 ms +9.94% -1.83% 287.12 ms +2.92% -0.63% 1.6%
mediaProcessingAvif 4138.82 ms +6.66% -0.18% 4162.05 ms +4.55% -0.33% -0.56%
mediaProcessingJpegToAvif 2818.21 ms +2.02% -0.38% 2842.98 ms +2.59% -0.68% -0.87%

media-upload

Metric 9113d6a trunk % Change
jpegUploadProcessing 1396.83 ms +0.26% -0.8% 1398.35 ms +1.17% -0.47% -0.11%
pngUploadProcessing 166.27 ms +3.87% -2.7% 163.7 ms +8.75% -4.34% 1.57%
largeJpegUploadProcessing 1401.8 ms +0.31% -1.15% 1401.2 ms +0.3% -1.5% 0.04%
multipleImageUploadProcessing 1462.71 ms +1.65% -0.19% 1457.41 ms +0.66% -0.92% 0.36%

post-editor

Metric 9113d6a trunk % Change
serverResponse 515.4 ms +2.45% -5.02% 505.08 ms +3.34% -4.33% 2.04%
firstPaint 350.79 ms +49.62% -26.01% 501.35 ms +3.7% -55.73% -30.03%
domContentLoaded 1188.05 ms +1.96% -1.47% 1202 ms +0.84% -2.78% -1.16%
loaded 1189.17 ms +1.96% -1.46% 1202.99 ms +0.88% -2.76% -1.15%
firstContentfulPaint 486.32 ms +9.38% -9.79% 517.41 ms +0.83% -4.27% -6.01%
firstBlock 3523.55 ms +2.26% -1.14% 3519.77 ms +3.02% -2.25% 0.11%
type 17.38 ms +4.66% -2.24% 17.87 ms +9.07% -3.75% -2.74%
typeWithoutInspector 17.33 ms +2.25% -6.35% 17.86 ms +7.39% -7.78% -2.97%
typeWithTopToolbar 22.65 ms +7.42% -4.46% 23.52 ms +1.83% -5.31% -3.7%
typeContainer 9.25 ms +10.16% -11.89% 8.63 ms +6.03% -6.6% 7.18%
focus 116.64 ms +6.32% -3.78% 127.18 ms +7.83% -9.08% -8.29%
firstFocus 243.32 ms +0% -0% 228.57 ms +0% -0% 6.45%
selectAll 588.14 ms +2.21% -6.2% 581.76 ms +0.58% -0.59% 1.1%
listViewOpen 77.4 ms +1.74% -5.01% 87.02 ms +4.3% -14.51% -11.05%
inserterOpen 42.7 ms +10.66% -5.15% 44.86 ms +2.65% -5.19% -4.81%
inserterHover 12.2 ms +8.28% -8.03% 11.69 ms +10.95% -8.81% 4.36%
inserterSearch 8.51 ms +9.52% -5.05% 8.12 ms +3.94% -9.61% 4.8%
loadPatterns 658.43 ms +7.02% -1.88% 652.97 ms +5.79% -1.61% 0.84%
wpTotal 505.68 ms +2.39% -5.33% 495.64 ms +3.32% -4.43% 2.03%
wpMemoryUsage 14.71 MB +0% -0% 14.67 MB +0% -0% 0.24%
wpDbQueries 55 +0% -1.82% 55 +0% -1.82% 0%

site-editor

Metric 9113d6a trunk % Change
serverResponse 412.07 ms +2.13% -8.55% 398.25 ms +1.78% -5.5% 3.47%
firstPaint 261.16 ms +23.57% -8.28% 252.23 ms +39.98% -9.37% 3.54%
domContentLoaded 1165.57 ms +1.72% -2.98% 1116.28 ms +2.15% -0.41% 4.42%
loaded 1166.6 ms +1.74% -2.95% 1117.23 ms +2.16% -0.42% 4.42%
firstContentfulPaint 491.64 ms +2.97% -6.72% 459.07 ms +7.11% -11.39% 7.09%
firstBlock 4095.96 ms +1.74% -0.93% 4000.51 ms +1.06% -1.48% 2.39%
type 18.5 ms +3.73% -3.84% 17.51 ms +7.14% -2.11% 5.65%
navigate 115.03 ms +4.06% -3.92% 109.35 ms +2.1% -2.62% 5.19%
loadPatterns 1220.9 ms +2.77% -6.2% 1173.95 ms +10.97% -2.56% 4%
loadPages 1020.29 ms +4.88% -4.14% 1031.76 ms +3.23% -5.57% -1.11%
wpTotal 402.51 ms +2.09% -8.72% 388.82 ms +1.75% -5.69% 3.52%
wpMemoryUsage 12.72 MB +0% -0% 12.69 MB +0% -0% 0.27%
wpDbQueries 44 +2.27% -0% 44 +2.27% -0% 0%

0c18df0 Run

🏁 Flaky tests

Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

Regression: updating a specific option will only change its value and will not corrupt others in /test/e2e/specs/editor/various/core-settings.spec.js, passed after 1 failed attempt.
Error: expect(received).toStrictEqual(expected) // deep equality

- Expected  - 1
+ Received  + 1

  Array [
    "rewrite_rules",
-   "SERIALIZED DATA",
+   "",
  ]
    at forEach (/home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/core-settings.spec.js:46:26)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/core-settings.spec.js:43:35

0c18df0 Run

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Code Quality Issues or PRs that relate to code quality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant