@jbpark/live-editor 4.0.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dnd/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as Panel, c as useChildrenEditor, d as useDndPanel, f as DraggableItem, i as Palette, l as useDndLayout, n as Canvas, o as Field, r as Layout, s as useItemsEditor, t as Dnd, u as useDndPalette } from "../dnd-ClnGRNaY.js";
1
+ import { a as Panel, c as useChildrenEditor, d as useDndPanel, f as DraggableItem, i as Palette, l as useDndLayout, n as Canvas, o as Field, r as Layout, s as useItemsEditor, t as Dnd, u as useDndPalette } from "../dnd-_0jfnnVB.js";
2
2
  export { Canvas, DraggableItem, Field, Layout, Palette, Panel, Dnd as default, useChildrenEditor, useDndLayout, useDndPalette, useDndPanel, useItemsEditor };
@@ -229,21 +229,65 @@ const Node = ({ data, onChange }) => {
229
229
  });
230
230
  };
231
231
  //#endregion
232
+ //#region src/components/dnd/panel/use-structural-selection.ts
233
+ const selectionAfter = (command, selected, count) => {
234
+ switch (command.type) {
235
+ case "append":
236
+ case "duplicate": return new Set(selected);
237
+ case "move-selected": return moveSelectedIndices(Array.from({ length: count }, (_, index) => index), new Set(command.indices), command.direction).indices;
238
+ default: return /* @__PURE__ */ new Set();
239
+ }
240
+ };
241
+ const useStructuralSelection = (count, revision) => {
242
+ const selection = useMultiSelect(count);
243
+ const [seen, setSeen] = useState(revision);
244
+ const [pending, setPending] = useState(null);
245
+ if (revision !== seen) {
246
+ setSeen(revision);
247
+ setPending(null);
248
+ if (pending?.matches(revision) && pending.selection.size > 0) selection.replace(pending.selection);
249
+ else selection.clear();
250
+ }
251
+ const record = (next, matches, { now = false } = {}) => {
252
+ setPending({
253
+ matches,
254
+ selection: next
255
+ });
256
+ if (!now) return;
257
+ if (next.size > 0) selection.replace(next);
258
+ else selection.clear();
259
+ };
260
+ return {
261
+ selection,
262
+ record
263
+ };
264
+ };
265
+ //#endregion
232
266
  //#region src/components/dnd/panel/use-children-editor.ts
267
+ const producedBy = (expected, action) => {
268
+ if (action.type === "move-selected") {
269
+ const moved = JSON.stringify(moveSelectedIndices(expected, new Set(action.indices), action.direction).items);
270
+ return (revision) => revision === moved;
271
+ }
272
+ const added = action.type === "append" ? 1 : action.type === "duplicate" ? action.indices.length : 0;
273
+ return (revision) => {
274
+ const next = JSON.parse(revision);
275
+ return next.length === expected.length + added && expected.every((signature, index) => next[index] === signature);
276
+ };
277
+ };
233
278
  const useChildrenEditor = (items, { onChange } = {}) => {
234
- const selection = useMultiSelect(items.length);
235
279
  const expected = useMemo(() => getChildrenSignatures(items), [items]);
236
280
  const revision = JSON.stringify(expected);
237
- const clear = selection.clear;
238
- useEffect(() => {
239
- clear();
240
- }, [revision, clear]);
281
+ const { selection, record } = useStructuralSelection(items.length, revision);
241
282
  const commit = (action) => {
242
- onChange?.(JSON.stringify({
283
+ const edit = {
243
284
  kind: "children-edit",
244
285
  expected,
245
286
  action
246
- }));
287
+ };
288
+ const next = selectionAfter(action, selection.selected, items.length);
289
+ if (next.size > 0) record(next, producedBy(expected, action));
290
+ onChange?.(JSON.stringify(edit));
247
291
  };
248
292
  return {
249
293
  items,
@@ -527,8 +571,8 @@ const useItemsEditor = (value, { render, onChange, onNodeChange } = {}) => {
527
571
  rawItems,
528
572
  value
529
573
  ]);
530
- const selection = useMultiSelect(isPrimitive ? primitiveItems.length : objectItems.length);
531
- const commit = (next, nextIds) => {
574
+ const { selection, record } = useStructuralSelection(isPrimitive ? primitiveItems.length : objectItems.length, value);
575
+ const commit = (next, nextIds, nextSelection) => {
532
576
  if (next === null) {
533
577
  reportError({
534
578
  type: "items",
@@ -541,6 +585,7 @@ const useItemsEditor = (value, { render, onChange, onNodeChange } = {}) => {
541
585
  const nextItems = kind === "primitive" ? parsed.primitiveItems : parsed.objectItems;
542
586
  if (nextIds) setIdentityState(createIdentityState(next, kind, nextItems, nextIds));
543
587
  else setIdentityState(createIdentityState(next, kind, nextItems, identity.ids));
588
+ record(nextSelection, (revision) => revision === next, { now: true });
544
589
  onChange?.(next);
545
590
  return true;
546
591
  };
@@ -548,7 +593,7 @@ const useItemsEditor = (value, { render, onChange, onNodeChange } = {}) => {
548
593
  return new Set((isPrimitive ? primitiveItems : objectItems).filter((item) => indices.has(item.index)).map((item) => item.elementIndex));
549
594
  };
550
595
  const updateProperty = (elementIndex, propertyKey, next) => {
551
- commit(updateArrayItemProperty(value, elementIndex, propertyKey, next, render));
596
+ commit(updateArrayItemProperty(value, elementIndex, propertyKey, next, render), void 0, new Set(selection.selected));
552
597
  };
553
598
  return {
554
599
  kind,
@@ -565,7 +610,7 @@ const useItemsEditor = (value, { render, onChange, onNodeChange } = {}) => {
565
610
  value: item.value ?? "",
566
611
  rawValue: item.type === "unknown" ? item.source : String(item.value ?? ""),
567
612
  canEditValue: canLosslesslyEvaluateSource(item.source),
568
- onChange: (next) => commit(updateArrayItemValue(value, item.elementIndex, next))
613
+ onChange: (next) => commit(updateArrayItemValue(value, item.elementIndex, next), void 0, new Set(selection.selected))
569
614
  }
570
615
  })) : objectItems.map((item) => {
571
616
  const id = identity.ids[item.index] ?? item.id;
@@ -622,38 +667,40 @@ const useItemsEditor = (value, { render, onChange, onNodeChange } = {}) => {
622
667
  actions: {
623
668
  add: () => {
624
669
  const next = appendArrayItem(value, kind);
625
- commit(next, next ? [...identity.ids, nanoid(6)] : void 0);
670
+ commit(next, next ? [...identity.ids, nanoid(6)] : void 0, selectionAfter({ type: "append" }, selection.selected, rawItems.length));
626
671
  },
627
672
  move: (elementIndex, toIndex) => {
628
673
  const items = isPrimitive ? primitiveItems : objectItems;
629
674
  const from = items.find((item) => item.elementIndex === elementIndex);
630
675
  const target = items.find((item) => item.index === toIndex);
631
676
  if (!from || !target) return;
632
- if (commit(moveArrayItem(value, elementIndex, target.elementIndex), moveId(identity.ids, from.index, target.index))) selection.clear();
677
+ commit(moveArrayItem(value, elementIndex, target.elementIndex), moveId(identity.ids, from.index, target.index), /* @__PURE__ */ new Set());
633
678
  },
634
679
  remove: (elementIndex) => {
635
680
  const removed = (isPrimitive ? primitiveItems : objectItems).find((item) => item.elementIndex === elementIndex);
636
- if (commit(removeArrayItems(value, /* @__PURE__ */ new Set([elementIndex]), kind), removed ? removeIds(identity.ids, /* @__PURE__ */ new Set([removed.index])) : void 0)) selection.clear();
681
+ commit(removeArrayItems(value, /* @__PURE__ */ new Set([elementIndex]), kind), removed ? removeIds(identity.ids, /* @__PURE__ */ new Set([removed.index])) : void 0, /* @__PURE__ */ new Set());
637
682
  },
638
683
  duplicateSelected: () => {
639
684
  const selected = elementIndicesOf(selection.selected);
640
685
  const next = duplicateArrayItems(value, selected);
641
686
  const copied = rawItems.filter((item) => selected.has(item.elementIndex)).sort((a, b) => a.elementIndex - b.elementIndex).map(() => nanoid(6));
642
- commit(next, next ? [...identity.ids, ...copied] : void 0);
687
+ commit(next, next ? [...identity.ids, ...copied] : void 0, selectionAfter({
688
+ type: "duplicate",
689
+ indices: [...selection.selected]
690
+ }, selection.selected, rawItems.length));
643
691
  },
644
692
  moveSelected: (direction) => {
645
693
  const nextIdentity = moveSelectedIndices(identity.ids, selection.selected, direction);
646
694
  const result = moveArrayItems(value, elementIndicesOf(selection.selected), direction);
647
695
  if (!result) {
648
- commit(null);
696
+ commit(null, void 0, selection.selected);
649
697
  return;
650
698
  }
651
699
  const visible = parseArrayExpression(result.code)?.elements.flatMap((node, index) => import_lib.isExpression(node) && import_lib.isObjectExpression(node) === !isPrimitive ? [index] : []) ?? [];
652
- selection.replace(new Set(visible.flatMap((position, index) => result.indices.has(position) ? [index] : [])));
653
- commit(result.code, nextIdentity.items);
700
+ commit(result.code, nextIdentity.items, new Set(visible.flatMap((position, index) => result.indices.has(position) ? [index] : [])));
654
701
  },
655
702
  removeSelected: () => {
656
- if (commit(removeArrayItems(value, elementIndicesOf(selection.selected), kind), removeIds(identity.ids, selection.selected))) selection.clear();
703
+ commit(removeArrayItems(value, elementIndicesOf(selection.selected), kind), removeIds(identity.ids, selection.selected), /* @__PURE__ */ new Set());
657
704
  }
658
705
  },
659
706
  canEditStructure,
@@ -1825,4 +1872,4 @@ Dnd.Layout = Layout;
1825
1872
  //#endregion
1826
1873
  export { Panel as a, useChildrenEditor as c, useDndPanel as d, DraggableItem as f, Palette as i, useDndLayout as l, Canvas as n, Field as o, Layout as r, useItemsEditor as s, Dnd as t, useDndPalette as u };
1827
1874
 
1828
- //# sourceMappingURL=dnd-ClnGRNaY.js.map
1875
+ //# sourceMappingURL=dnd-_0jfnnVB.js.map