@elytracms/studio 0.0.14 → 0.0.15

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 (93) hide show
  1. package/convex/cms.ts +8 -31
  2. package/convex/content.ts +3 -44
  3. package/convex/delivery.ts +8 -42
  4. package/convex/functions.ts +17 -2
  5. package/convex/members.ts +2 -2
  6. package/convex/referenceMaintenance.ts +4 -73
  7. package/convex/references.ts +4 -2
  8. package/convex/schema.ts +17 -37
  9. package/convex/sync.ts +10 -42
  10. package/convex/triggers.ts +57 -0
  11. package/convex/webhooks.ts +3 -2
  12. package/dist/components/builder/builder-store.d.ts +85 -39
  13. package/dist/components/builder/builder-store.js +29 -125
  14. package/dist/components/builder/builder-store.js.map +1 -1
  15. package/dist/components/builder/canvas.js +23 -55
  16. package/dist/components/builder/canvas.js.map +1 -1
  17. package/dist/components/builder/clipboard-actions.js +3 -3
  18. package/dist/components/builder/clipboard-actions.js.map +1 -1
  19. package/dist/components/builder/composition-field-editor.js +13 -23
  20. package/dist/components/builder/composition-field-editor.js.map +1 -1
  21. package/dist/components/builder/insert-context.js +1 -1
  22. package/dist/components/builder/insert-context.js.map +1 -1
  23. package/dist/components/builder/page-tree.js +3 -4
  24. package/dist/components/builder/page-tree.js.map +1 -1
  25. package/dist/components/builder/property-inspector.js +4 -64
  26. package/dist/components/builder/property-inspector.js.map +1 -1
  27. package/dist/components/cms/cell.d.ts +0 -4
  28. package/dist/components/cms/cell.js +1 -5
  29. package/dist/components/cms/cell.js.map +1 -1
  30. package/dist/components/cms/cms-store.d.ts +1 -1
  31. package/dist/components/cms/cms-store.js +4 -9
  32. package/dist/components/cms/cms-store.js.map +1 -1
  33. package/dist/components/cms/collection-table.js +1 -1
  34. package/dist/components/cms/collection-table.js.map +1 -1
  35. package/dist/components/cms/detail-editor.js +2 -2
  36. package/dist/components/cms/detail-editor.js.map +1 -1
  37. package/dist/components/cms/doc-state.d.ts +0 -5
  38. package/dist/components/cms/doc-state.js +1 -7
  39. package/dist/components/cms/doc-state.js.map +1 -1
  40. package/dist/components/cms/editable-cell.js +1 -1
  41. package/dist/components/cms/editable-cell.js.map +1 -1
  42. package/dist/components/collab/collab-context.d.ts +6 -14
  43. package/dist/components/collab/collab-context.js +3 -12
  44. package/dist/components/collab/collab-context.js.map +1 -1
  45. package/dist/components/collab/collab-seed.d.ts +7 -19
  46. package/dist/components/collab/collab-seed.js +9 -31
  47. package/dist/components/collab/collab-seed.js.map +1 -1
  48. package/dist/components/components/registry-browser.js +6 -12
  49. package/dist/components/components/registry-browser.js.map +1 -1
  50. package/dist/components/guards.d.ts +0 -9
  51. package/dist/components/guards.js +0 -12
  52. package/dist/components/guards.js.map +1 -1
  53. package/dist/components/section-state.d.ts +0 -2
  54. package/dist/components/section-state.js +0 -9
  55. package/dist/components/section-state.js.map +1 -1
  56. package/dist/components/section-surface.d.ts +3 -7
  57. package/dist/components/section-surface.js +5 -12
  58. package/dist/components/section-surface.js.map +1 -1
  59. package/dist/components/sections.d.ts +0 -1
  60. package/dist/components/sections.js +0 -10
  61. package/dist/components/sections.js.map +1 -1
  62. package/dist/components/studio-project-screen.js +13 -14
  63. package/dist/components/studio-project-screen.js.map +1 -1
  64. package/dist/components/studio-shell.d.ts +0 -4
  65. package/dist/components/studio-shell.js +1 -5
  66. package/dist/components/studio-shell.js.map +1 -1
  67. package/dist/lib/operations/graph-commands.d.ts +2 -6
  68. package/dist/lib/operations/graph-commands.js +1 -2
  69. package/dist/lib/operations/graph-commands.js.map +1 -1
  70. package/dist/lib/operations/index.d.ts +0 -2
  71. package/dist/lib/operations/index.js +0 -2
  72. package/dist/lib/operations/index.js.map +1 -1
  73. package/dist/lib/operations/session-hydration.d.ts +14 -24
  74. package/dist/lib/operations/session-hydration.js +15 -34
  75. package/dist/lib/operations/session-hydration.js.map +1 -1
  76. package/dist/lib/persistence/convex-adapter.d.ts +1 -3
  77. package/dist/lib/persistence/convex-adapter.js +1 -154
  78. package/dist/lib/persistence/convex-adapter.js.map +1 -1
  79. package/dist/lib/persona/labels.js +0 -2
  80. package/dist/lib/persona/labels.js.map +1 -1
  81. package/dist/lib/references/reference-model.d.ts +0 -16
  82. package/dist/lib/references/reference-model.js +2 -54
  83. package/dist/lib/references/reference-model.js.map +1 -1
  84. package/dist/lib/references/references-store.js +3 -4
  85. package/dist/lib/references/references-store.js.map +1 -1
  86. package/dist/lib/registry/index.d.ts +0 -16
  87. package/dist/lib/registry/index.js +0 -15
  88. package/dist/lib/registry/index.js.map +1 -1
  89. package/dist/lib/webhooks/tags.js +2 -16
  90. package/dist/lib/webhooks/tags.js.map +1 -1
  91. package/package.json +3 -2
  92. package/convex/graphs.ts +0 -55
  93. package/convex/publishing.ts +0 -76
@@ -1,10 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { createPortal } from 'react-dom';
4
- import { renderCompositionInLayout } from '@elytracms/core/runtime-renderer';
4
+ import { renderPageComposition } from '@elytracms/core/runtime-renderer';
5
5
  import { useParams } from '@elytracms/studio/router';
6
- import { getNode, getParentInfo, parseProjectGraph, staticProp } from '@elytracms/core/project-graph';
7
- import { toProjectGraph } from '@elytracms/studio/lib/working-graph';
6
+ import { getNode, getParentInfo, staticProp } from '@elytracms/core/project-graph';
8
7
  import { canNestInto, containerFlowAxis, dropIndicatorFor, dropPositionForPoint, resolveDrop, } from '@elytracms/studio/lib/dnd/drop-rules';
9
8
  import { activeDrag, beginDrag, endDrag, onDragSessionEnd } from './drag-session';
10
9
  import { PRESERVE_NODE_ATTR, collectPreservedPairs, richTextDocFromDom, } from '@elytracms/core/rich-text';
@@ -13,7 +12,6 @@ import { useOptionalAssets } from '../assets/assets-store';
13
12
  import { resolveCanvasListing, resolveCanvasRelation, useData } from '@elytracms/studio/lib/data';
14
13
  import { cmsBindingFallback, useStudioLocale } from '@elytracms/studio/lib/locale';
15
14
  import { getInstantiatedKit } from '@elytracms/studio/lib/starters/kit-session';
16
- import { useCollab } from '../collab/collab-context';
17
15
  import { getCanvasStylesheetUrl } from './canvas-stylesheet';
18
16
  import { useBuilder } from './builder-store';
19
17
  import { ClipboardNoticeOverlay, attachClipboardListeners, useStudioClipboard, } from './clipboard-actions';
@@ -119,26 +117,10 @@ export function BuilderCanvas() {
119
117
  const { dispatch } = builder;
120
118
  const studio = getStudioRegistry();
121
119
  const data = useData();
122
- const collab = useCollab();
123
- // Draft vs published preview (EC-123): in published mode render the live version (read-only),
124
- // distinct from the live draft the editor mutates. Single-environment (EC-179).
125
- const published = collab.previewMode === 'published';
126
- const publishedGraph = useMemo(() => {
127
- if (!published)
128
- return null;
129
- const versionId = collab.collab.publishing.state(collab.projectId).publishedVersionId;
130
- const version = versionId ? collab.collab.versions.get(collab.projectId, versionId) : undefined;
131
- if (!version)
132
- return null;
133
- const parsed = parseProjectGraph(version.snapshot);
134
- return parsed.ok ? parsed.graph : null;
135
- }, [published, collab]);
136
- const editable = !published;
137
- // The active editable working page (root-bearing surface composed into its
138
- // layout for preview). A published snapshot is a canonical layouts-only
139
- // graph — it has no editable page, so published preview renders the bare
140
- // layout chrome only (the legacy `/builder` page editor is in-memory now).
141
- const activePage = builder.present.pages.find((p) => p.id === builder.pageId) ?? builder.present.pages[0];
120
+ // The edited composition root, composed for preview. EC-287 retired the project
121
+ // graph and its published-graph preview; the canvas always renders the live,
122
+ // editable draft (content publishing is per document).
123
+ const activeRoot = builder.present;
142
124
  const iframeRef = useRef(null);
143
125
  const [doc, setDoc] = useState(null);
144
126
  // Inline editing (EC-158/EC-159): the active session lives in a ref — it is
@@ -157,8 +139,6 @@ export function BuilderCanvas() {
157
139
  const [richEditEpochs, setRichEditEpochs] = useState({});
158
140
  const presentRef = useRef(builder.present);
159
141
  presentRef.current = builder.present;
160
- const pageIdRef = useRef(builder.pageId);
161
- pageIdRef.current = builder.pageId;
162
142
  const selectedIdRef = useRef(builder.selectedId);
163
143
  selectedIdRef.current = builder.selectedId;
164
144
  // When the project was created from a starter kit, its brand token palette drives the canvas UI
@@ -234,10 +214,10 @@ export function BuilderCanvas() {
234
214
  // or insert) → one operations command → one undo step. Ineligible targets
235
215
  // never `preventDefault`, so releasing over one is a native no-op.
236
216
  useEffect(() => {
237
- if (!doc || !editable)
217
+ if (!doc)
238
218
  return;
239
219
  const getManifest = (id) => studio.registry.getManifest(id);
240
- const currentRoot = () => presentRef.current.pages.find((p) => p.id === pageIdRef.current)?.root;
220
+ const currentRoot = () => presentRef.current;
241
221
  let dropWrapper = null;
242
222
  let dropPlan = null;
243
223
  const clearIndicator = () => {
@@ -410,7 +390,7 @@ export function BuilderCanvas() {
410
390
  doc.removeEventListener('dragend', onDragEnd);
411
391
  doc.removeEventListener('dragleave', onDragLeave);
412
392
  };
413
- }, [doc, editable, dispatch, studio]);
393
+ }, [doc, dispatch, studio]);
414
394
  // Inline editing (EC-158 plain text, EC-159 rich text): double-click on a
415
395
  // node whose manifest flags an inline-editable prop turns the *rendered
416
396
  // element itself* contenteditable — no overlay, no input swap, so typography
@@ -424,7 +404,7 @@ export function BuilderCanvas() {
424
404
  // Cmd/Ctrl+Enter or blur (Enter-to-commit would make multi-paragraph content
425
405
  // unauthorable in place). Esc always cancels, dispatching nothing.
426
406
  useEffect(() => {
427
- if (!doc || !editable)
407
+ if (!doc)
428
408
  return;
429
409
  // ---- plain text (EC-158) ------------------------------------------------
430
410
  const beginText = (wrapper, host, session) => {
@@ -592,8 +572,7 @@ export function BuilderCanvas() {
592
572
  return;
593
573
  editingRef.current.finish('commit');
594
574
  }
595
- const page = presentRef.current.pages.find((p) => p.id === pageIdRef.current);
596
- const node = page ? getNode(page.root, nodeId) : undefined;
575
+ const node = getNode(presentRef.current, nodeId);
597
576
  if (!node)
598
577
  return;
599
578
  const manifest = studio.registry.getManifest(node.componentId);
@@ -618,7 +597,7 @@ export function BuilderCanvas() {
618
597
  // Teardown mid-session (doc swap/unmount): cancel — never dispatch from cleanup.
619
598
  editingRef.current?.finish('cancel');
620
599
  };
621
- }, [doc, editable, dispatch, studio]);
600
+ }, [doc, dispatch, studio]);
622
601
  // Copy/cut/paste on the canvas (EC-175): the same studio clipboard the page
623
602
  // tree and blocks panel use, wired to the *iframe* document (events never
624
603
  // cross frames). Shortcuts stay inert while an inline editor is live and in
@@ -626,7 +605,7 @@ export function BuilderCanvas() {
626
605
  // (Chromium scopes clipboard access to the focused document).
627
606
  const clipboard = useStudioClipboard();
628
607
  useEffect(() => {
629
- if (!doc || !editable)
608
+ if (!doc)
630
609
  return;
631
610
  return attachClipboardListeners(doc, {
632
611
  clipboard,
@@ -635,13 +614,10 @@ export function BuilderCanvas() {
635
614
  asyncClipboard: doc.defaultView?.navigator.clipboard,
636
615
  getSelection: () => doc.getSelection(),
637
616
  });
638
- }, [doc, editable, clipboard]);
617
+ }, [doc, clipboard]);
639
618
  // Only page nodes are editable; layout chrome (rendered around the page) is
640
619
  // read-only context and must not be selectable (it isn't in the page tree).
641
- const pageNodeIds = useMemo(() => {
642
- const page = builder.present.pages.find((p) => p.id === builder.pageId);
643
- return page ? collectIds(page.root) : new Set();
644
- }, [builder.present, builder.pageId]);
620
+ const pageNodeIds = useMemo(() => collectIds(builder.present), [builder.present]);
645
621
  // Bridge the renderer's untyped ItemContext (item: unknown) to the binding
646
622
  // layer's RepeaterItemContext (item: JsonValue). The renderer feeds back values
647
623
  // it resolved from JSON payloads, so the item is a JsonValue.
@@ -698,26 +674,18 @@ export function BuilderCanvas() {
698
674
  resolveAsset,
699
675
  resolveRelation,
700
676
  resolveListing,
701
- decorateNode: (node, rendered) => editable && pageNodeIds.has(node.id) ? (_jsx("div", { "data-ec-node-id": node.id, className: "ec-editable", "data-selected": node.id === builder.selectedId || undefined, "data-hovered": node.id === builder.hoveredId || undefined, "data-ec-locale-fallback": localeFallbackOf(node), children: rendered }, `${node.id}#${richEditEpochs[node.id] ?? 0}`)) : (rendered),
702
- }), [studio, resolveBinding, resolveAsset, resolveRelation, resolveListing, pageNodeIds, builder.selectedId, builder.hoveredId, editable, localeFallbackOf, richEditEpochs]);
677
+ decorateNode: (node, rendered) => pageNodeIds.has(node.id) ? (_jsx("div", { "data-ec-node-id": node.id, className: "ec-editable", "data-selected": node.id === builder.selectedId || undefined, "data-hovered": node.id === builder.hoveredId || undefined, "data-ec-locale-fallback": localeFallbackOf(node), children: rendered }, `${node.id}#${richEditEpochs[node.id] ?? 0}`)) : (rendered),
678
+ }), [studio, resolveBinding, resolveAsset, resolveRelation, resolveListing, pageNodeIds, builder.selectedId, builder.hoveredId, localeFallbackOf, richEditEpochs]);
703
679
  // Tokenized spacing handles (EC-163): a selected Stack/Grid with 2+ children
704
680
  // gets draggable gap handles between them, portaled into the iframe.
705
- const spacingTarget = editable && doc && hasSpacingHandles(builder.selectedNode) && pageNodeIds.has(builder.selectedNode.id)
681
+ const spacingTarget = doc && hasSpacingHandles(builder.selectedNode) && pageNodeIds.has(builder.selectedNode.id)
706
682
  ? builder.selectedNode
707
683
  : null;
708
- return (_jsxs("div", { className: "canvas-grid relative flex min-h-0 flex-1 items-stretch justify-center overflow-auto p-6", children: [editable ? _jsx(ClipboardNoticeOverlay, {}) : null, published ? (_jsx("div", { className: "pointer-events-none absolute left-1/2 top-3 z-10 -translate-x-1/2", children: _jsx("span", { className: "rounded-full border border-info/30 bg-info/10 px-2.5 py-0.5 text-xs font-medium text-info", children: publishedGraph ? 'Published preview' : 'Nothing published' }) })) : null, _jsxs("div", { style: { width: VIEWPORT_WIDTH[builder.viewport], maxWidth: '100%' }, className: "flex", children: [_jsx("iframe", { ref: iframeRef, onLoad: wireUp, title: "Page preview", className: "min-h-[480px] w-full rounded-lg border border-border bg-background shadow-md", srcDoc: "<!doctype html><html><head></head><body></body></html>" }), doc
709
- ? createPortal(published
710
- ? // Published preview: a layouts-only snapshot has no editable
711
- // page, so render the bare published layout chrome (empty
712
- // composition into the first layout), or nothing when absent.
713
- publishedGraph
714
- ? renderCompositionInLayout(publishedGraph, publishedGraph.layouts[0]?.id, [], ctx)
715
- : null
716
- : // Editable: compose the active working page's root into its
717
- // layout (or bare when it has no layout).
718
- activePage
719
- ? renderCompositionInLayout(toProjectGraph(builder.present), activePage.layoutId, activePage.root, ctx)
720
- : null, doc.body)
684
+ return (_jsxs("div", { className: "canvas-grid relative flex min-h-0 flex-1 items-stretch justify-center overflow-auto p-6", children: [_jsx(ClipboardNoticeOverlay, {}), _jsxs("div", { style: { width: VIEWPORT_WIDTH[builder.viewport], maxWidth: '100%' }, className: "flex", children: [_jsx("iframe", { ref: iframeRef, onLoad: wireUp, title: "Page preview", className: "min-h-[480px] w-full rounded-lg border border-border bg-background shadow-md", srcDoc: "<!doctype html><html><head></head><body></body></html>" }), doc
685
+ ? createPortal(
686
+ // Render the composition root directly (EC-287: no layout
687
+ // indirection — a page renders its blocks).
688
+ renderPageComposition(activeRoot, ctx), doc.body)
721
689
  : null, spacingTarget && doc ? (_jsx(SpacingHandles, { doc: doc, node: spacingTarget }, spacingTarget.id)) : null, richEditHost && doc ? _jsx(RichTextToolbar, { doc: doc, host: richEditHost }) : null] })] }));
722
690
  }
723
691
  //# sourceMappingURL=canvas.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"canvas.js","sourceRoot":"","sources":["../../../src/components/builder/canvas.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { renderCompositionInLayout } from '@elytracms/core/runtime-renderer'\nimport type {\n RenderContext,\n ResolveAsset,\n ResolveBinding,\n ResolveListing,\n ResolveRelation,\n} from '@elytracms/core/runtime-renderer'\nimport type { ComponentNode, JsonValue } from '@elytracms/core/project-graph'\nimport { useParams } from '@elytracms/studio/router'\nimport { getNode, getParentInfo, parseProjectGraph, staticProp } from '@elytracms/core/project-graph'\nimport type { ProjectGraph } from '@elytracms/core/project-graph'\nimport { toProjectGraph } from '@elytracms/studio/lib/working-graph'\nimport type { WorkingGraph, WorkingPage } from '@elytracms/studio/lib/working-graph'\nimport {\n canNestInto,\n containerFlowAxis,\n dropIndicatorFor,\n dropPositionForPoint,\n resolveDrop,\n} from '@elytracms/studio/lib/dnd/drop-rules'\nimport type { DropPlan, DropPosition, FlowAxis } from '@elytracms/studio/lib/dnd/drop-rules'\nimport { activeDrag, beginDrag, endDrag, onDragSessionEnd } from './drag-session'\nimport {\n PRESERVE_NODE_ATTR,\n collectPreservedPairs,\n richTextDocFromDom,\n} from '@elytracms/core/rich-text'\nimport type { RtDomElement } from '@elytracms/core/rich-text'\nimport { getStudioRegistry } from '@elytracms/studio/lib/registry'\nimport { useOptionalAssets } from '../assets/assets-store'\nimport { resolveCanvasListing, resolveCanvasRelation, useData } from '@elytracms/studio/lib/data'\nimport { cmsBindingFallback, useStudioLocale } from '@elytracms/studio/lib/locale'\nimport { getInstantiatedKit } from '@elytracms/studio/lib/starters/kit-session'\nimport { useCollab } from '../collab/collab-context'\nimport { getCanvasStylesheetUrl } from './canvas-stylesheet'\nimport { useBuilder } from './builder-store'\nimport type { Viewport } from './builder-store'\nimport {\n ClipboardNoticeOverlay,\n attachClipboardListeners,\n useStudioClipboard,\n} from './clipboard-actions'\nimport {\n createInlineEditSession,\n createInlineRichTextSession,\n findInlineTextHost,\n resolveInlineEditableProp,\n resolveInlineRichTextProp,\n} from './inline-edit'\nimport type { InlineEditSession, InlineRichTextProp } from './inline-edit'\nimport { RichTextToolbar } from './rich-text-toolbar'\nimport { SpacingHandles, hasSpacingHandles } from './spacing-handles'\n\nconst VIEWPORT_WIDTH: Record<Viewport, string> = {\n desktop: '100%',\n tablet: '768px',\n mobile: '390px',\n}\n\n/** Selection/hover outlines, scoped to the per-node editable wrappers. */\nconst OUTLINE_CSS = `\n html { color-scheme: dark; }\n body { margin: 0; padding: 16px; }\n .ec-editable { outline-offset: -1px; cursor: default; }\n .ec-editable[data-hovered]:not([data-selected]) { outline: 1px dashed rgba(130,150,190,0.75); }\n .ec-editable[data-selected] { outline: 2px solid #5b8cff; }\n /* Inline editing (EC-158 text, EC-159 rich text): the rendered element\n itself becomes the editor — no overlay, no replacement input — so\n typography, alignment, and layout are pixel-identical between edit and\n render states. The wrapper keeps the selection outline; the host only\n gets a caret. pre-wrap applies to PLAIN text hosts only — rich-text\n markup must keep its rendered whitespace handling (no layout shift). */\n .ec-editable[data-ec-editing] { outline: 2px solid #5b8cff; }\n .ec-editable [data-ec-edit] { outline: none; cursor: text; }\n .ec-editable [data-ec-edit='text'] { white-space: pre-wrap; }\n /* Preserved atoms during a rich-text session (custom blocks, unknown nodes,\n images, embeds): visible and rendered, but not text-editable. */\n .ec-editable [data-ec-edit='rich'] [${PRESERVE_NODE_ATTR}] { user-select: none; }\n /* Floating mark toolbar (EC-159), portaled into the iframe. */\n .ec-rt-toolbar { color-scheme: dark; }\n .ec-rt-toolbar-row { display: flex; align-items: center; gap: 2px; padding: 3px;\n border: 1px solid rgba(130,150,190,0.4); border-radius: 8px;\n background: rgb(24,26,32); box-shadow: 0 4px 16px rgba(0,0,0,0.4); }\n .ec-rt-toolbar-btn { min-width: 26px; height: 24px; padding: 0 7px; border: 0; border-radius: 5px;\n background: transparent; color: rgb(225,228,236); font: 600 12px/1 ui-sans-serif, system-ui, sans-serif;\n cursor: pointer; }\n .ec-rt-toolbar-btn:hover { background: rgba(130,150,190,0.25); }\n .ec-rt-toolbar-btn[data-active] { background: #5b8cff; color: white; }\n .ec-rt-toolbar-input { width: 200px; height: 24px; padding: 0 7px; border-radius: 5px;\n border: 1px solid rgba(130,150,190,0.4); background: rgb(16,18,22); color: rgb(225,228,236);\n font: 12px/1 ui-sans-serif, system-ui, sans-serif; outline: none; }\n /* Locale-fallback chips (EC-176): a node whose bound content is currently\n served via locale fallback wears a small corner chip naming the locale it\n actually came from — the canvas never silently mixes locales. */\n .ec-editable[data-ec-locale-fallback] { position: relative; }\n .ec-editable[data-ec-locale-fallback]::after {\n content: attr(data-ec-locale-fallback);\n position: absolute; top: 2px; right: 2px; z-index: 5; pointer-events: none;\n padding: 0 4px; border-radius: 4px;\n font: 600 9px/1.5 ui-sans-serif, system-ui, sans-serif;\n letter-spacing: 0.05em; text-transform: uppercase;\n color: #fbbf24; background: rgba(180,83,9,0.25); border: 1px solid rgba(245,158,11,0.45);\n }\n /* Drag & drop states (EC-160/EC-162): eligibility comes from the shared pure\n rules (lib/dnd/drop-rules); these classes only *show* the resolution.\n Rejection is explicit and visible during the drag — never a silent failed\n drop. Before/after bars follow the parent's flow axis (data-ec-drop-axis);\n left/right are the wrap-into-columns gesture (violet, paired highlight). */\n .ec-editable[data-ec-drop='into'] { outline: 2px solid #34d399; outline-offset: -2px; background-color: rgba(52, 211, 153, 0.08); }\n .ec-editable[data-ec-drop='before'] { box-shadow: 0 -3px 0 0 #38bdf8; }\n .ec-editable[data-ec-drop='after'] { box-shadow: 0 3px 0 0 #38bdf8; }\n .ec-editable[data-ec-drop='before'][data-ec-drop-axis='x'] { box-shadow: -3px 0 0 0 #38bdf8; }\n .ec-editable[data-ec-drop='after'][data-ec-drop-axis='x'] { box-shadow: 3px 0 0 0 #38bdf8; }\n .ec-editable[data-ec-drop='left'] { box-shadow: -3px 0 0 0 #a78bfa; background-color: rgba(167, 139, 250, 0.1); }\n .ec-editable[data-ec-drop='right'] { box-shadow: 3px 0 0 0 #a78bfa; background-color: rgba(167, 139, 250, 0.1); }\n .ec-editable[data-ec-drop='blocked'] { outline: 2px solid #ef4444; outline-offset: -2px; background-color: rgba(239, 68, 68, 0.08); cursor: not-allowed; }\n`\n\nfunction nodeIdAt(target: EventTarget | null): string | null {\n return wrapperAt(target)?.getAttribute('data-ec-node-id') ?? null\n}\n\nfunction wrapperAt(target: EventTarget | null): HTMLElement | null {\n const el = target as HTMLElement | null\n return (el?.closest?.('[data-ec-node-id]') as HTMLElement | null) ?? null\n}\n\n/** A live inline-editing session bound to its DOM host (EC-158/EC-159). */\ninterface ActiveInlineEdit {\n nodeId: string\n host: HTMLElement\n /** Finish the session exactly once (later calls are no-ops). */\n finish: (mode: 'commit' | 'cancel') => void\n}\n\n/**\n * The rendered `.rich-text` element inside a node's wrapper — the rich-text\n * editing host (EC-159). Never crosses into a nested node's wrapper.\n */\nfunction findRichTextHost(wrapper: HTMLElement): HTMLElement | null {\n const host = wrapper.querySelector('.rich-text') as HTMLElement | null\n return host && host.closest('[data-ec-node-id]') === wrapper ? host : null\n}\n\n/** Collect every node id under a root (the page subtree). */\nfunction collectIds(node: ComponentNode, out: Set<string> = new Set()): Set<string> {\n out.add(node.id)\n for (const children of Object.values(node.slots ?? {})) {\n for (const child of children) collectIds(child, out)\n }\n return out\n}\n\n/**\n * Iframe-isolated page preview (brief §8.2, EC-061, EC-064). The graph renders\n * into a same-origin iframe via a React portal — true style isolation + true\n * responsive widths. Each node is wrapped with an editable marker so clicks\n * select and hover/selection draw outlines. Native listeners bridge the iframe\n * boundary (React's synthetic events don't cross frames).\n */\nexport function BuilderCanvas() {\n const builder = useBuilder()\n const { dispatch } = builder\n const studio = getStudioRegistry()\n const data = useData()\n const collab = useCollab()\n\n // Draft vs published preview (EC-123): in published mode render the live version (read-only),\n // distinct from the live draft the editor mutates. Single-environment (EC-179).\n const published = collab.previewMode === 'published'\n const publishedGraph = useMemo<ProjectGraph | null>(() => {\n if (!published) return null\n const versionId = collab.collab.publishing.state(collab.projectId).publishedVersionId\n const version = versionId ? collab.collab.versions.get(collab.projectId, versionId) : undefined\n if (!version) return null\n const parsed = parseProjectGraph(version.snapshot)\n return parsed.ok ? parsed.graph : null\n }, [published, collab])\n const editable = !published\n // The active editable working page (root-bearing surface composed into its\n // layout for preview). A published snapshot is a canonical layouts-only\n // graph — it has no editable page, so published preview renders the bare\n // layout chrome only (the legacy `/builder` page editor is in-memory now).\n const activePage: WorkingPage | undefined =\n builder.present.pages.find((p) => p.id === builder.pageId) ?? builder.present.pages[0]\n const iframeRef = useRef<HTMLIFrameElement>(null)\n const [doc, setDoc] = useState<Document | null>(null)\n\n // Inline editing (EC-158/EC-159): the active session lives in a ref — it is\n // imperative DOM state inside the iframe, not render state. Graph/page refs\n // let the native dblclick handler read the *current* graph without\n // re-subscribing listeners on every edit. The rich-text host additionally\n // mirrors into render state so the floating mark toolbar can mount.\n const editingRef = useRef<ActiveInlineEdit | null>(null)\n const [richEditHost, setRichEditHost] = useState<HTMLElement | null>(null)\n // A rich-text session mutates the rendered DOM behind React's back\n // (contenteditable + mark commands), so finishing one must REMOUNT the\n // node's subtree — bumping its epoch changes the decorate key, React\n // discards the edited DOM wholesale and re-renders from the graph (the\n // committed value, or the untouched original on cancel). Patching the old\n // fiber tree against editor-mutated DOM would leave stale artifacts.\n const [richEditEpochs, setRichEditEpochs] = useState<Record<string, number>>({})\n const presentRef = useRef(builder.present)\n presentRef.current = builder.present\n const pageIdRef = useRef(builder.pageId)\n pageIdRef.current = builder.pageId\n const selectedIdRef = useRef(builder.selectedId)\n selectedIdRef.current = builder.selectedId\n\n // When the project was created from a starter kit, its brand token palette drives the canvas UI\n // (EC-117) — injected after app.css so the kit's overrides win in the cascade.\n const params = useParams({ strict: false }) as { projectId?: string }\n const kitTokensCss = params.projectId ? getInstantiatedKit(params.projectId)?.tokensCss : undefined\n\n const wireUp = useCallback(() => {\n const d = iframeRef.current?.contentDocument\n if (!d || !d.body) return\n d.documentElement.classList.add('dark')\n const appCss = getCanvasStylesheetUrl()\n if (appCss && !d.getElementById('ec-app-css')) {\n const link = d.createElement('link')\n link.id = 'ec-app-css'\n link.rel = 'stylesheet'\n link.href = appCss\n d.head.appendChild(link)\n }\n if (!d.getElementById('ec-outline-css')) {\n const style = d.createElement('style')\n style.id = 'ec-outline-css'\n style.textContent = OUTLINE_CSS\n d.head.appendChild(style)\n }\n if (kitTokensCss) {\n const existing = d.getElementById('ec-kit-tokens')\n if (existing) existing.remove()\n const style = d.createElement('style')\n style.id = 'ec-kit-tokens'\n style.textContent = kitTokensCss\n d.head.appendChild(style)\n }\n d.body.className = 'bg-background text-foreground font-sans'\n setDoc(d)\n }, [kitTokensCss])\n\n // Handle the already-loaded case (srcDoc may load before onLoad attaches).\n useEffect(() => {\n if (iframeRef.current?.contentDocument?.readyState === 'complete') wireUp()\n }, [wireUp])\n\n // Native selection/hover listeners inside the iframe document.\n useEffect(() => {\n if (!doc) return\n const onClick = (e: Event) => {\n // Clicks inside the active inline editor are caret moves, not selection.\n if (editingRef.current?.host.contains(e.target as Node)) return\n const id = nodeIdAt(e.target)\n if (id) {\n e.preventDefault()\n dispatch({ type: 'select', id })\n }\n }\n const onOver = (e: Event) => dispatch({ type: 'hover', id: nodeIdAt(e.target) })\n const onLeave = () => dispatch({ type: 'hover', id: null })\n doc.addEventListener('click', onClick, true)\n doc.addEventListener('mouseover', onOver)\n doc.addEventListener('mouseleave', onLeave, true)\n return () => {\n doc.removeEventListener('click', onClick, true)\n doc.removeEventListener('mouseover', onOver)\n doc.removeEventListener('mouseleave', onLeave, true)\n }\n }, [doc, dispatch])\n\n // Drag & drop on the canvas (EC-160). Eligibility is the pure shared rule\n // set (`lib/dnd/drop-rules`) — the same functions the page tree consumes —\n // evaluated live during `dragover`; the wrapper under the pointer shows the\n // resolution (`data-ec-drop`: into/before/after, or `blocked` for a visible\n // rejection). A completed drop dispatches exactly one builder action (move\n // or insert) → one operations command → one undo step. Ineligible targets\n // never `preventDefault`, so releasing over one is a native no-op.\n useEffect(() => {\n if (!doc || !editable) return\n const getManifest = (id: string) => studio.registry.getManifest(id)\n const currentRoot = () =>\n presentRef.current.pages.find((p: WorkingPage) => p.id === pageIdRef.current)?.root\n\n let dropWrapper: HTMLElement | null = null\n let dropPlan: DropPlan | null = null\n const clearIndicator = () => {\n dropWrapper?.removeAttribute('data-ec-drop')\n dropWrapper?.removeAttribute('data-ec-drop-axis')\n dropWrapper = null\n dropPlan = null\n }\n const showIndicator = (wrapper: HTMLElement | null, state: string | null, axis: FlowAxis) => {\n if (dropWrapper && dropWrapper !== wrapper) {\n dropWrapper.removeAttribute('data-ec-drop')\n dropWrapper.removeAttribute('data-ec-drop-axis')\n }\n dropWrapper = wrapper\n if (!wrapper) return\n if (state) {\n wrapper.setAttribute('data-ec-drop', state)\n // Before/after bars render along the parent's flow axis (EC-162).\n wrapper.setAttribute('data-ec-drop-axis', axis === 'horizontal' ? 'x' : 'y')\n } else {\n wrapper.removeAttribute('data-ec-drop')\n wrapper.removeAttribute('data-ec-drop-axis')\n }\n }\n\n // Wrappers are armed draggable per-gesture on mousedown, never via render\n // state: the active inline editor (EC-158) must keep native caret clicks\n // and text selection, so a press inside the editing host disarms its\n // wrapper instead of starting a node drag.\n const onMouseDown = (e: Event) => {\n const wrapper = wrapperAt(e.target)\n if (!wrapper) return\n const root = currentRoot()\n const nodeId = wrapper.getAttribute('data-ec-node-id')\n const inEditor = editingRef.current?.host.contains(e.target as Node) ?? false\n if (root && nodeId && nodeId !== root.id && !inEditor) {\n wrapper.setAttribute('draggable', 'true')\n } else {\n wrapper.removeAttribute('draggable')\n }\n }\n\n const onDragStart = (e: DragEvent) => {\n // Drags inside the live inline editor are native text drags — leave them alone.\n if (editingRef.current?.host.contains(e.target as Node)) return\n const wrapper = wrapperAt(e.target)\n if (!wrapper) return\n const root = currentRoot()\n const nodeId = wrapper.getAttribute('data-ec-node-id')!\n const node = root ? getNode(root, nodeId) : undefined\n if (!root || !node || nodeId === root.id) {\n e.preventDefault()\n return\n }\n beginDrag(\n { subject: { kind: 'node', nodeId, componentId: node.componentId }, source: 'canvas', label: node.componentId },\n e.dataTransfer,\n )\n }\n\n const onDragOver = (e: DragEvent) => {\n const drag = activeDrag()\n if (!drag) return\n const root = currentRoot()\n if (!root) return\n const wrapper = wrapperAt(e.target)\n // Empty space around the page subtree targets the root slot (append).\n const refId = wrapper?.getAttribute('data-ec-node-id') ?? root.id\n const refWrapper =\n wrapper ?? (doc.querySelector(`[data-ec-node-id=\"${root.id}\"]`) as HTMLElement | null)\n const refNode = getNode(root, refId)\n if (!refNode) {\n clearIndicator()\n return\n }\n let position: DropPosition = 'into'\n let flow: FlowAxis = 'vertical'\n if (wrapper && refId !== root.id) {\n const rect = wrapper.getBoundingClientRect()\n // Hit-bands follow the parent's flow axis (EC-162); the cross-axis\n // side bands of vertically flowing targets are the wrap gesture.\n flow = containerFlowAxis(getParentInfo(root, refId)?.parent)\n position = dropPositionForPoint({\n x: rect.width > 0 ? (e.clientX - rect.left) / rect.width : 0.5,\n y: rect.height > 0 ? (e.clientY - rect.top) / rect.height : 0.5,\n flow,\n nestable: canNestInto(getManifest, refNode.componentId),\n edges: true,\n wrappable: true,\n })\n }\n const resolution = resolveDrop({\n root,\n getManifest,\n subject: drag.subject,\n location: { nodeId: refId, position },\n })\n showIndicator(refWrapper, dropIndicatorFor(resolution, position), flow)\n if (resolution.eligible) {\n dropPlan = resolution\n e.preventDefault()\n if (e.dataTransfer) {\n e.dataTransfer.dropEffect = drag.subject.kind === 'node' ? 'move' : 'copy'\n }\n } else {\n dropPlan = null\n }\n }\n\n const onDrop = (e: DragEvent) => {\n const drag = activeDrag()\n if (!drag) return\n const plan = dropPlan\n clearIndicator()\n if (!plan) return\n e.preventDefault()\n // Exactly one dispatch per completed drop (one undo step, one command).\n if (plan.kind === 'move') {\n dispatch({ type: 'move', id: plan.nodeId, target: plan.target })\n } else if (plan.kind === 'wrap') {\n // EC-162 gesture: reference + subject become a two-column Grid.\n const subject =\n plan.nodeId !== undefined\n ? { kind: 'node' as const, nodeId: plan.nodeId }\n : drag.buildNode\n ? { kind: 'component' as const, node: drag.buildNode() }\n : null\n if (!subject) {\n endDrag('cancelled')\n return\n }\n dispatch({ type: 'wrap', referenceId: plan.referenceId, side: plan.side, subject })\n } else if (drag.buildNode) {\n dispatch({ type: 'insert', target: plan.target, node: drag.buildNode() })\n } else {\n endDrag('cancelled')\n return\n }\n endDrag('dropped')\n }\n\n const onDragEnd = () => {\n clearIndicator()\n endDrag('cancelled')\n }\n\n const onDragLeave = (e: DragEvent) => {\n // Leaving the iframe document entirely (relatedTarget is null).\n if (!e.relatedTarget) clearIndicator()\n }\n\n // Cleanup when the drag ends anywhere (e.g. dropped on the page tree).\n const unsubscribe = onDragSessionEnd(() => clearIndicator())\n\n doc.addEventListener('mousedown', onMouseDown, true)\n doc.addEventListener('dragstart', onDragStart)\n doc.addEventListener('dragover', onDragOver)\n doc.addEventListener('drop', onDrop)\n doc.addEventListener('dragend', onDragEnd)\n doc.addEventListener('dragleave', onDragLeave)\n return () => {\n unsubscribe()\n clearIndicator()\n doc.removeEventListener('mousedown', onMouseDown, true)\n doc.removeEventListener('dragstart', onDragStart)\n doc.removeEventListener('dragover', onDragOver)\n doc.removeEventListener('drop', onDrop)\n doc.removeEventListener('dragend', onDragEnd)\n doc.removeEventListener('dragleave', onDragLeave)\n }\n }, [doc, editable, dispatch, studio])\n\n // Inline editing (EC-158 plain text, EC-159 rich text): double-click on a\n // node whose manifest flags an inline-editable prop turns the *rendered\n // element itself* contenteditable — no overlay, no input swap, so typography\n // and layout are identical in edit and render states. A session finishes\n // exactly once, and a commit dispatches exactly one `setProp` action — one\n // undo step, mirrored as one `graph.setNodeProp` operations command by the\n // builder-store persister. The graph stays the single source of truth.\n //\n // Commit/cancel gestures: plain text commits on Enter or blur; rich text is\n // multiline, so plain Enter inserts a paragraph and the commit gesture is\n // Cmd/Ctrl+Enter or blur (Enter-to-commit would make multi-paragraph content\n // unauthorable in place). Esc always cancels, dispatching nothing.\n useEffect(() => {\n if (!doc || !editable) return\n\n // ---- plain text (EC-158) ------------------------------------------------\n const beginText = (wrapper: HTMLElement, host: HTMLElement, session: InlineEditSession) => {\n let done = false\n const finish = (mode: 'commit' | 'cancel') => {\n if (done) return\n done = true\n editingRef.current = null\n const text = host.textContent ?? ''\n host.removeEventListener('keydown', onKeyDown)\n host.removeEventListener('blur', onBlur)\n host.removeAttribute('contenteditable')\n host.removeAttribute('data-ec-edit')\n wrapper.removeAttribute('data-ec-editing')\n if (mode === 'commit') {\n const outcome = session.commit(text)\n if (outcome) {\n dispatch({\n type: 'setProp',\n id: outcome.nodeId,\n name: outcome.propName,\n value: staticProp(outcome.value),\n })\n }\n } else {\n const outcome = session.cancel()\n if (outcome) host.textContent = outcome.value\n }\n doc.getSelection()?.removeAllRanges()\n }\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n e.stopPropagation()\n finish('commit')\n } else if (e.key === 'Escape') {\n e.preventDefault()\n e.stopPropagation()\n finish('cancel')\n }\n }\n const onBlur = () => finish('commit')\n // `plaintext-only` keeps paste/typing plain; fall back where unsupported.\n host.setAttribute('contenteditable', 'plaintext-only')\n if (!host.isContentEditable) host.setAttribute('contenteditable', 'true')\n host.setAttribute('data-ec-edit', 'text')\n wrapper.setAttribute('data-ec-editing', '')\n host.addEventListener('keydown', onKeyDown)\n host.addEventListener('blur', onBlur)\n editingRef.current = { nodeId: session.nodeId, host, finish }\n host.focus({ preventScroll: true })\n // Keep the gesture's native caret/word selection when it landed inside\n // the host; otherwise select the whole value.\n const sel = doc.getSelection()\n if (!sel || sel.rangeCount === 0 || !host.contains(sel.anchorNode)) {\n const range = doc.createRange()\n range.selectNodeContents(host)\n sel?.removeAllRanges()\n sel?.addRange(range)\n }\n }\n\n // ---- rich text (EC-159) -------------------------------------------------\n const beginRichText = (wrapper: HTMLElement, nodeId: string, target: InlineRichTextProp) => {\n const host = findRichTextHost(wrapper)\n if (!host) return\n // Pair the storage tree against the rendered DOM and stamp every\n // non-invertible node (custom blocks, unknown nodes, images, embeds)\n // with its exact JSON: they stay rendered *inside* the live editor as\n // non-editable atoms and survive the session byte-exact. A pairing\n // mismatch means the DOM diverged from the deterministic render —\n // refuse to start rather than risk lossy parsing (\"polished or absent\").\n const pairs = collectPreservedPairs(target.value.doc, host as unknown as RtDomElement)\n if (!pairs) return\n const session = createInlineRichTextSession({\n nodeId,\n propName: target.propName,\n original: target.value,\n })\n for (const pair of pairs) {\n const el = pair.element as unknown as HTMLElement\n el.setAttribute(PRESERVE_NODE_ATTR, JSON.stringify(pair.node))\n el.setAttribute('contenteditable', 'false')\n }\n let done = false\n const finish = (mode: 'commit' | 'cancel') => {\n if (done) return\n done = true\n editingRef.current = null\n setRichEditHost(null)\n // Parse the edited DOM, detach the session, then bump the node's\n // remount epoch: React discards the editor-mutated DOM and renders\n // fresh from the graph — committed content or, on cancel, the\n // untouched original. Never patch a fiber tree against DOM the\n // editing commands rewrote.\n const parsed = mode === 'commit' ? richTextDocFromDom(host as unknown as RtDomElement) : null\n host.removeEventListener('keydown', onKeyDown)\n host.removeEventListener('blur', onBlur)\n host.removeAttribute('contenteditable')\n host.removeAttribute('data-ec-edit')\n wrapper.removeAttribute('data-ec-editing')\n setRichEditEpochs((prev) => ({ ...prev, [nodeId]: (prev[nodeId] ?? 0) + 1 }))\n if (parsed) {\n // An unchanged document commits nothing: the stored value is never\n // rewritten, so untouched content round-trips byte-identical.\n const outcome = session.commit(parsed.doc)\n if (outcome) {\n dispatch({\n type: 'setProp',\n id: outcome.nodeId,\n name: outcome.propName,\n value: staticProp(outcome.value as unknown as JsonValue),\n })\n }\n } else {\n session.cancel()\n }\n doc.getSelection()?.removeAllRanges()\n }\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n e.stopPropagation()\n finish('cancel')\n } else if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault()\n e.stopPropagation()\n finish('commit')\n }\n // Plain Enter falls through: native paragraph insertion (multiline).\n }\n const onBlur = (e: FocusEvent) => {\n // Interacting with the floating toolbar is part of the session.\n const next = e.relatedTarget as HTMLElement | null\n if (next?.closest?.('[data-ec-rt-toolbar]')) return\n finish('commit')\n }\n host.setAttribute('contenteditable', 'true')\n host.setAttribute('data-ec-edit', 'rich')\n wrapper.setAttribute('data-ec-editing', '')\n host.addEventListener('keydown', onKeyDown)\n host.addEventListener('blur', onBlur)\n editingRef.current = { nodeId, host, finish }\n setRichEditHost(host)\n host.focus({ preventScroll: true })\n }\n\n const onDblClick = (e: Event) => {\n const wrapper = wrapperAt(e.target)\n if (!wrapper) return\n const nodeId = wrapper.getAttribute('data-ec-node-id')!\n if (editingRef.current) {\n // Double-click inside the live editor is native word selection.\n if (editingRef.current.nodeId === nodeId) return\n editingRef.current.finish('commit')\n }\n const page = presentRef.current.pages.find((p: WorkingPage) => p.id === pageIdRef.current)\n const node = page ? getNode(page.root, nodeId) : undefined\n if (!node) return\n const manifest = studio.registry.getManifest(node.componentId)\n const target = resolveInlineEditableProp(manifest, node)\n if (target) {\n const host = findInlineTextHost(wrapper, target.value) as HTMLElement | null\n if (!host || typeof host.focus !== 'function') return\n dispatch({ type: 'select', id: nodeId })\n beginText(\n wrapper,\n host,\n createInlineEditSession({ nodeId, propName: target.propName, original: target.value }),\n )\n return\n }\n const richTarget = resolveInlineRichTextProp(manifest, node)\n if (!richTarget) return\n dispatch({ type: 'select', id: nodeId })\n beginRichText(wrapper, nodeId, richTarget)\n }\n\n doc.addEventListener('dblclick', onDblClick, true)\n return () => {\n doc.removeEventListener('dblclick', onDblClick, true)\n // Teardown mid-session (doc swap/unmount): cancel — never dispatch from cleanup.\n editingRef.current?.finish('cancel')\n }\n }, [doc, editable, dispatch, studio])\n\n // Copy/cut/paste on the canvas (EC-175): the same studio clipboard the page\n // tree and blocks panel use, wired to the *iframe* document (events never\n // cross frames). Shortcuts stay inert while an inline editor is live and in\n // form fields; the iframe's own navigator.clipboard does the async I/O\n // (Chromium scopes clipboard access to the focused document).\n const clipboard = useStudioClipboard()\n useEffect(() => {\n if (!doc || !editable) return\n return attachClipboardListeners(doc, {\n clipboard,\n getSelectedId: () => selectedIdRef.current,\n isBlocked: () => editingRef.current !== null,\n asyncClipboard: doc.defaultView?.navigator.clipboard,\n getSelection: () => doc.getSelection(),\n })\n }, [doc, editable, clipboard])\n\n // Only page nodes are editable; layout chrome (rendered around the page) is\n // read-only context and must not be selectable (it isn't in the page tree).\n const pageNodeIds = useMemo(() => {\n const page = builder.present.pages.find((p: WorkingPage) => p.id === builder.pageId)\n return page ? collectIds(page.root) : new Set<string>()\n }, [builder.present, builder.pageId])\n\n // Bridge the renderer's untyped ItemContext (item: unknown) to the binding\n // layer's RepeaterItemContext (item: JsonValue). The renderer feeds back values\n // it resolved from JSON payloads, so the item is a JsonValue.\n const resolveBinding: ResolveBinding = useCallback(\n (ref, item) =>\n data.resolveValue(ref, item ? { item: item.item as JsonValue, index: item.index } : undefined),\n [data],\n )\n\n // EC-195: resolve an `asset`-typed Image prop (an asset id) to its url +\n // intrinsic dimensions from the live asset library, so the canvas previews\n // exactly what the host renders. A record without a resolved url (e.g. a\n // never-served seed) → null → the implementation's visible empty state.\n const assetsStore = useOptionalAssets()\n const resolveAsset: ResolveAsset = useCallback(\n (assetId) => {\n const record = assetsStore?.assets.find((a) => a.id === assetId)\n if (!record?.url) return null\n return {\n url: record.url,\n width: record.width ?? null,\n height: record.height ?? null,\n alt: record.alt ?? null,\n focalPoint: record.focalPoint ?? null,\n }\n },\n [assetsStore],\n )\n\n // Locale-fallback chips (EC-176): a node whose bound content currently\n // previews via EC-018 locale fallback wears a corner chip naming the locale\n // the value actually came from. Same decision function as the inspector's\n // Content tab (`cmsBindingFallback`), so chip and label can never disagree.\n const { locale: activeLocale } = useStudioLocale()\n\n // EC-254: populate a block's `relation` prop (the editor's document pick — a\n // ProductGrid's products, a Reusable's element) to delivery shape from the\n // active content session, in the canvas's active locale, so the canvas previews\n // picked documents exactly as the host renders them. The studio analog of the\n // host's baked relations map. A missing/invisible target → null → the block's\n // own empty state.\n const resolveRelation: ResolveRelation = useCallback(\n (ref) => resolveCanvasRelation(ref, activeLocale),\n [activeLocale],\n )\n\n // EC-255: resolve a listing block's query (a ProductGrid keyed to a category) to\n // its documents from the active content session, in the canvas's active locale, so\n // the canvas previews a dynamic grid exactly as the host renders it. The studio\n // analog of the host's baked listings map; an empty/invalid query → [] → the\n // block's own empty state.\n const resolveListing: ResolveListing = useCallback(\n (query) => resolveCanvasListing(query, activeLocale),\n [activeLocale],\n )\n\n const localeFallbackOf = useCallback(\n (node: ComponentNode): string | undefined => {\n for (const value of Object.values(node.props ?? {})) {\n if (value.kind !== 'binding') continue\n const fallback = cmsBindingFallback(\n value.binding,\n data.getSource(value.binding.sourceId),\n activeLocale,\n )\n if (fallback) return fallback.sourceLocale\n }\n return undefined\n },\n [data, activeLocale],\n )\n\n const ctx: RenderContext = useMemo(\n () => ({\n registry: studio.registry,\n implementations: studio.implementations,\n resolveBinding,\n resolveAsset,\n resolveRelation,\n resolveListing,\n decorateNode: (node, rendered) =>\n editable && pageNodeIds.has(node.id) ? (\n <div\n // The epoch suffix forces a remount after a rich-text editing\n // session mutated this node's rendered DOM (see richEditEpochs).\n key={`${node.id}#${richEditEpochs[node.id] ?? 0}`}\n data-ec-node-id={node.id}\n className=\"ec-editable\"\n data-selected={node.id === builder.selectedId || undefined}\n data-hovered={node.id === builder.hoveredId || undefined}\n data-ec-locale-fallback={localeFallbackOf(node)}\n >\n {rendered}\n </div>\n ) : (\n rendered\n ),\n }),\n [studio, resolveBinding, resolveAsset, resolveRelation, resolveListing, pageNodeIds, builder.selectedId, builder.hoveredId, editable, localeFallbackOf, richEditEpochs],\n )\n\n // Tokenized spacing handles (EC-163): a selected Stack/Grid with 2+ children\n // gets draggable gap handles between them, portaled into the iframe.\n const spacingTarget =\n editable && doc && hasSpacingHandles(builder.selectedNode) && pageNodeIds.has(builder.selectedNode.id)\n ? builder.selectedNode\n : null\n\n return (\n <div className=\"canvas-grid relative flex min-h-0 flex-1 items-stretch justify-center overflow-auto p-6\">\n {/* Copy/cut/paste outcomes (EC-175): non-blocking, with issue deep links. */}\n {editable ? <ClipboardNoticeOverlay /> : null}\n {published ? (\n <div className=\"pointer-events-none absolute left-1/2 top-3 z-10 -translate-x-1/2\">\n <span className=\"rounded-full border border-info/30 bg-info/10 px-2.5 py-0.5 text-xs font-medium text-info\">\n {publishedGraph ? 'Published preview' : 'Nothing published'}\n </span>\n </div>\n ) : null}\n <div style={{ width: VIEWPORT_WIDTH[builder.viewport], maxWidth: '100%' }} className=\"flex\">\n <iframe\n ref={iframeRef}\n onLoad={wireUp}\n title=\"Page preview\"\n className=\"min-h-[480px] w-full rounded-lg border border-border bg-background shadow-md\"\n srcDoc=\"<!doctype html><html><head></head><body></body></html>\"\n />\n {doc\n ? createPortal(\n published\n ? // Published preview: a layouts-only snapshot has no editable\n // page, so render the bare published layout chrome (empty\n // composition into the first layout), or nothing when absent.\n publishedGraph\n ? renderCompositionInLayout(publishedGraph, publishedGraph.layouts[0]?.id, [], ctx)\n : null\n : // Editable: compose the active working page's root into its\n // layout (or bare when it has no layout).\n activePage\n ? renderCompositionInLayout(\n toProjectGraph(builder.present),\n activePage.layoutId,\n activePage.root,\n ctx,\n )\n : null,\n doc.body,\n )\n : null}\n {spacingTarget && doc ? (\n <SpacingHandles key={spacingTarget.id} doc={doc} node={spacingTarget} />\n ) : null}\n {/* Floating mark toolbar for the live rich-text session (EC-159). */}\n {richEditHost && doc ? <RichTextToolbar doc={doc} host={richEditHost} /> : null}\n </div>\n </div>\n )\n}\n"]}
1
+ {"version":3,"file":"canvas.js","sourceRoot":"","sources":["../../../src/components/builder/canvas.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { renderPageComposition } from '@elytracms/core/runtime-renderer'\nimport type {\n RenderContext,\n ResolveAsset,\n ResolveBinding,\n ResolveListing,\n ResolveRelation,\n} from '@elytracms/core/runtime-renderer'\nimport type { ComponentNode, JsonValue } from '@elytracms/core/project-graph'\nimport { useParams } from '@elytracms/studio/router'\nimport { getNode, getParentInfo, staticProp } from '@elytracms/core/project-graph'\nimport {\n canNestInto,\n containerFlowAxis,\n dropIndicatorFor,\n dropPositionForPoint,\n resolveDrop,\n} from '@elytracms/studio/lib/dnd/drop-rules'\nimport type { DropPlan, DropPosition, FlowAxis } from '@elytracms/studio/lib/dnd/drop-rules'\nimport { activeDrag, beginDrag, endDrag, onDragSessionEnd } from './drag-session'\nimport {\n PRESERVE_NODE_ATTR,\n collectPreservedPairs,\n richTextDocFromDom,\n} from '@elytracms/core/rich-text'\nimport type { RtDomElement } from '@elytracms/core/rich-text'\nimport { getStudioRegistry } from '@elytracms/studio/lib/registry'\nimport { useOptionalAssets } from '../assets/assets-store'\nimport { resolveCanvasListing, resolveCanvasRelation, useData } from '@elytracms/studio/lib/data'\nimport { cmsBindingFallback, useStudioLocale } from '@elytracms/studio/lib/locale'\nimport { getInstantiatedKit } from '@elytracms/studio/lib/starters/kit-session'\nimport { getCanvasStylesheetUrl } from './canvas-stylesheet'\nimport { useBuilder } from './builder-store'\nimport type { Viewport } from './builder-store'\nimport {\n ClipboardNoticeOverlay,\n attachClipboardListeners,\n useStudioClipboard,\n} from './clipboard-actions'\nimport {\n createInlineEditSession,\n createInlineRichTextSession,\n findInlineTextHost,\n resolveInlineEditableProp,\n resolveInlineRichTextProp,\n} from './inline-edit'\nimport type { InlineEditSession, InlineRichTextProp } from './inline-edit'\nimport { RichTextToolbar } from './rich-text-toolbar'\nimport { SpacingHandles, hasSpacingHandles } from './spacing-handles'\n\nconst VIEWPORT_WIDTH: Record<Viewport, string> = {\n desktop: '100%',\n tablet: '768px',\n mobile: '390px',\n}\n\n/** Selection/hover outlines, scoped to the per-node editable wrappers. */\nconst OUTLINE_CSS = `\n html { color-scheme: dark; }\n body { margin: 0; padding: 16px; }\n .ec-editable { outline-offset: -1px; cursor: default; }\n .ec-editable[data-hovered]:not([data-selected]) { outline: 1px dashed rgba(130,150,190,0.75); }\n .ec-editable[data-selected] { outline: 2px solid #5b8cff; }\n /* Inline editing (EC-158 text, EC-159 rich text): the rendered element\n itself becomes the editor — no overlay, no replacement input — so\n typography, alignment, and layout are pixel-identical between edit and\n render states. The wrapper keeps the selection outline; the host only\n gets a caret. pre-wrap applies to PLAIN text hosts only — rich-text\n markup must keep its rendered whitespace handling (no layout shift). */\n .ec-editable[data-ec-editing] { outline: 2px solid #5b8cff; }\n .ec-editable [data-ec-edit] { outline: none; cursor: text; }\n .ec-editable [data-ec-edit='text'] { white-space: pre-wrap; }\n /* Preserved atoms during a rich-text session (custom blocks, unknown nodes,\n images, embeds): visible and rendered, but not text-editable. */\n .ec-editable [data-ec-edit='rich'] [${PRESERVE_NODE_ATTR}] { user-select: none; }\n /* Floating mark toolbar (EC-159), portaled into the iframe. */\n .ec-rt-toolbar { color-scheme: dark; }\n .ec-rt-toolbar-row { display: flex; align-items: center; gap: 2px; padding: 3px;\n border: 1px solid rgba(130,150,190,0.4); border-radius: 8px;\n background: rgb(24,26,32); box-shadow: 0 4px 16px rgba(0,0,0,0.4); }\n .ec-rt-toolbar-btn { min-width: 26px; height: 24px; padding: 0 7px; border: 0; border-radius: 5px;\n background: transparent; color: rgb(225,228,236); font: 600 12px/1 ui-sans-serif, system-ui, sans-serif;\n cursor: pointer; }\n .ec-rt-toolbar-btn:hover { background: rgba(130,150,190,0.25); }\n .ec-rt-toolbar-btn[data-active] { background: #5b8cff; color: white; }\n .ec-rt-toolbar-input { width: 200px; height: 24px; padding: 0 7px; border-radius: 5px;\n border: 1px solid rgba(130,150,190,0.4); background: rgb(16,18,22); color: rgb(225,228,236);\n font: 12px/1 ui-sans-serif, system-ui, sans-serif; outline: none; }\n /* Locale-fallback chips (EC-176): a node whose bound content is currently\n served via locale fallback wears a small corner chip naming the locale it\n actually came from — the canvas never silently mixes locales. */\n .ec-editable[data-ec-locale-fallback] { position: relative; }\n .ec-editable[data-ec-locale-fallback]::after {\n content: attr(data-ec-locale-fallback);\n position: absolute; top: 2px; right: 2px; z-index: 5; pointer-events: none;\n padding: 0 4px; border-radius: 4px;\n font: 600 9px/1.5 ui-sans-serif, system-ui, sans-serif;\n letter-spacing: 0.05em; text-transform: uppercase;\n color: #fbbf24; background: rgba(180,83,9,0.25); border: 1px solid rgba(245,158,11,0.45);\n }\n /* Drag & drop states (EC-160/EC-162): eligibility comes from the shared pure\n rules (lib/dnd/drop-rules); these classes only *show* the resolution.\n Rejection is explicit and visible during the drag — never a silent failed\n drop. Before/after bars follow the parent's flow axis (data-ec-drop-axis);\n left/right are the wrap-into-columns gesture (violet, paired highlight). */\n .ec-editable[data-ec-drop='into'] { outline: 2px solid #34d399; outline-offset: -2px; background-color: rgba(52, 211, 153, 0.08); }\n .ec-editable[data-ec-drop='before'] { box-shadow: 0 -3px 0 0 #38bdf8; }\n .ec-editable[data-ec-drop='after'] { box-shadow: 0 3px 0 0 #38bdf8; }\n .ec-editable[data-ec-drop='before'][data-ec-drop-axis='x'] { box-shadow: -3px 0 0 0 #38bdf8; }\n .ec-editable[data-ec-drop='after'][data-ec-drop-axis='x'] { box-shadow: 3px 0 0 0 #38bdf8; }\n .ec-editable[data-ec-drop='left'] { box-shadow: -3px 0 0 0 #a78bfa; background-color: rgba(167, 139, 250, 0.1); }\n .ec-editable[data-ec-drop='right'] { box-shadow: 3px 0 0 0 #a78bfa; background-color: rgba(167, 139, 250, 0.1); }\n .ec-editable[data-ec-drop='blocked'] { outline: 2px solid #ef4444; outline-offset: -2px; background-color: rgba(239, 68, 68, 0.08); cursor: not-allowed; }\n`\n\nfunction nodeIdAt(target: EventTarget | null): string | null {\n return wrapperAt(target)?.getAttribute('data-ec-node-id') ?? null\n}\n\nfunction wrapperAt(target: EventTarget | null): HTMLElement | null {\n const el = target as HTMLElement | null\n return (el?.closest?.('[data-ec-node-id]') as HTMLElement | null) ?? null\n}\n\n/** A live inline-editing session bound to its DOM host (EC-158/EC-159). */\ninterface ActiveInlineEdit {\n nodeId: string\n host: HTMLElement\n /** Finish the session exactly once (later calls are no-ops). */\n finish: (mode: 'commit' | 'cancel') => void\n}\n\n/**\n * The rendered `.rich-text` element inside a node's wrapper — the rich-text\n * editing host (EC-159). Never crosses into a nested node's wrapper.\n */\nfunction findRichTextHost(wrapper: HTMLElement): HTMLElement | null {\n const host = wrapper.querySelector('.rich-text') as HTMLElement | null\n return host && host.closest('[data-ec-node-id]') === wrapper ? host : null\n}\n\n/** Collect every node id under a root (the page subtree). */\nfunction collectIds(node: ComponentNode, out: Set<string> = new Set()): Set<string> {\n out.add(node.id)\n for (const children of Object.values(node.slots ?? {})) {\n for (const child of children) collectIds(child, out)\n }\n return out\n}\n\n/**\n * Iframe-isolated page preview (brief §8.2, EC-061, EC-064). The graph renders\n * into a same-origin iframe via a React portal — true style isolation + true\n * responsive widths. Each node is wrapped with an editable marker so clicks\n * select and hover/selection draw outlines. Native listeners bridge the iframe\n * boundary (React's synthetic events don't cross frames).\n */\nexport function BuilderCanvas() {\n const builder = useBuilder()\n const { dispatch } = builder\n const studio = getStudioRegistry()\n const data = useData()\n\n // The edited composition root, composed for preview. EC-287 retired the project\n // graph and its published-graph preview; the canvas always renders the live,\n // editable draft (content publishing is per document).\n const activeRoot: ComponentNode = builder.present\n const iframeRef = useRef<HTMLIFrameElement>(null)\n const [doc, setDoc] = useState<Document | null>(null)\n\n // Inline editing (EC-158/EC-159): the active session lives in a ref — it is\n // imperative DOM state inside the iframe, not render state. Graph/page refs\n // let the native dblclick handler read the *current* graph without\n // re-subscribing listeners on every edit. The rich-text host additionally\n // mirrors into render state so the floating mark toolbar can mount.\n const editingRef = useRef<ActiveInlineEdit | null>(null)\n const [richEditHost, setRichEditHost] = useState<HTMLElement | null>(null)\n // A rich-text session mutates the rendered DOM behind React's back\n // (contenteditable + mark commands), so finishing one must REMOUNT the\n // node's subtree — bumping its epoch changes the decorate key, React\n // discards the edited DOM wholesale and re-renders from the graph (the\n // committed value, or the untouched original on cancel). Patching the old\n // fiber tree against editor-mutated DOM would leave stale artifacts.\n const [richEditEpochs, setRichEditEpochs] = useState<Record<string, number>>({})\n const presentRef = useRef(builder.present)\n presentRef.current = builder.present\n const selectedIdRef = useRef(builder.selectedId)\n selectedIdRef.current = builder.selectedId\n\n // When the project was created from a starter kit, its brand token palette drives the canvas UI\n // (EC-117) — injected after app.css so the kit's overrides win in the cascade.\n const params = useParams({ strict: false }) as { projectId?: string }\n const kitTokensCss = params.projectId ? getInstantiatedKit(params.projectId)?.tokensCss : undefined\n\n const wireUp = useCallback(() => {\n const d = iframeRef.current?.contentDocument\n if (!d || !d.body) return\n d.documentElement.classList.add('dark')\n const appCss = getCanvasStylesheetUrl()\n if (appCss && !d.getElementById('ec-app-css')) {\n const link = d.createElement('link')\n link.id = 'ec-app-css'\n link.rel = 'stylesheet'\n link.href = appCss\n d.head.appendChild(link)\n }\n if (!d.getElementById('ec-outline-css')) {\n const style = d.createElement('style')\n style.id = 'ec-outline-css'\n style.textContent = OUTLINE_CSS\n d.head.appendChild(style)\n }\n if (kitTokensCss) {\n const existing = d.getElementById('ec-kit-tokens')\n if (existing) existing.remove()\n const style = d.createElement('style')\n style.id = 'ec-kit-tokens'\n style.textContent = kitTokensCss\n d.head.appendChild(style)\n }\n d.body.className = 'bg-background text-foreground font-sans'\n setDoc(d)\n }, [kitTokensCss])\n\n // Handle the already-loaded case (srcDoc may load before onLoad attaches).\n useEffect(() => {\n if (iframeRef.current?.contentDocument?.readyState === 'complete') wireUp()\n }, [wireUp])\n\n // Native selection/hover listeners inside the iframe document.\n useEffect(() => {\n if (!doc) return\n const onClick = (e: Event) => {\n // Clicks inside the active inline editor are caret moves, not selection.\n if (editingRef.current?.host.contains(e.target as Node)) return\n const id = nodeIdAt(e.target)\n if (id) {\n e.preventDefault()\n dispatch({ type: 'select', id })\n }\n }\n const onOver = (e: Event) => dispatch({ type: 'hover', id: nodeIdAt(e.target) })\n const onLeave = () => dispatch({ type: 'hover', id: null })\n doc.addEventListener('click', onClick, true)\n doc.addEventListener('mouseover', onOver)\n doc.addEventListener('mouseleave', onLeave, true)\n return () => {\n doc.removeEventListener('click', onClick, true)\n doc.removeEventListener('mouseover', onOver)\n doc.removeEventListener('mouseleave', onLeave, true)\n }\n }, [doc, dispatch])\n\n // Drag & drop on the canvas (EC-160). Eligibility is the pure shared rule\n // set (`lib/dnd/drop-rules`) — the same functions the page tree consumes —\n // evaluated live during `dragover`; the wrapper under the pointer shows the\n // resolution (`data-ec-drop`: into/before/after, or `blocked` for a visible\n // rejection). A completed drop dispatches exactly one builder action (move\n // or insert) → one operations command → one undo step. Ineligible targets\n // never `preventDefault`, so releasing over one is a native no-op.\n useEffect(() => {\n if (!doc) return\n const getManifest = (id: string) => studio.registry.getManifest(id)\n const currentRoot = () => presentRef.current\n\n let dropWrapper: HTMLElement | null = null\n let dropPlan: DropPlan | null = null\n const clearIndicator = () => {\n dropWrapper?.removeAttribute('data-ec-drop')\n dropWrapper?.removeAttribute('data-ec-drop-axis')\n dropWrapper = null\n dropPlan = null\n }\n const showIndicator = (wrapper: HTMLElement | null, state: string | null, axis: FlowAxis) => {\n if (dropWrapper && dropWrapper !== wrapper) {\n dropWrapper.removeAttribute('data-ec-drop')\n dropWrapper.removeAttribute('data-ec-drop-axis')\n }\n dropWrapper = wrapper\n if (!wrapper) return\n if (state) {\n wrapper.setAttribute('data-ec-drop', state)\n // Before/after bars render along the parent's flow axis (EC-162).\n wrapper.setAttribute('data-ec-drop-axis', axis === 'horizontal' ? 'x' : 'y')\n } else {\n wrapper.removeAttribute('data-ec-drop')\n wrapper.removeAttribute('data-ec-drop-axis')\n }\n }\n\n // Wrappers are armed draggable per-gesture on mousedown, never via render\n // state: the active inline editor (EC-158) must keep native caret clicks\n // and text selection, so a press inside the editing host disarms its\n // wrapper instead of starting a node drag.\n const onMouseDown = (e: Event) => {\n const wrapper = wrapperAt(e.target)\n if (!wrapper) return\n const root = currentRoot()\n const nodeId = wrapper.getAttribute('data-ec-node-id')\n const inEditor = editingRef.current?.host.contains(e.target as Node) ?? false\n if (root && nodeId && nodeId !== root.id && !inEditor) {\n wrapper.setAttribute('draggable', 'true')\n } else {\n wrapper.removeAttribute('draggable')\n }\n }\n\n const onDragStart = (e: DragEvent) => {\n // Drags inside the live inline editor are native text drags — leave them alone.\n if (editingRef.current?.host.contains(e.target as Node)) return\n const wrapper = wrapperAt(e.target)\n if (!wrapper) return\n const root = currentRoot()\n const nodeId = wrapper.getAttribute('data-ec-node-id')!\n const node = root ? getNode(root, nodeId) : undefined\n if (!root || !node || nodeId === root.id) {\n e.preventDefault()\n return\n }\n beginDrag(\n { subject: { kind: 'node', nodeId, componentId: node.componentId }, source: 'canvas', label: node.componentId },\n e.dataTransfer,\n )\n }\n\n const onDragOver = (e: DragEvent) => {\n const drag = activeDrag()\n if (!drag) return\n const root = currentRoot()\n if (!root) return\n const wrapper = wrapperAt(e.target)\n // Empty space around the page subtree targets the root slot (append).\n const refId = wrapper?.getAttribute('data-ec-node-id') ?? root.id\n const refWrapper =\n wrapper ?? (doc.querySelector(`[data-ec-node-id=\"${root.id}\"]`) as HTMLElement | null)\n const refNode = getNode(root, refId)\n if (!refNode) {\n clearIndicator()\n return\n }\n let position: DropPosition = 'into'\n let flow: FlowAxis = 'vertical'\n if (wrapper && refId !== root.id) {\n const rect = wrapper.getBoundingClientRect()\n // Hit-bands follow the parent's flow axis (EC-162); the cross-axis\n // side bands of vertically flowing targets are the wrap gesture.\n flow = containerFlowAxis(getParentInfo(root, refId)?.parent)\n position = dropPositionForPoint({\n x: rect.width > 0 ? (e.clientX - rect.left) / rect.width : 0.5,\n y: rect.height > 0 ? (e.clientY - rect.top) / rect.height : 0.5,\n flow,\n nestable: canNestInto(getManifest, refNode.componentId),\n edges: true,\n wrappable: true,\n })\n }\n const resolution = resolveDrop({\n root,\n getManifest,\n subject: drag.subject,\n location: { nodeId: refId, position },\n })\n showIndicator(refWrapper, dropIndicatorFor(resolution, position), flow)\n if (resolution.eligible) {\n dropPlan = resolution\n e.preventDefault()\n if (e.dataTransfer) {\n e.dataTransfer.dropEffect = drag.subject.kind === 'node' ? 'move' : 'copy'\n }\n } else {\n dropPlan = null\n }\n }\n\n const onDrop = (e: DragEvent) => {\n const drag = activeDrag()\n if (!drag) return\n const plan = dropPlan\n clearIndicator()\n if (!plan) return\n e.preventDefault()\n // Exactly one dispatch per completed drop (one undo step, one command).\n if (plan.kind === 'move') {\n dispatch({ type: 'move', id: plan.nodeId, target: plan.target })\n } else if (plan.kind === 'wrap') {\n // EC-162 gesture: reference + subject become a two-column Grid.\n const subject =\n plan.nodeId !== undefined\n ? { kind: 'node' as const, nodeId: plan.nodeId }\n : drag.buildNode\n ? { kind: 'component' as const, node: drag.buildNode() }\n : null\n if (!subject) {\n endDrag('cancelled')\n return\n }\n dispatch({ type: 'wrap', referenceId: plan.referenceId, side: plan.side, subject })\n } else if (drag.buildNode) {\n dispatch({ type: 'insert', target: plan.target, node: drag.buildNode() })\n } else {\n endDrag('cancelled')\n return\n }\n endDrag('dropped')\n }\n\n const onDragEnd = () => {\n clearIndicator()\n endDrag('cancelled')\n }\n\n const onDragLeave = (e: DragEvent) => {\n // Leaving the iframe document entirely (relatedTarget is null).\n if (!e.relatedTarget) clearIndicator()\n }\n\n // Cleanup when the drag ends anywhere (e.g. dropped on the page tree).\n const unsubscribe = onDragSessionEnd(() => clearIndicator())\n\n doc.addEventListener('mousedown', onMouseDown, true)\n doc.addEventListener('dragstart', onDragStart)\n doc.addEventListener('dragover', onDragOver)\n doc.addEventListener('drop', onDrop)\n doc.addEventListener('dragend', onDragEnd)\n doc.addEventListener('dragleave', onDragLeave)\n return () => {\n unsubscribe()\n clearIndicator()\n doc.removeEventListener('mousedown', onMouseDown, true)\n doc.removeEventListener('dragstart', onDragStart)\n doc.removeEventListener('dragover', onDragOver)\n doc.removeEventListener('drop', onDrop)\n doc.removeEventListener('dragend', onDragEnd)\n doc.removeEventListener('dragleave', onDragLeave)\n }\n }, [doc, dispatch, studio])\n\n // Inline editing (EC-158 plain text, EC-159 rich text): double-click on a\n // node whose manifest flags an inline-editable prop turns the *rendered\n // element itself* contenteditable — no overlay, no input swap, so typography\n // and layout are identical in edit and render states. A session finishes\n // exactly once, and a commit dispatches exactly one `setProp` action — one\n // undo step, mirrored as one `graph.setNodeProp` operations command by the\n // builder-store persister. The graph stays the single source of truth.\n //\n // Commit/cancel gestures: plain text commits on Enter or blur; rich text is\n // multiline, so plain Enter inserts a paragraph and the commit gesture is\n // Cmd/Ctrl+Enter or blur (Enter-to-commit would make multi-paragraph content\n // unauthorable in place). Esc always cancels, dispatching nothing.\n useEffect(() => {\n if (!doc) return\n\n // ---- plain text (EC-158) ------------------------------------------------\n const beginText = (wrapper: HTMLElement, host: HTMLElement, session: InlineEditSession) => {\n let done = false\n const finish = (mode: 'commit' | 'cancel') => {\n if (done) return\n done = true\n editingRef.current = null\n const text = host.textContent ?? ''\n host.removeEventListener('keydown', onKeyDown)\n host.removeEventListener('blur', onBlur)\n host.removeAttribute('contenteditable')\n host.removeAttribute('data-ec-edit')\n wrapper.removeAttribute('data-ec-editing')\n if (mode === 'commit') {\n const outcome = session.commit(text)\n if (outcome) {\n dispatch({\n type: 'setProp',\n id: outcome.nodeId,\n name: outcome.propName,\n value: staticProp(outcome.value),\n })\n }\n } else {\n const outcome = session.cancel()\n if (outcome) host.textContent = outcome.value\n }\n doc.getSelection()?.removeAllRanges()\n }\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n e.stopPropagation()\n finish('commit')\n } else if (e.key === 'Escape') {\n e.preventDefault()\n e.stopPropagation()\n finish('cancel')\n }\n }\n const onBlur = () => finish('commit')\n // `plaintext-only` keeps paste/typing plain; fall back where unsupported.\n host.setAttribute('contenteditable', 'plaintext-only')\n if (!host.isContentEditable) host.setAttribute('contenteditable', 'true')\n host.setAttribute('data-ec-edit', 'text')\n wrapper.setAttribute('data-ec-editing', '')\n host.addEventListener('keydown', onKeyDown)\n host.addEventListener('blur', onBlur)\n editingRef.current = { nodeId: session.nodeId, host, finish }\n host.focus({ preventScroll: true })\n // Keep the gesture's native caret/word selection when it landed inside\n // the host; otherwise select the whole value.\n const sel = doc.getSelection()\n if (!sel || sel.rangeCount === 0 || !host.contains(sel.anchorNode)) {\n const range = doc.createRange()\n range.selectNodeContents(host)\n sel?.removeAllRanges()\n sel?.addRange(range)\n }\n }\n\n // ---- rich text (EC-159) -------------------------------------------------\n const beginRichText = (wrapper: HTMLElement, nodeId: string, target: InlineRichTextProp) => {\n const host = findRichTextHost(wrapper)\n if (!host) return\n // Pair the storage tree against the rendered DOM and stamp every\n // non-invertible node (custom blocks, unknown nodes, images, embeds)\n // with its exact JSON: they stay rendered *inside* the live editor as\n // non-editable atoms and survive the session byte-exact. A pairing\n // mismatch means the DOM diverged from the deterministic render —\n // refuse to start rather than risk lossy parsing (\"polished or absent\").\n const pairs = collectPreservedPairs(target.value.doc, host as unknown as RtDomElement)\n if (!pairs) return\n const session = createInlineRichTextSession({\n nodeId,\n propName: target.propName,\n original: target.value,\n })\n for (const pair of pairs) {\n const el = pair.element as unknown as HTMLElement\n el.setAttribute(PRESERVE_NODE_ATTR, JSON.stringify(pair.node))\n el.setAttribute('contenteditable', 'false')\n }\n let done = false\n const finish = (mode: 'commit' | 'cancel') => {\n if (done) return\n done = true\n editingRef.current = null\n setRichEditHost(null)\n // Parse the edited DOM, detach the session, then bump the node's\n // remount epoch: React discards the editor-mutated DOM and renders\n // fresh from the graph — committed content or, on cancel, the\n // untouched original. Never patch a fiber tree against DOM the\n // editing commands rewrote.\n const parsed = mode === 'commit' ? richTextDocFromDom(host as unknown as RtDomElement) : null\n host.removeEventListener('keydown', onKeyDown)\n host.removeEventListener('blur', onBlur)\n host.removeAttribute('contenteditable')\n host.removeAttribute('data-ec-edit')\n wrapper.removeAttribute('data-ec-editing')\n setRichEditEpochs((prev) => ({ ...prev, [nodeId]: (prev[nodeId] ?? 0) + 1 }))\n if (parsed) {\n // An unchanged document commits nothing: the stored value is never\n // rewritten, so untouched content round-trips byte-identical.\n const outcome = session.commit(parsed.doc)\n if (outcome) {\n dispatch({\n type: 'setProp',\n id: outcome.nodeId,\n name: outcome.propName,\n value: staticProp(outcome.value as unknown as JsonValue),\n })\n }\n } else {\n session.cancel()\n }\n doc.getSelection()?.removeAllRanges()\n }\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n e.stopPropagation()\n finish('cancel')\n } else if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault()\n e.stopPropagation()\n finish('commit')\n }\n // Plain Enter falls through: native paragraph insertion (multiline).\n }\n const onBlur = (e: FocusEvent) => {\n // Interacting with the floating toolbar is part of the session.\n const next = e.relatedTarget as HTMLElement | null\n if (next?.closest?.('[data-ec-rt-toolbar]')) return\n finish('commit')\n }\n host.setAttribute('contenteditable', 'true')\n host.setAttribute('data-ec-edit', 'rich')\n wrapper.setAttribute('data-ec-editing', '')\n host.addEventListener('keydown', onKeyDown)\n host.addEventListener('blur', onBlur)\n editingRef.current = { nodeId, host, finish }\n setRichEditHost(host)\n host.focus({ preventScroll: true })\n }\n\n const onDblClick = (e: Event) => {\n const wrapper = wrapperAt(e.target)\n if (!wrapper) return\n const nodeId = wrapper.getAttribute('data-ec-node-id')!\n if (editingRef.current) {\n // Double-click inside the live editor is native word selection.\n if (editingRef.current.nodeId === nodeId) return\n editingRef.current.finish('commit')\n }\n const node = getNode(presentRef.current, nodeId)\n if (!node) return\n const manifest = studio.registry.getManifest(node.componentId)\n const target = resolveInlineEditableProp(manifest, node)\n if (target) {\n const host = findInlineTextHost(wrapper, target.value) as HTMLElement | null\n if (!host || typeof host.focus !== 'function') return\n dispatch({ type: 'select', id: nodeId })\n beginText(\n wrapper,\n host,\n createInlineEditSession({ nodeId, propName: target.propName, original: target.value }),\n )\n return\n }\n const richTarget = resolveInlineRichTextProp(manifest, node)\n if (!richTarget) return\n dispatch({ type: 'select', id: nodeId })\n beginRichText(wrapper, nodeId, richTarget)\n }\n\n doc.addEventListener('dblclick', onDblClick, true)\n return () => {\n doc.removeEventListener('dblclick', onDblClick, true)\n // Teardown mid-session (doc swap/unmount): cancel — never dispatch from cleanup.\n editingRef.current?.finish('cancel')\n }\n }, [doc, dispatch, studio])\n\n // Copy/cut/paste on the canvas (EC-175): the same studio clipboard the page\n // tree and blocks panel use, wired to the *iframe* document (events never\n // cross frames). Shortcuts stay inert while an inline editor is live and in\n // form fields; the iframe's own navigator.clipboard does the async I/O\n // (Chromium scopes clipboard access to the focused document).\n const clipboard = useStudioClipboard()\n useEffect(() => {\n if (!doc) return\n return attachClipboardListeners(doc, {\n clipboard,\n getSelectedId: () => selectedIdRef.current,\n isBlocked: () => editingRef.current !== null,\n asyncClipboard: doc.defaultView?.navigator.clipboard,\n getSelection: () => doc.getSelection(),\n })\n }, [doc, clipboard])\n\n // Only page nodes are editable; layout chrome (rendered around the page) is\n // read-only context and must not be selectable (it isn't in the page tree).\n const pageNodeIds = useMemo(() => collectIds(builder.present), [builder.present])\n\n // Bridge the renderer's untyped ItemContext (item: unknown) to the binding\n // layer's RepeaterItemContext (item: JsonValue). The renderer feeds back values\n // it resolved from JSON payloads, so the item is a JsonValue.\n const resolveBinding: ResolveBinding = useCallback(\n (ref, item) =>\n data.resolveValue(ref, item ? { item: item.item as JsonValue, index: item.index } : undefined),\n [data],\n )\n\n // EC-195: resolve an `asset`-typed Image prop (an asset id) to its url +\n // intrinsic dimensions from the live asset library, so the canvas previews\n // exactly what the host renders. A record without a resolved url (e.g. a\n // never-served seed) → null → the implementation's visible empty state.\n const assetsStore = useOptionalAssets()\n const resolveAsset: ResolveAsset = useCallback(\n (assetId) => {\n const record = assetsStore?.assets.find((a) => a.id === assetId)\n if (!record?.url) return null\n return {\n url: record.url,\n width: record.width ?? null,\n height: record.height ?? null,\n alt: record.alt ?? null,\n focalPoint: record.focalPoint ?? null,\n }\n },\n [assetsStore],\n )\n\n // Locale-fallback chips (EC-176): a node whose bound content currently\n // previews via EC-018 locale fallback wears a corner chip naming the locale\n // the value actually came from. Same decision function as the inspector's\n // Content tab (`cmsBindingFallback`), so chip and label can never disagree.\n const { locale: activeLocale } = useStudioLocale()\n\n // EC-254: populate a block's `relation` prop (the editor's document pick — a\n // ProductGrid's products, a Reusable's element) to delivery shape from the\n // active content session, in the canvas's active locale, so the canvas previews\n // picked documents exactly as the host renders them. The studio analog of the\n // host's baked relations map. A missing/invisible target → null → the block's\n // own empty state.\n const resolveRelation: ResolveRelation = useCallback(\n (ref) => resolveCanvasRelation(ref, activeLocale),\n [activeLocale],\n )\n\n // EC-255: resolve a listing block's query (a ProductGrid keyed to a category) to\n // its documents from the active content session, in the canvas's active locale, so\n // the canvas previews a dynamic grid exactly as the host renders it. The studio\n // analog of the host's baked listings map; an empty/invalid query → [] → the\n // block's own empty state.\n const resolveListing: ResolveListing = useCallback(\n (query) => resolveCanvasListing(query, activeLocale),\n [activeLocale],\n )\n\n const localeFallbackOf = useCallback(\n (node: ComponentNode): string | undefined => {\n for (const value of Object.values(node.props ?? {})) {\n if (value.kind !== 'binding') continue\n const fallback = cmsBindingFallback(\n value.binding,\n data.getSource(value.binding.sourceId),\n activeLocale,\n )\n if (fallback) return fallback.sourceLocale\n }\n return undefined\n },\n [data, activeLocale],\n )\n\n const ctx: RenderContext = useMemo(\n () => ({\n registry: studio.registry,\n implementations: studio.implementations,\n resolveBinding,\n resolveAsset,\n resolveRelation,\n resolveListing,\n decorateNode: (node, rendered) =>\n pageNodeIds.has(node.id) ? (\n <div\n // The epoch suffix forces a remount after a rich-text editing\n // session mutated this node's rendered DOM (see richEditEpochs).\n key={`${node.id}#${richEditEpochs[node.id] ?? 0}`}\n data-ec-node-id={node.id}\n className=\"ec-editable\"\n data-selected={node.id === builder.selectedId || undefined}\n data-hovered={node.id === builder.hoveredId || undefined}\n data-ec-locale-fallback={localeFallbackOf(node)}\n >\n {rendered}\n </div>\n ) : (\n rendered\n ),\n }),\n [studio, resolveBinding, resolveAsset, resolveRelation, resolveListing, pageNodeIds, builder.selectedId, builder.hoveredId, localeFallbackOf, richEditEpochs],\n )\n\n // Tokenized spacing handles (EC-163): a selected Stack/Grid with 2+ children\n // gets draggable gap handles between them, portaled into the iframe.\n const spacingTarget =\n doc && hasSpacingHandles(builder.selectedNode) && pageNodeIds.has(builder.selectedNode.id)\n ? builder.selectedNode\n : null\n\n return (\n <div className=\"canvas-grid relative flex min-h-0 flex-1 items-stretch justify-center overflow-auto p-6\">\n {/* Copy/cut/paste outcomes (EC-175): non-blocking, with issue deep links. */}\n <ClipboardNoticeOverlay />\n <div style={{ width: VIEWPORT_WIDTH[builder.viewport], maxWidth: '100%' }} className=\"flex\">\n <iframe\n ref={iframeRef}\n onLoad={wireUp}\n title=\"Page preview\"\n className=\"min-h-[480px] w-full rounded-lg border border-border bg-background shadow-md\"\n srcDoc=\"<!doctype html><html><head></head><body></body></html>\"\n />\n {doc\n ? createPortal(\n // Render the composition root directly (EC-287: no layout\n // indirection — a page renders its blocks).\n renderPageComposition(activeRoot, ctx),\n doc.body,\n )\n : null}\n {spacingTarget && doc ? (\n <SpacingHandles key={spacingTarget.id} doc={doc} node={spacingTarget} />\n ) : null}\n {/* Floating mark toolbar for the live rich-text session (EC-159). */}\n {richEditHost && doc ? <RichTextToolbar doc={doc} host={richEditHost} /> : null}\n </div>\n </div>\n )\n}\n"]}
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useMemo, useRef, useSyncExternalStore } from 'react';
3
3
  import { AlertTriangle, CircleCheck, Crosshair, X } from 'lucide-react';
4
4
  import { cloneWithNewIds } from '@elytracms/core/project-graph';
5
- import { buildFragmentFromGraph } from '@elytracms/core/clipboard';
5
+ import { buildFragmentFromComposition } from '@elytracms/core/clipboard';
6
6
  import { readFragmentFromClipboard, readFragmentFromDataTransfer, resolvePasteTarget, diffPastedSubtree, pasteSummaryMessage, writeFragmentToClipboard, writeFragmentToDataTransfer, } from '@elytracms/studio/lib/clipboard';
7
7
  import { getStudioRegistry } from '@elytracms/studio/lib/registry';
8
8
  import { useData } from '@elytracms/studio/lib/data';
@@ -67,7 +67,7 @@ export function useStudioClipboard() {
67
67
  return useMemo(() => {
68
68
  const fragmentFor = (nodeId) => {
69
69
  const { builder: b, projectId } = stateRef.current;
70
- const built = buildFragmentFromGraph(b.present, nodeId, { source: { projectId } });
70
+ const built = buildFragmentFromComposition(b.present, nodeId, { source: { projectId } });
71
71
  if (!built.ok) {
72
72
  publishClipboardNotice({ kind: 'error', message: built.error.message });
73
73
  return null;
@@ -89,7 +89,7 @@ export function useStudioClipboard() {
89
89
  };
90
90
  const currentRoot = () => {
91
91
  const { builder: b } = stateRef.current;
92
- return b.present.pages.find((p) => p.id === b.pageId)?.root;
92
+ return b.present;
93
93
  };
94
94
  const applyPaste = (result, anchorId) => {
95
95
  const { builder: b, data: d } = stateRef.current;