@particle-academy/fancy-cms-ui 0.8.0 → 0.9.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.
package/CHANGELOG.md CHANGED
@@ -14,6 +14,59 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
14
14
 
15
15
  ## [Unreleased]
16
16
 
17
+ ## [0.9.0] - 2026-10-23
18
+
19
+ Released together with `particle-academy/fancy-cms` 0.5.0, whose PHP renderer
20
+ emits the same markup and CSS: all five canonical documents are byte-identical
21
+ in both `parity/run.mjs` (CSS) and `parity/html.mjs` (HTML).
22
+
23
+ Found by rendering the lab's reference page server-side and capturing it at
24
+ phone and desktop widths: browser-default margins stacked on top of every
25
+ layout's `gap`, buttons were underlined links, and the JS and PHP renderers
26
+ produced different markup because the JS one used inline style objects.
27
+
28
+ ### Changed
29
+
30
+ - **BREAKING (markup + CSS): one fixed base stylesheet replaces inline styles.**
31
+ `emitDocCss` now emits `BASE_CSS` first: it resets the margins of headings,
32
+ paragraphs and lists, sets `box-sizing`, and styles buttons, callouts, code,
33
+ dividers and images. Every rule is wrapped in `:where()`, is never more
34
+ specific than a node's own `[data-cms="<id>"]` rule and comes before it, so
35
+ whatever a node sets wins. Elements carry data attributes instead:
36
+ - a `button` is ONE element, the `<a>` (or `<div>` without an href), with
37
+ `data-cms-button="primary|outline|ghost"`; there is no inner `<span>`;
38
+ - a `callout` is `data-cms-callout="info|success|warning|danger"` with its
39
+ text directly inside;
40
+ - an `image` keeps `<img>` and carries `data-cms-fit` when not `cover`;
41
+ - `divider` and `code` render bare `<hr>` and `<pre><code>`.
42
+ Buttons and callouts take `var(--cms-color-primary)` when the theme sets it.
43
+ **What to do:** nothing, unless your CSS targeted the old inner
44
+ `span[data-cms-button]` or your design relied on browser-default margins;
45
+ set the margin on the node instead. Unknown variants fall back to the
46
+ default rather than being written into the attribute.
47
+ - `emitDocCss` emits the base whenever a document has nodes or theme tokens,
48
+ even if no node sets a style; an empty document still emits nothing.
49
+
50
+ ### Fixed
51
+
52
+ - A node with no `props` or no `style` (a stored or legacy node) crashed both
53
+ the renderer and the emitter, taking the whole page with it. Both now read
54
+ nodes through `withNodeDefaults` (exported).
55
+ - A breakpoint named after an `Object.prototype` member (`constructor`, ...)
56
+ made the emitter print a function into a media query; breakpoint and
57
+ per-breakpoint lookups are now own-property only.
58
+ - An image with no `src` rendered `src=""`, which makes a browser request the
59
+ page again; the attribute is now omitted.
60
+
61
+ ### Added
62
+
63
+ - The parity runners call PHP without a shell (`FANCY_CMS_PHP` overrides the
64
+ binary), so a fixture's filename can never be read as shell text.
65
+ - `parity/html.mjs`: the markup half of the parity gate. It renders every
66
+ canonical document with `CmsPage` and with fancy-cms's PHP renderer and
67
+ requires byte-identical HTML. `canonical-page-ledgerline.json` is the lab's
68
+ premium reference page, so a real page is in the corpus.
69
+
17
70
  ## [0.8.0] - 2026-10-23
18
71
 
19
72
  What a professional landing page needs from the renderer, found by mapping
@@ -1,4 +1,4 @@
1
- import { migrateDoc, reduce, CmsPage, rootIds, childrenOf, lastRootId, emptyDoc } from './chunk-SJYKJ6SG.js';
1
+ import { migrateDoc, reduce, CmsPage, rootIds, childrenOf, lastRootId, emptyDoc } from './chunk-IRG5IKKO.js';
2
2
  import { useReducer, useCallback, useMemo, useRef, useState, useLayoutEffect, Fragment, useId, useEffect } from 'react';
3
3
  import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
4
4
  import { fractionalKey } from '@particle-academy/fancy-doc-commons';
@@ -576,5 +576,5 @@ var LIGHT_VARS = "color-scheme:light;--fcms-bg:#ffffff;--fcms-fg:#0f172a;--fcms-
576
576
  var CHROME_CSS = `.fancy-cms-editor{--fcms-accent:#8b5cf6;${LIGHT_VARS}}@media (prefers-color-scheme:dark){.fancy-cms-editor{${DARK_VARS}}}:where(.light,[data-theme="light"]) .fancy-cms-editor{${LIGHT_VARS}}:where(.dark,[data-theme="dark"]) .fancy-cms-editor{${DARK_VARS}}`;
577
577
 
578
578
  export { ADD_DEFAULTS, ADD_MENU, CONTAINER_TYPES, Canvas, Editor, Inspector, LayersPanel, buildInsertOp, editorReduce, initEditor, resolveInsertParent, useEditor, useLatestRef };
579
- //# sourceMappingURL=chunk-IOMIYI45.js.map
580
- //# sourceMappingURL=chunk-IOMIYI45.js.map
579
+ //# sourceMappingURL=chunk-BVMSHUQF.js.map
580
+ //# sourceMappingURL=chunk-BVMSHUQF.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/editor/state.ts","../src/editor/useEditor.ts","../src/editor/Canvas.tsx","../src/editor/LayersPanel.tsx","../src/editor/Inspector.tsx","../src/editor/insert.ts","../src/editor/useLatestRef.ts","../src/editor/Editor.tsx"],"names":["useState","jsx","keyBetween","jsxs","Fragment","useRef","useMemo","useEffect"],"mappings":"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","file":"chunk-IOMIYI45.js","sourcesContent":["/**\n * Editor state engine — pure and framework-agnostic so it's unit-testable.\n * `useEditor` wraps this with `useReducer`. Undo/redo uses document snapshots\n * (simple + robust); the op-level `invert` in the spine is for collab/op-stream\n * undo.\n */\nimport { migrateDoc, type LegacyPageDoc } from \"../document/migrate\";\nimport type { PageDoc } from \"../document/types\";\nimport type { PageOp } from \"../document/ops\";\nimport { reduce } from \"../document/reduce\";\n\nexport interface EditorState {\n doc: PageDoc;\n past: PageDoc[];\n future: PageDoc[];\n selection: string | null;\n}\n\nexport type EditorAction =\n | { type: \"apply\"; op: PageOp }\n | { type: \"undo\" }\n | { type: \"redo\" }\n | { type: \"select\"; id: string | null }\n | { type: \"replace\"; doc: PageDoc };\n\nconst HISTORY_LIMIT = 100;\n\n/**\n * Seed the editor from a document.\n *\n * Migrates a pre-`sections[]` document on the way in. Doing it here rather than\n * leaving it to the host is deliberate: the legacy failure is SILENT — a page\n * whose sections were ever reordered would simply open in the wrong order, with\n * nothing thrown and nothing logged — so a host that has not heard of the\n * migration is exactly the one that needs it. Already-migrated documents pass\n * through by reference.\n */\nexport function initEditor(doc: LegacyPageDoc | PageDoc): EditorState {\n return { doc: migrateDoc(doc), past: [], future: [], selection: null };\n}\n\nexport function editorReduce(state: EditorState, action: EditorAction): EditorState {\n switch (action.type) {\n case \"apply\": {\n const next = reduce(state.doc, action.op);\n if (next === state.doc) return state; // invalid op → no-op, no history entry\n return {\n ...state,\n doc: next,\n past: [...state.past, state.doc].slice(-HISTORY_LIMIT),\n future: [],\n };\n }\n case \"undo\": {\n if (state.past.length === 0) return state;\n const prev = state.past[state.past.length - 1]!;\n return {\n ...state,\n doc: prev,\n past: state.past.slice(0, -1),\n future: [state.doc, ...state.future],\n };\n }\n case \"redo\": {\n if (state.future.length === 0) return state;\n const next = state.future[0]!;\n return {\n ...state,\n doc: next,\n past: [...state.past, state.doc],\n future: state.future.slice(1),\n };\n }\n case \"select\":\n return state.selection === action.id ? state : { ...state, selection: action.id };\n case \"replace\":\n return state.doc === action.doc ? state : { ...state, doc: action.doc, future: [] };\n default:\n return state;\n }\n}\n","import { useCallback, useMemo, useReducer } from \"react\";\nimport type { PageDoc } from \"../document/types\";\nimport type { PageOp } from \"../document/ops\";\nimport { editorReduce, initEditor, type EditorState } from \"./state\";\n\nexport interface EditorApi {\n state: EditorState;\n /** Dispatch a mutation through the op-spine (records an undo snapshot). */\n apply: (op: PageOp) => void;\n undo: () => void;\n redo: () => void;\n select: (id: string | null) => void;\n /** Replace the document wholesale (e.g. a controlled `value` change). */\n replace: (doc: PageDoc) => void;\n canUndo: boolean;\n canRedo: boolean;\n}\n\nexport function useEditor(initialDoc: PageDoc): EditorApi {\n const [state, dispatch] = useReducer(editorReduce, initialDoc, initEditor);\n const apply = useCallback((op: PageOp) => dispatch({ type: \"apply\", op }), []);\n const undo = useCallback(() => dispatch({ type: \"undo\" }), []);\n const redo = useCallback(() => dispatch({ type: \"redo\" }), []);\n const select = useCallback((id: string | null) => dispatch({ type: \"select\", id }), []);\n const replace = useCallback((doc: PageDoc) => dispatch({ type: \"replace\", doc }), []);\n\n return useMemo(\n () => ({\n state,\n apply,\n undo,\n redo,\n select,\n replace,\n canUndo: state.past.length > 0,\n canRedo: state.future.length > 0,\n }),\n [state, apply, undo, redo, select, replace],\n );\n}\n","import {\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type MouseEvent as ReactMouseEvent,\n type PointerEvent as ReactPointerEvent,\n type ReactElement,\n} from \"react\";\nimport type { PageDoc } from \"../document/types\";\nimport type { PageOp } from \"../document/ops\";\nimport type { DataContext, ElementRegistry } from \"../react/registry\";\nimport { CmsPage } from \"../react/CmsPage\";\n\nexport interface CanvasProps {\n doc: PageDoc;\n selection: string | null;\n onSelect: (id: string | null) => void;\n apply: (op: PageOp) => void;\n /** Custom element registry so custom node types render on the canvas (not a blank placeholder). */\n registry?: ElementRegistry;\n /** Data context for `{ $bind }` props + repeaters previewed on the canvas. */\n data?: DataContext;\n}\n\ninterface Box {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/**\n * The edit surface: renders the live page and overlays a selection box. Click to\n * select; drag the box to move (px constraints). Phase 1 cut: free-parent\n * move + resize handles, stack/grid reordering, and snapping come next.\n */\nexport function Canvas({ doc, selection, onSelect, apply, registry, data }: CanvasProps): ReactElement {\n const ref = useRef<HTMLDivElement>(null);\n const [box, setBox] = useState<Box | null>(null);\n const drag = useRef<{ x: number; y: number; left: number; top: number } | null>(null);\n\n useLayoutEffect(() => {\n const root = ref.current;\n if (!root || !selection) {\n setBox(null);\n return;\n }\n const el = root.querySelector(`[data-cms=\"${cssEscape(selection)}\"]`);\n if (!el) {\n setBox(null);\n return;\n }\n const r = el.getBoundingClientRect();\n const rootRect = root.getBoundingClientRect();\n setBox({\n x: r.left - rootRect.left + root.scrollLeft,\n y: r.top - rootRect.top + root.scrollTop,\n w: r.width,\n h: r.height,\n });\n }, [selection, doc]);\n\n const handleClick = (e: ReactMouseEvent<HTMLDivElement>) => {\n const target = (e.target as HTMLElement).closest(\"[data-cms]\");\n onSelect(target ? target.getAttribute(\"data-cms\") : null);\n };\n\n const handlePointerDown = (e: ReactPointerEvent<HTMLDivElement>) => {\n if (!selection) return;\n const c = doc.nodes[selection]?.constraints?.base;\n const left = c && c.left && typeof c.left === \"object\" ? c.left.value : 0;\n const top = c && c.top && typeof c.top === \"object\" ? c.top.value : 0;\n drag.current = { x: e.clientX, y: e.clientY, left, top };\n e.currentTarget.setPointerCapture(e.pointerId);\n e.stopPropagation();\n };\n\n const handlePointerMove = (e: ReactPointerEvent<HTMLDivElement>) => {\n const d = drag.current;\n if (!d || !selection) return;\n apply({\n t: \"set_constraints\",\n id: selection,\n breakpoint: \"base\",\n patch: {\n left: { value: Math.round(d.left + (e.clientX - d.x)), unit: \"px\" },\n top: { value: Math.round(d.top + (e.clientY - d.y)), unit: \"px\" },\n },\n });\n };\n\n const handlePointerUp = () => {\n drag.current = null;\n };\n\n const surface: CSSProperties = {\n position: \"relative\",\n overflow: \"auto\",\n height: \"100%\",\n background: \"var(--fcms-canvas)\",\n };\n const overlay: CSSProperties = box\n ? {\n position: \"absolute\",\n left: box.x,\n top: box.y,\n width: box.w,\n height: box.h,\n outline: \"2px solid var(--fcms-accent, #8b5cf6)\",\n outlineOffset: -1,\n cursor: \"move\",\n touchAction: \"none\",\n }\n : { display: \"none\" };\n\n return (\n <div ref={ref} onClick={handleClick} style={surface}>\n <CmsPage doc={doc} registry={registry} data={data} />\n <div\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n style={overlay}\n />\n </div>\n );\n}\n\nfunction cssEscape(value: string): string {\n return value.replace(/[\"\\\\]/g, \"\\\\$&\");\n}\n","import { Fragment, useState, type DragEvent as ReactDragEvent, type ReactElement } from \"react\";\nimport type { NodeId, PageDoc } from \"../document/types\";\nimport { childrenOf, rootIds } from \"../document/reduce\";\nimport { fractionalKey as keyBetween } from \"@particle-academy/fancy-doc-commons\";\n\nexport interface LayersPanelProps {\n doc: PageDoc;\n selection: string | null;\n onSelect: (id: string) => void;\n /** Reparent/reorder a node (drag-to-reorder). Omit to disable dragging. */\n onMove?: (id: NodeId, parent: NodeId | null, order: string) => void;\n}\n\nconst MIME = \"application/x-cms-node\";\n\n/** True when `maybeAncestor` is `id` itself or one of its ancestors. */\nfunction isAncestorOrSelf(doc: PageDoc, id: string, maybeAncestor: string): boolean {\n for (let cur: string | null = id; cur; cur = doc.nodes[cur]?.parent ?? null) {\n if (cur === maybeAncestor) return true;\n }\n return false;\n}\n\n/** The section/layer tree. Click a row to select; drag a row onto another to reorder. */\nexport function LayersPanel({ doc, selection, onSelect, onMove }: LayersPanelProps): ReactElement {\n const [overId, setOverId] = useState<string | null>(null);\n\n return (\n <div style={{ overflow: \"auto\", padding: 8, fontSize: 13, fontFamily: \"system-ui, sans-serif\" }}>\n {rootIds(doc).map((id: string) => (\n <LayerRow key={id} doc={doc} id={id} depth={0} selection={selection} onSelect={onSelect} onMove={onMove} overId={overId} setOverId={setOverId} />\n ))}\n </div>\n );\n}\n\ninterface LayerRowProps {\n doc: PageDoc;\n id: string;\n depth: number;\n selection: string | null;\n onSelect: (id: string) => void;\n onMove?: (id: NodeId, parent: NodeId | null, order: string) => void;\n overId: string | null;\n setOverId: (id: string | null) => void;\n}\n\nfunction LayerRow({ doc, id, depth, selection, onSelect, onMove, overId, setOverId }: LayerRowProps): ReactElement | null {\n const node = doc.nodes[id];\n if (!node) return null;\n const selected = selection === id;\n const draggable = Boolean(onMove);\n\n const drop = (e: ReactDragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setOverId(null);\n if (!onMove) return;\n const dragId = e.dataTransfer.getData(MIME);\n // Reject no-op + any move that would drop a node into its own subtree.\n if (!dragId || dragId === id || isAncestorOrSelf(doc, id, dragId)) return;\n // Place the dragged node immediately after this row, among this row's siblings.\n const siblings = childrenOf(doc, node.parent);\n const idx = siblings.findIndex((n) => n.id === id);\n const next = siblings[idx + 1];\n onMove(dragId, node.parent, keyBetween(node.order, next ? next.order : null));\n };\n\n return (\n <Fragment>\n <button\n type=\"button\"\n draggable={draggable}\n onClick={() => onSelect(id)}\n onDragStart={(e) => {\n e.dataTransfer.setData(MIME, id);\n e.dataTransfer.effectAllowed = \"move\";\n }}\n onDragOver={(e) => {\n if (!onMove) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n if (overId !== id) setOverId(id);\n }}\n onDragLeave={() => overId === id && setOverId(null)}\n onDrop={drop}\n style={{\n display: \"block\",\n width: \"100%\",\n textAlign: \"left\",\n border: \"none\",\n borderRadius: 6,\n cursor: draggable ? \"grab\" : \"pointer\",\n padding: \"4px 8px\",\n paddingLeft: 8 + depth * 14,\n background: selected ? \"var(--fcms-sel-bg)\" : \"transparent\",\n color: selected ? \"var(--fcms-sel-fg)\" : \"var(--fcms-row-fg)\",\n font: \"inherit\",\n boxShadow: overId === id ? \"inset 0 -2px 0 0 var(--fcms-accent, #8b5cf6)\" : \"none\",\n }}\n >\n <span style={{ opacity: 0.6 }}>{node.type}</span> · {id}\n </button>\n {childrenOf(doc, id).map((child) => (\n <LayerRow key={child.id} doc={doc} id={child.id} depth={depth + 1} selection={selection} onSelect={onSelect} onMove={onMove} overId={overId} setOverId={setOverId} />\n ))}\n </Fragment>\n );\n}\n","import { useId, type CSSProperties, type ReactElement } from \"react\";\nimport type { PageDoc, StyleProps } from \"../document/types\";\nimport type { PageOp } from \"../document/ops\";\n\nexport interface InspectorProps {\n doc: PageDoc;\n selection: string | null;\n apply: (op: PageOp) => void;\n}\n\nconst label: CSSProperties = {\n display: \"block\",\n fontSize: 11,\n textTransform: \"uppercase\",\n letterSpacing: \"0.04em\",\n color: \"var(--fcms-muted)\",\n margin: \"10px 0 4px\",\n};\nconst input: CSSProperties = {\n width: \"100%\",\n boxSizing: \"border-box\",\n padding: \"6px 8px\",\n borderRadius: 6,\n border: \"1px solid var(--fcms-border)\",\n background: \"var(--fcms-input-bg)\",\n color: \"var(--fcms-fg)\",\n font: \"inherit\",\n fontSize: 13,\n};\n\n/**\n * Contextual property editor for the selected node. Every change is one op.\n *\n * Each `<label>` here is a SIBLING of its control rather than wrapping it, so\n * none of them were associated: clicking a label focused nothing and a screen\n * reader announced the panel as unlabelled boxes. (`NodeInspector` wraps its\n * controls, which associates them implicitly — these did not.)\n *\n * `htmlFor`/`id` fixes that, and `data-cms-field` gives each control the stable\n * handle the Human+ contract asks for so an agent addresses a field by name\n * instead of guessing at the DOM.\n */\nexport function Inspector({ doc, selection, apply }: InspectorProps): ReactElement {\n // Before the early return — every hook must run on every render. fancy-flow\n // shipped a blank-editor crash by getting this wrong in the same shape of\n // component.\n const uid = useId();\n const fieldId = (key: string) => `${uid}-${key}`;\n\n const node = selection ? doc.nodes[selection] : null;\n if (!node) {\n return (\n <div style={{ padding: 16, color: \"var(--fcms-muted)\", fontFamily: \"system-ui, sans-serif\", fontSize: 13 }}>\n Select an element to edit.\n </div>\n );\n }\n\n const s = node.style.base;\n const setStyle = (patch: Partial<StyleProps>) =>\n apply({ t: \"set_style\", id: node.id, breakpoint: \"base\", patch });\n const setProp = (key: string, value: unknown) =>\n apply({ t: \"set_node_props\", id: node.id, patch: { [key]: value } });\n\n return (\n <div style={{ overflow: \"auto\", padding: 16, fontFamily: \"system-ui, sans-serif\", height: \"100%\", boxSizing: \"border-box\" }}>\n <div style={{ fontSize: 13, fontWeight: 600, color: \"var(--fcms-fg)\" }}>{node.type}</div>\n <div style={{ fontSize: 11, color: \"var(--fcms-muted)\", marginBottom: 8 }}>{node.id}</div>\n\n {node.type === \"text\" ? (\n <>\n <label style={label} htmlFor={fieldId(\"content\")}>Content</label>\n <textarea\n id={fieldId(\"content\")}\n data-cms-field=\"content\"\n style={{ ...input, minHeight: 64, resize: \"vertical\" }}\n value={typeof node.props.content === \"string\" ? node.props.content : \"\"}\n onChange={(e) => setProp(\"content\", e.target.value)}\n />\n </>\n ) : null}\n\n {node.type === \"image\" ? (\n <>\n <label style={label} htmlFor={fieldId(\"src\")}>Source</label>\n <input\n id={fieldId(\"src\")}\n data-cms-field=\"src\"\n style={input}\n value={typeof node.props.src === \"string\" ? node.props.src : \"\"}\n onChange={(e) => setProp(\"src\", e.target.value)}\n />\n </>\n ) : null}\n\n <label style={label} htmlFor={fieldId(\"background\")}>Background</label>\n <input\n id={fieldId(\"background\")}\n data-cms-field=\"background\"\n style={input}\n placeholder=\"#ffffff | gradient | url(…)\"\n value={s.background ?? \"\"}\n onChange={(e) => setStyle({ background: e.target.value })}\n />\n\n <label style={label} htmlFor={fieldId(\"color\")}>Text color</label>\n <input\n id={fieldId(\"color\")}\n data-cms-field=\"color\"\n style={input}\n placeholder=\"#0f172a\"\n value={s.color ?? \"\"}\n onChange={(e) => setStyle({ color: e.target.value })}\n />\n\n <label style={label} htmlFor={fieldId(\"fontSize\")}>Font size (px)</label>\n <input\n id={fieldId(\"fontSize\")}\n data-cms-field=\"fontSize\"\n type=\"number\"\n style={input}\n value={s.fontSize?.value ?? \"\"}\n onChange={(e) => setStyle({ fontSize: { value: Number(e.target.value) || 0, unit: \"px\" } })}\n />\n\n <label style={label} htmlFor={fieldId(\"padding\")}>Padding (px)</label>\n <input\n id={fieldId(\"padding\")}\n data-cms-field=\"padding\"\n type=\"number\"\n style={input}\n value={s.padding?.value ?? \"\"}\n onChange={(e) => setStyle({ padding: { value: Number(e.target.value) || 0, unit: \"px\" } })}\n />\n\n <label style={label} htmlFor={fieldId(\"opacity\")}>Opacity</label>\n <input\n id={fieldId(\"opacity\")}\n data-cms-field=\"opacity\"\n type=\"number\"\n step=\"0.1\"\n min=\"0\"\n max=\"1\"\n style={input}\n value={s.opacity ?? \"\"}\n onChange={(e) => setStyle({ opacity: Number(e.target.value) })}\n />\n </div>\n );\n}\n","import type { Json, LayoutMode, NodeId, PageDoc, StyleProps } from \"../document/types\";\nimport type { PageOp } from \"../document/ops\";\nimport { childrenOf, lastRootId } from \"../document/reduce\";\nimport { fractionalKey as keyBetween } from \"@particle-academy/fancy-doc-commons\";\n\n/**\n * Element insertion — shared by `EditablePage` (inline editing) and `Editor`\n * (the standalone WYSIWYG shell).\n *\n * This used to live entirely inside EditablePage, which meant the embeddable\n * `Editor` had no way to add an element at all: starting from `emptyDoc()` gave\n * a blank canvas with nothing to select and no control to insert anything, so\n * a host embedding `Editor` could not author a page from scratch (#3).\n * EditablePage had the menu but no `onChange` to hand the document back —\n * each surface had half of what an embedding host needs.\n */\n\n/** Node types that accept children, so an insert lands *inside* them. */\nexport const CONTAINER_TYPES = new Set([\n \"section\",\n \"frame\",\n \"stack\",\n \"grid\",\n \"shape\",\n \"card\",\n \"device\",\n \"repeater\",\n]);\n\nexport type AddKind =\n | \"text\"\n | \"heading\"\n | \"button\"\n | \"link\"\n | \"image\"\n | \"box\"\n | \"stack\"\n | \"grid\"\n | \"card\"\n | \"callout\"\n | \"divider\"\n | \"code\"\n | \"richtext\"\n | \"repeater\"\n | \"list\";\n\nexport const ADD_DEFAULTS: Record<\n AddKind,\n { type: string; props: Record<string, Json>; style: StyleProps; layout?: LayoutMode }\n> = {\n text: { type: \"text\", props: { content: \"New text\" }, style: { color: \"inherit\" } },\n heading: { type: \"heading\", props: { content: \"New heading\" }, style: { fontSize: { value: 28, unit: \"px\" }, fontWeight: 700 } },\n button: { type: \"button\", props: { label: \"Button\", href: \"#\", variant: \"primary\" }, style: {} },\n link: { type: \"link\", props: { content: \"link text\", href: \"#\" }, style: { color: \"#7c3aed\" } },\n image: { type: \"image\", props: { src: \"\", alt: \"\" }, style: {} },\n box: { type: \"frame\", props: {}, style: { padding: { value: 16, unit: \"px\" } } },\n stack: { type: \"stack\", props: {}, style: { gap: { value: 12, unit: \"px\" } }, layout: \"stack\" },\n grid: { type: \"grid\", props: {}, style: { gap: { value: 12, unit: \"px\" } }, layout: \"grid\" },\n card: { type: \"card\", props: {}, style: { padding: { value: 16, unit: \"px\" }, radius: { value: 12, unit: \"px\" }, border: \"1px solid #e2e8f0\" } },\n callout: { type: \"callout\", props: { content: \"Heads up — this is a callout.\", variant: \"info\" }, style: {} },\n divider: { type: \"divider\", props: {}, style: {} },\n code: { type: \"code\", props: { content: \"npm install @particle-academy/react-fancy\", lang: \"bash\" }, style: {} },\n richtext: { type: \"richtext\", props: { html: \"<p>Rich <strong>text</strong> with <em>inline</em> formatting.</p>\" }, style: {} },\n repeater: { type: \"repeater\", props: { items: \"\" }, style: { gap: { value: 12, unit: \"px\" } }, layout: \"stack\" },\n list: { type: \"list\", props: { items: [\"First point\", \"Second point\"], ordered: false }, style: {} },\n};\n\nexport const ADD_MENU: Array<{ kind: AddKind; label: string }> = [\n { kind: \"heading\", label: \"Heading\" },\n { kind: \"text\", label: \"Text\" },\n { kind: \"button\", label: \"Button\" },\n { kind: \"link\", label: \"Link\" },\n { kind: \"image\", label: \"Image\" },\n { kind: \"card\", label: \"Card\" },\n { kind: \"callout\", label: \"Callout\" },\n { kind: \"stack\", label: \"Stack\" },\n { kind: \"grid\", label: \"Grid\" },\n { kind: \"box\", label: \"Box\" },\n { kind: \"divider\", label: \"Divider\" },\n { kind: \"code\", label: \"Code\" },\n { kind: \"richtext\", label: \"Rich text\" },\n { kind: \"list\", label: \"List\" },\n { kind: \"repeater\", label: \"Repeater\" },\n];\n\n/**\n * Where a new node of `kind` should land, given the current selection.\n *\n * Into the selected container; else alongside the selected node; else the last\n * section — and when the page has no sections at all, at the top level, which\n * is what makes authoring from `emptyDoc()` possible.\n */\nexport function resolveInsertParent(doc: PageDoc, selectedId: NodeId | null): NodeId | null {\n const selected = selectedId ? doc.nodes[selectedId] : null;\n if (selected) {\n return CONTAINER_TYPES.has(selected.type) ? selected.id : selected.parent;\n }\n return lastRootId(doc);\n}\n\n/**\n * Build the `insert_node` op for adding `kind` to `doc`.\n *\n * Pure — returns the op plus the new id so the caller can select it. Callers\n * apply the op through their own editor state.\n */\nexport function buildInsertOp(\n doc: PageDoc,\n kind: AddKind,\n selectedId: NodeId | null,\n /** Explicit target, overriding selection — used by drag-and-drop. */\n targetId?: NodeId | null,\n): { op: PageOp; id: NodeId } {\n const parent =\n targetId !== undefined\n ? targetId && doc.nodes[targetId]\n ? CONTAINER_TYPES.has(doc.nodes[targetId]!.type)\n ? targetId\n : doc.nodes[targetId]!.parent\n : null\n : resolveInsertParent(doc, selectedId);\n\n const siblings = childrenOf(doc, parent);\n const order = keyBetween(siblings.length ? siblings[siblings.length - 1]!.order : null, null);\n const id = `n${doc.seq + 1}-${Math.floor(performance.now())}`;\n const def = ADD_DEFAULTS[kind];\n\n return {\n id,\n op: {\n t: \"insert_node\",\n node: {\n id,\n type: def.type,\n parent,\n order,\n layout: def.layout,\n props: { ...def.props },\n style: { base: { ...def.style } },\n },\n } as PageOp,\n };\n}\n","import { useEffect, useRef, type RefObject } from \"react\";\n\n/**\n * Hold the latest `value` in a ref, synced in an effect after every render.\n *\n * Notify effects read `ref.current` instead of closing over a callback prop, so\n * their dependency arrays stay data-only (`doc`, `selection`, …). A consumer\n * passing an inline closure — new identity every render, the most natural\n * usage — can then never re-trigger the notify: without this, notify → consumer\n * setState → render → new closure identity → effect re-fires → notify → … loops\n * unbounded (#1). Standard uncontrolled-with-notify hygiene.\n */\nexport function useLatestRef<T>(value: T): RefObject<T> {\n const ref = useRef(value);\n useEffect(() => {\n ref.current = value;\n });\n return ref;\n}\n","import { useEffect, useMemo, useRef, useState, type CSSProperties, type ReactElement } from \"react\";\nimport type { PageDoc } from \"../document/types\";\nimport type { DataContext, ElementRegistry } from \"../react/registry\";\nimport { useEditor, type EditorApi } from \"./useEditor\";\nimport { useLatestRef } from \"./useLatestRef\";\nimport { Canvas } from \"./Canvas\";\nimport { LayersPanel } from \"./LayersPanel\";\nimport { Inspector } from \"./Inspector\";\nimport { ADD_MENU, buildInsertOp, type AddKind } from \"./insert\";\nimport { emptyDoc } from \"../document/types\";\n\nexport interface EditorProps {\n /**\n * Initial document; edits are surfaced via {@link EditorProps.onChange}.\n * Omit to start from an empty page.\n */\n defaultValue?: PageDoc;\n onChange?: (doc: PageDoc) => void;\n /**\n * Custom element registry — mirrors {@link CmsPageProps.registry} so the edit\n * canvas renders your own node types instead of a blank placeholder. Pass the\n * same registry you give `CmsPage` at runtime.\n */\n registry?: ElementRegistry;\n /** Data context that `{ $bind: \"…\" }` props + repeaters preview against on the canvas. */\n data?: DataContext;\n}\n\n/**\n * The fancy-cms editor: layers · canvas · inspector over the op-spine.\n *\n * The chrome is plain markup **deliberately**, and stays that way. It themes\n * through the `--fcms-*` layer defined at the bottom of this file — light by\n * default, dark under `prefers-color-scheme` or a `.dark` ancestor — and\n * react-fancy's primitives are hardcoded Tailwind palette classes that read no\n * custom properties, so swapping them in would ignore `--fcms-accent` and strand\n * a themed host with a half-themed editor.\n *\n * An earlier revision of this comment said the chrome \"graduates to react-fancy\n * next\". That predates the token layer by three weeks and is no longer the\n * plan; it is recorded here because it is the kind of note that gets acted on\n * long after it stopped being true.\n */\nexport function Editor({ defaultValue, onChange, registry, data }: EditorProps): ReactElement {\n // Render an empty page rather than throwing on a missing document. Reading\n // `.sections` off undefined crashed the entire editor, which is a hostile way\n // to tell a host \"you haven't passed a doc yet\" (#3).\n const initial = useMemo(() => defaultValue ?? emptyDoc(\"untitled\"), [defaultValue]);\n const ed = useEditor(initial);\n const first = useRef(true);\n\n // Notify depends ONLY on the doc — the latest onChange lives in a ref, so an\n // inline-closure consumer (whose handler identity changes every render) can't\n // re-trigger the notify and loop it (#1).\n const onChangeRef = useLatestRef(onChange);\n useEffect(() => {\n if (first.current) {\n first.current = false;\n return;\n }\n onChangeRef.current?.(ed.state.doc);\n }, [ed.state.doc, onChangeRef]);\n\n const shell: CSSProperties = {\n display: \"grid\",\n gridTemplateColumns: \"220px 1fr 300px\",\n height: \"100%\",\n minHeight: 0,\n background: \"var(--fcms-bg)\",\n color: \"var(--fcms-fg)\",\n border: \"1px solid var(--fcms-border)\",\n borderRadius: 12,\n overflow: \"hidden\",\n };\n\n return (\n <div className=\"fancy-cms-editor\" style={shell}>\n <style>{CHROME_CSS}</style>\n <div style={{ borderRight: \"1px solid var(--fcms-border)\", display: \"flex\", flexDirection: \"column\", minHeight: 0 }}>\n <Toolbar ed={ed} />\n <LayersPanel\n doc={ed.state.doc}\n selection={ed.state.selection}\n onSelect={ed.select}\n onMove={(id, parent, order) => ed.apply({ t: \"move_node\", id, parent, order })}\n />\n </div>\n <Canvas doc={ed.state.doc} selection={ed.state.selection} onSelect={ed.select} apply={ed.apply} registry={registry} data={data} />\n <div style={{ borderLeft: \"1px solid var(--fcms-border)\", minHeight: 0 }}>\n <Inspector doc={ed.state.doc} selection={ed.state.selection} apply={ed.apply} />\n </div>\n </div>\n );\n}\n\nfunction Toolbar({ ed }: { ed: EditorApi }): ReactElement {\n const btn: CSSProperties = {\n font: \"inherit\",\n fontSize: 12,\n padding: \"4px 10px\",\n borderRadius: 6,\n border: \"1px solid var(--fcms-border)\",\n background: \"var(--fcms-bg)\",\n color: \"var(--fcms-fg)\",\n cursor: \"pointer\",\n };\n return (\n <div\n style={{\n display: \"flex\",\n gap: 6,\n padding: 8,\n borderBottom: \"1px solid var(--fcms-border)\",\n fontFamily: \"system-ui, sans-serif\",\n }}\n >\n <button type=\"button\" style={{ ...btn, opacity: ed.canUndo ? 1 : 0.4 }} disabled={!ed.canUndo} onClick={ed.undo}>\n Undo\n </button>\n <button type=\"button\" style={{ ...btn, opacity: ed.canRedo ? 1 : 0.4 }} disabled={!ed.canRedo} onClick={ed.redo}>\n Redo\n </button>\n <AddElementMenu ed={ed} btn={btn} />\n </div>\n );\n}\n\n/**\n * Insert control for the standalone editor.\n *\n * Without this, `Editor` could not add an element at all: a host starting from\n * `emptyDoc()` got a blank canvas with nothing to select and no way to put\n * anything on it (#3). The palette itself was only ever wired into\n * `EditablePage`, which has no `onChange` to hand the document back — so\n * neither surface alone was embeddable.\n */\nfunction AddElementMenu({ ed, btn }: { ed: EditorApi; btn: CSSProperties }): ReactElement {\n const [open, setOpen] = useState(false);\n\n // Dismiss on any outside click or Escape.\n useEffect(() => {\n if (!open) return;\n const close = () => setOpen(false);\n const onKey = (e: KeyboardEvent) => e.key === \"Escape\" && setOpen(false);\n window.addEventListener(\"click\", close);\n window.addEventListener(\"keydown\", onKey);\n return () => {\n window.removeEventListener(\"click\", close);\n window.removeEventListener(\"keydown\", onKey);\n };\n }, [open]);\n\n const add = (kind: AddKind) => {\n const { op, id } = buildInsertOp(ed.state.doc, kind, ed.state.selection);\n ed.apply(op);\n ed.select(id);\n setOpen(false);\n };\n\n return (\n <div style={{ position: \"relative\", marginLeft: \"auto\" }} onClick={(e) => e.stopPropagation()}>\n <button\n type=\"button\"\n style={{ ...btn, borderColor: \"var(--fcms-accent, #7c3aed)\" }}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n data-cms-add-trigger=\"\"\n onClick={() => setOpen((v) => !v)}\n >\n + Add\n </button>\n {open && (\n <div\n role=\"menu\"\n data-cms-add-menu=\"\"\n style={{\n position: \"absolute\",\n top: \"calc(100% + 4px)\",\n left: 0,\n zIndex: 20,\n minWidth: 150,\n maxHeight: 280,\n overflowY: \"auto\",\n padding: 4,\n borderRadius: 8,\n border: \"1px solid var(--fcms-border)\",\n background: \"var(--fcms-bg)\",\n boxShadow: \"0 12px 32px rgba(0,0,0,.28)\",\n }}\n >\n {ADD_MENU.map((item) => (\n <button\n key={item.kind}\n type=\"button\"\n role=\"menuitem\"\n data-cms-add={item.kind}\n style={{\n ...btn,\n display: \"block\",\n width: \"100%\",\n textAlign: \"left\",\n border: 0,\n background: \"transparent\",\n }}\n onClick={() => add(item.kind)}\n >\n {item.label}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * Editor chrome tokens. Light by default; dark under `@media (prefers-color-scheme:\n * dark)` OR an ancestor `.dark` / `[data-theme=\"dark\"]` (Tailwind/class strategy),\n * with an explicit `.light` / `[data-theme=\"light\"]` ancestor forcing light back.\n * The panels below read `var(--fcms-*)`, so the whole editor embeds cleanly in a\n * dark app. `color-scheme` flips native inputs + scrollbars too.\n */\nconst DARK_VARS =\n \"color-scheme:dark;--fcms-bg:#0b0f19;--fcms-fg:#e5e7eb;--fcms-muted:#94a3b8;--fcms-border:#27272a;\" +\n \"--fcms-canvas:#0f141f;--fcms-input-bg:#111827;--fcms-row-fg:#cbd5e1;\" +\n \"--fcms-sel-bg:color-mix(in oklab, #8b5cf6 24%, transparent);--fcms-sel-fg:#ddd6fe;\" +\n \"--fcms-drop:#ec4899;--fcms-danger:#fca5a5;\";\nconst LIGHT_VARS =\n \"color-scheme:light;--fcms-bg:#ffffff;--fcms-fg:#0f172a;--fcms-muted:#64748b;--fcms-border:#e2e8f0;\" +\n \"--fcms-canvas:#f8fafc;--fcms-input-bg:#ffffff;--fcms-row-fg:#334155;--fcms-sel-bg:#ede9fe;--fcms-sel-fg:#5b21b6;\" +\n \"--fcms-drop:#db2777;--fcms-danger:#dc2626;\";\nconst CHROME_CSS =\n `.fancy-cms-editor{--fcms-accent:#8b5cf6;${LIGHT_VARS}}` +\n `@media (prefers-color-scheme:dark){.fancy-cms-editor{${DARK_VARS}}}` +\n `:where(.light,[data-theme=\"light\"]) .fancy-cms-editor{${LIGHT_VARS}}` +\n `:where(.dark,[data-theme=\"dark\"]) .fancy-cms-editor{${DARK_VARS}}`;\n"]}
1
+ {"version":3,"sources":["../src/editor/state.ts","../src/editor/useEditor.ts","../src/editor/Canvas.tsx","../src/editor/LayersPanel.tsx","../src/editor/Inspector.tsx","../src/editor/insert.ts","../src/editor/useLatestRef.ts","../src/editor/Editor.tsx"],"names":["useState","jsx","keyBetween","jsxs","Fragment","useRef","useMemo","useEffect"],"mappings":"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","file":"chunk-BVMSHUQF.js","sourcesContent":["/**\n * Editor state engine — pure and framework-agnostic so it's unit-testable.\n * `useEditor` wraps this with `useReducer`. Undo/redo uses document snapshots\n * (simple + robust); the op-level `invert` in the spine is for collab/op-stream\n * undo.\n */\nimport { migrateDoc, type LegacyPageDoc } from \"../document/migrate\";\nimport type { PageDoc } from \"../document/types\";\nimport type { PageOp } from \"../document/ops\";\nimport { reduce } from \"../document/reduce\";\n\nexport interface EditorState {\n doc: PageDoc;\n past: PageDoc[];\n future: PageDoc[];\n selection: string | null;\n}\n\nexport type EditorAction =\n | { type: \"apply\"; op: PageOp }\n | { type: \"undo\" }\n | { type: \"redo\" }\n | { type: \"select\"; id: string | null }\n | { type: \"replace\"; doc: PageDoc };\n\nconst HISTORY_LIMIT = 100;\n\n/**\n * Seed the editor from a document.\n *\n * Migrates a pre-`sections[]` document on the way in. Doing it here rather than\n * leaving it to the host is deliberate: the legacy failure is SILENT — a page\n * whose sections were ever reordered would simply open in the wrong order, with\n * nothing thrown and nothing logged — so a host that has not heard of the\n * migration is exactly the one that needs it. Already-migrated documents pass\n * through by reference.\n */\nexport function initEditor(doc: LegacyPageDoc | PageDoc): EditorState {\n return { doc: migrateDoc(doc), past: [], future: [], selection: null };\n}\n\nexport function editorReduce(state: EditorState, action: EditorAction): EditorState {\n switch (action.type) {\n case \"apply\": {\n const next = reduce(state.doc, action.op);\n if (next === state.doc) return state; // invalid op → no-op, no history entry\n return {\n ...state,\n doc: next,\n past: [...state.past, state.doc].slice(-HISTORY_LIMIT),\n future: [],\n };\n }\n case \"undo\": {\n if (state.past.length === 0) return state;\n const prev = state.past[state.past.length - 1]!;\n return {\n ...state,\n doc: prev,\n past: state.past.slice(0, -1),\n future: [state.doc, ...state.future],\n };\n }\n case \"redo\": {\n if (state.future.length === 0) return state;\n const next = state.future[0]!;\n return {\n ...state,\n doc: next,\n past: [...state.past, state.doc],\n future: state.future.slice(1),\n };\n }\n case \"select\":\n return state.selection === action.id ? state : { ...state, selection: action.id };\n case \"replace\":\n return state.doc === action.doc ? state : { ...state, doc: action.doc, future: [] };\n default:\n return state;\n }\n}\n","import { useCallback, useMemo, useReducer } from \"react\";\nimport type { PageDoc } from \"../document/types\";\nimport type { PageOp } from \"../document/ops\";\nimport { editorReduce, initEditor, type EditorState } from \"./state\";\n\nexport interface EditorApi {\n state: EditorState;\n /** Dispatch a mutation through the op-spine (records an undo snapshot). */\n apply: (op: PageOp) => void;\n undo: () => void;\n redo: () => void;\n select: (id: string | null) => void;\n /** Replace the document wholesale (e.g. a controlled `value` change). */\n replace: (doc: PageDoc) => void;\n canUndo: boolean;\n canRedo: boolean;\n}\n\nexport function useEditor(initialDoc: PageDoc): EditorApi {\n const [state, dispatch] = useReducer(editorReduce, initialDoc, initEditor);\n const apply = useCallback((op: PageOp) => dispatch({ type: \"apply\", op }), []);\n const undo = useCallback(() => dispatch({ type: \"undo\" }), []);\n const redo = useCallback(() => dispatch({ type: \"redo\" }), []);\n const select = useCallback((id: string | null) => dispatch({ type: \"select\", id }), []);\n const replace = useCallback((doc: PageDoc) => dispatch({ type: \"replace\", doc }), []);\n\n return useMemo(\n () => ({\n state,\n apply,\n undo,\n redo,\n select,\n replace,\n canUndo: state.past.length > 0,\n canRedo: state.future.length > 0,\n }),\n [state, apply, undo, redo, select, replace],\n );\n}\n","import {\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type MouseEvent as ReactMouseEvent,\n type PointerEvent as ReactPointerEvent,\n type ReactElement,\n} from \"react\";\nimport type { PageDoc } from \"../document/types\";\nimport type { PageOp } from \"../document/ops\";\nimport type { DataContext, ElementRegistry } from \"../react/registry\";\nimport { CmsPage } from \"../react/CmsPage\";\n\nexport interface CanvasProps {\n doc: PageDoc;\n selection: string | null;\n onSelect: (id: string | null) => void;\n apply: (op: PageOp) => void;\n /** Custom element registry so custom node types render on the canvas (not a blank placeholder). */\n registry?: ElementRegistry;\n /** Data context for `{ $bind }` props + repeaters previewed on the canvas. */\n data?: DataContext;\n}\n\ninterface Box {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/**\n * The edit surface: renders the live page and overlays a selection box. Click to\n * select; drag the box to move (px constraints). Phase 1 cut: free-parent\n * move + resize handles, stack/grid reordering, and snapping come next.\n */\nexport function Canvas({ doc, selection, onSelect, apply, registry, data }: CanvasProps): ReactElement {\n const ref = useRef<HTMLDivElement>(null);\n const [box, setBox] = useState<Box | null>(null);\n const drag = useRef<{ x: number; y: number; left: number; top: number } | null>(null);\n\n useLayoutEffect(() => {\n const root = ref.current;\n if (!root || !selection) {\n setBox(null);\n return;\n }\n const el = root.querySelector(`[data-cms=\"${cssEscape(selection)}\"]`);\n if (!el) {\n setBox(null);\n return;\n }\n const r = el.getBoundingClientRect();\n const rootRect = root.getBoundingClientRect();\n setBox({\n x: r.left - rootRect.left + root.scrollLeft,\n y: r.top - rootRect.top + root.scrollTop,\n w: r.width,\n h: r.height,\n });\n }, [selection, doc]);\n\n const handleClick = (e: ReactMouseEvent<HTMLDivElement>) => {\n const target = (e.target as HTMLElement).closest(\"[data-cms]\");\n onSelect(target ? target.getAttribute(\"data-cms\") : null);\n };\n\n const handlePointerDown = (e: ReactPointerEvent<HTMLDivElement>) => {\n if (!selection) return;\n const c = doc.nodes[selection]?.constraints?.base;\n const left = c && c.left && typeof c.left === \"object\" ? c.left.value : 0;\n const top = c && c.top && typeof c.top === \"object\" ? c.top.value : 0;\n drag.current = { x: e.clientX, y: e.clientY, left, top };\n e.currentTarget.setPointerCapture(e.pointerId);\n e.stopPropagation();\n };\n\n const handlePointerMove = (e: ReactPointerEvent<HTMLDivElement>) => {\n const d = drag.current;\n if (!d || !selection) return;\n apply({\n t: \"set_constraints\",\n id: selection,\n breakpoint: \"base\",\n patch: {\n left: { value: Math.round(d.left + (e.clientX - d.x)), unit: \"px\" },\n top: { value: Math.round(d.top + (e.clientY - d.y)), unit: \"px\" },\n },\n });\n };\n\n const handlePointerUp = () => {\n drag.current = null;\n };\n\n const surface: CSSProperties = {\n position: \"relative\",\n overflow: \"auto\",\n height: \"100%\",\n background: \"var(--fcms-canvas)\",\n };\n const overlay: CSSProperties = box\n ? {\n position: \"absolute\",\n left: box.x,\n top: box.y,\n width: box.w,\n height: box.h,\n outline: \"2px solid var(--fcms-accent, #8b5cf6)\",\n outlineOffset: -1,\n cursor: \"move\",\n touchAction: \"none\",\n }\n : { display: \"none\" };\n\n return (\n <div ref={ref} onClick={handleClick} style={surface}>\n <CmsPage doc={doc} registry={registry} data={data} />\n <div\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n style={overlay}\n />\n </div>\n );\n}\n\nfunction cssEscape(value: string): string {\n return value.replace(/[\"\\\\]/g, \"\\\\$&\");\n}\n","import { Fragment, useState, type DragEvent as ReactDragEvent, type ReactElement } from \"react\";\nimport type { NodeId, PageDoc } from \"../document/types\";\nimport { childrenOf, rootIds } from \"../document/reduce\";\nimport { fractionalKey as keyBetween } from \"@particle-academy/fancy-doc-commons\";\n\nexport interface LayersPanelProps {\n doc: PageDoc;\n selection: string | null;\n onSelect: (id: string) => void;\n /** Reparent/reorder a node (drag-to-reorder). Omit to disable dragging. */\n onMove?: (id: NodeId, parent: NodeId | null, order: string) => void;\n}\n\nconst MIME = \"application/x-cms-node\";\n\n/** True when `maybeAncestor` is `id` itself or one of its ancestors. */\nfunction isAncestorOrSelf(doc: PageDoc, id: string, maybeAncestor: string): boolean {\n for (let cur: string | null = id; cur; cur = doc.nodes[cur]?.parent ?? null) {\n if (cur === maybeAncestor) return true;\n }\n return false;\n}\n\n/** The section/layer tree. Click a row to select; drag a row onto another to reorder. */\nexport function LayersPanel({ doc, selection, onSelect, onMove }: LayersPanelProps): ReactElement {\n const [overId, setOverId] = useState<string | null>(null);\n\n return (\n <div style={{ overflow: \"auto\", padding: 8, fontSize: 13, fontFamily: \"system-ui, sans-serif\" }}>\n {rootIds(doc).map((id: string) => (\n <LayerRow key={id} doc={doc} id={id} depth={0} selection={selection} onSelect={onSelect} onMove={onMove} overId={overId} setOverId={setOverId} />\n ))}\n </div>\n );\n}\n\ninterface LayerRowProps {\n doc: PageDoc;\n id: string;\n depth: number;\n selection: string | null;\n onSelect: (id: string) => void;\n onMove?: (id: NodeId, parent: NodeId | null, order: string) => void;\n overId: string | null;\n setOverId: (id: string | null) => void;\n}\n\nfunction LayerRow({ doc, id, depth, selection, onSelect, onMove, overId, setOverId }: LayerRowProps): ReactElement | null {\n const node = doc.nodes[id];\n if (!node) return null;\n const selected = selection === id;\n const draggable = Boolean(onMove);\n\n const drop = (e: ReactDragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setOverId(null);\n if (!onMove) return;\n const dragId = e.dataTransfer.getData(MIME);\n // Reject no-op + any move that would drop a node into its own subtree.\n if (!dragId || dragId === id || isAncestorOrSelf(doc, id, dragId)) return;\n // Place the dragged node immediately after this row, among this row's siblings.\n const siblings = childrenOf(doc, node.parent);\n const idx = siblings.findIndex((n) => n.id === id);\n const next = siblings[idx + 1];\n onMove(dragId, node.parent, keyBetween(node.order, next ? next.order : null));\n };\n\n return (\n <Fragment>\n <button\n type=\"button\"\n draggable={draggable}\n onClick={() => onSelect(id)}\n onDragStart={(e) => {\n e.dataTransfer.setData(MIME, id);\n e.dataTransfer.effectAllowed = \"move\";\n }}\n onDragOver={(e) => {\n if (!onMove) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n if (overId !== id) setOverId(id);\n }}\n onDragLeave={() => overId === id && setOverId(null)}\n onDrop={drop}\n style={{\n display: \"block\",\n width: \"100%\",\n textAlign: \"left\",\n border: \"none\",\n borderRadius: 6,\n cursor: draggable ? \"grab\" : \"pointer\",\n padding: \"4px 8px\",\n paddingLeft: 8 + depth * 14,\n background: selected ? \"var(--fcms-sel-bg)\" : \"transparent\",\n color: selected ? \"var(--fcms-sel-fg)\" : \"var(--fcms-row-fg)\",\n font: \"inherit\",\n boxShadow: overId === id ? \"inset 0 -2px 0 0 var(--fcms-accent, #8b5cf6)\" : \"none\",\n }}\n >\n <span style={{ opacity: 0.6 }}>{node.type}</span> · {id}\n </button>\n {childrenOf(doc, id).map((child) => (\n <LayerRow key={child.id} doc={doc} id={child.id} depth={depth + 1} selection={selection} onSelect={onSelect} onMove={onMove} overId={overId} setOverId={setOverId} />\n ))}\n </Fragment>\n );\n}\n","import { useId, type CSSProperties, type ReactElement } from \"react\";\nimport type { PageDoc, StyleProps } from \"../document/types\";\nimport type { PageOp } from \"../document/ops\";\n\nexport interface InspectorProps {\n doc: PageDoc;\n selection: string | null;\n apply: (op: PageOp) => void;\n}\n\nconst label: CSSProperties = {\n display: \"block\",\n fontSize: 11,\n textTransform: \"uppercase\",\n letterSpacing: \"0.04em\",\n color: \"var(--fcms-muted)\",\n margin: \"10px 0 4px\",\n};\nconst input: CSSProperties = {\n width: \"100%\",\n boxSizing: \"border-box\",\n padding: \"6px 8px\",\n borderRadius: 6,\n border: \"1px solid var(--fcms-border)\",\n background: \"var(--fcms-input-bg)\",\n color: \"var(--fcms-fg)\",\n font: \"inherit\",\n fontSize: 13,\n};\n\n/**\n * Contextual property editor for the selected node. Every change is one op.\n *\n * Each `<label>` here is a SIBLING of its control rather than wrapping it, so\n * none of them were associated: clicking a label focused nothing and a screen\n * reader announced the panel as unlabelled boxes. (`NodeInspector` wraps its\n * controls, which associates them implicitly — these did not.)\n *\n * `htmlFor`/`id` fixes that, and `data-cms-field` gives each control the stable\n * handle the Human+ contract asks for so an agent addresses a field by name\n * instead of guessing at the DOM.\n */\nexport function Inspector({ doc, selection, apply }: InspectorProps): ReactElement {\n // Before the early return — every hook must run on every render. fancy-flow\n // shipped a blank-editor crash by getting this wrong in the same shape of\n // component.\n const uid = useId();\n const fieldId = (key: string) => `${uid}-${key}`;\n\n const node = selection ? doc.nodes[selection] : null;\n if (!node) {\n return (\n <div style={{ padding: 16, color: \"var(--fcms-muted)\", fontFamily: \"system-ui, sans-serif\", fontSize: 13 }}>\n Select an element to edit.\n </div>\n );\n }\n\n const s = node.style.base;\n const setStyle = (patch: Partial<StyleProps>) =>\n apply({ t: \"set_style\", id: node.id, breakpoint: \"base\", patch });\n const setProp = (key: string, value: unknown) =>\n apply({ t: \"set_node_props\", id: node.id, patch: { [key]: value } });\n\n return (\n <div style={{ overflow: \"auto\", padding: 16, fontFamily: \"system-ui, sans-serif\", height: \"100%\", boxSizing: \"border-box\" }}>\n <div style={{ fontSize: 13, fontWeight: 600, color: \"var(--fcms-fg)\" }}>{node.type}</div>\n <div style={{ fontSize: 11, color: \"var(--fcms-muted)\", marginBottom: 8 }}>{node.id}</div>\n\n {node.type === \"text\" ? (\n <>\n <label style={label} htmlFor={fieldId(\"content\")}>Content</label>\n <textarea\n id={fieldId(\"content\")}\n data-cms-field=\"content\"\n style={{ ...input, minHeight: 64, resize: \"vertical\" }}\n value={typeof node.props.content === \"string\" ? node.props.content : \"\"}\n onChange={(e) => setProp(\"content\", e.target.value)}\n />\n </>\n ) : null}\n\n {node.type === \"image\" ? (\n <>\n <label style={label} htmlFor={fieldId(\"src\")}>Source</label>\n <input\n id={fieldId(\"src\")}\n data-cms-field=\"src\"\n style={input}\n value={typeof node.props.src === \"string\" ? node.props.src : \"\"}\n onChange={(e) => setProp(\"src\", e.target.value)}\n />\n </>\n ) : null}\n\n <label style={label} htmlFor={fieldId(\"background\")}>Background</label>\n <input\n id={fieldId(\"background\")}\n data-cms-field=\"background\"\n style={input}\n placeholder=\"#ffffff | gradient | url(…)\"\n value={s.background ?? \"\"}\n onChange={(e) => setStyle({ background: e.target.value })}\n />\n\n <label style={label} htmlFor={fieldId(\"color\")}>Text color</label>\n <input\n id={fieldId(\"color\")}\n data-cms-field=\"color\"\n style={input}\n placeholder=\"#0f172a\"\n value={s.color ?? \"\"}\n onChange={(e) => setStyle({ color: e.target.value })}\n />\n\n <label style={label} htmlFor={fieldId(\"fontSize\")}>Font size (px)</label>\n <input\n id={fieldId(\"fontSize\")}\n data-cms-field=\"fontSize\"\n type=\"number\"\n style={input}\n value={s.fontSize?.value ?? \"\"}\n onChange={(e) => setStyle({ fontSize: { value: Number(e.target.value) || 0, unit: \"px\" } })}\n />\n\n <label style={label} htmlFor={fieldId(\"padding\")}>Padding (px)</label>\n <input\n id={fieldId(\"padding\")}\n data-cms-field=\"padding\"\n type=\"number\"\n style={input}\n value={s.padding?.value ?? \"\"}\n onChange={(e) => setStyle({ padding: { value: Number(e.target.value) || 0, unit: \"px\" } })}\n />\n\n <label style={label} htmlFor={fieldId(\"opacity\")}>Opacity</label>\n <input\n id={fieldId(\"opacity\")}\n data-cms-field=\"opacity\"\n type=\"number\"\n step=\"0.1\"\n min=\"0\"\n max=\"1\"\n style={input}\n value={s.opacity ?? \"\"}\n onChange={(e) => setStyle({ opacity: Number(e.target.value) })}\n />\n </div>\n );\n}\n","import type { Json, LayoutMode, NodeId, PageDoc, StyleProps } from \"../document/types\";\nimport type { PageOp } from \"../document/ops\";\nimport { childrenOf, lastRootId } from \"../document/reduce\";\nimport { fractionalKey as keyBetween } from \"@particle-academy/fancy-doc-commons\";\n\n/**\n * Element insertion — shared by `EditablePage` (inline editing) and `Editor`\n * (the standalone WYSIWYG shell).\n *\n * This used to live entirely inside EditablePage, which meant the embeddable\n * `Editor` had no way to add an element at all: starting from `emptyDoc()` gave\n * a blank canvas with nothing to select and no control to insert anything, so\n * a host embedding `Editor` could not author a page from scratch (#3).\n * EditablePage had the menu but no `onChange` to hand the document back —\n * each surface had half of what an embedding host needs.\n */\n\n/** Node types that accept children, so an insert lands *inside* them. */\nexport const CONTAINER_TYPES = new Set([\n \"section\",\n \"frame\",\n \"stack\",\n \"grid\",\n \"shape\",\n \"card\",\n \"device\",\n \"repeater\",\n]);\n\nexport type AddKind =\n | \"text\"\n | \"heading\"\n | \"button\"\n | \"link\"\n | \"image\"\n | \"box\"\n | \"stack\"\n | \"grid\"\n | \"card\"\n | \"callout\"\n | \"divider\"\n | \"code\"\n | \"richtext\"\n | \"repeater\"\n | \"list\";\n\nexport const ADD_DEFAULTS: Record<\n AddKind,\n { type: string; props: Record<string, Json>; style: StyleProps; layout?: LayoutMode }\n> = {\n text: { type: \"text\", props: { content: \"New text\" }, style: { color: \"inherit\" } },\n heading: { type: \"heading\", props: { content: \"New heading\" }, style: { fontSize: { value: 28, unit: \"px\" }, fontWeight: 700 } },\n button: { type: \"button\", props: { label: \"Button\", href: \"#\", variant: \"primary\" }, style: {} },\n link: { type: \"link\", props: { content: \"link text\", href: \"#\" }, style: { color: \"#7c3aed\" } },\n image: { type: \"image\", props: { src: \"\", alt: \"\" }, style: {} },\n box: { type: \"frame\", props: {}, style: { padding: { value: 16, unit: \"px\" } } },\n stack: { type: \"stack\", props: {}, style: { gap: { value: 12, unit: \"px\" } }, layout: \"stack\" },\n grid: { type: \"grid\", props: {}, style: { gap: { value: 12, unit: \"px\" } }, layout: \"grid\" },\n card: { type: \"card\", props: {}, style: { padding: { value: 16, unit: \"px\" }, radius: { value: 12, unit: \"px\" }, border: \"1px solid #e2e8f0\" } },\n callout: { type: \"callout\", props: { content: \"Heads up — this is a callout.\", variant: \"info\" }, style: {} },\n divider: { type: \"divider\", props: {}, style: {} },\n code: { type: \"code\", props: { content: \"npm install @particle-academy/react-fancy\", lang: \"bash\" }, style: {} },\n richtext: { type: \"richtext\", props: { html: \"<p>Rich <strong>text</strong> with <em>inline</em> formatting.</p>\" }, style: {} },\n repeater: { type: \"repeater\", props: { items: \"\" }, style: { gap: { value: 12, unit: \"px\" } }, layout: \"stack\" },\n list: { type: \"list\", props: { items: [\"First point\", \"Second point\"], ordered: false }, style: {} },\n};\n\nexport const ADD_MENU: Array<{ kind: AddKind; label: string }> = [\n { kind: \"heading\", label: \"Heading\" },\n { kind: \"text\", label: \"Text\" },\n { kind: \"button\", label: \"Button\" },\n { kind: \"link\", label: \"Link\" },\n { kind: \"image\", label: \"Image\" },\n { kind: \"card\", label: \"Card\" },\n { kind: \"callout\", label: \"Callout\" },\n { kind: \"stack\", label: \"Stack\" },\n { kind: \"grid\", label: \"Grid\" },\n { kind: \"box\", label: \"Box\" },\n { kind: \"divider\", label: \"Divider\" },\n { kind: \"code\", label: \"Code\" },\n { kind: \"richtext\", label: \"Rich text\" },\n { kind: \"list\", label: \"List\" },\n { kind: \"repeater\", label: \"Repeater\" },\n];\n\n/**\n * Where a new node of `kind` should land, given the current selection.\n *\n * Into the selected container; else alongside the selected node; else the last\n * section — and when the page has no sections at all, at the top level, which\n * is what makes authoring from `emptyDoc()` possible.\n */\nexport function resolveInsertParent(doc: PageDoc, selectedId: NodeId | null): NodeId | null {\n const selected = selectedId ? doc.nodes[selectedId] : null;\n if (selected) {\n return CONTAINER_TYPES.has(selected.type) ? selected.id : selected.parent;\n }\n return lastRootId(doc);\n}\n\n/**\n * Build the `insert_node` op for adding `kind` to `doc`.\n *\n * Pure — returns the op plus the new id so the caller can select it. Callers\n * apply the op through their own editor state.\n */\nexport function buildInsertOp(\n doc: PageDoc,\n kind: AddKind,\n selectedId: NodeId | null,\n /** Explicit target, overriding selection — used by drag-and-drop. */\n targetId?: NodeId | null,\n): { op: PageOp; id: NodeId } {\n const parent =\n targetId !== undefined\n ? targetId && doc.nodes[targetId]\n ? CONTAINER_TYPES.has(doc.nodes[targetId]!.type)\n ? targetId\n : doc.nodes[targetId]!.parent\n : null\n : resolveInsertParent(doc, selectedId);\n\n const siblings = childrenOf(doc, parent);\n const order = keyBetween(siblings.length ? siblings[siblings.length - 1]!.order : null, null);\n const id = `n${doc.seq + 1}-${Math.floor(performance.now())}`;\n const def = ADD_DEFAULTS[kind];\n\n return {\n id,\n op: {\n t: \"insert_node\",\n node: {\n id,\n type: def.type,\n parent,\n order,\n layout: def.layout,\n props: { ...def.props },\n style: { base: { ...def.style } },\n },\n } as PageOp,\n };\n}\n","import { useEffect, useRef, type RefObject } from \"react\";\n\n/**\n * Hold the latest `value` in a ref, synced in an effect after every render.\n *\n * Notify effects read `ref.current` instead of closing over a callback prop, so\n * their dependency arrays stay data-only (`doc`, `selection`, …). A consumer\n * passing an inline closure — new identity every render, the most natural\n * usage — can then never re-trigger the notify: without this, notify → consumer\n * setState → render → new closure identity → effect re-fires → notify → … loops\n * unbounded (#1). Standard uncontrolled-with-notify hygiene.\n */\nexport function useLatestRef<T>(value: T): RefObject<T> {\n const ref = useRef(value);\n useEffect(() => {\n ref.current = value;\n });\n return ref;\n}\n","import { useEffect, useMemo, useRef, useState, type CSSProperties, type ReactElement } from \"react\";\nimport type { PageDoc } from \"../document/types\";\nimport type { DataContext, ElementRegistry } from \"../react/registry\";\nimport { useEditor, type EditorApi } from \"./useEditor\";\nimport { useLatestRef } from \"./useLatestRef\";\nimport { Canvas } from \"./Canvas\";\nimport { LayersPanel } from \"./LayersPanel\";\nimport { Inspector } from \"./Inspector\";\nimport { ADD_MENU, buildInsertOp, type AddKind } from \"./insert\";\nimport { emptyDoc } from \"../document/types\";\n\nexport interface EditorProps {\n /**\n * Initial document; edits are surfaced via {@link EditorProps.onChange}.\n * Omit to start from an empty page.\n */\n defaultValue?: PageDoc;\n onChange?: (doc: PageDoc) => void;\n /**\n * Custom element registry — mirrors {@link CmsPageProps.registry} so the edit\n * canvas renders your own node types instead of a blank placeholder. Pass the\n * same registry you give `CmsPage` at runtime.\n */\n registry?: ElementRegistry;\n /** Data context that `{ $bind: \"…\" }` props + repeaters preview against on the canvas. */\n data?: DataContext;\n}\n\n/**\n * The fancy-cms editor: layers · canvas · inspector over the op-spine.\n *\n * The chrome is plain markup **deliberately**, and stays that way. It themes\n * through the `--fcms-*` layer defined at the bottom of this file — light by\n * default, dark under `prefers-color-scheme` or a `.dark` ancestor — and\n * react-fancy's primitives are hardcoded Tailwind palette classes that read no\n * custom properties, so swapping them in would ignore `--fcms-accent` and strand\n * a themed host with a half-themed editor.\n *\n * An earlier revision of this comment said the chrome \"graduates to react-fancy\n * next\". That predates the token layer by three weeks and is no longer the\n * plan; it is recorded here because it is the kind of note that gets acted on\n * long after it stopped being true.\n */\nexport function Editor({ defaultValue, onChange, registry, data }: EditorProps): ReactElement {\n // Render an empty page rather than throwing on a missing document. Reading\n // `.sections` off undefined crashed the entire editor, which is a hostile way\n // to tell a host \"you haven't passed a doc yet\" (#3).\n const initial = useMemo(() => defaultValue ?? emptyDoc(\"untitled\"), [defaultValue]);\n const ed = useEditor(initial);\n const first = useRef(true);\n\n // Notify depends ONLY on the doc — the latest onChange lives in a ref, so an\n // inline-closure consumer (whose handler identity changes every render) can't\n // re-trigger the notify and loop it (#1).\n const onChangeRef = useLatestRef(onChange);\n useEffect(() => {\n if (first.current) {\n first.current = false;\n return;\n }\n onChangeRef.current?.(ed.state.doc);\n }, [ed.state.doc, onChangeRef]);\n\n const shell: CSSProperties = {\n display: \"grid\",\n gridTemplateColumns: \"220px 1fr 300px\",\n height: \"100%\",\n minHeight: 0,\n background: \"var(--fcms-bg)\",\n color: \"var(--fcms-fg)\",\n border: \"1px solid var(--fcms-border)\",\n borderRadius: 12,\n overflow: \"hidden\",\n };\n\n return (\n <div className=\"fancy-cms-editor\" style={shell}>\n <style>{CHROME_CSS}</style>\n <div style={{ borderRight: \"1px solid var(--fcms-border)\", display: \"flex\", flexDirection: \"column\", minHeight: 0 }}>\n <Toolbar ed={ed} />\n <LayersPanel\n doc={ed.state.doc}\n selection={ed.state.selection}\n onSelect={ed.select}\n onMove={(id, parent, order) => ed.apply({ t: \"move_node\", id, parent, order })}\n />\n </div>\n <Canvas doc={ed.state.doc} selection={ed.state.selection} onSelect={ed.select} apply={ed.apply} registry={registry} data={data} />\n <div style={{ borderLeft: \"1px solid var(--fcms-border)\", minHeight: 0 }}>\n <Inspector doc={ed.state.doc} selection={ed.state.selection} apply={ed.apply} />\n </div>\n </div>\n );\n}\n\nfunction Toolbar({ ed }: { ed: EditorApi }): ReactElement {\n const btn: CSSProperties = {\n font: \"inherit\",\n fontSize: 12,\n padding: \"4px 10px\",\n borderRadius: 6,\n border: \"1px solid var(--fcms-border)\",\n background: \"var(--fcms-bg)\",\n color: \"var(--fcms-fg)\",\n cursor: \"pointer\",\n };\n return (\n <div\n style={{\n display: \"flex\",\n gap: 6,\n padding: 8,\n borderBottom: \"1px solid var(--fcms-border)\",\n fontFamily: \"system-ui, sans-serif\",\n }}\n >\n <button type=\"button\" style={{ ...btn, opacity: ed.canUndo ? 1 : 0.4 }} disabled={!ed.canUndo} onClick={ed.undo}>\n Undo\n </button>\n <button type=\"button\" style={{ ...btn, opacity: ed.canRedo ? 1 : 0.4 }} disabled={!ed.canRedo} onClick={ed.redo}>\n Redo\n </button>\n <AddElementMenu ed={ed} btn={btn} />\n </div>\n );\n}\n\n/**\n * Insert control for the standalone editor.\n *\n * Without this, `Editor` could not add an element at all: a host starting from\n * `emptyDoc()` got a blank canvas with nothing to select and no way to put\n * anything on it (#3). The palette itself was only ever wired into\n * `EditablePage`, which has no `onChange` to hand the document back — so\n * neither surface alone was embeddable.\n */\nfunction AddElementMenu({ ed, btn }: { ed: EditorApi; btn: CSSProperties }): ReactElement {\n const [open, setOpen] = useState(false);\n\n // Dismiss on any outside click or Escape.\n useEffect(() => {\n if (!open) return;\n const close = () => setOpen(false);\n const onKey = (e: KeyboardEvent) => e.key === \"Escape\" && setOpen(false);\n window.addEventListener(\"click\", close);\n window.addEventListener(\"keydown\", onKey);\n return () => {\n window.removeEventListener(\"click\", close);\n window.removeEventListener(\"keydown\", onKey);\n };\n }, [open]);\n\n const add = (kind: AddKind) => {\n const { op, id } = buildInsertOp(ed.state.doc, kind, ed.state.selection);\n ed.apply(op);\n ed.select(id);\n setOpen(false);\n };\n\n return (\n <div style={{ position: \"relative\", marginLeft: \"auto\" }} onClick={(e) => e.stopPropagation()}>\n <button\n type=\"button\"\n style={{ ...btn, borderColor: \"var(--fcms-accent, #7c3aed)\" }}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n data-cms-add-trigger=\"\"\n onClick={() => setOpen((v) => !v)}\n >\n + Add\n </button>\n {open && (\n <div\n role=\"menu\"\n data-cms-add-menu=\"\"\n style={{\n position: \"absolute\",\n top: \"calc(100% + 4px)\",\n left: 0,\n zIndex: 20,\n minWidth: 150,\n maxHeight: 280,\n overflowY: \"auto\",\n padding: 4,\n borderRadius: 8,\n border: \"1px solid var(--fcms-border)\",\n background: \"var(--fcms-bg)\",\n boxShadow: \"0 12px 32px rgba(0,0,0,.28)\",\n }}\n >\n {ADD_MENU.map((item) => (\n <button\n key={item.kind}\n type=\"button\"\n role=\"menuitem\"\n data-cms-add={item.kind}\n style={{\n ...btn,\n display: \"block\",\n width: \"100%\",\n textAlign: \"left\",\n border: 0,\n background: \"transparent\",\n }}\n onClick={() => add(item.kind)}\n >\n {item.label}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * Editor chrome tokens. Light by default; dark under `@media (prefers-color-scheme:\n * dark)` OR an ancestor `.dark` / `[data-theme=\"dark\"]` (Tailwind/class strategy),\n * with an explicit `.light` / `[data-theme=\"light\"]` ancestor forcing light back.\n * The panels below read `var(--fcms-*)`, so the whole editor embeds cleanly in a\n * dark app. `color-scheme` flips native inputs + scrollbars too.\n */\nconst DARK_VARS =\n \"color-scheme:dark;--fcms-bg:#0b0f19;--fcms-fg:#e5e7eb;--fcms-muted:#94a3b8;--fcms-border:#27272a;\" +\n \"--fcms-canvas:#0f141f;--fcms-input-bg:#111827;--fcms-row-fg:#cbd5e1;\" +\n \"--fcms-sel-bg:color-mix(in oklab, #8b5cf6 24%, transparent);--fcms-sel-fg:#ddd6fe;\" +\n \"--fcms-drop:#ec4899;--fcms-danger:#fca5a5;\";\nconst LIGHT_VARS =\n \"color-scheme:light;--fcms-bg:#ffffff;--fcms-fg:#0f172a;--fcms-muted:#64748b;--fcms-border:#e2e8f0;\" +\n \"--fcms-canvas:#f8fafc;--fcms-input-bg:#ffffff;--fcms-row-fg:#334155;--fcms-sel-bg:#ede9fe;--fcms-sel-fg:#5b21b6;\" +\n \"--fcms-drop:#db2777;--fcms-danger:#dc2626;\";\nconst CHROME_CSS =\n `.fancy-cms-editor{--fcms-accent:#8b5cf6;${LIGHT_VARS}}` +\n `@media (prefers-color-scheme:dark){.fancy-cms-editor{${DARK_VARS}}}` +\n `:where(.light,[data-theme=\"light\"]) .fancy-cms-editor{${LIGHT_VARS}}` +\n `:where(.dark,[data-theme=\"dark\"]) .fancy-cms-editor{${DARK_VARS}}`;\n"]}
@@ -11,6 +11,12 @@ function hasNodeMap(value) {
11
11
  const nodes = value.nodes;
12
12
  return typeof nodes === "object" && nodes !== null && !Array.isArray(nodes);
13
13
  }
14
+ function withNodeDefaults(node) {
15
+ const props = typeof node.props === "object" && node.props !== null ? node.props : {};
16
+ const style = typeof node.style === "object" && node.style !== null ? node.style : { base: {} };
17
+ const base = typeof style.base === "object" && style.base !== null ? style.base : {};
18
+ return props === node.props && style === node.style && base === style.base ? node : { ...node, props, style: { ...style, base } };
19
+ }
14
20
  var DEFAULT_BREAKPOINTS = {
15
21
  base: 0,
16
22
  md: 768,
@@ -297,6 +303,28 @@ function cssString(value) {
297
303
  return out;
298
304
  }
299
305
  var selectorFor = (id) => `[data-cms="${cssString(id)}"]`;
306
+ var BASE_CSS = [
307
+ "/* fancy-cms base */",
308
+ ":where([data-cms]) {\n box-sizing: border-box;\n}",
309
+ ":where(h1, h2, h3, h4, h5, h6, p, ul, ol)[data-cms] {\n margin: 0;\n}",
310
+ ":where(ul, ol)[data-cms] {\n padding-left: 1.25em;\n}",
311
+ ":where(a[data-cms]) {\n color: inherit;\n}",
312
+ ":where([data-cms] > img) {\n display: block;\n height: 100%;\n object-fit: cover;\n width: 100%;\n}",
313
+ ':where([data-cms] > img[data-cms-fit="contain"]) {\n object-fit: contain;\n}',
314
+ ':where([data-cms] > img[data-cms-fit="fill"]) {\n object-fit: fill;\n}',
315
+ ':where([data-cms] > img[data-cms-fit="none"]) {\n object-fit: none;\n}',
316
+ ':where([data-cms] > img[data-cms-fit="scale-down"]) {\n object-fit: scale-down;\n}',
317
+ ":where([data-cms-button]) {\n align-items: center;\n border: 1px solid var(--cms-color-primary, #7c3aed);\n border-radius: 8px;\n cursor: pointer;\n display: inline-flex;\n font-weight: 600;\n gap: 6px;\n justify-content: center;\n line-height: 1.2;\n padding: 10px 18px;\n text-decoration: none;\n}",
318
+ ':where([data-cms-button="primary"]) {\n background: var(--cms-color-primary, #7c3aed);\n color: #ffffff;\n}',
319
+ ':where([data-cms-button="outline"]) {\n background: transparent;\n color: var(--cms-color-primary, #7c3aed);\n}',
320
+ ':where([data-cms-button="ghost"]) {\n background: transparent;\n border-color: currentColor;\n color: inherit;\n}',
321
+ ":where([data-cms-callout]) {\n background: #3b82f614;\n border-left: 3px solid #3b82f6;\n border-radius: 10px;\n padding: 12px 14px;\n}",
322
+ ':where([data-cms-callout="success"]) {\n background: #10b98114;\n border-left-color: #10b981;\n}',
323
+ ':where([data-cms-callout="warning"]) {\n background: #f59e0b14;\n border-left-color: #f59e0b;\n}',
324
+ ':where([data-cms-callout="danger"]) {\n background: #ef444414;\n border-left-color: #ef4444;\n}',
325
+ ":where([data-cms] > hr) {\n border: none;\n border-top: 1px solid #e2e8f0;\n margin: 0;\n}",
326
+ ":where([data-cms] > pre) {\n background: #0b1220;\n border-radius: 10px;\n color: #e2e8f0;\n font-family: ui-monospace, monospace;\n font-size: 13px;\n margin: 0;\n overflow-x: auto;\n padding: 12px 14px;\n}"
327
+ ].join("\n\n");
300
328
  var UNITS = /* @__PURE__ */ new Set(["px", "%", "vw", "vh", "rem", "fr"]);
301
329
  function lengthToCss(len) {
302
330
  if (typeof len !== "object" || len === null) return null;
@@ -509,7 +537,7 @@ function emitDocCss(doc) {
509
537
  const themeRule = serializeRule(":root", themeDecls(doc.theme), "");
510
538
  if (themeRule) blocks.push(themeRule);
511
539
  for (const id of Object.keys(doc.nodes).sort()) {
512
- const node = doc.nodes[id];
540
+ const node = withNodeDefaults(doc.nodes[id]);
513
541
  const selector = selectorFor(id);
514
542
  const parentFree = isParentFree(doc, node);
515
543
  const base = {
@@ -522,12 +550,13 @@ function emitDocCss(doc) {
522
550
  if (baseRule) blocks.push(baseRule);
523
551
  for (const bp of doc.breakpoints) {
524
552
  if (bp === "base") continue;
525
- const px = breakpointPx[bp];
526
- if (px === void 0) continue;
527
- const bpStyle = node.style[bp];
553
+ const px = own(breakpointPx, bp);
554
+ if (typeof px !== "number") continue;
555
+ const bpStyle = own(node.style, bp);
556
+ const bpConstraints = node.constraints ? own(node.constraints, bp) : void 0;
528
557
  const decls = {
529
558
  ...bpStyle ? containerDecls(node, bpStyle, false) : {},
530
- ...node.constraints?.[bp] ? constraintDecls(node.constraints[bp], parentFree) : {},
559
+ ...bpConstraints ? constraintDecls(bpConstraints, parentFree) : {},
531
560
  ...bpStyle ? styleDecls(bpStyle) : {},
532
561
  ...bpStyle ? visibilityDecls(node, bpStyle, false) : {}
533
562
  };
@@ -537,7 +566,8 @@ ${inner}
537
566
  }`);
538
567
  }
539
568
  }
540
- return blocks.join("\n\n") + (blocks.length ? "\n" : "");
569
+ if (blocks.length === 0 && Object.keys(doc.nodes).length === 0) return "";
570
+ return [BASE_CSS, ...blocks].join("\n\n") + "\n";
541
571
  }
542
572
  function getPath(data, path) {
543
573
  return path.split(".").reduce((o, k) => o == null ? void 0 : o[k], data);
@@ -580,10 +610,17 @@ function elementFor(node, text) {
580
610
  case "button":
581
611
  case "link": {
582
612
  const href = safeHref(text(node.props.href));
583
- if (href === null) return { tag: node.type === "link" ? "span" : "div" };
584
- const attrs = { href };
585
- if (/^https?:\/\//i.test(href)) attrs.rel = "noopener noreferrer";
586
- return { tag: "a", attrs };
613
+ const attrs = {};
614
+ if (href !== null) {
615
+ attrs.href = href;
616
+ if (/^https?:\/\//i.test(href)) attrs.rel = "noopener noreferrer";
617
+ }
618
+ if (node.type === "button") attrs["data-cms-button"] = BUTTON_VARIANTS.has(text(node.props.variant)) ? text(node.props.variant) : "primary";
619
+ return { tag: href !== null ? "a" : node.type === "link" ? "span" : "div", attrs };
620
+ }
621
+ case "callout": {
622
+ const variant = text(node.props.variant);
623
+ return { tag: "div", attrs: { "data-cms-callout": CALLOUT_VARIANTS.has(variant) ? variant : "info" } };
587
624
  }
588
625
  default:
589
626
  return { tag: CONTAINERS.has(node.type) && LANDMARKS.has(as) ? as : "div" };
@@ -607,51 +644,32 @@ var defaultRegistry = {
607
644
  const items = resolve(node.props.items);
608
645
  return Array.isArray(items) ? items.map((item, i) => /* @__PURE__ */ jsx("li", { children: item === null || item === void 0 ? "" : String(item) }, i)) : null;
609
646
  },
610
- divider: () => /* @__PURE__ */ jsx("hr", { style: { border: "none", borderTop: "1px solid #e2e8f0", margin: 0 } }),
611
- callout: ({ node, text }) => {
612
- const tone = { info: "#3b82f6", success: "#10b981", warning: "#f59e0b", danger: "#ef4444" }[text(node.props.variant)] ?? "#3b82f6";
613
- return /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 10, padding: "12px 14px", borderRadius: 10, background: `${tone}14`, borderLeft: `3px solid ${tone}` }, children: /* @__PURE__ */ jsx("span", { style: { fontSize: 13 }, children: text(node.props.content) || "Callout" }) });
614
- },
615
- code: ({ node, text }) => /* @__PURE__ */ jsx("pre", { style: { margin: 0, padding: "12px 14px", borderRadius: 10, background: "#0b1220", color: "#e2e8f0", fontFamily: "ui-monospace, monospace", fontSize: 13, overflowX: "auto" }, children: /* @__PURE__ */ jsx("code", { children: text(node.props.content) }) }),
616
- button: ({ node, text }) => {
617
- const label = text(node.props.label) || text(node.props.content) || "Button";
618
- const variant = text(node.props.variant) || "primary";
619
- return /* @__PURE__ */ jsx("span", { "data-cms-button": variant, style: buttonStyle(variant), children: label });
620
- },
647
+ // Looks come from the base stylesheet (render/css.ts BASE_CSS), never from
648
+ // inline style objects, so the PHP renderer emits the same markup.
649
+ divider: () => /* @__PURE__ */ jsx("hr", {}),
650
+ callout: ({ node, text }) => text(node.props.content) || "Callout",
651
+ code: ({ node, text }) => /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: text(node.props.content) }) }),
652
+ button: ({ node, text }) => text(node.props.label) || text(node.props.content) || "Button",
621
653
  image: ({ node, text }) => {
622
654
  const fit = text(node.props.fit);
623
655
  return /* @__PURE__ */ jsx(
624
656
  "img",
625
657
  {
626
- src: text(node.props.src),
658
+ src: text(node.props.src) || void 0,
627
659
  alt: text(node.props.alt),
628
660
  loading: text(node.props.loading) === "eager" ? "eager" : "lazy",
629
- style: { width: "100%", height: "100%", objectFit: IMAGE_FITS.has(fit) ? fit : "cover", display: "block" }
661
+ "data-cms-fit": IMAGE_FITS.has(fit) && fit !== "cover" ? fit : void 0
630
662
  }
631
663
  );
632
664
  }
633
665
  };
634
666
  var IMAGE_FITS = /* @__PURE__ */ new Set(["cover", "contain", "fill", "none", "scale-down"]);
635
- function buttonStyle(variant) {
636
- const base = {
637
- display: "inline-flex",
638
- alignItems: "center",
639
- gap: 6,
640
- padding: "9px 16px",
641
- borderRadius: 8,
642
- fontWeight: 600,
643
- fontSize: 14,
644
- lineHeight: 1,
645
- cursor: "pointer",
646
- userSelect: "none"
647
- };
648
- if (variant === "ghost") return { ...base, background: "transparent", color: "inherit", border: "1px solid currentColor" };
649
- if (variant === "outline") return { ...base, background: "transparent", color: "#7c3aed", border: "1px solid #7c3aed" };
650
- return { ...base, background: "#7c3aed", color: "#fff", border: "1px solid #7c3aed" };
651
- }
667
+ var BUTTON_VARIANTS = /* @__PURE__ */ new Set(["primary", "outline", "ghost"]);
668
+ var CALLOUT_VARIANTS = /* @__PURE__ */ new Set(["info", "success", "warning", "danger"]);
652
669
  function RenderNode({ doc, id, registry = defaultRegistry, data }) {
653
- const node = own(doc.nodes, id);
654
- if (!node) return null;
670
+ const stored = own(doc.nodes, id);
671
+ if (!stored) return null;
672
+ const node = withNodeDefaults(stored);
655
673
  if (node.type === "repeater") {
656
674
  const arr = resolveValue(node.props.items, data);
657
675
  const items = Array.isArray(arr) ? arr : [];
@@ -693,6 +711,6 @@ function CmsPage({
693
711
  ] });
694
712
  }
695
713
 
696
- export { CmsPage, DEFAULT_BREAKPOINTS, RenderNode, childrenOf, defaultRegistry, descendantIds, emitDocCss, emptyDoc, getPath, hasNodeMap, invert, isBinding, lastRootId, migrateDoc, migrateDocVerbose, needsMigration, reduce, reduceAll, resolveValue, rootIds };
697
- //# sourceMappingURL=chunk-SJYKJ6SG.js.map
698
- //# sourceMappingURL=chunk-SJYKJ6SG.js.map
714
+ export { CmsPage, DEFAULT_BREAKPOINTS, RenderNode, childrenOf, defaultRegistry, descendantIds, emitDocCss, emptyDoc, getPath, hasNodeMap, invert, isBinding, lastRootId, migrateDoc, migrateDocVerbose, needsMigration, reduce, reduceAll, resolveValue, rootIds, withNodeDefaults };
715
+ //# sourceMappingURL=chunk-IRG5IKKO.js.map
716
+ //# sourceMappingURL=chunk-IRG5IKKO.js.map