@pixerate/editor 0.19.0 → 0.20.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 (112) hide show
  1. package/README.md +91 -2
  2. package/dist/agent/index.cjs +625 -2
  3. package/dist/agent/index.cjs.map +1 -1
  4. package/dist/agent/index.d.cts +286 -2
  5. package/dist/agent/index.d.ts +286 -2
  6. package/dist/agent/index.js +624 -1
  7. package/dist/agent/index.js.map +1 -1
  8. package/dist/canvas/index.cjs +1240 -22
  9. package/dist/canvas/index.cjs.map +1 -1
  10. package/dist/canvas/index.d.cts +515 -3
  11. package/dist/canvas/index.d.ts +515 -3
  12. package/dist/canvas/index.js +1219 -1
  13. package/dist/canvas/index.js.map +1 -1
  14. package/dist/chunk-3TYMNULT.js +1367 -0
  15. package/dist/chunk-3TYMNULT.js.map +1 -0
  16. package/dist/chunk-4QPLEUL2.cjs +4480 -0
  17. package/dist/chunk-4QPLEUL2.cjs.map +1 -0
  18. package/dist/chunk-4SUNJZWB.cjs +553 -0
  19. package/dist/chunk-4SUNJZWB.cjs.map +1 -0
  20. package/dist/chunk-A7DKIA72.js +2657 -0
  21. package/dist/chunk-A7DKIA72.js.map +1 -0
  22. package/dist/chunk-AXV2ZW34.cjs +118 -0
  23. package/dist/chunk-AXV2ZW34.cjs.map +1 -0
  24. package/dist/chunk-B2ZRLN4S.js +118 -0
  25. package/dist/chunk-B2ZRLN4S.js.map +1 -0
  26. package/dist/chunk-CYFJCKC4.js +4480 -0
  27. package/dist/chunk-CYFJCKC4.js.map +1 -0
  28. package/dist/chunk-GVW4P7BG.js +2706 -0
  29. package/dist/chunk-GVW4P7BG.js.map +1 -0
  30. package/dist/chunk-JACER6TE.cjs +1 -0
  31. package/dist/chunk-JACER6TE.cjs.map +1 -0
  32. package/dist/chunk-JYRIOFEN.cjs +2657 -0
  33. package/dist/chunk-JYRIOFEN.cjs.map +1 -0
  34. package/dist/chunk-KYRZDWM4.js +299 -0
  35. package/dist/chunk-KYRZDWM4.js.map +1 -0
  36. package/dist/chunk-LA7PEGU3.cjs +299 -0
  37. package/dist/chunk-LA7PEGU3.cjs.map +1 -0
  38. package/dist/chunk-N7FG6CBO.js +1 -0
  39. package/dist/chunk-N7FG6CBO.js.map +1 -0
  40. package/dist/chunk-OYXSKQFR.js +553 -0
  41. package/dist/chunk-OYXSKQFR.js.map +1 -0
  42. package/dist/chunk-TVRC4KVT.cjs +1367 -0
  43. package/dist/chunk-TVRC4KVT.cjs.map +1 -0
  44. package/dist/chunk-U6NDQFOK.cjs +2706 -0
  45. package/dist/chunk-U6NDQFOK.cjs.map +1 -0
  46. package/dist/controller-OUdxPY-X.d.cts +754 -0
  47. package/dist/controller-OUdxPY-X.d.ts +754 -0
  48. package/dist/extensions/index.cjs +144 -3
  49. package/dist/extensions/index.cjs.map +1 -1
  50. package/dist/extensions/index.d.cts +9 -144
  51. package/dist/extensions/index.d.ts +9 -144
  52. package/dist/extensions/index.js +145 -4
  53. package/dist/grammar/index.cjs +31 -3
  54. package/dist/grammar/index.cjs.map +1 -1
  55. package/dist/grammar/index.d.cts +239 -19
  56. package/dist/grammar/index.d.ts +239 -19
  57. package/dist/grammar/index.js +31 -3
  58. package/dist/history/index.d.cts +2 -41
  59. package/dist/history/index.d.ts +2 -41
  60. package/dist/index-Ng1pG7JE.d.ts +899 -0
  61. package/dist/index-k3mFbPx_.d.cts +899 -0
  62. package/dist/index.cjs +457 -20
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +99 -12
  65. package/dist/index.d.ts +99 -12
  66. package/dist/index.js +457 -20
  67. package/dist/index.js.map +1 -1
  68. package/dist/registry-iAHbqkYt.d.cts +128 -0
  69. package/dist/registry-iAHbqkYt.d.ts +128 -0
  70. package/dist/serializers/index.cjs +26 -3
  71. package/dist/serializers/index.cjs.map +1 -1
  72. package/dist/serializers/index.d.cts +119 -6
  73. package/dist/serializers/index.d.ts +119 -6
  74. package/dist/serializers/index.js +24 -1
  75. package/dist/spreadsheet/index.cjs +122 -2
  76. package/dist/spreadsheet/index.cjs.map +1 -1
  77. package/dist/spreadsheet/index.d.cts +371 -313
  78. package/dist/spreadsheet/index.d.ts +371 -313
  79. package/dist/spreadsheet/index.js +127 -7
  80. package/dist/tokens-CyLZmIei.d.cts +76 -0
  81. package/dist/tokens-CyLZmIei.d.ts +76 -0
  82. package/dist/track-changes-G8JcWB8b.d.cts +306 -0
  83. package/dist/track-changes-G8JcWB8b.d.ts +306 -0
  84. package/dist/types-BZgcDsC5.d.cts +42 -0
  85. package/dist/types-BZgcDsC5.d.ts +42 -0
  86. package/dist/{types-JV3S8VeR.d.cts → types-DMe0vFB1.d.cts} +1 -1
  87. package/dist/{types-JV3S8VeR.d.ts → types-DMe0vFB1.d.ts} +1 -1
  88. package/package.json +1 -1
  89. package/dist/chunk-7FWEWE6T.js +0 -1888
  90. package/dist/chunk-7FWEWE6T.js.map +0 -1
  91. package/dist/chunk-AIZUKWTL.js +0 -1715
  92. package/dist/chunk-AIZUKWTL.js.map +0 -1
  93. package/dist/chunk-GLSIZKOX.js +0 -17
  94. package/dist/chunk-GLSIZKOX.js.map +0 -1
  95. package/dist/chunk-LDES3EOS.cjs +0 -1888
  96. package/dist/chunk-LDES3EOS.cjs.map +0 -1
  97. package/dist/chunk-LLUAKTLW.cjs +0 -532
  98. package/dist/chunk-LLUAKTLW.cjs.map +0 -1
  99. package/dist/chunk-MPPXH7U5.cjs +0 -336
  100. package/dist/chunk-MPPXH7U5.cjs.map +0 -1
  101. package/dist/chunk-O7LOPQMH.js +0 -336
  102. package/dist/chunk-O7LOPQMH.js.map +0 -1
  103. package/dist/chunk-QGVMBCT5.js +0 -532
  104. package/dist/chunk-QGVMBCT5.js.map +0 -1
  105. package/dist/chunk-SEDR75VH.cjs +0 -17
  106. package/dist/chunk-SEDR75VH.cjs.map +0 -1
  107. package/dist/chunk-YQCI4CCN.cjs +0 -1715
  108. package/dist/chunk-YQCI4CCN.cjs.map +0 -1
  109. package/dist/mention-Dcevh3ff.d.cts +0 -32
  110. package/dist/mention-Dcevh3ff.d.ts +0 -32
  111. package/dist/tokens-7kRTEtPb.d.cts +0 -39
  112. package/dist/tokens-7kRTEtPb.d.ts +0 -39
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3;
2
2
 
3
3
 
4
4
 
@@ -160,7 +160,7 @@ function withStyleOpacity(style, opacity, emptyFormat = "string") {
160
160
  }
161
161
  function runMultiNodeTransition(transitions, options = {}) {
162
162
  if (transitions.length === 0) {
163
- _optionalChain([options, 'access', _ => _.onComplete, 'optionalCall', _2 => _2([])]);
163
+ _optionalChain([options, 'access', _2 => _2.onComplete, 'optionalCall', _3 => _3([])]);
164
164
  return () => {
165
165
  };
166
166
  }
@@ -215,11 +215,11 @@ function runMultiNodeTransition(transitions, options = {}) {
215
215
  allCompleted = false;
216
216
  }
217
217
  }
218
- _optionalChain([onUpdate, 'optionalCall', _3 => _3(current.slice())]);
218
+ _optionalChain([onUpdate, 'optionalCall', _4 => _4(current.slice())]);
219
219
  if (!allCompleted) {
220
220
  clock.frame().then(frame);
221
221
  } else {
222
- _optionalChain([onComplete, 'optionalCall', _4 => _4(current.slice())]);
222
+ _optionalChain([onComplete, 'optionalCall', _5 => _5(current.slice())]);
223
223
  }
224
224
  }
225
225
  frame();
@@ -239,8 +239,8 @@ function computeNodesBoundingBox(nodes, defaultWidth = 200, defaultHeight = 60)
239
239
  let maxX = -Infinity;
240
240
  let maxY = -Infinity;
241
241
  for (const node of nodes) {
242
- const width = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _5 => _5.measured, 'optionalAccess', _6 => _6.width]), () => ( node.width)), () => ( defaultWidth));
243
- const height = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _7 => _7.measured, 'optionalAccess', _8 => _8.height]), () => ( node.height)), () => ( defaultHeight));
242
+ const width = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _6 => _6.measured, 'optionalAccess', _7 => _7.width]), () => ( node.width)), () => ( defaultWidth));
243
+ const height = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _8 => _8.measured, 'optionalAccess', _9 => _9.height]), () => ( node.height)), () => ( defaultHeight));
244
244
  minX = Math.min(minX, node.position.x);
245
245
  minY = Math.min(minY, node.position.y);
246
246
  maxX = Math.max(maxX, node.position.x + width);
@@ -273,8 +273,8 @@ function calculateDirectionalDisplacement(params) {
273
273
  return displacedMap;
274
274
  }
275
275
  const childBounds = getNodesBounds ? getNodesBounds(childNodes) : computeNodesBoundingBox(childNodes);
276
- const originWidth = _nullishCoalesce(_nullishCoalesce(_optionalChain([originNode, 'access', _9 => _9.measured, 'optionalAccess', _10 => _10.width]), () => ( originNode.width)), () => ( 200));
277
- const originHeight = _nullishCoalesce(_nullishCoalesce(_optionalChain([originNode, 'access', _11 => _11.measured, 'optionalAccess', _12 => _12.height]), () => ( originNode.height)), () => ( 60));
276
+ const originWidth = _nullishCoalesce(_nullishCoalesce(_optionalChain([originNode, 'access', _10 => _10.measured, 'optionalAccess', _11 => _11.width]), () => ( originNode.width)), () => ( 200));
277
+ const originHeight = _nullishCoalesce(_nullishCoalesce(_optionalChain([originNode, 'access', _12 => _12.measured, 'optionalAccess', _13 => _13.height]), () => ( originNode.height)), () => ( 60));
278
278
  const deltaPrimary = direction === "right" || direction === "left" ? childBounds.width + gap : childBounds.height + gap;
279
279
  const deltaUp = Math.max(0, originNode.position.y - childBounds.y + gap);
280
280
  const deltaDown = Math.max(
@@ -382,8 +382,8 @@ function calculateDagreReflowDisplacement(params) {
382
382
  g.setGraph({ rankdir: direction, ranksep, nodesep });
383
383
  const nodeIds = new Set(futureNodes.map((n) => n.id));
384
384
  futureNodes.forEach((node) => {
385
- const nodeWidth = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _13 => _13.measured, 'optionalAccess', _14 => _14.width]), () => ( node.width)), () => ( defaultNodeWidth));
386
- const nodeHeight = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _15 => _15.measured, 'optionalAccess', _16 => _16.height]), () => ( node.height)), () => ( defaultNodeHeight));
385
+ const nodeWidth = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _14 => _14.measured, 'optionalAccess', _15 => _15.width]), () => ( node.width)), () => ( defaultNodeWidth));
386
+ const nodeHeight = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _16 => _16.measured, 'optionalAccess', _17 => _17.height]), () => ( node.height)), () => ( defaultNodeHeight));
387
387
  g.setNode(node.id, { width: nodeWidth, height: nodeHeight });
388
388
  });
389
389
  futureEdges.forEach((edge) => {
@@ -394,8 +394,8 @@ function calculateDagreReflowDisplacement(params) {
394
394
  _dagre2.default.layout(g);
395
395
  const anchorLayoutPos = g.node(anchorNodeId);
396
396
  if (!anchorLayoutPos) return /* @__PURE__ */ new Map();
397
- const anchorWidth = _nullishCoalesce(_nullishCoalesce(_optionalChain([anchorNode, 'access', _17 => _17.measured, 'optionalAccess', _18 => _18.width]), () => ( anchorNode.width)), () => ( defaultNodeWidth));
398
- const anchorHeight = _nullishCoalesce(_nullishCoalesce(_optionalChain([anchorNode, 'access', _19 => _19.measured, 'optionalAccess', _20 => _20.height]), () => ( anchorNode.height)), () => ( defaultNodeHeight));
397
+ const anchorWidth = _nullishCoalesce(_nullishCoalesce(_optionalChain([anchorNode, 'access', _18 => _18.measured, 'optionalAccess', _19 => _19.width]), () => ( anchorNode.width)), () => ( defaultNodeWidth));
398
+ const anchorHeight = _nullishCoalesce(_nullishCoalesce(_optionalChain([anchorNode, 'access', _20 => _20.measured, 'optionalAccess', _21 => _21.height]), () => ( anchorNode.height)), () => ( defaultNodeHeight));
399
399
  const anchorLayoutUpperLeft = {
400
400
  x: anchorLayoutPos.x - anchorWidth / 2,
401
401
  y: anchorLayoutPos.y - anchorHeight / 2
@@ -407,8 +407,8 @@ function calculateDagreReflowDisplacement(params) {
407
407
  if (node.id === anchorNodeId) return;
408
408
  const layoutNode = g.node(node.id);
409
409
  if (!layoutNode) return;
410
- const nodeWidth = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _21 => _21.measured, 'optionalAccess', _22 => _22.width]), () => ( node.width)), () => ( defaultNodeWidth));
411
- const nodeHeight = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _23 => _23.measured, 'optionalAccess', _24 => _24.height]), () => ( node.height)), () => ( defaultNodeHeight));
410
+ const nodeWidth = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _22 => _22.measured, 'optionalAccess', _23 => _23.width]), () => ( node.width)), () => ( defaultNodeWidth));
411
+ const nodeHeight = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _24 => _24.measured, 'optionalAccess', _25 => _25.height]), () => ( node.height)), () => ( defaultNodeHeight));
412
412
  const upperLeftX = layoutNode.x - nodeWidth / 2 + deltaX;
413
413
  const upperLeftY = layoutNode.y - nodeHeight / 2 + deltaY;
414
414
  if (Math.abs(upperLeftX - node.position.x) > 1 || Math.abs(upperLeftY - node.position.y) > 1) {
@@ -422,7 +422,7 @@ function calculateDagreReflowDisplacement(params) {
422
422
  function isEventFromTextInput(event) {
423
423
  const target = event.target;
424
424
  if (!target) return false;
425
- if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.tagName === "SELECT" || target.isContentEditable || _optionalChain([target, 'access', _25 => _25.closest, 'optionalCall', _26 => _26('[contenteditable="true"]')]) || _optionalChain([target, 'access', _27 => _27.closest, 'optionalCall', _28 => _28(".ProseMirror")])) {
425
+ if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.tagName === "SELECT" || target.isContentEditable || _optionalChain([target, 'access', _26 => _26.closest, 'optionalCall', _27 => _27('[contenteditable="true"]')]) || _optionalChain([target, 'access', _28 => _28.closest, 'optionalCall', _29 => _29(".ProseMirror")])) {
426
426
  return true;
427
427
  }
428
428
  return false;
@@ -469,8 +469,8 @@ function parseCanvasClipboardData(raw) {
469
469
  function remapPastedNodes(nodes, edges = [], offset = { x: 30, y: 30 }, idGenerator = () => `node-${Math.random().toString(36).substring(2, 9)}`) {
470
470
  const validNodes = (Array.isArray(nodes) ? nodes : []).filter(isValidCanvasNode);
471
471
  const validEdges = (Array.isArray(edges) ? edges : []).filter(isValidCanvasEdge);
472
- const dx = Number.isFinite(_optionalChain([offset, 'optionalAccess', _29 => _29.x])) ? offset.x : 0;
473
- const dy = Number.isFinite(_optionalChain([offset, 'optionalAccess', _30 => _30.y])) ? offset.y : 0;
472
+ const dx = Number.isFinite(_optionalChain([offset, 'optionalAccess', _30 => _30.x])) ? offset.x : 0;
473
+ const dy = Number.isFinite(_optionalChain([offset, 'optionalAccess', _31 => _31.y])) ? offset.y : 0;
474
474
  const idMap = /* @__PURE__ */ new Map();
475
475
  for (const node of validNodes) {
476
476
  idMap.set(node.id, idGenerator());
@@ -547,7 +547,7 @@ function layoutBounds(nodes) {
547
547
  return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
548
548
  }
549
549
  function canvasHeight(nodes, options) {
550
- return clampHeight(_nullishCoalesce(_optionalChain([layoutBounds, 'call', _31 => _31(nodes), 'optionalAccess', _32 => _32.height]), () => ( 0)), options);
550
+ return clampHeight(_nullishCoalesce(_optionalChain([layoutBounds, 'call', _32 => _32(nodes), 'optionalAccess', _33 => _33.height]), () => ( 0)), options);
551
551
  }
552
552
  var DEFAULT_RANK_HEIGHT = 80 + 72;
553
553
  var NODES_PER_RANK = 2;
@@ -683,7 +683,7 @@ var StreamingLayoutManager = (_class2 = class {
683
683
  this.targetPositions = nextPositions;
684
684
  if (transitions.length === 0) {
685
685
  this.livePositions = new Map(nextPositions);
686
- _optionalChain([this, 'access', _33 => _33.onLayoutUpdated, 'optionalCall', _34 => _34(nextPositions)]);
686
+ _optionalChain([this, 'access', _34 => _34.onLayoutUpdated, 'optionalCall', _35 => _35(nextPositions)]);
687
687
  return;
688
688
  }
689
689
  const live = new Map(nextPositions);
@@ -700,13 +700,13 @@ var StreamingLayoutManager = (_class2 = class {
700
700
  frame.set(node.id, { ...node.position });
701
701
  }
702
702
  this.livePositions = frame;
703
- _optionalChain([this, 'access', _35 => _35.onLayoutUpdated, 'optionalCall', _36 => _36(frame)]);
703
+ _optionalChain([this, 'access', _36 => _36.onLayoutUpdated, 'optionalCall', _37 => _37(frame)]);
704
704
  },
705
705
  onComplete: () => {
706
706
  finished = true;
707
707
  this.activeTransitionCancel = null;
708
708
  this.livePositions = new Map(nextPositions);
709
- _optionalChain([this, 'access', _37 => _37.onLayoutUpdated, 'optionalCall', _38 => _38(nextPositions)]);
709
+ _optionalChain([this, 'access', _38 => _38.onLayoutUpdated, 'optionalCall', _39 => _39(nextPositions)]);
710
710
  }
711
711
  });
712
712
  this.activeTransitionCancel = finished ? null : cancel;
@@ -720,6 +720,1224 @@ var StreamingLayoutManager = (_class2 = class {
720
720
  }
721
721
  }, _class2);
722
722
 
723
+ // src/canvas/arrange.ts
724
+ var LOCKED_DATA_KEY = "locked";
725
+ var LOCKED_PREVIOUS_FLAGS_KEY = "lockedPrevious";
726
+ function parsePx(value) {
727
+ if (typeof value === "number" && Number.isFinite(value)) return value;
728
+ if (typeof value === "string") {
729
+ const match = /^\s*(-?\d+(?:\.\d+)?)(px)?\s*$/i.exec(value);
730
+ if (match) return Number(match[1]);
731
+ }
732
+ return void 0;
733
+ }
734
+ function readStyleSize(style) {
735
+ if (!style) return {};
736
+ if (typeof style === "object") {
737
+ return { width: parsePx(style.width), height: parsePx(style.height) };
738
+ }
739
+ const read = (prop) => {
740
+ const match = new RegExp(`(?:^|;)\\s*${prop}\\s*:\\s*([^;]+)`, "i").exec(style);
741
+ return match ? parsePx(match[1]) : void 0;
742
+ };
743
+ return { width: read("width"), height: read("height") };
744
+ }
745
+ function withStyleSize(style, size) {
746
+ if (!style) return _nullishCoalesce(style, () => ( void 0));
747
+ if (typeof style === "object") {
748
+ const next2 = { ...style };
749
+ if (size.width !== void 0 && "width" in next2) next2.width = size.width;
750
+ if (size.height !== void 0 && "height" in next2) next2.height = size.height;
751
+ return next2;
752
+ }
753
+ let next = style;
754
+ for (const prop of ["width", "height"]) {
755
+ const value = size[prop];
756
+ if (value === void 0) continue;
757
+ next = next.replace(
758
+ new RegExp(`((?:^|;)\\s*${prop}\\s*:\\s*)[^;]+`, "i"),
759
+ `$1${value}px`
760
+ );
761
+ }
762
+ return next;
763
+ }
764
+ function getNodeSize(node, options = {}) {
765
+ const styleSize = readStyleSize(node.style);
766
+ let width = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _40 => _40.measured, 'optionalAccess', _41 => _41.width]), () => ( node.width)), () => ( styleSize.width));
767
+ let height = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _42 => _42.measured, 'optionalAccess', _43 => _43.height]), () => ( node.height)), () => ( styleSize.height));
768
+ if (width === void 0 || height === void 0) {
769
+ const fallback = options.estimate === false ? { width: _nullishCoalesce(options.defaultWidth, () => ( 200)), height: _nullishCoalesce(options.defaultHeight, () => ( 60)) } : _chunkWADCJ7A7cjs.estimateNodeSize.call(void 0, node, options.defaultWidth, options.defaultHeight);
770
+ width ??= fallback.width;
771
+ height ??= fallback.height;
772
+ }
773
+ return { width, height };
774
+ }
775
+ function getAbsolutePosition(node, lookup) {
776
+ let x = node.position.x;
777
+ let y = node.position.y;
778
+ const seen = /* @__PURE__ */ new Set([node.id]);
779
+ let parentId = node.parentId;
780
+ while (parentId && !seen.has(parentId)) {
781
+ const parent = lookup.get(parentId);
782
+ if (!parent) break;
783
+ seen.add(parentId);
784
+ x += parent.position.x;
785
+ y += parent.position.y;
786
+ parentId = parent.parentId;
787
+ }
788
+ return { x, y };
789
+ }
790
+ function createNodeLookup(nodes) {
791
+ return new Map(nodes.map((n) => [n.id, n]));
792
+ }
793
+ function getNodeRect(node, lookup, options) {
794
+ const { x, y } = node.parentId && lookup ? getAbsolutePosition(node, lookup) : node.position;
795
+ return { x, y, ...getNodeSize(node, options) };
796
+ }
797
+ function isLocked(node) {
798
+ return _optionalChain([node, 'optionalAccess', _44 => _44.data, 'optionalAccess', _45 => _45[LOCKED_DATA_KEY]]) === true;
799
+ }
800
+ function lockNodes(nodes, ids) {
801
+ const idSet = new Set(ids);
802
+ return nodes.map((node) => {
803
+ if (!idSet.has(node.id) || isLocked(node)) return node;
804
+ const previous = {};
805
+ if (node.draggable !== void 0) previous.draggable = node.draggable;
806
+ if (node.deletable !== void 0) previous.deletable = node.deletable;
807
+ return {
808
+ ...node,
809
+ draggable: false,
810
+ deletable: false,
811
+ data: { ...node.data, [LOCKED_DATA_KEY]: true, [LOCKED_PREVIOUS_FLAGS_KEY]: previous }
812
+ };
813
+ });
814
+ }
815
+ function unlockNodes(nodes, ids) {
816
+ const idSet = new Set(ids);
817
+ return nodes.map((node) => {
818
+ if (!idSet.has(node.id) || !isLocked(node)) return node;
819
+ const {
820
+ [LOCKED_DATA_KEY]: _locked,
821
+ [LOCKED_PREVIOUS_FLAGS_KEY]: previous = {},
822
+ ...data
823
+ } = node.data;
824
+ const next = { ...node, data };
825
+ delete next.draggable;
826
+ delete next.deletable;
827
+ if (previous.draggable !== void 0) next.draggable = previous.draggable;
828
+ if (previous.deletable !== void 0) next.deletable = previous.deletable;
829
+ return next;
830
+ });
831
+ }
832
+ function toggleLockNodes(nodes, ids) {
833
+ const idSet = new Set(ids);
834
+ const anyUnlocked = nodes.some((n) => idSet.has(n.id) && !isLocked(n));
835
+ return anyUnlocked ? lockNodes(nodes, idSet) : unlockNodes(nodes, idSet);
836
+ }
837
+ function collect(nodes, ids, options) {
838
+ const lookup = createNodeLookup(nodes);
839
+ const items = [];
840
+ const seen = /* @__PURE__ */ new Set();
841
+ for (const id of ids) {
842
+ const node = lookup.get(id);
843
+ if (!node || seen.has(id)) continue;
844
+ seen.add(id);
845
+ items.push({ node, rect: getNodeRect(node, lookup, options), locked: isLocked(node) });
846
+ }
847
+ return { lookup, items };
848
+ }
849
+ function toPositionUpdates(lookup, targets) {
850
+ const updates = [];
851
+ for (const [id, abs] of targets) {
852
+ const node = lookup.get(id);
853
+ let position = abs;
854
+ if (node.parentId && lookup.has(node.parentId)) {
855
+ const parent = lookup.get(node.parentId);
856
+ const parentAbs = _nullishCoalesce(targets.get(parent.id), () => ( getAbsolutePosition(parent, lookup)));
857
+ position = { x: abs.x - parentAbs.x, y: abs.y - parentAbs.y };
858
+ }
859
+ if (position.x !== node.position.x || position.y !== node.position.y) {
860
+ updates.push({ id, position });
861
+ }
862
+ }
863
+ return updates;
864
+ }
865
+ function alignNodes(nodes, ids, edge, options = {}) {
866
+ const { lookup, items } = collect(nodes, ids, options);
867
+ const fixed = typeof options.to === "object" ? options.to : null;
868
+ if (items.length === 0 || !fixed && items.length < 2) return [];
869
+ const bounds = _nullishCoalesce(fixed, () => ( _chunkWADCJ7A7cjs.boundsOf.call(void 0, items.map((i) => i.rect))));
870
+ const targets = /* @__PURE__ */ new Map();
871
+ for (const { node, rect, locked } of items) {
872
+ if (locked) continue;
873
+ let { x, y } = rect;
874
+ switch (edge) {
875
+ case "left":
876
+ x = bounds.x;
877
+ break;
878
+ case "center":
879
+ x = bounds.x + bounds.width / 2 - rect.width / 2;
880
+ break;
881
+ case "right":
882
+ x = bounds.x + bounds.width - rect.width;
883
+ break;
884
+ case "top":
885
+ y = bounds.y;
886
+ break;
887
+ case "middle":
888
+ y = bounds.y + bounds.height / 2 - rect.height / 2;
889
+ break;
890
+ case "bottom":
891
+ y = bounds.y + bounds.height - rect.height;
892
+ break;
893
+ }
894
+ targets.set(node.id, { x, y });
895
+ }
896
+ return toPositionUpdates(lookup, targets);
897
+ }
898
+ function distributeAxis(items, horizontal, mode, gapOverride, targets) {
899
+ const start = (r) => horizontal ? r.x : r.y;
900
+ const size = (r) => horizontal ? r.width : r.height;
901
+ const sorted = [...items].sort(
902
+ (a, b) => start(a.rect) + size(a.rect) / 2 - (start(b.rect) + size(b.rect) / 2)
903
+ );
904
+ const first = sorted[0].rect;
905
+ const last = sorted[sorted.length - 1].rect;
906
+ const n = sorted.length;
907
+ const set = (item, value) => {
908
+ if (item.locked) return;
909
+ const current = _nullishCoalesce(targets.get(item.node.id), () => ( { x: item.rect.x, y: item.rect.y }));
910
+ targets.set(item.node.id, horizontal ? { ...current, x: value } : { ...current, y: value });
911
+ };
912
+ if (mode === "centres") {
913
+ const c0 = start(first) + size(first) / 2;
914
+ const c1 = start(last) + size(last) / 2;
915
+ const step = (c1 - c0) / (n - 1);
916
+ sorted.forEach((item, i) => set(item, c0 + step * i - size(item.rect) / 2));
917
+ return;
918
+ }
919
+ const span = start(last) + size(last) - start(first);
920
+ const total = sorted.reduce((sum, item) => sum + size(item.rect), 0);
921
+ const gap = _nullishCoalesce(gapOverride, () => ( (span - total) / (n - 1)));
922
+ let cursor = start(first);
923
+ for (const item of sorted) {
924
+ set(item, cursor);
925
+ cursor += size(item.rect) + gap;
926
+ }
927
+ }
928
+ function distributeNodes(nodes, ids, axis, mode = "gaps", options = {}) {
929
+ const { lookup, items } = collect(nodes, ids, options);
930
+ const minimum = options.gap !== void 0 && mode === "gaps" ? 2 : 3;
931
+ if (items.length < minimum) return [];
932
+ const targets = /* @__PURE__ */ new Map();
933
+ if (axis !== "vertical") distributeAxis(items, true, mode, options.gap, targets);
934
+ if (axis !== "horizontal") distributeAxis(items, false, mode, options.gap, targets);
935
+ return toPositionUpdates(lookup, targets);
936
+ }
937
+ function matchSize(nodes, ids, dimension, options = {}) {
938
+ const { items } = collect(nodes, ids, options);
939
+ if (items.length < 2) return [];
940
+ const reference = _nullishCoalesce(options.reference, () => ( "largest"));
941
+ const pick = (dim) => {
942
+ if (typeof reference === "object") {
943
+ const item = items.find((i) => i.node.id === reference.id);
944
+ if (item) return item.rect[dim];
945
+ }
946
+ if (reference === "first") return items[0].rect[dim];
947
+ const values = items.map((i) => i.rect[dim]);
948
+ return reference === "smallest" ? Math.min(...values) : Math.max(...values);
949
+ };
950
+ const width = dimension !== "height" ? pick("width") : void 0;
951
+ const height = dimension !== "width" ? pick("height") : void 0;
952
+ const updates = [];
953
+ for (const { node, rect, locked } of items) {
954
+ if (locked) continue;
955
+ const update = { id: node.id };
956
+ if (width !== void 0 && width !== rect.width) update.width = width;
957
+ if (height !== void 0 && height !== rect.height) update.height = height;
958
+ if (update.width === void 0 && update.height === void 0) continue;
959
+ if (options.keepCentre) {
960
+ update.position = {
961
+ x: node.position.x - ((_nullishCoalesce(update.width, () => ( rect.width))) - rect.width) / 2,
962
+ y: node.position.y - ((_nullishCoalesce(update.height, () => ( rect.height))) - rect.height) / 2
963
+ };
964
+ }
965
+ updates.push(update);
966
+ }
967
+ return updates;
968
+ }
969
+ function reorderNodes(nodes, ids, operation, options = {}) {
970
+ const lookup = createNodeLookup(nodes);
971
+ const targetIds = new Set(
972
+ [...ids].filter((id) => lookup.has(id) && !isLocked(lookup.get(id)))
973
+ );
974
+ if (targetIds.size === 0) return [];
975
+ const groups = /* @__PURE__ */ new Map();
976
+ for (const node of nodes) {
977
+ const key = _nullishCoalesce(node.parentId, () => ( ""));
978
+ if (!groups.has(key)) groups.set(key, []);
979
+ groups.get(key).push(node);
980
+ }
981
+ const updates = [];
982
+ for (const siblings of groups.values()) {
983
+ if (!siblings.some((n) => targetIds.has(n.id))) continue;
984
+ const order = siblings.map((node, index) => ({ node, index, z: typeof node.zIndex === "number" ? node.zIndex : 0 })).sort((a, b) => a.z - b.z || a.index - b.index).map((entry) => entry.node);
985
+ const isTarget = (n) => targetIds.has(n.id);
986
+ let next;
987
+ if (operation === "bringToFront") {
988
+ next = [...order.filter((n) => !isTarget(n)), ...order.filter(isTarget)];
989
+ } else if (operation === "sendToBack") {
990
+ next = [...order.filter(isTarget), ...order.filter((n) => !isTarget(n))];
991
+ } else {
992
+ next = [...order];
993
+ const forward = operation === "bringForward";
994
+ const rects = new Map(next.map((n) => [n.id, getNodeRect(n, lookup, options)]));
995
+ const intersects = (a, b) => a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y;
996
+ const indices = next.map((_, i) => i);
997
+ if (forward) indices.reverse();
998
+ for (const i of indices) {
999
+ const node = next[i];
1000
+ if (!isTarget(node)) continue;
1001
+ const step = forward ? 1 : -1;
1002
+ let j = i + step;
1003
+ let swapWith = -1;
1004
+ let firstNonTarget = -1;
1005
+ while (j >= 0 && j < next.length) {
1006
+ if (!isTarget(next[j])) {
1007
+ if (firstNonTarget === -1) firstNonTarget = j;
1008
+ if (intersects(rects.get(node.id), rects.get(next[j].id))) {
1009
+ swapWith = j;
1010
+ break;
1011
+ }
1012
+ }
1013
+ j += step;
1014
+ }
1015
+ if (swapWith === -1) swapWith = firstNonTarget;
1016
+ if (swapWith === -1) continue;
1017
+ next.splice(i, 1);
1018
+ next.splice(swapWith, 0, node);
1019
+ }
1020
+ }
1021
+ if (next.every((node, i) => node === order[i])) continue;
1022
+ next.forEach((node, rank) => {
1023
+ const current = typeof node.zIndex === "number" ? node.zIndex : 0;
1024
+ if (current !== rank) updates.push({ id: node.id, zIndex: rank });
1025
+ });
1026
+ }
1027
+ return updates;
1028
+ }
1029
+ function applyNodeUpdates(nodes, updates) {
1030
+ if (updates.length === 0) return nodes;
1031
+ const byId = /* @__PURE__ */ new Map();
1032
+ for (const update of updates) {
1033
+ byId.set(update.id, { ...byId.get(update.id), ...update });
1034
+ }
1035
+ return nodes.map((node) => {
1036
+ const update = byId.get(node.id);
1037
+ if (!update) return node;
1038
+ const next = { ...node };
1039
+ if (update.position) next.position = { ...update.position };
1040
+ if (update.zIndex !== void 0) next.zIndex = update.zIndex;
1041
+ if (update.width !== void 0 || update.height !== void 0) {
1042
+ if (update.width !== void 0) next.width = update.width;
1043
+ if (update.height !== void 0) next.height = update.height;
1044
+ if (node.style) next.style = withStyleSize(node.style, update);
1045
+ if (node.measured) {
1046
+ next.measured = {
1047
+ ...node.measured,
1048
+ ...update.width !== void 0 ? { width: update.width } : {},
1049
+ ...update.height !== void 0 ? { height: update.height } : {}
1050
+ };
1051
+ }
1052
+ }
1053
+ return next;
1054
+ });
1055
+ }
1056
+ function invertNodeUpdates(nodes, updates) {
1057
+ const lookup = createNodeLookup(nodes);
1058
+ const inverse = [];
1059
+ for (const update of updates) {
1060
+ const node = lookup.get(update.id);
1061
+ if (!node) continue;
1062
+ const back = { id: node.id };
1063
+ if (update.position) back.position = { ...node.position };
1064
+ if (update.zIndex !== void 0) back.zIndex = typeof node.zIndex === "number" ? node.zIndex : 0;
1065
+ if (update.width !== void 0 || update.height !== void 0) {
1066
+ const size = getNodeSize(node);
1067
+ if (update.width !== void 0) back.width = size.width;
1068
+ if (update.height !== void 0) back.height = size.height;
1069
+ }
1070
+ inverse.push(back);
1071
+ }
1072
+ return inverse;
1073
+ }
1074
+
1075
+ // src/canvas/guides.ts
1076
+ function buildAxis(entries) {
1077
+ entries.sort((a, b) => a.value - b.value);
1078
+ return {
1079
+ values: Float64Array.from(entries.map((e) => e.value)),
1080
+ rects: entries.map((e) => e.rect)
1081
+ };
1082
+ }
1083
+ function lowerBound(values, v) {
1084
+ let lo = 0;
1085
+ let hi = values.length;
1086
+ while (lo < hi) {
1087
+ const mid = lo + hi >>> 1;
1088
+ if (values[mid] < v) lo = mid + 1;
1089
+ else hi = mid;
1090
+ }
1091
+ return lo;
1092
+ }
1093
+ function createGuideIndex(rects) {
1094
+ const edgeX = [];
1095
+ const centreX = [];
1096
+ const edgeY = [];
1097
+ const centreY = [];
1098
+ for (const rect of rects) {
1099
+ edgeX.push({ value: rect.x, rect }, { value: rect.x + rect.width, rect });
1100
+ centreX.push({ value: rect.x + rect.width / 2, rect });
1101
+ edgeY.push({ value: rect.y, rect }, { value: rect.y + rect.height, rect });
1102
+ centreY.push({ value: rect.y + rect.height / 2, rect });
1103
+ }
1104
+ return {
1105
+ rects,
1106
+ edgeX: buildAxis(edgeX),
1107
+ centreX: buildAxis(centreX),
1108
+ edgeY: buildAxis(edgeY),
1109
+ centreY: buildAxis(centreY)
1110
+ };
1111
+ }
1112
+ function nearest(axis, v, tolerance) {
1113
+ const { values } = axis;
1114
+ let best = null;
1115
+ for (let i = lowerBound(values, v - tolerance); i < values.length && values[i] <= v + tolerance; i++) {
1116
+ const delta = values[i] - v;
1117
+ if (best === null || Math.abs(delta) < Math.abs(best)) best = delta;
1118
+ }
1119
+ return best;
1120
+ }
1121
+ function matches(axis, v, eps) {
1122
+ const { values, rects } = axis;
1123
+ const out = [];
1124
+ for (let i = lowerBound(values, v - eps); i < values.length && values[i] <= v + eps; i++) {
1125
+ out.push(rects[i]);
1126
+ }
1127
+ return out;
1128
+ }
1129
+ function spacingCandidate(rects, moving, horizontal, tolerance) {
1130
+ const start = (r) => horizontal ? r.x : r.y;
1131
+ const end = (r) => horizontal ? r.x + r.width : r.y + r.height;
1132
+ const crossStart = (r) => horizontal ? r.y : r.x;
1133
+ const crossEnd = (r) => horizontal ? r.y + r.height : r.x + r.width;
1134
+ const size = end(moving) - start(moving);
1135
+ const inLane = (r, lane2) => crossStart(r) < crossEnd(lane2) && crossEnd(r) > crossStart(lane2);
1136
+ const lane = rects.filter((r) => inLane(r, moving));
1137
+ if (lane.length === 0) return null;
1138
+ let before = null;
1139
+ let after = null;
1140
+ for (const r of lane) {
1141
+ if (end(r) <= start(moving) + tolerance && (!before || end(r) > end(before))) before = r;
1142
+ if (start(r) >= end(moving) - tolerance && (!after || start(r) < start(after))) after = r;
1143
+ }
1144
+ const neighbourOf = (r, forward) => {
1145
+ let best2 = null;
1146
+ for (const other of lane) {
1147
+ if (other === r || !inLane(other, r)) continue;
1148
+ if (forward ? start(other) >= end(r) : end(other) <= start(r)) {
1149
+ if (!best2 || (forward ? start(other) < start(best2) : end(other) > end(best2))) best2 = other;
1150
+ }
1151
+ }
1152
+ return best2;
1153
+ };
1154
+ const crossMid = (a, b) => (Math.max(crossStart(a), crossStart(b)) + Math.min(crossEnd(a), crossEnd(b))) / 2;
1155
+ const segment = (from, to, cross) => horizontal ? { orientation: "horizontal", kind: "spacing", x1: from, y1: cross, x2: to, y2: cross } : { orientation: "vertical", kind: "spacing", x1: cross, y1: from, x2: cross, y2: to };
1156
+ const candidates = [];
1157
+ if (before && after) {
1158
+ const b = before;
1159
+ const a = after;
1160
+ const pos = (end(b) + start(a) - size) / 2;
1161
+ if (pos >= end(b)) {
1162
+ candidates.push({
1163
+ pos,
1164
+ guides: (p) => [
1165
+ segment(end(b), p, crossMid(b, moving)),
1166
+ segment(p + size, start(a), crossMid(a, moving))
1167
+ ]
1168
+ });
1169
+ }
1170
+ }
1171
+ if (before) {
1172
+ const b = before;
1173
+ const prev = neighbourOf(b, false);
1174
+ if (prev) {
1175
+ const gap = start(b) - end(prev);
1176
+ candidates.push({
1177
+ pos: end(b) + gap,
1178
+ guides: (p) => [segment(end(prev), start(b), crossMid(prev, b)), segment(end(b), p, crossMid(b, moving))]
1179
+ });
1180
+ }
1181
+ }
1182
+ if (after) {
1183
+ const a = after;
1184
+ const next = neighbourOf(a, true);
1185
+ if (next) {
1186
+ const gap = start(next) - end(a);
1187
+ candidates.push({
1188
+ pos: start(a) - gap - size,
1189
+ guides: (p) => [segment(p + size, start(a), crossMid(a, moving)), segment(end(a), start(next), crossMid(a, next))]
1190
+ });
1191
+ }
1192
+ }
1193
+ let best = null;
1194
+ for (const c of candidates) {
1195
+ const delta = c.pos - start(moving);
1196
+ if (Math.abs(delta) <= tolerance && (!best || Math.abs(delta) < Math.abs(best.delta))) {
1197
+ best = { delta, guides: c.guides(c.pos) };
1198
+ }
1199
+ }
1200
+ return best;
1201
+ }
1202
+ function computeSnapGuides(moving, targets, options = {}) {
1203
+ const index = Array.isArray(targets) ? createGuideIndex(targets) : targets;
1204
+ const zoom = options.zoom && options.zoom > 0 ? options.zoom : 1;
1205
+ const tolerance = (_nullishCoalesce(options.threshold, () => ( 6))) / zoom;
1206
+ const useEdges = options.edges !== false;
1207
+ const useCentres = options.centres !== false;
1208
+ const useSpacing = options.spacing !== false;
1209
+ const eps = 0.5 / zoom;
1210
+ const snapAxis = (horizontal) => {
1211
+ const start = horizontal ? moving.x : moving.y;
1212
+ const size = horizontal ? moving.width : moving.height;
1213
+ const edgeAxis = horizontal ? index.edgeX : index.edgeY;
1214
+ const centreAxis = horizontal ? index.centreX : index.centreY;
1215
+ let delta = null;
1216
+ const consider = (d) => {
1217
+ if (d !== null && (delta === null || Math.abs(d) < Math.abs(delta))) delta = d;
1218
+ };
1219
+ if (useEdges) {
1220
+ consider(nearest(edgeAxis, start, tolerance));
1221
+ consider(nearest(edgeAxis, start + size, tolerance));
1222
+ }
1223
+ if (useCentres) consider(nearest(centreAxis, start + size / 2, tolerance));
1224
+ const spacing = useSpacing ? spacingCandidate(index.rects, moving, horizontal, tolerance) : null;
1225
+ if (spacing && (delta === null || Math.abs(spacing.delta) < Math.abs(delta) - eps)) {
1226
+ return { delta: spacing.delta, spacing };
1227
+ }
1228
+ return { delta, spacing: null };
1229
+ };
1230
+ const sx = snapAxis(true);
1231
+ const sy = snapAxis(false);
1232
+ const dx = _nullishCoalesce(sx.delta, () => ( 0));
1233
+ const dy = _nullishCoalesce(sy.delta, () => ( 0));
1234
+ const snapped = { x: moving.x + dx, y: moving.y + dy, width: moving.width, height: moving.height };
1235
+ const guides = [];
1236
+ const alignmentGuides = (horizontal) => {
1237
+ const start = horizontal ? snapped.x : snapped.y;
1238
+ const size = horizontal ? snapped.width : snapped.height;
1239
+ const lines = [];
1240
+ if (useEdges) {
1241
+ const axis = horizontal ? index.edgeX : index.edgeY;
1242
+ lines.push({ value: start, kind: "edge", axis }, { value: start + size, kind: "edge", axis });
1243
+ }
1244
+ if (useCentres) {
1245
+ lines.push({ value: start + size / 2, kind: "centre", axis: horizontal ? index.centreX : index.centreY });
1246
+ }
1247
+ for (const line of lines) {
1248
+ const aligned = matches(line.axis, line.value, eps);
1249
+ if (aligned.length === 0) continue;
1250
+ const span = _chunkWADCJ7A7cjs.boundsOf.call(void 0, [snapped, ...aligned]);
1251
+ guides.push(
1252
+ horizontal ? { orientation: "vertical", kind: line.kind, x1: line.value, y1: span.y, x2: line.value, y2: span.y + span.height } : { orientation: "horizontal", kind: line.kind, x1: span.x, y1: line.value, x2: span.x + span.width, y2: line.value }
1253
+ );
1254
+ }
1255
+ };
1256
+ if (sx.delta !== null) {
1257
+ if (sx.spacing) guides.push(...shiftGuides(sx.spacing.guides, 0, dy));
1258
+ else alignmentGuides(true);
1259
+ }
1260
+ if (sy.delta !== null) {
1261
+ if (sy.spacing) guides.push(...shiftGuides(sy.spacing.guides, dx, 0));
1262
+ else alignmentGuides(false);
1263
+ }
1264
+ return {
1265
+ position: { x: snapped.x, y: snapped.y },
1266
+ offset: { x: dx, y: dy },
1267
+ guides,
1268
+ snappedX: sx.delta !== null,
1269
+ snappedY: sy.delta !== null
1270
+ };
1271
+ }
1272
+ function shiftGuides(guides, dx, dy) {
1273
+ return guides.map(
1274
+ (g) => g.orientation === "horizontal" ? { ...g, y1: g.y1 + dy, y2: g.y2 + dy } : { ...g, x1: g.x1 + dx, x2: g.x2 + dx }
1275
+ );
1276
+ }
1277
+ function collectDescendantIds(nodes, ids) {
1278
+ const result = new Set(ids);
1279
+ let grew = true;
1280
+ while (grew) {
1281
+ grew = false;
1282
+ for (const node of nodes) {
1283
+ if (node.parentId && result.has(node.parentId) && !result.has(node.id)) {
1284
+ result.add(node.id);
1285
+ grew = true;
1286
+ }
1287
+ }
1288
+ }
1289
+ return result;
1290
+ }
1291
+ function createNodeGuideIndex(nodes, draggingIds, options = {}) {
1292
+ const exclude = collectDescendantIds(nodes, draggingIds);
1293
+ const lookup = createNodeLookup(nodes);
1294
+ const rects = [];
1295
+ for (const node of nodes) {
1296
+ if (exclude.has(node.id) || node.hidden === true) continue;
1297
+ if (options.filter && !options.filter(node)) continue;
1298
+ rects.push(getNodeRect(node, lookup, options));
1299
+ }
1300
+ return createGuideIndex(rects);
1301
+ }
1302
+ function snapNodeDrag(nodes, draggingIds, options = {}) {
1303
+ const ids = new Set(draggingIds);
1304
+ const lookup = createNodeLookup(nodes);
1305
+ const dragged = [...ids].map((id) => lookup.get(id)).filter((n) => !!n);
1306
+ const empty = {
1307
+ position: { x: 0, y: 0 },
1308
+ offset: { x: 0, y: 0 },
1309
+ guides: [],
1310
+ snappedX: false,
1311
+ snappedY: false,
1312
+ updates: []
1313
+ };
1314
+ if (dragged.length === 0) return empty;
1315
+ const bounds = _chunkWADCJ7A7cjs.boundsOf.call(void 0, dragged.map((n) => getNodeRect(n, lookup, options)));
1316
+ const index = _nullishCoalesce(options.index, () => ( createNodeGuideIndex(nodes, ids, options)));
1317
+ const result = computeSnapGuides(bounds, index, options);
1318
+ const { x: dx, y: dy } = result.offset;
1319
+ const updates = [];
1320
+ if (dx !== 0 || dy !== 0) {
1321
+ for (const node of dragged) {
1322
+ if (node.parentId && ids.has(node.parentId)) continue;
1323
+ updates.push({ id: node.id, position: { x: node.position.x + dx, y: node.position.y + dy } });
1324
+ }
1325
+ }
1326
+ return { ...result, updates };
1327
+ }
1328
+
1329
+ // src/canvas/connectors.ts
1330
+ var CONNECTION_LINE_TYPES = [
1331
+ "default",
1332
+ "straight",
1333
+ "step",
1334
+ "smoothstep",
1335
+ "simplebezier"
1336
+ ];
1337
+ function positionToSide(position) {
1338
+ switch (position) {
1339
+ case "top":
1340
+ return "above";
1341
+ case "bottom":
1342
+ return "below";
1343
+ default:
1344
+ return position;
1345
+ }
1346
+ }
1347
+ function sideToPosition(side) {
1348
+ switch (side) {
1349
+ case "above":
1350
+ return "top";
1351
+ case "below":
1352
+ return "bottom";
1353
+ default:
1354
+ return side;
1355
+ }
1356
+ }
1357
+ function oppositePosition(position) {
1358
+ switch (position) {
1359
+ case "top":
1360
+ return "bottom";
1361
+ case "bottom":
1362
+ return "top";
1363
+ case "left":
1364
+ return "right";
1365
+ default:
1366
+ return "left";
1367
+ }
1368
+ }
1369
+ function handlePoint(rect, position) {
1370
+ switch (position) {
1371
+ case "top":
1372
+ return { x: rect.x + rect.width / 2, y: rect.y };
1373
+ case "bottom":
1374
+ return { x: rect.x + rect.width / 2, y: rect.y + rect.height };
1375
+ case "left":
1376
+ return { x: rect.x, y: rect.y + rect.height / 2 };
1377
+ default:
1378
+ return { x: rect.x + rect.width, y: rect.y + rect.height / 2 };
1379
+ }
1380
+ }
1381
+ function findConnectorSnap(pointer, targets, options = {}) {
1382
+ const zoom = options.zoom && options.zoom > 0 ? options.zoom : 1;
1383
+ const radius = (_nullishCoalesce(options.radius, () => ( 24))) / zoom;
1384
+ const exclude = new Set(_nullishCoalesce(options.excludeIds, () => ( [])));
1385
+ const all = ["top", "right", "bottom", "left"];
1386
+ let best = null;
1387
+ for (const target of targets) {
1388
+ if (exclude.has(target.id)) continue;
1389
+ const { rect } = target;
1390
+ if (pointer.x < rect.x - radius || pointer.x > rect.x + rect.width + radius || pointer.y < rect.y - radius || pointer.y > rect.y + rect.height + radius) {
1391
+ continue;
1392
+ }
1393
+ const inside = pointer.x >= rect.x && pointer.x <= rect.x + rect.width && pointer.y >= rect.y && pointer.y <= rect.y + rect.height;
1394
+ for (const position of _nullishCoalesce(target.positions, () => ( all))) {
1395
+ const point = options.mode === "edge" ? closestPointOnSide(rect, position, pointer) : handlePoint(rect, position);
1396
+ const sidePoint = closestPointOnSide(rect, position, pointer);
1397
+ const rank = Math.hypot(pointer.x - sidePoint.x, pointer.y - sidePoint.y);
1398
+ const distance = Math.hypot(pointer.x - point.x, pointer.y - point.y);
1399
+ if (!inside && rank > radius) continue;
1400
+ const better = !best || inside && !best.inside || inside === best.inside && rank < best.rank;
1401
+ if (better) {
1402
+ best = { nodeId: target.id, position, side: positionToSide(position), point, distance, inside, rank };
1403
+ }
1404
+ }
1405
+ }
1406
+ if (!best) return null;
1407
+ const { inside: _inside, rank: _rank, ...snap } = best;
1408
+ return snap;
1409
+ }
1410
+ function closestPointOnSide(rect, position, p) {
1411
+ const clampX = Math.min(rect.x + rect.width, Math.max(rect.x, p.x));
1412
+ const clampY = Math.min(rect.y + rect.height, Math.max(rect.y, p.y));
1413
+ switch (position) {
1414
+ case "top":
1415
+ return { x: clampX, y: rect.y };
1416
+ case "bottom":
1417
+ return { x: clampX, y: rect.y + rect.height };
1418
+ case "left":
1419
+ return { x: rect.x, y: clampY };
1420
+ default:
1421
+ return { x: rect.x + rect.width, y: clampY };
1422
+ }
1423
+ }
1424
+ function nearestHandlePositions(source, target) {
1425
+ const a = _chunkWADCJ7A7cjs.centre.call(void 0, source);
1426
+ const b = _chunkWADCJ7A7cjs.centre.call(void 0, target);
1427
+ const dx = b.x - a.x;
1428
+ const dy = b.y - a.y;
1429
+ if (Math.abs(dx) >= Math.abs(dy)) {
1430
+ return dx >= 0 ? { source: "right", target: "left" } : { source: "left", target: "right" };
1431
+ }
1432
+ return dy >= 0 ? { source: "bottom", target: "top" } : { source: "top", target: "bottom" };
1433
+ }
1434
+
1435
+ // src/canvas/scenes.ts
1436
+ var fallbackCounter = 0;
1437
+ function defaultId() {
1438
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
1439
+ return crypto.randomUUID();
1440
+ }
1441
+ fallbackCounter += 1;
1442
+ return `scene-${Date.now().toString(36)}-${fallbackCounter}`;
1443
+ }
1444
+ function isFiniteNumber(value) {
1445
+ return typeof value === "number" && Number.isFinite(value);
1446
+ }
1447
+ function isValidCanvasScene(value) {
1448
+ if (typeof value !== "object" || value === null) return false;
1449
+ const scene = value;
1450
+ const vp = scene.viewport;
1451
+ return typeof scene.id === "string" && typeof scene.name === "string" && typeof vp === "object" && vp !== null && isFiniteNumber(vp.x) && isFiniteNumber(vp.y) && isFiniteNumber(vp.zoom) && vp.zoom > 0 && (scene.nodeIds === void 0 || Array.isArray(scene.nodeIds) && scene.nodeIds.every((id) => typeof id === "string"));
1452
+ }
1453
+ function cloneScene(scene) {
1454
+ const copy = {
1455
+ id: scene.id,
1456
+ name: scene.name,
1457
+ viewport: { x: scene.viewport.x, y: scene.viewport.y, zoom: scene.viewport.zoom }
1458
+ };
1459
+ if (scene.nodeIds) copy.nodeIds = [...scene.nodeIds];
1460
+ return copy;
1461
+ }
1462
+ function parseCanvasScenes(input) {
1463
+ let value = input;
1464
+ if (typeof input === "string") {
1465
+ try {
1466
+ value = JSON.parse(input);
1467
+ } catch (e4) {
1468
+ return [];
1469
+ }
1470
+ }
1471
+ const list = Array.isArray(value) ? value : typeof value === "object" && value !== null && Array.isArray(value.scenes) ? value.scenes : [];
1472
+ const seen = /* @__PURE__ */ new Set();
1473
+ const scenes = [];
1474
+ for (const entry of list) {
1475
+ if (!isValidCanvasScene(entry) || seen.has(entry.id)) continue;
1476
+ seen.add(entry.id);
1477
+ scenes.push(cloneScene(entry));
1478
+ }
1479
+ return scenes;
1480
+ }
1481
+ var CanvasScenesStore = (_class3 = class {
1482
+
1483
+ __init10() {this.currentId = null}
1484
+
1485
+ __init11() {this.listeners = /* @__PURE__ */ new Set()}
1486
+
1487
+
1488
+
1489
+ constructor(options = {}) {;_class3.prototype.__init10.call(this);_class3.prototype.__init11.call(this);
1490
+ this.scenes = parseCanvasScenes(_nullishCoalesce(options.initialScenes, () => ( [])));
1491
+ this.createId = _nullishCoalesce(options.createId, () => ( defaultId));
1492
+ this.wrap = _nullishCoalesce(options.wrap, () => ( false));
1493
+ this.onChange = options.onChange;
1494
+ this.cached = this.snapshot();
1495
+ }
1496
+ snapshot() {
1497
+ const currentIndex = this.currentId ? this.scenes.findIndex((s) => s.id === this.currentId) : -1;
1498
+ return {
1499
+ scenes: this.scenes,
1500
+ currentId: currentIndex === -1 ? null : this.currentId,
1501
+ currentIndex
1502
+ };
1503
+ }
1504
+ commit(scenes = this.scenes) {
1505
+ this.scenes = scenes;
1506
+ if (this.currentId && !scenes.some((s) => s.id === this.currentId)) this.currentId = null;
1507
+ this.cached = this.snapshot();
1508
+ _optionalChain([this, 'access', _46 => _46.onChange, 'optionalCall', _47 => _47(this.cached)]);
1509
+ for (const listener of this.listeners) listener(this.cached);
1510
+ }
1511
+ getState() {
1512
+ return this.cached;
1513
+ }
1514
+ getScene(id) {
1515
+ return this.scenes.find((s) => s.id === id);
1516
+ }
1517
+ subscribe(listener) {
1518
+ this.listeners.add(listener);
1519
+ return () => {
1520
+ this.listeners.delete(listener);
1521
+ };
1522
+ }
1523
+ /** First unused "Scene N" name. */
1524
+ nextDefaultName() {
1525
+ const names = new Set(this.scenes.map((s) => s.name));
1526
+ let n = this.scenes.length + 1;
1527
+ while (names.has(`Scene ${n}`)) n += 1;
1528
+ return `Scene ${n}`;
1529
+ }
1530
+ /**
1531
+ * Adds a scene (appended, or inserted at `index`) and makes it current.
1532
+ */
1533
+ add(input, index) {
1534
+ const scene = cloneScene({
1535
+ id: input.id && !this.getScene(input.id) ? input.id : this.createId(),
1536
+ name: _optionalChain([input, 'access', _48 => _48.name, 'optionalAccess', _49 => _49.trim, 'call', _50 => _50()]) || this.nextDefaultName(),
1537
+ viewport: input.viewport,
1538
+ nodeIds: input.nodeIds
1539
+ });
1540
+ if (!isValidCanvasScene(scene)) throw new Error("[CanvasScenesStore] Invalid scene viewport.");
1541
+ const scenes = [...this.scenes];
1542
+ const at = index === void 0 ? scenes.length : Math.max(0, Math.min(scenes.length, index));
1543
+ scenes.splice(at, 0, scene);
1544
+ this.currentId = scene.id;
1545
+ this.commit(scenes);
1546
+ return scene;
1547
+ }
1548
+ /** Patches a scene's name, viewport or node ids. Returns the updated scene. */
1549
+ update(id, patch) {
1550
+ const index = this.scenes.findIndex((s) => s.id === id);
1551
+ if (index === -1) return void 0;
1552
+ const current = this.scenes[index];
1553
+ const next = cloneScene({
1554
+ ...current,
1555
+ ...patch,
1556
+ name: patch.name !== void 0 ? patch.name.trim() || current.name : current.name,
1557
+ viewport: _nullishCoalesce(patch.viewport, () => ( current.viewport)),
1558
+ id
1559
+ });
1560
+ if (!isValidCanvasScene(next)) throw new Error("[CanvasScenesStore] Invalid scene viewport.");
1561
+ const scenes = [...this.scenes];
1562
+ scenes[index] = next;
1563
+ this.commit(scenes);
1564
+ return next;
1565
+ }
1566
+ rename(id, name) {
1567
+ return this.update(id, { name });
1568
+ }
1569
+ /** Moves a scene to `toIndex` (clamped). */
1570
+ move(id, toIndex) {
1571
+ const from = this.scenes.findIndex((s) => s.id === id);
1572
+ if (from === -1) return;
1573
+ const to = Math.max(0, Math.min(this.scenes.length - 1, Math.trunc(toIndex)));
1574
+ if (from === to) return;
1575
+ const scenes = [...this.scenes];
1576
+ const [scene] = scenes.splice(from, 1);
1577
+ scenes.splice(to, 0, scene);
1578
+ this.commit(scenes);
1579
+ }
1580
+ /** Reorders scenes to match `ids`; unknown ids are ignored and missing scenes keep their relative order at the end. */
1581
+ reorder(ids) {
1582
+ const byId = new Map(this.scenes.map((s) => [s.id, s]));
1583
+ const ordered = [];
1584
+ for (const id of ids) {
1585
+ const scene = byId.get(id);
1586
+ if (scene) {
1587
+ ordered.push(scene);
1588
+ byId.delete(id);
1589
+ }
1590
+ }
1591
+ this.commit([...ordered, ...this.scenes.filter((s) => byId.has(s.id))]);
1592
+ }
1593
+ remove(id) {
1594
+ if (!this.getScene(id)) return;
1595
+ this.commit(this.scenes.filter((s) => s.id !== id));
1596
+ }
1597
+ clear() {
1598
+ this.currentId = null;
1599
+ this.commit([]);
1600
+ }
1601
+ /** Marks a scene as current and returns it. */
1602
+ goTo(id) {
1603
+ const scene = this.getScene(id);
1604
+ if (!scene) return void 0;
1605
+ if (this.currentId !== id) {
1606
+ this.currentId = id;
1607
+ this.commit();
1608
+ }
1609
+ return scene;
1610
+ }
1611
+ step(direction) {
1612
+ const count = this.scenes.length;
1613
+ if (count === 0) return void 0;
1614
+ const index = this.cached.currentIndex;
1615
+ let next;
1616
+ if (index === -1) next = direction === 1 ? 0 : count - 1;
1617
+ else next = index + direction;
1618
+ if (next < 0 || next >= count) {
1619
+ if (!this.wrap) return void 0;
1620
+ next = (next + count) % count;
1621
+ }
1622
+ return this.goTo(this.scenes[next].id);
1623
+ }
1624
+ /** Shows the next scene. Returns `undefined` at the end unless `wrap` is on. */
1625
+ next() {
1626
+ return this.step(1);
1627
+ }
1628
+ /** Shows the previous scene. Returns `undefined` at the start unless `wrap` is on. */
1629
+ previous() {
1630
+ return this.step(-1);
1631
+ }
1632
+ toJSON() {
1633
+ return { version: 1, scenes: this.scenes.map(cloneScene) };
1634
+ }
1635
+ serialize() {
1636
+ return JSON.stringify(this.toJSON());
1637
+ }
1638
+ /** Replaces all scenes from serialized data (see `parseCanvasScenes`). */
1639
+ load(input) {
1640
+ this.currentId = null;
1641
+ this.commit(parseCanvasScenes(input));
1642
+ }
1643
+ }, _class3);
1644
+ function createCanvasScenesStore(options) {
1645
+ return new CanvasScenesStore(options);
1646
+ }
1647
+ function fitViewportToRect(rect, size, options = {}) {
1648
+ const { padding = 0.1, minZoom = 0.1, maxZoom = 2 } = options;
1649
+ const paddedWidth = Math.max(rect.width * (1 + padding * 2), 1);
1650
+ const paddedHeight = Math.max(rect.height * (1 + padding * 2), 1);
1651
+ const raw = Math.min(size.width / paddedWidth, size.height / paddedHeight);
1652
+ const zoom = Math.min(maxZoom, Math.max(minZoom, raw));
1653
+ const cx = rect.x + rect.width / 2;
1654
+ const cy = rect.y + rect.height / 2;
1655
+ return { x: size.width / 2 - cx * zoom, y: size.height / 2 - cy * zoom, zoom };
1656
+ }
1657
+ function fitViewportToNodes(nodes, size, ids, options = {}) {
1658
+ const lookup = createNodeLookup(nodes);
1659
+ const wanted = ids ? new Set(ids) : null;
1660
+ const rects = nodes.filter((n) => wanted ? wanted.has(n.id) : true).map((n) => getNodeRect(n, lookup, options));
1661
+ const bounds = _chunkWADCJ7A7cjs.boundsOf.call(void 0, rects);
1662
+ return bounds ? fitViewportToRect(bounds, size, options) : null;
1663
+ }
1664
+
1665
+ // src/canvas/arrangeShortcuts.ts
1666
+ var DEFAULT_ARRANGE_SHORTCUTS = [
1667
+ { action: "alignLeft", code: "KeyA", alt: true, label: "Alt+A" },
1668
+ { action: "alignCenter", code: "KeyH", alt: true, label: "Alt+H" },
1669
+ { action: "alignRight", code: "KeyD", alt: true, label: "Alt+D" },
1670
+ { action: "alignTop", code: "KeyW", alt: true, label: "Alt+W" },
1671
+ { action: "alignMiddle", code: "KeyV", alt: true, label: "Alt+V" },
1672
+ { action: "alignBottom", code: "KeyS", alt: true, label: "Alt+S" },
1673
+ { action: "distributeHorizontal", code: "KeyH", alt: true, shift: true, label: "Alt+Shift+H" },
1674
+ { action: "distributeVertical", code: "KeyV", alt: true, shift: true, label: "Alt+Shift+V" },
1675
+ { action: "lock", code: "KeyL", mod: true, label: "Mod+L" },
1676
+ { action: "unlock", code: "KeyL", mod: true, alt: true, label: "Mod+Alt+L" },
1677
+ { action: "bringForward", code: "BracketRight", mod: true, label: "Mod+]" },
1678
+ { action: "sendBackward", code: "BracketLeft", mod: true, label: "Mod+[" },
1679
+ { action: "bringToFront", code: "BracketRight", mod: true, alt: true, label: "Mod+Alt+]" },
1680
+ { action: "sendToBack", code: "BracketLeft", mod: true, alt: true, label: "Mod+Alt+[" },
1681
+ { action: "nextScene", code: "PageDown", label: "PageDown" },
1682
+ { action: "previousScene", code: "PageUp", label: "PageUp" }
1683
+ ];
1684
+ var KEY_TO_CODE = {
1685
+ "]": "BracketRight",
1686
+ "[": "BracketLeft",
1687
+ PageDown: "PageDown",
1688
+ PageUp: "PageUp"
1689
+ };
1690
+ function eventCode(event) {
1691
+ if (event.code) return event.code;
1692
+ if (KEY_TO_CODE[event.key]) return KEY_TO_CODE[event.key];
1693
+ if (/^[a-z]$/i.test(event.key)) return `Key${event.key.toUpperCase()}`;
1694
+ return event.key;
1695
+ }
1696
+ function matchArrangeShortcut(event, bindings = DEFAULT_ARRANGE_SHORTCUTS) {
1697
+ if (isEventFromTextInput(event)) return null;
1698
+ const code = eventCode(event);
1699
+ const mod = event.metaKey || event.ctrlKey;
1700
+ for (const binding of bindings) {
1701
+ if (binding.code === code && !!binding.mod === mod && !!binding.alt === event.altKey && !!binding.shift === event.shiftKey) {
1702
+ return binding.action;
1703
+ }
1704
+ }
1705
+ return null;
1706
+ }
1707
+
1708
+ // src/canvas/arrangeController.ts
1709
+ function createCanvasArrangeController(options) {
1710
+ let guides = [];
1711
+ let dragIndex = null;
1712
+ let dragKey = "";
1713
+ const selectedIds = (ids) => ids ? [...ids] : _nullishCoalesce(_optionalChain([options, 'access', _51 => _51.getSelectedIds, 'optionalCall', _52 => _52()]), () => ( options.getNodes().filter((n) => n.selected).map((n) => n.id)));
1714
+ const setGuides = (next) => {
1715
+ if (next.length === 0 && guides.length === 0) return;
1716
+ guides = next;
1717
+ _optionalChain([options, 'access', _53 => _53.onGuidesChange, 'optionalCall', _54 => _54(guides)]);
1718
+ };
1719
+ function apply(name, updates) {
1720
+ if (updates.length === 0) return updates;
1721
+ const inverse = invertNodeUpdates(options.getNodes(), updates);
1722
+ const run = (u) => options.setNodes(applyNodeUpdates(options.getNodes(), u));
1723
+ if (options.history) {
1724
+ options.history.execute({ name, execute: () => run(updates), undo: () => run(inverse) });
1725
+ } else {
1726
+ run(updates);
1727
+ }
1728
+ return updates;
1729
+ }
1730
+ function setLocked(name, ids, locked) {
1731
+ const nodes = options.getNodes();
1732
+ const set = new Set(ids);
1733
+ const changed = nodes.filter((n) => set.has(n.id) && isLocked(n) !== locked).map((n) => n.id);
1734
+ if (changed.length === 0) return changed;
1735
+ const lock = () => options.setNodes(lockNodes(options.getNodes(), changed));
1736
+ const unlock = () => options.setNodes(unlockNodes(options.getNodes(), changed));
1737
+ if (options.history) {
1738
+ options.history.execute({ name, execute: locked ? lock : unlock, undo: locked ? unlock : lock });
1739
+ } else if (locked) lock();
1740
+ else unlock();
1741
+ return changed;
1742
+ }
1743
+ const rect = () => _nullishCoalesce(options.rectOptions, () => ( {}));
1744
+ const controller = {
1745
+ get guides() {
1746
+ return guides;
1747
+ },
1748
+ apply,
1749
+ align(edge, ids, alignOptions = {}) {
1750
+ return apply(`Align ${edge}`, alignNodes(options.getNodes(), selectedIds(ids), edge, { ...rect(), ...alignOptions }));
1751
+ },
1752
+ distribute(axis, mode = "gaps", ids, distributeOptions = {}) {
1753
+ return apply(
1754
+ `Distribute ${axis}`,
1755
+ distributeNodes(options.getNodes(), selectedIds(ids), axis, mode, { ...rect(), ...distributeOptions })
1756
+ );
1757
+ },
1758
+ matchSize(dimension, ids, sizeOptions = {}) {
1759
+ return apply(
1760
+ "Make Same Size",
1761
+ matchSize(options.getNodes(), selectedIds(ids), dimension, { ...rect(), ...sizeOptions })
1762
+ );
1763
+ },
1764
+ reorder(operation, ids) {
1765
+ return apply(operation, reorderNodes(options.getNodes(), selectedIds(ids), operation, rect()));
1766
+ },
1767
+ bringForward: (ids) => controller.reorder("bringForward", ids),
1768
+ sendBackward: (ids) => controller.reorder("sendBackward", ids),
1769
+ bringToFront: (ids) => controller.reorder("bringToFront", ids),
1770
+ sendToBack: (ids) => controller.reorder("sendToBack", ids),
1771
+ lock: (ids) => setLocked("Lock", selectedIds(ids), true),
1772
+ unlock: (ids) => setLocked("Unlock", selectedIds(ids), false),
1773
+ toggleLock(ids) {
1774
+ const list = selectedIds(ids);
1775
+ const set = new Set(list);
1776
+ const anyUnlocked = options.getNodes().some((n) => set.has(n.id) && !isLocked(n));
1777
+ return anyUnlocked ? controller.lock(list) : controller.unlock(list);
1778
+ },
1779
+ isLocked: (id) => isLocked(options.getNodes().find((n) => n.id === id)),
1780
+ /**
1781
+ * Runs a shortcut action. Scene actions are not handled here (see the scenes store);
1782
+ * returns `false` for them and for unknown actions.
1783
+ */
1784
+ runAction(action) {
1785
+ switch (action) {
1786
+ case "alignLeft":
1787
+ controller.align("left");
1788
+ return true;
1789
+ case "alignCenter":
1790
+ controller.align("center");
1791
+ return true;
1792
+ case "alignRight":
1793
+ controller.align("right");
1794
+ return true;
1795
+ case "alignTop":
1796
+ controller.align("top");
1797
+ return true;
1798
+ case "alignMiddle":
1799
+ controller.align("middle");
1800
+ return true;
1801
+ case "alignBottom":
1802
+ controller.align("bottom");
1803
+ return true;
1804
+ case "distributeHorizontal":
1805
+ controller.distribute("horizontal");
1806
+ return true;
1807
+ case "distributeVertical":
1808
+ controller.distribute("vertical");
1809
+ return true;
1810
+ case "lock":
1811
+ controller.lock();
1812
+ return true;
1813
+ case "unlock":
1814
+ controller.unlock();
1815
+ return true;
1816
+ case "bringForward":
1817
+ controller.bringForward();
1818
+ return true;
1819
+ case "sendBackward":
1820
+ controller.sendBackward();
1821
+ return true;
1822
+ case "bringToFront":
1823
+ controller.bringToFront();
1824
+ return true;
1825
+ case "sendToBack":
1826
+ controller.sendToBack();
1827
+ return true;
1828
+ default:
1829
+ return false;
1830
+ }
1831
+ },
1832
+ /** Caches the snap targets for a drag. Optional: `drag` builds them lazily. */
1833
+ beginDrag(ids) {
1834
+ const list = selectedIds(ids);
1835
+ dragKey = list.slice().sort().join("\0");
1836
+ dragIndex = createNodeGuideIndex(options.getNodes(), list, rect());
1837
+ },
1838
+ /**
1839
+ * Snaps the dragged nodes (as currently positioned in `getNodes()`) to the other
1840
+ * nodes, writes the snapped positions back through `setNodes` (not recorded in
1841
+ * history) and updates `guides`.
1842
+ */
1843
+ drag(ids) {
1844
+ if (options.snapping === false) return null;
1845
+ const list = selectedIds(ids);
1846
+ const key = list.slice().sort().join("\0");
1847
+ if (!dragIndex || key !== dragKey) controller.beginDrag(list);
1848
+ const result = snapNodeDrag(options.getNodes(), list, {
1849
+ ...rect(),
1850
+ ...options.guides,
1851
+ zoom: _nullishCoalesce(_optionalChain([options, 'access', _55 => _55.getZoom, 'optionalCall', _56 => _56()]), () => ( 1)),
1852
+ index: dragIndex
1853
+ });
1854
+ if (result.updates.length > 0) {
1855
+ options.setNodes(applyNodeUpdates(options.getNodes(), result.updates));
1856
+ }
1857
+ setGuides(result.guides);
1858
+ return result;
1859
+ },
1860
+ /**
1861
+ * React Flow style: adjusts dragging `position` changes in an `onNodesChange` batch so
1862
+ * the dragged nodes snap, and updates `guides`. Returns the (possibly new) changes array.
1863
+ * A batch without a dragging position change ends the drag and clears the guides.
1864
+ */
1865
+ snapPositionChanges(changes) {
1866
+ const dragging = changes.filter((c) => c.type === "position" && c.position && c.dragging);
1867
+ if (dragging.length === 0) {
1868
+ if (changes.some((c) => c.type === "position" && c.dragging === false)) controller.endDrag();
1869
+ return changes;
1870
+ }
1871
+ if (options.snapping === false) return changes;
1872
+ const ids = dragging.map((c) => c.id);
1873
+ const key = ids.slice().sort().join("\0");
1874
+ if (!dragIndex || key !== dragKey) controller.beginDrag(ids);
1875
+ const proposed = new Map(dragging.map((c) => [c.id, c.position]));
1876
+ const nodes = options.getNodes().map((n) => proposed.has(n.id) ? { ...n, position: proposed.get(n.id) } : n);
1877
+ const result = snapNodeDrag(nodes, ids, {
1878
+ ...rect(),
1879
+ ...options.guides,
1880
+ zoom: _nullishCoalesce(_optionalChain([options, 'access', _57 => _57.getZoom, 'optionalCall', _58 => _58()]), () => ( 1)),
1881
+ index: dragIndex
1882
+ });
1883
+ setGuides(result.guides);
1884
+ const { x: dx, y: dy } = result.offset;
1885
+ if (dx === 0 && dy === 0) return changes;
1886
+ const parents = new Map(nodes.map((n) => [n.id, n.parentId]));
1887
+ const shift = new Set(ids.filter((id) => !proposed.has(_nullishCoalesce(parents.get(id), () => ( "")))));
1888
+ return changes.map(
1889
+ (c) => c.type === "position" && c.position && c.dragging && shift.has(c.id) ? { ...c, position: { x: c.position.x + dx, y: c.position.y + dy } } : c
1890
+ );
1891
+ },
1892
+ /** Clears guides and the cached snap targets. */
1893
+ endDrag() {
1894
+ dragIndex = null;
1895
+ dragKey = "";
1896
+ setGuides([]);
1897
+ }
1898
+ };
1899
+ return controller;
1900
+ }
1901
+
1902
+
1903
+
1904
+
1905
+
1906
+
1907
+
1908
+
1909
+
1910
+
1911
+
1912
+
1913
+
1914
+
1915
+
1916
+
1917
+
1918
+
1919
+
1920
+
1921
+
1922
+
1923
+
1924
+
1925
+
1926
+
1927
+
1928
+
1929
+
1930
+
1931
+
1932
+
1933
+
1934
+
1935
+
1936
+
1937
+
1938
+
1939
+
1940
+
723
1941
 
724
1942
 
725
1943
 
@@ -760,5 +1978,5 @@ var StreamingLayoutManager = (_class2 = class {
760
1978
 
761
1979
 
762
1980
 
763
- exports.DEFAULT_NODE_HEIGHT = _chunkWADCJ7A7cjs.DEFAULT_NODE_HEIGHT; exports.DEFAULT_NODE_WIDTH = _chunkWADCJ7A7cjs.DEFAULT_NODE_WIDTH; exports.DEFAULT_PLACEMENT_GAP = _chunkWADCJ7A7cjs.DEFAULT_PLACEMENT_GAP; exports.ManualClock = ManualClock; exports.StreamingLayoutManager = StreamingLayoutManager; exports.blendLayout = blendLayout; exports.boundsOf = _chunkWADCJ7A7cjs.boundsOf; exports.calculateDagreReflowDisplacement = calculateDagreReflowDisplacement; exports.calculateDirectionalDisplacement = calculateDirectionalDisplacement; exports.canvasHeight = canvasHeight; exports.centerNodes = _chunkWADCJ7A7cjs.centerNodes; exports.centre = _chunkWADCJ7A7cjs.centre; exports.computeNodesBoundingBox = computeNodesBoundingBox; exports.connectedOnly = connectedOnly; exports.createBezierTrajectory = createBezierTrajectory; exports.createFanOutTrajectory = createFanOutTrajectory; exports.defaultEasing = defaultEasing; exports.ensureLayout = _chunkWADCJ7A7cjs.ensureLayout; exports.estimateCanvasHeight = estimateCanvasHeight; exports.estimateNodeSize = _chunkWADCJ7A7cjs.estimateNodeSize; exports.flowSide = _chunkWADCJ7A7cjs.flowSide; exports.getCenteredNodePosition = _chunkWADCJ7A7cjs.getCenteredNodePosition; exports.getLayoutedNodes = _chunkWADCJ7A7cjs.getLayoutedNodes; exports.isEventFromTextInput = isEventFromTextInput; exports.isValidCanvasEdge = isValidCanvasEdge; exports.isValidCanvasNode = isValidCanvasNode; exports.isValidUrl = isValidUrl; exports.layoutBounds = layoutBounds; exports.linearPositionTrajectory = linearPositionTrajectory; exports.linearTrajectory = linearTrajectory; exports.overlaps = _chunkWADCJ7A7cjs.overlaps; exports.pageHidden = pageHidden; exports.parseCanvasClipboardData = parseCanvasClipboardData; exports.placeBeside = _chunkWADCJ7A7cjs.placeBeside; exports.realClock = realClock; exports.remapPastedNodes = remapPastedNodes; exports.repositionNodesTo = repositionNodesTo; exports.runMultiNodeTransition = runMultiNodeTransition; exports.serializeCanvasNodes = serializeCanvasNodes; exports.withStyleOpacity = withStyleOpacity;
1981
+ exports.CONNECTION_LINE_TYPES = CONNECTION_LINE_TYPES; exports.CanvasScenesStore = CanvasScenesStore; exports.DEFAULT_ARRANGE_SHORTCUTS = DEFAULT_ARRANGE_SHORTCUTS; exports.DEFAULT_NODE_HEIGHT = _chunkWADCJ7A7cjs.DEFAULT_NODE_HEIGHT; exports.DEFAULT_NODE_WIDTH = _chunkWADCJ7A7cjs.DEFAULT_NODE_WIDTH; exports.DEFAULT_PLACEMENT_GAP = _chunkWADCJ7A7cjs.DEFAULT_PLACEMENT_GAP; exports.LOCKED_DATA_KEY = LOCKED_DATA_KEY; exports.LOCKED_PREVIOUS_FLAGS_KEY = LOCKED_PREVIOUS_FLAGS_KEY; exports.ManualClock = ManualClock; exports.StreamingLayoutManager = StreamingLayoutManager; exports.alignNodes = alignNodes; exports.applyNodeUpdates = applyNodeUpdates; exports.blendLayout = blendLayout; exports.boundsOf = _chunkWADCJ7A7cjs.boundsOf; exports.calculateDagreReflowDisplacement = calculateDagreReflowDisplacement; exports.calculateDirectionalDisplacement = calculateDirectionalDisplacement; exports.canvasHeight = canvasHeight; exports.centerNodes = _chunkWADCJ7A7cjs.centerNodes; exports.centre = _chunkWADCJ7A7cjs.centre; exports.collectDescendantIds = collectDescendantIds; exports.computeNodesBoundingBox = computeNodesBoundingBox; exports.computeSnapGuides = computeSnapGuides; exports.connectedOnly = connectedOnly; exports.createBezierTrajectory = createBezierTrajectory; exports.createCanvasArrangeController = createCanvasArrangeController; exports.createCanvasScenesStore = createCanvasScenesStore; exports.createFanOutTrajectory = createFanOutTrajectory; exports.createGuideIndex = createGuideIndex; exports.createNodeGuideIndex = createNodeGuideIndex; exports.createNodeLookup = createNodeLookup; exports.defaultEasing = defaultEasing; exports.distributeNodes = distributeNodes; exports.ensureLayout = _chunkWADCJ7A7cjs.ensureLayout; exports.estimateCanvasHeight = estimateCanvasHeight; exports.estimateNodeSize = _chunkWADCJ7A7cjs.estimateNodeSize; exports.findConnectorSnap = findConnectorSnap; exports.fitViewportToNodes = fitViewportToNodes; exports.fitViewportToRect = fitViewportToRect; exports.flowSide = _chunkWADCJ7A7cjs.flowSide; exports.getAbsolutePosition = getAbsolutePosition; exports.getCenteredNodePosition = _chunkWADCJ7A7cjs.getCenteredNodePosition; exports.getLayoutedNodes = _chunkWADCJ7A7cjs.getLayoutedNodes; exports.getNodeRect = getNodeRect; exports.getNodeSize = getNodeSize; exports.handlePoint = handlePoint; exports.invertNodeUpdates = invertNodeUpdates; exports.isEventFromTextInput = isEventFromTextInput; exports.isLocked = isLocked; exports.isValidCanvasEdge = isValidCanvasEdge; exports.isValidCanvasNode = isValidCanvasNode; exports.isValidCanvasScene = isValidCanvasScene; exports.isValidUrl = isValidUrl; exports.layoutBounds = layoutBounds; exports.linearPositionTrajectory = linearPositionTrajectory; exports.linearTrajectory = linearTrajectory; exports.lockNodes = lockNodes; exports.matchArrangeShortcut = matchArrangeShortcut; exports.matchSize = matchSize; exports.nearestHandlePositions = nearestHandlePositions; exports.oppositePosition = oppositePosition; exports.overlaps = _chunkWADCJ7A7cjs.overlaps; exports.pageHidden = pageHidden; exports.parseCanvasClipboardData = parseCanvasClipboardData; exports.parseCanvasScenes = parseCanvasScenes; exports.placeBeside = _chunkWADCJ7A7cjs.placeBeside; exports.positionToSide = positionToSide; exports.readStyleSize = readStyleSize; exports.realClock = realClock; exports.remapPastedNodes = remapPastedNodes; exports.reorderNodes = reorderNodes; exports.repositionNodesTo = repositionNodesTo; exports.runMultiNodeTransition = runMultiNodeTransition; exports.serializeCanvasNodes = serializeCanvasNodes; exports.sideToPosition = sideToPosition; exports.snapNodeDrag = snapNodeDrag; exports.toggleLockNodes = toggleLockNodes; exports.unlockNodes = unlockNodes; exports.withStyleOpacity = withStyleOpacity; exports.withStyleSize = withStyleSize;
764
1982
  //# sourceMappingURL=index.cjs.map