@jbpark/live-editor 1.12.0 → 1.14.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.
@@ -1,4 +1,16 @@
1
- import { n as Section } from "./index-C8h8TcIl.mjs";
1
+ //#region src/types/index.d.ts
2
+ interface Module {
3
+ exports: {
4
+ default?: React.ComponentType<Record<string, unknown>>;
5
+ };
6
+ error?: string;
7
+ }
8
+ interface Section {
9
+ id: string;
10
+ name: string;
11
+ code: string;
12
+ }
13
+ //#endregion
2
14
  //#region node_modules/.pnpm/@babel+types@7.29.8/node_modules/@babel/types/lib/index-legacy.d.ts
3
15
  // NOTE: This file is autogenerated. Do not modify.
4
16
  // See packages/babel-types/scripts/generators/typescript-legacy.ts for script used.
@@ -1516,5 +1528,5 @@ interface SectionPreviewCache {
1516
1528
  }
1517
1529
  declare const createSectionPreviewCache: () => SectionPreviewCache;
1518
1530
  //#endregion
1519
- export { generateDocumentCode as a, getSections as c, ArrayExpression as d, Expression as f, ObjectExpression as h, createSectionPreviewCache as i, parseDocument as l, Node as m, SectionPreviewCache as n, generateSectionPreview as o, File as p, clearDocumentParseCache as r, generateSectionPreviews as s, DocumentTree as t, replaceDocumentSections as u };
1520
- //# sourceMappingURL=document-BVWq-dmf.d.mts.map
1531
+ export { Section as _, generateDocumentCode as a, getSections as c, ArrayExpression as d, Expression as f, Module as g, ObjectExpression as h, createSectionPreviewCache as i, parseDocument as l, Node as m, SectionPreviewCache as n, generateSectionPreview as o, File as p, clearDocumentParseCache as r, generateSectionPreviews as s, DocumentTree as t, replaceDocumentSections as u };
1532
+ //# sourceMappingURL=document-DXOwpvWM.d.ts.map
@@ -1,4 +1,4 @@
1
- import { a as generateDocumentCode, c as getSections, d as ArrayExpression, f as Expression, h as ObjectExpression, i as createSectionPreviewCache, l as parseDocument, m as Node, n as SectionPreviewCache, o as generateSectionPreview, p as File, r as clearDocumentParseCache, s as generateSectionPreviews, t as DocumentTree, u as replaceDocumentSections } from "../../document-BVWq-dmf.mjs";
1
+ import { d as ArrayExpression, f as Expression, h as ObjectExpression, m as Node, p as File } from "./document-DXOwpvWM.js";
2
2
  //#region src/utils/ast/types.d.ts
3
3
  interface Attribute {
4
4
  name: string;
@@ -134,5 +134,5 @@ interface ValidationResult {
134
134
  }
135
135
  declare const validateBindingValue: (binding: BindingItem, value: unknown) => ValidationResult;
136
136
  //#endregion
137
- export { type BindingItem, type BindingOption, type BindingRenderLeaf, type BindingRenderMap, type BindingType, type DataAttrNode, type DocumentTree, type EditableNodeValueType, type ExtractedNodeValue, type NodeValueType, type SectionPreviewCache, type ValidationResult, arrayExpressionToCode, bulkUpdate, clearDocumentParseCache, clearExtractCache, clone, createNodeFromValue, createSectionPreviewCache, extract, extractNodeValue, extractObjectProperties, fillIds, findEditableChildren, generateCode, generateDocumentCode, generateSectionPreview, generateSectionPreviews, getCurrentValue, getSections, parseArrayExpression, parseBinding, parseDocument, parseValue, replaceDocumentSections, replaceIds, update, validateBindingValue };
138
- //# sourceMappingURL=index.d.mts.map
137
+ export { BindingRenderMap as C, ExtractedNodeValue as D, EditableNodeValueType as E, NodeValueType as O, BindingRenderLeaf as S, DataAttrNode as T, findEditableChildren as _, replaceIds as a, BindingItem as b, clearExtractCache as c, arrayExpressionToCode as d, createNodeFromValue as f, parseValue as g, parseArrayExpression as h, fillIds as i, extract as l, extractObjectProperties as m, validateBindingValue as n, bulkUpdate as o, extractNodeValue as p, clone as r, update as s, ValidationResult as t, generateCode as u, getCurrentValue as v, BindingType as w, BindingOption as x, parseBinding as y };
138
+ //# sourceMappingURL=index-BVjSMVya.d.ts.map
@@ -1,4 +1,5 @@
1
- import { n as Section } from "./index-C8h8TcIl.mjs";
1
+ import { _ as Section } from "./document-DXOwpvWM.js";
2
+ import { w as BindingType, x as BindingOption } from "./index-BVjSMVya.js";
2
3
  import "@jbpark/ui-kit/style.css";
3
4
  import React$1, { ReactNode } from "react";
4
5
  import { Extension } from "@uiw/react-codemirror";
@@ -135,11 +136,26 @@ interface PaletteRenderData {
135
136
  items: Section[];
136
137
  onAdd: (item: Section) => void;
137
138
  DraggableItem: typeof DraggableItem;
139
+ isMobile: boolean;
138
140
  }
139
141
  interface PanelRenderData {
140
142
  item?: Section;
141
143
  onChange: (next: Partial<Section>) => void;
142
144
  onDelete: (id: string) => void;
145
+ onMoveUp: () => void;
146
+ onMoveDown: () => void;
147
+ canMoveUp: boolean;
148
+ canMoveDown: boolean;
149
+ bindings: PanelBinding[];
150
+ }
151
+ interface PanelBinding {
152
+ id: string;
153
+ label: string;
154
+ property: string;
155
+ type?: BindingType;
156
+ options?: BindingOption[];
157
+ value: string;
158
+ onChange: (value: string) => void;
143
159
  }
144
160
  interface Props extends Omit<React.ComponentPropsWithRef<'div'>, 'onChange'> {
145
161
  value?: string;
@@ -182,4 +198,4 @@ declare const App: {
182
198
  declare const LiveRenderer: ({ code, props, modules, dynamicTailwind, provider, ...restProps }: Props$7) => import("react").JSX.Element;
183
199
  //#endregion
184
200
  export { Dnd as LiveDnd, Editor as LiveEditor, Error$1 as LiveError, Preview as LivePreview, App as LiveProvider, App as default, LiveRenderer };
185
- //# sourceMappingURL=index.d.mts.map
201
+ //# sourceMappingURL=index.d.ts.map
@@ -1,7 +1,7 @@
1
- import { _ as DEFAULT_TEMPLATE, f as require_lib$1, m as BINDING_PROP, n as createSectionPreviewCache, p as require_lib, v as DRAGGABLE_ITEMS, x as __toESM } from "./document-DocoSXLT.mjs";
2
- import { a as detectTypeScript, d as replaceSections, i as compile, l as getCachedScriptBlob, n as clearCompilationCache, o as extractSections, r as cn, s as generateSection, t as baseModules, u as preloadScripts } from "./utils-DP9WPbBJ.mjs";
3
- import { _ as parseArrayExpression, c as extract, d as getCurrentValue, f as parseBinding, g as extractObjectProperties, h as extractNodeValue, i as replaceIds, l as nanoid, m as createNodeFromValue, n as clone, o as update, p as arrayExpressionToCode, r as fillIds, t as validateBindingValue, u as findEditableChildren, v as parseValue, y as generateCode } from "./ast-9E8pNi7j.mjs";
4
- import { t as generateTailwindCSS } from "./tailwind-CzPhj3D9.mjs";
1
+ import { _ as DEFAULT_TEMPLATE, f as require_lib$1, m as BINDING_PROP, n as createSectionPreviewCache, p as require_lib, v as DRAGGABLE_ITEMS, x as __toESM } from "./document-CSIscFpL.js";
2
+ import { a as detectTypeScript, d as replaceSections, i as compile, l as getCachedScriptBlob, n as clearCompilationCache, o as extractSections, r as cn, s as generateSection, t as baseModules, u as preloadScripts } from "./utils-B11t9ZYd.js";
3
+ import { _ as parseArrayExpression, c as extract, d as getCurrentValue, f as parseBinding, g as extractObjectProperties, h as extractNodeValue, i as replaceIds, l as nanoid, m as createNodeFromValue, n as clone, o as update, p as arrayExpressionToCode, r as fillIds, t as validateBindingValue, u as findEditableChildren, v as parseValue, y as generateCode } from "./ast-Dq1EfxA5.js";
4
+ import { t as generateTailwindCSS } from "./tailwind-CzPhj3D9.js";
5
5
  import "@jbpark/ui-kit/style.css";
6
6
  import React, { createContext, memo, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
7
7
  import { Button, Card, Checkbox, ColorPicker, DatePicker, Drawer, Input, Select, Space, Toast, Typography, Upload } from "@jbpark/ui-kit";
@@ -10,7 +10,7 @@ import { DndContext, DragOverlay, PointerSensor, closestCenter, useDndContext, u
10
10
  import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
11
11
  import { SortableContext, arrayMove, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
12
12
  import { useDebounce, useDebouncedValue, useEventListener, useMultiSelect, useMutationObserver, useResizeObserver, useResponsiveSize } from "@jbpark/use-hooks";
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";
13
+ import { AlertCircle, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Bell, Bookmark, Calendar, Camera, Check, ChevronDown, ChevronRight, ChevronUp, Clock, Copy, Download, Edit, Eye, Filter, Heart, Home, Image, Info, LayoutGrid, Link, Mail, Map as Map$1, Menu, MessageCircle, Phone, Plus, Search, Settings, Share, ShoppingCart, Star, Trash, Upload as Upload$1, User, X } from "lucide-react";
14
14
  import { v4 } from "uuid";
15
15
  import { createPortal } from "react-dom";
16
16
  import { CSS } from "@dnd-kit/utilities";
@@ -100,6 +100,20 @@ const UNIT_MAP = {
100
100
  const UNITS_PATTERN = Object.keys(UNIT_MAP).sort((a, b) => b.length - a.length).join("|");
101
101
  const VIEWPORT_UNIT_RE = new RegExp(`(?<![\\w.-])(-?(?:\\d+\\.?\\d*|\\.\\d+))(${UNITS_PATTERN})(?![a-zA-Z0-9_-])`, "gi");
102
102
  const convertViewportUnits = (css) => css.replace(VIEWPORT_UNIT_RE, (_match, number, unit) => number + UNIT_MAP[unit.toLowerCase()]);
103
+ const rewriteInlineViewportUnits = (root) => {
104
+ root.querySelectorAll("[style*=\"vh\" i], [style*=\"vmin\" i], [style*=\"vmax\" i]").forEach((el) => {
105
+ const current = el.getAttribute("style");
106
+ if (current == null) return;
107
+ const converted = convertViewportUnits(current);
108
+ if (converted !== current) el.setAttribute("style", converted);
109
+ });
110
+ root.querySelectorAll("style").forEach((styleEl) => {
111
+ const current = styleEl.textContent;
112
+ if (!current) return;
113
+ const converted = convertViewportUnits(current);
114
+ if (converted !== current) styleEl.textContent = converted;
115
+ });
116
+ };
103
117
  //#endregion
104
118
  //#region src/components/frame/iframe.tsx
105
119
  const EMPTY_STRING_ARRAY = [];
@@ -237,6 +251,7 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
237
251
  prevStylesheetCountRef.current = stylesheets.length;
238
252
  }, [styles, stylesheets]);
239
253
  const CONTAINER_STYLE_ID = "autoheight-container";
254
+ const HIDE_SCROLLBAR_STYLE_ID = "autoheight-hide-scrollbar";
240
255
  const ensureContainerStyle = (doc, probeHeight) => {
241
256
  let styleEl = doc.getElementById(CONTAINER_STYLE_ID);
242
257
  if (!styleEl) {
@@ -288,6 +303,7 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
288
303
  let contentHeight = 0;
289
304
  withMeasurementOverrides(doc, () => {
290
305
  ensureContainerStyle(doc, probeHeight);
306
+ rewriteInlineViewportUnits(mountNode);
291
307
  contentHeight = mountNode.scrollHeight;
292
308
  mountNode.querySelectorAll("*").forEach((el) => {
293
309
  const style = win.getComputedStyle(el);
@@ -304,6 +320,20 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
304
320
  if (shouldAutoHeight) return;
305
321
  iframeRef.current?.contentDocument?.getElementById(CONTAINER_STYLE_ID)?.remove();
306
322
  }, [shouldAutoHeight]);
323
+ useEffect(() => {
324
+ const doc = iframeRef.current?.contentDocument;
325
+ if (!doc?.head) return;
326
+ const existing = doc.getElementById(HIDE_SCROLLBAR_STYLE_ID);
327
+ if (!shouldAutoHeight) {
328
+ existing?.remove();
329
+ return;
330
+ }
331
+ if (existing) return;
332
+ const styleEl = doc.createElement("style");
333
+ styleEl.id = HIDE_SCROLLBAR_STYLE_ID;
334
+ styleEl.textContent = ["html, body { scrollbar-width: none !important; }", "html::-webkit-scrollbar, body::-webkit-scrollbar { display: none !important; }"].join("\n");
335
+ doc.head.appendChild(styleEl);
336
+ }, [shouldAutoHeight, mountNode]);
307
337
  useEffect(() => {
308
338
  updateHeight();
309
339
  }, [updateHeight]);
@@ -405,13 +435,14 @@ const DraggableItem = ({ item, children }) => {
405
435
  isDragging
406
436
  });
407
437
  };
408
- const DefaultDraggableItem = ({ item, onAdd }) => /* @__PURE__ */ jsx(DraggableItem, {
438
+ const DefaultDraggableItem = ({ item, onAdd, tapToAdd = false }) => /* @__PURE__ */ jsx(DraggableItem, {
409
439
  item,
410
440
  children: ({ ref, dragProps, isDragging }) => /* @__PURE__ */ jsx(Card, {
411
441
  ref,
412
442
  style: { opacity: isDragging ? .5 : 1 },
413
443
  ...dragProps,
414
444
  className: cn("cursor-grab", "outline-none", "hover:border-blue-300 hover:shadow-md", isDragging && "opacity-50"),
445
+ onClick: tapToAdd && onAdd ? () => onAdd(item) : void 0,
415
446
  onDoubleClick: onAdd ? () => onAdd(item) : void 0,
416
447
  children: item.name
417
448
  })
@@ -12861,33 +12892,7 @@ const Node = ({ data, onChange }) => {
12861
12892
  };
12862
12893
  //#endregion
12863
12894
  //#region src/components/dnd/panel/panel.tsx
12864
- const Panel = ({ item, onChange, onDelete }) => {
12865
- const code = item?.code;
12866
- const { dataAttrNodes, updatedCode, parseError } = useMemo(() => {
12867
- if (!code) return {
12868
- dataAttrNodes: [],
12869
- updatedCode: "",
12870
- parseError: false
12871
- };
12872
- try {
12873
- const updatedCode = fillIds(code);
12874
- return {
12875
- dataAttrNodes: extract(updatedCode).filter((node) => node.tagName !== "section"),
12876
- updatedCode: updatedCode !== code ? updatedCode : code,
12877
- parseError: false
12878
- };
12879
- } catch (e) {
12880
- console.warn("⚠️ Parsing error", e);
12881
- return {
12882
- dataAttrNodes: [],
12883
- updatedCode: "",
12884
- parseError: true
12885
- };
12886
- }
12887
- }, [code]);
12888
- useEffect(() => {
12889
- if (parseError) Toast.error("Failed to parse this section", { description: "Check the console for details." });
12890
- }, [parseError]);
12895
+ const Panel = ({ item, onDelete, onMoveUp, onMoveDown, canMoveUp = false, canMoveDown = false, fields, onFieldChange }) => {
12891
12896
  if (!item) return /* @__PURE__ */ jsx(Typography.Paragraph, {
12892
12897
  className: cn("p-4 text-sm text-gray-500"),
12893
12898
  children: "Please select a section."
@@ -12900,29 +12905,37 @@ const Panel = ({ item, onChange, onDelete }) => {
12900
12905
  children: [/* @__PURE__ */ jsx(Typography.Title, {
12901
12906
  className: "text-lg font-semibold",
12902
12907
  children: item.name
12903
- }), onDelete && /* @__PURE__ */ jsx(Button, {
12904
- danger: true,
12905
- icon: /* @__PURE__ */ jsx(Trash, {}),
12906
- onClick: () => onDelete(item.id)
12908
+ }), /* @__PURE__ */ jsxs("div", {
12909
+ className: "flex items-center gap-1",
12910
+ children: [
12911
+ onMoveUp && /* @__PURE__ */ jsx(Button, {
12912
+ icon: /* @__PURE__ */ jsx(ChevronUp, {}),
12913
+ disabled: !canMoveUp,
12914
+ onClick: onMoveUp,
12915
+ "aria-label": "Move section up"
12916
+ }),
12917
+ onMoveDown && /* @__PURE__ */ jsx(Button, {
12918
+ icon: /* @__PURE__ */ jsx(ChevronDown, {}),
12919
+ disabled: !canMoveDown,
12920
+ onClick: onMoveDown,
12921
+ "aria-label": "Move section down"
12922
+ }),
12923
+ onDelete && /* @__PURE__ */ jsx(Button, {
12924
+ danger: true,
12925
+ icon: /* @__PURE__ */ jsx(Trash, {}),
12926
+ onClick: () => onDelete(item.id),
12927
+ "aria-label": "Delete section"
12928
+ })
12929
+ ]
12907
12930
  })]
12908
12931
  }),
12909
- !dataAttrNodes.length && /* @__PURE__ */ jsx(Typography.Text, {
12932
+ !fields.length && /* @__PURE__ */ jsx(Typography.Text, {
12910
12933
  className: "text-xs text-gray-400",
12911
12934
  children: "No editable elements."
12912
12935
  }),
12913
- dataAttrNodes.map((node, index) => /* @__PURE__ */ jsx(Node, {
12936
+ fields.map((node, index) => /* @__PURE__ */ jsx(Node, {
12914
12937
  data: node,
12915
- onChange: ({ id, label, value }) => {
12916
- const result = update(updatedCode, id, label, value);
12917
- if (!result.success) {
12918
- Toast.error("Failed to update this field", { description: "Check the console for details." });
12919
- return;
12920
- }
12921
- onChange?.({
12922
- ...item,
12923
- code: result.code
12924
- });
12925
- }
12938
+ onChange: onFieldChange
12926
12939
  }, `${item.id}-${index}`))
12927
12940
  ]
12928
12941
  });
@@ -12943,6 +12956,7 @@ const Dnd$1 = ({ value: _value, props, modules = {}, onChange: _onChange, classN
12943
12956
  const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 10 } }));
12944
12957
  const value = _value || DEFAULT_TEMPLATE;
12945
12958
  const sections = useMemo(() => extractSections(value), [value]);
12959
+ const selectedItem = useMemo(() => sections.find((s) => s.id === selectedId), [sections, selectedId]);
12946
12960
  const [previewCache] = useState(() => createSectionPreviewCache());
12947
12961
  const previews = useMemo(() => previewCache.compute(value, sections), [
12948
12962
  previewCache,
@@ -13006,6 +13020,16 @@ const Dnd$1 = ({ value: _value, props, modules = {}, onChange: _onChange, classN
13006
13020
  _onChange?.(nextCode);
13007
13021
  setCode(nextCode);
13008
13022
  };
13023
+ const moveSection = (id, direction) => {
13024
+ const index = sections.findIndex((s) => s.id === id);
13025
+ const targetIndex = direction === "up" ? index - 1 : index + 1;
13026
+ if (index < 0 || targetIndex < 0 || targetIndex >= sections.length) return;
13027
+ const nextSections = arrayMove(sections, index, targetIndex);
13028
+ const nextCode = replaceSections(value, nextSections.map((s) => s.code));
13029
+ _onChange?.(nextCode);
13030
+ setCode(nextCode);
13031
+ setSelectedId(String(targetIndex));
13032
+ };
13009
13033
  const onCopy = (id) => {
13010
13034
  const sectionIndex = sections.findIndex((s) => s.id === id);
13011
13035
  const sectionToCopy = sections[sectionIndex];
@@ -13039,36 +13063,107 @@ const Dnd$1 = ({ value: _value, props, modules = {}, onChange: _onChange, classN
13039
13063
  _onChange?.(nextCode);
13040
13064
  setCode(nextCode);
13041
13065
  };
13066
+ const selectedCode = selectedItem?.code;
13067
+ const { fields, updatedCode, parseError } = useMemo(() => {
13068
+ if (!selectedCode) return {
13069
+ fields: [],
13070
+ updatedCode: "",
13071
+ parseError: false
13072
+ };
13073
+ try {
13074
+ const updated = fillIds(selectedCode);
13075
+ return {
13076
+ fields: extract(updated).filter((node) => node.tagName !== "section"),
13077
+ updatedCode: updated !== selectedCode ? updated : selectedCode,
13078
+ parseError: false
13079
+ };
13080
+ } catch (e) {
13081
+ console.warn("⚠️ Parsing error", e);
13082
+ return {
13083
+ fields: [],
13084
+ updatedCode: "",
13085
+ parseError: true
13086
+ };
13087
+ }
13088
+ }, [selectedCode]);
13089
+ useEffect(() => {
13090
+ if (parseError) Toast.error("Failed to parse this section", { description: "Check the console for details." });
13091
+ }, [parseError]);
13092
+ const onFieldChange = ({ id, label, value: fieldValue }) => {
13093
+ const result = update(updatedCode, id, label, fieldValue);
13094
+ if (!result.success) {
13095
+ Toast.error("Failed to update this field", { description: "Check the console for details." });
13096
+ return;
13097
+ }
13098
+ if (selectedItem) onChange({
13099
+ ...selectedItem,
13100
+ code: result.code
13101
+ });
13102
+ };
13103
+ const bindings = useMemo(() => {
13104
+ return fields.flatMap((node) => {
13105
+ const dataId = node.dataAttributes.find((a) => a.name === "data-id")?.value;
13106
+ const bindingAttr = node.dataAttributes.find((a) => a.name === "data-binding")?.value;
13107
+ if (!dataId || !bindingAttr) return [];
13108
+ return (node.bindings ?? parseBinding(bindingAttr)).map((binding) => ({
13109
+ id: dataId,
13110
+ label: binding.label,
13111
+ property: binding.property,
13112
+ type: binding.type,
13113
+ options: binding.options,
13114
+ value: getCurrentValue(node, binding.property),
13115
+ onChange: (value) => onFieldChange({
13116
+ id: dataId,
13117
+ label: binding.label,
13118
+ value
13119
+ })
13120
+ }));
13121
+ });
13122
+ }, [fields]);
13042
13123
  useEffect(() => {
13043
13124
  if (frame?.scripts?.length) preloadScripts(frame.scripts);
13044
13125
  }, [frame?.scripts]);
13045
- const renderPaletteItems = (onAdd) => {
13126
+ const renderPaletteItems = (onAdd, forMobileDrawer = false) => {
13046
13127
  const paletteItems = items?.length ? items : DRAGGABLE_ITEMS;
13047
13128
  if (renderPalette) return renderPalette({
13048
13129
  items: paletteItems,
13049
13130
  onAdd,
13050
- DraggableItem
13131
+ DraggableItem,
13132
+ isMobile: forMobileDrawer
13051
13133
  });
13052
13134
  return /* @__PURE__ */ jsx(Space, {
13053
13135
  orientation: "vertical",
13054
13136
  align: "start",
13055
13137
  children: paletteItems.map((item) => /* @__PURE__ */ jsx(DefaultDraggableItem, {
13056
13138
  item,
13057
- onAdd
13139
+ onAdd,
13140
+ tapToAdd: forMobileDrawer
13058
13141
  }, item.id))
13059
13142
  });
13060
13143
  };
13061
13144
  const renderPanelContent = () => {
13062
- const selectedItem = sections.find((s) => s.id === selectedId);
13145
+ const selectedIndex = sections.findIndex((s) => s.id === selectedId);
13146
+ const canMoveUp = selectedIndex > 0;
13147
+ const canMoveDown = selectedIndex >= 0 && selectedIndex < sections.length - 1;
13063
13148
  if (renderPanel) return renderPanel({
13064
13149
  item: selectedItem,
13065
13150
  onChange,
13066
- onDelete
13151
+ onDelete,
13152
+ onMoveUp: () => moveSection(selectedId, "up"),
13153
+ onMoveDown: () => moveSection(selectedId, "down"),
13154
+ canMoveUp,
13155
+ canMoveDown,
13156
+ bindings
13067
13157
  });
13068
13158
  return /* @__PURE__ */ jsx(Panel, {
13069
13159
  item: selectedItem,
13070
- onChange,
13071
- onDelete
13160
+ onDelete,
13161
+ onMoveUp: () => moveSection(selectedId, "up"),
13162
+ onMoveDown: () => moveSection(selectedId, "down"),
13163
+ canMoveUp,
13164
+ canMoveDown,
13165
+ fields,
13166
+ onFieldChange
13072
13167
  });
13073
13168
  };
13074
13169
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(DndContext, {
@@ -13148,7 +13243,7 @@ const Dnd$1 = ({ value: _value, props, modules = {}, onChange: _onChange, classN
13148
13243
  children: renderPaletteItems((item) => {
13149
13244
  addItem(item);
13150
13245
  setMobilePaletteOpen(false);
13151
- })
13246
+ }, true)
13152
13247
  }),
13153
13248
  /* @__PURE__ */ jsx(Drawer, {
13154
13249
  open: isMobile && Boolean(selectedId),
@@ -13528,4 +13623,4 @@ App.Dnd = Dnd;
13528
13623
  //#endregion
13529
13624
  export { Dnd as LiveDnd, Editor as LiveEditor, Error$1 as LiveError, Preview as LivePreview, App as LiveProvider, App as default, LiveRenderer };
13530
13625
 
13531
- //# sourceMappingURL=index.mjs.map
13626
+ //# sourceMappingURL=index.js.map