@jbpark/live-editor 1.8.0 → 1.9.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/README.ko.md +12 -9
- package/README.md +12 -9
- package/dist/index.d.mts +49 -4
- package/dist/index.mjs +235 -191
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
9
9
|
import { DndContext, DragOverlay, PointerSensor, closestCenter, useDndContext, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
|
|
10
10
|
import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
|
|
11
11
|
import { SortableContext, arrayMove, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
|
12
|
-
import {
|
|
12
|
+
import { useDebouncedValue, useEventListener, useMultiSelect, useMutationObserver, useResizeObserver, useResponsiveSize } from "@jbpark/use-hooks";
|
|
13
13
|
import { AlertCircle, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Bell, Bookmark, Calendar, Camera, Check, ChevronDown, ChevronRight, 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";
|
|
14
14
|
import { v4 } from "uuid";
|
|
15
15
|
import { createPortal } from "react-dom";
|
|
@@ -26,41 +26,45 @@ import { EditorContent, useEditor } from "@tiptap/react";
|
|
|
26
26
|
import StarterKit from "@tiptap/starter-kit";
|
|
27
27
|
|
|
28
28
|
//#region src/components/context/states.ts
|
|
29
|
-
const PreviewContext = createContext(
|
|
30
|
-
|
|
31
|
-
setCode: () => {}
|
|
32
|
-
});
|
|
33
|
-
const ErrorContext = createContext({
|
|
34
|
-
error: null,
|
|
35
|
-
setError: () => {}
|
|
36
|
-
});
|
|
29
|
+
const PreviewContext = createContext(void 0);
|
|
30
|
+
const ErrorContext = createContext(void 0);
|
|
37
31
|
const usePreview = () => {
|
|
38
|
-
|
|
32
|
+
const context = useContext(PreviewContext);
|
|
33
|
+
if (context === void 0) throw new Error("usePreview must be used within <Live> (ContextProvider)");
|
|
34
|
+
return context;
|
|
39
35
|
};
|
|
40
36
|
const useError = () => {
|
|
41
|
-
|
|
37
|
+
const context = useContext(ErrorContext);
|
|
38
|
+
if (context === void 0) throw new Error("useError must be used within <Live> (ContextProvider)");
|
|
39
|
+
return context;
|
|
42
40
|
};
|
|
43
41
|
|
|
44
42
|
//#endregion
|
|
45
43
|
//#region src/components/context/context.tsx
|
|
46
44
|
const ContextProvider = ({ children }) => {
|
|
47
|
-
const [code,
|
|
45
|
+
const [code, setCodeState] = useState(DEFAULT_TEMPLATE);
|
|
48
46
|
const [error, setError] = useState(null);
|
|
47
|
+
const setCode = useCallback((next) => {
|
|
48
|
+
setError(null);
|
|
49
|
+
setCodeState(next);
|
|
50
|
+
}, []);
|
|
49
51
|
useEffect(() => {
|
|
50
52
|
return () => {
|
|
51
53
|
clearCompilationCache();
|
|
52
54
|
};
|
|
53
55
|
}, []);
|
|
56
|
+
const previewValue = useMemo(() => ({
|
|
57
|
+
code,
|
|
58
|
+
setCode
|
|
59
|
+
}), [code, setCode]);
|
|
60
|
+
const errorValue = useMemo(() => ({
|
|
61
|
+
error,
|
|
62
|
+
setError
|
|
63
|
+
}), [error, setError]);
|
|
54
64
|
return /* @__PURE__ */ jsx(PreviewContext.Provider, {
|
|
55
|
-
value:
|
|
56
|
-
code,
|
|
57
|
-
setCode
|
|
58
|
-
},
|
|
65
|
+
value: previewValue,
|
|
59
66
|
children: /* @__PURE__ */ jsx(ErrorContext.Provider, {
|
|
60
|
-
value:
|
|
61
|
-
error,
|
|
62
|
-
setError
|
|
63
|
-
},
|
|
67
|
+
value: errorValue,
|
|
64
68
|
children
|
|
65
69
|
})
|
|
66
70
|
});
|
|
@@ -72,7 +76,9 @@ const EMPTY_STRING_ARRAY = [];
|
|
|
72
76
|
const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_STRING_ARRAY, styles = EMPTY_STRING_ARRAY, stylesheets = EMPTY_STRING_ARRAY, autoHeight = false, syncStyle = false, children, onLoaded, ...props }) => {
|
|
73
77
|
const iframeRef = useRef(null);
|
|
74
78
|
const [mountNode, setMountNode] = useState(null);
|
|
75
|
-
const
|
|
79
|
+
const loadedScriptsRef = useRef(/* @__PURE__ */ new Set());
|
|
80
|
+
const prevStyleCountRef = useRef(0);
|
|
81
|
+
const prevStylesheetCountRef = useRef(0);
|
|
76
82
|
const shouldAutoHeight = autoHeight && style.height == null;
|
|
77
83
|
const styleManagerRef = useRef({
|
|
78
84
|
copiedLinks: /* @__PURE__ */ new Set(),
|
|
@@ -113,6 +119,21 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
113
119
|
doc.head.appendChild(fragment);
|
|
114
120
|
}
|
|
115
121
|
}, [syncStyle]);
|
|
122
|
+
const applyStyleTimeoutRef = useRef(void 0);
|
|
123
|
+
const debouncedApplyStyle = useCallback(() => {
|
|
124
|
+
clearTimeout(applyStyleTimeoutRef.current);
|
|
125
|
+
applyStyleTimeoutRef.current = window.setTimeout(applyStyle, 50);
|
|
126
|
+
}, [applyStyle]);
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
return () => clearTimeout(applyStyleTimeoutRef.current);
|
|
129
|
+
}, []);
|
|
130
|
+
useMutationObserver(document.head, debouncedApplyStyle, {
|
|
131
|
+
enabled: syncStyle,
|
|
132
|
+
childList: true,
|
|
133
|
+
subtree: true,
|
|
134
|
+
attributes: true,
|
|
135
|
+
attributeFilter: ["href"]
|
|
136
|
+
});
|
|
116
137
|
useEffect(() => {
|
|
117
138
|
const $iframe = iframeRef.current;
|
|
118
139
|
if (!$iframe) return;
|
|
@@ -129,9 +150,10 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
129
150
|
}
|
|
130
151
|
setMountNode(node);
|
|
131
152
|
applyStyle();
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
153
|
+
const pendingScripts = scripts.filter((src) => !loadedScriptsRef.current.has(src));
|
|
154
|
+
if (pendingScripts.length) {
|
|
155
|
+
pendingScripts.forEach((src) => loadedScriptsRef.current.add(src));
|
|
156
|
+
Promise.all(pendingScripts.map(getCachedScriptBlob)).then((blobUrls) => {
|
|
135
157
|
if (!doc.head) return;
|
|
136
158
|
const fragment = doc.createDocumentFragment();
|
|
137
159
|
blobUrls.forEach((blobUrl) => {
|
|
@@ -145,28 +167,11 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
145
167
|
onLoaded?.();
|
|
146
168
|
};
|
|
147
169
|
$iframe.addEventListener("load", onLoad);
|
|
148
|
-
let timeoutId;
|
|
149
|
-
let observer = null;
|
|
150
|
-
if (syncStyle) {
|
|
151
|
-
observer = new MutationObserver(() => {
|
|
152
|
-
clearTimeout(timeoutId);
|
|
153
|
-
timeoutId = window.setTimeout(applyStyle, 50);
|
|
154
|
-
});
|
|
155
|
-
observer.observe(document.head, {
|
|
156
|
-
childList: true,
|
|
157
|
-
subtree: true,
|
|
158
|
-
attributes: true,
|
|
159
|
-
attributeFilter: ["href"]
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
170
|
if ($iframe.contentDocument?.readyState === "complete") onLoad();
|
|
163
171
|
return () => {
|
|
164
172
|
$iframe.removeEventListener("load", onLoad);
|
|
165
|
-
observer?.disconnect();
|
|
166
|
-
clearTimeout(timeoutId);
|
|
167
173
|
};
|
|
168
174
|
}, [
|
|
169
|
-
syncStyle,
|
|
170
175
|
scripts,
|
|
171
176
|
onLoaded,
|
|
172
177
|
applyStyle
|
|
@@ -184,6 +189,8 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
184
189
|
}
|
|
185
190
|
if (styleEl.textContent !== css) styleEl.textContent = css;
|
|
186
191
|
});
|
|
192
|
+
for (let index = styles.length; index < prevStyleCountRef.current; index++) doc.getElementById(`injected-style-${index}`)?.remove();
|
|
193
|
+
prevStyleCountRef.current = styles.length;
|
|
187
194
|
stylesheets.forEach((href, index) => {
|
|
188
195
|
const linkId = `injected-stylesheet-${index}`;
|
|
189
196
|
let linkEl = doc.getElementById(linkId);
|
|
@@ -195,67 +202,76 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
195
202
|
}
|
|
196
203
|
if (linkEl.href !== href) linkEl.href = href;
|
|
197
204
|
});
|
|
205
|
+
for (let index = stylesheets.length; index < prevStylesheetCountRef.current; index++) doc.getElementById(`injected-stylesheet-${index}`)?.remove();
|
|
206
|
+
prevStylesheetCountRef.current = stylesheets.length;
|
|
198
207
|
}, [styles, stylesheets]);
|
|
199
|
-
|
|
208
|
+
const updateHeight = useCallback(() => {
|
|
200
209
|
if (!shouldAutoHeight || !mountNode || !iframeRef.current) return;
|
|
201
210
|
const iframe = iframeRef.current;
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
211
|
+
const scrollParent = iframe.closest("[data-frame-container]");
|
|
212
|
+
const savedScrollTop = scrollParent?.scrollTop ?? 0;
|
|
213
|
+
iframe.style.height = "0px";
|
|
214
|
+
let childrenHeight = 0;
|
|
215
|
+
Array.from(mountNode.children).forEach((child) => {
|
|
216
|
+
const el = child;
|
|
217
|
+
childrenHeight = Math.max(childrenHeight, el.scrollHeight);
|
|
218
|
+
});
|
|
219
|
+
const win = iframe.contentDocument?.defaultView;
|
|
220
|
+
mountNode.querySelectorAll("[data-floating-ui-focusable]").forEach((popup) => {
|
|
221
|
+
if (popup.offsetHeight > 0) {
|
|
222
|
+
let offsetY = 0;
|
|
223
|
+
const transform = popup.style.transform;
|
|
224
|
+
if (transform) {
|
|
225
|
+
const match = transform.match(/translate\([^,]+,\s*([+-]?\d+(?:\.\d+)?)/);
|
|
226
|
+
if (match?.[1]) offsetY = parseFloat(match[1]);
|
|
227
|
+
}
|
|
228
|
+
const estimatedHeight = offsetY + popup.offsetHeight;
|
|
229
|
+
childrenHeight = Math.max(childrenHeight, estimatedHeight);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
if (win) Array.from(mountNode.children).forEach((child) => {
|
|
233
|
+
const el = child;
|
|
234
|
+
const style = win.getComputedStyle(el);
|
|
235
|
+
if (style.position === "fixed" || style.position === "absolute") {
|
|
236
|
+
if (el.offsetHeight > 0) {
|
|
214
237
|
let offsetY = 0;
|
|
215
|
-
const transform =
|
|
238
|
+
const transform = el.style.transform;
|
|
216
239
|
if (transform) {
|
|
217
240
|
const match = transform.match(/translate\([^,]+,\s*([+-]?\d+(?:\.\d+)?)/);
|
|
218
241
|
if (match?.[1]) offsetY = parseFloat(match[1]);
|
|
219
242
|
}
|
|
220
|
-
const estimatedHeight = offsetY +
|
|
243
|
+
const estimatedHeight = offsetY + el.offsetHeight;
|
|
221
244
|
childrenHeight = Math.max(childrenHeight, estimatedHeight);
|
|
222
245
|
}
|
|
223
|
-
}
|
|
224
|
-
if (win) Array.from(mountNode.children).forEach((child) => {
|
|
225
|
-
const el = child;
|
|
226
|
-
const style = win.getComputedStyle(el);
|
|
227
|
-
if (style.position === "fixed" || style.position === "absolute") {
|
|
228
|
-
if (el.offsetHeight > 0) {
|
|
229
|
-
let offsetY = 0;
|
|
230
|
-
const transform = el.style.transform;
|
|
231
|
-
if (transform) {
|
|
232
|
-
const match = transform.match(/translate\([^,]+,\s*([+-]?\d+(?:\.\d+)?)/);
|
|
233
|
-
if (match?.[1]) offsetY = parseFloat(match[1]);
|
|
234
|
-
}
|
|
235
|
-
const estimatedHeight = offsetY + el.offsetHeight;
|
|
236
|
-
childrenHeight = Math.max(childrenHeight, estimatedHeight);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
});
|
|
240
|
-
const contentHeight = Math.max(mountNode.scrollHeight, childrenHeight);
|
|
241
|
-
if (contentHeight > 0) iframe.style.height = `${Math.ceil(contentHeight)}px`;
|
|
242
|
-
if (scrollParent) scrollParent.scrollTop = savedScrollTop;
|
|
243
|
-
};
|
|
244
|
-
updateHeight();
|
|
245
|
-
const resizeObserver = new ResizeObserver(updateHeight);
|
|
246
|
-
resizeObserver.observe(mountNode);
|
|
247
|
-
const mutationObserver = new MutationObserver(updateHeight);
|
|
248
|
-
mutationObserver.observe(mountNode, {
|
|
249
|
-
childList: true,
|
|
250
|
-
subtree: true,
|
|
251
|
-
attributes: true,
|
|
252
|
-
characterData: true
|
|
246
|
+
}
|
|
253
247
|
});
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
248
|
+
const contentHeight = Math.max(mountNode.scrollHeight, childrenHeight);
|
|
249
|
+
if (contentHeight > 0) iframe.style.height = `${Math.ceil(contentHeight)}px`;
|
|
250
|
+
if (scrollParent) scrollParent.scrollTop = savedScrollTop;
|
|
251
|
+
}, [shouldAutoHeight, mountNode]);
|
|
252
|
+
useEffect(() => {
|
|
253
|
+
updateHeight();
|
|
254
|
+
}, [updateHeight]);
|
|
255
|
+
const [resizeRef, resizeSize] = useResizeObserver();
|
|
256
|
+
useEffect(() => {
|
|
257
|
+
if (!shouldAutoHeight || !mountNode) return;
|
|
258
|
+
resizeRef(mountNode);
|
|
259
|
+
return () => resizeRef(null);
|
|
260
|
+
}, [
|
|
261
|
+
shouldAutoHeight,
|
|
262
|
+
mountNode,
|
|
263
|
+
resizeRef
|
|
264
|
+
]);
|
|
265
|
+
useEffect(() => {
|
|
266
|
+
updateHeight();
|
|
267
|
+
}, [resizeSize]);
|
|
268
|
+
useMutationObserver(mountNode, updateHeight, {
|
|
269
|
+
enabled: shouldAutoHeight,
|
|
270
|
+
childList: true,
|
|
271
|
+
subtree: true,
|
|
272
|
+
attributes: true,
|
|
273
|
+
characterData: true
|
|
274
|
+
});
|
|
259
275
|
const content = mountNode ? createPortal(children(mountNode), mountNode) : null;
|
|
260
276
|
return /* @__PURE__ */ jsx("iframe", {
|
|
261
277
|
ref: iframeRef,
|
|
@@ -295,41 +311,6 @@ const Shadow = ({ children }) => {
|
|
|
295
311
|
renderTargetRef.current = target;
|
|
296
312
|
setRenderTarget(target);
|
|
297
313
|
}
|
|
298
|
-
const onClick = (e) => {
|
|
299
|
-
const eventInit = {
|
|
300
|
-
bubbles: true,
|
|
301
|
-
cancelable: true,
|
|
302
|
-
composed: true
|
|
303
|
-
};
|
|
304
|
-
let newEvent;
|
|
305
|
-
if (e instanceof MouseEvent) newEvent = new MouseEvent(e.type, {
|
|
306
|
-
...eventInit,
|
|
307
|
-
clientX: e.clientX,
|
|
308
|
-
clientY: e.clientY,
|
|
309
|
-
button: e.button
|
|
310
|
-
});
|
|
311
|
-
else if (e instanceof PointerEvent) newEvent = new PointerEvent(e.type, {
|
|
312
|
-
...eventInit,
|
|
313
|
-
clientX: e.clientX,
|
|
314
|
-
clientY: e.clientY,
|
|
315
|
-
pointerId: e.pointerId
|
|
316
|
-
});
|
|
317
|
-
else newEvent = new Event(e.type, eventInit);
|
|
318
|
-
hostRef.current?.dispatchEvent(newEvent);
|
|
319
|
-
};
|
|
320
|
-
const eventTypes = [
|
|
321
|
-
"click",
|
|
322
|
-
"pointerdown",
|
|
323
|
-
"pointerup"
|
|
324
|
-
];
|
|
325
|
-
eventTypes.forEach((type) => {
|
|
326
|
-
target.addEventListener(type, onClick, true);
|
|
327
|
-
});
|
|
328
|
-
return () => {
|
|
329
|
-
eventTypes.forEach((type) => {
|
|
330
|
-
target?.removeEventListener(type, onClick, true);
|
|
331
|
-
});
|
|
332
|
-
};
|
|
333
314
|
}, []);
|
|
334
315
|
useLayoutEffect(() => {
|
|
335
316
|
if (renderTargetRef.current && !renderTarget) setRenderTarget(renderTargetRef.current);
|
|
@@ -354,24 +335,34 @@ const Frame = ({ mode, children, ...restProps }) => {
|
|
|
354
335
|
|
|
355
336
|
//#endregion
|
|
356
337
|
//#region src/components/dnd/draggable.tsx
|
|
357
|
-
const
|
|
358
|
-
const { attributes, listeners, setNodeRef,
|
|
338
|
+
const DraggableItem = ({ item, children }) => {
|
|
339
|
+
const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
|
|
359
340
|
id: item.id,
|
|
360
341
|
data: {
|
|
361
342
|
type: "new-item",
|
|
362
343
|
item
|
|
363
344
|
}
|
|
364
345
|
});
|
|
365
|
-
return
|
|
346
|
+
return children({
|
|
366
347
|
ref: setNodeRef,
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
children: item.name
|
|
348
|
+
dragProps: {
|
|
349
|
+
...listeners,
|
|
350
|
+
...attributes
|
|
351
|
+
},
|
|
352
|
+
isDragging
|
|
373
353
|
});
|
|
374
354
|
};
|
|
355
|
+
const DefaultDraggableItem = ({ item, onAdd }) => /* @__PURE__ */ jsx(DraggableItem, {
|
|
356
|
+
item,
|
|
357
|
+
children: ({ ref, dragProps, isDragging }) => /* @__PURE__ */ jsx(Card, {
|
|
358
|
+
ref,
|
|
359
|
+
style: { opacity: isDragging ? .5 : 1 },
|
|
360
|
+
...dragProps,
|
|
361
|
+
className: cn("cursor-grab", "outline-none", "hover:border-blue-300 hover:shadow-md", isDragging && "opacity-50"),
|
|
362
|
+
onDoubleClick: onAdd ? () => onAdd(item) : void 0,
|
|
363
|
+
children: item.name
|
|
364
|
+
})
|
|
365
|
+
});
|
|
375
366
|
|
|
376
367
|
//#endregion
|
|
377
368
|
//#region src/components/dnd/droppable.tsx
|
|
@@ -402,7 +393,16 @@ const Renderer = ({ preview, headers, modules, frame, provider }) => {
|
|
|
402
393
|
...baseModules,
|
|
403
394
|
...modules
|
|
404
395
|
}), [modules]);
|
|
405
|
-
const module = useMemo(() =>
|
|
396
|
+
const module = useMemo(() => {
|
|
397
|
+
try {
|
|
398
|
+
return compile(preview, memoizedModules);
|
|
399
|
+
} catch (e) {
|
|
400
|
+
return {
|
|
401
|
+
exports: {},
|
|
402
|
+
error: e instanceof Error ? e.message : "Module transformation error"
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
}, [preview, memoizedModules]);
|
|
406
406
|
const renderProvider = (component) => {
|
|
407
407
|
return provider ? provider(component) : component;
|
|
408
408
|
};
|
|
@@ -474,7 +474,7 @@ const Overlay = ({ sections, renderProps }) => {
|
|
|
474
474
|
if (!active) return null;
|
|
475
475
|
if (active.data.current?.type === "new-item") {
|
|
476
476
|
const item = active.data.current.item;
|
|
477
|
-
return /* @__PURE__ */ jsx(
|
|
477
|
+
return /* @__PURE__ */ jsx(DefaultDraggableItem, { item });
|
|
478
478
|
}
|
|
479
479
|
const section = sections.find((s) => s.id === active.id);
|
|
480
480
|
if (section) {
|
|
@@ -12621,7 +12621,7 @@ const conditionalModifiers = (args) => {
|
|
|
12621
12621
|
if (active?.data.current?.type === "new-item") return args.transform;
|
|
12622
12622
|
return restrictToVerticalAxis(args);
|
|
12623
12623
|
};
|
|
12624
|
-
const Dnd = ({ value: _value, props, modules = {}, onChange: _onChange, className, items = [], frame, provider, ...restProps }) => {
|
|
12624
|
+
const Dnd$1 = ({ value: _value, props, modules = {}, onChange: _onChange, className, items = [], frame, provider, renderPalette, renderPanel, ...restProps }) => {
|
|
12625
12625
|
const [selectedId, setSelectedId] = useState(null);
|
|
12626
12626
|
const [mobilePaletteOpen, setMobilePaletteOpen] = useState(false);
|
|
12627
12627
|
const { breakpoint } = useResponsiveSize();
|
|
@@ -12721,14 +12721,35 @@ const Dnd = ({ value: _value, props, modules = {}, onChange: _onChange, classNam
|
|
|
12721
12721
|
useEffect(() => {
|
|
12722
12722
|
if (frame?.scripts?.length) preloadScripts(frame.scripts);
|
|
12723
12723
|
}, [frame?.scripts]);
|
|
12724
|
-
const renderPaletteItems = (onAdd) =>
|
|
12725
|
-
|
|
12726
|
-
|
|
12727
|
-
|
|
12728
|
-
|
|
12729
|
-
|
|
12730
|
-
}
|
|
12731
|
-
|
|
12724
|
+
const renderPaletteItems = (onAdd) => {
|
|
12725
|
+
const paletteItems = items?.length ? items : DRAGGABLE_ITEMS;
|
|
12726
|
+
if (renderPalette) return renderPalette({
|
|
12727
|
+
items: paletteItems,
|
|
12728
|
+
onAdd,
|
|
12729
|
+
DraggableItem
|
|
12730
|
+
});
|
|
12731
|
+
return /* @__PURE__ */ jsx(Space, {
|
|
12732
|
+
orientation: "vertical",
|
|
12733
|
+
align: "start",
|
|
12734
|
+
children: paletteItems.map((item) => /* @__PURE__ */ jsx(DefaultDraggableItem, {
|
|
12735
|
+
item,
|
|
12736
|
+
onAdd
|
|
12737
|
+
}, item.id))
|
|
12738
|
+
});
|
|
12739
|
+
};
|
|
12740
|
+
const renderPanelContent = () => {
|
|
12741
|
+
const selectedItem = sections.find((s) => s.id === selectedId);
|
|
12742
|
+
if (renderPanel) return renderPanel({
|
|
12743
|
+
item: selectedItem,
|
|
12744
|
+
onChange,
|
|
12745
|
+
onDelete
|
|
12746
|
+
});
|
|
12747
|
+
return /* @__PURE__ */ jsx(Panel, {
|
|
12748
|
+
item: selectedItem,
|
|
12749
|
+
onChange,
|
|
12750
|
+
onDelete
|
|
12751
|
+
});
|
|
12752
|
+
};
|
|
12732
12753
|
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(DndContext, {
|
|
12733
12754
|
sensors,
|
|
12734
12755
|
collisionDetection: closestCenter,
|
|
@@ -12787,11 +12808,7 @@ const Dnd = ({ value: _value, props, modules = {}, onChange: _onChange, classNam
|
|
|
12787
12808
|
}),
|
|
12788
12809
|
/* @__PURE__ */ jsx("div", {
|
|
12789
12810
|
className: "hidden w-1/5 md:block",
|
|
12790
|
-
children:
|
|
12791
|
-
item: sections.find((s) => s.id === selectedId),
|
|
12792
|
-
onChange,
|
|
12793
|
-
onDelete
|
|
12794
|
-
})
|
|
12811
|
+
children: renderPanelContent()
|
|
12795
12812
|
}),
|
|
12796
12813
|
/* @__PURE__ */ jsx(Button, {
|
|
12797
12814
|
type: "primary",
|
|
@@ -12818,11 +12835,7 @@ const Dnd = ({ value: _value, props, modules = {}, onChange: _onChange, classNam
|
|
|
12818
12835
|
direction: "bottom",
|
|
12819
12836
|
size: "large",
|
|
12820
12837
|
title: "Properties",
|
|
12821
|
-
children:
|
|
12822
|
-
item: sections.find((s) => s.id === selectedId),
|
|
12823
|
-
onChange,
|
|
12824
|
-
onDelete
|
|
12825
|
-
})
|
|
12838
|
+
children: renderPanelContent()
|
|
12826
12839
|
})
|
|
12827
12840
|
]
|
|
12828
12841
|
}), /* @__PURE__ */ jsx(DragOverlay, { children: /* @__PURE__ */ jsx(Overlay, {
|
|
@@ -12837,6 +12850,11 @@ const Dnd = ({ value: _value, props, modules = {}, onChange: _onChange, classNam
|
|
|
12837
12850
|
}) });
|
|
12838
12851
|
};
|
|
12839
12852
|
|
|
12853
|
+
//#endregion
|
|
12854
|
+
//#region src/components/dnd/index.ts
|
|
12855
|
+
const Dnd = Dnd$1;
|
|
12856
|
+
Dnd.DraggableItem = DraggableItem;
|
|
12857
|
+
|
|
12840
12858
|
//#endregion
|
|
12841
12859
|
//#region src/components/editor/editor.tsx
|
|
12842
12860
|
const Editor$1 = ({ defaultValue, value: _value, debounce = 1e3, onChange: _onChange, ...props }) => {
|
|
@@ -12852,9 +12870,10 @@ const Editor$1 = ({ defaultValue, value: _value, debounce = 1e3, onChange: _onCh
|
|
|
12852
12870
|
const onError = useCallback((error) => {
|
|
12853
12871
|
setError(error);
|
|
12854
12872
|
}, [setError]);
|
|
12855
|
-
|
|
12856
|
-
|
|
12857
|
-
|
|
12873
|
+
const debouncedValue = useDebouncedValue(value, debounce);
|
|
12874
|
+
useEffect(() => {
|
|
12875
|
+
setCode(debouncedValue);
|
|
12876
|
+
}, [debouncedValue, setCode]);
|
|
12858
12877
|
return /* @__PURE__ */ jsx(Core, {
|
|
12859
12878
|
value,
|
|
12860
12879
|
onChange,
|
|
@@ -12935,6 +12954,15 @@ var ErrorBoundary = class extends React.Component {
|
|
|
12935
12954
|
console.error("🚨 [Boundary] Rendering error:", error, errorInfo);
|
|
12936
12955
|
this.props.onError?.(error, errorInfo);
|
|
12937
12956
|
}
|
|
12957
|
+
componentDidUpdate(prevProps) {
|
|
12958
|
+
if (!this.state.hasError) return;
|
|
12959
|
+
const prevKeys = prevProps.resetKeys ?? [];
|
|
12960
|
+
const nextKeys = this.props.resetKeys ?? [];
|
|
12961
|
+
if (prevKeys.length !== nextKeys.length || nextKeys.some((key, i) => key !== prevKeys[i])) this.setState({
|
|
12962
|
+
hasError: false,
|
|
12963
|
+
error: void 0
|
|
12964
|
+
});
|
|
12965
|
+
}
|
|
12938
12966
|
render() {
|
|
12939
12967
|
if (this.state.hasError) return this.props.fallback ? /* @__PURE__ */ jsx(Fragment, { children: this.props.fallback(this.state.error?.message) }) : /* @__PURE__ */ jsx(Error$2, {
|
|
12940
12968
|
message: this.state.error?.message,
|
|
@@ -12954,21 +12982,20 @@ const Guard = ({ children, onError }) => {
|
|
|
12954
12982
|
const [error, setError] = useState(null);
|
|
12955
12983
|
const containerRef = useRef(null);
|
|
12956
12984
|
const errorHandled = useRef(false);
|
|
12985
|
+
useEventListener("error", (event) => {
|
|
12986
|
+
if (errorHandled.current) return;
|
|
12987
|
+
errorHandled.current = true;
|
|
12988
|
+
const errorMessage = event.error?.message || event.message || "Unknown error";
|
|
12989
|
+
console.error("⚡ [Guard] Event handler error:", errorMessage);
|
|
12990
|
+
event.preventDefault();
|
|
12991
|
+
setError(errorMessage);
|
|
12992
|
+
onError?.(event.error || new window.Error(errorMessage));
|
|
12993
|
+
setTimeout(() => {
|
|
12994
|
+
errorHandled.current = false;
|
|
12995
|
+
}, 100);
|
|
12996
|
+
}, { capture: true });
|
|
12957
12997
|
useEffect(() => {
|
|
12958
12998
|
if (!containerRef.current) return;
|
|
12959
|
-
const handleWindowError = (event) => {
|
|
12960
|
-
if (errorHandled.current) return;
|
|
12961
|
-
errorHandled.current = true;
|
|
12962
|
-
const errorMessage = event.error?.message || event.message || "Unknown error";
|
|
12963
|
-
console.error("⚡ [Guard] Event handler error:", errorMessage);
|
|
12964
|
-
event.preventDefault();
|
|
12965
|
-
setError(errorMessage);
|
|
12966
|
-
onError?.(event.error || new window.Error(errorMessage));
|
|
12967
|
-
setTimeout(() => {
|
|
12968
|
-
errorHandled.current = false;
|
|
12969
|
-
}, 100);
|
|
12970
|
-
return true;
|
|
12971
|
-
};
|
|
12972
12999
|
const handleUnhandledRejection = (event) => {
|
|
12973
13000
|
if (errorHandled.current) return;
|
|
12974
13001
|
errorHandled.current = true;
|
|
@@ -12980,10 +13007,8 @@ const Guard = ({ children, onError }) => {
|
|
|
12980
13007
|
errorHandled.current = false;
|
|
12981
13008
|
}, 100);
|
|
12982
13009
|
};
|
|
12983
|
-
window.addEventListener("error", handleWindowError, true);
|
|
12984
13010
|
window.addEventListener("unhandledrejection", handleUnhandledRejection, true);
|
|
12985
13011
|
return () => {
|
|
12986
|
-
window.removeEventListener("error", handleWindowError, true);
|
|
12987
13012
|
window.removeEventListener("unhandledrejection", handleUnhandledRejection, true);
|
|
12988
13013
|
};
|
|
12989
13014
|
}, [onError]);
|
|
@@ -13006,16 +13031,12 @@ const Guard = ({ children, onError }) => {
|
|
|
13006
13031
|
//#region src/components/error/runtime.tsx
|
|
13007
13032
|
const Runtime = ({ open = true, reset }) => {
|
|
13008
13033
|
const { error: message, setError } = useError();
|
|
13034
|
+
useEventListener("error", (e) => {
|
|
13035
|
+
setError(e.message);
|
|
13036
|
+
e.preventDefault();
|
|
13037
|
+
});
|
|
13009
13038
|
useEffect(() => {
|
|
13010
|
-
|
|
13011
|
-
setError(e.message);
|
|
13012
|
-
e.preventDefault();
|
|
13013
|
-
};
|
|
13014
|
-
window.addEventListener("error", onError);
|
|
13015
|
-
return () => {
|
|
13016
|
-
setError(null);
|
|
13017
|
-
window.removeEventListener("error", onError);
|
|
13018
|
-
};
|
|
13039
|
+
return () => setError(null);
|
|
13019
13040
|
}, [setError]);
|
|
13020
13041
|
if (!open) return null;
|
|
13021
13042
|
return /* @__PURE__ */ jsx(Error$2, {
|
|
@@ -13043,9 +13064,10 @@ const Client = ({ code: _code = "", className, showError, props = {}, modules =
|
|
|
13043
13064
|
...baseModules,
|
|
13044
13065
|
...modules
|
|
13045
13066
|
};
|
|
13067
|
+
const effectiveCode = _code || code;
|
|
13046
13068
|
let module = null;
|
|
13047
|
-
if (
|
|
13048
|
-
module = compile(
|
|
13069
|
+
if (effectiveCode) try {
|
|
13070
|
+
module = compile(effectiveCode, mergedModules);
|
|
13049
13071
|
} catch (e) {
|
|
13050
13072
|
module = {
|
|
13051
13073
|
exports: {},
|
|
@@ -13070,6 +13092,7 @@ const Client = ({ code: _code = "", className, showError, props = {}, modules =
|
|
|
13070
13092
|
children: /* @__PURE__ */ jsx(Frame, {
|
|
13071
13093
|
...frame,
|
|
13072
13094
|
children: (container) => /* @__PURE__ */ jsx(Error$1.Boundary, {
|
|
13095
|
+
resetKeys: [effectiveCode],
|
|
13073
13096
|
onError: (e) => setError(e.message),
|
|
13074
13097
|
children: renderProvider(/* @__PURE__ */ jsx(Error$1.Guard, {
|
|
13075
13098
|
onError: (e) => setError(e.message),
|
|
@@ -13088,6 +13111,7 @@ const Client = ({ code: _code = "", className, showError, props = {}, modules =
|
|
|
13088
13111
|
containerType: "inline-size"
|
|
13089
13112
|
},
|
|
13090
13113
|
children: /* @__PURE__ */ jsx(Error$1.Boundary, {
|
|
13114
|
+
resetKeys: [effectiveCode],
|
|
13091
13115
|
onError: (e) => setError(e.message),
|
|
13092
13116
|
children: renderProvider(/* @__PURE__ */ jsx(Error$1.Guard, {
|
|
13093
13117
|
onError: (e) => setError(e.message),
|
|
@@ -13102,12 +13126,23 @@ const Client = ({ code: _code = "", className, showError, props = {}, modules =
|
|
|
13102
13126
|
const Preview = ({ code, props = {}, modules = {}, dynamicTailwind = false, provider, ...restProps }) => {
|
|
13103
13127
|
const [runtimeError, setRuntimeError] = useState(null);
|
|
13104
13128
|
const [dynamicCSS, setDynamicCSS] = useState("");
|
|
13129
|
+
const [prevCode, setPrevCode] = useState(code);
|
|
13130
|
+
if (code !== prevCode) {
|
|
13131
|
+
setPrevCode(code);
|
|
13132
|
+
setRuntimeError(null);
|
|
13133
|
+
}
|
|
13105
13134
|
const renderProvider = (component) => {
|
|
13106
13135
|
return provider ? provider(component) : component;
|
|
13107
13136
|
};
|
|
13108
13137
|
useEffect(() => {
|
|
13109
13138
|
if (!code || !dynamicTailwind) return;
|
|
13110
|
-
|
|
13139
|
+
let cancelled = false;
|
|
13140
|
+
generateTailwindCSS(code).then((css) => {
|
|
13141
|
+
if (!cancelled) setDynamicCSS(css);
|
|
13142
|
+
});
|
|
13143
|
+
return () => {
|
|
13144
|
+
cancelled = true;
|
|
13145
|
+
};
|
|
13111
13146
|
}, [code, dynamicTailwind]);
|
|
13112
13147
|
if (runtimeError) return /* @__PURE__ */ jsx(Error$1, {
|
|
13113
13148
|
title: "Runtime Error",
|
|
@@ -13116,10 +13151,18 @@ const Preview = ({ code, props = {}, modules = {}, dynamicTailwind = false, prov
|
|
|
13116
13151
|
onReset: () => setRuntimeError(null)
|
|
13117
13152
|
});
|
|
13118
13153
|
if (code) {
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
|
|
13122
|
-
|
|
13154
|
+
let module;
|
|
13155
|
+
try {
|
|
13156
|
+
module = compile(code, {
|
|
13157
|
+
...baseModules,
|
|
13158
|
+
...modules
|
|
13159
|
+
});
|
|
13160
|
+
} catch (e) {
|
|
13161
|
+
module = {
|
|
13162
|
+
exports: {},
|
|
13163
|
+
error: e instanceof Error ? e.message : "Module transformation error"
|
|
13164
|
+
};
|
|
13165
|
+
}
|
|
13123
13166
|
if (module.error) return /* @__PURE__ */ jsx(Error$1, {
|
|
13124
13167
|
title: "Compile Error",
|
|
13125
13168
|
message: module.error,
|
|
@@ -13131,13 +13174,14 @@ const Preview = ({ code, props = {}, modules = {}, dynamicTailwind = false, prov
|
|
|
13131
13174
|
className: "mx-5 mt-25"
|
|
13132
13175
|
});
|
|
13133
13176
|
return /* @__PURE__ */ jsx(Error$1.Boundary, {
|
|
13177
|
+
resetKeys: [code],
|
|
13134
13178
|
fallback: (message) => /* @__PURE__ */ jsx(Error$1, {
|
|
13135
13179
|
title: "Rendering Error",
|
|
13136
13180
|
message
|
|
13137
13181
|
}),
|
|
13138
13182
|
children: renderProvider(/* @__PURE__ */ jsxs(Error$1.Guard, {
|
|
13139
13183
|
onError: (e) => setRuntimeError(e.message),
|
|
13140
|
-
children: [/* @__PURE__ */ jsx(Component, { ...props }), dynamicCSS && /* @__PURE__ */ jsx("style", { children: dynamicCSS })]
|
|
13184
|
+
children: [/* @__PURE__ */ jsx(Component, { ...props }), dynamicTailwind && dynamicCSS && /* @__PURE__ */ jsx("style", { children: dynamicCSS })]
|
|
13141
13185
|
}))
|
|
13142
13186
|
});
|
|
13143
13187
|
}
|