diff --git a/web/sections/PageBuilderPanel.tsx b/web/sections/PageBuilderPanel.tsx index 5db8a44..950df3c 100644 --- a/web/sections/PageBuilderPanel.tsx +++ b/web/sections/PageBuilderPanel.tsx @@ -38,6 +38,34 @@ import { BandSettings } from './BandSettings'; import { BlockSettings } from './BlockSettings'; import { GalleryItems } from './GalleryItems'; import { PartnersEditor } from './PartnersEditor'; +import { MediaField } from '../MediaField'; + +/** + * The shapes a photograph block may take. + * + * One list, because three things need it and must agree: the select's options, the number stored as + * `content.ratio`, and the Tailwind aspect `MediaField` frames into. Two of those are strings and one + * is a float, which is exactly the drift a single table prevents. + */ +const SHAPES = [ + { value: '', label: "The picture's own shape", ratio: null as number | null }, + { value: '21/9', label: '21:9 — a letterbox band', ratio: 21 / 9 }, + { value: '16/9', label: '16:9', ratio: 16 / 9 }, + { value: '3/2', label: '3:2', ratio: 3 / 2 }, + { value: '4/3', label: '4:3', ratio: 4 / 3 }, + { value: '1/1', label: '1:1 — square', ratio: 1 }, + { value: '3/4', label: '3:4 — upright', ratio: 3 / 4 }, + { value: '2/3', label: '2:3 — upright', ratio: 2 / 3 }, +]; + +/** Stored as a float, matched with a tolerance: 21/9 does not survive a round trip exactly. */ +const closeTo = (a: number, b: unknown): boolean => typeof b === 'number' && Math.abs(a - b) < 0.01; + +/** The Tailwind aspect for a block's stored ratio, or null when it keeps its own shape. */ +const shapeOf = (block: { content?: { url?: string; ratio?: number } }): string | null => { + if (!block.content?.url || /\.(mp4|mov|webm|m4v)$/i.test(block.content.url)) return null; + return SHAPES.find((one) => one.ratio && closeTo(one.ratio, block.content?.ratio))?.value ?? null; +}; import { useEditorSlot } from '../useEditorSlot'; import { AddComponentDialog, type ComponentKind } from './AddComponentDialog'; import { MediaPicker } from '../MediaPicker'; @@ -737,79 +765,87 @@ export const PageBuilderPanel = () => { )} {(block.kind === 'media' || block.kind === 'video') && ( -