@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.
- package/dist/ast-CZwpVrJv.js +851 -0
- package/dist/ast-CZwpVrJv.js.map +1 -0
- package/dist/{boundary-BTP1nfG6.js → boundary-C90q3YsT.js} +8 -7
- package/dist/boundary-C90q3YsT.js.map +1 -0
- package/dist/{context-649REFsj.js → context-Y-M9fViD.js} +4 -8
- package/dist/context-Y-M9fViD.js.map +1 -0
- package/dist/{core-D3q5rpuz.js → core-Co8Nlq16.js} +2 -2
- package/dist/{core-D3q5rpuz.js.map → core-Co8Nlq16.js.map} +1 -1
- package/dist/dnd/index.d.ts +2 -2
- package/dist/dnd/index.js +2 -2
- package/dist/{dnd-D90jLjLH.js → dnd-ClnGRNaY.js} +353 -319
- package/dist/dnd-ClnGRNaY.js.map +1 -0
- package/dist/editor/index.js +2 -2
- package/dist/{editor-LzqHe_-F.js → editor-COKGtmfE.js} +3 -3
- package/dist/{editor-LzqHe_-F.js.map → editor-COKGtmfE.js.map} +1 -1
- package/dist/error/index.d.ts +1 -1
- package/dist/error/index.js +2 -2
- package/dist/{error-CO0EbMlA.js → error-o0SBwtTv.js} +2 -2
- package/dist/{error-CO0EbMlA.js.map → error-o0SBwtTv.js.map} +1 -1
- package/dist/{document-C6bNHl7l.js → extract-abHYmNsu.js} +927 -42
- package/dist/extract-abHYmNsu.js.map +1 -0
- package/dist/{index-DxbG789f.d.ts → index-B_p74BRM.d.ts} +29 -14
- package/dist/{index-CCynrS6c.d.ts → index-DNNj_0ba.d.ts} +3 -2
- package/dist/{index-lgHdCda5.d.ts → index-DQkL37eL.d.ts} +10 -2
- package/dist/{index-DswWDEXZ.d.ts → index-Doh4VTXr.d.ts} +65 -35
- package/dist/index.d.ts +6 -6
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/preview/index.d.ts +2 -2
- package/dist/preview/index.js +3 -2
- package/dist/{preview-CWT0lgwq.js → preview-DKyKKcu7.js} +4 -4
- package/dist/{preview-CWT0lgwq.js.map → preview-DKyKKcu7.js.map} +1 -1
- package/dist/provider/index.js +1 -1
- package/dist/{use-dynamic-tailwind-DAhKGsY4.js → use-dynamic-tailwind-BF8TQ3Yy.js} +83 -27
- package/dist/use-dynamic-tailwind-BF8TQ3Yy.js.map +1 -0
- package/dist/utils/ast/index.d.ts +2 -2
- package/dist/utils/ast/index.js +3 -3
- package/dist/utils/index.d.ts +4 -7
- package/dist/utils/index.js +3 -3
- package/dist/{utils-WyxPYZGh.js → utils-BQ7WL7Jh.js} +33 -16
- package/dist/{utils-WyxPYZGh.js.map → utils-BQ7WL7Jh.js.map} +1 -1
- package/package.json +3 -1
- package/dist/ast-Bx2Avo4d.js +0 -1530
- package/dist/ast-Bx2Avo4d.js.map +0 -1
- package/dist/boundary-BTP1nfG6.js.map +0 -1
- package/dist/context-649REFsj.js.map +0 -1
- package/dist/dnd-D90jLjLH.js.map +0 -1
- package/dist/document-C6bNHl7l.js.map +0 -1
- package/dist/use-dynamic-tailwind-DAhKGsY4.js.map +0 -1
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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 {
|
|
5
|
-
import {
|
|
6
|
-
import { t as Core } from "./core-
|
|
7
|
-
import { n as Error$1, t as ErrorBoundary } from "./boundary-
|
|
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 {
|
|
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
|
|
130
|
-
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
},
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
578
|
+
meta: {
|
|
579
|
+
...binding.meta,
|
|
580
|
+
valueType: prop.type
|
|
581
|
+
},
|
|
573
582
|
value: parseValue(String(prop.value)),
|
|
574
|
-
rawValue: String(prop.value),
|
|
575
|
-
|
|
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
|
|
583
|
-
|
|
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:
|
|
590
|
-
bindings:
|
|
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
|
|
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]) =>
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
className: "
|
|
1023
|
-
children:
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
})
|
|
1042
|
-
}
|
|
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
|
|
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 (
|
|
1390
|
-
|
|
1391
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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)
|
|
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
|
-
|
|
1657
|
-
|
|
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
|
|
1666
|
-
|
|
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(
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
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,
|
|
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-
|
|
1828
|
+
//# sourceMappingURL=dnd-ClnGRNaY.js.map
|