@jbpark/live-editor 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/{ast-CMD20ykx.js → ast-BFbDWO-l.js} +198 -208
  2. package/dist/ast-BFbDWO-l.js.map +1 -0
  3. package/dist/{boundary-D2IFja-3.js → boundary-B17cepvm.js} +12 -9
  4. package/dist/boundary-B17cepvm.js.map +1 -0
  5. package/dist/dnd/index.d.ts +2 -2
  6. package/dist/dnd/index.js +2 -2
  7. package/dist/{dnd-DBaH2L8N.js → dnd-Z1KS16Fy.js} +462 -222
  8. package/dist/dnd-Z1KS16Fy.js.map +1 -0
  9. package/dist/{document-C3eCRQlj.js → document-cEEdFERz.js} +79 -20
  10. package/dist/document-cEEdFERz.js.map +1 -0
  11. package/dist/error/index.d.ts +1 -1
  12. package/dist/error/index.js +2 -2
  13. package/dist/{error-KW8XCcjH.js → error-DWhxQEom.js} +2 -2
  14. package/dist/{error-KW8XCcjH.js.map → error-DWhxQEom.js.map} +1 -1
  15. package/dist/{index-DNNj_0ba.d.ts → index-C4SGQ3Ci.d.ts} +4 -3
  16. package/dist/{index-DVgwXnPa.d.ts → index-CtlUYnWq.d.ts} +25 -3
  17. package/dist/index.d.ts +4 -4
  18. package/dist/index.js +3 -3
  19. package/dist/index.js.map +1 -1
  20. package/dist/preview/index.js +2 -2
  21. package/dist/{preview-B9Jhv1Up.js → preview-C_UzpGWh.js} +3 -3
  22. package/dist/{preview-B9Jhv1Up.js.map → preview-C_UzpGWh.js.map} +1 -1
  23. package/dist/{sections-A4TAXUP8.js → sections-GJQ63uEB.js} +2 -2
  24. package/dist/{sections-A4TAXUP8.js.map → sections-GJQ63uEB.js.map} +1 -1
  25. package/dist/{use-dynamic-tailwind-BDfytfYC.js → use-dynamic-tailwind-DpbjmATF.js} +5 -5
  26. package/dist/use-dynamic-tailwind-DpbjmATF.js.map +1 -0
  27. package/dist/utils/ast/index.js +2 -2
  28. package/dist/utils/index.js +2 -2
  29. package/package.json +1 -1
  30. package/dist/ast-CMD20ykx.js.map +0 -1
  31. package/dist/boundary-D2IFja-3.js.map +0 -1
  32. package/dist/dnd-DBaH2L8N.js.map +0 -1
  33. package/dist/document-C3eCRQlj.js.map +0 -1
  34. package/dist/use-dynamic-tailwind-BDfytfYC.js.map +0 -1
@@ -1,22 +1,23 @@
1
- import { _ as __toESM, c as inspectDocument, h as require_lib, n as createSectionPreviewCache, p as nanoid, r as fillSectionIds } from "./document-C3eCRQlj.js";
2
- import { c as RESERVED_BINDING_PROPERTIES, o as DRAGGABLE_ITEMS, t as BINDING_PROP } from "./constants-CKvdqZtO.js";
1
+ import { S as require_lib, _ as nanoid, c as inspectDocument, h as replaceIds, m as fillIdsFrom, n as createSectionPreviewCache, r as fillSectionIds, w as __toESM } from "./document-cEEdFERz.js";
2
+ import { c as RESERVED_BINDING_PROPERTIES, o as DRAGGABLE_ITEMS, r as DATA_ATTR, t as BINDING_PROP } from "./constants-CKvdqZtO.js";
3
3
  import { i as usePreview } from "./states-Ci1AvoQ9.js";
4
- import { A as extractObjectProperties, C as getStructuredValue, D as canLosslesslyEvaluateSource, M as parseArrayExpression, N as parseValue, S as getCurrentValue, _ as updateArrayItemProperty, b as moveSelectedIndices, c as getChildrenSignatures, d as appendArrayItem, f as duplicateArrayItems, g as removeArrayItems, i as replaceIds, k as extractNodeValue, m as moveArrayItems, p as moveArrayItem, r as fillIds, s as updateAll, t as validateBindingValue, u as extract, v as updateArrayItemValue, w as parseBinding, x as findEditableChildren, y as canStructurallyEditArray } from "./ast-CMD20ykx.js";
4
+ import { A as parseValue, D as extractObjectProperties, E as extractNodeValue, _ as moveSelectedIndices, a as getChildrenSignatures, b as getStructuredValue, c as appendArrayItem, d as moveArrayItems, g as canStructurallyEditArray, h as updateArrayItemValue, i as updateAll, k as parseArrayExpression, l as duplicateArrayItems, m as updateArrayItemProperty, p as removeArrayItems, s as extract, t as validateBindingValue, u as moveArrayItem, v as findEditableChildren, w as canLosslesslyEvaluateSource, x as parseBinding, y as getCurrentValue } from "./ast-BFbDWO-l.js";
5
5
  import { t as cn } from "./cn-CAnad2vL.js";
6
6
  import { o as preloadScripts } from "./compile-0Dvp8zp5.js";
7
- import { a as Frame, i as useStableModules, n as useCompiledModule, t as useDynamicTailwind } from "./use-dynamic-tailwind-BDfytfYC.js";
7
+ import { a as Frame, i as useStableModules, n as useCompiledModule, t as useDynamicTailwind } from "./use-dynamic-tailwind-DpbjmATF.js";
8
8
  import { t as Core } from "./core-B3ruccKb.js";
9
- import { a as replaceSections, n as extractSections, r as generateSection } from "./sections-A4TAXUP8.js";
10
- import { n as Error$1, t as ErrorBoundary } from "./boundary-D2IFja-3.js";
9
+ import { a as replaceSections, n as extractSections, r as generateSection } from "./sections-GJQ63uEB.js";
10
+ import { n as Error$1, t as ErrorBoundary } from "./boundary-B17cepvm.js";
11
11
  import { Children, createContext, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
12
12
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
13
- import { DndContext, DragOverlay, KeyboardSensor, PointerSensor, closestCenter, useDndContext, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
14
- import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
13
+ import { DndContext, DragOverlay, KeyboardSensor, MouseSensor, PointerSensor, TouchSensor, closestCenter, useDndContext, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
14
+ import { restrictToParentElement, restrictToVerticalAxis } from "@dnd-kit/modifiers";
15
15
  import { SortableContext, arrayMove, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
16
16
  import { Button, Card, Checkbox, ColorPicker, DatePicker, Drawer, Input, RichTextEditor, Select, Space, Splitter, Toast, Typography } from "@jbpark/ui-kit";
17
17
  import { useDebounce, useMultiSelect, useResponsiveSize } from "@jbpark/use-hooks";
18
- import { ArrowDown, ArrowUp, ChevronDown, ChevronUp, Copy, LayoutGrid, Plus, Trash, X } from "lucide-react";
19
- import { CSS } from "@dnd-kit/utilities";
18
+ import { createPortal } from "react-dom";
19
+ import { ArrowDown, ArrowUp, ChevronDown, ChevronRight, ChevronUp, Copy, Crosshair, GripVertical, LayoutGrid, Plus, Trash, X } from "lucide-react";
20
+ import { CSS as CSS$1 } from "@dnd-kit/utilities";
20
21
  //#region src/components/dnd/droppable.tsx
21
22
  var import_lib = /* @__PURE__ */ __toESM(require_lib(), 1);
22
23
  const Droppable = ({ children, className }) => {
@@ -46,6 +47,64 @@ const toastEditError = (error) => {
46
47
  const DndEditOptionsContext = createContext({ reportError: toastEditError });
47
48
  const useDndEditOptions = () => useContext(DndEditOptionsContext);
48
49
  //#endregion
50
+ //#region src/components/dnd/inspector.ts
51
+ const DndInspectorContext = createContext(null);
52
+ const useDndInspector = () => {
53
+ const inspector = useContext(DndInspectorContext);
54
+ if (!inspector) throw new Error("useDndInspector() must be used inside <Live.Dnd>.");
55
+ return inspector;
56
+ };
57
+ const outside = (root) => (element) => element.getRootNode() !== root;
58
+ const deepestAt = (root, x, y, skip) => {
59
+ const element = root.elementsFromPoint(x, y).find((candidate) => !skip(candidate));
60
+ if (!element) return null;
61
+ if (element instanceof HTMLIFrameElement) {
62
+ const document = element.contentDocument;
63
+ if (!document) return element;
64
+ const rect = element.getBoundingClientRect();
65
+ return deepestAt(document, x - rect.left, y - rect.top, outside(document)) ?? element;
66
+ }
67
+ if (element.shadowRoot && element.shadowRoot !== root) return deepestAt(element.shadowRoot, x, y, outside(element.shadowRoot)) ?? element;
68
+ return element;
69
+ };
70
+ const hasId = (element) => Boolean(element.getAttribute(DATA_ATTR.ID));
71
+ const pickElement = (section, overlay, x, y) => {
72
+ let element = deepestAt(section.ownerDocument, x, y, (candidate) => candidate === overlay || candidate === section || !section.contains(candidate));
73
+ while (element && element !== section && !hasId(element)) element = element.parentElement ?? element.parentNode?.host ?? null;
74
+ return element === section ? null : element;
75
+ };
76
+ const viewportRect = (element) => {
77
+ const rect = element.getBoundingClientRect();
78
+ let x = rect.left;
79
+ let y = rect.top;
80
+ let frame = element.ownerDocument.defaultView?.frameElement ?? null;
81
+ while (frame) {
82
+ const frameRect = frame.getBoundingClientRect();
83
+ x += frameRect.left;
84
+ y += frameRect.top;
85
+ frame = frame.ownerDocument.defaultView?.frameElement ?? null;
86
+ }
87
+ return new DOMRect(x, y, rect.width, rect.height);
88
+ };
89
+ //#endregion
90
+ //#region src/components/dnd/inspector-highlight.tsx
91
+ const InspectorHighlight = ({ rect }) => rect ? createPortal(/* @__PURE__ */ jsx("div", {
92
+ "aria-hidden": true,
93
+ "data-dnd-inspector-highlight": true,
94
+ style: {
95
+ position: "fixed",
96
+ left: rect.left,
97
+ top: rect.top,
98
+ width: rect.width,
99
+ height: rect.height,
100
+ pointerEvents: "none",
101
+ outline: "2px solid #3b82f6",
102
+ outlineOffset: -1,
103
+ background: "rgba(59, 130, 246, 0.12)",
104
+ zIndex: 2147483647
105
+ }
106
+ }), document.body) : null;
107
+ //#endregion
49
108
  //#region src/components/dnd/draggable.tsx
50
109
  const DraggableItem = ({ item, children }) => {
51
110
  const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
@@ -436,7 +495,8 @@ const Children$1 = ({ value, onChange, onNodeChange }) => {
436
495
  }), editableChildrenMap.get(itemIndex).map((editableNode, idx) => {
437
496
  const nodeId = editableNode.dataAttributes.find((a) => a.name === "data-id")?.value;
438
497
  return /* @__PURE__ */ jsxs("div", {
439
- className: "rounded border border-green-100 bg-white p-2",
498
+ "data-node-id": nodeId,
499
+ className: "rounded border border-green-100 bg-white p-2\n data-[picked]:ring-2 data-[picked]:ring-blue-400",
440
500
  children: [/* @__PURE__ */ jsx("div", {
441
501
  className: "mb-1 text-xs text-green-600",
442
502
  children: editableNode.tagName
@@ -487,6 +547,84 @@ const getFieldKind = (binding) => {
487
547
  };
488
548
  const isStructuralFieldKind = (kind) => kind === "items" || kind === "children";
489
549
  //#endregion
550
+ //#region src/components/dnd/panel/sortable-items.tsx
551
+ const label = (items, id) => {
552
+ const index = items.findIndex((item) => item.id === id);
553
+ return index >= 0 ? `Item ${index + 1}` : "Item";
554
+ };
555
+ const SortableItems = ({ items, disabled, onMove, children }) => {
556
+ const sensors = useSensors(useSensor(MouseSensor, { activationConstraint: { distance: 4 } }), useSensor(TouchSensor, { activationConstraint: {
557
+ delay: 250,
558
+ tolerance: 5
559
+ } }), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }));
560
+ const onDragEnd = ({ active, over }) => {
561
+ const from = items.find((item) => item.id === active.id);
562
+ const to = items.find((item) => item.id === over?.id);
563
+ if (from && to && from !== to) onMove(from, to.index);
564
+ };
565
+ return /* @__PURE__ */ jsx(DndContext, {
566
+ sensors,
567
+ collisionDetection: closestCenter,
568
+ modifiers: [restrictToVerticalAxis, restrictToParentElement],
569
+ accessibility: { announcements: {
570
+ onDragStart: ({ active }) => `Picked up ${label(items, active.id)}.`,
571
+ onDragOver: ({ active, over }) => over ? `${label(items, active.id)} is over ${label(items, over.id)}.` : void 0,
572
+ onDragEnd: ({ active, over }) => over ? `${label(items, active.id)} was moved to the place of ${label(items, over.id)}.` : `${label(items, active.id)} was dropped.`,
573
+ onDragCancel: ({ active }) => `Moving ${label(items, active.id)} was cancelled.`
574
+ } },
575
+ onDragEnd,
576
+ children: /* @__PURE__ */ jsx(SortableContext, {
577
+ items: items.map((item) => item.id),
578
+ strategy: verticalListSortingStrategy,
579
+ disabled,
580
+ children: /* @__PURE__ */ jsx("div", {
581
+ className: "space-y-4",
582
+ children: items.map(children)
583
+ })
584
+ })
585
+ });
586
+ };
587
+ const ItemCard = ({ id, title, disabled, expanded, onToggle, checkbox, controls, className, children }) => {
588
+ const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({
589
+ id,
590
+ disabled
591
+ });
592
+ return /* @__PURE__ */ jsxs("div", {
593
+ ref: setNodeRef,
594
+ style: {
595
+ transform: CSS$1.Translate.toString(transform),
596
+ transition
597
+ },
598
+ className: cn(className, isDragging && "relative z-10 shadow-md"),
599
+ children: [/* @__PURE__ */ jsxs("div", {
600
+ className: "flex items-center justify-between",
601
+ children: [/* @__PURE__ */ jsxs("div", {
602
+ className: "flex items-center space-x-1",
603
+ children: [
604
+ /* @__PURE__ */ jsx("button", {
605
+ type: "button",
606
+ ref: setActivatorNodeRef,
607
+ ...attributes,
608
+ ...listeners,
609
+ "aria-label": `Reorder ${title}`,
610
+ disabled,
611
+ className: "cursor-grab rounded p-0.5 text-gray-400\n hover:text-gray-700 disabled:cursor-not-allowed\n disabled:opacity-40",
612
+ children: /* @__PURE__ */ jsx(GripVertical, { size: 14 })
613
+ }),
614
+ checkbox,
615
+ /* @__PURE__ */ jsxs("button", {
616
+ type: "button",
617
+ "aria-expanded": expanded,
618
+ onClick: onToggle,
619
+ className: "inline-flex items-center space-x-1 rounded px-1 text-xs\n font-medium",
620
+ children: [expanded ? /* @__PURE__ */ jsx(ChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(ChevronRight, { size: 14 }), /* @__PURE__ */ jsx("span", { children: title })]
621
+ })
622
+ ]
623
+ }), controls]
624
+ }), expanded && children]
625
+ });
626
+ };
627
+ //#endregion
490
628
  //#region src/components/dnd/panel/use-dnd-items.ts
491
629
  const createPendingCommit = () => {
492
630
  let current = null;
@@ -623,6 +761,7 @@ const useDndItems = (value, { render, onChange, onNodeChange } = {}) => {
623
761
  rawItems,
624
762
  value
625
763
  ]);
764
+ const [collapsed, setCollapsed] = useState(() => /* @__PURE__ */ new Set());
626
765
  const { selection, record } = useStructuralSelection(isPrimitive ? primitiveItems.length : objectItems.length, value);
627
766
  const [pending] = useState(createPendingCommit);
628
767
  useEffect(() => {
@@ -686,120 +825,135 @@ const useDndItems = (value, { render, onChange, onNodeChange } = {}) => {
686
825
  if (item === null) return;
687
826
  commit(snapshot, updateArrayItemValue(snapshot.value, item?.elementIndex ?? elementIndex, next), void 0, new Set(snapshot.selected));
688
827
  };
689
- return {
690
- kind,
691
- items: isPrimitive ? primitiveItems.map((item) => ({
692
- id: identity.ids[item.index] ?? item.id,
693
- index: item.index,
694
- elementIndex: item.elementIndex,
695
- properties: [],
696
- nested: [],
697
- value: {
698
- id: `primitive-${item.id}`,
699
- label: `item-${item.index}`,
700
- property: item.type,
701
- value: item.value ?? "",
702
- rawValue: item.type === "unknown" ? item.source : String(item.value ?? ""),
703
- canEditValue: canLosslesslyEvaluateSource(item.source),
704
- onChange: (next) => updateValue(item.elementIndex, next)
828
+ const actions = {
829
+ add: () => {
830
+ const snapshot = latest();
831
+ const next = appendArrayItem(snapshot.value, kind);
832
+ commit(snapshot, next, next ? [...snapshot.ids, nanoid(6)] : void 0, selectionAfter({ type: "append" }, snapshot.selected, snapshot.items.length));
833
+ },
834
+ move: (elementIndex, toIndex) => {
835
+ const snapshot = latest();
836
+ const from = locate(snapshot, elementIndex);
837
+ const target = snapshot.items.find((item) => item.index === toIndex);
838
+ if (!from || !target) return;
839
+ commit(snapshot, moveArrayItem(snapshot.value, from.elementIndex, target.elementIndex), moveId(snapshot.ids, from.index, target.index), /* @__PURE__ */ new Set());
840
+ },
841
+ remove: (elementIndex) => {
842
+ const snapshot = latest();
843
+ const removed = locate(snapshot, elementIndex);
844
+ if (removed === null) return;
845
+ commit(snapshot, removeArrayItems(snapshot.value, /* @__PURE__ */ new Set([removed?.elementIndex ?? elementIndex]), kind), removed ? removeIds(snapshot.ids, /* @__PURE__ */ new Set([removed.index])) : void 0, /* @__PURE__ */ new Set());
846
+ },
847
+ duplicateSelected: () => {
848
+ const snapshot = latest();
849
+ const selected = elementIndicesOf(snapshot, snapshot.selected);
850
+ const next = duplicateArrayItems(snapshot.value, selected);
851
+ const copied = snapshot.items.filter((item) => selected.has(item.elementIndex)).sort((a, b) => a.elementIndex - b.elementIndex).map(() => nanoid(6));
852
+ commit(snapshot, next, next ? [...snapshot.ids, ...copied] : void 0, selectionAfter({
853
+ type: "duplicate",
854
+ indices: [...snapshot.selected]
855
+ }, snapshot.selected, snapshot.items.length));
856
+ },
857
+ moveSelected: (direction) => {
858
+ const snapshot = latest();
859
+ const nextIdentity = moveSelectedIndices(snapshot.ids, snapshot.selected, direction);
860
+ const result = moveArrayItems(snapshot.value, elementIndicesOf(snapshot, snapshot.selected), direction);
861
+ if (!result) {
862
+ commit(snapshot, null, void 0, snapshot.selected);
863
+ return;
705
864
  }
706
- })) : objectItems.map((item) => {
707
- const id = identity.ids[item.index] ?? item.id;
708
- const properties = Object.entries(item.editableProperties).map(([key, prop]) => {
709
- const binding = resolveRenderEntry(render, key);
710
- const propertySource = value.slice(prop.astNode.start, prop.astNode.end);
711
- return {
712
- ...toBindingFields(binding),
713
- id: `item-${id}-${key}`,
714
- meta: {
715
- ...binding.meta,
716
- valueType: prop.type
717
- },
718
- value: parseValue(String(prop.value)),
719
- rawValue: prop.type === "unknown" ? propertySource : String(prop.value),
720
- canEditValue: canLosslesslyEvaluateSource(propertySource),
721
- onChange: (next) => updateProperty(item.elementIndex, key, next)
722
- };
723
- });
724
- const nested = [...Object.entries(item.jsxBindings).map(([property, nodes]) => ({
725
- property,
726
- elements: nodes.flatMap((node) => {
727
- const source = resolvePanelBindings(node);
728
- if (!source) return [];
729
- return [{
730
- id: source.id,
731
- tagName: source.tagName,
732
- bindings: withPanelCommit(source.bindings, onNodeChange)
733
- }];
734
- })
735
- })), ...Object.entries(item.jsxFallbacks).map(([property, code]) => ({
736
- property,
737
- elements: [],
738
- fallback: {
739
- id: `item-${id}-${property}-jsx`,
740
- label: property,
741
- property,
742
- type: "jsx",
743
- value: code,
744
- rawValue: code,
745
- canEditValue: true,
746
- onChange: (next) => updateProperty(item.elementIndex, property, next)
747
- }
748
- }))];
865
+ const visible = parseArrayExpression(result.code)?.elements.flatMap((node, index) => import_lib.isExpression(node) && import_lib.isObjectExpression(node) === !isPrimitive ? [index] : []) ?? [];
866
+ commit(snapshot, result.code, nextIdentity.items, new Set(visible.flatMap((position, index) => result.indices.has(position) ? [index] : [])));
867
+ },
868
+ removeSelected: () => {
869
+ const snapshot = latest();
870
+ commit(snapshot, removeArrayItems(snapshot.value, elementIndicesOf(snapshot, snapshot.selected), kind), removeIds(snapshot.ids, snapshot.selected), /* @__PURE__ */ new Set());
871
+ }
872
+ };
873
+ const items = isPrimitive ? primitiveItems.map((item) => ({
874
+ id: identity.ids[item.index] ?? item.id,
875
+ index: item.index,
876
+ elementIndex: item.elementIndex,
877
+ properties: [],
878
+ nested: [],
879
+ value: {
880
+ id: `primitive-${item.id}`,
881
+ label: `item-${item.index}`,
882
+ property: item.type,
883
+ value: item.value ?? "",
884
+ rawValue: item.type === "unknown" ? item.source : String(item.value ?? ""),
885
+ canEditValue: canLosslesslyEvaluateSource(item.source),
886
+ onChange: (next) => updateValue(item.elementIndex, next)
887
+ }
888
+ })) : objectItems.map((item) => {
889
+ const id = identity.ids[item.index] ?? item.id;
890
+ const properties = Object.entries(item.editableProperties).map(([key, prop]) => {
891
+ const binding = resolveRenderEntry(render, key);
892
+ const propertySource = value.slice(prop.astNode.start, prop.astNode.end);
749
893
  return {
750
- id,
751
- index: item.index,
752
- elementIndex: item.elementIndex,
753
- properties,
754
- nested
894
+ ...toBindingFields(binding),
895
+ id: `item-${id}-${key}`,
896
+ meta: {
897
+ ...binding.meta,
898
+ valueType: prop.type
899
+ },
900
+ value: parseValue(String(prop.value)),
901
+ rawValue: prop.type === "unknown" ? propertySource : String(prop.value),
902
+ canEditValue: canLosslesslyEvaluateSource(propertySource),
903
+ onChange: (next) => updateProperty(item.elementIndex, key, next)
755
904
  };
756
- }),
905
+ });
906
+ const nested = [...Object.entries(item.jsxBindings).map(([property, nodes]) => ({
907
+ property,
908
+ elements: nodes.flatMap((node) => {
909
+ const source = resolvePanelBindings(node);
910
+ if (!source) return [];
911
+ return [{
912
+ id: source.id,
913
+ tagName: source.tagName,
914
+ bindings: withPanelCommit(source.bindings, onNodeChange)
915
+ }];
916
+ })
917
+ })), ...Object.entries(item.jsxFallbacks).map(([property, code]) => ({
918
+ property,
919
+ elements: [],
920
+ fallback: {
921
+ id: `item-${id}-${property}-jsx`,
922
+ label: property,
923
+ property,
924
+ type: "jsx",
925
+ value: code,
926
+ rawValue: code,
927
+ canEditValue: true,
928
+ onChange: (next) => updateProperty(item.elementIndex, property, next)
929
+ }
930
+ }))];
931
+ return {
932
+ id,
933
+ index: item.index,
934
+ elementIndex: item.elementIndex,
935
+ properties,
936
+ nested
937
+ };
938
+ });
939
+ return {
940
+ kind,
941
+ items,
757
942
  selection,
758
- actions: {
759
- add: () => {
760
- const snapshot = latest();
761
- const next = appendArrayItem(snapshot.value, kind);
762
- commit(snapshot, next, next ? [...snapshot.ids, nanoid(6)] : void 0, selectionAfter({ type: "append" }, snapshot.selected, snapshot.items.length));
763
- },
764
- move: (elementIndex, toIndex) => {
765
- const snapshot = latest();
766
- const from = locate(snapshot, elementIndex);
767
- const target = snapshot.items.find((item) => item.index === toIndex);
768
- if (!from || !target) return;
769
- commit(snapshot, moveArrayItem(snapshot.value, from.elementIndex, target.elementIndex), moveId(snapshot.ids, from.index, target.index), /* @__PURE__ */ new Set());
770
- },
771
- remove: (elementIndex) => {
772
- const snapshot = latest();
773
- const removed = locate(snapshot, elementIndex);
774
- if (removed === null) return;
775
- commit(snapshot, removeArrayItems(snapshot.value, /* @__PURE__ */ new Set([removed?.elementIndex ?? elementIndex]), kind), removed ? removeIds(snapshot.ids, /* @__PURE__ */ new Set([removed.index])) : void 0, /* @__PURE__ */ new Set());
776
- },
777
- duplicateSelected: () => {
778
- const snapshot = latest();
779
- const selected = elementIndicesOf(snapshot, snapshot.selected);
780
- const next = duplicateArrayItems(snapshot.value, selected);
781
- const copied = snapshot.items.filter((item) => selected.has(item.elementIndex)).sort((a, b) => a.elementIndex - b.elementIndex).map(() => nanoid(6));
782
- commit(snapshot, next, next ? [...snapshot.ids, ...copied] : void 0, selectionAfter({
783
- type: "duplicate",
784
- indices: [...snapshot.selected]
785
- }, snapshot.selected, snapshot.items.length));
786
- },
787
- moveSelected: (direction) => {
788
- const snapshot = latest();
789
- const nextIdentity = moveSelectedIndices(snapshot.ids, snapshot.selected, direction);
790
- const result = moveArrayItems(snapshot.value, elementIndicesOf(snapshot, snapshot.selected), direction);
791
- if (!result) {
792
- commit(snapshot, null, void 0, snapshot.selected);
793
- return;
794
- }
795
- const visible = parseArrayExpression(result.code)?.elements.flatMap((node, index) => import_lib.isExpression(node) && import_lib.isObjectExpression(node) === !isPrimitive ? [index] : []) ?? [];
796
- commit(snapshot, result.code, nextIdentity.items, new Set(visible.flatMap((position, index) => result.indices.has(position) ? [index] : [])));
797
- },
798
- removeSelected: () => {
799
- const snapshot = latest();
800
- commit(snapshot, removeArrayItems(snapshot.value, elementIndicesOf(snapshot, snapshot.selected), kind), removeIds(snapshot.ids, snapshot.selected), /* @__PURE__ */ new Set());
943
+ expansion: {
944
+ expandedIds: items.flatMap((item) => collapsed.has(item.id) ? [] : [item.id]),
945
+ isExpanded: (id) => !collapsed.has(id),
946
+ toggle: (id) => setCollapsed((previous) => {
947
+ const next = new Set(previous);
948
+ if (!next.delete(id)) next.add(id);
949
+ return next;
950
+ }),
951
+ setExpanded: (ids) => {
952
+ const expanded = new Set(ids);
953
+ setCollapsed(new Set(items.flatMap((item) => expanded.has(item.id) ? [] : [item.id])));
801
954
  }
802
955
  },
956
+ actions,
803
957
  canEditStructure,
804
958
  parseError
805
959
  };
@@ -828,7 +982,8 @@ const NestedGroup = ({ group, onNodeChange }) => {
828
982
  "):"
829
983
  ]
830
984
  }), group.elements.map((element) => /* @__PURE__ */ jsxs("div", {
831
- className: "rounded border border-blue-100 bg-blue-50 p-2",
985
+ "data-node-id": element.id,
986
+ className: "rounded border border-blue-100 bg-blue-50 p-2\n data-[picked]:ring-2 data-[picked]:ring-blue-400",
832
987
  children: [/* @__PURE__ */ jsxs("div", {
833
988
  className: "mb-1 text-xs text-blue-600",
834
989
  children: [
@@ -863,7 +1018,7 @@ const NestedGroup = ({ group, onNodeChange }) => {
863
1018
  });
864
1019
  };
865
1020
  const Items = ({ value, render, onChange, onChildChange }) => {
866
- const { kind, items, selection, actions, canEditStructure, parseError } = useDndItems(value, {
1021
+ const { kind, items, selection, expansion, actions, canEditStructure, parseError } = useDndItems(value, {
867
1022
  render,
868
1023
  onChange,
869
1024
  onNodeChange: onChildChange
@@ -933,97 +1088,82 @@ const Items = ({ value, render, onChange, onChildChange }) => {
933
1088
  })
934
1089
  ]
935
1090
  });
936
- if (kind === "primitive") return /* @__PURE__ */ jsxs("div", {
937
- className: "space-y-4",
938
- children: [
939
- header,
940
- bulkBar,
941
- !canEditStructure && /* @__PURE__ */ jsx("div", {
942
- className: "rounded border border-dashed border-amber-200 p-3 text-xs\n text-amber-700",
943
- children: "Values remain editable, but moving, copying, adding, and deleting require a dense array without spreads or parenthesized top-level items. Use the code editor for those structural changes."
944
- }),
945
- items.map((item) => /* @__PURE__ */ jsxs("div", {
946
- className: "space-y-2 rounded border border-gray-100 bg-gray-50 p-2",
947
- children: [/* @__PURE__ */ jsxs("div", {
948
- className: "flex items-center justify-between space-x-1",
949
- children: [/* @__PURE__ */ jsx("div", {
950
- onClick: (e) => canEditStructure && selection.toggle(item.index, e.shiftKey),
951
- className: "inline-flex",
952
- children: /* @__PURE__ */ jsx(Checkbox, {
953
- checked: selection.isSelected(item.index),
954
- disabled: !canEditStructure,
955
- onChange: () => {}
956
- })
957
- }), itemControls(item)]
958
- }), /* @__PURE__ */ jsx(Field, {
959
- binding: item.value,
960
- onNodeChange: onChildChange
961
- })]
962
- }, item.id))
963
- ]
1091
+ const itemCheckbox = (item) => /* @__PURE__ */ jsx("div", {
1092
+ onClick: (e) => canEditStructure && selection.toggle(item.index, e.shiftKey),
1093
+ className: "inline-flex",
1094
+ children: /* @__PURE__ */ jsx(Checkbox, {
1095
+ checked: selection.isSelected(item.index),
1096
+ disabled: !canEditStructure,
1097
+ onChange: () => {}
1098
+ })
964
1099
  });
1100
+ const objectBody = (item) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
1101
+ className: "space-y-2",
1102
+ children: item.properties.map((binding) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("div", {
1103
+ className: "flex flex-col space-y-2",
1104
+ children: [/* @__PURE__ */ jsx("label", {
1105
+ className: "w-20 shrink-0 text-xs font-medium",
1106
+ children: binding.label
1107
+ }), /* @__PURE__ */ jsx(Field, {
1108
+ binding,
1109
+ onNodeChange: onChildChange
1110
+ })]
1111
+ }), /* @__PURE__ */ jsxs("span", {
1112
+ className: "text-right text-xs text-gray-500",
1113
+ children: [
1114
+ "(",
1115
+ String(binding.meta?.valueType),
1116
+ ")"
1117
+ ]
1118
+ })] }, `${item.id}-${binding.property}-${binding.label}`))
1119
+ }), /* @__PURE__ */ jsx("div", {
1120
+ className: "space-y-3 border-t pt-2",
1121
+ children: item.nested.length ? item.nested.map((group) => /* @__PURE__ */ jsx(NestedGroup, {
1122
+ group,
1123
+ onNodeChange: onChildChange
1124
+ }, group.property)) : /* @__PURE__ */ jsx("div", {
1125
+ className: "text-xs text-gray-500",
1126
+ children: "✓ No JSX bindings found"
1127
+ })
1128
+ })] });
1129
+ const allExpanded = expansion.expandedIds.length === items.length;
965
1130
  return /* @__PURE__ */ jsxs("div", {
966
1131
  className: "space-y-4",
967
1132
  children: [
968
1133
  header,
1134
+ items.length > 1 && /* @__PURE__ */ jsx("div", {
1135
+ className: "flex justify-end",
1136
+ children: /* @__PURE__ */ jsx(Button, {
1137
+ size: "small",
1138
+ variant: "text",
1139
+ onClick: () => expansion.setExpanded(allExpanded ? [] : items.map((item) => item.id)),
1140
+ children: allExpanded ? "Collapse all" : "Expand all"
1141
+ })
1142
+ }),
969
1143
  bulkBar,
970
1144
  !canEditStructure && /* @__PURE__ */ jsx("div", {
971
1145
  className: "rounded border border-dashed border-amber-200 p-3 text-xs\n text-amber-700",
972
1146
  children: "Values remain editable, but moving, copying, adding, and deleting require a dense array without spreads or parenthesized top-level items. Use the code editor for those structural changes."
973
1147
  }),
974
- items.map((item) => /* @__PURE__ */ jsxs("div", {
975
- className: "space-y-3 rounded border bg-gray-50 p-3",
976
- children: [
977
- /* @__PURE__ */ jsxs("div", {
978
- className: "flex items-center justify-between",
979
- children: [/* @__PURE__ */ jsxs("div", {
980
- className: "flex items-center space-x-2",
981
- children: [/* @__PURE__ */ jsx("div", {
982
- onClick: (e) => canEditStructure && selection.toggle(item.index, e.shiftKey),
983
- className: "inline-flex",
984
- children: /* @__PURE__ */ jsx(Checkbox, {
985
- checked: selection.isSelected(item.index),
986
- disabled: !canEditStructure,
987
- onChange: () => {}
988
- })
989
- }), /* @__PURE__ */ jsxs("div", {
990
- className: "text-xs font-medium",
991
- children: ["Item ", item.index + 1]
992
- })]
993
- }), itemControls(item)]
994
- }),
995
- /* @__PURE__ */ jsx("div", {
996
- className: "space-y-2",
997
- children: item.properties.map((binding) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("div", {
998
- className: "flex flex-col space-y-2",
999
- children: [/* @__PURE__ */ jsx("label", {
1000
- className: "w-20 shrink-0 text-xs font-medium",
1001
- children: binding.label
1002
- }), /* @__PURE__ */ jsx(Field, {
1003
- binding,
1004
- onNodeChange: onChildChange
1005
- })]
1006
- }), /* @__PURE__ */ jsxs("span", {
1007
- className: "text-right text-xs text-gray-500",
1008
- children: [
1009
- "(",
1010
- String(binding.meta?.valueType),
1011
- ")"
1012
- ]
1013
- })] }, `${item.id}-${binding.property}-${binding.label}`))
1014
- }),
1015
- /* @__PURE__ */ jsx("div", {
1016
- className: "space-y-3 border-t pt-2",
1017
- children: item.nested.length ? item.nested.map((group) => /* @__PURE__ */ jsx(NestedGroup, {
1018
- group,
1019
- onNodeChange: onChildChange
1020
- }, group.property)) : /* @__PURE__ */ jsx("div", {
1021
- className: "text-xs text-gray-500",
1022
- children: "✓ No JSX bindings found"
1023
- })
1024
- })
1025
- ]
1026
- }, item.id))
1148
+ /* @__PURE__ */ jsx(SortableItems, {
1149
+ items,
1150
+ disabled: !canEditStructure,
1151
+ onMove: (item, toIndex) => actions.move(item.elementIndex, toIndex),
1152
+ children: (item) => /* @__PURE__ */ jsx(ItemCard, {
1153
+ id: item.id,
1154
+ title: `Item ${item.index + 1}`,
1155
+ disabled: !canEditStructure,
1156
+ expanded: expansion.isExpanded(item.id),
1157
+ onToggle: () => expansion.toggle(item.id),
1158
+ checkbox: itemCheckbox(item),
1159
+ controls: itemControls(item),
1160
+ className: kind === "primitive" ? "space-y-2 rounded border border-gray-100 bg-gray-50 p-2" : "space-y-3 rounded border bg-gray-50 p-3",
1161
+ children: kind === "primitive" ? /* @__PURE__ */ jsx(Field, {
1162
+ binding: item.value,
1163
+ onNodeChange: onChildChange
1164
+ }) : objectBody(item)
1165
+ }, item.id)
1166
+ })
1027
1167
  ]
1028
1168
  });
1029
1169
  };
@@ -1318,11 +1458,34 @@ const groupBindingsById = (bindings) => {
1318
1458
  };
1319
1459
  const Panel$1 = ({ item, onDelete, onMoveUp, onMoveDown, canMoveUp = false, canMoveDown = false, bindings, onNodeChange, readOnly = false }) => {
1320
1460
  const groups = groupBindingsById(bindings);
1461
+ const rootRef = useRef(null);
1462
+ const pickedId = (useContext(DndInspectorContext)?.picked ?? null)?.id;
1463
+ useEffect(() => {
1464
+ const root = rootRef.current;
1465
+ if (!root || !pickedId) return;
1466
+ const target = root.querySelector(`[data-node-id="${CSS.escape(pickedId)}"]`);
1467
+ if (!target) return;
1468
+ target.setAttribute("data-picked", "");
1469
+ const until = performance.now() + 600;
1470
+ let frame = 0;
1471
+ const keepInView = () => {
1472
+ const box = target.getBoundingClientRect();
1473
+ const view = root.getBoundingClientRect();
1474
+ if (box.top < view.top || box.bottom > view.bottom) target.scrollIntoView?.({ block: "nearest" });
1475
+ if (performance.now() < until) frame = requestAnimationFrame(keepInView);
1476
+ };
1477
+ keepInView();
1478
+ return () => {
1479
+ cancelAnimationFrame(frame);
1480
+ target.removeAttribute("data-picked");
1481
+ };
1482
+ }, [pickedId, groups.length]);
1321
1483
  if (!item) return /* @__PURE__ */ jsx(Typography.Paragraph, {
1322
1484
  className: cn("p-4 text-sm text-gray-500"),
1323
1485
  children: "Please select a section."
1324
1486
  });
1325
1487
  return /* @__PURE__ */ jsxs("div", {
1488
+ ref: rootRef,
1326
1489
  className: cn("h-full space-y-4 p-4", "overflow-x-hidden overflow-y-auto"),
1327
1490
  children: [
1328
1491
  /* @__PURE__ */ jsxs("div", {
@@ -1363,9 +1526,13 @@ const Panel$1 = ({ item, onDelete, onMoveUp, onMoveDown, canMoveUp = false, canM
1363
1526
  className: "text-xs text-gray-400",
1364
1527
  children: "No editable elements."
1365
1528
  }),
1366
- groups.map((group) => /* @__PURE__ */ jsx(FieldGroup, {
1367
- bindings: group,
1368
- onNodeChange
1529
+ groups.map((group) => /* @__PURE__ */ jsx("div", {
1530
+ "data-node-id": group[0].id,
1531
+ className: "rounded data-[picked]:ring-2 data-[picked]:ring-blue-400\n data-[picked]:ring-offset-2",
1532
+ children: /* @__PURE__ */ jsx(FieldGroup, {
1533
+ bindings: group,
1534
+ onNodeChange
1535
+ })
1369
1536
  }, group[0].id))
1370
1537
  ]
1371
1538
  });
@@ -1404,8 +1571,9 @@ const Palette = ({ className, ...restProps }) => /* @__PURE__ */ jsx("div", {
1404
1571
  children: /* @__PURE__ */ jsx(PaletteItems, { subject: "<Live.Dnd.Palette>" })
1405
1572
  });
1406
1573
  const Canvas = ({ className, style, ...restProps }) => {
1407
- const { canvas } = useDndRegions("<Live.Dnd.Canvas>");
1408
- return /* @__PURE__ */ jsx("div", {
1574
+ const { canvas, documentError } = useDndRegions("<Live.Dnd.Canvas>");
1575
+ const inspector = useDndInspector();
1576
+ return /* @__PURE__ */ jsxs("div", {
1409
1577
  className: cn("relative h-full w-full overflow-y-auto", className),
1410
1578
  "data-frame-container": true,
1411
1579
  style: {
@@ -1415,7 +1583,21 @@ const Canvas = ({ className, style, ...restProps }) => {
1415
1583
  ...style
1416
1584
  },
1417
1585
  ...restProps,
1418
- children: canvas
1586
+ children: [canvas, !documentError && /* @__PURE__ */ jsx("div", {
1587
+ className: "pointer-events-none sticky bottom-0 z-70 h-0",
1588
+ children: /* @__PURE__ */ jsx("div", {
1589
+ className: "pointer-events-auto absolute bottom-3 left-3",
1590
+ children: /* @__PURE__ */ jsx(Button, {
1591
+ icon: /* @__PURE__ */ jsx(Crosshair, {}),
1592
+ color: "primary",
1593
+ variant: inspector.active ? "solid" : "outlined",
1594
+ "aria-pressed": inspector.active,
1595
+ "aria-label": "Pick an element",
1596
+ title: inspector.active ? "Click an element to edit it. Esc to cancel." : "Pick an element",
1597
+ onClick: inspector.toggle
1598
+ })
1599
+ })
1600
+ })]
1419
1601
  });
1420
1602
  };
1421
1603
  const Panel = ({ className, ...restProps }) => /* @__PURE__ */ jsx("div", {
@@ -1588,13 +1770,16 @@ const NAVIGATION_KEYS = {
1588
1770
  Home: "first",
1589
1771
  End: "last"
1590
1772
  };
1591
- const Sortable = ({ id, children, selected, onClick, onDelete: _onDelete, onCopy: _onCopy, nodeRef, onNavigate, onDeleteKey }) => {
1592
- const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging, isOver, active } = useSortable({ id });
1773
+ const Sortable = ({ id, children, selected, onClick, onDelete: _onDelete, onCopy: _onCopy, nodeRef, onNavigate, onDeleteKey, inspecting = false, onInspectMove, onInspectPick, onInspectLeave }) => {
1774
+ const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging, isOver, active } = useSortable({
1775
+ id,
1776
+ disabled: inspecting
1777
+ });
1593
1778
  const style = {
1594
- transform: CSS.Transform.toString(transform),
1779
+ transform: CSS$1.Transform.toString(transform),
1595
1780
  transition,
1596
1781
  opacity: isDragging ? .5 : 1,
1597
- cursor: "grab"
1782
+ cursor: inspecting ? "crosshair" : "grab"
1598
1783
  };
1599
1784
  const isNewItemOver = isOver && active?.data.current?.type === "new-item";
1600
1785
  const onKeyDown = (e) => {
@@ -1638,7 +1823,15 @@ const Sortable = ({ id, children, selected, onClick, onDelete: _onDelete, onCopy
1638
1823
  onClick,
1639
1824
  className: cn("relative", selected && "z-10 outline-2 outline-offset-2 outline-blue-500", isNewItemOver && "border-t-4 border-t-green-500"),
1640
1825
  children: [
1641
- /* @__PURE__ */ jsx("div", { className: cn("absolute inset-0 z-50") }),
1826
+ /* @__PURE__ */ jsx("div", {
1827
+ className: cn("absolute inset-0 z-50"),
1828
+ onPointerMove: inspecting ? (e) => onInspectMove?.(e.currentTarget.parentElement, e.currentTarget, e.clientX, e.clientY) : void 0,
1829
+ onPointerLeave: inspecting ? onInspectLeave : void 0,
1830
+ onClick: inspecting ? (e) => {
1831
+ e.stopPropagation();
1832
+ onInspectPick?.(e.currentTarget.parentElement, e.currentTarget, e.clientX, e.clientY);
1833
+ } : void 0
1834
+ }),
1642
1835
  children,
1643
1836
  selected && /* @__PURE__ */ jsxs(Space, {
1644
1837
  className: cn("absolute top-1 right-1 z-60"),
@@ -1959,7 +2152,7 @@ const conditionalModifiers = (args) => {
1959
2152
  return restrictToVerticalAxis(args);
1960
2153
  };
1961
2154
  const NO_MODULES = {};
1962
- const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange: _onChange, className, items = [], frame, dynamicTailwind = false, provider, renderField, onEditError, renderSectionFallback, shouldForceSectionFallback, onBeforeDelete, sectionNameFallback, containerId, children, ...restProps }) => {
2155
+ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange: _onChange, className, items = [], frame, dynamicTailwind = false, provider, renderField, onEditError, renderSectionFallback, shouldForceSectionFallback, onBeforeDelete, sectionNameFallback, containerId, onNodePick, children, ...restProps }) => {
1963
2156
  const modules = useStableModules(_modules);
1964
2157
  const [mobilePaletteOpen, setMobilePaletteOpen] = useState(false);
1965
2158
  const { breakpoint } = useResponsiveSize();
@@ -2016,6 +2209,45 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2016
2209
  if (active.id !== over.id && sections.some((s) => s.id === active.id)) reorder(String(active.id), String(over.id));
2017
2210
  };
2018
2211
  const onSelect = (id) => select(id);
2212
+ const [inspecting, setInspecting] = useState(false);
2213
+ const [picked, setPicked] = useState(null);
2214
+ const [highlight, setHighlight] = useState(null);
2215
+ if (picked && picked.sectionId !== selectedId) setPicked(null);
2216
+ const stopInspecting = useCallback(() => {
2217
+ setInspecting(false);
2218
+ setHighlight(null);
2219
+ }, []);
2220
+ useEffect(() => {
2221
+ if (!inspecting) return;
2222
+ const onKeyDown = (e) => {
2223
+ if (e.key === "Escape") stopInspecting();
2224
+ };
2225
+ window.addEventListener("keydown", onKeyDown);
2226
+ return () => window.removeEventListener("keydown", onKeyDown);
2227
+ }, [inspecting, stopInspecting]);
2228
+ const inspector = {
2229
+ active: inspecting,
2230
+ activate: () => setInspecting(true),
2231
+ deactivate: stopInspecting,
2232
+ toggle: () => inspecting ? stopInspecting() : setInspecting(true),
2233
+ picked
2234
+ };
2235
+ const onInspectMove = (section, overlay, x, y) => {
2236
+ const element = pickElement(section, overlay, x, y);
2237
+ setHighlight(element ? viewportRect(element) : null);
2238
+ };
2239
+ const onInspectPick = (sectionId, section, overlay, x, y) => {
2240
+ const id = pickElement(section, overlay, x, y)?.getAttribute(DATA_ATTR.ID);
2241
+ if (!id) return;
2242
+ const pick = {
2243
+ id,
2244
+ sectionId
2245
+ };
2246
+ selectOnly(sectionId);
2247
+ setPicked(pick);
2248
+ stopInspecting();
2249
+ onNodePick?.(pick);
2250
+ };
2019
2251
  const removeRef = useRef(remove);
2020
2252
  useEffect(() => {
2021
2253
  removeRef.current = remove;
@@ -2080,6 +2312,7 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2080
2312
  patch(next);
2081
2313
  };
2082
2314
  const selectedCode = selectedItem?.code;
2315
+ const selectedSectionId = selectedItem?.id;
2083
2316
  const { fields, updatedCode, parseError } = useMemo(() => {
2084
2317
  if (!selectedCode) return {
2085
2318
  fields: [],
@@ -2087,7 +2320,7 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2087
2320
  parseError: null
2088
2321
  };
2089
2322
  try {
2090
- const updated = fillIds(selectedCode);
2323
+ const updated = fillIdsFrom(selectedCode, selectedSectionId ?? "");
2091
2324
  return {
2092
2325
  fields: extract(updated),
2093
2326
  updatedCode: updated !== selectedCode ? updated : selectedCode,
@@ -2101,7 +2334,7 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2101
2334
  parseError: { error: e }
2102
2335
  };
2103
2336
  }
2104
- }, [selectedCode]);
2337
+ }, [selectedCode, selectedSectionId]);
2105
2338
  useEffect(() => {
2106
2339
  if (missingContainer !== null) reportErrorRef.current({
2107
2340
  type: "parse",
@@ -2219,6 +2452,10 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2219
2452
  nodeRef: sectionNodes.register(section.id),
2220
2453
  onNavigate: (to) => onNavigate(section.id, to),
2221
2454
  onDeleteKey: () => onDeleteKey(section.id),
2455
+ inspecting,
2456
+ onInspectMove,
2457
+ onInspectPick: (...args) => onInspectPick(section.id, ...args),
2458
+ onInspectLeave: () => setHighlight(null),
2222
2459
  children: /* @__PURE__ */ jsx(renderer_default, {
2223
2460
  preview: previews[index],
2224
2461
  sectionId: section.id,
@@ -2250,12 +2487,12 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2250
2487
  children: [/* @__PURE__ */ jsx("div", {
2251
2488
  className: cn("relative flex h-full w-full", className),
2252
2489
  ...restProps,
2253
- children: /* @__PURE__ */ jsx(DndEditOptionsContext.Provider, {
2490
+ children: /* @__PURE__ */ jsxs(DndEditOptionsContext.Provider, {
2254
2491
  value: {
2255
2492
  renderField,
2256
2493
  reportError
2257
2494
  },
2258
- children: /* @__PURE__ */ jsx(DndRegionContext.Provider, {
2495
+ children: [/* @__PURE__ */ jsx(DndRegionContext.Provider, {
2259
2496
  value: {
2260
2497
  palette,
2261
2498
  panel,
@@ -2267,8 +2504,11 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2267
2504
  setPaletteOpen: setMobilePaletteOpen,
2268
2505
  documentError: problem?.reason ?? null
2269
2506
  },
2270
- children: Children.toArray(children).length ? children : /* @__PURE__ */ jsx(Layout, {})
2271
- })
2507
+ children: /* @__PURE__ */ jsx(DndInspectorContext.Provider, {
2508
+ value: inspector,
2509
+ children: Children.toArray(children).length ? children : /* @__PURE__ */ jsx(Layout, {})
2510
+ })
2511
+ }), /* @__PURE__ */ jsx(InspectorHighlight, { rect: inspecting ? highlight : null })]
2272
2512
  })
2273
2513
  }), /* @__PURE__ */ jsx(DragOverlay, { children: /* @__PURE__ */ jsx(Overlay, {
2274
2514
  sections,
@@ -2299,6 +2539,6 @@ const useItemsEditor = useDndItems;
2299
2539
  /** @deprecated Renamed to `useDndChildren`. */
2300
2540
  const useChildrenEditor = useDndChildren;
2301
2541
  //#endregion
2302
- export { useDndPanel as _, Layout as a, Field as c, isStructuralFieldKind as d, useDndChildren as f, useDndPalette as g, useDndLayout as h, Canvas as i, useDndItems as l, withPanelCommit as m, useChildrenEditor as n, Palette as o, resolvePanelBindings as p, useItemsEditor as r, Panel as s, Dnd as t, getFieldKind as u, DraggableItem as v };
2542
+ export { useDndPanel as _, Layout as a, Field as c, isStructuralFieldKind as d, useDndChildren as f, useDndPalette as g, useDndLayout as h, Canvas as i, useDndItems as l, withPanelCommit as m, useChildrenEditor as n, Palette as o, resolvePanelBindings as p, useItemsEditor as r, Panel as s, Dnd as t, getFieldKind as u, DraggableItem as v, useDndInspector as y };
2303
2543
 
2304
- //# sourceMappingURL=dnd-DBaH2L8N.js.map
2544
+ //# sourceMappingURL=dnd-Z1KS16Fy.js.map