debounce the framing, or the preview reloads sixty times a drag

MediaField is controlled: it reports every pointer move and draws what it is
handed back. Wired straight to the block, that was a PATCH and a full reload of
the preview per move, and the page went white while somebody dragged.

The drag runs against local state now — instant — and the write is debounced by
useAutosave, the same hook every other control here uses.

The reset effect keys on the url and the shape, not on the crop. Keyed on the
crop it would fight the drag: the parent's value is the last SAVED one, so every
move would snap back until the save landed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-01 21:40:35 +01:00
co-authored by Claude Opus 5
parent 53d1937430
commit 3053765494
2 changed files with 61 additions and 8 deletions
+7 -8
View File
@@ -38,7 +38,7 @@ import { BandSettings } from './BandSettings';
import { BlockSettings } from './BlockSettings';
import { GalleryItems } from './GalleryItems';
import { PartnersEditor } from './PartnersEditor';
import { MediaField } from '../MediaField';
import { BlockMedia } from './BlockMedia';
/**
* The shapes a photograph block may take.
@@ -807,15 +807,14 @@ export const PageBuilderPanel = () => {
)}
{shapeOf(block) ? (
<MediaField
value={block.content?.url ?? null}
onChange={(url) => void handlersRef.current.setContent(block, { ...block.content, url: url ?? '' })}
<BlockMedia
url={block.content?.url ?? null}
crop={block.content?.crop ?? null}
onCropChange={(crop) =>
void handlersRef.current.setContent(block, { ...block.content, crop: crop ?? undefined })
}
aspect={shapeOf(block)!}
label="Choose a photograph"
onUrl={(url) => void handlersRef.current.setContent(block, { ...block.content, url: url ?? '' })}
onCrop={(crop) =>
void handlersRef.current.setContent(block, { ...block.content, crop: crop || undefined })
}
/>
) : (
<>