@jbpark/live-editor 1.8.1 → 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 CHANGED
@@ -12,16 +12,19 @@ live-editor/
12
12
  │ ├─ components/
13
13
  │ │ ├─ Context/ # 전역 상태 관리
14
14
  │ │ ├─ Dnd/ # 드래그 앤 드롭 시스템 및 편집 패널
15
- │ │ ├─ Editor/ # 코드 에디터
16
- │ │ ├─ Error/ # 에러 바운더리
17
- │ │ └─ Preview/ # 격리된 프리뷰 런타임
15
+ │ │ ├─ Editor/ # 코드 에디터
16
+ │ │ ├─ Error/ # 에러 바운더리
17
+ │ │ ├─ Frame/ # iframe/shadow DOM 프리뷰 격리
18
+ │ │ └─ Preview/ # 격리된 프리뷰 런타임
18
19
  │ ├─ pages/
19
- │ │ ├─ Playground/ # 메인 에디터 페이지
20
- │ │ └─ Preview/ # 전체화면 프리뷰 페이지
21
- │ ├─ utils/ast/ # AST 조작 코드 생성
22
- ├─ constants/ # 상수 설정
23
- │ ├─ types/ # TypeScript 타입 정의
24
- └─ App.tsx # 라우팅이 포함된 앱 레이아웃
20
+ │ │ ├─ Docs/ # 문서 형태 데모 사이트 (개요 + 기능별 페이지)
21
+ │ │ ├─ Editor/ # 전체 에디터 앱 (에디터 + DnD 전환)
22
+ ├─ Playground/ # 데이터 바인딩 설정 테스트 페이지
23
+ │ └─ Preview/ # 전체화면 프리뷰 페이지
24
+ │ ├─ utils/ast/ # AST 조작 및 코드 생성
25
+ ├─ constants/ # 상수 설정
26
+ │ ├─ types/ # TypeScript 타입 정의
27
+ │ └─ main.tsx # 앱 진입점 + 라우팅
25
28
  └─ package.json
26
29
  ```
27
30
 
package/README.md CHANGED
@@ -12,16 +12,19 @@ live-editor/
12
12
  │ ├─ components/
13
13
  │ │ ├─ Context/ # Global state management
14
14
  │ │ ├─ Dnd/ # Drag-and-drop system with editing panels
15
- │ │ ├─ Editor/ # Code editor
16
- │ │ ├─ Error/ # Error boundary
17
- │ │ └─ Preview/ # Isolated preview runtime
15
+ │ │ ├─ Editor/ # Code editor
16
+ │ │ ├─ Error/ # Error boundary
17
+ │ │ ├─ Frame/ # iframe/shadow-DOM preview isolation
18
+ │ │ └─ Preview/ # Isolated preview runtime
18
19
  │ ├─ pages/
19
- │ │ ├─ Playground/ # Main editor page
20
- │ │ └─ Preview/ # Full-screen preview page
21
- │ ├─ utils/ast/ # AST manipulation & code generation
22
- ├─ constants/ # Constants and configurations
23
- │ ├─ types/ # TypeScript type definitions
24
- └─ App.tsx # App layout with routing
20
+ │ │ ├─ Docs/ # Docs-style demo site (overview + feature pages)
21
+ │ │ ├─ Editor/ # Full editor app (editor + DnD toggle)
22
+ ├─ Playground/ # Data-binding config test page
23
+ │ └─ Preview/ # Full-screen preview page
24
+ │ ├─ utils/ast/ # AST manipulation & code generation
25
+ ├─ constants/ # Constants and configurations
26
+ │ ├─ types/ # TypeScript type definitions
27
+ │ └─ main.tsx # App entry + routing
25
28
  └─ package.json
26
29
  ```
27
30
 
package/dist/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { n as Section } from "./index-DdSjzvA3.mjs";
2
2
  import "@jbpark/ui-kit/style.css";
3
+ import * as react from "react";
3
4
  import React$1, { ReactNode } from "react";
4
5
  import * as react_jsx_runtime0 from "react/jsx-runtime";
5
6
  import { Extension } from "@uiw/react-codemirror";
@@ -60,7 +61,7 @@ declare class ErrorBoundary extends React$1.Component<Props$6, State> {
60
61
  static getDerivedStateFromError(error: Error): State;
61
62
  componentDidCatch(error: Error, errorInfo: React$1.ErrorInfo): void;
62
63
  componentDidUpdate(prevProps: Props$6): void;
63
- render(): string | number | bigint | boolean | react_jsx_runtime0.JSX.Element | Iterable<React$1.ReactNode> | Promise<string | number | bigint | boolean | React$1.ReactPortal | React$1.ReactElement<unknown, string | React$1.JSXElementConstructor<any>> | Iterable<React$1.ReactNode> | null | undefined> | null | undefined;
64
+ render(): string | number | bigint | boolean | Iterable<React$1.ReactNode> | Promise<string | number | bigint | boolean | React$1.ReactPortal | React$1.ReactElement<unknown, string | React$1.JSXElementConstructor<any>> | Iterable<React$1.ReactNode> | null | undefined> | react_jsx_runtime0.JSX.Element | null | undefined;
64
65
  }
65
66
  //#endregion
66
67
  //#region src/components/error/error.d.ts
@@ -150,7 +151,32 @@ type EditorComponent = typeof Editor$1 & {
150
151
  };
151
152
  declare const Editor: EditorComponent;
152
153
  //#endregion
154
+ //#region src/components/dnd/draggable.d.ts
155
+ interface DraggableItemDragState {
156
+ ref: (node: HTMLElement | null) => void;
157
+ dragProps: React.HTMLAttributes<HTMLElement>;
158
+ isDragging: boolean;
159
+ }
160
+ interface DraggableItemProps {
161
+ item: Section;
162
+ children: (drag: DraggableItemDragState) => React.ReactNode;
163
+ }
164
+ declare const DraggableItem: ({
165
+ item,
166
+ children
167
+ }: DraggableItemProps) => react.ReactNode;
168
+ //#endregion
153
169
  //#region src/components/dnd/dnd.d.ts
170
+ interface PaletteRenderData {
171
+ items: Section[];
172
+ onAdd: (item: Section) => void;
173
+ DraggableItem: typeof DraggableItem;
174
+ }
175
+ interface PanelRenderData {
176
+ item?: Section;
177
+ onChange: (next: Partial<Section>) => void;
178
+ onDelete: (id: string) => void;
179
+ }
154
180
  interface Props extends Omit<React.ComponentPropsWithRef<'div'>, 'onChange'> {
155
181
  value?: string;
156
182
  props?: Record<string, unknown>;
@@ -159,8 +185,10 @@ interface Props extends Omit<React.ComponentPropsWithRef<'div'>, 'onChange'> {
159
185
  frame?: FrameProps;
160
186
  provider?: (children: React.ReactNode) => React.ReactNode;
161
187
  onChange?: (value: string) => void;
188
+ renderPalette?: (data: PaletteRenderData) => React.ReactNode;
189
+ renderPanel?: (data: PanelRenderData) => React.ReactNode;
162
190
  }
163
- declare const Dnd: ({
191
+ declare const Dnd$1: ({
164
192
  value: _value,
165
193
  props,
166
194
  modules,
@@ -169,9 +197,17 @@ declare const Dnd: ({
169
197
  items,
170
198
  frame,
171
199
  provider,
200
+ renderPalette,
201
+ renderPanel,
172
202
  ...restProps
173
203
  }: Props) => react_jsx_runtime0.JSX.Element;
174
204
  //#endregion
205
+ //#region src/components/dnd/index.d.ts
206
+ type DndComponent = typeof Dnd$1 & {
207
+ DraggableItem: typeof DraggableItem;
208
+ };
209
+ declare const Dnd: DndComponent;
210
+ //#endregion
175
211
  //#region src/index.d.ts
176
212
  declare const App: {
177
213
  ({
@@ -232,7 +268,7 @@ declare const App: {
232
268
  ...props
233
269
  }: Props$2) => react_jsx_runtime0.JSX.Element;
234
270
  };
235
- Dnd: ({
271
+ Dnd: (({
236
272
  value: _value,
237
273
  props,
238
274
  modules,
@@ -241,8 +277,15 @@ declare const App: {
241
277
  items,
242
278
  frame,
243
279
  provider,
280
+ renderPalette,
281
+ renderPanel,
244
282
  ...restProps
245
- }: Props) => react_jsx_runtime0.JSX.Element;
283
+ }: Props) => react_jsx_runtime0.JSX.Element) & {
284
+ DraggableItem: ({
285
+ item,
286
+ children
287
+ }: DraggableItemProps) => react.ReactNode;
288
+ };
246
289
  };
247
290
  declare const LiveRenderer: ({
248
291
  code,
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 { useDebounce, useMultiSelect, useResponsiveSize } from "@jbpark/use-hooks";
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,19 +26,17 @@ 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
- code: "",
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
- return useContext(PreviewContext);
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
- return useContext(ErrorContext);
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
@@ -55,16 +53,18 @@ const ContextProvider = ({ children }) => {
55
53
  clearCompilationCache();
56
54
  };
57
55
  }, []);
56
+ const previewValue = useMemo(() => ({
57
+ code,
58
+ setCode
59
+ }), [code, setCode]);
60
+ const errorValue = useMemo(() => ({
61
+ error,
62
+ setError
63
+ }), [error, setError]);
58
64
  return /* @__PURE__ */ jsx(PreviewContext.Provider, {
59
- value: {
60
- code,
61
- setCode
62
- },
65
+ value: previewValue,
63
66
  children: /* @__PURE__ */ jsx(ErrorContext.Provider, {
64
- value: {
65
- error,
66
- setError
67
- },
67
+ value: errorValue,
68
68
  children
69
69
  })
70
70
  });
@@ -119,6 +119,21 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
119
119
  doc.head.appendChild(fragment);
120
120
  }
121
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
+ });
122
137
  useEffect(() => {
123
138
  const $iframe = iframeRef.current;
124
139
  if (!$iframe) return;
@@ -152,28 +167,11 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
152
167
  onLoaded?.();
153
168
  };
154
169
  $iframe.addEventListener("load", onLoad);
155
- let timeoutId;
156
- let observer = null;
157
- if (syncStyle) {
158
- observer = new MutationObserver(() => {
159
- clearTimeout(timeoutId);
160
- timeoutId = window.setTimeout(applyStyle, 50);
161
- });
162
- observer.observe(document.head, {
163
- childList: true,
164
- subtree: true,
165
- attributes: true,
166
- attributeFilter: ["href"]
167
- });
168
- }
169
170
  if ($iframe.contentDocument?.readyState === "complete") onLoad();
170
171
  return () => {
171
172
  $iframe.removeEventListener("load", onLoad);
172
- observer?.disconnect();
173
- clearTimeout(timeoutId);
174
173
  };
175
174
  }, [
176
- syncStyle,
177
175
  scripts,
178
176
  onLoaded,
179
177
  applyStyle
@@ -207,66 +205,73 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
207
205
  for (let index = stylesheets.length; index < prevStylesheetCountRef.current; index++) doc.getElementById(`injected-stylesheet-${index}`)?.remove();
208
206
  prevStylesheetCountRef.current = stylesheets.length;
209
207
  }, [styles, stylesheets]);
210
- useEffect(() => {
208
+ const updateHeight = useCallback(() => {
211
209
  if (!shouldAutoHeight || !mountNode || !iframeRef.current) return;
212
210
  const iframe = iframeRef.current;
213
- const updateHeight = () => {
214
- const scrollParent = iframe.closest("[data-frame-container]");
215
- const savedScrollTop = scrollParent?.scrollTop ?? 0;
216
- iframe.style.height = "0px";
217
- let childrenHeight = 0;
218
- Array.from(mountNode.children).forEach((child) => {
219
- const el = child;
220
- childrenHeight = Math.max(childrenHeight, el.scrollHeight);
221
- });
222
- const win = iframe.contentDocument?.defaultView;
223
- mountNode.querySelectorAll("[data-floating-ui-focusable]").forEach((popup) => {
224
- if (popup.offsetHeight > 0) {
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) {
225
237
  let offsetY = 0;
226
- const transform = popup.style.transform;
238
+ const transform = el.style.transform;
227
239
  if (transform) {
228
240
  const match = transform.match(/translate\([^,]+,\s*([+-]?\d+(?:\.\d+)?)/);
229
241
  if (match?.[1]) offsetY = parseFloat(match[1]);
230
242
  }
231
- const estimatedHeight = offsetY + popup.offsetHeight;
243
+ const estimatedHeight = offsetY + el.offsetHeight;
232
244
  childrenHeight = Math.max(childrenHeight, estimatedHeight);
233
245
  }
234
- });
235
- if (win) Array.from(mountNode.children).forEach((child) => {
236
- const el = child;
237
- const style = win.getComputedStyle(el);
238
- if (style.position === "fixed" || style.position === "absolute") {
239
- if (el.offsetHeight > 0) {
240
- let offsetY = 0;
241
- const transform = el.style.transform;
242
- if (transform) {
243
- const match = transform.match(/translate\([^,]+,\s*([+-]?\d+(?:\.\d+)?)/);
244
- if (match?.[1]) offsetY = parseFloat(match[1]);
245
- }
246
- const estimatedHeight = offsetY + el.offsetHeight;
247
- childrenHeight = Math.max(childrenHeight, estimatedHeight);
248
- }
249
- }
250
- });
251
- const contentHeight = Math.max(mountNode.scrollHeight, childrenHeight);
252
- if (contentHeight > 0) iframe.style.height = `${Math.ceil(contentHeight)}px`;
253
- if (scrollParent) scrollParent.scrollTop = savedScrollTop;
254
- };
255
- updateHeight();
256
- const resizeObserver = new ResizeObserver(updateHeight);
257
- resizeObserver.observe(mountNode);
258
- const mutationObserver = new MutationObserver(updateHeight);
259
- mutationObserver.observe(mountNode, {
260
- childList: true,
261
- subtree: true,
262
- attributes: true,
263
- characterData: true
246
+ }
264
247
  });
265
- return () => {
266
- resizeObserver.disconnect();
267
- mutationObserver.disconnect();
268
- };
269
- }, [mountNode, shouldAutoHeight]);
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
+ });
270
275
  const content = mountNode ? createPortal(children(mountNode), mountNode) : null;
271
276
  return /* @__PURE__ */ jsx("iframe", {
272
277
  ref: iframeRef,
@@ -330,24 +335,34 @@ const Frame = ({ mode, children, ...restProps }) => {
330
335
 
331
336
  //#endregion
332
337
  //#region src/components/dnd/draggable.tsx
333
- const Draggable = ({ item, onAdd }) => {
334
- const { attributes, listeners, setNodeRef, transform, isDragging } = useDraggable({
338
+ const DraggableItem = ({ item, children }) => {
339
+ const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
335
340
  id: item.id,
336
341
  data: {
337
342
  type: "new-item",
338
343
  item
339
344
  }
340
345
  });
341
- return /* @__PURE__ */ jsx(Card, {
346
+ return children({
342
347
  ref: setNodeRef,
343
- style: transform ? { opacity: isDragging ? .5 : 1 } : void 0,
344
- ...listeners,
345
- ...attributes,
346
- className: cn("cursor-grab", "outline-none", "hover:border-blue-300 hover:shadow-md", isDragging && "opacity-50"),
347
- onDoubleClick: () => onAdd?.(item),
348
- children: item.name
348
+ dragProps: {
349
+ ...listeners,
350
+ ...attributes
351
+ },
352
+ isDragging
349
353
  });
350
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
+ });
351
366
 
352
367
  //#endregion
353
368
  //#region src/components/dnd/droppable.tsx
@@ -459,7 +474,7 @@ const Overlay = ({ sections, renderProps }) => {
459
474
  if (!active) return null;
460
475
  if (active.data.current?.type === "new-item") {
461
476
  const item = active.data.current.item;
462
- return /* @__PURE__ */ jsx(Draggable, { item });
477
+ return /* @__PURE__ */ jsx(DefaultDraggableItem, { item });
463
478
  }
464
479
  const section = sections.find((s) => s.id === active.id);
465
480
  if (section) {
@@ -12606,7 +12621,7 @@ const conditionalModifiers = (args) => {
12606
12621
  if (active?.data.current?.type === "new-item") return args.transform;
12607
12622
  return restrictToVerticalAxis(args);
12608
12623
  };
12609
- 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 }) => {
12610
12625
  const [selectedId, setSelectedId] = useState(null);
12611
12626
  const [mobilePaletteOpen, setMobilePaletteOpen] = useState(false);
12612
12627
  const { breakpoint } = useResponsiveSize();
@@ -12706,14 +12721,35 @@ const Dnd = ({ value: _value, props, modules = {}, onChange: _onChange, classNam
12706
12721
  useEffect(() => {
12707
12722
  if (frame?.scripts?.length) preloadScripts(frame.scripts);
12708
12723
  }, [frame?.scripts]);
12709
- const renderPaletteItems = (onAdd) => /* @__PURE__ */ jsx(Space, {
12710
- orientation: "vertical",
12711
- align: "start",
12712
- children: (items?.length ? items : DRAGGABLE_ITEMS).map((item) => /* @__PURE__ */ jsx(Draggable, {
12713
- item,
12714
- onAdd
12715
- }, item.id))
12716
- });
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
+ };
12717
12753
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(DndContext, {
12718
12754
  sensors,
12719
12755
  collisionDetection: closestCenter,
@@ -12772,11 +12808,7 @@ const Dnd = ({ value: _value, props, modules = {}, onChange: _onChange, classNam
12772
12808
  }),
12773
12809
  /* @__PURE__ */ jsx("div", {
12774
12810
  className: "hidden w-1/5 md:block",
12775
- children: /* @__PURE__ */ jsx(Panel, {
12776
- item: sections.find((s) => s.id === selectedId),
12777
- onChange,
12778
- onDelete
12779
- })
12811
+ children: renderPanelContent()
12780
12812
  }),
12781
12813
  /* @__PURE__ */ jsx(Button, {
12782
12814
  type: "primary",
@@ -12803,11 +12835,7 @@ const Dnd = ({ value: _value, props, modules = {}, onChange: _onChange, classNam
12803
12835
  direction: "bottom",
12804
12836
  size: "large",
12805
12837
  title: "Properties",
12806
- children: /* @__PURE__ */ jsx(Panel, {
12807
- item: sections.find((s) => s.id === selectedId),
12808
- onChange,
12809
- onDelete
12810
- })
12838
+ children: renderPanelContent()
12811
12839
  })
12812
12840
  ]
12813
12841
  }), /* @__PURE__ */ jsx(DragOverlay, { children: /* @__PURE__ */ jsx(Overlay, {
@@ -12822,6 +12850,11 @@ const Dnd = ({ value: _value, props, modules = {}, onChange: _onChange, classNam
12822
12850
  }) });
12823
12851
  };
12824
12852
 
12853
+ //#endregion
12854
+ //#region src/components/dnd/index.ts
12855
+ const Dnd = Dnd$1;
12856
+ Dnd.DraggableItem = DraggableItem;
12857
+
12825
12858
  //#endregion
12826
12859
  //#region src/components/editor/editor.tsx
12827
12860
  const Editor$1 = ({ defaultValue, value: _value, debounce = 1e3, onChange: _onChange, ...props }) => {
@@ -12837,9 +12870,10 @@ const Editor$1 = ({ defaultValue, value: _value, debounce = 1e3, onChange: _onCh
12837
12870
  const onError = useCallback((error) => {
12838
12871
  setError(error);
12839
12872
  }, [setError]);
12840
- useDebounce(() => {
12841
- setCode(value);
12842
- }, { delay: debounce }, [value]);
12873
+ const debouncedValue = useDebouncedValue(value, debounce);
12874
+ useEffect(() => {
12875
+ setCode(debouncedValue);
12876
+ }, [debouncedValue, setCode]);
12843
12877
  return /* @__PURE__ */ jsx(Core, {
12844
12878
  value,
12845
12879
  onChange,
@@ -12948,21 +12982,20 @@ const Guard = ({ children, onError }) => {
12948
12982
  const [error, setError] = useState(null);
12949
12983
  const containerRef = useRef(null);
12950
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 });
12951
12997
  useEffect(() => {
12952
12998
  if (!containerRef.current) return;
12953
- const handleWindowError = (event) => {
12954
- if (errorHandled.current) return;
12955
- errorHandled.current = true;
12956
- const errorMessage = event.error?.message || event.message || "Unknown error";
12957
- console.error("⚡ [Guard] Event handler error:", errorMessage);
12958
- event.preventDefault();
12959
- setError(errorMessage);
12960
- onError?.(event.error || new window.Error(errorMessage));
12961
- setTimeout(() => {
12962
- errorHandled.current = false;
12963
- }, 100);
12964
- return true;
12965
- };
12966
12999
  const handleUnhandledRejection = (event) => {
12967
13000
  if (errorHandled.current) return;
12968
13001
  errorHandled.current = true;
@@ -12974,10 +13007,8 @@ const Guard = ({ children, onError }) => {
12974
13007
  errorHandled.current = false;
12975
13008
  }, 100);
12976
13009
  };
12977
- window.addEventListener("error", handleWindowError, true);
12978
13010
  window.addEventListener("unhandledrejection", handleUnhandledRejection, true);
12979
13011
  return () => {
12980
- window.removeEventListener("error", handleWindowError, true);
12981
13012
  window.removeEventListener("unhandledrejection", handleUnhandledRejection, true);
12982
13013
  };
12983
13014
  }, [onError]);
@@ -13000,16 +13031,12 @@ const Guard = ({ children, onError }) => {
13000
13031
  //#region src/components/error/runtime.tsx
13001
13032
  const Runtime = ({ open = true, reset }) => {
13002
13033
  const { error: message, setError } = useError();
13034
+ useEventListener("error", (e) => {
13035
+ setError(e.message);
13036
+ e.preventDefault();
13037
+ });
13003
13038
  useEffect(() => {
13004
- const onError = (e) => {
13005
- setError(e.message);
13006
- e.preventDefault();
13007
- };
13008
- window.addEventListener("error", onError);
13009
- return () => {
13010
- setError(null);
13011
- window.removeEventListener("error", onError);
13012
- };
13039
+ return () => setError(null);
13013
13040
  }, [setError]);
13014
13041
  if (!open) return null;
13015
13042
  return /* @__PURE__ */ jsx(Error$2, {