@jbpark/live-editor 3.2.1 → 4.0.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 (49) hide show
  1. package/dist/ast-CZwpVrJv.js +851 -0
  2. package/dist/ast-CZwpVrJv.js.map +1 -0
  3. package/dist/{boundary-BTP1nfG6.js → boundary-C90q3YsT.js} +8 -7
  4. package/dist/boundary-C90q3YsT.js.map +1 -0
  5. package/dist/{context-649REFsj.js → context-Y-M9fViD.js} +4 -8
  6. package/dist/context-Y-M9fViD.js.map +1 -0
  7. package/dist/{core-D3q5rpuz.js → core-Co8Nlq16.js} +2 -2
  8. package/dist/{core-D3q5rpuz.js.map → core-Co8Nlq16.js.map} +1 -1
  9. package/dist/dnd/index.d.ts +2 -2
  10. package/dist/dnd/index.js +2 -2
  11. package/dist/{dnd-D90jLjLH.js → dnd-ClnGRNaY.js} +353 -319
  12. package/dist/dnd-ClnGRNaY.js.map +1 -0
  13. package/dist/editor/index.js +2 -2
  14. package/dist/{editor-LzqHe_-F.js → editor-COKGtmfE.js} +3 -3
  15. package/dist/{editor-LzqHe_-F.js.map → editor-COKGtmfE.js.map} +1 -1
  16. package/dist/error/index.d.ts +1 -1
  17. package/dist/error/index.js +2 -2
  18. package/dist/{error-CO0EbMlA.js → error-o0SBwtTv.js} +2 -2
  19. package/dist/{error-CO0EbMlA.js.map → error-o0SBwtTv.js.map} +1 -1
  20. package/dist/{document-C6bNHl7l.js → extract-abHYmNsu.js} +927 -42
  21. package/dist/extract-abHYmNsu.js.map +1 -0
  22. package/dist/{index-DxbG789f.d.ts → index-B_p74BRM.d.ts} +29 -14
  23. package/dist/{index-CCynrS6c.d.ts → index-DNNj_0ba.d.ts} +3 -2
  24. package/dist/{index-lgHdCda5.d.ts → index-DQkL37eL.d.ts} +10 -2
  25. package/dist/{index-DswWDEXZ.d.ts → index-Doh4VTXr.d.ts} +65 -35
  26. package/dist/index.d.ts +6 -6
  27. package/dist/index.js +5 -5
  28. package/dist/index.js.map +1 -1
  29. package/dist/preview/index.d.ts +2 -2
  30. package/dist/preview/index.js +3 -2
  31. package/dist/{preview-CWT0lgwq.js → preview-DKyKKcu7.js} +4 -4
  32. package/dist/{preview-CWT0lgwq.js.map → preview-DKyKKcu7.js.map} +1 -1
  33. package/dist/provider/index.js +1 -1
  34. package/dist/{use-dynamic-tailwind-DAhKGsY4.js → use-dynamic-tailwind-BF8TQ3Yy.js} +83 -27
  35. package/dist/use-dynamic-tailwind-BF8TQ3Yy.js.map +1 -0
  36. package/dist/utils/ast/index.d.ts +2 -2
  37. package/dist/utils/ast/index.js +3 -3
  38. package/dist/utils/index.d.ts +4 -7
  39. package/dist/utils/index.js +3 -3
  40. package/dist/{utils-WyxPYZGh.js → utils-BQ7WL7Jh.js} +33 -16
  41. package/dist/{utils-WyxPYZGh.js.map → utils-BQ7WL7Jh.js.map} +1 -1
  42. package/package.json +3 -1
  43. package/dist/ast-Bx2Avo4d.js +0 -1530
  44. package/dist/ast-Bx2Avo4d.js.map +0 -1
  45. package/dist/boundary-BTP1nfG6.js.map +0 -1
  46. package/dist/context-649REFsj.js.map +0 -1
  47. package/dist/dnd-D90jLjLH.js.map +0 -1
  48. package/dist/document-C6bNHl7l.js.map +0 -1
  49. package/dist/use-dynamic-tailwind-DAhKGsY4.js.map +0 -1
@@ -1,18 +1,18 @@
1
- import { C as __toESM, b as DRAGGABLE_ITEMS, f as nanoid, g as BINDING_PROP, m as require_lib, n as createSectionPreviewCache, r as fillSectionIds } from "./document-C6bNHl7l.js";
2
- import { d as replaceSections, o as extractSections, r as cn, s as generateSection, u as preloadScripts } from "./utils-WyxPYZGh.js";
1
+ import { D as fillSectionIds, E as createSectionPreviewCache, I as nanoid, K as __toESM, L as require_lib, U as DRAGGABLE_ITEMS, _ as parseArrayExpression, a as findEditableChildren, c as parseBinding, d as canLosslesslyEvaluateSource, m as extractObjectProperties, n as extract, o as getCurrentValue, p as extractNodeValue, s as getStructuredValue, v as parseValue, z as BINDING_PROP } from "./extract-abHYmNsu.js";
2
+ import { c as generateSection, d as preloadScripts, i as cn, p as replaceSections, s as extractSections } from "./utils-BQ7WL7Jh.js";
3
3
  import { i as usePreview } from "./states-Ci1AvoQ9.js";
4
- import { A as parseValue, D as extractObjectProperties, E as extractNodeValue, S as parseBinding, _ as updateArrayItemValue, b as getCurrentValue, d as duplicateArrayItems, f as moveArrayItem, g as updateArrayItemProperty, h as removeArrayItems, i as replaceIds, k as parseArrayExpression, l as extract, o as update, p as moveArrayItems, r as fillIds, s as getChildrenSignatures, t as validateBindingValue, u as appendArrayItem, v as moveSelectedIndices, x as getStructuredValue, y as findEditableChildren } from "./ast-Bx2Avo4d.js";
5
- import { n as useCompiledModule, r as Frame, t as useDynamicTailwind } from "./use-dynamic-tailwind-DAhKGsY4.js";
6
- import { t as Core } from "./core-D3q5rpuz.js";
7
- import { n as Error$1, t as ErrorBoundary } from "./boundary-BTP1nfG6.js";
4
+ import { _ as moveSelectedIndices, c as appendArrayItem, d as moveArrayItems, g as canStructurallyEditArray, h as updateArrayItemValue, i as replaceIds, l as duplicateArrayItems, m as updateArrayItemProperty, o as update, p as removeArrayItems, r as fillIds, s as getChildrenSignatures, t as validateBindingValue, u as moveArrayItem } from "./ast-CZwpVrJv.js";
5
+ import { i as Frame, n as useCompiledModule, t as useDynamicTailwind } from "./use-dynamic-tailwind-BF8TQ3Yy.js";
6
+ import { t as Core } from "./core-Co8Nlq16.js";
7
+ import { n as Error$1, t as ErrorBoundary } from "./boundary-C90q3YsT.js";
8
8
  import { Children, createContext, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
9
- import { Button, Card, Checkbox, ColorPicker, DatePicker, Drawer, Input, RichTextEditor, Select, Space, Splitter, Toast, Typography, Upload } from "@jbpark/ui-kit";
10
9
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
10
  import { DndContext, DragOverlay, PointerSensor, closestCenter, useDndContext, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
12
11
  import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
13
12
  import { SortableContext, arrayMove, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
13
+ import { Button, Card, Checkbox, ColorPicker, DatePicker, Drawer, Input, RichTextEditor, Select, Space, Splitter, Toast, Typography } from "@jbpark/ui-kit";
14
14
  import { useDebounce, useMultiSelect, useResponsiveSize } from "@jbpark/use-hooks";
15
- import { AlertCircle, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Bell, Bookmark, Calendar, Camera, Check, ChevronDown, ChevronRight, ChevronUp, Clock, Copy, Download, Edit, Eye, Filter, Heart, Home, Image, Info, LayoutGrid, Link, Mail, Map as Map$1, Menu, MessageCircle, Phone, Plus, Search, Settings, Share, ShoppingCart, Star, Trash, Upload as Upload$1, User, X } from "lucide-react";
15
+ import { ArrowDown, ArrowUp, ChevronDown, ChevronUp, Copy, LayoutGrid, Plus, Trash, X } from "lucide-react";
16
16
  import { CSS } from "@dnd-kit/utilities";
17
17
  //#region src/components/dnd/droppable.tsx
18
18
  var import_lib = /* @__PURE__ */ __toESM(require_lib(), 1);
@@ -36,6 +36,13 @@ const Droppable = ({ children, className }) => {
36
36
  });
37
37
  };
38
38
  //#endregion
39
+ //#region src/components/dnd/edit-options.ts
40
+ const toastEditError = (error) => {
41
+ Toast.error(error.title, error.description ? { description: error.description } : void 0);
42
+ };
43
+ const DndEditOptionsContext = createContext({ reportError: toastEditError });
44
+ const useDndEditOptions = () => useContext(DndEditOptionsContext);
45
+ //#endregion
39
46
  //#region src/components/dnd/draggable.tsx
40
47
  const DraggableItem = ({ item, children }) => {
41
48
  const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
@@ -78,8 +85,73 @@ const useDndPalette = () => useDndRegions("useDndPalette()").palette;
78
85
  const useDndPanel = () => useDndRegions("useDndPanel()").panel;
79
86
  const useDndLayout = () => useDndRegions("useDndLayout()");
80
87
  //#endregion
88
+ //#region src/components/dnd/panel-binding.ts
89
+ const readAttribute = (node, name) => node.dataAttributes.find((attribute) => attribute.name === name)?.value;
90
+ const canEditBindingValue = (node, binding) => {
91
+ if (binding.property === "children" || binding.property === "innerText" || binding.property === "innerHTML" || binding.property === "items" || binding.property === "data" || binding.type === "array" || binding.type === "jsx" || binding.type === "richtext") return true;
92
+ const attribute = node.attributes.find((candidate) => candidate.name === binding.property);
93
+ return attribute?.isStringLiteral === true || canLosslesslyEvaluateSource(attribute?.value ?? "");
94
+ };
95
+ const toBindingFields = (binding) => ({
96
+ label: binding.label,
97
+ property: binding.property,
98
+ type: binding.type,
99
+ widget: binding.widget,
100
+ options: binding.options,
101
+ render: binding.render,
102
+ min: binding.min,
103
+ max: binding.max,
104
+ pattern: binding.pattern,
105
+ required: binding.required,
106
+ meta: binding.meta
107
+ });
108
+ const resolveRenderEntry = (render, key) => {
109
+ const entry = render?.[key];
110
+ if (entry && "type" in entry) {
111
+ const leaf = entry;
112
+ return {
113
+ ...leaf,
114
+ label: leaf.label ?? key,
115
+ property: leaf.property ?? key
116
+ };
117
+ }
118
+ return {
119
+ label: key,
120
+ property: key,
121
+ render: entry
122
+ };
123
+ };
124
+ const toPanelBindingData = (node, id, binding) => ({
125
+ ...toBindingFields(binding),
126
+ id,
127
+ value: getStructuredValue(node, binding.property, binding.type),
128
+ rawValue: getCurrentValue(node, binding.property),
129
+ ...!canEditBindingValue(node, binding) && { canEditValue: false }
130
+ });
131
+ const resolvePanelBindings = (node) => {
132
+ const id = readAttribute(node, "data-id");
133
+ const bindingAttr = readAttribute(node, "data-binding");
134
+ if (!id || !bindingAttr) return null;
135
+ const parsed = node.bindings ?? parseBinding(bindingAttr);
136
+ if (!parsed.length) return null;
137
+ return {
138
+ id,
139
+ tagName: node.tagName || "element",
140
+ bindings: parsed.map((binding) => toPanelBindingData(node, id, binding))
141
+ };
142
+ };
143
+ const withPanelCommit = (bindings, commit) => bindings.map((binding) => ({
144
+ ...binding,
145
+ onChange: (value) => commit?.({
146
+ id: binding.id,
147
+ label: binding.label,
148
+ property: binding.property,
149
+ value
150
+ })
151
+ }));
152
+ //#endregion
81
153
  //#region src/components/dnd/panel/bulk-actions-bar.tsx
82
- const BulkActionsBar = ({ count, onDuplicate, onMoveUp, onMoveDown, onDelete, onClear }) => {
154
+ const BulkActionsBar = ({ count, disabled = false, onDuplicate, onMoveUp, onMoveDown, onDelete, onClear }) => {
83
155
  if (count === 0) return null;
84
156
  return /* @__PURE__ */ jsxs("div", {
85
157
  className: "flex items-center justify-between rounded border\n border-blue-200 bg-blue-50 p-2",
@@ -93,18 +165,21 @@ const BulkActionsBar = ({ count, onDuplicate, onMoveUp, onMoveDown, onDelete, on
93
165
  size: "small",
94
166
  icon: /* @__PURE__ */ jsx(Copy, {}),
95
167
  title: "Duplicate selected",
168
+ disabled,
96
169
  onClick: onDuplicate
97
170
  }),
98
171
  /* @__PURE__ */ jsx(Button, {
99
172
  size: "small",
100
173
  icon: /* @__PURE__ */ jsx(ArrowUp, {}),
101
174
  title: "Move selected up",
175
+ disabled,
102
176
  onClick: onMoveUp
103
177
  }),
104
178
  /* @__PURE__ */ jsx(Button, {
105
179
  size: "small",
106
180
  icon: /* @__PURE__ */ jsx(ArrowDown, {}),
107
181
  title: "Move selected down",
182
+ disabled,
108
183
  onClick: onMoveDown
109
184
  }),
110
185
  /* @__PURE__ */ jsx(Button, {
@@ -112,6 +187,7 @@ const BulkActionsBar = ({ count, onDuplicate, onMoveUp, onMoveDown, onDelete, on
112
187
  size: "small",
113
188
  icon: /* @__PURE__ */ jsx(X, {}),
114
189
  title: "Delete selected",
190
+ disabled,
115
191
  onClick: onDelete
116
192
  }),
117
193
  /* @__PURE__ */ jsx(Button, {
@@ -126,58 +202,29 @@ const BulkActionsBar = ({ count, onDuplicate, onMoveUp, onMoveDown, onDelete, on
126
202
  //#endregion
127
203
  //#region src/components/dnd/panel/node.tsx
128
204
  const Node = ({ data, onChange }) => {
129
- const idAttr = data.dataAttributes.find((a) => a.name === "data-id");
130
- const bindingAttr = data.dataAttributes.find((a) => a.name === "data-binding");
131
- if (!idAttr?.value || !bindingAttr?.value) return null;
132
- const dataId = idAttr.value;
133
- const bindings = data.bindings || parseBinding(bindingAttr.value);
134
- if (!bindings.length) return null;
205
+ const source = resolvePanelBindings(data);
206
+ if (!source) return null;
135
207
  return /* @__PURE__ */ jsx("div", {
136
208
  className: "space-y-2 rounded",
137
209
  children: /* @__PURE__ */ jsx("div", {
138
210
  className: "space-y-1",
139
- children: bindings.map((binding) => {
140
- const currentValue = getCurrentValue(data, binding.property);
141
- const structuredValue = getStructuredValue(data, binding.property, binding.type);
142
- return /* @__PURE__ */ jsxs("div", {
143
- className: "space-y-1",
144
- children: [/* @__PURE__ */ jsxs("label", {
145
- className: "block text-xs font-semibold text-gray-700",
146
- children: [binding.label, /* @__PURE__ */ jsxs("span", {
147
- className: "ml-1 text-gray-400",
148
- children: [
149
- "(",
150
- binding.property,
151
- ")"
152
- ]
153
- })]
154
- }), /* @__PURE__ */ jsx(Field, {
155
- binding: {
156
- id: dataId,
157
- label: binding.label,
158
- property: binding.property,
159
- type: binding.type,
160
- widget: binding.widget,
161
- options: binding.options,
162
- render: binding.render,
163
- min: binding.min,
164
- max: binding.max,
165
- pattern: binding.pattern,
166
- required: binding.required,
167
- meta: binding.meta,
168
- value: structuredValue,
169
- rawValue: currentValue,
170
- onChange: (next) => onChange?.({
171
- id: dataId,
172
- label: binding.label,
173
- property: binding.property,
174
- value: next
175
- })
176
- },
177
- onNodeChange: onChange
211
+ children: withPanelCommit(source.bindings, onChange).map((binding) => /* @__PURE__ */ jsxs("div", {
212
+ className: "space-y-1",
213
+ children: [/* @__PURE__ */ jsxs("label", {
214
+ className: "block text-xs font-semibold text-gray-700",
215
+ children: [binding.label, /* @__PURE__ */ jsxs("span", {
216
+ className: "ml-1 text-gray-400",
217
+ children: [
218
+ "(",
219
+ binding.property,
220
+ ")"
221
+ ]
178
222
  })]
179
- }, `${binding.property}-${binding.label}`);
180
- })
223
+ }), /* @__PURE__ */ jsx(Field, {
224
+ binding,
225
+ onNodeChange: onChange
226
+ })]
227
+ }, `${binding.id}-${binding.property}`))
181
228
  })
182
229
  });
183
230
  };
@@ -356,63 +403,7 @@ const Children$1 = ({ value, onChange, onNodeChange }) => {
356
403
  });
357
404
  };
358
405
  //#endregion
359
- //#region src/components/dnd/panel/icon-map.tsx
360
- const ICON_MAP = {
361
- AlertCircle,
362
- ArrowDown,
363
- ArrowLeft,
364
- ArrowRight,
365
- ArrowUp,
366
- Bell,
367
- Bookmark,
368
- Calendar,
369
- Camera,
370
- Check,
371
- ChevronDown,
372
- ChevronRight,
373
- Clock,
374
- Download,
375
- Edit,
376
- Eye,
377
- Filter,
378
- Heart,
379
- Home,
380
- Image,
381
- Info,
382
- Link,
383
- Mail,
384
- Map: Map$1,
385
- Menu,
386
- MessageCircle,
387
- Phone,
388
- Plus,
389
- Search,
390
- Settings,
391
- Share,
392
- ShoppingCart,
393
- Star,
394
- Trash,
395
- Upload: Upload$1,
396
- User,
397
- X
398
- };
399
- const ICON_OPTIONS = Object.entries(ICON_MAP).map(([name, Icon]) => ({
400
- label: /* @__PURE__ */ jsxs("span", {
401
- className: "flex items-center gap-2",
402
- children: [/* @__PURE__ */ jsx(Icon, { size: 14 }), name]
403
- }),
404
- value: name
405
- }));
406
- //#endregion
407
406
  //#region src/components/dnd/panel/use-items-editor.ts
408
- const resolveLeaf = (render, key) => {
409
- const leaf = render?.[key];
410
- return leaf && "type" in leaf ? leaf : null;
411
- };
412
- const resolveMap = (render, key) => {
413
- const leaf = render?.[key];
414
- return leaf && !("type" in leaf) ? leaf : void 0;
415
- };
416
407
  const bindingsInJSX = (source) => {
417
408
  const nodes = extract(source);
418
409
  const container = nodes.find((n) => n.bindings?.some((b) => b.property === "children"));
@@ -512,8 +503,19 @@ const removeIds = (ids, indices) => {
512
503
  };
513
504
  const useItemsEditor = (value, { render, onChange, onNodeChange } = {}) => {
514
505
  const { objectItems, primitiveItems, parseError } = useMemo(() => parseSource(value), [value]);
506
+ const canEditStructure = useMemo(() => canStructurallyEditArray(value), [value]);
507
+ const { reportError } = useDndEditOptions();
508
+ const reportErrorRef = useRef(reportError);
515
509
  useEffect(() => {
516
- if (parseError) Toast.error("Failed to parse items", { description: "Check the console for details." });
510
+ reportErrorRef.current = reportError;
511
+ });
512
+ useEffect(() => {
513
+ if (parseError) reportErrorRef.current({
514
+ type: "parse",
515
+ target: "items",
516
+ title: "Failed to parse items",
517
+ description: "Check the console for details."
518
+ });
517
519
  }, [parseError]);
518
520
  const kind = primitiveItems.length > 0 && objectItems.length === 0 ? "primitive" : "object";
519
521
  const isPrimitive = kind === "primitive";
@@ -528,7 +530,11 @@ const useItemsEditor = (value, { render, onChange, onNodeChange } = {}) => {
528
530
  const selection = useMultiSelect(isPrimitive ? primitiveItems.length : objectItems.length);
529
531
  const commit = (next, nextIds) => {
530
532
  if (next === null) {
531
- Toast.error("Failed to update this item", { description: "The source was preserved. Structural edits require a dense array without spreads; use the code editor for unsupported syntax." });
533
+ reportError({
534
+ type: "items",
535
+ title: "Failed to update this item",
536
+ description: "The source was preserved. Structural edits require a dense array without spreads; use the code editor for unsupported syntax."
537
+ });
532
538
  return false;
533
539
  }
534
540
  const parsed = parseSource(next);
@@ -557,58 +563,37 @@ const useItemsEditor = (value, { render, onChange, onNodeChange } = {}) => {
557
563
  label: `item-${item.index}`,
558
564
  property: item.type,
559
565
  value: item.value ?? "",
560
- rawValue: String(item.value ?? ""),
566
+ rawValue: item.type === "unknown" ? item.source : String(item.value ?? ""),
567
+ canEditValue: canLosslesslyEvaluateSource(item.source),
561
568
  onChange: (next) => commit(updateArrayItemValue(value, item.elementIndex, next))
562
569
  }
563
570
  })) : objectItems.map((item) => {
564
571
  const id = identity.ids[item.index] ?? item.id;
565
572
  const properties = Object.entries(item.editableProperties).map(([key, prop]) => {
566
- const leaf = resolveLeaf(render, key);
573
+ const binding = resolveRenderEntry(render, key);
574
+ const propertySource = value.slice(prop.astNode.start, prop.astNode.end);
567
575
  return {
576
+ ...toBindingFields(binding),
568
577
  id: `item-${id}-${key}`,
569
- label: key,
570
- property: leaf ? leaf.property ?? leaf.type : key,
571
- type: leaf?.type,
572
- render: leaf ? leaf.render : resolveMap(render, key),
578
+ meta: {
579
+ ...binding.meta,
580
+ valueType: prop.type
581
+ },
573
582
  value: parseValue(String(prop.value)),
574
- rawValue: String(prop.value),
575
- meta: { valueType: prop.type },
583
+ rawValue: prop.type === "unknown" ? propertySource : String(prop.value),
584
+ canEditValue: canLosslesslyEvaluateSource(propertySource),
576
585
  onChange: (next) => updateProperty(item.elementIndex, key, next)
577
586
  };
578
587
  });
579
588
  const nested = [...Object.entries(item.jsxBindings).map(([property, nodes]) => ({
580
589
  property,
581
590
  elements: nodes.flatMap((node) => {
582
- const id = node.dataAttributes.find((a) => a.name === "data-id")?.value;
583
- const attr = node.dataAttributes.find((a) => a.name === "data-binding")?.value;
584
- if (!id || !attr) return [];
585
- const parsed = node.bindings ?? parseBinding(attr);
586
- if (!parsed.length) return [];
591
+ const source = resolvePanelBindings(node);
592
+ if (!source) return [];
587
593
  return [{
588
- id,
589
- tagName: node.tagName || "element",
590
- bindings: parsed.map((binding) => ({
591
- id,
592
- label: binding.label,
593
- property: binding.property,
594
- type: binding.type,
595
- widget: binding.widget,
596
- options: binding.options,
597
- render: binding.render,
598
- min: binding.min,
599
- max: binding.max,
600
- pattern: binding.pattern,
601
- required: binding.required,
602
- meta: binding.meta,
603
- value: getStructuredValue(node, binding.property, binding.type),
604
- rawValue: getCurrentValue(node, binding.property),
605
- onChange: (next) => onNodeChange?.({
606
- id,
607
- label: binding.label,
608
- property: binding.property,
609
- value: next
610
- })
611
- }))
594
+ id: source.id,
595
+ tagName: source.tagName,
596
+ bindings: withPanelCommit(source.bindings, onNodeChange)
612
597
  }];
613
598
  })
614
599
  })), ...Object.entries(item.jsxFallbacks).map(([property, code]) => ({
@@ -621,6 +606,7 @@ const useItemsEditor = (value, { render, onChange, onNodeChange } = {}) => {
621
606
  type: "jsx",
622
607
  value: code,
623
608
  rawValue: code,
609
+ canEditValue: true,
624
610
  onChange: (next) => updateProperty(item.elementIndex, property, next)
625
611
  }
626
612
  }))];
@@ -670,6 +656,7 @@ const useItemsEditor = (value, { render, onChange, onNodeChange } = {}) => {
670
656
  if (commit(removeArrayItems(value, elementIndicesOf(selection.selected), kind), removeIds(identity.ids, selection.selected))) selection.clear();
671
657
  }
672
658
  },
659
+ canEditStructure,
673
660
  parseError
674
661
  };
675
662
  };
@@ -732,7 +719,7 @@ const NestedGroup = ({ group, onNodeChange }) => {
732
719
  });
733
720
  };
734
721
  const Items = ({ value, render, onChange, onChildChange }) => {
735
- const { kind, items, selection, actions, parseError } = useItemsEditor(value, {
722
+ const { kind, items, selection, actions, canEditStructure, parseError } = useItemsEditor(value, {
736
723
  render,
737
724
  onChange,
738
725
  onNodeChange: onChildChange
@@ -746,7 +733,7 @@ const Items = ({ value, render, onChange, onChildChange }) => {
746
733
  items.length,
747
734
  ")"
748
735
  ]
749
- }), items.length > 0 && /* @__PURE__ */ jsx(Button, {
736
+ }), items.length > 0 && canEditStructure && /* @__PURE__ */ jsx(Button, {
750
737
  size: "small",
751
738
  icon: /* @__PURE__ */ jsx(Plus, {}),
752
739
  variant: "solid",
@@ -771,6 +758,7 @@ const Items = ({ value, render, onChange, onChildChange }) => {
771
758
  });
772
759
  const bulkBar = /* @__PURE__ */ jsx(BulkActionsBar, {
773
760
  count: selection.selected.size,
761
+ disabled: !canEditStructure,
774
762
  onDuplicate: actions.duplicateSelected,
775
763
  onMoveUp: () => actions.moveSelected("up"),
776
764
  onMoveDown: () => actions.moveSelected("down"),
@@ -783,20 +771,20 @@ const Items = ({ value, render, onChange, onChildChange }) => {
783
771
  /* @__PURE__ */ jsx(Button, {
784
772
  size: "small",
785
773
  icon: /* @__PURE__ */ jsx(ArrowUp, {}),
786
- disabled: item.index === 0,
774
+ disabled: !canEditStructure || item.index === 0,
787
775
  onClick: () => actions.move(item.elementIndex, item.index - 1)
788
776
  }),
789
777
  /* @__PURE__ */ jsx(Button, {
790
778
  size: "small",
791
779
  icon: /* @__PURE__ */ jsx(ArrowDown, {}),
792
- disabled: item.index === items.length - 1,
780
+ disabled: !canEditStructure || item.index === items.length - 1,
793
781
  onClick: () => actions.move(item.elementIndex, item.index + 1)
794
782
  }),
795
783
  /* @__PURE__ */ jsx(Button, {
796
784
  danger: true,
797
785
  size: "small",
798
786
  icon: /* @__PURE__ */ jsx(X, {}),
799
- disabled: items.length <= 1,
787
+ disabled: !canEditStructure || items.length <= 1,
800
788
  onClick: () => actions.remove(item.elementIndex)
801
789
  })
802
790
  ]
@@ -806,15 +794,20 @@ const Items = ({ value, render, onChange, onChildChange }) => {
806
794
  children: [
807
795
  header,
808
796
  bulkBar,
797
+ !canEditStructure && /* @__PURE__ */ jsx("div", {
798
+ className: "rounded border border-dashed border-amber-200 p-3 text-xs\n text-amber-700",
799
+ 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."
800
+ }),
809
801
  items.map((item) => /* @__PURE__ */ jsxs("div", {
810
802
  className: "space-y-2 rounded border border-gray-100 bg-gray-50 p-2",
811
803
  children: [/* @__PURE__ */ jsxs("div", {
812
804
  className: "flex items-center justify-between space-x-1",
813
805
  children: [/* @__PURE__ */ jsx("div", {
814
- onClick: (e) => selection.toggle(item.index, e.shiftKey),
806
+ onClick: (e) => canEditStructure && selection.toggle(item.index, e.shiftKey),
815
807
  className: "inline-flex",
816
808
  children: /* @__PURE__ */ jsx(Checkbox, {
817
809
  checked: selection.isSelected(item.index),
810
+ disabled: !canEditStructure,
818
811
  onChange: () => {}
819
812
  })
820
813
  }), itemControls(item)]
@@ -830,6 +823,10 @@ const Items = ({ value, render, onChange, onChildChange }) => {
830
823
  children: [
831
824
  header,
832
825
  bulkBar,
826
+ !canEditStructure && /* @__PURE__ */ jsx("div", {
827
+ className: "rounded border border-dashed border-amber-200 p-3 text-xs\n text-amber-700",
828
+ 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."
829
+ }),
833
830
  items.map((item) => /* @__PURE__ */ jsxs("div", {
834
831
  className: "space-y-3 rounded border bg-gray-50 p-3",
835
832
  children: [
@@ -838,10 +835,11 @@ const Items = ({ value, render, onChange, onChildChange }) => {
838
835
  children: [/* @__PURE__ */ jsxs("div", {
839
836
  className: "flex items-center space-x-2",
840
837
  children: [/* @__PURE__ */ jsx("div", {
841
- onClick: (e) => selection.toggle(item.index, e.shiftKey),
838
+ onClick: (e) => canEditStructure && selection.toggle(item.index, e.shiftKey),
842
839
  className: "inline-flex",
843
840
  children: /* @__PURE__ */ jsx(Checkbox, {
844
841
  checked: selection.isSelected(item.index),
842
+ disabled: !canEditStructure,
845
843
  onChange: () => {}
846
844
  })
847
845
  }), /* @__PURE__ */ jsxs("div", {
@@ -976,7 +974,7 @@ const ColorPickerField = ({ value, onChange }) => {
976
974
  }
977
975
  });
978
976
  };
979
- const Field = ({ binding, onNodeChange }) => {
977
+ const BuiltinField = ({ binding, onNodeChange }) => {
980
978
  const { id, value, rawValue, onChange } = binding;
981
979
  const [validationError, setValidationError] = useState(null);
982
980
  const [text, setText] = useState(rawValue);
@@ -985,6 +983,17 @@ const Field = ({ binding, onNodeChange }) => {
985
983
  setPrevRawValue(rawValue);
986
984
  setText(rawValue);
987
985
  }
986
+ if (binding.canEditValue === false) return /* @__PURE__ */ jsxs("div", {
987
+ className: "space-y-1 rounded border border-dashed border-amber-200 p-3\n text-xs text-amber-700",
988
+ children: [
989
+ /* @__PURE__ */ jsx("div", { children: "This expression is preserved but is not editable here." }),
990
+ /* @__PURE__ */ jsx("code", {
991
+ className: "block overflow-x-auto text-amber-800",
992
+ children: rawValue
993
+ }),
994
+ /* @__PURE__ */ jsx("div", { children: "Use the code editor to change it." })
995
+ ]
996
+ });
988
997
  const commitIfChanged = (next) => {
989
998
  if (next !== (typeof next === "string" ? rawValue : value)) onChange(next);
990
999
  };
@@ -1016,30 +1025,30 @@ const Field = ({ binding, onNodeChange }) => {
1016
1025
  const objectValue = value;
1017
1026
  return /* @__PURE__ */ jsx("div", {
1018
1027
  className: "space-y-2 rounded border border-gray-200 bg-gray-50 p-2",
1019
- children: Object.entries(objectValue).map(([key, val]) => /* @__PURE__ */ jsxs("div", {
1020
- className: "space-y-1",
1021
- children: [/* @__PURE__ */ jsx("label", {
1022
- className: "block text-xs font-medium text-gray-600",
1023
- children: key
1024
- }), /* @__PURE__ */ jsx(Field, {
1025
- binding: {
1026
- id,
1027
- label: key,
1028
- property: binding.render?.[key] && "type" in binding.render[key] ? binding.render[key].type : key,
1029
- type: binding.render?.[key] && "type" in binding.render[key] ? binding.render[key].type : void 0,
1030
- render: binding.render?.[key] && !("type" in binding.render[key]) ? binding.render[key] : void 0,
1031
- value: val,
1032
- rawValue: typeof val === "object" && val !== null ? JSON.stringify(val) : String(val),
1033
- onChange: (next) => {
1034
- onChange({
1035
- ...objectValue,
1036
- [key]: next
1037
- });
1038
- }
1039
- },
1040
- onNodeChange
1041
- })]
1042
- }, key))
1028
+ children: Object.entries(objectValue).map(([key, val]) => {
1029
+ const nested = resolveRenderEntry(binding.render, key);
1030
+ return /* @__PURE__ */ jsxs("div", {
1031
+ className: "space-y-1",
1032
+ children: [/* @__PURE__ */ jsx("label", {
1033
+ className: "block text-xs font-medium text-gray-600",
1034
+ children: nested.label
1035
+ }), /* @__PURE__ */ jsx(Field, {
1036
+ binding: {
1037
+ ...toBindingFields(nested),
1038
+ id,
1039
+ value: val,
1040
+ rawValue: typeof val === "object" && val !== null ? JSON.stringify(val) : String(val),
1041
+ onChange: (next) => {
1042
+ onChange({
1043
+ ...objectValue,
1044
+ [key]: next
1045
+ });
1046
+ }
1047
+ },
1048
+ onNodeChange
1049
+ })]
1050
+ }, key);
1051
+ })
1043
1052
  });
1044
1053
  }
1045
1054
  if (binding.type === "boolean" || typeof value === "boolean") return /* @__PURE__ */ jsx(Checkbox, {
@@ -1093,61 +1102,6 @@ const Field = ({ binding, onNodeChange }) => {
1093
1102
  className: "mt-1 text-xs text-red-500",
1094
1103
  children: validationError
1095
1104
  })] });
1096
- if (binding.widget === "icon-picker" || binding.type === "icon-picker") {
1097
- const SelectedIcon = ICON_MAP[stringValue];
1098
- return /* @__PURE__ */ jsxs("div", {
1099
- className: "flex items-center gap-2",
1100
- children: [/* @__PURE__ */ jsx(Select, {
1101
- value: stringValue,
1102
- options: ICON_OPTIONS,
1103
- onChange: commitIfChanged
1104
- }), SelectedIcon && /* @__PURE__ */ jsx(SelectedIcon, {
1105
- size: 18,
1106
- className: "shrink-0"
1107
- })]
1108
- });
1109
- }
1110
- if (binding.widget === "asset-picker" || binding.type === "asset-picker") {
1111
- const defaultUploadValue = stringValue ? [{
1112
- uid: "current",
1113
- name: stringValue.split("/").pop() || "asset",
1114
- url: stringValue
1115
- }] : [];
1116
- return /* @__PURE__ */ jsxs("div", {
1117
- className: "space-y-2",
1118
- children: [
1119
- /* @__PURE__ */ jsx(Input, {
1120
- value: text,
1121
- onChange: (e) => setText(e.target.value),
1122
- placeholder: "Enter an image URL",
1123
- onBlur: (e) => {
1124
- const next = e.target.value.trim();
1125
- const result = validateBindingValue(binding, next);
1126
- if (!result.valid) {
1127
- setValidationError(result.message ?? "Invalid value.");
1128
- return;
1129
- }
1130
- setValidationError(null);
1131
- commitIfChanged(next);
1132
- }
1133
- }),
1134
- /* @__PURE__ */ jsx(Upload, {
1135
- multiple: false,
1136
- maxCount: 1,
1137
- accept: "image/*",
1138
- defaultValue: defaultUploadValue,
1139
- onChange: (files) => {
1140
- const next = files[0]?.url ?? "";
1141
- commitIfChanged(next);
1142
- }
1143
- }),
1144
- validationError && /* @__PURE__ */ jsx("p", {
1145
- className: "mt-1 text-xs text-red-500",
1146
- children: validationError
1147
- })
1148
- ]
1149
- });
1150
- }
1151
1105
  if (binding.type === "number" || typeof value === "number") return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Input, {
1152
1106
  type: "number",
1153
1107
  value: text,
@@ -1188,6 +1142,13 @@ const Field = ({ binding, onNodeChange }) => {
1188
1142
  children: validationError
1189
1143
  })] });
1190
1144
  };
1145
+ const Field = (props) => {
1146
+ const { renderField } = useDndEditOptions();
1147
+ const builtin = /* @__PURE__ */ jsx(BuiltinField, { ...props });
1148
+ if (!renderField) return builtin;
1149
+ const custom = renderField(props, builtin);
1150
+ return custom === void 0 ? builtin : /* @__PURE__ */ jsx(Fragment, { children: custom });
1151
+ };
1191
1152
  //#endregion
1192
1153
  //#region src/components/dnd/panel/field-group.tsx
1193
1154
  const FieldGroup = ({ bindings, onNodeChange }) => /* @__PURE__ */ jsx("div", {
@@ -1379,16 +1340,59 @@ const Layout = ({ palette, panel }) => {
1379
1340
  ] });
1380
1341
  };
1381
1342
  //#endregion
1343
+ //#region src/components/dnd/section-fallback-context.ts
1344
+ const SectionFallbackContext = createContext(void 0);
1345
+ //#endregion
1346
+ //#region src/components/dnd/section-fallback.tsx
1347
+ const ConsumerFallback = ({ render, args, builtin }) => {
1348
+ const node = render(args);
1349
+ return node === void 0 ? builtin : /* @__PURE__ */ jsx(Fragment, { children: node });
1350
+ };
1351
+ const SectionFallback = ({ args, builtin }) => {
1352
+ const render = useContext(SectionFallbackContext);
1353
+ if (!render) return builtin;
1354
+ return /* @__PURE__ */ jsx(ErrorBoundary, {
1355
+ fallback: () => builtin,
1356
+ children: /* @__PURE__ */ jsx(ConsumerFallback, {
1357
+ render,
1358
+ args,
1359
+ builtin
1360
+ })
1361
+ });
1362
+ };
1363
+ //#endregion
1382
1364
  //#region src/components/dnd/renderer.tsx
1383
- const Renderer = ({ preview, headers, modules, frame, dynamicTailwind = false, provider }) => {
1384
- const module = useCompiledModule(preview, modules);
1385
- const { ref: wrapperRef, css: dynamicCSS } = useDynamicTailwind(preview, dynamicTailwind);
1365
+ const Renderer = ({ preview, sectionId = "", sectionName = "", sectionCode = preview, forceFallback = false, headers, modules, frame, dynamicTailwind = false, provider }) => {
1366
+ const module = useCompiledModule(forceFallback ? "" : preview, modules);
1367
+ const section = {
1368
+ id: sectionId,
1369
+ name: sectionName,
1370
+ code: sectionCode
1371
+ };
1372
+ const { ref: wrapperRef, css: dynamicCSS } = useDynamicTailwind(preview, dynamicTailwind && !forceFallback);
1386
1373
  const renderProvider = (component) => {
1387
1374
  return provider ? provider(component) : component;
1388
1375
  };
1389
- if (module?.error) return /* @__PURE__ */ jsx(Error$1, {
1390
- message: module.error,
1391
- title: "Compile Error"
1376
+ if (forceFallback) return /* @__PURE__ */ jsx(SectionFallback, {
1377
+ args: {
1378
+ section,
1379
+ reason: "forced"
1380
+ },
1381
+ builtin: /* @__PURE__ */ jsx(Error$1, {
1382
+ message: "This section is not rendered in this editor.",
1383
+ title: "Section Unavailable"
1384
+ })
1385
+ });
1386
+ if (module?.error) return /* @__PURE__ */ jsx(SectionFallback, {
1387
+ args: {
1388
+ section,
1389
+ reason: "compile",
1390
+ message: module.error
1391
+ },
1392
+ builtin: /* @__PURE__ */ jsx(Error$1, {
1393
+ message: module.error,
1394
+ title: "Compile Error"
1395
+ })
1392
1396
  });
1393
1397
  const Component = module?.exports?.default;
1394
1398
  if (!Component) return null;
@@ -1401,6 +1405,18 @@ const Renderer = ({ preview, headers, modules, frame, dynamicTailwind = false, p
1401
1405
  "data-editor-mode": true,
1402
1406
  children: /* @__PURE__ */ jsx(ErrorBoundary, {
1403
1407
  resetKeys: [preview],
1408
+ fallback: (message, reset) => /* @__PURE__ */ jsx(SectionFallback, {
1409
+ args: {
1410
+ section,
1411
+ reason: "runtime",
1412
+ message
1413
+ },
1414
+ builtin: /* @__PURE__ */ jsx(Error$1, {
1415
+ message,
1416
+ onReset: reset,
1417
+ title: "Rendering Error"
1418
+ })
1419
+ }),
1404
1420
  children: renderProvider(/* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Component, {
1405
1421
  headers,
1406
1422
  container
@@ -1455,7 +1471,7 @@ const Sortable = ({ id, children, selected, onClick, onDelete: _onDelete, onCopy
1455
1471
  };
1456
1472
  //#endregion
1457
1473
  //#region src/components/dnd/overlay.tsx
1458
- const Overlay = ({ sections, renderProps }) => {
1474
+ const Overlay = ({ sections, isForced, renderProps }) => {
1459
1475
  const { active } = useDndContext();
1460
1476
  if (!active) return null;
1461
1477
  if (active.data.current?.type === "new-item") {
@@ -1470,6 +1486,10 @@ const Overlay = ({ sections, renderProps }) => {
1470
1486
  name: section.name,
1471
1487
  children: /* @__PURE__ */ jsx(renderer_default, {
1472
1488
  preview,
1489
+ sectionId: section.id,
1490
+ sectionName: section.name,
1491
+ sectionCode: section.code,
1492
+ forceFallback: isForced?.(section) ?? false,
1473
1493
  modules: renderProps.modules,
1474
1494
  frame: renderProps.frame,
1475
1495
  dynamicTailwind: renderProps.dynamicTailwind
@@ -1586,6 +1606,10 @@ const describeUpdateFailure = (failure, label) => {
1586
1606
  title: `Failed to update "${label}"`,
1587
1607
  description: "The target element could not be found in this section."
1588
1608
  };
1609
+ case "unsupported-syntax": return {
1610
+ title: `Cannot edit "${label}" in the panel`,
1611
+ description: `The "${failure.property}" expression was preserved. Change it in the code editor instead.`
1612
+ };
1589
1613
  case "parse-error": return {
1590
1614
  title: `Failed to update "${label}"`,
1591
1615
  description: failure.error instanceof Error ? failure.error.message : "Check the console for details."
@@ -1598,11 +1622,19 @@ const conditionalModifiers = (args) => {
1598
1622
  if (active?.data.current?.type === "new-item") return args.transform;
1599
1623
  return restrictToVerticalAxis(args);
1600
1624
  };
1601
- const Dnd$1 = ({ value: _value, props, modules = {}, onChange: _onChange, className, items = [], frame, dynamicTailwind = false, provider, children, ...restProps }) => {
1625
+ const Dnd$1 = ({ value: _value, props, modules = {}, onChange: _onChange, className, items = [], frame, dynamicTailwind = false, provider, renderField, onEditError, renderSectionFallback, shouldForceSectionFallback, children, ...restProps }) => {
1602
1626
  const [mobilePaletteOpen, setMobilePaletteOpen] = useState(false);
1603
1627
  const { breakpoint } = useResponsiveSize();
1604
1628
  const isMobile = breakpoint.current === "xs" || breakpoint.current === "sm";
1605
1629
  const { code } = usePreview();
1630
+ const isForced = (section) => {
1631
+ try {
1632
+ return shouldForceSectionFallback?.(section) === true;
1633
+ } catch (error) {
1634
+ console.error("shouldForceSectionFallback threw", error);
1635
+ return false;
1636
+ }
1637
+ };
1606
1638
  const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 10 } }));
1607
1639
  const value = _value === void 0 ? code : _value;
1608
1640
  const { sections, previews, selectedId, selectedItem, selectedIndex, select, clearSelection, add: addItem, remove: onDelete, copy: onCopy, move: moveSection, reorder, patch } = useSectionDocument(value, _onChange);
@@ -1629,32 +1661,49 @@ const Dnd$1 = ({ value: _value, props, modules = {}, onChange: _onChange, classN
1629
1661
  if (!selectedCode) return {
1630
1662
  fields: [],
1631
1663
  updatedCode: "",
1632
- parseError: false
1664
+ parseError: null
1633
1665
  };
1634
1666
  try {
1635
1667
  const updated = fillIds(selectedCode);
1636
1668
  return {
1637
1669
  fields: extract(updated).filter((node) => node.tagName !== "section"),
1638
1670
  updatedCode: updated !== selectedCode ? updated : selectedCode,
1639
- parseError: false
1671
+ parseError: null
1640
1672
  };
1641
1673
  } catch (e) {
1642
1674
  console.warn("⚠️ Parsing error", e);
1643
1675
  return {
1644
1676
  fields: [],
1645
1677
  updatedCode: "",
1646
- parseError: true
1678
+ parseError: { error: e }
1647
1679
  };
1648
1680
  }
1649
1681
  }, [selectedCode]);
1682
+ const reportError = onEditError ?? toastEditError;
1683
+ const reportErrorRef = useRef(reportError);
1684
+ useEffect(() => {
1685
+ reportErrorRef.current = reportError;
1686
+ });
1650
1687
  useEffect(() => {
1651
- if (parseError) Toast.error("Failed to parse this section", { description: "Check the console for details." });
1688
+ if (parseError) reportErrorRef.current({
1689
+ type: "parse",
1690
+ target: "section",
1691
+ error: parseError.error,
1692
+ title: "Failed to parse this section",
1693
+ description: "Check the console for details."
1694
+ });
1652
1695
  }, [parseError]);
1653
1696
  const onFieldChange = ({ id, label, property, value: fieldValue }) => {
1654
1697
  const result = update(updatedCode, id, label, fieldValue, property);
1655
1698
  if (!result.success) {
1656
- const { title, description } = describeUpdateFailure(result.failure, label);
1657
- Toast.error(title, description ? { description } : void 0);
1699
+ reportError({
1700
+ type: "update",
1701
+ id,
1702
+ label,
1703
+ property,
1704
+ failure: result.failure,
1705
+ ...describeUpdateFailure(result.failure, label)
1706
+ });
1658
1707
  return;
1659
1708
  }
1660
1709
  if (selectedItem) onChange({
@@ -1662,37 +1711,8 @@ const Dnd$1 = ({ value: _value, props, modules = {}, onChange: _onChange, classN
1662
1711
  code: result.code
1663
1712
  });
1664
1713
  };
1665
- const bindings = useMemo(() => {
1666
- return fields.flatMap((node) => {
1667
- const dataId = node.dataAttributes.find((a) => a.name === "data-id")?.value;
1668
- const bindingAttr = node.dataAttributes.find((a) => a.name === "data-binding")?.value;
1669
- if (!dataId || !bindingAttr) return [];
1670
- return (node.bindings ?? parseBinding(bindingAttr)).map((binding) => ({
1671
- id: dataId,
1672
- label: binding.label,
1673
- property: binding.property,
1674
- type: binding.type,
1675
- widget: binding.widget,
1676
- options: binding.options,
1677
- render: binding.render,
1678
- min: binding.min,
1679
- max: binding.max,
1680
- pattern: binding.pattern,
1681
- required: binding.required,
1682
- meta: binding.meta,
1683
- value: getStructuredValue(node, binding.property, binding.type),
1684
- rawValue: getCurrentValue(node, binding.property)
1685
- }));
1686
- });
1687
- }, [fields]).map((field) => ({
1688
- ...field,
1689
- onChange: (value) => onFieldChange({
1690
- id: field.id,
1691
- label: field.label,
1692
- property: field.property,
1693
- value
1694
- })
1695
- }));
1714
+ const bindingFields = useMemo(() => fields.flatMap((node) => resolvePanelBindings(node)?.bindings ?? []), [fields]);
1715
+ const bindings = withPanelCommit(bindingFields, onFieldChange);
1696
1716
  useEffect(() => {
1697
1717
  if (frame?.scripts?.length) preloadScripts(frame.scripts);
1698
1718
  }, [frame?.scripts]);
@@ -1735,6 +1755,10 @@ const Dnd$1 = ({ value: _value, props, modules = {}, onChange: _onChange, classN
1735
1755
  onCopy,
1736
1756
  children: /* @__PURE__ */ jsx(renderer_default, {
1737
1757
  preview: previews[index],
1758
+ sectionId: section.id,
1759
+ sectionName: section.name,
1760
+ sectionCode: section.code,
1761
+ forceFallback: isForced(section),
1738
1762
  modules,
1739
1763
  frame,
1740
1764
  dynamicTailwind,
@@ -1744,40 +1768,50 @@ const Dnd$1 = ({ value: _value, props, modules = {}, onChange: _onChange, classN
1744
1768
  }, section.id))
1745
1769
  })
1746
1770
  }) });
1747
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(DndContext, {
1748
- sensors,
1749
- collisionDetection: closestCenter,
1750
- modifiers: [conditionalModifiers],
1751
- onDragStart,
1752
- onDragOver,
1753
- onDragEnd,
1754
- children: [/* @__PURE__ */ jsx("div", {
1755
- className: cn("relative flex h-full w-full", className),
1756
- ...restProps,
1757
- children: /* @__PURE__ */ jsx(DndRegionContext.Provider, {
1758
- value: {
1759
- palette,
1760
- panel,
1761
- canvas,
1762
- isMobile,
1763
- selectedId,
1764
- clearSelection,
1765
- paletteOpen: mobilePaletteOpen,
1766
- setPaletteOpen: setMobilePaletteOpen
1767
- },
1768
- children: Children.toArray(children).length ? children : /* @__PURE__ */ jsx(Layout, {})
1769
- })
1770
- }), /* @__PURE__ */ jsx(DragOverlay, { children: /* @__PURE__ */ jsx(Overlay, {
1771
- sections,
1772
- renderProps: {
1773
- fullCode: value,
1774
- modules,
1775
- frame,
1776
- dynamicTailwind,
1777
- ...props
1778
- }
1779
- }) })]
1780
- }) });
1771
+ return /* @__PURE__ */ jsx(SectionFallbackContext.Provider, {
1772
+ value: renderSectionFallback,
1773
+ children: /* @__PURE__ */ jsxs(DndContext, {
1774
+ sensors,
1775
+ collisionDetection: closestCenter,
1776
+ modifiers: [conditionalModifiers],
1777
+ onDragStart,
1778
+ onDragOver,
1779
+ onDragEnd,
1780
+ children: [/* @__PURE__ */ jsx("div", {
1781
+ className: cn("relative flex h-full w-full", className),
1782
+ ...restProps,
1783
+ children: /* @__PURE__ */ jsx(DndEditOptionsContext.Provider, {
1784
+ value: {
1785
+ renderField,
1786
+ reportError
1787
+ },
1788
+ children: /* @__PURE__ */ jsx(DndRegionContext.Provider, {
1789
+ value: {
1790
+ palette,
1791
+ panel,
1792
+ canvas,
1793
+ isMobile,
1794
+ selectedId,
1795
+ clearSelection,
1796
+ paletteOpen: mobilePaletteOpen,
1797
+ setPaletteOpen: setMobilePaletteOpen
1798
+ },
1799
+ children: Children.toArray(children).length ? children : /* @__PURE__ */ jsx(Layout, {})
1800
+ })
1801
+ })
1802
+ }), /* @__PURE__ */ jsx(DragOverlay, { children: /* @__PURE__ */ jsx(Overlay, {
1803
+ sections,
1804
+ isForced,
1805
+ renderProps: {
1806
+ fullCode: value,
1807
+ modules,
1808
+ frame,
1809
+ dynamicTailwind,
1810
+ ...props
1811
+ }
1812
+ }) })]
1813
+ })
1814
+ });
1781
1815
  };
1782
1816
  //#endregion
1783
1817
  //#region src/components/dnd/index.ts
@@ -1789,6 +1823,6 @@ Dnd.Canvas = Canvas;
1789
1823
  Dnd.Panel = Panel;
1790
1824
  Dnd.Layout = Layout;
1791
1825
  //#endregion
1792
- export { Panel as a, ICON_MAP as c, useDndLayout as d, useDndPalette as f, Palette as i, ICON_OPTIONS as l, DraggableItem as m, Canvas as n, Field as o, useDndPanel as p, Layout as r, useItemsEditor as s, Dnd as t, useChildrenEditor as u };
1826
+ export { Panel as a, useChildrenEditor as c, useDndPanel as d, DraggableItem as f, Palette as i, useDndLayout as l, Canvas as n, Field as o, Layout as r, useItemsEditor as s, Dnd as t, useDndPalette as u };
1793
1827
 
1794
- //# sourceMappingURL=dnd-D90jLjLH.js.map
1828
+ //# sourceMappingURL=dnd-ClnGRNaY.js.map