@particle-academy/fancy-cms-ui 0.0.1-dev.9 → 0.1.1

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/dist/index.cjs CHANGED
@@ -1,5 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var react = require('react');
5
+
3
6
  // src/document/types.ts
4
7
  function isBinding(v) {
5
8
  return typeof v === "object" && v !== null && typeof v.$bind === "string";
@@ -401,16 +404,529 @@ ${inner}
401
404
  }
402
405
  return blocks.join("\n\n") + (blocks.length ? "\n" : "");
403
406
  }
407
+ function getPath(data, path) {
408
+ return path.split(".").reduce((o, k) => o == null ? void 0 : o[k], data);
409
+ }
410
+ function resolveValue(v, data) {
411
+ if (v === void 0 || v === null) return v;
412
+ if (isBinding(v)) return getPath(data, v.$bind);
413
+ return v;
414
+ }
415
+ var defaultRegistry = {
416
+ section: ({ children }) => children,
417
+ stack: ({ children }) => children,
418
+ grid: ({ children }) => children,
419
+ frame: ({ children }) => children,
420
+ shape: ({ children }) => children,
421
+ card: ({ children }) => children,
422
+ text: ({ node, text }) => text(node.props.content),
423
+ heading: ({ node, text }) => text(node.props.content) || "Heading",
424
+ // Rich text — inline-formatted HTML (gradient spans, links, <code>, …) that
425
+ // plain `text` can't express. The author owns the markup (it's their content).
426
+ richtext: ({ node, text }) => /* @__PURE__ */ jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: text(node.props.html) } }),
427
+ link: ({ node, text }) => /* @__PURE__ */ jsxRuntime.jsx("a", { href: text(node.props.href) || "#", style: { color: "inherit", textDecoration: "underline" }, children: text(node.props.content) || "link" }),
428
+ divider: () => /* @__PURE__ */ jsxRuntime.jsx("hr", { style: { border: "none", borderTop: "1px solid #e2e8f0", margin: 0 } }),
429
+ callout: ({ node, text }) => {
430
+ const tone = { info: "#3b82f6", success: "#10b981", warning: "#f59e0b", danger: "#ef4444" }[text(node.props.variant)] ?? "#3b82f6";
431
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", gap: 10, padding: "12px 14px", borderRadius: 10, background: `${tone}14`, borderLeft: `3px solid ${tone}` }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 13 }, children: text(node.props.content) || "Callout" }) });
432
+ },
433
+ code: ({ node, text }) => /* @__PURE__ */ jsxRuntime.jsx("pre", { style: { margin: 0, padding: "12px 14px", borderRadius: 10, background: "#0b1220", color: "#e2e8f0", fontFamily: "ui-monospace, monospace", fontSize: 13, overflowX: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: text(node.props.content) }) }),
434
+ button: ({ node, text }) => {
435
+ const label2 = text(node.props.label) || text(node.props.content) || "Button";
436
+ const variant = text(node.props.variant) || "primary";
437
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cms-button": variant, style: buttonStyle(variant), children: label2 });
438
+ },
439
+ image: ({ node, text }) => /* @__PURE__ */ jsxRuntime.jsx(
440
+ "img",
441
+ {
442
+ src: text(node.props.src),
443
+ alt: text(node.props.alt),
444
+ style: { width: "100%", height: "100%", objectFit: "cover", display: "block" }
445
+ }
446
+ )
447
+ };
448
+ function buttonStyle(variant) {
449
+ const base = {
450
+ display: "inline-flex",
451
+ alignItems: "center",
452
+ gap: 6,
453
+ padding: "9px 16px",
454
+ borderRadius: 8,
455
+ fontWeight: 600,
456
+ fontSize: 14,
457
+ lineHeight: 1,
458
+ cursor: "pointer",
459
+ userSelect: "none"
460
+ };
461
+ if (variant === "ghost") return { ...base, background: "transparent", color: "inherit", border: "1px solid currentColor" };
462
+ if (variant === "outline") return { ...base, background: "transparent", color: "#7c3aed", border: "1px solid #7c3aed" };
463
+ return { ...base, background: "#7c3aed", color: "#fff", border: "1px solid #7c3aed" };
464
+ }
465
+ function RenderNode({ doc, id, registry = defaultRegistry, data }) {
466
+ const node = doc.nodes[id];
467
+ if (!node) return null;
468
+ if (node.type === "repeater") {
469
+ const arr = resolveValue(node.props.items, data);
470
+ const items = Array.isArray(arr) ? arr : [];
471
+ const template = childrenOf(doc, id)[0];
472
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cms": node.id, className: node.className, children: template ? items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(RenderNode, { doc, id: template.id, registry, data: { ...data, item, index } }, index)) : null });
473
+ }
474
+ const kids = childrenOf(doc, id).map((child) => /* @__PURE__ */ jsxRuntime.jsx(RenderNode, { doc, id: child.id, registry, data }, child.id));
475
+ const resolve = (v) => resolveValue(v, data);
476
+ const text = (v) => {
477
+ const r = resolve(v);
478
+ return r === void 0 || r === null ? "" : String(r);
479
+ };
480
+ const renderer = registry[node.type];
481
+ const inner = renderer ? renderer({ node, doc, children: kids, data, resolve, text }) : node.island ? null : kids;
482
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cms": node.id, "data-cms-island": node.island ? node.type : void 0, className: node.className, children: inner });
483
+ }
484
+ function CmsPage({
485
+ doc,
486
+ registry = defaultRegistry,
487
+ data,
488
+ includeStyles = true
489
+ }) {
490
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
491
+ includeStyles ? /* @__PURE__ */ jsxRuntime.jsx("style", { "data-cms-styles": "", children: emitDocCss(doc) }) : null,
492
+ doc.sections.map((id) => /* @__PURE__ */ jsxRuntime.jsx(RenderNode, { doc, id, registry, data }, id))
493
+ ] });
494
+ }
495
+ function CmsRegion({
496
+ doc,
497
+ root,
498
+ registry = defaultRegistry,
499
+ includeStyles = true
500
+ }) {
501
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
502
+ includeStyles ? /* @__PURE__ */ jsxRuntime.jsx("style", { "data-cms-styles": "", children: emitDocCss(doc) }) : null,
503
+ /* @__PURE__ */ jsxRuntime.jsx(RenderNode, { doc, id: root, registry })
504
+ ] });
505
+ }
506
+ function initEditor(doc) {
507
+ return { doc, past: [], future: [], selection: null };
508
+ }
509
+ function editorReduce(state, action) {
510
+ switch (action.type) {
511
+ case "apply": {
512
+ const next = reduce(state.doc, action.op);
513
+ if (next === state.doc) return state;
514
+ return {
515
+ ...state,
516
+ doc: next,
517
+ past: [...state.past, state.doc].slice(-100),
518
+ future: []
519
+ };
520
+ }
521
+ case "undo": {
522
+ if (state.past.length === 0) return state;
523
+ const prev = state.past[state.past.length - 1];
524
+ return {
525
+ ...state,
526
+ doc: prev,
527
+ past: state.past.slice(0, -1),
528
+ future: [state.doc, ...state.future]
529
+ };
530
+ }
531
+ case "redo": {
532
+ if (state.future.length === 0) return state;
533
+ const next = state.future[0];
534
+ return {
535
+ ...state,
536
+ doc: next,
537
+ past: [...state.past, state.doc],
538
+ future: state.future.slice(1)
539
+ };
540
+ }
541
+ case "select":
542
+ return state.selection === action.id ? state : { ...state, selection: action.id };
543
+ case "replace":
544
+ return state.doc === action.doc ? state : { ...state, doc: action.doc, future: [] };
545
+ default:
546
+ return state;
547
+ }
548
+ }
549
+
550
+ // src/editor/useEditor.ts
551
+ function useEditor(initialDoc) {
552
+ const [state, dispatch] = react.useReducer(editorReduce, initialDoc, initEditor);
553
+ const apply = react.useCallback((op) => dispatch({ type: "apply", op }), []);
554
+ const undo = react.useCallback(() => dispatch({ type: "undo" }), []);
555
+ const redo = react.useCallback(() => dispatch({ type: "redo" }), []);
556
+ const select = react.useCallback((id) => dispatch({ type: "select", id }), []);
557
+ const replace = react.useCallback((doc) => dispatch({ type: "replace", doc }), []);
558
+ return react.useMemo(
559
+ () => ({
560
+ state,
561
+ apply,
562
+ undo,
563
+ redo,
564
+ select,
565
+ replace,
566
+ canUndo: state.past.length > 0,
567
+ canRedo: state.future.length > 0
568
+ }),
569
+ [state, apply, undo, redo, select, replace]
570
+ );
571
+ }
572
+ function useLatestRef(value) {
573
+ const ref = react.useRef(value);
574
+ react.useEffect(() => {
575
+ ref.current = value;
576
+ });
577
+ return ref;
578
+ }
579
+ function Canvas({ doc, selection, onSelect, apply }) {
580
+ const ref = react.useRef(null);
581
+ const [box, setBox] = react.useState(null);
582
+ const drag = react.useRef(null);
583
+ react.useLayoutEffect(() => {
584
+ const root = ref.current;
585
+ if (!root || !selection) {
586
+ setBox(null);
587
+ return;
588
+ }
589
+ const el = root.querySelector(`[data-cms="${cssEscape(selection)}"]`);
590
+ if (!el) {
591
+ setBox(null);
592
+ return;
593
+ }
594
+ const r = el.getBoundingClientRect();
595
+ const rootRect = root.getBoundingClientRect();
596
+ setBox({
597
+ x: r.left - rootRect.left + root.scrollLeft,
598
+ y: r.top - rootRect.top + root.scrollTop,
599
+ w: r.width,
600
+ h: r.height
601
+ });
602
+ }, [selection, doc]);
603
+ const handleClick = (e) => {
604
+ const target = e.target.closest("[data-cms]");
605
+ onSelect(target ? target.getAttribute("data-cms") : null);
606
+ };
607
+ const handlePointerDown = (e) => {
608
+ if (!selection) return;
609
+ const c = doc.nodes[selection]?.constraints?.base;
610
+ const left = c && c.left && typeof c.left === "object" ? c.left.value : 0;
611
+ const top = c && c.top && typeof c.top === "object" ? c.top.value : 0;
612
+ drag.current = { x: e.clientX, y: e.clientY, left, top };
613
+ e.currentTarget.setPointerCapture(e.pointerId);
614
+ e.stopPropagation();
615
+ };
616
+ const handlePointerMove = (e) => {
617
+ const d = drag.current;
618
+ if (!d || !selection) return;
619
+ apply({
620
+ t: "set_constraints",
621
+ id: selection,
622
+ breakpoint: "base",
623
+ patch: {
624
+ left: { value: Math.round(d.left + (e.clientX - d.x)), unit: "px" },
625
+ top: { value: Math.round(d.top + (e.clientY - d.y)), unit: "px" }
626
+ }
627
+ });
628
+ };
629
+ const handlePointerUp = () => {
630
+ drag.current = null;
631
+ };
632
+ const surface = {
633
+ position: "relative",
634
+ overflow: "auto",
635
+ height: "100%",
636
+ background: "#f8fafc"
637
+ };
638
+ const overlay = box ? {
639
+ position: "absolute",
640
+ left: box.x,
641
+ top: box.y,
642
+ width: box.w,
643
+ height: box.h,
644
+ outline: "2px solid #8b5cf6",
645
+ outlineOffset: -1,
646
+ cursor: "move",
647
+ touchAction: "none"
648
+ } : { display: "none" };
649
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, onClick: handleClick, style: surface, children: [
650
+ /* @__PURE__ */ jsxRuntime.jsx(CmsPage, { doc }),
651
+ /* @__PURE__ */ jsxRuntime.jsx(
652
+ "div",
653
+ {
654
+ onPointerDown: handlePointerDown,
655
+ onPointerMove: handlePointerMove,
656
+ onPointerUp: handlePointerUp,
657
+ style: overlay
658
+ }
659
+ )
660
+ ] });
661
+ }
662
+ function cssEscape(value) {
663
+ return value.replace(/["\\]/g, "\\$&");
664
+ }
665
+ var MIME = "application/x-cms-node";
666
+ function isAncestorOrSelf(doc, id, maybeAncestor) {
667
+ for (let cur = id; cur; cur = doc.nodes[cur]?.parent ?? null) {
668
+ if (cur === maybeAncestor) return true;
669
+ }
670
+ return false;
671
+ }
672
+ function LayersPanel({ doc, selection, onSelect, onMove }) {
673
+ const [overId, setOverId] = react.useState(null);
674
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { overflow: "auto", padding: 8, fontSize: 13, fontFamily: "system-ui, sans-serif" }, children: doc.sections.map((id) => /* @__PURE__ */ jsxRuntime.jsx(LayerRow, { doc, id, depth: 0, selection, onSelect, onMove, overId, setOverId }, id)) });
675
+ }
676
+ function LayerRow({ doc, id, depth, selection, onSelect, onMove, overId, setOverId }) {
677
+ const node = doc.nodes[id];
678
+ if (!node) return null;
679
+ const selected = selection === id;
680
+ const draggable = Boolean(onMove);
681
+ const drop = (e) => {
682
+ e.preventDefault();
683
+ e.stopPropagation();
684
+ setOverId(null);
685
+ if (!onMove) return;
686
+ const dragId = e.dataTransfer.getData(MIME);
687
+ if (!dragId || dragId === id || isAncestorOrSelf(doc, id, dragId)) return;
688
+ const siblings = childrenOf(doc, node.parent);
689
+ const idx = siblings.findIndex((n) => n.id === id);
690
+ const next = siblings[idx + 1];
691
+ onMove(dragId, node.parent, keyBetween(node.order, next ? next.order : null));
692
+ };
693
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
694
+ /* @__PURE__ */ jsxRuntime.jsxs(
695
+ "button",
696
+ {
697
+ type: "button",
698
+ draggable,
699
+ onClick: () => onSelect(id),
700
+ onDragStart: (e) => {
701
+ e.dataTransfer.setData(MIME, id);
702
+ e.dataTransfer.effectAllowed = "move";
703
+ },
704
+ onDragOver: (e) => {
705
+ if (!onMove) return;
706
+ e.preventDefault();
707
+ e.dataTransfer.dropEffect = "move";
708
+ if (overId !== id) setOverId(id);
709
+ },
710
+ onDragLeave: () => overId === id && setOverId(null),
711
+ onDrop: drop,
712
+ style: {
713
+ display: "block",
714
+ width: "100%",
715
+ textAlign: "left",
716
+ border: "none",
717
+ borderRadius: 6,
718
+ cursor: draggable ? "grab" : "pointer",
719
+ padding: "4px 8px",
720
+ paddingLeft: 8 + depth * 14,
721
+ background: selected ? "#ede9fe" : "transparent",
722
+ color: selected ? "#5b21b6" : "#334155",
723
+ font: "inherit",
724
+ boxShadow: overId === id ? "inset 0 -2px 0 0 #8b5cf6" : "none"
725
+ },
726
+ children: [
727
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { opacity: 0.6 }, children: node.type }),
728
+ " \xB7 ",
729
+ id
730
+ ]
731
+ }
732
+ ),
733
+ childrenOf(doc, id).map((child) => /* @__PURE__ */ jsxRuntime.jsx(LayerRow, { doc, id: child.id, depth: depth + 1, selection, onSelect, onMove, overId, setOverId }, child.id))
734
+ ] });
735
+ }
736
+ var label = {
737
+ display: "block",
738
+ fontSize: 11,
739
+ textTransform: "uppercase",
740
+ letterSpacing: "0.04em",
741
+ color: "#94a3b8",
742
+ margin: "10px 0 4px"
743
+ };
744
+ var input = {
745
+ width: "100%",
746
+ boxSizing: "border-box",
747
+ padding: "6px 8px",
748
+ borderRadius: 6,
749
+ border: "1px solid #e2e8f0",
750
+ font: "inherit",
751
+ fontSize: 13
752
+ };
753
+ function Inspector({ doc, selection, apply }) {
754
+ const node = selection ? doc.nodes[selection] : null;
755
+ if (!node) {
756
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: 16, color: "#94a3b8", fontFamily: "system-ui, sans-serif", fontSize: 13 }, children: "Select an element to edit." });
757
+ }
758
+ const s = node.style.base;
759
+ const setStyle = (patch) => apply({ t: "set_style", id: node.id, breakpoint: "base", patch });
760
+ const setProp = (key, value) => apply({ t: "set_props", id: node.id, patch: { [key]: value } });
761
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { overflow: "auto", padding: 16, fontFamily: "system-ui, sans-serif", height: "100%", boxSizing: "border-box" }, children: [
762
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, fontWeight: 600, color: "#0f172a" }, children: node.type }),
763
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: "#94a3b8", marginBottom: 8 }, children: node.id }),
764
+ node.type === "text" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
765
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: label, children: "Content" }),
766
+ /* @__PURE__ */ jsxRuntime.jsx(
767
+ "textarea",
768
+ {
769
+ style: { ...input, minHeight: 64, resize: "vertical" },
770
+ value: typeof node.props.content === "string" ? node.props.content : "",
771
+ onChange: (e) => setProp("content", e.target.value)
772
+ }
773
+ )
774
+ ] }) : null,
775
+ node.type === "image" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
776
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: label, children: "Source" }),
777
+ /* @__PURE__ */ jsxRuntime.jsx(
778
+ "input",
779
+ {
780
+ style: input,
781
+ value: typeof node.props.src === "string" ? node.props.src : "",
782
+ onChange: (e) => setProp("src", e.target.value)
783
+ }
784
+ )
785
+ ] }) : null,
786
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: label, children: "Background" }),
787
+ /* @__PURE__ */ jsxRuntime.jsx(
788
+ "input",
789
+ {
790
+ style: input,
791
+ placeholder: "#ffffff | gradient | url(\u2026)",
792
+ value: s.background ?? "",
793
+ onChange: (e) => setStyle({ background: e.target.value })
794
+ }
795
+ ),
796
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: label, children: "Text color" }),
797
+ /* @__PURE__ */ jsxRuntime.jsx(
798
+ "input",
799
+ {
800
+ style: input,
801
+ placeholder: "#0f172a",
802
+ value: s.color ?? "",
803
+ onChange: (e) => setStyle({ color: e.target.value })
804
+ }
805
+ ),
806
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: label, children: "Font size (px)" }),
807
+ /* @__PURE__ */ jsxRuntime.jsx(
808
+ "input",
809
+ {
810
+ type: "number",
811
+ style: input,
812
+ value: s.fontSize?.value ?? "",
813
+ onChange: (e) => setStyle({ fontSize: { value: Number(e.target.value) || 0, unit: "px" } })
814
+ }
815
+ ),
816
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: label, children: "Padding (px)" }),
817
+ /* @__PURE__ */ jsxRuntime.jsx(
818
+ "input",
819
+ {
820
+ type: "number",
821
+ style: input,
822
+ value: s.padding?.value ?? "",
823
+ onChange: (e) => setStyle({ padding: { value: Number(e.target.value) || 0, unit: "px" } })
824
+ }
825
+ ),
826
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: label, children: "Opacity" }),
827
+ /* @__PURE__ */ jsxRuntime.jsx(
828
+ "input",
829
+ {
830
+ type: "number",
831
+ step: "0.1",
832
+ min: "0",
833
+ max: "1",
834
+ style: input,
835
+ value: s.opacity ?? "",
836
+ onChange: (e) => setStyle({ opacity: Number(e.target.value) })
837
+ }
838
+ )
839
+ ] });
840
+ }
841
+ function Editor({ defaultValue, onChange }) {
842
+ const ed = useEditor(defaultValue);
843
+ const first = react.useRef(true);
844
+ const onChangeRef = useLatestRef(onChange);
845
+ react.useEffect(() => {
846
+ if (first.current) {
847
+ first.current = false;
848
+ return;
849
+ }
850
+ onChangeRef.current?.(ed.state.doc);
851
+ }, [ed.state.doc, onChangeRef]);
852
+ const shell = {
853
+ display: "grid",
854
+ gridTemplateColumns: "220px 1fr 300px",
855
+ height: "100%",
856
+ minHeight: 0,
857
+ background: "#fff",
858
+ color: "#0f172a",
859
+ border: "1px solid #e2e8f0",
860
+ borderRadius: 12,
861
+ overflow: "hidden"
862
+ };
863
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: shell, children: [
864
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { borderRight: "1px solid #e2e8f0", display: "flex", flexDirection: "column", minHeight: 0 }, children: [
865
+ /* @__PURE__ */ jsxRuntime.jsx(Toolbar, { ed }),
866
+ /* @__PURE__ */ jsxRuntime.jsx(
867
+ LayersPanel,
868
+ {
869
+ doc: ed.state.doc,
870
+ selection: ed.state.selection,
871
+ onSelect: ed.select,
872
+ onMove: (id, parent, order) => ed.apply({ t: "move_node", id, parent, order })
873
+ }
874
+ )
875
+ ] }),
876
+ /* @__PURE__ */ jsxRuntime.jsx(Canvas, { doc: ed.state.doc, selection: ed.state.selection, onSelect: ed.select, apply: ed.apply }),
877
+ /* @__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 }) })
878
+ ] });
879
+ }
880
+ function Toolbar({ ed }) {
881
+ const btn = {
882
+ font: "inherit",
883
+ fontSize: 12,
884
+ padding: "4px 10px",
885
+ borderRadius: 6,
886
+ border: "1px solid #e2e8f0",
887
+ background: "#fff",
888
+ cursor: "pointer"
889
+ };
890
+ return /* @__PURE__ */ jsxRuntime.jsxs(
891
+ "div",
892
+ {
893
+ style: {
894
+ display: "flex",
895
+ gap: 6,
896
+ padding: 8,
897
+ borderBottom: "1px solid #e2e8f0",
898
+ fontFamily: "system-ui, sans-serif"
899
+ },
900
+ children: [
901
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: { ...btn, opacity: ed.canUndo ? 1 : 0.4 }, disabled: !ed.canUndo, onClick: ed.undo, children: "Undo" }),
902
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: { ...btn, opacity: ed.canRedo ? 1 : 0.4 }, disabled: !ed.canRedo, onClick: ed.redo, children: "Redo" })
903
+ ]
904
+ }
905
+ );
906
+ }
404
907
 
908
+ exports.Canvas = Canvas;
909
+ exports.CmsPage = CmsPage;
910
+ exports.CmsRegion = CmsRegion;
405
911
  exports.DEFAULT_BREAKPOINTS = DEFAULT_BREAKPOINTS;
912
+ exports.Editor = Editor;
913
+ exports.Inspector = Inspector;
914
+ exports.LayersPanel = LayersPanel;
915
+ exports.RenderNode = RenderNode;
406
916
  exports.childrenOf = childrenOf;
917
+ exports.defaultRegistry = defaultRegistry;
407
918
  exports.descendantIds = descendantIds;
919
+ exports.editorReduce = editorReduce;
408
920
  exports.emitDocCss = emitDocCss;
409
921
  exports.emptyDoc = emptyDoc;
922
+ exports.getPath = getPath;
923
+ exports.initEditor = initEditor;
410
924
  exports.invert = invert;
411
925
  exports.isBinding = isBinding;
412
926
  exports.keyBetween = keyBetween;
413
927
  exports.reduce = reduce;
414
928
  exports.reduceAll = reduceAll;
929
+ exports.resolveValue = resolveValue;
930
+ exports.useEditor = useEditor;
415
931
  //# sourceMappingURL=index.cjs.map
416
932
  //# sourceMappingURL=index.cjs.map