@tangle-network/agent-app 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/DesignCanvas-3JEEIT6Y.js +10 -0
  2. package/dist/DesignCanvas-3JEEIT6Y.js.map +1 -0
  3. package/dist/DesignCanvasEditor-37LPJIIR.js +9 -0
  4. package/dist/DesignCanvasEditor-37LPJIIR.js.map +1 -0
  5. package/dist/chunk-2Q73HGDI.js +1743 -0
  6. package/dist/chunk-2Q73HGDI.js.map +1 -0
  7. package/dist/{chunk-3WAJWYKD.js → chunk-6UOE5CTA.js} +9 -92
  8. package/dist/{chunk-3WAJWYKD.js.map → chunk-6UOE5CTA.js.map} +1 -1
  9. package/dist/chunk-7QCIYDGC.js +1119 -0
  10. package/dist/chunk-7QCIYDGC.js.map +1 -0
  11. package/dist/chunk-A76ZHWNF.js +194 -0
  12. package/dist/chunk-A76ZHWNF.js.map +1 -0
  13. package/dist/{chunk-CF5DZELC.js → chunk-ABGSFUJQ.js} +2 -2
  14. package/dist/chunk-F5KTWRO7.js +2276 -0
  15. package/dist/chunk-F5KTWRO7.js.map +1 -0
  16. package/dist/chunk-JZAJE3JL.js +990 -0
  17. package/dist/chunk-JZAJE3JL.js.map +1 -0
  18. package/dist/design-canvas/drizzle.d.ts +569 -0
  19. package/dist/design-canvas/drizzle.js +183 -0
  20. package/dist/design-canvas/drizzle.js.map +1 -0
  21. package/dist/design-canvas/index.d.ts +261 -0
  22. package/dist/design-canvas/index.js +96 -0
  23. package/dist/design-canvas/index.js.map +1 -0
  24. package/dist/design-canvas-react/index.d.ts +916 -0
  25. package/dist/design-canvas-react/index.js +423 -0
  26. package/dist/design-canvas-react/index.js.map +1 -0
  27. package/dist/export-presets-Dl5Aa5xj.d.ts +284 -0
  28. package/dist/index.d.ts +5 -0
  29. package/dist/index.js +99 -3
  30. package/dist/mcp-rpc-DLw_r9PQ.d.ts +55 -0
  31. package/dist/model-BHLN208Z.d.ts +183 -0
  32. package/dist/sequences/index.d.ts +4 -0
  33. package/dist/sequences/index.js +2 -2
  34. package/dist/store-CUStmtdH.d.ts +64 -0
  35. package/dist/tools/index.d.ts +1 -0
  36. package/dist/tools/index.js +6 -2
  37. package/package.json +28 -3
  38. package/dist/chunk-IJZJWKUK.js +0 -77
  39. package/dist/chunk-IJZJWKUK.js.map +0 -1
  40. /package/dist/{chunk-CF5DZELC.js.map → chunk-ABGSFUJQ.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/design-canvas/model.ts","../src/design-canvas/validate.ts","../src/design-canvas/apply.ts","../src/design-canvas/export-presets.ts"],"sourcesContent":["/**\n * Design-canvas scene model — the product-agnostic document behind the visual\n * asset editor. A document is an ordered list of pages; a page is an ordered\n * list of elements (index order IS z-order, bottom→top); every element is a\n * typed node with a closed attribute vocabulary. The whole document\n * serializes as one JSON value and persists atomically with a revision\n * counter (see ./store) — every canvas action is a durable operation against\n * this schema, which is what makes the canvas automatable: agents and\n * external data sources mutate the same document the editor renders.\n *\n * Units are CSS pixels throughout; `settings.dpi` carries the print\n * conversion factor for bleed/trim-aware exports. Angles are degrees.\n * Nothing here touches Konva, React, or a database.\n */\n\nexport const SCENE_SCHEMA_VERSION = 1\n\nexport interface SceneDocument {\n schemaVersion: typeof SCENE_SCHEMA_VERSION\n title: string\n pages: ScenePage[]\n settings: SceneSettings\n metadata: Record<string, unknown>\n}\n\nexport interface SceneSettings {\n /** Print conversion factor for mm↔px math at export; 96 = CSS default. */\n dpi: number\n}\n\n/** Per-side bleed extents in px, drawn OUTSIDE the page bounds. Trim = the\n * page rect itself; exports may include or exclude the bleed area. */\nexport interface PageBleed {\n top: number\n right: number\n bottom: number\n left: number\n}\n\n/** Saved ruler guides, in page coordinates. */\nexport interface PageGuides {\n vertical: number[]\n horizontal: number[]\n}\n\nexport interface ScenePage {\n id: string\n name: string\n width: number\n height: number\n /** Page background fill (color string); elements paint over it. */\n background: string\n bleed: PageBleed | null\n guides: PageGuides\n elements: SceneElement[]\n}\n\n// ---------------------------------------------------------------------------\n// Elements\n// ---------------------------------------------------------------------------\n\n/** Attributes every element carries. `x`/`y` are the element's top-left in\n * page coordinates (for `group`, children are relative to the group origin).\n * `slot` names a template binding point — `apply_data` targets it. */\nexport interface SceneElementBase {\n id: string\n name: string\n x: number\n y: number\n /** Degrees, clockwise, about the element's top-left origin (Konva default). */\n rotation: number\n /** 0..1 */\n opacity: number\n locked: boolean\n visible: boolean\n slot?: string\n}\n\nexport interface RectElement extends SceneElementBase {\n kind: 'rect'\n width: number\n height: number\n fill: string\n stroke?: string\n strokeWidth?: number\n cornerRadius?: number\n}\n\nexport interface EllipseElement extends SceneElementBase {\n kind: 'ellipse'\n width: number\n height: number\n fill: string\n stroke?: string\n strokeWidth?: number\n}\n\nexport interface LineElement extends SceneElementBase {\n kind: 'line'\n /** Flat [x0, y0, x1, y1, ...] relative to (x, y); ≥ 2 points. */\n points: number[]\n stroke: string\n strokeWidth: number\n dash?: number[]\n}\n\nexport interface TextElement extends SceneElementBase {\n kind: 'text'\n text: string\n /** Wrap width; height derives from content. */\n width: number\n fontFamily: string\n fontSize: number\n fontStyle: 'normal' | 'bold' | 'italic' | 'bold italic'\n fill: string\n align: 'left' | 'center' | 'right'\n lineHeight: number\n letterSpacing: number\n}\n\nexport interface ImageElement extends SceneElementBase {\n kind: 'image'\n width: number\n height: number\n /** http(s) or rooted /api/ path — same boundary rule as sequences media. */\n src: string\n /** How the source maps into the frame; 'fill' stretches, 'cover' crops. */\n fit: 'fill' | 'cover' | 'contain'\n}\n\n/** Video placed on a canvas renders and exports as its poster frame — motion\n * belongs to the sequences surface; this keeps video assets placeable in\n * static layouts (e.g. a thumbnail mock) without a playback engine. */\nexport interface VideoElement extends SceneElementBase {\n kind: 'video'\n width: number\n height: number\n src: string\n posterSrc?: string\n}\n\nexport interface GroupElement extends SceneElementBase {\n kind: 'group'\n children: SceneElement[]\n}\n\nexport type SceneElement =\n | RectElement\n | EllipseElement\n | LineElement\n | TextElement\n | ImageElement\n | VideoElement\n | GroupElement\n\nexport type SceneElementKind = SceneElement['kind']\n\nexport const SCENE_ELEMENT_KINDS: readonly SceneElementKind[] = [\n 'rect', 'ellipse', 'line', 'text', 'image', 'video', 'group',\n] as const\n\n// ---------------------------------------------------------------------------\n// Geometry\n// ---------------------------------------------------------------------------\n\nexport interface Bounds {\n x: number\n y: number\n width: number\n height: number\n}\n\n/** Unrotated local extent of an element (line/group derive from content). */\nexport function elementExtent(element: SceneElement): { width: number; height: number } {\n switch (element.kind) {\n case 'rect':\n case 'ellipse':\n case 'image':\n case 'video':\n return { width: element.width, height: element.height }\n case 'text':\n // Height derives from content at render time; the model exposes a\n // deterministic estimate so layout math (snapping, describe) never\n // depends on a canvas context: lines × fontSize × lineHeight.\n return {\n width: element.width,\n height: estimateTextHeight(element),\n }\n case 'line': {\n let maxX = 0\n let maxY = 0\n for (let i = 0; i < element.points.length; i += 2) {\n maxX = Math.max(maxX, Math.abs(element.points[i]!))\n maxY = Math.max(maxY, Math.abs(element.points[i + 1]!))\n }\n return { width: maxX, height: maxY }\n }\n case 'group': {\n // minX/minY track the negative-space corner: a rotated child whose AABB\n // extends left/above the group origin contributes negative values, so\n // they must seed from the first child, not 0 (0 would clip them).\n let minX = 0, minY = 0, maxX = 0, maxY = 0\n for (const child of element.children) {\n const aabb = elementAabb(child)\n minX = Math.min(minX, aabb.x)\n minY = Math.min(minY, aabb.y)\n maxX = Math.max(maxX, aabb.x + aabb.width)\n maxY = Math.max(maxY, aabb.y + aabb.height)\n }\n return { width: maxX - minX, height: maxY - minY }\n }\n }\n}\n\nexport function estimateTextHeight(element: Pick<TextElement, 'text' | 'fontSize' | 'lineHeight'>): number {\n const lines = element.text.length === 0 ? 1 : element.text.split('\\n').length\n return lines * element.fontSize * element.lineHeight\n}\n\n/** Axis-aligned bounding box in the parent's coordinate space, accounting for\n * rotation about the element's top-left origin. */\nexport function elementAabb(element: SceneElement): Bounds {\n const { width, height } = elementExtent(element)\n if (element.rotation % 360 === 0) {\n return { x: element.x, y: element.y, width, height }\n }\n const rad = (element.rotation * Math.PI) / 180\n const cos = Math.cos(rad)\n const sin = Math.sin(rad)\n const corners: Array<[number, number]> = [\n [0, 0],\n [width * cos, width * sin],\n [-height * sin, height * cos],\n [width * cos - height * sin, width * sin + height * cos],\n ]\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity\n for (const [cx, cy] of corners) {\n minX = Math.min(minX, cx); minY = Math.min(minY, cy)\n maxX = Math.max(maxX, cx); maxY = Math.max(maxY, cy)\n }\n return { x: element.x + minX, y: element.y + minY, width: maxX - minX, height: maxY - minY }\n}\n\nexport function boundsIntersect(a: Bounds, b: Bounds): boolean {\n return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y\n}\n\n// ---------------------------------------------------------------------------\n// Lookup + traversal\n// ---------------------------------------------------------------------------\n\nexport function requirePage(document: SceneDocument, pageId: string): ScenePage {\n const page = document.pages.find((candidate) => candidate.id === pageId)\n if (!page) throw new Error(`page ${pageId} not found in document`)\n return page\n}\n\n/** Depth-first search across a page including group children. Returns the\n * element and the array that owns it (page.elements or a group's children),\n * so callers can splice in place. */\nexport function findElement(page: ScenePage, elementId: string): { element: SceneElement; owner: SceneElement[]; index: number } | null {\n const stack: SceneElement[][] = [page.elements]\n while (stack.length > 0) {\n const owner = stack.pop()!\n for (let index = 0; index < owner.length; index += 1) {\n const element = owner[index]!\n if (element.id === elementId) return { element, owner, index }\n if (element.kind === 'group') stack.push(element.children)\n }\n }\n return null\n}\n\nexport function requireElement(page: ScenePage, elementId: string): { element: SceneElement; owner: SceneElement[]; index: number } {\n const found = findElement(page, elementId)\n if (!found) throw new Error(`element ${elementId} not found on page ${page.id}`)\n return found\n}\n\n/** All slot names declared across the document — the template's fillable\n * surface. Duplicate slot names are a validation error (see ./validate). */\nexport function collectSlots(document: SceneDocument): Map<string, { pageId: string; elementId: string; kind: SceneElementKind }> {\n const slots = new Map<string, { pageId: string; elementId: string; kind: SceneElementKind }>()\n for (const page of document.pages) {\n const stack = [...page.elements]\n while (stack.length > 0) {\n const element = stack.pop()!\n if (element.slot) {\n if (slots.has(element.slot)) throw new Error(`duplicate slot name \"${element.slot}\"`)\n slots.set(element.slot, { pageId: page.id, elementId: element.id, kind: element.kind })\n }\n if (element.kind === 'group') stack.push(...element.children)\n }\n }\n return slots\n}\n\n// ---------------------------------------------------------------------------\n// Construction\n// ---------------------------------------------------------------------------\n\nexport interface NewPageOptions {\n name?: string\n width?: number\n height?: number\n background?: string\n}\n\nexport function createEmptyDocument(title: string, page?: NewPageOptions): SceneDocument {\n return {\n schemaVersion: SCENE_SCHEMA_VERSION,\n title,\n pages: [createPage(page ?? {}, 'page-1')],\n settings: { dpi: 96 },\n metadata: {},\n }\n}\n\nexport function createPage(options: NewPageOptions, id: string): ScenePage {\n const width = options.width ?? 1080\n const height = options.height ?? 1080\n assertPositiveFinite(width, 'page width')\n assertPositiveFinite(height, 'page height')\n return {\n id,\n name: options.name ?? 'Page',\n width,\n height,\n background: options.background ?? '#ffffff',\n bleed: null,\n guides: { vertical: [], horizontal: [] },\n elements: [],\n }\n}\n\nexport function assertPositiveFinite(value: number, label: string): void {\n if (!Number.isFinite(value) || value <= 0) throw new Error(`${label} must be a positive finite number`)\n}\n\nexport function assertFinite(value: number, label: string): void {\n if (!Number.isFinite(value)) throw new Error(`${label} must be a finite number`)\n}\n\nconst COLOR_PATTERN = /^(#[0-9a-fA-F]{3,8}|rgba?\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*(,\\s*(0|1|0?\\.\\d+)\\s*)?\\)|transparent)$/\n\nexport function assertColor(value: string, label: string): void {\n if (!COLOR_PATTERN.test(value)) throw new Error(`${label} must be a hex/rgb(a) color or 'transparent', got \"${value}\"`)\n}\n\n/** Media boundary rule shared with sequences: remote http(s) or a rooted\n * /api/ path — never sandbox-local files or data: blobs. */\nexport function assertSceneMediaSrc(value: string, label: string): void {\n if (/^https?:\\/\\//i.test(value) || /^\\/api\\//.test(value)) return\n throw new Error(`${label} must be an http(s) URL or a rooted /api/ path, got \"${value}\"`)\n}\n","/**\n * Pre-write validation for scene operations. Every rule runs against a\n * `SceneDocument` snapshot BEFORE any mutation, so a rejected batch leaves no\n * partial state. Batch errors carry the shape `operation N (type): reason` —\n * precise enough for an LLM planner to repair the offending operation and\n * resubmit.\n *\n * Validation is static: a batch is checked against the document as given, so\n * an operation may not reference entities created by an earlier operation in\n * the same batch. Dispatchers that chain operations must refresh the document\n * between applications and validate per-operation.\n *\n * Slot typing contract (for apply_data bindings):\n * text elements → value is any string\n * image elements → value must pass assertSceneMediaSrc (src rewrite)\n * video elements → value must pass assertSceneMediaSrc (src rewrite)\n * rect elements → value must pass assertColor (fill recolor)\n * ellipse elements → value must pass assertColor (fill recolor)\n * line elements → value must pass assertColor (stroke recolor)\n * group elements → value must pass assertColor (fill/stroke passed down to children)\n */\n\nimport {\n assertColor,\n assertFinite,\n assertPositiveFinite,\n assertSceneMediaSrc,\n collectSlots,\n findElement,\n requireElement,\n requirePage,\n} from './model'\nimport type { SceneDocument, SceneElement, SceneElementKind } from './model'\nimport type {\n AddElementOperation,\n ApplyDataOperation,\n BindSlotOperation,\n DeleteElementOperation,\n DeletePageOperation,\n DuplicatePageOperation,\n GroupElementsOperation,\n ReorderElementOperation,\n ReorderPageOperation,\n SceneAttrsPatch,\n SceneOperation,\n SetAttrsOperation,\n SetDocumentTitleOperation,\n SetPageGuidesOperation,\n SetPagePropsOperation,\n UngroupElementOperation,\n} from './operations'\n\n// ---------------------------------------------------------------------------\n// Public entry\n// ---------------------------------------------------------------------------\n\nexport function validateSceneOperations(document: SceneDocument, operations: SceneOperation[]): void {\n operations.forEach((operation, index) => {\n try {\n validateSceneOperation(document, operation)\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n throw new Error(`operation ${index + 1} (${operation.type}): ${reason}`)\n }\n })\n}\n\nexport function validateSceneOperation(document: SceneDocument, operation: SceneOperation): void {\n switch (operation.type) {\n case 'add_element':\n return validateAddElement(document, operation)\n case 'set_attrs':\n return validateSetAttrs(document, operation)\n case 'reorder_element':\n return validateReorderElement(document, operation)\n case 'delete_element':\n return validateDeleteElement(document, operation)\n case 'group_elements':\n return validateGroupElements(document, operation)\n case 'ungroup_element':\n return validateUngroupElement(document, operation)\n case 'add_page':\n return validateAddPage(operation)\n case 'duplicate_page':\n return validateDuplicatePage(document, operation)\n case 'delete_page':\n return validateDeletePage(document, operation)\n case 'reorder_page':\n return validateReorderPage(document, operation)\n case 'set_page_props':\n return validateSetPageProps(document, operation)\n case 'set_page_guides':\n return validateSetPageGuides(document, operation)\n case 'bind_slot':\n return validateBindSlot(document, operation)\n case 'apply_data':\n return validateApplyData(document, operation)\n case 'set_document_title':\n return validateSetDocumentTitle(operation)\n default: {\n const unknown = operation as { type?: unknown }\n throw new Error(`unsupported operation type ${JSON.stringify(unknown.type)}`)\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Per-operation validators\n// ---------------------------------------------------------------------------\n\nfunction validateAddElement(document: SceneDocument, op: AddElementOperation): void {\n const page = requirePage(document, op.pageId)\n assertUniqueIdDocumentWide(document, op.element.id)\n if (op.parentGroupId !== undefined) {\n const { element: parent } = requireElement(page, op.parentGroupId)\n if (parent.kind !== 'group') {\n throw new Error(`parentGroupId \"${op.parentGroupId}\" is a ${parent.kind}, not a group`)\n }\n }\n if (op.index !== undefined) {\n const owner = op.parentGroupId\n ? (() => {\n const { element: g } = requireElement(page, op.parentGroupId)\n return (g as { kind: 'group'; children: SceneElement[] }).children\n })()\n : page.elements\n if (op.index < 0 || op.index > owner.length) {\n throw new Error(`index ${op.index} out of range (owner has ${owner.length} elements)`)\n }\n }\n validateElementAttrs(op.element.kind, op.element as unknown as SceneAttrsPatch, true)\n}\n\nfunction validateSetAttrs(document: SceneDocument, op: SetAttrsOperation): void {\n const page = requirePage(document, op.pageId)\n const { element } = requireElement(page, op.elementId)\n // A patch that ONLY unlocks is always permitted even on a locked element.\n const isUnlockOnly = Object.keys(op.attrs).length === 1 && op.attrs.locked === false\n if (element.locked && !isUnlockOnly) {\n throw new Error(`element \"${op.elementId}\" is locked; unlock it first (pass attrs: {locked: false}) before making other changes`)\n }\n validateElementAttrs(element.kind, op.attrs, false)\n}\n\nfunction validateReorderElement(document: SceneDocument, op: ReorderElementOperation): void {\n const page = requirePage(document, op.pageId)\n const { element, owner } = requireElement(page, op.elementId)\n if (element.locked) {\n throw new Error(`element \"${op.elementId}\" is locked; unlock it before reordering`)\n }\n // toIndex is the insertion point after splice-remove; owner.length-1 is valid\n // (element becomes last). owner.length itself is out-of-range post-remove.\n if (op.toIndex < 0 || op.toIndex >= owner.length) {\n throw new Error(`toIndex ${op.toIndex} out of range (owner has ${owner.length} elements)`)\n }\n}\n\nfunction validateDeleteElement(document: SceneDocument, op: DeleteElementOperation): void {\n const page = requirePage(document, op.pageId)\n const { element } = requireElement(page, op.elementId)\n if (element.locked) {\n throw new Error(`element \"${op.elementId}\" is locked; unlock it before deleting`)\n }\n}\n\nfunction validateGroupElements(document: SceneDocument, op: GroupElementsOperation): void {\n if (op.elementIds.length < 2) {\n throw new Error(`group_elements requires ≥ 2 element ids (got ${op.elementIds.length})`)\n }\n assertUniqueIdDocumentWide(document, op.groupId)\n const page = requirePage(document, op.pageId)\n // Resolve all targets and check siblings + locked\n const owners = op.elementIds.map((id) => {\n const { element, owner } = requireElement(page, id)\n if (element.locked) throw new Error(`element \"${id}\" is locked; unlock before grouping`)\n return owner\n })\n // All must share the exact same owner array reference (sibling check)\n const firstOwner = owners[0]\n for (let i = 1; i < owners.length; i++) {\n if (owners[i] !== firstOwner) {\n throw new Error(`elements are not siblings — they must all share the same parent (page root or one group)`)\n }\n }\n}\n\nfunction validateUngroupElement(document: SceneDocument, op: UngroupElementOperation): void {\n const page = requirePage(document, op.pageId)\n const { element } = requireElement(page, op.groupId)\n if (element.kind !== 'group') {\n throw new Error(`element \"${op.groupId}\" is a ${element.kind}, not a group`)\n }\n}\n\nfunction validateAddPage(op: { options?: { width?: number; height?: number; background?: string } }): void {\n const opts = op.options\n if (!opts) return\n if (opts.width !== undefined) assertPositiveFinite(opts.width, 'page width')\n if (opts.height !== undefined) assertPositiveFinite(opts.height, 'page height')\n if (opts.background !== undefined) assertColor(opts.background, 'page background')\n}\n\nfunction validateDuplicatePage(document: SceneDocument, op: DuplicatePageOperation): void {\n requirePage(document, op.sourcePageId)\n const existing = document.pages.find((p) => p.id === op.pageId)\n if (existing) throw new Error(`pageId \"${op.pageId}\" already exists in the document`)\n}\n\nfunction validateDeletePage(document: SceneDocument, op: DeletePageOperation): void {\n requirePage(document, op.pageId)\n if (document.pages.length === 1) {\n throw new Error('cannot delete the last remaining page')\n }\n}\n\nfunction validateReorderPage(document: SceneDocument, op: ReorderPageOperation): void {\n requirePage(document, op.pageId)\n if (op.toIndex < 0 || op.toIndex >= document.pages.length) {\n throw new Error(`toIndex ${op.toIndex} out of range (document has ${document.pages.length} pages)`)\n }\n}\n\nfunction validateSetPageProps(document: SceneDocument, op: SetPagePropsOperation): void {\n requirePage(document, op.pageId)\n if (op.width !== undefined) assertPositiveFinite(op.width, 'page width')\n if (op.height !== undefined) assertPositiveFinite(op.height, 'page height')\n if (op.background !== undefined) assertColor(op.background, 'page background')\n if (op.bleed != null) {\n assertNonNegativeFinite(op.bleed.top, 'bleed.top')\n assertNonNegativeFinite(op.bleed.right, 'bleed.right')\n assertNonNegativeFinite(op.bleed.bottom, 'bleed.bottom')\n assertNonNegativeFinite(op.bleed.left, 'bleed.left')\n }\n}\n\nfunction validateSetPageGuides(document: SceneDocument, op: SetPageGuidesOperation): void {\n requirePage(document, op.pageId)\n for (const pos of op.guides.vertical) {\n if (!Number.isFinite(pos)) throw new Error(`guide position ${pos} is not finite`)\n }\n for (const pos of op.guides.horizontal) {\n if (!Number.isFinite(pos)) throw new Error(`guide position ${pos} is not finite`)\n }\n}\n\nfunction validateBindSlot(document: SceneDocument, op: BindSlotOperation): void {\n const page = requirePage(document, op.pageId)\n requireElement(page, op.elementId)\n if (op.slot === null) return\n // Slot names must be unique document-wide; a re-bind of the SAME element to\n // its own current slot name is fine (idempotent) — collectSlots throws on\n // duplicates owned by DIFFERENT elements, so we check manually.\n for (const p of document.pages) {\n const stack = [...p.elements]\n while (stack.length > 0) {\n const el = stack.pop()!\n if (el.slot === op.slot && el.id !== op.elementId) {\n throw new Error(`slot \"${op.slot}\" is already bound to element \"${el.id}\" on page \"${p.id}\"`)\n }\n if (el.kind === 'group') stack.push(...el.children)\n }\n }\n}\n\nfunction validateApplyData(document: SceneDocument, op: ApplyDataOperation): void {\n // Build the slot map; collectSlots throws on internal duplicates\n const slots = collectSlots(document)\n for (const [slotName, value] of Object.entries(op.bindings)) {\n const slot = slots.get(slotName)\n if (!slot) {\n throw new Error(`slot \"${slotName}\" does not exist in the document`)\n }\n validateSlotValue(slotName, slot.kind, value)\n }\n}\n\nfunction validateSetDocumentTitle(op: SetDocumentTitleOperation): void {\n if (op.title.trim().length === 0) throw new Error('title must be non-empty')\n}\n\n// ---------------------------------------------------------------------------\n// Element attr validation\n// ---------------------------------------------------------------------------\n\n/** Attributes present on EVERY element kind (SceneElementBase minus id/kind). */\nconst BASE_ATTRS = new Set([\n 'name', 'x', 'y', 'rotation', 'opacity', 'locked', 'visible', 'slot',\n])\n\n/** Per-kind allowed attributes (beyond base). */\nconst KIND_ATTRS: Record<SceneElementKind, Set<string>> = {\n rect: new Set(['width', 'height', 'fill', 'stroke', 'strokeWidth', 'cornerRadius']),\n ellipse: new Set(['width', 'height', 'fill', 'stroke', 'strokeWidth']),\n line: new Set(['points', 'stroke', 'strokeWidth', 'dash']),\n text: new Set(['text', 'width', 'fontFamily', 'fontSize', 'fontStyle', 'fill', 'align', 'lineHeight', 'letterSpacing']),\n image: new Set(['width', 'height', 'src', 'fit']),\n video: new Set(['width', 'height', 'src', 'posterSrc']),\n group: new Set([]),\n}\n\nconst FONT_STYLES = new Set(['normal', 'bold', 'italic', 'bold italic'])\nconst ALIGN_VALUES = new Set(['left', 'center', 'right'])\nconst FIT_VALUES = new Set(['fill', 'cover', 'contain'])\n\n/**\n * Validates attribute patches (or full element attrs for add_element).\n * `isConstruction` = true when validating a new element (required fields\n * must be present); false for a partial set_attrs patch.\n */\nfunction validateElementAttrs(\n kind: SceneElementKind,\n attrs: SceneAttrsPatch,\n isConstruction: boolean,\n): void {\n const allowed = KIND_ATTRS[kind]\n\n // Foreign attribute check: reject any key that is neither base nor kind-specific.\n for (const key of Object.keys(attrs)) {\n if (key === 'id' || key === 'kind' || key === 'children') continue\n if (!BASE_ATTRS.has(key) && !allowed.has(key)) {\n throw new Error(`attribute \"${key}\" is not valid for a ${kind} element`)\n }\n }\n\n // Base attribute validation\n if (attrs.opacity !== undefined) {\n if (typeof attrs.opacity !== 'number' || !Number.isFinite(attrs.opacity) || attrs.opacity < 0 || attrs.opacity > 1) {\n throw new Error('opacity must be a number in [0, 1]')\n }\n }\n if (attrs.x !== undefined) assertFinite(attrs.x, 'x')\n if (attrs.y !== undefined) assertFinite(attrs.y, 'y')\n if (attrs.rotation !== undefined) assertFinite(attrs.rotation, 'rotation')\n\n // Kind-specific attribute validation\n switch (kind) {\n case 'rect':\n case 'ellipse':\n case 'image':\n case 'video':\n if (attrs.width !== undefined) assertPositiveFinite(attrs.width, 'width')\n if (attrs.height !== undefined) assertPositiveFinite(attrs.height, 'height')\n break\n case 'text':\n if (attrs.width !== undefined) assertPositiveFinite(attrs.width, 'width')\n if (attrs.fontSize !== undefined) assertPositiveFinite(attrs.fontSize, 'fontSize')\n if (attrs.lineHeight !== undefined) {\n if (typeof attrs.lineHeight !== 'number' || !Number.isFinite(attrs.lineHeight) || attrs.lineHeight <= 0) {\n throw new Error('lineHeight must be a positive finite number')\n }\n }\n if (attrs.fontStyle !== undefined && !FONT_STYLES.has(attrs.fontStyle)) {\n throw new Error(`fontStyle must be one of: ${[...FONT_STYLES].join(', ')}`)\n }\n if (attrs.align !== undefined && !ALIGN_VALUES.has(attrs.align)) {\n throw new Error(`align must be one of: ${[...ALIGN_VALUES].join(', ')}`)\n }\n break\n case 'line':\n if (attrs.points !== undefined) {\n if (!Array.isArray(attrs.points) || attrs.points.length < 4 || attrs.points.length % 2 !== 0) {\n throw new Error('points must be an even-length array with at least 4 numbers (2 points)')\n }\n for (let i = 0; i < attrs.points.length; i++) {\n if (!Number.isFinite(attrs.points[i])) {\n throw new Error(`points[${i}] is not finite`)\n }\n }\n }\n if (attrs.strokeWidth !== undefined) assertPositiveFinite(attrs.strokeWidth, 'strokeWidth')\n break\n case 'group':\n // Group geometry derives from children; no width/height attrs.\n break\n }\n\n // Color validation for fill/stroke\n if (attrs.fill !== undefined) assertColor(attrs.fill, 'fill')\n if (attrs.stroke !== undefined) assertColor(attrs.stroke, 'stroke')\n if (attrs.strokeWidth !== undefined && kind !== 'line') {\n assertPositiveFinite(attrs.strokeWidth, 'strokeWidth')\n }\n\n // Image/video src\n if (attrs.src !== undefined) assertSceneMediaSrc(attrs.src, 'src')\n if ((attrs as { posterSrc?: string }).posterSrc !== undefined) {\n assertSceneMediaSrc((attrs as { posterSrc: string }).posterSrc, 'posterSrc')\n }\n\n // fit\n if (attrs.fit !== undefined && !FIT_VALUES.has(attrs.fit)) {\n throw new Error(`fit must be one of: ${[...FIT_VALUES].join(', ')}`)\n }\n\n // Construction-time required-field checks\n if (isConstruction) {\n validateRequiredConstructionAttrs(kind, attrs)\n }\n}\n\nfunction validateRequiredConstructionAttrs(kind: SceneElementKind, attrs: SceneAttrsPatch): void {\n switch (kind) {\n case 'rect':\n requireAttrPresent(attrs, 'width', kind)\n requireAttrPresent(attrs, 'height', kind)\n requireAttrPresent(attrs, 'fill', kind)\n break\n case 'ellipse':\n requireAttrPresent(attrs, 'width', kind)\n requireAttrPresent(attrs, 'height', kind)\n requireAttrPresent(attrs, 'fill', kind)\n break\n case 'line':\n requireAttrPresent(attrs, 'points', kind)\n requireAttrPresent(attrs, 'stroke', kind)\n requireAttrPresent(attrs, 'strokeWidth', kind)\n break\n case 'text':\n requireAttrPresent(attrs, 'text', kind)\n requireAttrPresent(attrs, 'width', kind)\n requireAttrPresent(attrs, 'fontFamily', kind)\n requireAttrPresent(attrs, 'fontSize', kind)\n requireAttrPresent(attrs, 'fontStyle', kind)\n requireAttrPresent(attrs, 'fill', kind)\n requireAttrPresent(attrs, 'align', kind)\n requireAttrPresent(attrs, 'lineHeight', kind)\n requireAttrPresent(attrs, 'letterSpacing', kind)\n break\n case 'image':\n requireAttrPresent(attrs, 'width', kind)\n requireAttrPresent(attrs, 'height', kind)\n requireAttrPresent(attrs, 'src', kind)\n requireAttrPresent(attrs, 'fit', kind)\n break\n case 'video':\n requireAttrPresent(attrs, 'width', kind)\n requireAttrPresent(attrs, 'height', kind)\n requireAttrPresent(attrs, 'src', kind)\n break\n case 'group':\n // Groups are created empty; children are added separately.\n break\n }\n}\n\nfunction requireAttrPresent(attrs: SceneAttrsPatch, key: string, kind: SceneElementKind): void {\n if ((attrs as Record<string, unknown>)[key] === undefined) {\n throw new Error(`${key} is required when constructing a ${kind} element`)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Slot value typing (apply_data)\n// ---------------------------------------------------------------------------\n\n/**\n * Validates that a slot binding value matches the slot element's kind.\n * text → any string; image/video → media src; rect/ellipse/line/group → color.\n */\nexport function validateSlotValue(slotName: string, elementKind: SceneElementKind, value: string): void {\n switch (elementKind) {\n case 'text':\n // Any string is valid for a text slot.\n return\n case 'image':\n case 'video':\n try {\n assertSceneMediaSrc(value, `slot \"${slotName}\" value`)\n } catch (e) {\n throw new Error(\n `slot \"${slotName}\" is bound to a ${elementKind} element — value must be an http(s) URL or a rooted /api/ path (got \"${value}\")`,\n )\n }\n return\n case 'rect':\n case 'ellipse':\n case 'line':\n case 'group':\n try {\n assertColor(value, `slot \"${slotName}\" value`)\n } catch {\n throw new Error(\n `slot \"${slotName}\" is bound to a ${elementKind} element — value must be a color (hex/rgb(a)/transparent) for fill/stroke recolor (got \"${value}\")`,\n )\n }\n return\n }\n}\n\n// ---------------------------------------------------------------------------\n// Document-wide uniqueness\n// ---------------------------------------------------------------------------\n\nfunction assertUniqueIdDocumentWide(document: SceneDocument, id: string): void {\n for (const page of document.pages) {\n if (page.id === id) throw new Error(`id \"${id}\" is already used by a page`)\n const stack = [...page.elements]\n while (stack.length > 0) {\n const el = stack.pop()!\n if (el.id === id) throw new Error(`id \"${id}\" is already used by element on page \"${page.id}\"`)\n if (el.kind === 'group') stack.push(...el.children)\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal guards\n// ---------------------------------------------------------------------------\n\nfunction assertNonNegativeFinite(value: number, label: string): void {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`${label} must be a non-negative finite number`)\n }\n}\n","/**\n * Pure application of validated scene operations to a SceneDocument.\n * `applySceneOperations` deep-clones the document then mutates the clone,\n * returning the new document and per-op results. It never touches the store,\n * a clock, or a PRNG — all id generation goes through the caller-supplied\n * `mintId` option so callers control determinism (counter in tests,\n * crypto.randomUUID in production).\n *\n * Rotation semantics for group/ungroup:\n * Group: children retain their absolute rotation. The group origin is the\n * min-x, min-y corner of the AABB union of all member elements. Children\n * are rebased so their position in group-local space equals\n * (element.x - group.x, element.y - group.y). A rotated child appears at\n * the same absolute page position after grouping because the group's additive\n * translation preserves the child's own-origin transform.\n * Ungroup: inverse — child.x += group.x, child.y += group.y; rotation stays.\n * This is consistent with Konva's transform-about-own-origin model without\n * needing a full matrix concatenation for the common case.\n *\n * `storeApplyScenePlan` layers store I/O on top: getDocument → validate →\n * apply → saveDocument(expectedRev) → recordDecision, retrying once on\n * stale-rev by refetch + revalidate + reapply.\n */\n\nimport {\n assertColor,\n assertSceneMediaSrc,\n collectSlots,\n createPage,\n elementAabb,\n requireElement,\n requirePage,\n} from './model'\nimport type {\n GroupElement,\n NewPageOptions,\n SceneDocument,\n SceneElement,\n ScenePage,\n} from './model'\nimport type {\n AddElementOperation,\n AddPageOperation,\n ApplyDataOperation,\n BindSlotOperation,\n DeleteElementOperation,\n DeletePageOperation,\n DuplicatePageOperation,\n GroupElementsOperation,\n ReorderElementOperation,\n ReorderPageOperation,\n SceneOperation,\n ScenePlan,\n SetAttrsOperation,\n SetDocumentTitleOperation,\n SetPageGuidesOperation,\n SetPagePropsOperation,\n UngroupElementOperation,\n} from './operations'\nimport type { NewSceneDecision, SceneDocumentRecord, SceneStore } from './store'\nimport { validateSceneOperations } from './validate'\n\n// ---------------------------------------------------------------------------\n// Result types\n// ---------------------------------------------------------------------------\n\nexport type SceneApplyResult =\n | { kind: 'element'; pageId: string; element: SceneElement }\n | { kind: 'page'; page: ScenePage }\n | { kind: 'document' }\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface ApplySceneOptions {\n /**\n * Provides fresh ids when duplicate_page re-mints element ids. Never called\n * by any other operation. Counter-based in tests; crypto.randomUUID in\n * production (wrapped so `mintId()` has no arguments, matching this signature).\n */\n mintId: () => string\n}\n\n// ---------------------------------------------------------------------------\n// Public: pure apply\n// ---------------------------------------------------------------------------\n\n/** Full form: returns the new document AND per-op results. `mintId` must be\n * provided when any operation in the list may be `duplicate_page` (which\n * re-mints element ids); for all other operation types it is never called. */\nexport function applySceneOperations(\n document: SceneDocument,\n operations: SceneOperation[],\n options: ApplySceneOptions,\n): { document: SceneDocument; results: SceneApplyResult[] }\n\n/** Convenience 2-arg form: returns the new document directly. Uses a\n * monotonic counter as the mintId so `duplicate_page` never collides within\n * a single call (suitable for editor-local optimistic state; server will\n * re-mint on persist). */\nexport function applySceneOperations(\n document: SceneDocument,\n operations: SceneOperation[],\n): SceneDocument\n\nexport function applySceneOperations(\n document: SceneDocument,\n operations: SceneOperation[],\n options?: ApplySceneOptions,\n): { document: SceneDocument; results: SceneApplyResult[] } | SceneDocument {\n const opts = options ?? { mintId: makeCounter() }\n const doc = deepCloneDocument(document)\n const results: SceneApplyResult[] = []\n for (const operation of operations) {\n results.push(applyOneOperation(doc, operation, opts))\n }\n return options !== undefined ? { document: doc, results } : doc\n}\n\n/** Apply a single operation to a document and return the new document.\n * Equivalent to `applySceneOperations(doc, [op])` but returns `SceneDocument`\n * directly — the common case in editor commands and tests. */\nexport function applySceneOperation(\n document: SceneDocument,\n operation: SceneOperation,\n): SceneDocument {\n return applySceneOperations(document, [operation])\n}\n\nfunction makeCounter(): () => string {\n let n = 0\n return () => `minted-${(n += 1)}`\n}\n\n// ---------------------------------------------------------------------------\n// Public: store-integrated helper\n// ---------------------------------------------------------------------------\n\n/** Detects the stale-revision sentinel thrown by drizzle-store. The store\n * throws a plain Error whose message contains \"stale rev\" — no custom class\n * is needed because the store contract documents exactly this phrase. */\nfunction isStaleRevError(err: unknown): boolean {\n return err instanceof Error && /stale rev/i.test(err.message)\n}\n\nexport async function storeApplyScenePlan(\n store: SceneStore,\n plan: ScenePlan,\n opts: { actorKind: NewSceneDecision['kind']; mintId: () => string },\n): Promise<{ record: SceneDocumentRecord; results: SceneApplyResult[] }> {\n let { document, rev } = await store.getDocument()\n\n validateSceneOperations(document, plan.operations)\n let applied = applySceneOperations(document, plan.operations, { mintId: opts.mintId })\n\n let record: SceneDocumentRecord\n try {\n record = await store.saveDocument(applied.document, rev)\n } catch (firstError) {\n // Only retry for stale-rev conflicts. Any other error (network, constraint,\n // permissions) is a hard failure — retrying would risk a double-apply if\n // the first save actually succeeded but the acknowledgement was lost.\n if (!isStaleRevError(firstError)) throw firstError\n const refreshed = await store.getDocument()\n validateSceneOperations(refreshed.document, plan.operations)\n applied = applySceneOperations(refreshed.document, plan.operations, { mintId: opts.mintId })\n try {\n record = await store.saveDocument(applied.document, refreshed.rev)\n } catch (secondError) {\n const reason = secondError instanceof Error ? secondError.message : String(secondError)\n throw new Error(`storeApplyScenePlan: stale rev persists after retry — ${reason}`)\n }\n }\n\n const opTypeCounts: Record<string, number> = {}\n for (const op of plan.operations) {\n opTypeCounts[op.type] = (opTypeCounts[op.type] ?? 0) + 1\n }\n\n await store.recordDecision({\n kind: opts.actorKind,\n instruction: plan.summary,\n metadata: { opTypeCounts, operationCount: plan.operations.length },\n })\n\n return { record, results: applied.results }\n}\n\n// ---------------------------------------------------------------------------\n// Per-operation dispatch (mutates cloned doc in-place)\n// ---------------------------------------------------------------------------\n\nfunction applyOneOperation(\n doc: SceneDocument,\n operation: SceneOperation,\n options: ApplySceneOptions,\n): SceneApplyResult {\n switch (operation.type) {\n case 'add_element':\n return applyAddElement(doc, operation)\n case 'set_attrs':\n return applySetAttrs(doc, operation)\n case 'reorder_element':\n return applyReorderElement(doc, operation)\n case 'delete_element':\n return applyDeleteElement(doc, operation)\n case 'group_elements':\n return applyGroupElements(doc, operation)\n case 'ungroup_element':\n return applyUngroupElement(doc, operation)\n case 'add_page':\n return applyAddPage(doc, operation)\n case 'duplicate_page':\n return applyDuplicatePage(doc, operation, options)\n case 'delete_page':\n return applyDeletePage(doc, operation)\n case 'reorder_page':\n return applyReorderPage(doc, operation)\n case 'set_page_props':\n return applySetPageProps(doc, operation)\n case 'set_page_guides':\n return applySetPageGuides(doc, operation)\n case 'bind_slot':\n return applyBindSlot(doc, operation)\n case 'apply_data':\n return applyApplyData(doc, operation)\n case 'set_document_title':\n return applySetDocumentTitle(doc, operation)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Operation implementations (all mutate the deep-cloned doc)\n// ---------------------------------------------------------------------------\n\nfunction applyAddElement(doc: SceneDocument, op: AddElementOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const owner: SceneElement[] = op.parentGroupId !== undefined\n ? (() => {\n const { element: g } = requireElement(page, op.parentGroupId)\n return (g as GroupElement).children\n })()\n : page.elements\n const index = op.index !== undefined ? op.index : owner.length\n owner.splice(index, 0, op.element)\n return { kind: 'element', pageId: op.pageId, element: op.element }\n}\n\nfunction applySetAttrs(doc: SceneDocument, op: SetAttrsOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const { element, owner, index } = requireElement(page, op.elementId)\n const patched = { ...element, ...op.attrs } as SceneElement\n owner[index] = patched\n return { kind: 'element', pageId: op.pageId, element: patched }\n}\n\nfunction applyReorderElement(doc: SceneDocument, op: ReorderElementOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const { element, owner, index } = requireElement(page, op.elementId)\n owner.splice(index, 1)\n owner.splice(op.toIndex, 0, element)\n return { kind: 'element', pageId: op.pageId, element }\n}\n\nfunction applyDeleteElement(doc: SceneDocument, op: DeleteElementOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const { element, owner, index } = requireElement(page, op.elementId)\n owner.splice(index, 1)\n return { kind: 'element', pageId: op.pageId, element }\n}\n\nfunction applyGroupElements(doc: SceneDocument, op: GroupElementsOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const members = op.elementIds.map((id) => requireElement(page, id))\n\n // Group origin = min AABB corner of all members in the owner coordinate space.\n let minX = Infinity, minY = Infinity\n for (const { element } of members) {\n const aabb = elementAabb(element)\n if (aabb.x < minX) minX = aabb.x\n if (aabb.y < minY) minY = aabb.y\n }\n\n const owner = members[0]!.owner\n // Sort ascending by index to preserve z-order in children array.\n const sortedByIndex = [...members].sort((a, b) => a.index - b.index)\n\n // Children retain rotation; x/y rebased to group-local space.\n const children: SceneElement[] = sortedByIndex.map(({ element }) => ({\n ...element,\n x: element.x - minX,\n y: element.y - minY,\n }))\n\n // Remove in reverse order to avoid index drift.\n for (const { index } of [...sortedByIndex].reverse()) {\n owner.splice(index, 1)\n }\n\n // Group inserted at the slot vacated by the bottommost former member.\n const insertAt = sortedByIndex[0]!.index\n\n const group: GroupElement = {\n id: op.groupId,\n kind: 'group',\n name: op.name ?? 'Group',\n x: minX,\n y: minY,\n rotation: 0,\n opacity: 1,\n locked: false,\n visible: true,\n children,\n }\n\n owner.splice(insertAt, 0, group)\n return { kind: 'element', pageId: op.pageId, element: group }\n}\n\nfunction applyUngroupElement(doc: SceneDocument, op: UngroupElementOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const { element: groupEl, owner, index: groupIndex } = requireElement(page, op.groupId)\n const group = groupEl as GroupElement\n\n // Re-absolutize: child.x/y += group.x/y; rotation unchanged.\n const promoted: SceneElement[] = group.children.map((child) => ({\n ...child,\n x: child.x + group.x,\n y: child.y + group.y,\n }))\n\n owner.splice(groupIndex, 1, ...promoted)\n return { kind: 'element', pageId: op.pageId, element: groupEl }\n}\n\nfunction applyAddPage(doc: SceneDocument, op: AddPageOperation): SceneApplyResult {\n const opts: NewPageOptions = op.options ?? {}\n const page = createPage(opts, op.pageId)\n const index = op.index !== undefined ? op.index : doc.pages.length\n doc.pages.splice(index, 0, page)\n return { kind: 'page', page }\n}\n\nfunction applyDuplicatePage(\n doc: SceneDocument,\n op: DuplicatePageOperation,\n options: ApplySceneOptions,\n): SceneApplyResult {\n const source = requirePage(doc, op.sourcePageId)\n const copy: ScenePage = JSON.parse(JSON.stringify(source)) as ScenePage\n copy.id = op.pageId\n // Re-mint all element ids so the copy has no id collisions with the source.\n remintElementIds(copy.elements, options.mintId)\n doc.pages.push(copy)\n return { kind: 'page', page: copy }\n}\n\nfunction remintElementIds(elements: SceneElement[], mintId: () => string): void {\n for (let i = 0; i < elements.length; i++) {\n const el = elements[i]!\n const newEl: SceneElement = { ...el, id: mintId() }\n if (newEl.kind === 'group') {\n remintElementIds((newEl as GroupElement).children, mintId)\n }\n elements[i] = newEl\n }\n}\n\nfunction applyDeletePage(doc: SceneDocument, op: DeletePageOperation): SceneApplyResult {\n if (doc.pages.length <= 1) throw new Error('delete_page: cannot delete the last page')\n const index = doc.pages.findIndex((p) => p.id === op.pageId)\n if (index < 0) throw new Error(`page ${op.pageId} not found`)\n const [page] = doc.pages.splice(index, 1) as [ScenePage]\n return { kind: 'page', page }\n}\n\nfunction applyReorderPage(doc: SceneDocument, op: ReorderPageOperation): SceneApplyResult {\n const index = doc.pages.findIndex((p) => p.id === op.pageId)\n if (index < 0) throw new Error(`page ${op.pageId} not found`)\n const [page] = doc.pages.splice(index, 1) as [ScenePage]\n doc.pages.splice(op.toIndex, 0, page)\n return { kind: 'page', page }\n}\n\nfunction applySetPageProps(doc: SceneDocument, op: SetPagePropsOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n if (op.name !== undefined) page.name = op.name\n if (op.width !== undefined) page.width = op.width\n if (op.height !== undefined) page.height = op.height\n if (op.background !== undefined) page.background = op.background\n if (op.bleed !== undefined) page.bleed = op.bleed\n return { kind: 'page', page }\n}\n\nfunction applySetPageGuides(doc: SceneDocument, op: SetPageGuidesOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n page.guides = op.guides\n return { kind: 'page', page }\n}\n\nfunction applyBindSlot(doc: SceneDocument, op: BindSlotOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const { element, owner, index } = requireElement(page, op.elementId)\n const patched: SceneElement = op.slot === null ? omitSlot(element) : { ...element, slot: op.slot }\n owner[index] = patched\n return { kind: 'element', pageId: op.pageId, element: patched }\n}\n\nfunction omitSlot(element: SceneElement): SceneElement {\n const { slot: _slot, ...rest } = element as SceneElement & { slot?: string }\n return rest as SceneElement\n}\n\nfunction applyApplyData(doc: SceneDocument, op: ApplyDataOperation): SceneApplyResult {\n const slots = collectSlots(doc)\n for (const [slotName, value] of Object.entries(op.bindings)) {\n const slot = slots.get(slotName)\n if (!slot) throw new Error(`slot \"${slotName}\" not found in document`)\n const page = requirePage(doc, slot.pageId)\n const { element, owner, index } = requireElement(page, slot.elementId)\n owner[index] = applySlotValue(element, value)\n }\n return { kind: 'document' }\n}\n\nfunction applySlotValue(element: SceneElement, value: string): SceneElement {\n switch (element.kind) {\n case 'text':\n return { ...element, text: value }\n case 'image':\n case 'video':\n assertSceneMediaSrc(value, 'slot value')\n return { ...element, src: value }\n case 'rect':\n case 'ellipse':\n assertColor(value, 'slot value')\n return { ...element, fill: value }\n case 'line':\n assertColor(value, 'slot value')\n return { ...element, stroke: value }\n case 'group':\n // Group recolor: propagate fill/stroke to children that carry the property.\n assertColor(value, 'slot value')\n return recolorGroupChildren(element as GroupElement, value)\n }\n}\n\nfunction recolorGroupChildren(group: GroupElement, color: string): GroupElement {\n const children = group.children.map((child): SceneElement => {\n switch (child.kind) {\n case 'rect':\n case 'ellipse':\n return { ...child, fill: color }\n case 'line':\n return { ...child, stroke: color }\n case 'text':\n return { ...child, fill: color }\n case 'image':\n case 'video':\n return child\n case 'group':\n return recolorGroupChildren(child, color)\n }\n })\n return { ...group, children }\n}\n\nfunction applySetDocumentTitle(doc: SceneDocument, op: SetDocumentTitleOperation): SceneApplyResult {\n doc.title = op.title\n return { kind: 'document' }\n}\n\n// ---------------------------------------------------------------------------\n// Deep clone\n// ---------------------------------------------------------------------------\n\nfunction deepCloneDocument(document: SceneDocument): SceneDocument {\n return JSON.parse(JSON.stringify(document)) as SceneDocument\n}\n","/**\n * Page size presets, channel-size output presets, and export math for the\n * design canvas.\n *\n * Size presets (SizePreset / SIZE_PRESETS) describe page dimensions for the\n * new-page dialog. Export presets (ExportPreset / EXPORT_PRESETS) pin pixel\n * ratio, output dimensions, bleed, and format for the export dialog and the\n * MCP export tool. Channel presets (ChannelPreset / CHANNEL_PRESETS) are the\n * fixed output resolutions the export UI offers; `scaleForPreset` + the\n * letterbox helper derive Konva stage parameters from them.\n *\n * All dimensions are CSS pixels at 96 DPI unless noted otherwise.\n */\n\nimport type { Bounds, PageBleed, ScenePage } from './model'\n\nexport interface SizePreset {\n id: string\n label: string\n category: 'social' | 'print' | 'presentation' | 'custom'\n width: number\n height: number\n}\n\nexport const SIZE_PRESETS: readonly SizePreset[] = [\n // Social\n { id: 'instagram-square', label: 'Instagram — Square', category: 'social', width: 1080, height: 1080 },\n { id: 'instagram-portrait', label: 'Instagram — Portrait', category: 'social', width: 1080, height: 1350 },\n { id: 'instagram-story', label: 'Instagram Story', category: 'social', width: 1080, height: 1920 },\n { id: 'twitter-post', label: 'X / Twitter Post', category: 'social', width: 1200, height: 675 },\n { id: 'linkedin-post', label: 'LinkedIn Post', category: 'social', width: 1200, height: 627 },\n { id: 'facebook-post', label: 'Facebook Post', category: 'social', width: 1200, height: 630 },\n { id: 'youtube-thumbnail', label: 'YouTube Thumbnail', category: 'social', width: 1280, height: 720 },\n { id: 'og-image', label: 'Open Graph Image', category: 'social', width: 1200, height: 630 },\n // Presentation\n { id: 'slide-16-9', label: 'Slide — 16:9', category: 'presentation', width: 1920, height: 1080 },\n { id: 'slide-4-3', label: 'Slide — 4:3', category: 'presentation', width: 1024, height: 768 },\n // Print (96 DPI px equivalents of A4, Letter — products may scale at export)\n { id: 'a4-landscape', label: 'A4 Landscape', category: 'print', width: 1123, height: 794 },\n { id: 'a4-portrait', label: 'A4 Portrait', category: 'print', width: 794, height: 1123 },\n { id: 'us-letter-landscape', label: 'US Letter Landscape', category: 'print', width: 1100, height: 850 },\n { id: 'us-letter-portrait', label: 'US Letter Portrait', category: 'print', width: 850, height: 1100 },\n] as const\n\nexport function findPreset(id: string): SizePreset | null {\n return SIZE_PRESETS.find((p) => p.id === id) ?? null\n}\n\n/** Match a (width, height) pair against the preset table. Returns the first\n * exact match or null — used to drive the dropdown selection indicator. */\nexport function matchPreset(width: number, height: number): SizePreset | null {\n return SIZE_PRESETS.find((p) => p.width === width && p.height === height) ?? null\n}\n\n// ---------------------------------------------------------------------------\n// Export quality presets\n// ---------------------------------------------------------------------------\n\nexport type ExportFormat = 'png' | 'jpeg'\n\n/**\n * Export quality preset — pins pixel density, optional output dimensions,\n * bleed inclusion, and raster format so callers pass a preset id rather than\n * a full parameter bag.\n *\n * `outputWidth` / `outputHeight`: when non-null, the pixel ratio is derived\n * from the crop rect width (see `scaleForPreset`) so the output is exactly\n * this many pixels wide. When null, `pixelRatio` applies directly.\n */\nexport interface ExportPreset {\n name: string\n /** Target pixels-per-document-px for stage.toDataURL. */\n pixelRatio: number\n outputWidth: number | null\n outputHeight: number | null\n /** Whether bleed margins are included in the crop rect. */\n includeBleed: boolean\n format: ExportFormat\n}\n\nexport const EXPORT_PRESETS: Record<string, ExportPreset> = {\n 'instagram-square': {\n name: 'Instagram square (1080×1080)',\n pixelRatio: 1,\n outputWidth: 1080,\n outputHeight: 1080,\n includeBleed: false,\n format: 'jpeg',\n },\n 'instagram-portrait': {\n name: 'Instagram portrait (1080×1350)',\n pixelRatio: 1,\n outputWidth: 1080,\n outputHeight: 1350,\n includeBleed: false,\n format: 'jpeg',\n },\n 'twitter-card': {\n name: 'Twitter/X card (1200×675)',\n pixelRatio: 1,\n outputWidth: 1200,\n outputHeight: 675,\n includeBleed: false,\n format: 'jpeg',\n },\n 'og-image': {\n name: 'OG image (1200×630)',\n pixelRatio: 1,\n outputWidth: 1200,\n outputHeight: 630,\n includeBleed: false,\n format: 'png',\n },\n 'print-a4': {\n name: 'Print A4 (300 dpi)',\n pixelRatio: 3.125,\n outputWidth: null,\n outputHeight: null,\n includeBleed: true,\n format: 'png',\n },\n 'screen-2x': {\n name: 'Screen @2×',\n pixelRatio: 2,\n outputWidth: null,\n outputHeight: null,\n includeBleed: false,\n format: 'png',\n },\n} as const\n\n// ---------------------------------------------------------------------------\n// Crop + scale math (pure, no canvas context)\n// ---------------------------------------------------------------------------\n\nexport interface ExportCropRect {\n /** Page-coordinate origin. Negative when bleed extends outside page bounds. */\n x: number\n y: number\n width: number\n height: number\n}\n\n/**\n * Crop rectangle in page coordinates for a given page, optionally expanded to\n * include bleed margins. Bleed extends OUTSIDE the page bounds, so the origin\n * goes negative when bleed is included.\n *\n * When `includeBleed` is true but `page.bleed` is null, the page rect is\n * returned unchanged — the caller must not assume symmetric expansion.\n */\nexport function bleedAwareExportBounds(page: ScenePage, includeBleed: boolean): ExportCropRect {\n if (!includeBleed || page.bleed === null) {\n return { x: 0, y: 0, width: page.width, height: page.height }\n }\n const bleed: PageBleed = page.bleed\n return {\n x: -bleed.left,\n y: -bleed.top,\n width: page.width + bleed.left + bleed.right,\n height: page.height + bleed.top + bleed.bottom,\n }\n}\n\n/**\n * Pixel ratio for stage.toDataURL given a crop rect and an export preset.\n *\n * When the preset pins `outputWidth`, the ratio is derived from the crop rect\n * width so the final raster is exactly that many pixels wide. When there is no\n * output pin, the preset's declared `pixelRatio` is returned directly.\n *\n * The crop rect must already account for bleed inclusion before this call.\n */\nexport function scaleForPreset(preset: ExportPreset, cropRect: ExportCropRect): number {\n if (preset.outputWidth !== null) {\n if (cropRect.width <= 0) {\n throw new Error(`export crop width must be positive, got ${cropRect.width}`)\n }\n return preset.outputWidth / cropRect.width\n }\n return preset.pixelRatio\n}\n\n// ---------------------------------------------------------------------------\n// Channel-size presets (fixed output resolutions for the export UI)\n// ---------------------------------------------------------------------------\n\nexport interface ChannelPreset {\n id: string\n label: string\n width: number\n height: number\n}\n\n/**\n * Fixed output resolution presets for the channel/platform export dialog.\n * Width × height are OUTPUT pixels (the raster the export produces), not page\n * CSS px — they describe the target delivery format, not the canvas layout.\n * The a4_print_2480x3508 preset corresponds to A4 at 300 dpi.\n */\nexport const CHANNEL_PRESETS: readonly ChannelPreset[] = [\n { id: 'square_1080', label: 'Square (1080×1080)', width: 1080, height: 1080 },\n { id: 'portrait_1080x1350', label: 'Portrait (1080×1350)', width: 1080, height: 1350 },\n { id: 'story_1080x1920', label: 'Story (1080×1920)', width: 1080, height: 1920 },\n { id: 'landscape_1200x628', label: 'Landscape (1200×628)', width: 1200, height: 628 },\n { id: 'wide_1920x1080', label: 'Wide (1920×1080)', width: 1920, height: 1080 },\n { id: 'og_1200x630', label: 'Open Graph (1200×630)', width: 1200, height: 630 },\n { id: 'a4_print_2480x3508', label: 'A4 Print (2480×3508 · 300 dpi)', width: 2480, height: 3508 },\n] as const\n\nexport type ChannelPresetId = (typeof CHANNEL_PRESETS)[number]['id']\n\n/** Throws when the id is unknown — callers should only pass ids sourced from\n * `CHANNEL_PRESETS`. */\nexport function requireChannelPreset(id: string): ChannelPreset {\n const found = CHANNEL_PRESETS.find((p) => p.id === id)\n if (!found) {\n throw new Error(\n `unknown channel preset \"${id}\" — valid ids: ${CHANNEL_PRESETS.map((p) => p.id).join(', ')}`,\n )\n }\n return found\n}\n\n// ---------------------------------------------------------------------------\n// Letterbox scale math (page → channel preset, centered contain)\n// ---------------------------------------------------------------------------\n\nexport interface ChannelScaleResult {\n /**\n * Konva stage pixelRatio: the stage logical size stays at page dimensions;\n * the backing canvas renders at `pixelRatio × page` px. Setting Konva's\n * pixelRatio to this value yields an output canvas exactly\n * `channelPreset.width × channelPreset.height` pixels.\n */\n pixelRatio: number\n /**\n * Horizontal letterbox offset in PAGE-coordinate px. Add to the stage x\n * translation so the page is centered horizontally in the output frame.\n * Zero when the page fills the full width after scaling.\n */\n offsetX: number\n /**\n * Vertical letterbox offset in PAGE-coordinate px. Add to the stage y\n * translation. Zero when the page fills the full height.\n */\n offsetY: number\n fit: 'contain'\n}\n\n/**\n * Computes the Konva stage parameters to render `page` centered inside\n * `channelPreset` without cropping (contain / letterbox).\n *\n * Exact-ratio fast path: when page and preset share the same aspect ratio\n * (within 1e-9 floating-point tolerance) both offsets are 0 and pixelRatio\n * is exact.\n *\n * Example — 1080×1080 page into 1920×1080 preset:\n * scaleX = 1920/1080 ≈ 1.7778, scaleY = 1080/1080 = 1.0\n * pixelRatio = 1.0, rendered page = 1080×1080 px\n * offsetX = (1920 − 1080) / 2 / 1.0 = 420 page-px, offsetY = 0\n */\nexport function scalePageForChannelPreset(\n page: Pick<ScenePage, 'width' | 'height'>,\n channelPreset: ChannelPreset,\n): ChannelScaleResult {\n if (page.width <= 0 || page.height <= 0) {\n throw new Error(`page dimensions must be positive; got ${page.width}×${page.height}`)\n }\n\n const scaleX = channelPreset.width / page.width\n const scaleY = channelPreset.height / page.height\n const pixelRatio = Math.min(scaleX, scaleY)\n\n const renderedW = page.width * pixelRatio\n const renderedH = page.height * pixelRatio\n\n // Back-project padding into page coordinates so the Konva offset is in the\n // stage's own coordinate space\n const offsetX = ((channelPreset.width - renderedW) / 2) / pixelRatio\n const offsetY = ((channelPreset.height - renderedH) / 2) / pixelRatio\n\n return { pixelRatio, offsetX, offsetY, fit: 'contain' }\n}\n\n// ---------------------------------------------------------------------------\n// Bleed-aware trim bounds (no-arg bleed variant for templates/channel exports)\n// ---------------------------------------------------------------------------\n\n/**\n * Export rectangle in page coordinates that includes bleed margins when\n * present. When `page.bleed` is null, returns the trim rectangle (origin 0,0;\n * size = page dimensions).\n *\n * The bleed rectangle extends OUTSIDE the page: x and y are negative (bleed\n * bleeds off the left/top edge), width and height exceed the page by the\n * combined bleed on each axis. Pass into Konva's clip/export bounds to\n * include the bleed zone in the render.\n *\n * Named `bleedAwareExportRect` to avoid collision with the two-arg\n * `bleedAwareExportBounds(page, includeBleed)` above.\n */\nexport function bleedAwareExportRect(page: Pick<ScenePage, 'width' | 'height' | 'bleed'>): Bounds {\n if (page.bleed === null) {\n return { x: 0, y: 0, width: page.width, height: page.height }\n }\n const bleed: PageBleed = page.bleed\n return {\n x: -bleed.left,\n y: -bleed.top,\n width: page.width + bleed.left + bleed.right,\n height: page.height + bleed.top + bleed.bottom,\n }\n}\n"],"mappings":"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","names":[]}