@particle-academy/fancy-cms-ui 0.1.1 → 0.2.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.
@@ -109,7 +109,7 @@ function useEditor(initialDoc) {
109
109
  [state, apply, undo, redo, select, replace]
110
110
  );
111
111
  }
112
- function Canvas({ doc, selection, onSelect, apply }) {
112
+ function Canvas({ doc, selection, onSelect, apply, registry, data }) {
113
113
  const ref = useRef(null);
114
114
  const [box, setBox] = useState(null);
115
115
  const drag = useRef(null);
@@ -166,7 +166,7 @@ function Canvas({ doc, selection, onSelect, apply }) {
166
166
  position: "relative",
167
167
  overflow: "auto",
168
168
  height: "100%",
169
- background: "#f8fafc"
169
+ background: "var(--fcms-canvas)"
170
170
  };
171
171
  const overlay = box ? {
172
172
  position: "absolute",
@@ -174,13 +174,13 @@ function Canvas({ doc, selection, onSelect, apply }) {
174
174
  top: box.y,
175
175
  width: box.w,
176
176
  height: box.h,
177
- outline: "2px solid #8b5cf6",
177
+ outline: "2px solid var(--fcms-accent, #8b5cf6)",
178
178
  outlineOffset: -1,
179
179
  cursor: "move",
180
180
  touchAction: "none"
181
181
  } : { display: "none" };
182
182
  return /* @__PURE__ */ jsxs("div", { ref, onClick: handleClick, style: surface, children: [
183
- /* @__PURE__ */ jsx(CmsPage, { doc }),
183
+ /* @__PURE__ */ jsx(CmsPage, { doc, registry, data }),
184
184
  /* @__PURE__ */ jsx(
185
185
  "div",
186
186
  {
@@ -251,10 +251,10 @@ function LayerRow({ doc, id, depth, selection, onSelect, onMove, overId, setOver
251
251
  cursor: draggable ? "grab" : "pointer",
252
252
  padding: "4px 8px",
253
253
  paddingLeft: 8 + depth * 14,
254
- background: selected ? "#ede9fe" : "transparent",
255
- color: selected ? "#5b21b6" : "#334155",
254
+ background: selected ? "var(--fcms-sel-bg)" : "transparent",
255
+ color: selected ? "var(--fcms-sel-fg)" : "var(--fcms-row-fg)",
256
256
  font: "inherit",
257
- boxShadow: overId === id ? "inset 0 -2px 0 0 #8b5cf6" : "none"
257
+ boxShadow: overId === id ? "inset 0 -2px 0 0 var(--fcms-accent, #8b5cf6)" : "none"
258
258
  },
259
259
  children: [
260
260
  /* @__PURE__ */ jsx("span", { style: { opacity: 0.6 }, children: node.type }),
@@ -271,7 +271,7 @@ var label = {
271
271
  fontSize: 11,
272
272
  textTransform: "uppercase",
273
273
  letterSpacing: "0.04em",
274
- color: "#94a3b8",
274
+ color: "var(--fcms-muted)",
275
275
  margin: "10px 0 4px"
276
276
  };
277
277
  var input = {
@@ -279,21 +279,23 @@ var input = {
279
279
  boxSizing: "border-box",
280
280
  padding: "6px 8px",
281
281
  borderRadius: 6,
282
- border: "1px solid #e2e8f0",
282
+ border: "1px solid var(--fcms-border)",
283
+ background: "var(--fcms-input-bg)",
284
+ color: "var(--fcms-fg)",
283
285
  font: "inherit",
284
286
  fontSize: 13
285
287
  };
286
288
  function Inspector({ doc, selection, apply }) {
287
289
  const node = selection ? doc.nodes[selection] : null;
288
290
  if (!node) {
289
- return /* @__PURE__ */ jsx("div", { style: { padding: 16, color: "#94a3b8", fontFamily: "system-ui, sans-serif", fontSize: 13 }, children: "Select an element to edit." });
291
+ return /* @__PURE__ */ jsx("div", { style: { padding: 16, color: "var(--fcms-muted)", fontFamily: "system-ui, sans-serif", fontSize: 13 }, children: "Select an element to edit." });
290
292
  }
291
293
  const s = node.style.base;
292
294
  const setStyle = (patch) => apply({ t: "set_style", id: node.id, breakpoint: "base", patch });
293
295
  const setProp = (key, value) => apply({ t: "set_props", id: node.id, patch: { [key]: value } });
294
296
  return /* @__PURE__ */ jsxs("div", { style: { overflow: "auto", padding: 16, fontFamily: "system-ui, sans-serif", height: "100%", boxSizing: "border-box" }, children: [
295
- /* @__PURE__ */ jsx("div", { style: { fontSize: 13, fontWeight: 600, color: "#0f172a" }, children: node.type }),
296
- /* @__PURE__ */ jsx("div", { style: { fontSize: 11, color: "#94a3b8", marginBottom: 8 }, children: node.id }),
297
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 13, fontWeight: 600, color: "var(--fcms-fg)" }, children: node.type }),
298
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 11, color: "var(--fcms-muted)", marginBottom: 8 }, children: node.id }),
297
299
  node.type === "text" ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
298
300
  /* @__PURE__ */ jsx("label", { style: label, children: "Content" }),
299
301
  /* @__PURE__ */ jsx(
@@ -378,7 +380,7 @@ function useLatestRef(value) {
378
380
  });
379
381
  return ref;
380
382
  }
381
- function Editor({ defaultValue, onChange }) {
383
+ function Editor({ defaultValue, onChange, registry, data }) {
382
384
  const ed = useEditor(defaultValue);
383
385
  const first = useRef(true);
384
386
  const onChangeRef = useLatestRef(onChange);
@@ -394,14 +396,15 @@ function Editor({ defaultValue, onChange }) {
394
396
  gridTemplateColumns: "220px 1fr 300px",
395
397
  height: "100%",
396
398
  minHeight: 0,
397
- background: "#fff",
398
- color: "#0f172a",
399
- border: "1px solid #e2e8f0",
399
+ background: "var(--fcms-bg)",
400
+ color: "var(--fcms-fg)",
401
+ border: "1px solid var(--fcms-border)",
400
402
  borderRadius: 12,
401
403
  overflow: "hidden"
402
404
  };
403
- return /* @__PURE__ */ jsxs("div", { style: shell, children: [
404
- /* @__PURE__ */ jsxs("div", { style: { borderRight: "1px solid #e2e8f0", display: "flex", flexDirection: "column", minHeight: 0 }, children: [
405
+ return /* @__PURE__ */ jsxs("div", { className: "fancy-cms-editor", style: shell, children: [
406
+ /* @__PURE__ */ jsx("style", { children: CHROME_CSS }),
407
+ /* @__PURE__ */ jsxs("div", { style: { borderRight: "1px solid var(--fcms-border)", display: "flex", flexDirection: "column", minHeight: 0 }, children: [
405
408
  /* @__PURE__ */ jsx(Toolbar, { ed }),
406
409
  /* @__PURE__ */ jsx(
407
410
  LayersPanel,
@@ -413,8 +416,8 @@ function Editor({ defaultValue, onChange }) {
413
416
  }
414
417
  )
415
418
  ] }),
416
- /* @__PURE__ */ jsx(Canvas, { doc: ed.state.doc, selection: ed.state.selection, onSelect: ed.select, apply: ed.apply }),
417
- /* @__PURE__ */ jsx("div", { style: { borderLeft: "1px solid #e2e8f0", minHeight: 0 }, children: /* @__PURE__ */ jsx(Inspector, { doc: ed.state.doc, selection: ed.state.selection, apply: ed.apply }) })
419
+ /* @__PURE__ */ jsx(Canvas, { doc: ed.state.doc, selection: ed.state.selection, onSelect: ed.select, apply: ed.apply, registry, data }),
420
+ /* @__PURE__ */ jsx("div", { style: { borderLeft: "1px solid var(--fcms-border)", minHeight: 0 }, children: /* @__PURE__ */ jsx(Inspector, { doc: ed.state.doc, selection: ed.state.selection, apply: ed.apply }) })
418
421
  ] });
419
422
  }
420
423
  function Toolbar({ ed }) {
@@ -423,8 +426,9 @@ function Toolbar({ ed }) {
423
426
  fontSize: 12,
424
427
  padding: "4px 10px",
425
428
  borderRadius: 6,
426
- border: "1px solid #e2e8f0",
427
- background: "#fff",
429
+ border: "1px solid var(--fcms-border)",
430
+ background: "var(--fcms-bg)",
431
+ color: "var(--fcms-fg)",
428
432
  cursor: "pointer"
429
433
  };
430
434
  return /* @__PURE__ */ jsxs(
@@ -434,7 +438,7 @@ function Toolbar({ ed }) {
434
438
  display: "flex",
435
439
  gap: 6,
436
440
  padding: 8,
437
- borderBottom: "1px solid #e2e8f0",
441
+ borderBottom: "1px solid var(--fcms-border)",
438
442
  fontFamily: "system-ui, sans-serif"
439
443
  },
440
444
  children: [
@@ -444,7 +448,10 @@ function Toolbar({ ed }) {
444
448
  }
445
449
  );
446
450
  }
451
+ var DARK_VARS = "color-scheme:dark;--fcms-bg:#0b0f19;--fcms-fg:#e5e7eb;--fcms-muted:#94a3b8;--fcms-border:#27272a;--fcms-canvas:#0f141f;--fcms-input-bg:#111827;--fcms-row-fg:#cbd5e1;--fcms-sel-bg:color-mix(in oklab, #8b5cf6 24%, transparent);--fcms-sel-fg:#ddd6fe;";
452
+ var LIGHT_VARS = "color-scheme:light;--fcms-bg:#ffffff;--fcms-fg:#0f172a;--fcms-muted:#64748b;--fcms-border:#e2e8f0;--fcms-canvas:#f8fafc;--fcms-input-bg:#ffffff;--fcms-row-fg:#334155;--fcms-sel-bg:#ede9fe;--fcms-sel-fg:#5b21b6;";
453
+ 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}}`;
447
454
 
448
455
  export { Canvas, Editor, Inspector, LayersPanel, editorReduce, initEditor, keyBetween, useEditor, useLatestRef };
449
- //# sourceMappingURL=chunk-524NYOHK.js.map
450
- //# sourceMappingURL=chunk-524NYOHK.js.map
456
+ //# sourceMappingURL=chunk-XQ3KHMBJ.js.map
457
+ //# sourceMappingURL=chunk-XQ3KHMBJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/document/fractional.ts","../src/editor/state.ts","../src/editor/useEditor.ts","../src/editor/Canvas.tsx","../src/editor/LayersPanel.tsx","../src/editor/Inspector.tsx","../src/editor/useLatestRef.ts","../src/editor/Editor.tsx"],"names":["useState","jsx","jsxs","Fragment","useRef","useEffect"],"mappings":"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","file":"chunk-XQ3KHMBJ.js","sourcesContent":["/**\n * Minimal collab-safe fractional ordering keys.\n *\n * Sibling `order` is a string over a base-62 alphabet interpreted as a fraction\n * in (0, 1). `keyBetween(a, b)` returns a key that sorts strictly between `a`\n * and `b` (lexicographically), extending precision when the bounds are\n * adjacent. Concurrent inserts at the same spot produce different keys (vary by\n * actor), so reorders never collide.\n *\n * This is intentionally compact for Phase 0. Before live collaboration ships it\n * should be swapped for a hardened implementation with jitter + bucket bounds.\n */\n\nconst BASE = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\nconst RADIX = BASE.length; // 62\nconst MID = Math.floor(RADIX / 2);\n\nfunction val(c: string): number {\n const i = BASE.indexOf(c);\n return i < 0 ? 0 : i;\n}\n\n/**\n * Return a key strictly between `a` and `b`. Pass `null` for an open bound\n * (`keyBetween(null, null)` for the first key, `keyBetween(last, null)` to\n * append, `keyBetween(null, first)` to prepend).\n */\nexport function keyBetween(a: string | null, b: string | null): string {\n if (a === null) a = \"\";\n if (b === null) {\n // Append: a key greater than `a`. Appending a mid digit always sorts after.\n return a + BASE[MID];\n }\n if (a >= b) {\n throw new Error(`keyBetween: lower bound \"${a}\" is not below upper bound \"${b}\"`);\n }\n\n let result = \"\";\n let i = 0;\n // Walk the common prefix, then split at the first differing digit.\n for (;;) {\n const ca = i < a.length ? val(a[i] as string) : 0;\n const cb = i < b.length ? val(b[i] as string) : RADIX;\n if (cb - ca > 1) {\n result += BASE[ca + Math.floor((cb - ca) / 2)];\n return result;\n }\n if (ca === cb) {\n result += BASE[ca];\n i++;\n continue;\n }\n // Adjacent digits (cb - ca === 1): take the lower path, then descend into\n // `a`'s remainder with RADIX as the upper bound until a gap opens.\n result += BASE[ca];\n i++;\n for (;;) {\n const da = i < a.length ? val(a[i] as string) : 0;\n if (RADIX - da > 1) {\n result += BASE[da + Math.floor((RADIX - da) / 2)];\n return result;\n }\n result += BASE[da];\n i++;\n }\n }\n}\n","/**\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 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\nexport function initEditor(doc: PageDoc): EditorState {\n return { 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 } from \"../document/reduce\";\nimport { keyBetween } from \"../document/fractional\";\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 {doc.sections.map((id) => (\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 type { CSSProperties, 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/** Contextual property editor for the selected node. Every change is one op. */\nexport function Inspector({ doc, selection, apply }: InspectorProps): ReactElement {\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_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}>Content</label>\n <textarea\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}>Source</label>\n <input\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}>Background</label>\n <input\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}>Text color</label>\n <input\n style={input}\n placeholder=\"#0f172a\"\n value={s.color ?? \"\"}\n onChange={(e) => setStyle({ color: e.target.value })}\n />\n\n <label style={label}>Font size (px)</label>\n <input\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}>Padding (px)</label>\n <input\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}>Opacity</label>\n <input\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 { 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, useRef, 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\";\n\nexport interface EditorProps {\n /** Initial document; edits are surfaced via {@link EditorProps.onChange}. */\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. Phase 1\n * cut — chrome is plain markup for now; it graduates to react-fancy next.\n */\nexport function Editor({ defaultValue, onChange, registry, data }: EditorProps): ReactElement {\n const ed = useEditor(defaultValue);\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 </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;\";\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;\";\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"]}
package/dist/editor.cjs CHANGED
@@ -456,7 +456,7 @@ function CmsPage({
456
456
  doc.sections.map((id) => /* @__PURE__ */ jsxRuntime.jsx(RenderNode, { doc, id, registry, data }, id))
457
457
  ] });
458
458
  }
459
- function Canvas({ doc, selection, onSelect, apply }) {
459
+ function Canvas({ doc, selection, onSelect, apply, registry, data }) {
460
460
  const ref = react.useRef(null);
461
461
  const [box, setBox] = react.useState(null);
462
462
  const drag = react.useRef(null);
@@ -513,7 +513,7 @@ function Canvas({ doc, selection, onSelect, apply }) {
513
513
  position: "relative",
514
514
  overflow: "auto",
515
515
  height: "100%",
516
- background: "#f8fafc"
516
+ background: "var(--fcms-canvas)"
517
517
  };
518
518
  const overlay = box ? {
519
519
  position: "absolute",
@@ -521,13 +521,13 @@ function Canvas({ doc, selection, onSelect, apply }) {
521
521
  top: box.y,
522
522
  width: box.w,
523
523
  height: box.h,
524
- outline: "2px solid #8b5cf6",
524
+ outline: "2px solid var(--fcms-accent, #8b5cf6)",
525
525
  outlineOffset: -1,
526
526
  cursor: "move",
527
527
  touchAction: "none"
528
528
  } : { display: "none" };
529
529
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, onClick: handleClick, style: surface, children: [
530
- /* @__PURE__ */ jsxRuntime.jsx(CmsPage, { doc }),
530
+ /* @__PURE__ */ jsxRuntime.jsx(CmsPage, { doc, registry, data }),
531
531
  /* @__PURE__ */ jsxRuntime.jsx(
532
532
  "div",
533
533
  {
@@ -642,10 +642,10 @@ function LayerRow({ doc, id, depth, selection, onSelect, onMove, overId, setOver
642
642
  cursor: draggable ? "grab" : "pointer",
643
643
  padding: "4px 8px",
644
644
  paddingLeft: 8 + depth * 14,
645
- background: selected ? "#ede9fe" : "transparent",
646
- color: selected ? "#5b21b6" : "#334155",
645
+ background: selected ? "var(--fcms-sel-bg)" : "transparent",
646
+ color: selected ? "var(--fcms-sel-fg)" : "var(--fcms-row-fg)",
647
647
  font: "inherit",
648
- boxShadow: overId === id ? "inset 0 -2px 0 0 #8b5cf6" : "none"
648
+ boxShadow: overId === id ? "inset 0 -2px 0 0 var(--fcms-accent, #8b5cf6)" : "none"
649
649
  },
650
650
  children: [
651
651
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { opacity: 0.6 }, children: node.type }),
@@ -662,7 +662,7 @@ var label = {
662
662
  fontSize: 11,
663
663
  textTransform: "uppercase",
664
664
  letterSpacing: "0.04em",
665
- color: "#94a3b8",
665
+ color: "var(--fcms-muted)",
666
666
  margin: "10px 0 4px"
667
667
  };
668
668
  var input = {
@@ -670,21 +670,23 @@ var input = {
670
670
  boxSizing: "border-box",
671
671
  padding: "6px 8px",
672
672
  borderRadius: 6,
673
- border: "1px solid #e2e8f0",
673
+ border: "1px solid var(--fcms-border)",
674
+ background: "var(--fcms-input-bg)",
675
+ color: "var(--fcms-fg)",
674
676
  font: "inherit",
675
677
  fontSize: 13
676
678
  };
677
679
  function Inspector({ doc, selection, apply }) {
678
680
  const node = selection ? doc.nodes[selection] : null;
679
681
  if (!node) {
680
- return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: 16, color: "#94a3b8", fontFamily: "system-ui, sans-serif", fontSize: 13 }, children: "Select an element to edit." });
682
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: 16, color: "var(--fcms-muted)", fontFamily: "system-ui, sans-serif", fontSize: 13 }, children: "Select an element to edit." });
681
683
  }
682
684
  const s = node.style.base;
683
685
  const setStyle = (patch) => apply({ t: "set_style", id: node.id, breakpoint: "base", patch });
684
686
  const setProp = (key, value) => apply({ t: "set_props", id: node.id, patch: { [key]: value } });
685
687
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { overflow: "auto", padding: 16, fontFamily: "system-ui, sans-serif", height: "100%", boxSizing: "border-box" }, children: [
686
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, fontWeight: 600, color: "#0f172a" }, children: node.type }),
687
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: "#94a3b8", marginBottom: 8 }, children: node.id }),
688
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, fontWeight: 600, color: "var(--fcms-fg)" }, children: node.type }),
689
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: "var(--fcms-muted)", marginBottom: 8 }, children: node.id }),
688
690
  node.type === "text" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
689
691
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: label, children: "Content" }),
690
692
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -762,7 +764,7 @@ function Inspector({ doc, selection, apply }) {
762
764
  )
763
765
  ] });
764
766
  }
765
- function Editor({ defaultValue, onChange }) {
767
+ function Editor({ defaultValue, onChange, registry, data }) {
766
768
  const ed = useEditor(defaultValue);
767
769
  const first = react.useRef(true);
768
770
  const onChangeRef = useLatestRef(onChange);
@@ -778,14 +780,15 @@ function Editor({ defaultValue, onChange }) {
778
780
  gridTemplateColumns: "220px 1fr 300px",
779
781
  height: "100%",
780
782
  minHeight: 0,
781
- background: "#fff",
782
- color: "#0f172a",
783
- border: "1px solid #e2e8f0",
783
+ background: "var(--fcms-bg)",
784
+ color: "var(--fcms-fg)",
785
+ border: "1px solid var(--fcms-border)",
784
786
  borderRadius: 12,
785
787
  overflow: "hidden"
786
788
  };
787
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: shell, children: [
788
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { borderRight: "1px solid #e2e8f0", display: "flex", flexDirection: "column", minHeight: 0 }, children: [
789
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fancy-cms-editor", style: shell, children: [
790
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: CHROME_CSS }),
791
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { borderRight: "1px solid var(--fcms-border)", display: "flex", flexDirection: "column", minHeight: 0 }, children: [
789
792
  /* @__PURE__ */ jsxRuntime.jsx(Toolbar, { ed }),
790
793
  /* @__PURE__ */ jsxRuntime.jsx(
791
794
  LayersPanel,
@@ -797,8 +800,8 @@ function Editor({ defaultValue, onChange }) {
797
800
  }
798
801
  )
799
802
  ] }),
800
- /* @__PURE__ */ jsxRuntime.jsx(Canvas, { doc: ed.state.doc, selection: ed.state.selection, onSelect: ed.select, apply: ed.apply }),
801
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { borderLeft: "1px solid #e2e8f0", minHeight: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(Inspector, { doc: ed.state.doc, selection: ed.state.selection, apply: ed.apply }) })
803
+ /* @__PURE__ */ jsxRuntime.jsx(Canvas, { doc: ed.state.doc, selection: ed.state.selection, onSelect: ed.select, apply: ed.apply, registry, data }),
804
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { borderLeft: "1px solid var(--fcms-border)", minHeight: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(Inspector, { doc: ed.state.doc, selection: ed.state.selection, apply: ed.apply }) })
802
805
  ] });
803
806
  }
804
807
  function Toolbar({ ed }) {
@@ -807,8 +810,9 @@ function Toolbar({ ed }) {
807
810
  fontSize: 12,
808
811
  padding: "4px 10px",
809
812
  borderRadius: 6,
810
- border: "1px solid #e2e8f0",
811
- background: "#fff",
813
+ border: "1px solid var(--fcms-border)",
814
+ background: "var(--fcms-bg)",
815
+ color: "var(--fcms-fg)",
812
816
  cursor: "pointer"
813
817
  };
814
818
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -818,7 +822,7 @@ function Toolbar({ ed }) {
818
822
  display: "flex",
819
823
  gap: 6,
820
824
  padding: 8,
821
- borderBottom: "1px solid #e2e8f0",
825
+ borderBottom: "1px solid var(--fcms-border)",
822
826
  fontFamily: "system-ui, sans-serif"
823
827
  },
824
828
  children: [
@@ -828,6 +832,9 @@ function Toolbar({ ed }) {
828
832
  }
829
833
  );
830
834
  }
835
+ var DARK_VARS = "color-scheme:dark;--fcms-bg:#0b0f19;--fcms-fg:#e5e7eb;--fcms-muted:#94a3b8;--fcms-border:#27272a;--fcms-canvas:#0f141f;--fcms-input-bg:#111827;--fcms-row-fg:#cbd5e1;--fcms-sel-bg:color-mix(in oklab, #8b5cf6 24%, transparent);--fcms-sel-fg:#ddd6fe;";
836
+ var LIGHT_VARS = "color-scheme:light;--fcms-bg:#ffffff;--fcms-fg:#0f172a;--fcms-muted:#64748b;--fcms-border:#e2e8f0;--fcms-canvas:#f8fafc;--fcms-input-bg:#ffffff;--fcms-row-fg:#334155;--fcms-sel-bg:#ede9fe;--fcms-sel-fg:#5b21b6;";
837
+ 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}}`;
831
838
  var CONTAINER_TYPES = /* @__PURE__ */ new Set(["section", "frame", "stack", "grid", "shape", "card", "device"]);
832
839
  function NodeInspector({
833
840
  node,