@jbpark/live-editor 4.4.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +2 -2
  2. package/dist/{boundary-B17cepvm.js → boundary-DnjGgsK6.js} +8 -5
  3. package/dist/boundary-DnjGgsK6.js.map +1 -0
  4. package/dist/{context-DB5kW3qe.js → context-DsEXJl4h.js} +10 -4
  5. package/dist/context-DsEXJl4h.js.map +1 -0
  6. package/dist/dnd/index.d.ts +1 -1
  7. package/dist/dnd/index.js +1 -1
  8. package/dist/{dnd-BE5ZizqX.js → dnd-DGNp20Nk.js} +370 -305
  9. package/dist/dnd-DGNp20Nk.js.map +1 -0
  10. package/dist/{document-BDn_f08_.js → document-DGHTfrda.js} +7738 -7735
  11. package/dist/document-DGHTfrda.js.map +1 -0
  12. package/dist/error/index.d.ts +1 -1
  13. package/dist/error/index.js +2 -2
  14. package/dist/{error-DWhxQEom.js → error-DwqwjJ2C.js} +13 -6
  15. package/dist/error-DwqwjJ2C.js.map +1 -0
  16. package/dist/{index-f7ijuNTa.d.ts → index-CHknA6k1.d.ts} +108 -154
  17. package/dist/{index-Dgh1JTX3.d.ts → index-P9Aifaui.d.ts} +3 -2
  18. package/dist/index-WQgFy510.d.ts +11 -0
  19. package/dist/{index-C4SGQ3Ci.d.ts → index-vtyggWy0.d.ts} +4 -1
  20. package/dist/index.d.ts +18 -18
  21. package/dist/index.js +11 -7
  22. package/dist/index.js.map +1 -1
  23. package/dist/{ast-dYb78955.js → items-DdrwGxJw.js} +324 -373
  24. package/dist/items-DdrwGxJw.js.map +1 -0
  25. package/dist/messages-Cp3g1mn1.d.ts +129 -0
  26. package/dist/messages-CzUPVnzH.js +132 -0
  27. package/dist/messages-CzUPVnzH.js.map +1 -0
  28. package/dist/preview/index.js +2 -2
  29. package/dist/{preview-BnaCEFsF.js → preview-BKFgq_5u.js} +6 -4
  30. package/dist/preview-BKFgq_5u.js.map +1 -0
  31. package/dist/provider/index.d.ts +3 -8
  32. package/dist/provider/index.js +3 -2
  33. package/dist/{sections-CBVMO8Jl.js → sections-BRH3KHYc.js} +8 -3
  34. package/dist/sections-BRH3KHYc.js.map +1 -0
  35. package/dist/style.css +505 -21
  36. package/dist/{use-dynamic-tailwind-Bcipc1hL.js → use-dynamic-tailwind-T9r9ExbR.js} +9 -3
  37. package/dist/{use-dynamic-tailwind-Bcipc1hL.js.map → use-dynamic-tailwind-T9r9ExbR.js.map} +1 -1
  38. package/dist/utils/ast/index.d.ts +3 -2
  39. package/dist/utils/ast/index.js +66 -3
  40. package/dist/utils/ast/index.js.map +1 -0
  41. package/dist/utils/index.d.ts +30 -13
  42. package/dist/utils/index.js +26 -6
  43. package/dist/utils/index.js.map +1 -0
  44. package/dist/validate-DB59Z_Nx.d.ts +100 -0
  45. package/dist/validate-iLo8IONY.js +64 -0
  46. package/dist/validate-iLo8IONY.js.map +1 -0
  47. package/package.json +3 -3
  48. package/dist/ast-dYb78955.js.map +0 -1
  49. package/dist/boundary-B17cepvm.js.map +0 -1
  50. package/dist/context-DB5kW3qe.js.map +0 -1
  51. package/dist/dnd-BE5ZizqX.js.map +0 -1
  52. package/dist/document-BDn_f08_.js.map +0 -1
  53. package/dist/error-DWhxQEom.js.map +0 -1
  54. package/dist/preview-BnaCEFsF.js.map +0 -1
  55. package/dist/sections-CBVMO8Jl.js.map +0 -1
@@ -1,13 +1,15 @@
1
- import { S as require_lib, _ as nanoid, c as inspectDocument, h as replaceIds, m as fillIdsFrom, n as createSectionPreviewCache, r as fillSectionIds, w as __toESM } from "./document-BDn_f08_.js";
1
+ import { S as require_lib, c as inspectDocument, h as replaceIds, m as fillIdsFrom, n as createSectionPreviewCache, r as fillSectionIds, w as __toESM, x as nanoid } from "./document-DGHTfrda.js";
2
2
  import { c as RESERVED_BINDING_PROPERTIES, o as DRAGGABLE_ITEMS, r as DATA_ATTR, t as BINDING_PROP } from "./constants-h1JAgOeW.js";
3
+ import { n as validateBindingValue } from "./validate-iLo8IONY.js";
4
+ import { i as useLiveMessages } from "./messages-CzUPVnzH.js";
3
5
  import { i as usePreview } from "./states-Ci1AvoQ9.js";
4
- import { E as readNodeBindings, F as parseValue, M as extractObjectProperties, P as parseArrayExpression, S as getStructuredValue, _ as moveSelectedIndices, a as getChildrenSignatures, c as appendArrayItem, d as moveArrayItems, g as canStructurallyEditArray, h as updateArrayItemValue, i as updateAll, j as extractNodeValue, k as canLosslesslyEvaluateSource, l as duplicateArrayItems, m as updateArrayItemProperty, p as removeArrayItems, s as extract, t as validateBindingValue, u as moveArrayItem, v as findEditableChildren, y as getCurrentValue } from "./ast-dYb78955.js";
6
+ import { A as extractNodeValue, N as parseArrayExpression, O as canLosslesslyEvaluateSource, P as parseValue, T as readNodeBindings, _ as findEditableChildren, c as updateArrayItemValue, f as updateAll, g as extract, i as moveArrayItems, j as extractObjectProperties, l as canStructurallyEditArray, m as moveSelectedIndices, n as duplicateArrayItems, o as removeArrayItems, p as getChildrenSignatures, r as moveArrayItem, s as updateArrayItemProperty, t as appendArrayItem, v as getCurrentValue, x as getStructuredValue } from "./items-DdrwGxJw.js";
5
7
  import { t as cn } from "./cn-CAnad2vL.js";
6
8
  import { o as preloadScripts } from "./compile-DDfk5P25.js";
7
- import { a as Frame, i as useStableModules, n as useCompiledModule, t as useDynamicTailwind } from "./use-dynamic-tailwind-Bcipc1hL.js";
9
+ import { a as Frame, i as useStableModules, n as useCompiledModule, t as useDynamicTailwind } from "./use-dynamic-tailwind-T9r9ExbR.js";
8
10
  import { t as Core } from "./core-CRsAGpei.js";
9
- import { a as replaceSections, n as extractSections, r as generateSection } from "./sections-CBVMO8Jl.js";
10
- import { n as Error$1, t as ErrorBoundary } from "./boundary-B17cepvm.js";
11
+ import { i as generateSection, o as replaceSections, r as extractSections } from "./sections-BRH3KHYc.js";
12
+ import { n as Error$1, t as ErrorBoundary } from "./boundary-DnjGgsK6.js";
11
13
  import { Children, createContext, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
12
14
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
13
15
  import { DndContext, DragOverlay, KeyboardSensor, MouseSensor, PointerSensor, TouchSensor, closestCenter, useDndContext, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
@@ -26,6 +28,7 @@ const Droppable = ({ children, className }) => {
26
28
  const isNewItemDragging = active?.data.current?.type === "new-item";
27
29
  const shouldHighlight = isOver && isNewItemDragging;
28
30
  const shouldHighlightBottom = isBottomOver && isNewItemDragging;
31
+ const messages = useLiveMessages();
29
32
  return /* @__PURE__ */ jsxs("div", {
30
33
  ref: setNodeRef,
31
34
  className: cn("min-h-full", "border-2 border-dashed p-1", shouldHighlight ? "border-blue-300 bg-blue-50" : "border-gray-200", className),
@@ -34,7 +37,7 @@ const Droppable = ({ children, className }) => {
34
37
  className: cn("mt-2 min-h-24", "rounded-lg border-2 border-dashed", "transition-all duration-200", "flex items-center justify-center", shouldHighlightBottom ? "border-blue-400 bg-blue-100" : "border-gray-300 bg-gray-50"),
35
38
  children: /* @__PURE__ */ jsx(Typography.Text, {
36
39
  className: "text-sm text-gray-500",
37
- children: shouldHighlightBottom ? "Drop here" : "Drag here to add at bottom"
40
+ children: shouldHighlightBottom ? messages.canvas.dropHere : messages.canvas.dropAtBottom
38
41
  })
39
42
  })]
40
43
  });
@@ -248,33 +251,34 @@ const withPanelCommit = (bindings, commit) => bindings.map((binding) => ({
248
251
  //#endregion
249
252
  //#region src/components/dnd/panel/bulk-actions-bar.tsx
250
253
  const BulkActionsBar = ({ count, disabled = false, onDuplicate, onMoveUp, onMoveDown, onDelete, onClear }) => {
254
+ const messages = useLiveMessages();
251
255
  if (count === 0) return null;
252
256
  return /* @__PURE__ */ jsxs("div", {
253
257
  className: "flex items-center justify-between rounded border\n border-blue-200 bg-blue-50 p-2",
254
- children: [/* @__PURE__ */ jsxs("div", {
258
+ children: [/* @__PURE__ */ jsx("div", {
255
259
  className: "text-xs font-medium text-blue-700",
256
- children: [count, " selected"]
260
+ children: messages.selection.count(count)
257
261
  }), /* @__PURE__ */ jsxs("div", {
258
262
  className: "flex items-center space-x-1",
259
263
  children: [
260
264
  /* @__PURE__ */ jsx(Button, {
261
265
  size: "small",
262
266
  icon: /* @__PURE__ */ jsx(Copy, {}),
263
- title: "Duplicate selected",
267
+ title: messages.selection.duplicate,
264
268
  disabled,
265
269
  onClick: onDuplicate
266
270
  }),
267
271
  /* @__PURE__ */ jsx(Button, {
268
272
  size: "small",
269
273
  icon: /* @__PURE__ */ jsx(ArrowUp, {}),
270
- title: "Move selected up",
274
+ title: messages.selection.moveUp,
271
275
  disabled,
272
276
  onClick: onMoveUp
273
277
  }),
274
278
  /* @__PURE__ */ jsx(Button, {
275
279
  size: "small",
276
280
  icon: /* @__PURE__ */ jsx(ArrowDown, {}),
277
- title: "Move selected down",
281
+ title: messages.selection.moveDown,
278
282
  disabled,
279
283
  onClick: onMoveDown
280
284
  }),
@@ -282,14 +286,14 @@ const BulkActionsBar = ({ count, disabled = false, onDuplicate, onMoveUp, onMove
282
286
  danger: true,
283
287
  size: "small",
284
288
  icon: /* @__PURE__ */ jsx(X, {}),
285
- title: "Delete selected",
289
+ title: messages.selection.delete,
286
290
  disabled,
287
291
  onClick: onDelete
288
292
  }),
289
293
  /* @__PURE__ */ jsx(Button, {
290
294
  size: "small",
291
295
  onClick: onClear,
292
- children: "Clear"
296
+ children: messages.selection.clear
293
297
  })
294
298
  ]
295
299
  })]
@@ -420,6 +424,7 @@ const useDndChildren = (items, { onChange } = {}) => {
420
424
  const Children$1 = ({ value, onChange, onNodeChange }) => {
421
425
  const items = useMemo(() => Array.isArray(value) ? value : [], [value]);
422
426
  const { selection, actions } = useDndChildren(items, { onChange });
427
+ const messages = useLiveMessages();
423
428
  const editableChildrenMap = useMemo(() => {
424
429
  const map = /* @__PURE__ */ new Map();
425
430
  items.forEach((item, index) => {
@@ -433,19 +438,15 @@ const Children$1 = ({ value, onChange, onNodeChange }) => {
433
438
  children: [
434
439
  /* @__PURE__ */ jsxs("div", {
435
440
  className: "flex items-center justify-between",
436
- children: [/* @__PURE__ */ jsxs("div", {
441
+ children: [/* @__PURE__ */ jsx("div", {
437
442
  className: "text-sm font-semibold text-green-700",
438
- children: [
439
- "Children Items (",
440
- items.length,
441
- ")"
442
- ]
443
+ children: messages.children.heading(items.length)
443
444
  }), /* @__PURE__ */ jsx(Button, {
444
445
  size: "small",
445
446
  color: "green",
446
447
  icon: /* @__PURE__ */ jsx(Plus, {}),
447
448
  onClick: actions.add,
448
- children: "Add Child"
449
+ children: messages.children.add
449
450
  })]
450
451
  }),
451
452
  /* @__PURE__ */ jsx(BulkActionsBar, {
@@ -470,15 +471,9 @@ const Children$1 = ({ value, onChange, onNodeChange }) => {
470
471
  checked: selection.isSelected(itemIndex),
471
472
  onChange: () => {}
472
473
  })
473
- }), /* @__PURE__ */ jsxs("div", {
474
+ }), /* @__PURE__ */ jsx("div", {
474
475
  className: "text-xs font-medium text-green-800",
475
- children: [
476
- "Child ",
477
- itemIndex + 1,
478
- " (",
479
- item.tagName || "fragment",
480
- ")"
481
- ]
476
+ children: messages.children.child(itemIndex + 1, item.tagName || "fragment")
482
477
  })]
483
478
  }), /* @__PURE__ */ jsxs("div", {
484
479
  className: "flex space-x-1",
@@ -486,17 +481,20 @@ const Children$1 = ({ value, onChange, onNodeChange }) => {
486
481
  /* @__PURE__ */ jsx(Button, {
487
482
  size: "small",
488
483
  icon: /* @__PURE__ */ jsx(ArrowUp, {}),
484
+ "aria-label": messages.children.moveUp,
489
485
  disabled: itemIndex === 0,
490
486
  onClick: () => actions.move(itemIndex, itemIndex - 1)
491
487
  }),
492
488
  /* @__PURE__ */ jsx(Button, {
493
489
  size: "small",
494
490
  icon: /* @__PURE__ */ jsx(ArrowDown, {}),
491
+ "aria-label": messages.children.moveDown,
495
492
  disabled: itemIndex === items.length - 1,
496
493
  onClick: () => actions.move(itemIndex, itemIndex + 1)
497
494
  }),
498
495
  /* @__PURE__ */ jsx(Button, {
499
- title: "Delete item",
496
+ "aria-label": messages.children.delete,
497
+ title: messages.children.delete,
500
498
  danger: true,
501
499
  size: "small",
502
500
  icon: /* @__PURE__ */ jsx(X, {}),
@@ -509,7 +507,7 @@ const Children$1 = ({ value, onChange, onNodeChange }) => {
509
507
  className: "space-y-2",
510
508
  children: [/* @__PURE__ */ jsx("div", {
511
509
  className: "text-xs font-medium text-green-700",
512
- children: "Editable Bindings:"
510
+ children: messages.children.editableBindings
513
511
  }), editableChildrenMap.get(itemIndex).map((editableNode, idx) => {
514
512
  const nodeId = editableNode.dataAttributes.find((a) => a.name === "data-id")?.value;
515
513
  return /* @__PURE__ */ jsxs("div", {
@@ -529,7 +527,7 @@ const Children$1 = ({ value, onChange, onNodeChange }) => {
529
527
  className: "space-y-1",
530
528
  children: [/* @__PURE__ */ jsx("div", {
531
529
  className: "text-xs font-medium text-green-700",
532
- children: "Child Nodes:"
530
+ children: messages.children.childNodes
533
531
  }), item.children.map((node, nodeIndex) => /* @__PURE__ */ jsx("div", {
534
532
  className: "ml-2 rounded border border-green-100 bg-white p-2",
535
533
  children: /* @__PURE__ */ jsx(Node, {
@@ -566,9 +564,9 @@ const getFieldKind = (binding) => {
566
564
  const isStructuralFieldKind = (kind) => kind === "items" || kind === "children";
567
565
  //#endregion
568
566
  //#region src/components/dnd/panel/sortable-items.tsx
569
- const label = (items, id) => {
567
+ const label = (messages, items, id) => {
570
568
  const index = items.findIndex((item) => item.id === id);
571
- return index >= 0 ? `Item ${index + 1}` : "Item";
569
+ return index >= 0 ? messages.items.item(index + 1) : String(id);
572
570
  };
573
571
  const SortableItems = ({ items, disabled, onMove, children }) => {
574
572
  const sensors = useSensors(useSensor(MouseSensor, { activationConstraint: { distance: 4 } }), useSensor(TouchSensor, { activationConstraint: {
@@ -580,15 +578,18 @@ const SortableItems = ({ items, disabled, onMove, children }) => {
580
578
  const to = items.find((item) => item.id === over?.id);
581
579
  if (from && to && from !== to) onMove(from, to.index);
582
580
  };
581
+ const messages = useLiveMessages();
582
+ const { announcements: say } = messages;
583
+ const name = (id) => label(messages, items, id);
583
584
  return /* @__PURE__ */ jsx(DndContext, {
584
585
  sensors,
585
586
  collisionDetection: closestCenter,
586
587
  modifiers: [restrictToVerticalAxis, restrictToParentElement],
587
588
  accessibility: { announcements: {
588
- onDragStart: ({ active }) => `Picked up ${label(items, active.id)}.`,
589
- onDragOver: ({ active, over }) => over ? `${label(items, active.id)} is over ${label(items, over.id)}.` : void 0,
590
- onDragEnd: ({ active, over }) => over ? `${label(items, active.id)} was moved to the place of ${label(items, over.id)}.` : `${label(items, active.id)} was dropped.`,
591
- onDragCancel: ({ active }) => `Moving ${label(items, active.id)} was cancelled.`
589
+ onDragStart: ({ active }) => say.pickedUp(name(active.id)),
590
+ onDragOver: ({ active, over }) => over ? say.itemOver(name(active.id), name(over.id)) : void 0,
591
+ onDragEnd: ({ active, over }) => over ? say.itemMoved(name(active.id), name(over.id)) : say.dropped(name(active.id)),
592
+ onDragCancel: ({ active }) => say.cancelled(name(active.id))
592
593
  } },
593
594
  onDragEnd,
594
595
  children: /* @__PURE__ */ jsx(SortableContext, {
@@ -603,6 +604,7 @@ const SortableItems = ({ items, disabled, onMove, children }) => {
603
604
  });
604
605
  };
605
606
  const ItemCard = ({ id, title, disabled, expanded, onToggle, checkbox, controls, className, children }) => {
607
+ const messages = useLiveMessages();
606
608
  const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({
607
609
  id,
608
610
  disabled
@@ -624,7 +626,7 @@ const ItemCard = ({ id, title, disabled, expanded, onToggle, checkbox, controls,
624
626
  ref: setActivatorNodeRef,
625
627
  ...attributes,
626
628
  ...listeners,
627
- "aria-label": `Reorder ${title}`,
629
+ "aria-label": messages.items.reorder(title),
628
630
  disabled,
629
631
  className: "cursor-grab rounded p-0.5 text-gray-400\n hover:text-gray-700 disabled:cursor-not-allowed\n disabled:opacity-40",
630
632
  children: /* @__PURE__ */ jsx(GripVertical, { size: 14 })
@@ -755,18 +757,21 @@ const removeIds = (ids, indices) => {
755
757
  };
756
758
  const useDndItems = (value, { render, onChange, onNodeChange } = {}) => {
757
759
  const { reportError, bindingOptions } = useDndEditOptions();
760
+ const messages = useLiveMessages();
758
761
  const { objectItems, primitiveItems, parseError } = useMemo(() => parseSource(value, bindingOptions), [value, bindingOptions]);
759
762
  const canEditStructure = useMemo(() => canStructurallyEditArray(value), [value]);
760
763
  const reportErrorRef = useRef(reportError);
764
+ const messagesRef = useRef(messages);
761
765
  useEffect(() => {
762
766
  reportErrorRef.current = reportError;
767
+ messagesRef.current = messages;
763
768
  });
764
769
  useEffect(() => {
765
770
  if (parseError) reportErrorRef.current({
766
771
  type: "parse",
767
772
  target: "items",
768
- title: "Failed to parse items",
769
- description: "Check the console for details."
773
+ title: messagesRef.current.editErrors.itemsParseFailed,
774
+ description: messagesRef.current.editErrors.checkConsole
770
775
  });
771
776
  }, [parseError]);
772
777
  const kind = primitiveItems.length > 0 && objectItems.length === 0 ? "primitive" : "object";
@@ -811,8 +816,8 @@ const useDndItems = (value, { render, onChange, onNodeChange } = {}) => {
811
816
  if (next === null) {
812
817
  reportError({
813
818
  type: "items",
814
- title: "Failed to update this item",
815
- description: "The source was preserved. Structural edits require a dense array without spreads; use the code editor for unsupported syntax."
819
+ title: messages.editErrors.itemUpdateFailed,
820
+ description: messages.editErrors.itemUpdateFailedDetail
816
821
  });
817
822
  return false;
818
823
  }
@@ -1036,6 +1041,7 @@ const NestedGroup = ({ group, onNodeChange }) => {
1036
1041
  });
1037
1042
  };
1038
1043
  const Items = ({ value, render, onChange, onChildChange }) => {
1044
+ const messages = useLiveMessages();
1039
1045
  const { kind, items, selection, expansion, actions, canEditStructure, parseError } = useDndItems(value, {
1040
1046
  render,
1041
1047
  onChange,
@@ -1043,34 +1049,30 @@ const Items = ({ value, render, onChange, onChildChange }) => {
1043
1049
  });
1044
1050
  const header = /* @__PURE__ */ jsxs("div", {
1045
1051
  className: "flex items-center justify-between",
1046
- children: [/* @__PURE__ */ jsxs("div", {
1052
+ children: [/* @__PURE__ */ jsx("div", {
1047
1053
  className: "text-sm font-semibold",
1048
- children: [
1049
- "Items (",
1050
- items.length,
1051
- ")"
1052
- ]
1054
+ children: messages.items.heading(items.length)
1053
1055
  }), items.length > 0 && canEditStructure && /* @__PURE__ */ jsx(Button, {
1054
1056
  size: "small",
1055
1057
  icon: /* @__PURE__ */ jsx(Plus, {}),
1056
1058
  variant: "solid",
1057
1059
  color: "green",
1058
1060
  onClick: actions.add,
1059
- children: "Add Item"
1061
+ children: messages.items.add
1060
1062
  })]
1061
1063
  });
1062
1064
  if (parseError) return /* @__PURE__ */ jsxs("div", {
1063
1065
  className: "space-y-4",
1064
1066
  children: [header, /* @__PURE__ */ jsx("div", {
1065
1067
  className: "rounded border border-dashed border-red-200 p-3 text-xs\n text-red-600",
1066
- children: "This value could not be read as a list. Edit it in the code editor."
1068
+ children: messages.items.unreadable
1067
1069
  })]
1068
1070
  });
1069
1071
  if (items.length === 0) return /* @__PURE__ */ jsxs("div", {
1070
1072
  className: "space-y-4",
1071
1073
  children: [header, /* @__PURE__ */ jsx("div", {
1072
1074
  className: "rounded border border-dashed border-gray-200 p-3 text-xs\n text-gray-500",
1073
- children: "No editable items. The panel copies an existing item rather than guessing the shape of a new one — add the first item in the code editor."
1075
+ children: messages.items.empty
1074
1076
  })]
1075
1077
  });
1076
1078
  const bulkBar = /* @__PURE__ */ jsx(BulkActionsBar, {
@@ -1088,12 +1090,14 @@ const Items = ({ value, render, onChange, onChildChange }) => {
1088
1090
  /* @__PURE__ */ jsx(Button, {
1089
1091
  size: "small",
1090
1092
  icon: /* @__PURE__ */ jsx(ArrowUp, {}),
1093
+ "aria-label": messages.items.moveUp,
1091
1094
  disabled: !canEditStructure || item.index === 0,
1092
1095
  onClick: () => actions.move(item.elementIndex, item.index - 1)
1093
1096
  }),
1094
1097
  /* @__PURE__ */ jsx(Button, {
1095
1098
  size: "small",
1096
1099
  icon: /* @__PURE__ */ jsx(ArrowDown, {}),
1100
+ "aria-label": messages.items.moveDown,
1097
1101
  disabled: !canEditStructure || item.index === items.length - 1,
1098
1102
  onClick: () => actions.move(item.elementIndex, item.index + 1)
1099
1103
  }),
@@ -1101,6 +1105,7 @@ const Items = ({ value, render, onChange, onChildChange }) => {
1101
1105
  danger: true,
1102
1106
  size: "small",
1103
1107
  icon: /* @__PURE__ */ jsx(X, {}),
1108
+ "aria-label": messages.items.delete,
1104
1109
  disabled: !canEditStructure || items.length <= 1,
1105
1110
  onClick: () => actions.remove(item.elementIndex)
1106
1111
  })
@@ -1139,9 +1144,16 @@ const Items = ({ value, render, onChange, onChildChange }) => {
1139
1144
  children: item.nested.length ? item.nested.map((group) => /* @__PURE__ */ jsx(NestedGroup, {
1140
1145
  group,
1141
1146
  onNodeChange: onChildChange
1142
- }, group.property)) : /* @__PURE__ */ jsx("div", {
1147
+ }, group.property)) : /* @__PURE__ */ jsxs("div", {
1143
1148
  className: "text-xs text-gray-500",
1144
- children: "✓ No JSX bindings found"
1149
+ children: [
1150
+ /* @__PURE__ */ jsx("span", {
1151
+ "aria-hidden": "true",
1152
+ children: "✓"
1153
+ }),
1154
+ " ",
1155
+ messages.items.noNestedBindings
1156
+ ]
1145
1157
  })
1146
1158
  })] });
1147
1159
  const allExpanded = expansion.expandedIds.length === items.length;
@@ -1155,13 +1167,13 @@ const Items = ({ value, render, onChange, onChildChange }) => {
1155
1167
  size: "small",
1156
1168
  variant: "text",
1157
1169
  onClick: () => expansion.setExpanded(allExpanded ? [] : items.map((item) => item.id)),
1158
- children: allExpanded ? "Collapse all" : "Expand all"
1170
+ children: allExpanded ? messages.items.collapseAll : messages.items.expandAll
1159
1171
  })
1160
1172
  }),
1161
1173
  bulkBar,
1162
1174
  !canEditStructure && /* @__PURE__ */ jsx("div", {
1163
1175
  className: "rounded border border-dashed border-amber-200 p-3 text-xs\n text-amber-700",
1164
- 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."
1176
+ children: messages.items.structureLocked
1165
1177
  }),
1166
1178
  /* @__PURE__ */ jsx(SortableItems, {
1167
1179
  items,
@@ -1169,7 +1181,7 @@ const Items = ({ value, render, onChange, onChildChange }) => {
1169
1181
  onMove: (item, toIndex) => actions.move(item.elementIndex, toIndex),
1170
1182
  children: (item) => /* @__PURE__ */ jsx(ItemCard, {
1171
1183
  id: item.id,
1172
- title: `Item ${item.index + 1}`,
1184
+ title: messages.items.item(item.index + 1),
1173
1185
  disabled: !canEditStructure,
1174
1186
  expanded: expansion.isExpanded(item.id),
1175
1187
  onToggle: () => expansion.toggle(item.id),
@@ -1278,6 +1290,8 @@ const FieldError = ({ message }) => message ? /* @__PURE__ */ jsx("p", {
1278
1290
  children: message
1279
1291
  }) : null;
1280
1292
  const BuiltinField = ({ binding, onNodeChange }) => {
1293
+ const messages = useLiveMessages();
1294
+ const validationOptions = { messages: messages.validation };
1281
1295
  const { id, value, rawValue, onChange } = binding;
1282
1296
  const [validationError, setValidationError] = useState(null);
1283
1297
  const [text, setText] = useState(rawValue);
@@ -1290,12 +1304,12 @@ const BuiltinField = ({ binding, onNodeChange }) => {
1290
1304
  if (kind === "readonly") return /* @__PURE__ */ jsxs("div", {
1291
1305
  className: "space-y-1 rounded border border-dashed border-amber-200 p-3\n text-xs text-amber-700",
1292
1306
  children: [
1293
- /* @__PURE__ */ jsx("div", { children: "This expression is preserved but is not editable here." }),
1307
+ /* @__PURE__ */ jsx("div", { children: messages.panel.expressionPreserved }),
1294
1308
  /* @__PURE__ */ jsx("code", {
1295
1309
  className: "block overflow-x-auto text-amber-800",
1296
1310
  children: rawValue
1297
1311
  }),
1298
- /* @__PURE__ */ jsx("div", { children: "Use the code editor to change it." })
1312
+ /* @__PURE__ */ jsx("div", { children: messages.panel.useCodeEditor })
1299
1313
  ]
1300
1314
  });
1301
1315
  const commitIfChanged = (next) => {
@@ -1372,9 +1386,9 @@ const BuiltinField = ({ binding, onNodeChange }) => {
1372
1386
  value: parseDateValue(stringValue),
1373
1387
  onChange: (date) => {
1374
1388
  const next = date ? formatDateValue(date) : "";
1375
- const result = validateBindingValue(binding, next);
1389
+ const result = validateBindingValue(binding, next, validationOptions);
1376
1390
  if (!result.valid) {
1377
- setValidationError(result.message ?? "Invalid value.");
1391
+ setValidationError(result.message ?? messages.panel.invalidValue);
1378
1392
  return;
1379
1393
  }
1380
1394
  setValidationError(null);
@@ -1385,12 +1399,12 @@ const BuiltinField = ({ binding, onNodeChange }) => {
1385
1399
  type: "url",
1386
1400
  value: text,
1387
1401
  onChange: (e) => setText(e.target.value),
1388
- placeholder: "https://example.com",
1402
+ placeholder: messages.panel.urlPlaceholder,
1389
1403
  onBlur: (e) => {
1390
1404
  const next = e.target.value.trim();
1391
- const result = validateBindingValue(binding, next);
1405
+ const result = validateBindingValue(binding, next, validationOptions);
1392
1406
  if (!result.valid) {
1393
- setValidationError(result.message ?? "Invalid value.");
1407
+ setValidationError(result.message ?? messages.panel.invalidValue);
1394
1408
  return;
1395
1409
  }
1396
1410
  setValidationError(null);
@@ -1401,13 +1415,13 @@ const BuiltinField = ({ binding, onNodeChange }) => {
1401
1415
  type: "number",
1402
1416
  value: text,
1403
1417
  onChange: (e) => setText(e.target.value),
1404
- placeholder: "Enter a numeric value",
1418
+ placeholder: messages.panel.numberPlaceholder,
1405
1419
  onBlur: (e) => {
1406
1420
  const raw = e.target.value.trim();
1407
1421
  const next = raw !== "" && !Number.isNaN(Number(raw)) ? Number(raw) : raw;
1408
- const result = validateBindingValue(binding, next);
1422
+ const result = validateBindingValue(binding, next, validationOptions);
1409
1423
  if (!result.valid) {
1410
- setValidationError(result.message ?? "Invalid value.");
1424
+ setValidationError(result.message ?? messages.panel.invalidValue);
1411
1425
  return;
1412
1426
  }
1413
1427
  setValidationError(null);
@@ -1417,13 +1431,13 @@ const BuiltinField = ({ binding, onNodeChange }) => {
1417
1431
  return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Input.TextArea, {
1418
1432
  value: text,
1419
1433
  onChange: (e) => setText(e.target.value),
1420
- placeholder: "Enter a value",
1434
+ placeholder: messages.panel.textPlaceholder,
1421
1435
  onBlur: (e) => {
1422
1436
  const raw = e.target.value.trim();
1423
1437
  const next = binding.type ? raw : parseValue(raw);
1424
- const result = validateBindingValue(binding, next);
1438
+ const result = validateBindingValue(binding, next, validationOptions);
1425
1439
  if (!result.valid) {
1426
- setValidationError(result.message ?? "Invalid value.");
1440
+ setValidationError(result.message ?? messages.panel.invalidValue);
1427
1441
  return;
1428
1442
  }
1429
1443
  setValidationError(null);
@@ -1484,6 +1498,7 @@ const describeElement = (binding) => {
1484
1498
  };
1485
1499
  const nodeIdOf = (target) => target instanceof Element && target.closest("[data-node-id]")?.getAttribute("data-node-id") || null;
1486
1500
  const Panel$1 = ({ item, onDelete, onMoveUp, onMoveDown, canMoveUp = false, canMoveDown = false, bindings, onNodeChange, readOnly = false }) => {
1501
+ const messages = useLiveMessages();
1487
1502
  const groups = groupBindingsById(bindings);
1488
1503
  const rootRef = useRef(null);
1489
1504
  const inspector = useContext(DndInspectorContext);
@@ -1519,7 +1534,7 @@ const Panel$1 = ({ item, onDelete, onMoveUp, onMoveDown, canMoveUp = false, canM
1519
1534
  }, [pickedId, groups.length]);
1520
1535
  if (!item) return /* @__PURE__ */ jsx(Typography.Paragraph, {
1521
1536
  className: cn("p-4 text-sm text-gray-500"),
1522
- children: "Please select a section."
1537
+ children: messages.panel.selectSection
1523
1538
  });
1524
1539
  return /* @__PURE__ */ jsxs("div", {
1525
1540
  ref: rootRef,
@@ -1543,19 +1558,19 @@ const Panel$1 = ({ item, onDelete, onMoveUp, onMoveDown, canMoveUp = false, canM
1543
1558
  icon: /* @__PURE__ */ jsx(ChevronUp, {}),
1544
1559
  disabled: !canMoveUp,
1545
1560
  onClick: onMoveUp,
1546
- "aria-label": "Move section up"
1561
+ "aria-label": messages.section.moveUp
1547
1562
  }),
1548
1563
  onMoveDown && /* @__PURE__ */ jsx(Button, {
1549
1564
  icon: /* @__PURE__ */ jsx(ChevronDown, {}),
1550
1565
  disabled: !canMoveDown,
1551
1566
  onClick: onMoveDown,
1552
- "aria-label": "Move section down"
1567
+ "aria-label": messages.section.moveDown
1553
1568
  }),
1554
1569
  onDelete && /* @__PURE__ */ jsx(Button, {
1555
1570
  danger: true,
1556
1571
  icon: /* @__PURE__ */ jsx(Trash, {}),
1557
1572
  onClick: () => onDelete(item.id),
1558
- "aria-label": "Delete section"
1573
+ "aria-label": messages.section.delete
1559
1574
  })
1560
1575
  ]
1561
1576
  })]
@@ -1563,11 +1578,11 @@ const Panel$1 = ({ item, onDelete, onMoveUp, onMoveDown, canMoveUp = false, canM
1563
1578
  readOnly && /* @__PURE__ */ jsx(Typography.Text, {
1564
1579
  role: "status",
1565
1580
  className: "block text-xs text-amber-700",
1566
- children: "The document has a syntax error. These fields are from the last version that parsed, and can't be edited until it parses again."
1581
+ children: messages.panel.readOnly
1567
1582
  }),
1568
1583
  !groups.length && /* @__PURE__ */ jsx(Typography.Text, {
1569
1584
  className: "text-xs text-gray-400",
1570
- children: "No editable elements."
1585
+ children: messages.panel.noEditableElements
1571
1586
  }),
1572
1587
  groups.map((group) => {
1573
1588
  const element = describeElement(group[0]);
@@ -1630,6 +1645,7 @@ const Palette = ({ className, ...restProps }) => /* @__PURE__ */ jsx("div", {
1630
1645
  const Canvas = ({ className, style, ...restProps }) => {
1631
1646
  const { canvas, documentError } = useDndRegions("<Live.Dnd.Canvas>");
1632
1647
  const inspector = useDndInspector();
1648
+ const messages = useLiveMessages();
1633
1649
  return /* @__PURE__ */ jsxs("div", {
1634
1650
  className: cn("relative h-full w-full overflow-y-auto", className),
1635
1651
  "data-frame-container": true,
@@ -1649,8 +1665,8 @@ const Canvas = ({ className, style, ...restProps }) => {
1649
1665
  color: "primary",
1650
1666
  variant: inspector.active ? "solid" : "outlined",
1651
1667
  "aria-pressed": inspector.active,
1652
- "aria-label": "Pick an element",
1653
- title: inspector.active ? "Click an element to edit it. Esc to cancel." : "Pick an element",
1668
+ "aria-label": messages.canvas.pickElement,
1669
+ title: inspector.active ? messages.canvas.pickElementActive : messages.canvas.pickElement,
1654
1670
  onClick: inspector.toggle
1655
1671
  })
1656
1672
  })
@@ -1664,6 +1680,7 @@ const Panel = ({ className, ...restProps }) => /* @__PURE__ */ jsx("div", {
1664
1680
  });
1665
1681
  const Layout = ({ palette, panel }) => {
1666
1682
  const { isMobile, selectedId, clearSelection, paletteOpen, setPaletteOpen } = useDndRegions("<Live.Dnd.Layout>");
1683
+ const messages = useLiveMessages();
1667
1684
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1668
1685
  isMobile ? /* @__PURE__ */ jsx(Canvas, {}) : /* @__PURE__ */ jsxs(Splitter, {
1669
1686
  withHandle: true,
@@ -1693,7 +1710,7 @@ const Layout = ({ palette, panel }) => {
1693
1710
  type: "primary",
1694
1711
  shape: "circle",
1695
1712
  icon: /* @__PURE__ */ jsx(LayoutGrid, {}),
1696
- "aria-label": "Components",
1713
+ "aria-label": messages.canvas.palette,
1697
1714
  className: "fixed right-4 bottom-4 z-20 md:hidden",
1698
1715
  onClick: () => setPaletteOpen(true)
1699
1716
  }),
@@ -1702,7 +1719,7 @@ const Layout = ({ palette, panel }) => {
1702
1719
  onClose: () => setPaletteOpen(false),
1703
1720
  direction: "bottom",
1704
1721
  size: "large",
1705
- title: "Components",
1722
+ title: messages.canvas.palette,
1706
1723
  children: palette ?? /* @__PURE__ */ jsx(PaletteItems, { subject: "<Live.Dnd.Layout>" })
1707
1724
  }),
1708
1725
  /* @__PURE__ */ jsx(Drawer, {
@@ -1710,7 +1727,7 @@ const Layout = ({ palette, panel }) => {
1710
1727
  onClose: clearSelection,
1711
1728
  direction: "bottom",
1712
1729
  size: "large",
1713
- title: "Properties",
1730
+ title: messages.canvas.properties,
1714
1731
  children: panel ?? /* @__PURE__ */ jsx(PanelFields, { subject: "<Live.Dnd.Layout>" })
1715
1732
  })
1716
1733
  ] });
@@ -1745,6 +1762,7 @@ const Renderer = ({ preview, sectionId = "", sectionName = "", sectionCode = pre
1745
1762
  name: sectionName,
1746
1763
  code: sectionCode
1747
1764
  };
1765
+ const messages = useLiveMessages();
1748
1766
  const { ref: wrapperRef, css: dynamicCSS } = useDynamicTailwind(preview, dynamicTailwind && !forceFallback);
1749
1767
  const renderProvider = (component) => {
1750
1768
  return provider ? provider(component) : component;
@@ -1755,8 +1773,8 @@ const Renderer = ({ preview, sectionId = "", sectionName = "", sectionCode = pre
1755
1773
  reason: "forced"
1756
1774
  },
1757
1775
  builtin: /* @__PURE__ */ jsx(Error$1, {
1758
- message: "This section is not rendered in this editor.",
1759
- title: "Section Unavailable"
1776
+ message: messages.errors.sectionNotRendered,
1777
+ title: messages.errors.sectionUnavailable
1760
1778
  })
1761
1779
  });
1762
1780
  if (module?.error) return /* @__PURE__ */ jsx(SectionFallback, {
@@ -1767,7 +1785,7 @@ const Renderer = ({ preview, sectionId = "", sectionName = "", sectionCode = pre
1767
1785
  },
1768
1786
  builtin: /* @__PURE__ */ jsx(Error$1, {
1769
1787
  message: module.error,
1770
- title: "Compile Error"
1788
+ title: messages.errors.compile
1771
1789
  })
1772
1790
  });
1773
1791
  const Component = module?.exports?.default;
@@ -1790,7 +1808,7 @@ const Renderer = ({ preview, sectionId = "", sectionName = "", sectionCode = pre
1790
1808
  builtin: /* @__PURE__ */ jsx(Error$1, {
1791
1809
  message,
1792
1810
  onReset: reset,
1793
- title: "Rendering Error"
1811
+ title: messages.errors.rendering
1794
1812
  })
1795
1813
  }),
1796
1814
  children: renderProvider(/* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Component, {
@@ -1832,6 +1850,7 @@ const Sortable = ({ id, children, selected, onClick, onDelete: _onDelete, onCopy
1832
1850
  id,
1833
1851
  disabled: inspecting
1834
1852
  });
1853
+ const messages = useLiveMessages();
1835
1854
  const style = {
1836
1855
  transform: CSS$1.Transform.toString(transform),
1837
1856
  transition,
@@ -1901,24 +1920,24 @@ const Sortable = ({ id, children, selected, onClick, onDelete: _onDelete, onCopy
1901
1920
  icon: /* @__PURE__ */ jsx(ChevronUp, {}),
1902
1921
  disabled: !canMoveUp,
1903
1922
  onClick: press(onMoveUp),
1904
- "aria-label": "Move section up"
1923
+ "aria-label": messages.section.moveUp
1905
1924
  }),
1906
1925
  onMoveDown && /* @__PURE__ */ jsx(Button, {
1907
1926
  icon: /* @__PURE__ */ jsx(ChevronDown, {}),
1908
1927
  disabled: !canMoveDown,
1909
1928
  onClick: press(onMoveDown),
1910
- "aria-label": "Move section down"
1929
+ "aria-label": messages.section.moveDown
1911
1930
  }),
1912
1931
  /* @__PURE__ */ jsx(Button, {
1913
1932
  icon: /* @__PURE__ */ jsx(Copy, {}),
1914
1933
  onClick: onCopy,
1915
- "aria-label": "Duplicate section"
1934
+ "aria-label": messages.section.duplicate
1916
1935
  }),
1917
1936
  /* @__PURE__ */ jsx(Button, {
1918
1937
  danger: true,
1919
1938
  icon: /* @__PURE__ */ jsx(Trash, {}),
1920
1939
  onClick: onDelete,
1921
- "aria-label": "Delete section"
1940
+ "aria-label": messages.section.delete
1922
1941
  })
1923
1942
  ]
1924
1943
  })
@@ -1955,6 +1974,205 @@ const Overlay = ({ sections, isForced, renderProps }) => {
1955
1974
  return null;
1956
1975
  };
1957
1976
  //#endregion
1977
+ //#region src/components/dnd/use-delete-flow.ts
1978
+ const useDeleteFlow = ({ sections, remove, onBeforeDelete }) => {
1979
+ const removeRef = useRef(remove);
1980
+ useEffect(() => {
1981
+ removeRef.current = remove;
1982
+ });
1983
+ return (id, onDeleted) => {
1984
+ const section = sections.find((candidate) => candidate.id === id);
1985
+ if (!onBeforeDelete || !section) {
1986
+ remove(id);
1987
+ onDeleted?.();
1988
+ return;
1989
+ }
1990
+ const decide = (allowed) => {
1991
+ if (allowed) {
1992
+ removeRef.current(id);
1993
+ onDeleted?.();
1994
+ }
1995
+ };
1996
+ try {
1997
+ const answer = onBeforeDelete(section);
1998
+ if (typeof answer === "boolean") {
1999
+ decide(answer);
2000
+ return;
2001
+ }
2002
+ answer.then(decide, (error) => {
2003
+ console.error("onBeforeDelete rejected; the section was kept", error);
2004
+ });
2005
+ } catch (error) {
2006
+ console.error("onBeforeDelete threw; the section was kept", error);
2007
+ }
2008
+ };
2009
+ };
2010
+ //#endregion
2011
+ //#region src/components/dnd/use-dnd-keyboard.ts
2012
+ const KEYBOARD_CODES = {
2013
+ start: ["Space"],
2014
+ cancel: ["Escape"],
2015
+ end: ["Space", "Enter"]
2016
+ };
2017
+ const createNodeRegistry = () => {
2018
+ const nodes = /* @__PURE__ */ new Map();
2019
+ const callbacks = /* @__PURE__ */ new Map();
2020
+ return {
2021
+ get: (id) => nodes.get(id),
2022
+ register: (id) => {
2023
+ let callback = callbacks.get(id);
2024
+ if (!callback) {
2025
+ callback = (node) => {
2026
+ if (node) nodes.set(id, node);
2027
+ else {
2028
+ nodes.delete(id);
2029
+ callbacks.delete(id);
2030
+ }
2031
+ };
2032
+ callbacks.set(id, callback);
2033
+ }
2034
+ return callback;
2035
+ }
2036
+ };
2037
+ };
2038
+ const useDndKeyboard = ({ sections, selectedId, selectedIndex, selectOnly, move, requestDelete }) => {
2039
+ const { announcements: say } = useLiveMessages();
2040
+ const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 10 } }), useSensor(KeyboardSensor, {
2041
+ coordinateGetter: sortableKeyboardCoordinates,
2042
+ keyboardCodes: KEYBOARD_CODES
2043
+ }));
2044
+ const nameOf = (id, data) => {
2045
+ return (data?.current)?.item?.name ?? sections.find((section) => section.id === id)?.name ?? say.section;
2046
+ };
2047
+ const positionOf = (id) => sections.findIndex((section) => section.id === id) + 1;
2048
+ const announcements = {
2049
+ onDragStart: ({ active }) => say.pickedUp(nameOf(active.id, active.data)),
2050
+ onDragOver: ({ active, over }) => over && positionOf(over.id) > 0 ? say.movedTo(nameOf(active.id, active.data), positionOf(over.id), sections.length) : say.notOver(nameOf(active.id, active.data)),
2051
+ onDragEnd: ({ active, over }) => over && positionOf(over.id) > 0 ? say.droppedAt(nameOf(active.id, active.data), positionOf(over.id), sections.length) : say.dropped(nameOf(active.id, active.data)),
2052
+ onDragCancel: ({ active }) => say.cancelled(nameOf(active.id, active.data))
2053
+ };
2054
+ const screenReaderInstructions = { draggable: say.instructions };
2055
+ const [sectionNodes] = useState(createNodeRegistry);
2056
+ const focusSection = (id) => sectionNodes.get(id)?.focus();
2057
+ const onNavigate = (fromId, to) => {
2058
+ const from = sections.findIndex((section) => section.id === fromId);
2059
+ const target = sections[to === "first" ? 0 : to === "last" ? sections.length - 1 : from + (to === "next" ? 1 : -1)];
2060
+ if (from < 0 || !target || target.id === fromId) return;
2061
+ selectOnly(target.id);
2062
+ focusSection(target.id);
2063
+ };
2064
+ const onDeleteKey = (id) => {
2065
+ const index = sections.findIndex((section) => section.id === id);
2066
+ const neighbor = sections[index + 1] ?? sections[index - 1];
2067
+ requestDelete(id, () => {
2068
+ if (neighbor) focusSection(neighbor.id);
2069
+ });
2070
+ };
2071
+ const onMoveButton = (id, direction) => {
2072
+ const to = sections.findIndex((section) => section.id === id) + (direction === "up" ? -1 : 1);
2073
+ move(id, direction);
2074
+ if (to === 0 || to === sections.length - 1) focusSection(id);
2075
+ };
2076
+ useEffect(() => {
2077
+ if (selectedId === null) return;
2078
+ const frame = requestAnimationFrame(() => {
2079
+ sectionNodes.get(selectedId)?.scrollIntoView?.({ block: "nearest" });
2080
+ });
2081
+ return () => cancelAnimationFrame(frame);
2082
+ }, [
2083
+ sectionNodes,
2084
+ selectedId,
2085
+ selectedIndex
2086
+ ]);
2087
+ return {
2088
+ sensors,
2089
+ announcements,
2090
+ screenReaderInstructions,
2091
+ sectionNodes,
2092
+ onNavigate,
2093
+ onDeleteKey,
2094
+ onMoveButton
2095
+ };
2096
+ };
2097
+ //#endregion
2098
+ //#region src/components/dnd/use-inspector-state.ts
2099
+ const useInspectorState = ({ selectedId, selectOnly, sectionNodes, onNodePick }) => {
2100
+ const [inspecting, setInspecting] = useState(false);
2101
+ const [picked, setPicked] = useState(null);
2102
+ const [hoverRect, setHoverRect] = useState(null);
2103
+ const [fieldTarget, setFieldTarget] = useState(null);
2104
+ const [fieldRect, setFieldRect] = useState(null);
2105
+ if (picked && picked.sectionId !== selectedId) setPicked(null);
2106
+ const stopInspecting = useCallback(() => {
2107
+ setInspecting(false);
2108
+ setHoverRect(null);
2109
+ }, []);
2110
+ useEffect(() => {
2111
+ if (!inspecting) return;
2112
+ const onKeyDown = (e) => {
2113
+ if (e.key === "Escape") stopInspecting();
2114
+ };
2115
+ window.addEventListener("keydown", onKeyDown);
2116
+ return () => window.removeEventListener("keydown", onKeyDown);
2117
+ }, [inspecting, stopInspecting]);
2118
+ useEffect(() => {
2119
+ const section = selectedId === null ? null : sectionNodes.get(selectedId);
2120
+ if (!fieldTarget || !section) return;
2121
+ let frame = 0;
2122
+ const measure = () => {
2123
+ cancelAnimationFrame(frame);
2124
+ frame = requestAnimationFrame(() => {
2125
+ const element = findElementById(section, fieldTarget);
2126
+ setFieldRect(element ? viewportRect(element) : null);
2127
+ });
2128
+ };
2129
+ measure();
2130
+ window.addEventListener("scroll", measure, true);
2131
+ window.addEventListener("resize", measure);
2132
+ return () => {
2133
+ cancelAnimationFrame(frame);
2134
+ window.removeEventListener("scroll", measure, true);
2135
+ window.removeEventListener("resize", measure);
2136
+ };
2137
+ }, [
2138
+ fieldTarget,
2139
+ selectedId,
2140
+ sectionNodes
2141
+ ]);
2142
+ const inspector = {
2143
+ active: inspecting,
2144
+ activate: () => setInspecting(true),
2145
+ deactivate: stopInspecting,
2146
+ toggle: () => inspecting ? stopInspecting() : setInspecting(true),
2147
+ picked,
2148
+ highlight: setFieldTarget
2149
+ };
2150
+ const onInspectMove = (section, overlay, x, y) => {
2151
+ const element = pickElement(section, overlay, x, y);
2152
+ setHoverRect(element ? viewportRect(element) : null);
2153
+ };
2154
+ const onInspectPick = (sectionId, section, overlay, x, y) => {
2155
+ const id = pickElement(section, overlay, x, y)?.getAttribute(DATA_ATTR.ID);
2156
+ if (!id) return;
2157
+ const pick = {
2158
+ id,
2159
+ sectionId
2160
+ };
2161
+ selectOnly(sectionId);
2162
+ setPicked(pick);
2163
+ stopInspecting();
2164
+ onNodePick?.(pick);
2165
+ };
2166
+ return {
2167
+ inspector,
2168
+ inspecting,
2169
+ onInspectMove,
2170
+ onInspectPick,
2171
+ onInspectLeave: () => setHoverRect(null),
2172
+ highlightRect: inspecting ? hoverRect : fieldTarget ? fieldRect : null
2173
+ };
2174
+ };
2175
+ //#endregion
1958
2176
  //#region src/components/dnd/use-section-document.ts
1959
2177
  const createLastParsed = () => {
1960
2178
  let last = null;
@@ -2148,81 +2366,61 @@ const useSectionDocument = (value, onChange, { containerId, sectionNameFallback,
2148
2366
  };
2149
2367
  //#endregion
2150
2368
  //#region src/components/dnd/dnd.tsx
2151
- const describeUpdateFailure = (failure, label) => {
2369
+ const describeUpdateFailure = (failure, label, { editErrors: m }) => {
2152
2370
  switch (failure?.reason) {
2153
2371
  case "attribute-not-found": return {
2154
- title: `Failed to update "${label}"`,
2155
- description: `This element has no "${failure.property}" attribute — check the property in its data-binding.`
2372
+ title: m.updateFailed(label),
2373
+ description: m.attributeNotFound(failure.property)
2156
2374
  };
2157
2375
  case "binding-not-declared": return {
2158
- title: `Failed to update "${label}"`,
2159
- description: `No binding for ${failure.property ? `property "${failure.property}"` : `label "${label}"`} is declared on this element's data-binding.`
2376
+ title: m.updateFailed(label),
2377
+ description: m.bindingNotDeclared({
2378
+ label,
2379
+ property: failure.property
2380
+ })
2160
2381
  };
2161
2382
  case "duplicate-binding": return {
2162
- title: `Failed to update "${label}"`,
2163
- description: `${failure.count} bindings share ${failure.property ? `property "${failure.property}"` : `label "${label}"`} on this element — remove the duplicate in its data-binding.`
2383
+ title: m.updateFailed(label),
2384
+ description: m.duplicateBinding({
2385
+ count: failure.count,
2386
+ label,
2387
+ property: failure.property
2388
+ })
2164
2389
  };
2165
2390
  case "reserved-property": return {
2166
- title: `Cannot edit "${label}" in the panel`,
2167
- description: `"${failure.property}" is managed by the editor, so a binding can't change it.`
2391
+ title: m.cannotEdit(label),
2392
+ description: m.reservedProperty(failure.property)
2168
2393
  };
2169
2394
  case "required-property": return {
2170
- title: `Cannot remove "${label}"`,
2171
- description: `"${failure.property}" is marked required in its data-binding, so it can't be removed.`
2395
+ title: m.cannotRemove(label),
2396
+ description: m.requiredProperty(failure.property)
2172
2397
  };
2173
2398
  case "no-binding": return {
2174
- title: `Failed to update "${label}"`,
2175
- description: "This element has no data-binding declaration."
2399
+ title: m.updateFailed(label),
2400
+ description: m.noBinding
2176
2401
  };
2177
2402
  case "element-not-found": return {
2178
- title: `Failed to update "${label}"`,
2179
- description: "The target element could not be found in this section."
2403
+ title: m.updateFailed(label),
2404
+ description: m.elementNotFound
2180
2405
  };
2181
2406
  case "unsupported-syntax": return {
2182
- title: `Cannot edit "${label}" in the panel`,
2183
- description: `The "${failure.property}" expression was preserved. Change it in the code editor instead.`
2407
+ title: m.cannotEdit(label),
2408
+ description: m.unsupportedSyntax(failure.property)
2184
2409
  };
2185
2410
  case "parse-error": return {
2186
- title: `Failed to update "${label}"`,
2187
- description: failure.error instanceof Error ? failure.error.message : "Check the console for details."
2411
+ title: m.updateFailed(label),
2412
+ description: failure.error instanceof Error ? failure.error.message : m.checkConsole
2188
2413
  };
2189
- default: return { title: `Failed to update "${label}"` };
2414
+ default: return { title: m.updateFailed(label) };
2190
2415
  }
2191
2416
  };
2192
- const KEYBOARD_CODES = {
2193
- start: ["Space"],
2194
- cancel: ["Escape"],
2195
- end: ["Space", "Enter"]
2196
- };
2197
- const SCREEN_READER_INSTRUCTIONS = { draggable: "On a palette item, press Enter to add it to the canvas. On a canvas section, press Enter to select it, the up and down arrow keys to go to the previous or next section, and Delete to remove it. Press Space to pick a section up, the arrow keys to move it, and Space or Enter to drop it. Press Escape to cancel." };
2198
- const createNodeRegistry = () => {
2199
- const nodes = /* @__PURE__ */ new Map();
2200
- const callbacks = /* @__PURE__ */ new Map();
2201
- return {
2202
- get: (id) => nodes.get(id),
2203
- register: (id) => {
2204
- let callback = callbacks.get(id);
2205
- if (!callback) {
2206
- callback = (node) => {
2207
- if (node) nodes.set(id, node);
2208
- else {
2209
- nodes.delete(id);
2210
- callbacks.delete(id);
2211
- }
2212
- };
2213
- callbacks.set(id, callback);
2214
- }
2215
- return callback;
2216
- }
2217
- };
2218
- };
2219
- const blockedEditError = (error) => ({
2417
+ const blockedEditError = (error, { editErrors: m }) => ({
2220
2418
  type: "parse",
2221
2419
  target: "document",
2222
2420
  reason: "parse-error",
2223
2421
  error,
2224
- title: "The document has a syntax error",
2225
- description: "The canvas shows the last version that parsed. Fix the error in the code, then edit here again."
2422
+ title: m.syntaxError,
2423
+ description: m.syntaxErrorDetail
2226
2424
  });
2227
2425
  const conditionalModifiers = (args) => {
2228
2426
  const { active } = args;
@@ -2244,28 +2442,17 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2244
2442
  return false;
2245
2443
  }
2246
2444
  };
2247
- const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 10 } }), useSensor(KeyboardSensor, {
2248
- coordinateGetter: sortableKeyboardCoordinates,
2249
- keyboardCodes: KEYBOARD_CODES
2250
- }));
2251
- const nameOf = (id, data) => {
2252
- return (data?.current)?.item?.name ?? sections.find((section) => section.id === id)?.name ?? "section";
2253
- };
2254
- const positionOf = (id) => sections.findIndex((section) => section.id === id) + 1;
2255
- const announcements = {
2256
- onDragStart: ({ active }) => `Picked up ${nameOf(active.id, active.data)}.`,
2257
- onDragOver: ({ active, over }) => over && positionOf(over.id) > 0 ? `${nameOf(active.id, active.data)} moved to position ${positionOf(over.id)} of ${sections.length}.` : `${nameOf(active.id, active.data)} is no longer over a position.`,
2258
- onDragEnd: ({ active, over }) => over && positionOf(over.id) > 0 ? `${nameOf(active.id, active.data)} dropped at position ${positionOf(over.id)} of ${sections.length}.` : `${nameOf(active.id, active.data)} dropped.`,
2259
- onDragCancel: ({ active }) => `Moving ${nameOf(active.id, active.data)} was cancelled.`
2260
- };
2261
2445
  const value = _value === void 0 ? code : _value;
2446
+ const messages = useLiveMessages();
2262
2447
  const reportError = onEditError ?? toastEditError;
2263
2448
  const reportErrorRef = useRef(reportError);
2449
+ const messagesRef = useRef(messages);
2264
2450
  useEffect(() => {
2265
2451
  reportErrorRef.current = reportError;
2452
+ messagesRef.current = messages;
2266
2453
  });
2267
2454
  const onBlockedEdit = useCallback((problem) => {
2268
- if (problem.reason === "parse-error") reportErrorRef.current(blockedEditError(problem.error));
2455
+ if (problem.reason === "parse-error") reportErrorRef.current(blockedEditError(problem.error, messagesRef.current));
2269
2456
  }, []);
2270
2457
  const { sections, previews, selectedId, selectedItem, selectedIndex, select, selectOnly, clearSelection, add: addItem, remove, copy: onCopy, move: moveSection, reorder, patch, getCommittedSection, problem, stale } = useSectionDocument(value, _onChange, {
2271
2458
  containerId,
@@ -2273,8 +2460,6 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2273
2460
  onBlockedEdit
2274
2461
  });
2275
2462
  const missingContainer = problem?.reason === "container-not-found" ? problem.containerId : null;
2276
- const onDragStart = (_) => {};
2277
- const onDragOver = (_e) => {};
2278
2463
  const onDragEnd = (event) => {
2279
2464
  const { active, over } = event;
2280
2465
  if (!over) return;
@@ -2287,136 +2472,26 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2287
2472
  if (active.id !== over.id && sections.some((s) => s.id === active.id)) reorder(String(active.id), String(over.id));
2288
2473
  };
2289
2474
  const onSelect = (id) => select(id);
2290
- const [inspecting, setInspecting] = useState(false);
2291
- const [picked, setPicked] = useState(null);
2292
- const [highlight, setHighlight] = useState(null);
2293
- const [fieldTarget, setFieldTarget] = useState(null);
2294
- const [fieldRect, setFieldRect] = useState(null);
2295
- if (picked && picked.sectionId !== selectedId) setPicked(null);
2296
- const stopInspecting = useCallback(() => {
2297
- setInspecting(false);
2298
- setHighlight(null);
2299
- }, []);
2300
- useEffect(() => {
2301
- if (!inspecting) return;
2302
- const onKeyDown = (e) => {
2303
- if (e.key === "Escape") stopInspecting();
2304
- };
2305
- window.addEventListener("keydown", onKeyDown);
2306
- return () => window.removeEventListener("keydown", onKeyDown);
2307
- }, [inspecting, stopInspecting]);
2308
- const inspector = {
2309
- active: inspecting,
2310
- activate: () => setInspecting(true),
2311
- deactivate: stopInspecting,
2312
- toggle: () => inspecting ? stopInspecting() : setInspecting(true),
2313
- picked,
2314
- highlight: setFieldTarget
2315
- };
2316
- const onInspectMove = (section, overlay, x, y) => {
2317
- const element = pickElement(section, overlay, x, y);
2318
- setHighlight(element ? viewportRect(element) : null);
2319
- };
2320
- const onInspectPick = (sectionId, section, overlay, x, y) => {
2321
- const id = pickElement(section, overlay, x, y)?.getAttribute(DATA_ATTR.ID);
2322
- if (!id) return;
2323
- const pick = {
2324
- id,
2325
- sectionId
2326
- };
2327
- selectOnly(sectionId);
2328
- setPicked(pick);
2329
- stopInspecting();
2330
- onNodePick?.(pick);
2331
- };
2332
- const removeRef = useRef(remove);
2333
- useEffect(() => {
2334
- removeRef.current = remove;
2475
+ const requestDelete = useDeleteFlow({
2476
+ sections,
2477
+ remove,
2478
+ onBeforeDelete
2335
2479
  });
2336
- const requestDelete = (id, onDeleted) => {
2337
- const section = sections.find((candidate) => candidate.id === id);
2338
- if (!onBeforeDelete || !section) {
2339
- remove(id);
2340
- onDeleted?.();
2341
- return;
2342
- }
2343
- const decide = (allowed) => {
2344
- if (allowed) {
2345
- removeRef.current(id);
2346
- onDeleted?.();
2347
- }
2348
- };
2349
- try {
2350
- const answer = onBeforeDelete(section);
2351
- if (typeof answer === "boolean") {
2352
- decide(answer);
2353
- return;
2354
- }
2355
- answer.then(decide, (error) => {
2356
- console.error("onBeforeDelete rejected; the section was kept", error);
2357
- });
2358
- } catch (error) {
2359
- console.error("onBeforeDelete threw; the section was kept", error);
2360
- }
2361
- };
2362
2480
  const onDelete = (id) => requestDelete(id);
2363
- const [sectionNodes] = useState(createNodeRegistry);
2364
- const focusSection = (id) => sectionNodes.get(id)?.focus();
2365
- const onNavigate = (fromId, to) => {
2366
- const from = sections.findIndex((section) => section.id === fromId);
2367
- const index = to === "first" ? 0 : to === "last" ? sections.length - 1 : from + (to === "next" ? 1 : -1);
2368
- const target = sections[index];
2369
- if (from < 0 || !target || target.id === fromId) return;
2370
- selectOnly(target.id);
2371
- focusSection(target.id);
2372
- };
2373
- const onDeleteKey = (id) => {
2374
- const index = sections.findIndex((section) => section.id === id);
2375
- const neighbor = sections[index + 1] ?? sections[index - 1];
2376
- requestDelete(id, () => {
2377
- if (neighbor) focusSection(neighbor.id);
2378
- });
2379
- };
2380
- const onMoveButton = (id, direction) => {
2381
- const to = sections.findIndex((section) => section.id === id) + (direction === "up" ? -1 : 1);
2382
- moveSection(id, direction);
2383
- if (to === 0 || to === sections.length - 1) focusSection(id);
2384
- };
2385
- useEffect(() => {
2386
- const section = selectedId === null ? null : sectionNodes.get(selectedId);
2387
- if (!fieldTarget || !section) return;
2388
- let frame = 0;
2389
- const measure = () => {
2390
- cancelAnimationFrame(frame);
2391
- frame = requestAnimationFrame(() => {
2392
- const element = findElementById(section, fieldTarget);
2393
- setFieldRect(element ? viewportRect(element) : null);
2394
- });
2395
- };
2396
- measure();
2397
- window.addEventListener("scroll", measure, true);
2398
- window.addEventListener("resize", measure);
2399
- return () => {
2400
- cancelAnimationFrame(frame);
2401
- window.removeEventListener("scroll", measure, true);
2402
- window.removeEventListener("resize", measure);
2403
- };
2404
- }, [
2405
- fieldTarget,
2481
+ const { sensors, announcements, screenReaderInstructions, sectionNodes, onNavigate, onDeleteKey, onMoveButton } = useDndKeyboard({
2482
+ sections,
2406
2483
  selectedId,
2407
- sectionNodes
2408
- ]);
2409
- useEffect(() => {
2410
- if (selectedId === null) return;
2411
- const frame = requestAnimationFrame(() => {
2412
- sectionNodes.get(selectedId)?.scrollIntoView?.({ block: "nearest" });
2413
- });
2414
- return () => cancelAnimationFrame(frame);
2415
- }, [
2416
- sectionNodes,
2484
+ selectedIndex,
2485
+ selectOnly,
2486
+ move: moveSection,
2487
+ requestDelete
2488
+ });
2489
+ const { inspector, inspecting, onInspectMove, onInspectPick, onInspectLeave, highlightRect } = useInspectorState({
2417
2490
  selectedId,
2418
- selectedIndex
2419
- ]);
2491
+ selectOnly,
2492
+ sectionNodes,
2493
+ onNodePick
2494
+ });
2420
2495
  const onChange = (next) => {
2421
2496
  if (!next.id) return;
2422
2497
  patch(next);
@@ -2459,8 +2534,8 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2459
2534
  target: "document",
2460
2535
  reason: "container-not-found",
2461
2536
  containerId: missingContainer,
2462
- title: `No #${missingContainer} element in the document`,
2463
- description: `Sections are the <section> elements inside the element with id="${missingContainer}". Start from createDocument(), or set containerId to match your document.`
2537
+ title: messagesRef.current.editErrors.missingContainer(missingContainer),
2538
+ description: messagesRef.current.editErrors.missingContainerDetail(missingContainer)
2464
2539
  });
2465
2540
  }, [missingContainer]);
2466
2541
  useEffect(() => {
@@ -2468,14 +2543,14 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2468
2543
  type: "parse",
2469
2544
  target: "section",
2470
2545
  error: parseError.error,
2471
- title: "Failed to parse this section",
2472
- description: "Check the console for details."
2546
+ title: messagesRef.current.editErrors.sectionParseFailed,
2547
+ description: messagesRef.current.editErrors.checkConsole
2473
2548
  });
2474
2549
  }, [parseError]);
2475
2550
  const commitChanges = (changes) => {
2476
2551
  if (changes.length === 0) return;
2477
2552
  if (stale && problem?.reason === "parse-error") {
2478
- reportError(blockedEditError(problem.error));
2553
+ reportError(blockedEditError(problem.error, messages));
2479
2554
  return;
2480
2555
  }
2481
2556
  const committed = selectedItem && getCommittedSection(selectedItem.id)?.code;
@@ -2493,7 +2568,7 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2493
2568
  label,
2494
2569
  property,
2495
2570
  failure: result.failure,
2496
- ...describeUpdateFailure(result.failure, label)
2571
+ ...describeUpdateFailure(result.failure, label, messages)
2497
2572
  });
2498
2573
  return;
2499
2574
  }
@@ -2532,7 +2607,7 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2532
2607
  const canvas = /* @__PURE__ */ jsxs(Fragment, { children: [stale && /* @__PURE__ */ jsx("div", {
2533
2608
  role: "status",
2534
2609
  className: cn("sticky top-0 z-70", "border-b border-amber-200 bg-amber-50 px-3 py-2", "text-sm text-amber-900"),
2535
- children: "Showing the last version that parsed. Fix the syntax error in the code to edit here again."
2610
+ children: messages.canvas.stale
2536
2611
  }), /* @__PURE__ */ jsx(Droppable, {
2537
2612
  className: cn(!sections.length && "h-full"),
2538
2613
  children: !sections.length ? /* @__PURE__ */ jsx("div", {
@@ -2540,23 +2615,15 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2540
2615
  children: problem?.reason === "parse-error" ? /* @__PURE__ */ jsxs(Space, {
2541
2616
  orientation: "vertical",
2542
2617
  align: "center",
2543
- children: [/* @__PURE__ */ jsx(Typography.Paragraph, { children: "The document has a syntax error" }), /* @__PURE__ */ jsx(Typography.Text, { children: "Fix it in the code to see its sections" })]
2618
+ children: [/* @__PURE__ */ jsx(Typography.Paragraph, { children: messages.canvas.syntaxError }), /* @__PURE__ */ jsx(Typography.Text, { children: messages.canvas.syntaxErrorDetail })]
2544
2619
  }) : missingContainer !== null ? /* @__PURE__ */ jsxs(Space, {
2545
2620
  orientation: "vertical",
2546
2621
  align: "center",
2547
- children: [/* @__PURE__ */ jsxs(Typography.Paragraph, { children: [
2548
- "No #",
2549
- missingContainer,
2550
- " element in the document"
2551
- ] }), /* @__PURE__ */ jsxs(Typography.Text, { children: [
2552
- "Sections go inside the element with id=\"",
2553
- missingContainer,
2554
- "\""
2555
- ] })]
2622
+ children: [/* @__PURE__ */ jsx(Typography.Paragraph, { children: messages.canvas.missingContainer(missingContainer) }), /* @__PURE__ */ jsx(Typography.Text, { children: messages.canvas.missingContainerDetail(missingContainer) })]
2556
2623
  }) : /* @__PURE__ */ jsxs(Space, {
2557
2624
  orientation: "vertical",
2558
2625
  align: "center",
2559
- children: [/* @__PURE__ */ jsx(Typography.Paragraph, { children: "No sections available" }), /* @__PURE__ */ jsx(Typography.Text, { children: isMobile ? "Tap a component to add it" : "Drag a component from the left to add it" })]
2626
+ children: [/* @__PURE__ */ jsx(Typography.Paragraph, { children: messages.canvas.empty }), /* @__PURE__ */ jsx(Typography.Text, { children: isMobile ? messages.canvas.emptyHintTouch : messages.canvas.emptyHintDrag })]
2560
2627
  })
2561
2628
  }) : /* @__PURE__ */ jsx(SortableContext, {
2562
2629
  items: sections.map((s) => s.id),
@@ -2578,7 +2645,7 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2578
2645
  inspecting,
2579
2646
  onInspectMove,
2580
2647
  onInspectPick: (...args) => onInspectPick(section.id, ...args),
2581
- onInspectLeave: () => setHighlight(null),
2648
+ onInspectLeave,
2582
2649
  children: /* @__PURE__ */ jsx(renderer_default, {
2583
2650
  preview: previews[index],
2584
2651
  sectionId: section.id,
@@ -2601,11 +2668,9 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2601
2668
  collisionDetection: closestCenter,
2602
2669
  accessibility: {
2603
2670
  announcements,
2604
- screenReaderInstructions: SCREEN_READER_INSTRUCTIONS
2671
+ screenReaderInstructions
2605
2672
  },
2606
2673
  modifiers: [conditionalModifiers],
2607
- onDragStart,
2608
- onDragOver,
2609
2674
  onDragEnd,
2610
2675
  children: [/* @__PURE__ */ jsx("div", {
2611
2676
  className: cn("relative flex h-full w-full", className),
@@ -2632,7 +2697,7 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
2632
2697
  value: inspector,
2633
2698
  children: Children.toArray(children).length ? children : /* @__PURE__ */ jsx(Layout, {})
2634
2699
  })
2635
- }), /* @__PURE__ */ jsx(InspectorHighlight, { rect: inspecting ? highlight : fieldTarget ? fieldRect : null })]
2700
+ }), /* @__PURE__ */ jsx(InspectorHighlight, { rect: highlightRect })]
2636
2701
  })
2637
2702
  }), /* @__PURE__ */ jsx(DragOverlay, { children: /* @__PURE__ */ jsx(Overlay, {
2638
2703
  sections,
@@ -2665,4 +2730,4 @@ const useChildrenEditor = useDndChildren;
2665
2730
  //#endregion
2666
2731
  export { useDndPanel as _, Layout as a, Field as c, isStructuralFieldKind as d, useDndChildren as f, useDndPalette as g, useDndLayout as h, Canvas as i, useDndItems as l, withPanelCommit as m, useChildrenEditor as n, Palette as o, resolvePanelBindings as p, useItemsEditor as r, Panel as s, Dnd as t, getFieldKind as u, DraggableItem as v, useDndInspector as y };
2667
2732
 
2668
- //# sourceMappingURL=dnd-BE5ZizqX.js.map
2733
+ //# sourceMappingURL=dnd-DGNp20Nk.js.map