@pixerate/editor 0.22.0 → 0.23.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 (83) hide show
  1. package/README.md +80 -2
  2. package/THIRD_PARTY_NOTICES.md +88 -0
  3. package/dist/agent/index.cjs +83 -108
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +69 -211
  6. package/dist/agent/index.d.ts +69 -211
  7. package/dist/agent/index.js +76 -101
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/arrangeShortcuts-B8O3f8-P.d.cts +184 -0
  10. package/dist/arrangeShortcuts-sLlD2rSX.d.ts +184 -0
  11. package/dist/canvas/index.cjs +879 -83
  12. package/dist/canvas/index.cjs.map +1 -1
  13. package/dist/canvas/index.d.cts +291 -186
  14. package/dist/canvas/index.d.ts +291 -186
  15. package/dist/canvas/index.js +865 -69
  16. package/dist/canvas/index.js.map +1 -1
  17. package/dist/chunk-26BVFKHU.cjs +453 -0
  18. package/dist/chunk-26BVFKHU.cjs.map +1 -0
  19. package/dist/chunk-2H7ZHPEJ.js +762 -0
  20. package/dist/chunk-2H7ZHPEJ.js.map +1 -0
  21. package/dist/chunk-7DWMJCAT.js +453 -0
  22. package/dist/chunk-7DWMJCAT.js.map +1 -0
  23. package/dist/chunk-ARRTP33I.js +101 -0
  24. package/dist/chunk-ARRTP33I.js.map +1 -0
  25. package/dist/chunk-CPOKFNBG.cjs +101 -0
  26. package/dist/chunk-CPOKFNBG.cjs.map +1 -0
  27. package/dist/chunk-G2I4QJOT.cjs +762 -0
  28. package/dist/chunk-G2I4QJOT.cjs.map +1 -0
  29. package/dist/{chunk-RU52I7QO.js → chunk-K3R5NG2D.js} +147 -42
  30. package/dist/chunk-K3R5NG2D.js.map +1 -0
  31. package/dist/{chunk-DENSCKFC.js → chunk-QBJ22YZR.js} +423 -30
  32. package/dist/chunk-QBJ22YZR.js.map +1 -0
  33. package/dist/{chunk-SAZRENEZ.cjs → chunk-RIKBJLS2.cjs} +424 -31
  34. package/dist/chunk-RIKBJLS2.cjs.map +1 -0
  35. package/dist/{chunk-6M3BCTBD.cjs → chunk-XDMXXC4Z.cjs} +230 -125
  36. package/dist/chunk-XDMXXC4Z.cjs.map +1 -0
  37. package/dist/commands/index.cjs +860 -0
  38. package/dist/commands/index.cjs.map +1 -0
  39. package/dist/commands/index.d.cts +592 -0
  40. package/dist/commands/index.d.ts +592 -0
  41. package/dist/commands/index.js +860 -0
  42. package/dist/commands/index.js.map +1 -0
  43. package/dist/{controller-B7GIybc4.d.cts → controller-pePCJLT1.d.cts} +78 -5
  44. package/dist/{controller-B7GIybc4.d.ts → controller-pePCJLT1.d.ts} +78 -5
  45. package/dist/history/index.cjs +12 -2
  46. package/dist/history/index.cjs.map +1 -1
  47. package/dist/history/index.d.cts +211 -7
  48. package/dist/history/index.d.ts +211 -7
  49. package/dist/history/index.js +13 -3
  50. package/dist/image-editor/index.cjs +418 -13
  51. package/dist/image-editor/index.cjs.map +1 -1
  52. package/dist/image-editor/index.d.cts +154 -3
  53. package/dist/image-editor/index.d.ts +154 -3
  54. package/dist/image-editor/index.js +417 -12
  55. package/dist/image-editor/index.js.map +1 -1
  56. package/dist/index.cjs +34 -76
  57. package/dist/index.cjs.map +1 -1
  58. package/dist/index.d.cts +5 -42
  59. package/dist/index.d.ts +5 -42
  60. package/dist/index.js +27 -69
  61. package/dist/index.js.map +1 -1
  62. package/dist/registry-D5-R90p0.d.cts +209 -0
  63. package/dist/registry-D5-R90p0.d.ts +209 -0
  64. package/dist/spreadsheet/index.cjs +19 -3
  65. package/dist/spreadsheet/index.cjs.map +1 -1
  66. package/dist/spreadsheet/index.d.cts +67 -9
  67. package/dist/spreadsheet/index.d.ts +67 -9
  68. package/dist/spreadsheet/index.js +18 -2
  69. package/dist/{types-CJ4U-HHI.d.cts → types-DX4Mh4SL.d.cts} +1 -1
  70. package/dist/{types-CJ4U-HHI.d.ts → types-DX4Mh4SL.d.ts} +1 -1
  71. package/dist/types-GT5a5YAX.d.cts +86 -0
  72. package/dist/types-GT5a5YAX.d.ts +86 -0
  73. package/package.json +8 -2
  74. package/dist/chunk-2TWGLC5K.cjs +0 -262
  75. package/dist/chunk-2TWGLC5K.cjs.map +0 -1
  76. package/dist/chunk-6M3BCTBD.cjs.map +0 -1
  77. package/dist/chunk-DENSCKFC.js.map +0 -1
  78. package/dist/chunk-KAADNAPF.js +0 -262
  79. package/dist/chunk-KAADNAPF.js.map +0 -1
  80. package/dist/chunk-RU52I7QO.js.map +0 -1
  81. package/dist/chunk-SAZRENEZ.cjs.map +0 -1
  82. package/dist/types-BZgcDsC5.d.cts +0 -42
  83. package/dist/types-BZgcDsC5.d.ts +0 -42
@@ -1,6 +1,10 @@
1
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; var _class4; var _class5;
2
2
 
3
3
 
4
+ var _chunk26BVFKHUcjs = require('../chunk-26BVFKHU.cjs');
5
+
6
+
7
+
4
8
 
5
9
 
6
10
 
@@ -1073,6 +1077,10 @@ function invertNodeUpdates(nodes, updates) {
1073
1077
  }
1074
1078
 
1075
1079
  // src/canvas/guides.ts
1080
+ function snapToGrid(value, spacing, origin = 0) {
1081
+ if (!(spacing > 0) || !Number.isFinite(spacing)) return value;
1082
+ return Math.round((value - origin) / spacing) * spacing + origin;
1083
+ }
1076
1084
  function buildAxis(entries) {
1077
1085
  entries.sort((a, b) => a.value - b.value);
1078
1086
  return {
@@ -1229,8 +1237,10 @@ function computeSnapGuides(moving, targets, options = {}) {
1229
1237
  };
1230
1238
  const sx = snapAxis(true);
1231
1239
  const sy = snapAxis(false);
1232
- const dx = _nullishCoalesce(sx.delta, () => ( 0));
1233
- const dy = _nullishCoalesce(sy.delta, () => ( 0));
1240
+ const grid = _nullishCoalesce(options.gridSize, () => ( 0));
1241
+ const gridDelta = (v, origin) => snapToGrid(v, grid, origin) - v;
1242
+ const dx = _nullishCoalesce(sx.delta, () => ( (grid > 0 ? gridDelta(moving.x, _nullishCoalesce(_optionalChain([options, 'access', _46 => _46.gridOrigin, 'optionalAccess', _47 => _47.x]), () => ( 0))) : 0)));
1243
+ const dy = _nullishCoalesce(sy.delta, () => ( (grid > 0 ? gridDelta(moving.y, _nullishCoalesce(_optionalChain([options, 'access', _48 => _48.gridOrigin, 'optionalAccess', _49 => _49.y]), () => ( 0))) : 0)));
1234
1244
  const snapped = { x: moving.x + dx, y: moving.y + dy, width: moving.width, height: moving.height };
1235
1245
  const guides = [];
1236
1246
  const alignmentGuides = (horizontal) => {
@@ -1244,12 +1254,12 @@ function computeSnapGuides(moving, targets, options = {}) {
1244
1254
  if (useCentres) {
1245
1255
  lines.push({ value: start + size / 2, kind: "centre", axis: horizontal ? index.centreX : index.centreY });
1246
1256
  }
1247
- for (const line of lines) {
1248
- const aligned = matches(line.axis, line.value, eps);
1257
+ for (const line2 of lines) {
1258
+ const aligned = matches(line2.axis, line2.value, eps);
1249
1259
  if (aligned.length === 0) continue;
1250
1260
  const span = _chunkWADCJ7A7cjs.boundsOf.call(void 0, [snapped, ...aligned]);
1251
1261
  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 }
1262
+ horizontal ? { orientation: "vertical", kind: line2.kind, x1: line2.value, y1: span.y, x2: line2.value, y2: span.y + span.height } : { orientation: "horizontal", kind: line2.kind, x1: span.x, y1: line2.value, x2: span.x + span.width, y2: line2.value }
1253
1263
  );
1254
1264
  }
1255
1265
  };
@@ -1390,16 +1400,16 @@ function findConnectorSnap(pointer, targets, options = {}) {
1390
1400
  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
1401
  continue;
1392
1402
  }
1393
- const inside = pointer.x >= rect.x && pointer.x <= rect.x + rect.width && pointer.y >= rect.y && pointer.y <= rect.y + rect.height;
1403
+ const inside2 = pointer.x >= rect.x && pointer.x <= rect.x + rect.width && pointer.y >= rect.y && pointer.y <= rect.y + rect.height;
1394
1404
  for (const position of _nullishCoalesce(target.positions, () => ( all))) {
1395
1405
  const point = options.mode === "edge" ? closestPointOnSide(rect, position, pointer) : handlePoint(rect, position);
1396
1406
  const sidePoint = closestPointOnSide(rect, position, pointer);
1397
1407
  const rank = Math.hypot(pointer.x - sidePoint.x, pointer.y - sidePoint.y);
1398
1408
  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;
1409
+ if (!inside2 && rank > radius) continue;
1410
+ const better = !best || inside2 && !best.inside || inside2 === best.inside && rank < best.rank;
1401
1411
  if (better) {
1402
- best = { nodeId: target.id, position, side: positionToSide(position), point, distance, inside, rank };
1412
+ best = { nodeId: target.id, position, side: positionToSide(position), point, distance, inside: inside2, rank };
1403
1413
  }
1404
1414
  }
1405
1415
  }
@@ -1505,7 +1515,7 @@ var CanvasScenesStore = (_class3 = class {
1505
1515
  this.scenes = scenes;
1506
1516
  if (this.currentId && !scenes.some((s) => s.id === this.currentId)) this.currentId = null;
1507
1517
  this.cached = this.snapshot();
1508
- _optionalChain([this, 'access', _46 => _46.onChange, 'optionalCall', _47 => _47(this.cached)]);
1518
+ _optionalChain([this, 'access', _50 => _50.onChange, 'optionalCall', _51 => _51(this.cached)]);
1509
1519
  for (const listener of this.listeners) listener(this.cached);
1510
1520
  }
1511
1521
  getState() {
@@ -1533,7 +1543,7 @@ var CanvasScenesStore = (_class3 = class {
1533
1543
  add(input, index) {
1534
1544
  const scene = cloneScene({
1535
1545
  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(),
1546
+ name: _optionalChain([input, 'access', _52 => _52.name, 'optionalAccess', _53 => _53.trim, 'call', _54 => _54()]) || this.nextDefaultName(),
1537
1547
  viewport: input.viewport,
1538
1548
  nodeIds: input.nodeIds
1539
1549
  });
@@ -1662,49 +1672,6 @@ function fitViewportToNodes(nodes, size, ids, options = {}) {
1662
1672
  return bounds ? fitViewportToRect(bounds, size, options) : null;
1663
1673
  }
1664
1674
 
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
1675
  // src/canvas/polygonBoolean.ts
1709
1676
  function ringSignedArea(ring) {
1710
1677
  let sum = 0;
@@ -1885,9 +1852,9 @@ function splitPass(segments, pool, eps) {
1885
1852
  ]) {
1886
1853
  for (const p of [other.a, other.b]) {
1887
1854
  if (p.id === seg.a.id || p.id === seg.b.id) continue;
1888
- const { t: t2, dist } = project(seg.a, seg.b, p);
1855
+ const { t: t2, dist: dist2 } = project(seg.a, seg.b, p);
1889
1856
  const len = Math.hypot(seg.b.x - seg.a.x, seg.b.y - seg.a.y);
1890
- if (dist <= eps && t2 * len > eps && (1 - t2) * len > eps) {
1857
+ if (dist2 <= eps && t2 * len > eps && (1 - t2) * len > eps) {
1891
1858
  addSplit(split, t2, p);
1892
1859
  touched = true;
1893
1860
  }
@@ -2077,8 +2044,8 @@ function removeCollinear(ring, eps) {
2077
2044
  const dy = nxt[1] - prev[1];
2078
2045
  const len = Math.hypot(dx, dy);
2079
2046
  const cross = (cur[0] - prev[0]) * dy - (cur[1] - prev[1]) * dx;
2080
- const dot = (cur[0] - prev[0]) * dx + (cur[1] - prev[1]) * dy;
2081
- if (len > 0 && Math.abs(cross) / len <= eps && dot > 0 && dot < len * len) {
2047
+ const dot2 = (cur[0] - prev[0]) * dx + (cur[1] - prev[1]) * dy;
2048
+ if (len > 0 && Math.abs(cross) / len <= eps && dot2 > 0 && dot2 < len * len) {
2082
2049
  changed = true;
2083
2050
  continue;
2084
2051
  }
@@ -2174,6 +2141,347 @@ function dividePolygons(operands, options = {}) {
2174
2141
  return pieces;
2175
2142
  }
2176
2143
 
2144
+ // src/canvas/curveFit.ts
2145
+ function formatNumber(value, precision) {
2146
+ const factor = 10 ** precision;
2147
+ const rounded = Math.round(value * factor) / factor;
2148
+ return Object.is(rounded, -0) ? "0" : String(rounded);
2149
+ }
2150
+ var MAX_REPARAM = 6;
2151
+ var sub = (a, b) => [a[0] - b[0], a[1] - b[1]];
2152
+ var add = (a, v, s = 1) => [a[0] + v[0] * s, a[1] + v[1] * s];
2153
+ var dot = (a, b) => a[0] * b[0] + a[1] * b[1];
2154
+ var dist = (a, b) => Math.hypot(a[0] - b[0], a[1] - b[1]);
2155
+ function unit(v) {
2156
+ const l = Math.hypot(v[0], v[1]);
2157
+ return l > 1e-12 && Number.isFinite(l) ? [v[0] / l, v[1] / l] : null;
2158
+ }
2159
+ function evalCubic(c, t) {
2160
+ const s = 1 - t;
2161
+ const b0 = s * s * s;
2162
+ const b1 = 3 * s * s * t;
2163
+ const b2 = 3 * s * t * t;
2164
+ const b3 = t * t * t;
2165
+ return [
2166
+ b0 * c.p0[0] + b1 * c.p1[0] + b2 * c.p2[0] + b3 * c.p3[0],
2167
+ b0 * c.p0[1] + b1 * c.p1[1] + b2 * c.p2[1] + b3 * c.p3[1]
2168
+ ];
2169
+ }
2170
+ function cubicPointAt(c, t) {
2171
+ return evalCubic(c, t);
2172
+ }
2173
+ function dedup(points) {
2174
+ const out = [];
2175
+ for (const p of points) {
2176
+ if (!Number.isFinite(p[0]) || !Number.isFinite(p[1])) continue;
2177
+ if (out.length === 0 || dist(out[out.length - 1], p) > 1e-12) out.push(p);
2178
+ }
2179
+ return out;
2180
+ }
2181
+ function chordParams(pts) {
2182
+ const u = [0];
2183
+ let acc = 0;
2184
+ for (let i = 1; i < pts.length; i++) {
2185
+ acc += dist(pts[i - 1], pts[i]);
2186
+ u.push(acc);
2187
+ }
2188
+ return acc > 0 ? u.map((x) => x / acc) : u;
2189
+ }
2190
+ function generate(pts, u, t0, t1) {
2191
+ const p0 = pts[0];
2192
+ const p3 = pts[pts.length - 1];
2193
+ const dirIn = [-t1[0], -t1[1]];
2194
+ let c00 = 0;
2195
+ let c01 = 0;
2196
+ let c11 = 0;
2197
+ let x0 = 0;
2198
+ let x1 = 0;
2199
+ for (let i = 0; i < pts.length; i++) {
2200
+ const t = u[i];
2201
+ const s = 1 - t;
2202
+ const b0 = s * s * s;
2203
+ const b1 = 3 * s * s * t;
2204
+ const b2 = 3 * s * t * t;
2205
+ const b3 = t * t * t;
2206
+ const a0 = [t0[0] * b1, t0[1] * b1];
2207
+ const a1 = [dirIn[0] * b2, dirIn[1] * b2];
2208
+ c00 += dot(a0, a0);
2209
+ c01 += dot(a0, a1);
2210
+ c11 += dot(a1, a1);
2211
+ const tmp = [
2212
+ pts[i][0] - (p0[0] * (b0 + b1) + p3[0] * (b2 + b3)),
2213
+ pts[i][1] - (p0[1] * (b0 + b1) + p3[1] * (b2 + b3))
2214
+ ];
2215
+ x0 += dot(a0, tmp);
2216
+ x1 += dot(a1, tmp);
2217
+ }
2218
+ const det = c00 * c11 - c01 * c01;
2219
+ const seg = dist(p0, p3);
2220
+ const eps = 1e-6 * seg;
2221
+ let al = seg / 3;
2222
+ let ar = seg / 3;
2223
+ if (Math.abs(det) > 1e-12) {
2224
+ al = (x0 * c11 - x1 * c01) / det;
2225
+ ar = (c00 * x1 - c01 * x0) / det;
2226
+ }
2227
+ if (!Number.isFinite(al) || !Number.isFinite(ar) || al < eps || ar < eps) {
2228
+ al = seg / 3;
2229
+ ar = seg / 3;
2230
+ }
2231
+ const cap = seg * 4 + 1e-9;
2232
+ al = Math.min(al, cap);
2233
+ ar = Math.min(ar, cap);
2234
+ return { p0, p1: add(p0, t0, al), p2: add(p3, dirIn, ar), p3 };
2235
+ }
2236
+ function maxError(pts, c, u) {
2237
+ let e = 0;
2238
+ let idx = pts.length >> 1;
2239
+ for (let i = 0; i < pts.length; i++) {
2240
+ const d = dist(evalCubic(c, u[i]), pts[i]);
2241
+ if (d > e) {
2242
+ e = d;
2243
+ idx = i;
2244
+ }
2245
+ }
2246
+ return [e, idx];
2247
+ }
2248
+ function newton(c, p, t) {
2249
+ const s = 1 - t;
2250
+ const q = evalCubic(c, t);
2251
+ const d1 = [
2252
+ 3 * (s * s * (c.p1[0] - c.p0[0]) + 2 * s * t * (c.p2[0] - c.p1[0]) + t * t * (c.p3[0] - c.p2[0])),
2253
+ 3 * (s * s * (c.p1[1] - c.p0[1]) + 2 * s * t * (c.p2[1] - c.p1[1]) + t * t * (c.p3[1] - c.p2[1]))
2254
+ ];
2255
+ const d2 = [
2256
+ 6 * (s * (c.p2[0] - 2 * c.p1[0] + c.p0[0]) + t * (c.p3[0] - 2 * c.p2[0] + c.p1[0])),
2257
+ 6 * (s * (c.p2[1] - 2 * c.p1[1] + c.p0[1]) + t * (c.p3[1] - 2 * c.p2[1] + c.p1[1]))
2258
+ ];
2259
+ const diff = [q[0] - p[0], q[1] - p[1]];
2260
+ const num = dot(diff, d1);
2261
+ const den = dot(d1, d1) + dot(diff, d2);
2262
+ if (Math.abs(den) < 1e-12) return t;
2263
+ const nt = t - num / den;
2264
+ return Number.isFinite(nt) ? Math.min(1, Math.max(0, nt)) : t;
2265
+ }
2266
+ function fitSingleFrom(pts, u, t0, t1) {
2267
+ let best = generate(pts, u, t0, t1);
2268
+ let [bestErr, bestSplit] = maxError(pts, best, u);
2269
+ const params = u.slice();
2270
+ for (let round = 0; round < MAX_REPARAM; round++) {
2271
+ for (let i = 0; i < params.length; i++) params[i] = newton(best, pts[i], params[i]);
2272
+ const c = generate(pts, params, t0, t1);
2273
+ const [e, s] = maxError(pts, c, params);
2274
+ if (e < bestErr) {
2275
+ best = c;
2276
+ bestErr = e;
2277
+ bestSplit = s;
2278
+ } else break;
2279
+ }
2280
+ return [best, bestErr, bestSplit];
2281
+ }
2282
+ function fitRec(pts, t0, t1, tol, out, depth) {
2283
+ const n = pts.length;
2284
+ if (n === 2) {
2285
+ const d = dist(pts[0], pts[1]) / 3;
2286
+ out.push({ p0: pts[0], p1: add(pts[0], t0, d), p2: add(pts[1], t1, -d), p3: pts[1] });
2287
+ return;
2288
+ }
2289
+ const [c, err, splitAt] = fitSingleFrom(pts, chordParams(pts), t0, t1);
2290
+ if (err <= tol || depth > 40) {
2291
+ out.push(c);
2292
+ return;
2293
+ }
2294
+ const split = Math.min(n - 2, Math.max(1, splitAt));
2295
+ const tc = _nullishCoalesce(unit(sub(pts[split + 1], pts[split - 1])), () => ( t0));
2296
+ fitRec(pts.slice(0, split + 1), t0, tc, tol, out, depth + 1);
2297
+ fitRec(pts.slice(split), tc, t1, tol, out, depth + 1);
2298
+ }
2299
+ function tangentFrom(a, b, c) {
2300
+ const chord = unit(sub(b, a));
2301
+ if (!c) return chord;
2302
+ const d1 = dist(a, b);
2303
+ const d2 = dist(b, c);
2304
+ if (!(d1 > 0) || !(d2 > 0)) return chord;
2305
+ const ka = -(2 * d1 + d2) / (d1 * (d1 + d2));
2306
+ const kb = (d1 + d2) / (d1 * d2);
2307
+ const kc = -d1 / (d2 * (d1 + d2));
2308
+ const est = unit([ka * a[0] + kb * b[0] + kc * c[0], ka * a[1] + kb * b[1] + kc * c[1]]);
2309
+ return est && chord && dot(est, chord) > Math.cos(Math.PI / 4) ? est : chord;
2310
+ }
2311
+ function fitCubicRun(points, tolerance, t0, t1) {
2312
+ const pts = dedup(points);
2313
+ const out = [];
2314
+ if (pts.length < 2) return out;
2315
+ const n = pts.length;
2316
+ const start = _nullishCoalesce(_nullishCoalesce((t0 && unit([t0[0], t0[1]])), () => ( tangentFrom(pts[0], pts[1], pts[2]))), () => ( [1, 0]));
2317
+ const back = tangentFrom(pts[n - 1], pts[n - 2], pts[n - 3]);
2318
+ const end = _nullishCoalesce((t1 && unit([t1[0], t1[1]])), () => ( (back ? [-back[0], -back[1]] : [1, 0])));
2319
+ fitRec(pts, start, end, Math.max(tolerance, 1e-9), out, 0);
2320
+ return out;
2321
+ }
2322
+ function turnDeg(a, b, c) {
2323
+ const u = unit(sub(b, a));
2324
+ const v = unit(sub(c, b));
2325
+ if (!u || !v) return 0;
2326
+ return Math.acos(Math.min(1, Math.max(-1, dot(u, v)))) * 180 / Math.PI;
2327
+ }
2328
+ function findCorners(pts, closed, cornerAngle, span) {
2329
+ const n = pts.length;
2330
+ const at = (i) => pts[closed ? (i % n + n) % n : i];
2331
+ const reach = (i, step) => {
2332
+ for (let k = 1; k < (closed ? n : Infinity); k++) {
2333
+ const j = i + step * k;
2334
+ if (!closed && (j < 0 || j >= n)) return k > 1 ? j - step : null;
2335
+ if (dist(at(j), pts[i]) >= span) return j;
2336
+ }
2337
+ return null;
2338
+ };
2339
+ const turns = new Float64Array(n);
2340
+ const windows = [];
2341
+ for (let i = 0; i < n; i++) {
2342
+ windows.push([i, i]);
2343
+ if (!closed && (i === 0 || i === n - 1)) continue;
2344
+ const prev = reach(i, -1);
2345
+ const next = reach(i, 1);
2346
+ if (prev === null || next === null) continue;
2347
+ windows[i] = [prev, next];
2348
+ turns[i] = turnDeg(at(prev), pts[i], at(next));
2349
+ }
2350
+ const corners = [];
2351
+ for (let i = 0; i < n; i++) {
2352
+ if (!(turns[i] > cornerAngle)) continue;
2353
+ const [lo, hi] = windows[i];
2354
+ let sharpest = true;
2355
+ for (let j = lo; j <= hi && sharpest; j++) {
2356
+ const k = closed ? (j % n + n) % n : j;
2357
+ if (k === i || dist(pts[k], pts[i]) >= span) continue;
2358
+ if (turns[k] > turns[i] || turns[k] === turns[i] && k < i) sharpest = false;
2359
+ }
2360
+ if (sharpest) corners.push(i);
2361
+ }
2362
+ return corners;
2363
+ }
2364
+ function densify(run) {
2365
+ if (run.length < 3) return run;
2366
+ const lengths = [];
2367
+ for (let i = 1; i < run.length; i++) lengths.push(dist(run[i - 1], run[i]));
2368
+ const sorted = [...lengths].sort((a, b) => a - b);
2369
+ const median = sorted[sorted.length >> 1];
2370
+ if (!(median > 0)) return run;
2371
+ const out = [run[0]];
2372
+ for (let i = 1; i < run.length; i++) {
2373
+ const len = lengths[i - 1];
2374
+ if (len > 2 * median) {
2375
+ const steps = Math.min(64, Math.ceil(len / median));
2376
+ const a = run[i - 1];
2377
+ const b = run[i];
2378
+ for (let k = 1; k < steps; k++) {
2379
+ const t = k / steps;
2380
+ out.push([a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t]);
2381
+ }
2382
+ }
2383
+ out.push(run[i]);
2384
+ }
2385
+ return out;
2386
+ }
2387
+ function fitCubics(points, tolerance, options = {}) {
2388
+ let pts = dedup(points);
2389
+ const closed = options.closed === true;
2390
+ if (closed && pts.length > 1 && dist(pts[0], pts[pts.length - 1]) <= 1e-12) pts = pts.slice(0, -1);
2391
+ if (pts.length < 2) return [];
2392
+ const tol = Math.max(tolerance, 1e-6);
2393
+ const cornerAngle = _nullishCoalesce(options.cornerAngleDeg, () => ( 30));
2394
+ const n = pts.length;
2395
+ const span = 4 * tol;
2396
+ if (!closed || n < 3) {
2397
+ const corners2 = [0, ...n > 2 ? findCorners(pts, false, cornerAngle, span) : [], n - 1];
2398
+ const out2 = [];
2399
+ for (let k = 1; k < corners2.length; k++) {
2400
+ const run = pts.slice(corners2[k - 1], corners2[k] + 1);
2401
+ out2.push(...fitCubicRun(densify(run), tol));
2402
+ }
2403
+ if (closed && n === 2) out2.push(...fitCubicRun([pts[1], pts[0]], tol));
2404
+ return out2;
2405
+ }
2406
+ const corners = findCorners(pts, true, cornerAngle, span);
2407
+ if (corners.length === 0) {
2408
+ const ring = [...pts, pts[0]];
2409
+ const t = _nullishCoalesce(unit(sub(pts[1], pts[n - 1])), () => ( [1, 0]));
2410
+ return fitCubicRun(densify(ring), tol, t, t);
2411
+ }
2412
+ const out = [];
2413
+ for (let k = 0; k < corners.length; k++) {
2414
+ const from = corners[k];
2415
+ const to = corners[(k + 1) % corners.length];
2416
+ const run = [];
2417
+ for (let i = from; ; i = (i + 1) % n) {
2418
+ run.push(pts[i]);
2419
+ if (run.length > 1 && i === to) break;
2420
+ }
2421
+ out.push(...fitCubicRun(densify(run), tol));
2422
+ }
2423
+ return out;
2424
+ }
2425
+ function isStraightCubic(c, tol) {
2426
+ const chord = sub(c.p3, c.p0);
2427
+ const len = Math.hypot(chord[0], chord[1]);
2428
+ if (len < 1e-12) return dist(c.p1, c.p0) <= tol && dist(c.p2, c.p0) <= tol;
2429
+ const dir = [chord[0] / len, chord[1] / len];
2430
+ return [c.p1, c.p2].every((h) => {
2431
+ const v = sub(h, c.p0);
2432
+ const along = dot(v, dir);
2433
+ const across = Math.abs(v[0] * dir[1] - v[1] * dir[0]);
2434
+ return across <= tol && along >= -tol && along <= len + tol;
2435
+ });
2436
+ }
2437
+ function cubicsToPathData(segments, options = {}) {
2438
+ if (segments.length === 0) return "";
2439
+ const f = (n) => formatNumber(n, _nullishCoalesce(options.precision, () => ( 3)));
2440
+ const dx = _nullishCoalesce(_optionalChain([options, 'access', _55 => _55.offset, 'optionalAccess', _56 => _56.x]), () => ( 0));
2441
+ const dy = _nullishCoalesce(_optionalChain([options, 'access', _57 => _57.offset, 'optionalAccess', _58 => _58.y]), () => ( 0));
2442
+ const pt = (p) => `${f(p[0] + dx)} ${f(p[1] + dy)}`;
2443
+ const straight = _nullishCoalesce(options.straightTolerance, () => ( 1e-3));
2444
+ let d = `M${pt(segments[0].p0)}`;
2445
+ segments.forEach((c, i) => {
2446
+ const last = options.closed && i === segments.length - 1;
2447
+ if (isStraightCubic(c, straight)) {
2448
+ if (!last) d += `L${pt(c.p3)}`;
2449
+ } else d += `C${pt(c.p1)} ${pt(c.p2)} ${pt(c.p3)}`;
2450
+ });
2451
+ return options.closed ? `${d}Z` : d;
2452
+ }
2453
+ function polylineToPathData(points, closed, options) {
2454
+ if (points.length < 2) return "";
2455
+ const f = (n) => formatNumber(n, _nullishCoalesce(options.precision, () => ( 3)));
2456
+ const dx = _nullishCoalesce(_optionalChain([options, 'access', _59 => _59.offset, 'optionalAccess', _60 => _60.x]), () => ( 0));
2457
+ const dy = _nullishCoalesce(_optionalChain([options, 'access', _61 => _61.offset, 'optionalAccess', _62 => _62.y]), () => ( 0));
2458
+ let d = `M${f(points[0][0] + dx)} ${f(points[0][1] + dy)}`;
2459
+ for (let i = 1; i < points.length; i++) d += `L${f(points[i][0] + dx)} ${f(points[i][1] + dy)}`;
2460
+ return closed ? `${d}Z` : d;
2461
+ }
2462
+ function fitPathData(ring, options = {}) {
2463
+ const closed = _nullishCoalesce(options.closed, () => ( true));
2464
+ const tolerance = _nullishCoalesce(options.tolerance, () => ( 0.5));
2465
+ const pts = dedup(ring);
2466
+ const segments = fitCubics(pts, tolerance, { ...options, closed });
2467
+ if (segments.length === 0) return "";
2468
+ const edges = closed ? pts.length : pts.length - 1;
2469
+ if (options.noWorse !== false) {
2470
+ const straight = segments.filter((c) => isStraightCubic(c, tolerance * 0.02)).length;
2471
+ if (segments.length >= edges && straight === segments.length) return polylineToPathData(pts, closed, options);
2472
+ if (segments.length > edges) return polylineToPathData(pts, closed, options);
2473
+ }
2474
+ return cubicsToPathData(segments, {
2475
+ precision: options.precision,
2476
+ offset: options.offset,
2477
+ closed,
2478
+ straightTolerance: tolerance * 0.02
2479
+ });
2480
+ }
2481
+ function fitFreehandPath(points, options = {}) {
2482
+ return fitPathData(points, { tolerance: 1, ...options, closed: false });
2483
+ }
2484
+
2177
2485
  // src/canvas/shapeGeometry.ts
2178
2486
  var SHAPE_KINDS = ["rect", "ellipse", "polygon", "star", "path"];
2179
2487
  function isShapeDescription(value) {
@@ -2302,8 +2610,8 @@ function parseSvgPath(d) {
2302
2610
  break;
2303
2611
  }
2304
2612
  case "s": {
2305
- const x1 = _optionalChain([lastControl, 'optionalAccess', _51 => _51.type]) === "C" ? 2 * cx - lastControl.x : cx;
2306
- const y1 = _optionalChain([lastControl, 'optionalAccess', _52 => _52.type]) === "C" ? 2 * cy - lastControl.y : cy;
2613
+ const x1 = _optionalChain([lastControl, 'optionalAccess', _63 => _63.type]) === "C" ? 2 * cx - lastControl.x : cx;
2614
+ const y1 = _optionalChain([lastControl, 'optionalAccess', _64 => _64.type]) === "C" ? 2 * cy - lastControl.y : cy;
2307
2615
  const c = {
2308
2616
  type: "C",
2309
2617
  x1,
@@ -2328,8 +2636,8 @@ function parseSvgPath(d) {
2328
2636
  break;
2329
2637
  }
2330
2638
  case "t": {
2331
- const x1 = _optionalChain([lastControl, 'optionalAccess', _53 => _53.type]) === "Q" ? 2 * cx - lastControl.x : cx;
2332
- const y1 = _optionalChain([lastControl, 'optionalAccess', _54 => _54.type]) === "Q" ? 2 * cy - lastControl.y : cy;
2639
+ const x1 = _optionalChain([lastControl, 'optionalAccess', _65 => _65.type]) === "Q" ? 2 * cx - lastControl.x : cx;
2640
+ const y1 = _optionalChain([lastControl, 'optionalAccess', _66 => _66.type]) === "Q" ? 2 * cy - lastControl.y : cy;
2333
2641
  const c = { type: "Q", x1, y1, x: args[0] + ox, y: args[1] + oy };
2334
2642
  commands.push(c);
2335
2643
  lastControl = { x: x1, y: y1, type: "Q" };
@@ -2540,7 +2848,7 @@ function rotationTransform(shape, size) {
2540
2848
  }
2541
2849
  function getShapeSvg(shape, size) {
2542
2850
  const { width: w, height: h } = size;
2543
- const f = (n) => formatNumber(n, 3);
2851
+ const f = (n) => formatNumber2(n, 3);
2544
2852
  const transforms = [];
2545
2853
  if (shape.rotation) transforms.push(`rotate(${f(shape.rotation)} ${f(w / 2)} ${f(h / 2)})`);
2546
2854
  let d = "";
@@ -2589,7 +2897,7 @@ function getShapeRenderData(shape, size = {}) {
2589
2897
  const height = size.height && size.height > 0 ? size.height : vb ? vb[3] : 100;
2590
2898
  const svg = getShapeSvg(shape, { width, height });
2591
2899
  const data = {
2592
- viewBox: `0 0 ${formatNumber(width, 3)} ${formatNumber(height, 3)}`,
2900
+ viewBox: `0 0 ${formatNumber2(width, 3)} ${formatNumber2(height, 3)}`,
2593
2901
  width,
2594
2902
  height,
2595
2903
  d: svg.d,
@@ -2636,7 +2944,7 @@ function shapeToPolygon(shape, size, options = {}) {
2636
2944
  if (rotate) rings = rings.map((ring) => ring.map(rotate));
2637
2945
  return { rings, fillRule };
2638
2946
  }
2639
- function formatNumber(value, precision = 3) {
2947
+ function formatNumber2(value, precision = 3) {
2640
2948
  const factor = 10 ** precision;
2641
2949
  const rounded = Math.round(value * factor) / factor;
2642
2950
  return Object.is(rounded, -0) ? "0" : String(rounded);
@@ -2670,9 +2978,9 @@ function rdp(points, tolerance) {
2670
2978
  let maxDist = -1;
2671
2979
  let index = -1;
2672
2980
  for (let i = s + 1; i < e; i++) {
2673
- const dist = segmentDistance(points[i], points[s], points[e]);
2674
- if (dist > maxDist) {
2675
- maxDist = dist;
2981
+ const dist2 = segmentDistance(points[i], points[s], points[e]);
2982
+ if (dist2 > maxDist) {
2983
+ maxDist = dist2;
2676
2984
  index = i;
2677
2985
  }
2678
2986
  }
@@ -2688,9 +2996,9 @@ function simplifyRing(ring, tolerance) {
2688
2996
  let far = 0;
2689
2997
  let farDist = -1;
2690
2998
  for (let i = 1; i < ring.length; i++) {
2691
- const dist = Math.hypot(ring[i][0] - ring[0][0], ring[i][1] - ring[0][1]);
2692
- if (dist > farDist) {
2693
- farDist = dist;
2999
+ const dist2 = Math.hypot(ring[i][0] - ring[0][0], ring[i][1] - ring[0][1]);
3000
+ if (dist2 > farDist) {
3001
+ farDist = dist2;
2694
3002
  far = i;
2695
3003
  }
2696
3004
  }
@@ -2701,20 +3009,31 @@ function simplifyRing(ring, tolerance) {
2701
3009
  }
2702
3010
  function polygonToSvgPath(input, options = {}) {
2703
3011
  const precision = _nullishCoalesce(options.precision, () => ( 3));
2704
- const f = (n) => formatNumber(n, precision);
2705
- const dx = _nullishCoalesce(_optionalChain([options, 'access', _55 => _55.offset, 'optionalAccess', _56 => _56.x]), () => ( 0));
2706
- const dy = _nullishCoalesce(_optionalChain([options, 'access', _57 => _57.offset, 'optionalAccess', _58 => _58.y]), () => ( 0));
3012
+ const f = (n) => formatNumber2(n, precision);
3013
+ const dx = _nullishCoalesce(_optionalChain([options, 'access', _67 => _67.offset, 'optionalAccess', _68 => _68.x]), () => ( 0));
3014
+ const dy = _nullishCoalesce(_optionalChain([options, 'access', _69 => _69.offset, 'optionalAccess', _70 => _70.y]), () => ( 0));
2707
3015
  const rings = [];
3016
+ const fit = options.curves === "fit";
3017
+ let fitted = "";
2708
3018
  for (const item of input) {
2709
3019
  const list = item.length > 0 && Array.isArray(item[0]) && Array.isArray(item[0][0]) ? item : [item];
2710
3020
  for (const ring of list) {
2711
3021
  let r = ring;
2712
3022
  if (options.simplify && options.simplify > 0) r = simplifyRing(r, options.simplify);
2713
3023
  if (r.length < 3) continue;
3024
+ if (fit) {
3025
+ fitted += fitPathData(r, {
3026
+ tolerance: _nullishCoalesce(options.curveTolerance, () => ( 0.25)),
3027
+ cornerAngleDeg: options.cornerAngleDeg,
3028
+ precision,
3029
+ offset: { x: dx, y: dy }
3030
+ });
3031
+ continue;
3032
+ }
2714
3033
  rings.push(dx || dy ? r.map(([x, y]) => [x + dx, y + dy]) : r);
2715
3034
  }
2716
3035
  }
2717
- return ringsToPath(rings, f);
3036
+ return fit ? fitted : ringsToPath(rings, f);
2718
3037
  }
2719
3038
 
2720
3039
  // src/canvas/shapeNodes.ts
@@ -2728,10 +3047,10 @@ var BOOLEAN_FOR = {
2728
3047
  exclude: "xor"
2729
3048
  };
2730
3049
  function isShapeNode(node) {
2731
- return !!node && isShapeDescription(_optionalChain([node, 'access', _59 => _59.data, 'optionalAccess', _60 => _60[SHAPE_DATA_KEY]]));
3050
+ return !!node && isShapeDescription(_optionalChain([node, 'access', _71 => _71.data, 'optionalAccess', _72 => _72[SHAPE_DATA_KEY]]));
2732
3051
  }
2733
3052
  function getNodeShape(node) {
2734
- const shape = _optionalChain([node, 'optionalAccess', _61 => _61.data, 'optionalAccess', _62 => _62[SHAPE_DATA_KEY]]);
3053
+ const shape = _optionalChain([node, 'optionalAccess', _73 => _73.data, 'optionalAccess', _74 => _74[SHAPE_DATA_KEY]]);
2735
3054
  return isShapeDescription(shape) ? shape : null;
2736
3055
  }
2737
3056
  function shapeNodeToPolygon(node, lookup, options = {}) {
@@ -2792,7 +3111,10 @@ function combineShapeNodes(nodes, ids, operation, options = {}) {
2792
3111
  const d = polygonToSvgPath(polygon, {
2793
3112
  precision: options.precision,
2794
3113
  simplify: options.simplify,
2795
- offset: { x: -bounds.minX, y: -bounds.minY }
3114
+ offset: { x: -bounds.minX, y: -bounds.minY },
3115
+ curves: _nullishCoalesce(options.curves, () => ( "fit")),
3116
+ curveTolerance: _nullishCoalesce(_nullishCoalesce(options.curveTolerance, () => ( options.tolerance)), () => ( 0.25)),
3117
+ cornerAngleDeg: options.cornerAngleDeg
2796
3118
  });
2797
3119
  if (!d) return null;
2798
3120
  const sourceShape = getNodeShape(source);
@@ -2876,17 +3198,211 @@ function revertShapeCombination(nodes, change, previous) {
2876
3198
  return out;
2877
3199
  }
2878
3200
 
3201
+ // src/canvas/resizeSnap.ts
3202
+ var RESIZE_HANDLES = [
3203
+ "top-left",
3204
+ "top",
3205
+ "top-right",
3206
+ "right",
3207
+ "bottom-right",
3208
+ "bottom",
3209
+ "bottom-left",
3210
+ "left"
3211
+ ];
3212
+ function resizeHandleAxes(handle) {
3213
+ const x = handle.includes("left") ? -1 : handle.includes("right") ? 1 : 0;
3214
+ const y = handle.includes("top") ? -1 : handle.includes("bottom") ? 1 : 0;
3215
+ return { x, y };
3216
+ }
3217
+ function inferResizeHandle(start, next, eps = 1e-6) {
3218
+ const moved = (a, b) => Math.abs(a - b) > eps;
3219
+ const left = moved(start.x, next.x);
3220
+ const right = moved(start.x + start.width, next.x + next.width);
3221
+ const top = moved(start.y, next.y);
3222
+ const bottom = moved(start.y + start.height, next.y + next.height);
3223
+ const h = left ? "left" : right ? "right" : "";
3224
+ const v = top ? "top" : bottom ? "bottom" : "";
3225
+ if (h && v) return `${v}-${h}`;
3226
+ return h || v || null;
3227
+ }
3228
+ function within(axis, v, tolerance) {
3229
+ const { values } = axis;
3230
+ let lo = 0;
3231
+ let hi = values.length;
3232
+ while (lo < hi) {
3233
+ const mid = lo + hi >>> 1;
3234
+ if (values[mid] < v - tolerance) lo = mid + 1;
3235
+ else hi = mid;
3236
+ }
3237
+ const out = [];
3238
+ for (let i = lo; i < values.length && values[i] <= v + tolerance; i++) out.push(values[i]);
3239
+ return out;
3240
+ }
3241
+ function matching(axis, v, eps) {
3242
+ const { values, rects } = axis;
3243
+ const out = [];
3244
+ for (let i = 0; i < values.length; i++) if (Math.abs(values[i] - v) <= eps) out.push(rects[i]);
3245
+ return out;
3246
+ }
3247
+ function snapResize(rect, handle, targets, options = {}) {
3248
+ const index = Array.isArray(targets) ? createGuideIndex(targets) : targets;
3249
+ const zoom = options.zoom && options.zoom > 0 ? options.zoom : 1;
3250
+ const tolerance = (_nullishCoalesce(options.threshold, () => ( 6))) / zoom;
3251
+ const eps = 0.5 / zoom;
3252
+ const useEdges = options.edges !== false;
3253
+ const useCentres = options.centres !== false;
3254
+ const grid = _nullishCoalesce(options.gridSize, () => ( 0));
3255
+ const axes = resizeHandleAxes(handle);
3256
+ const unchanged = { rect: { ...rect }, guides: [], snappedX: false, snappedY: false, changed: false };
3257
+ if (![rect.x, rect.y, rect.width, rect.height].every(Number.isFinite)) return unchanged;
3258
+ const x0 = rect.x;
3259
+ const x1 = rect.x + rect.width;
3260
+ const y0 = rect.y;
3261
+ const y1 = rect.y + rect.height;
3262
+ const bestHit = (horizontal) => {
3263
+ const dir = horizontal ? axes.x : axes.y;
3264
+ if (dir === 0) return null;
3265
+ const moving = horizontal ? dir < 0 ? x0 : x1 : dir < 0 ? y0 : y1;
3266
+ const fixed = horizontal ? dir < 0 ? x1 : x0 : dir < 0 ? y1 : y0;
3267
+ const min = _nullishCoalesce((horizontal ? options.minWidth : options.minHeight), () => ( 0));
3268
+ const valid = (t) => {
3269
+ const size = dir < 0 ? fixed - t : t - fixed;
3270
+ return Number.isFinite(size) && size > 1e-9 && size >= min;
3271
+ };
3272
+ let best = null;
3273
+ const consider = (values, kind) => {
3274
+ for (const t of values) {
3275
+ if (!valid(t)) continue;
3276
+ if (!best || Math.abs(t - moving) < Math.abs(best.value - moving)) best = { value: t, kind };
3277
+ }
3278
+ };
3279
+ if (useEdges) consider(within(horizontal ? index.edgeX : index.edgeY, moving, tolerance), "edge");
3280
+ if (useCentres) consider(within(horizontal ? index.centreX : index.centreY, moving, tolerance), "centre");
3281
+ if (!best && grid > 0) {
3282
+ const origin = horizontal ? _nullishCoalesce(_optionalChain([options, 'access', _75 => _75.gridOrigin, 'optionalAccess', _76 => _76.x]), () => ( 0)) : _nullishCoalesce(_optionalChain([options, 'access', _77 => _77.gridOrigin, 'optionalAccess', _78 => _78.y]), () => ( 0));
3283
+ consider([snapToGrid(moving, grid, origin)], "grid");
3284
+ }
3285
+ return best;
3286
+ };
3287
+ let nx0 = x0;
3288
+ let nx1 = x1;
3289
+ let ny0 = y0;
3290
+ let ny1 = y1;
3291
+ const setEdge = (horizontal, value) => {
3292
+ const dir = horizontal ? axes.x : axes.y;
3293
+ if (horizontal) {
3294
+ if (dir < 0) nx0 = value;
3295
+ else nx1 = value;
3296
+ } else if (dir < 0) ny0 = value;
3297
+ else ny1 = value;
3298
+ };
3299
+ let hitX = bestHit(true);
3300
+ let hitY = bestHit(false);
3301
+ const ratio = rect.height > 0 ? rect.width / rect.height : 0;
3302
+ if (options.keepAspectRatio && ratio > 0 && (hitX || hitY)) {
3303
+ if (axes.x !== 0 && axes.y !== 0) {
3304
+ const dist2 = (h, horizontal) => h ? Math.abs(h.value - (horizontal ? axes.x < 0 ? x0 : x1 : axes.y < 0 ? y0 : y1)) : Infinity;
3305
+ const useX = dist2(hitX, true) <= dist2(hitY, false);
3306
+ if (useX && hitX) {
3307
+ setEdge(true, hitX.value);
3308
+ const height = (nx1 - nx0) / ratio;
3309
+ if (axes.y < 0) ny0 = ny1 - height;
3310
+ else ny1 = ny0 + height;
3311
+ hitY = null;
3312
+ } else if (hitY) {
3313
+ setEdge(false, hitY.value);
3314
+ const width = (ny1 - ny0) * ratio;
3315
+ if (axes.x < 0) nx0 = nx1 - width;
3316
+ else nx1 = nx0 + width;
3317
+ hitX = null;
3318
+ }
3319
+ const min = (v) => _nullishCoalesce(v, () => ( 0));
3320
+ if (nx1 - nx0 < min(options.minWidth) || ny1 - ny0 < min(options.minHeight) || !(nx1 > nx0 && ny1 > ny0)) {
3321
+ return unchanged;
3322
+ }
3323
+ } else if (axes.x !== 0 && hitX) {
3324
+ setEdge(true, hitX.value);
3325
+ const height = (nx1 - nx0) / ratio;
3326
+ const cy = (y0 + y1) / 2;
3327
+ ny0 = cy - height / 2;
3328
+ ny1 = cy + height / 2;
3329
+ } else if (axes.y !== 0 && hitY) {
3330
+ setEdge(false, hitY.value);
3331
+ const width = (ny1 - ny0) * ratio;
3332
+ const cx = (x0 + x1) / 2;
3333
+ nx0 = cx - width / 2;
3334
+ nx1 = cx + width / 2;
3335
+ }
3336
+ } else {
3337
+ if (hitX) setEdge(true, hitX.value);
3338
+ if (hitY) setEdge(false, hitY.value);
3339
+ }
3340
+ const out = { x: nx0, y: ny0, width: nx1 - nx0, height: ny1 - ny0 };
3341
+ const guides = [];
3342
+ const guideFor = (horizontal, hit) => {
3343
+ if (!hit || hit.kind === "grid") return;
3344
+ const axis = hit.kind === "edge" ? horizontal ? index.edgeX : index.edgeY : horizontal ? index.centreX : index.centreY;
3345
+ const aligned = matching(axis, hit.value, eps);
3346
+ const span = _chunkWADCJ7A7cjs.boundsOf.call(void 0, [out, ...aligned]);
3347
+ guides.push(
3348
+ horizontal ? { orientation: "vertical", kind: hit.kind, x1: hit.value, y1: span.y, x2: hit.value, y2: span.y + span.height } : { orientation: "horizontal", kind: hit.kind, x1: span.x, y1: hit.value, x2: span.x + span.width, y2: hit.value }
3349
+ );
3350
+ };
3351
+ guideFor(true, hitX);
3352
+ guideFor(false, hitY);
3353
+ const changed = out.x !== rect.x || out.y !== rect.y || out.width !== rect.width || out.height !== rect.height;
3354
+ return {
3355
+ rect: out,
3356
+ guides,
3357
+ snappedX: !!hitX && hitX.kind !== "grid",
3358
+ snappedY: !!hitY && hitY.kind !== "grid",
3359
+ changed
3360
+ };
3361
+ }
3362
+ function snapNodeResize(nodes, id, rect, handle, options = {}) {
3363
+ const lookup = createNodeLookup(nodes);
3364
+ const node = lookup.get(id);
3365
+ if (!node || isLocked(node)) {
3366
+ return { rect: { ...rect }, guides: [], snappedX: false, snappedY: false, changed: false, updates: [] };
3367
+ }
3368
+ const index = _nullishCoalesce(options.index, () => ( createNodeGuideIndex(nodes, [id], options)));
3369
+ const result = snapResize(rect, handle, index, options);
3370
+ if (!result.changed) return { ...result, updates: [] };
3371
+ const parent = node.parentId ? lookup.get(node.parentId) : void 0;
3372
+ const origin = parent ? getAbsolutePosition(parent, lookup) : { x: 0, y: 0 };
3373
+ return {
3374
+ ...result,
3375
+ updates: [
3376
+ {
3377
+ id,
3378
+ position: { x: result.rect.x - origin.x, y: result.rect.y - origin.y },
3379
+ width: result.rect.width,
3380
+ height: result.rect.height
3381
+ }
3382
+ ]
3383
+ };
3384
+ }
3385
+ function getResizingNodeRect(node, lookup, options = {}) {
3386
+ const { x, y } = node.parentId ? getAbsolutePosition(node, lookup) : node.position;
3387
+ const size = getNodeSize(node, options);
3388
+ return { x, y, width: _nullishCoalesce(node.width, () => ( size.width)), height: _nullishCoalesce(node.height, () => ( size.height)) };
3389
+ }
3390
+
2879
3391
  // src/canvas/arrangeController.ts
2880
3392
  function createCanvasArrangeController(options) {
2881
3393
  let guides = [];
2882
3394
  let dragIndex = null;
2883
3395
  let dragKey = "";
2884
3396
  let lastSnapped = /* @__PURE__ */ new Map();
2885
- const selectedIds = (ids) => ids ? [...ids] : _nullishCoalesce(_optionalChain([options, 'access', _63 => _63.getSelectedIds, 'optionalCall', _64 => _64()]), () => ( options.getNodes().filter((n) => n.selected).map((n) => n.id)));
3397
+ let resizeId = null;
3398
+ let resizeStart = null;
3399
+ let resizeIndex = null;
3400
+ let lastResized = null;
3401
+ const selectedIds = (ids) => ids ? [...ids] : _nullishCoalesce(_optionalChain([options, 'access', _79 => _79.getSelectedIds, 'optionalCall', _80 => _80()]), () => ( options.getNodes().filter((n) => n.selected).map((n) => n.id)));
2886
3402
  const setGuides = (next) => {
2887
3403
  if (next.length === 0 && guides.length === 0) return;
2888
3404
  guides = next;
2889
- _optionalChain([options, 'access', _65 => _65.onGuidesChange, 'optionalCall', _66 => _66(guides)]);
3405
+ _optionalChain([options, 'access', _81 => _81.onGuidesChange, 'optionalCall', _82 => _82(guides)]);
2890
3406
  };
2891
3407
  function apply(name, updates) {
2892
3408
  if (updates.length === 0) return updates;
@@ -3044,7 +3560,7 @@ function createCanvasArrangeController(options) {
3044
3560
  const result = snapNodeDrag(options.getNodes(), list, {
3045
3561
  ...rect(),
3046
3562
  ...options.guides,
3047
- zoom: _nullishCoalesce(_optionalChain([options, 'access', _67 => _67.getZoom, 'optionalCall', _68 => _68()]), () => ( 1)),
3563
+ zoom: _nullishCoalesce(_optionalChain([options, 'access', _83 => _83.getZoom, 'optionalCall', _84 => _84()]), () => ( 1)),
3048
3564
  index: dragIndex
3049
3565
  });
3050
3566
  lastSnapped = /* @__PURE__ */ new Map();
@@ -3082,7 +3598,7 @@ function createCanvasArrangeController(options) {
3082
3598
  const result = snapNodeDrag(nodes, ids, {
3083
3599
  ...rect(),
3084
3600
  ...options.guides,
3085
- zoom: _nullishCoalesce(_optionalChain([options, 'access', _69 => _69.getZoom, 'optionalCall', _70 => _70()]), () => ( 1)),
3601
+ zoom: _nullishCoalesce(_optionalChain([options, 'access', _85 => _85.getZoom, 'optionalCall', _86 => _86()]), () => ( 1)),
3086
3602
  index: dragIndex
3087
3603
  });
3088
3604
  setGuides(result.guides);
@@ -3098,6 +3614,150 @@ function createCanvasArrangeController(options) {
3098
3614
  return { ...c, position };
3099
3615
  });
3100
3616
  },
3617
+ /**
3618
+ * Starts resize snapping for node `id`: records its box (to tell which handle is
3619
+ * dragged) and caches the snap targets. Optional: `resize` starts lazily.
3620
+ */
3621
+ beginResize(id) {
3622
+ const nodes = options.getNodes();
3623
+ const lookup = createNodeLookup(nodes);
3624
+ const node = lookup.get(id);
3625
+ resizeId = id;
3626
+ resizeStart = node ? getResizingNodeRect(node, lookup, rect()) : null;
3627
+ resizeIndex = createNodeGuideIndex(nodes, [id], rect());
3628
+ lastResized = null;
3629
+ },
3630
+ /**
3631
+ * Snaps node `id` as currently sized in `getNodes()` (call it after the flow wrote the
3632
+ * new size, e.g. SvelteFlow's `NodeResizer` `onResize`, deferred by a microtask) and
3633
+ * writes the snapped box back through `setNodes` (not recorded in history). `handle`
3634
+ * defaults to the one inferred from the edges that moved since `beginResize`. A locked
3635
+ * node is restored to its starting box.
3636
+ */
3637
+ resize(id, handle) {
3638
+ if (resizeId !== id) controller.beginResize(id);
3639
+ const nodes = options.getNodes();
3640
+ const lookup = createNodeLookup(nodes);
3641
+ const node = lookup.get(id);
3642
+ if (!node || !resizeStart) return null;
3643
+ const proposed = getResizingNodeRect(node, lookup, rect());
3644
+ if (isLocked(node)) {
3645
+ const start = resizeStart;
3646
+ const parent = node.parentId ? lookup.get(node.parentId) : void 0;
3647
+ const origin = parent ? getResizingNodeRect(parent, lookup, rect()) : { x: 0, y: 0 };
3648
+ if (proposed.x !== start.x || proposed.y !== start.y || proposed.width !== start.width || proposed.height !== start.height) {
3649
+ options.setNodes(
3650
+ applyNodeUpdates(nodes, [
3651
+ { id, position: { x: start.x - origin.x, y: start.y - origin.y }, width: start.width, height: start.height }
3652
+ ])
3653
+ );
3654
+ }
3655
+ return null;
3656
+ }
3657
+ if ((_nullishCoalesce(options.resizeSnapping, () => ( options.snapping))) === false) return null;
3658
+ const h = _nullishCoalesce(handle, () => ( inferResizeHandle(resizeStart, proposed)));
3659
+ if (!h) {
3660
+ setGuides([]);
3661
+ return null;
3662
+ }
3663
+ const result = snapNodeResize(nodes, id, proposed, h, {
3664
+ ...rect(),
3665
+ ...options.guides,
3666
+ ...options.resize,
3667
+ zoom: _nullishCoalesce(_optionalChain([options, 'access', _87 => _87.getZoom, 'optionalCall', _88 => _88()]), () => ( 1)),
3668
+ index: resizeIndex
3669
+ });
3670
+ lastResized = result.updates.length > 0 ? result : null;
3671
+ if (result.updates.length > 0) options.setNodes(applyNodeUpdates(nodes, result.updates));
3672
+ setGuides(result.guides);
3673
+ return result;
3674
+ },
3675
+ /**
3676
+ * Ends resize snapping: clears guides and re-applies the last snapped box if the flow
3677
+ * wrote the raw pointer size afterwards.
3678
+ */
3679
+ endResize() {
3680
+ const last = lastResized;
3681
+ resizeId = null;
3682
+ resizeStart = null;
3683
+ resizeIndex = null;
3684
+ lastResized = null;
3685
+ setGuides([]);
3686
+ const update = _optionalChain([last, 'optionalAccess', _89 => _89.updates, 'access', _90 => _90[0]]);
3687
+ if (!update) return;
3688
+ const node = options.getNodes().find((n) => n.id === update.id);
3689
+ if (!node) return;
3690
+ const drift = node.position.x !== update.position.x || node.position.y !== update.position.y || node.width !== update.width || node.height !== update.height;
3691
+ if (drift) options.setNodes(applyNodeUpdates(options.getNodes(), [update]));
3692
+ },
3693
+ /**
3694
+ * React Flow style: snaps the `dimensions` (and matching `position`) changes a
3695
+ * `NodeResizer` emits in an `onNodesChange` batch and updates `guides`. The resize-end
3696
+ * change (`resizing: false`) carries the raw pointer size, so the last snapped size is
3697
+ * kept. Resize changes of locked nodes are dropped. Returns the (possibly new) changes.
3698
+ */
3699
+ snapResizeChanges(changes) {
3700
+ const dims = changes.find(
3701
+ (c) => c.type === "dimensions" && typeof c.id === "string" && !!c.dimensions && typeof c.resizing === "boolean"
3702
+ );
3703
+ if (!dims) return changes;
3704
+ const id = dims.id;
3705
+ const nodes = options.getNodes();
3706
+ const lookup = createNodeLookup(nodes);
3707
+ const node = lookup.get(id);
3708
+ const isResizeChange = (c) => c.id === id && (c.type === "dimensions" || c.type === "position");
3709
+ if (node && isLocked(node)) {
3710
+ if (dims.resizing === false) controller.endResize();
3711
+ return changes.filter((c) => !isResizeChange(c));
3712
+ }
3713
+ if (dims.resizing === false) {
3714
+ const last = _optionalChain([lastResized, 'optionalAccess', _91 => _91.updates, 'access', _92 => _92[0]]);
3715
+ lastResized = null;
3716
+ controller.endResize();
3717
+ if (!last || last.id !== id) return changes;
3718
+ return changes.map(
3719
+ (c) => c === dims ? { ...c, dimensions: { width: last.width, height: last.height } } : c
3720
+ );
3721
+ }
3722
+ if (!node || (_nullishCoalesce(options.resizeSnapping, () => ( options.snapping))) === false) return changes;
3723
+ if (resizeId !== id) controller.beginResize(id);
3724
+ if (!resizeStart) return changes;
3725
+ const posChange = changes.find((c) => c.id === id && c.type === "position" && !!c.position);
3726
+ const parent = node.parentId ? lookup.get(node.parentId) : void 0;
3727
+ const origin = parent ? getResizingNodeRect(parent, lookup, rect()) : { x: 0, y: 0 };
3728
+ const position = _nullishCoalesce(_optionalChain([posChange, 'optionalAccess', _93 => _93.position]), () => ( node.position));
3729
+ const proposed = {
3730
+ x: position.x + origin.x,
3731
+ y: position.y + origin.y,
3732
+ width: dims.dimensions.width,
3733
+ height: dims.dimensions.height
3734
+ };
3735
+ const handle = inferResizeHandle(resizeStart, proposed);
3736
+ if (!handle) {
3737
+ setGuides([]);
3738
+ return changes;
3739
+ }
3740
+ const result = snapNodeResize(nodes, id, proposed, handle, {
3741
+ ...rect(),
3742
+ ...options.guides,
3743
+ ...options.resize,
3744
+ zoom: _nullishCoalesce(_optionalChain([options, 'access', _94 => _94.getZoom, 'optionalCall', _95 => _95()]), () => ( 1)),
3745
+ index: resizeIndex
3746
+ });
3747
+ setGuides(result.guides);
3748
+ const update = result.updates[0];
3749
+ lastResized = update ? result : null;
3750
+ if (!update) return changes;
3751
+ const next = changes.map((c) => {
3752
+ if (c === dims) return { ...c, dimensions: { width: update.width, height: update.height } };
3753
+ if (c === posChange) return { ...c, position: update.position };
3754
+ return c;
3755
+ });
3756
+ if (!posChange && (update.position.x !== node.position.x || update.position.y !== node.position.y)) {
3757
+ next.push({ id, type: "position", position: update.position });
3758
+ }
3759
+ return next;
3760
+ },
3101
3761
  /**
3102
3762
  * Clears guides and the cached snap targets. Call it from the flow's drag-stop
3103
3763
  * handler: flow libraries write the raw pointer position when a drag ends, so the
@@ -3123,6 +3783,142 @@ function createCanvasArrangeController(options) {
3123
3783
  return controller;
3124
3784
  }
3125
3785
 
3786
+ // src/canvas/measure.ts
3787
+ var EPS = 1e-6;
3788
+ function measureLabel(distance) {
3789
+ const v = Math.round(Math.abs(distance) * 100) / 100;
3790
+ return Object.is(v, -0) ? "0" : String(v);
3791
+ }
3792
+ var toBox = (r) => ({ x0: r.x, y0: r.y, x1: r.x + r.width, y1: r.y + r.height });
3793
+ var finiteBox = (b) => [b.x0, b.y0, b.x1, b.y1].every(Number.isFinite);
3794
+ function line(kind, x1, y1, x2, y2) {
3795
+ return { orientation: x1 === x2 ? "vertical" : "horizontal", kind, x1, y1, x2, y2 };
3796
+ }
3797
+ function measured(out, x1, y1, x2, y2) {
3798
+ const d = Math.hypot(x2 - x1, y2 - y1);
3799
+ if (d > EPS && Number.isFinite(d)) out.push({ ...line("measure", x1, y1, x2, y2), label: measureLabel(d) });
3800
+ }
3801
+ function extension(out, x1, y1, x2, y2) {
3802
+ if (Math.hypot(x2 - x1, y2 - y1) > EPS) out.push(line("extension", x1, y1, x2, y2));
3803
+ }
3804
+ function contains(outer, inner) {
3805
+ return outer.x0 <= inner.x0 + EPS && outer.y0 <= inner.y0 + EPS && outer.x1 >= inner.x1 - EPS && outer.y1 >= inner.y1 - EPS;
3806
+ }
3807
+ function overlapMid(a0, a1, b0, b1) {
3808
+ const lo = Math.max(a0, b0);
3809
+ const hi = Math.min(a1, b1);
3810
+ return lo <= hi ? (lo + hi) / 2 : null;
3811
+ }
3812
+ function inside(out, inner, outer) {
3813
+ const cx = (inner.x0 + inner.x1) / 2;
3814
+ const cy = (inner.y0 + inner.y1) / 2;
3815
+ measured(out, outer.x0, cy, inner.x0, cy);
3816
+ measured(out, inner.x1, cy, outer.x1, cy);
3817
+ measured(out, cx, outer.y0, cx, inner.y0);
3818
+ measured(out, cx, inner.y1, cx, outer.y1);
3819
+ }
3820
+ function measureBetween(a, b) {
3821
+ const out = [];
3822
+ const A = toBox(a);
3823
+ const B = toBox(b);
3824
+ if (!finiteBox(A) || !finiteBox(B)) return out;
3825
+ if (contains(B, A)) {
3826
+ inside(out, A, B);
3827
+ return out;
3828
+ }
3829
+ if (contains(A, B)) {
3830
+ inside(out, B, A);
3831
+ return out;
3832
+ }
3833
+ const ox = overlapMid(A.x0, A.x1, B.x0, B.x1);
3834
+ const oy = overlapMid(A.y0, A.y1, B.y0, B.y1);
3835
+ const overlapping = A.x0 < B.x1 && B.x0 < A.x1 && A.y0 < B.y1 && B.y0 < A.y1;
3836
+ if (overlapping && ox !== null && oy !== null) {
3837
+ measured(out, A.x0, oy, B.x0, oy);
3838
+ measured(out, A.x1, oy, B.x1, oy);
3839
+ measured(out, ox, A.y0, ox, B.y0);
3840
+ measured(out, ox, A.y1, ox, B.y1);
3841
+ return out;
3842
+ }
3843
+ const cx = (A.x0 + A.x1) / 2;
3844
+ const cy = (A.y0 + A.y1) / 2;
3845
+ const gapX = B.x0 >= A.x1 ? [A.x1, B.x0] : B.x1 <= A.x0 ? [A.x0, B.x1] : null;
3846
+ if (gapX) {
3847
+ const [from, to] = gapX;
3848
+ const y = _nullishCoalesce(oy, () => ( cy));
3849
+ measured(out, from, y, to, y);
3850
+ if (oy === null) extension(out, to, y, to, y < B.y0 ? B.y0 : B.y1);
3851
+ }
3852
+ const gapY = B.y0 >= A.y1 ? [A.y1, B.y0] : B.y1 <= A.y0 ? [A.y0, B.y1] : null;
3853
+ if (gapY) {
3854
+ const [from, to] = gapY;
3855
+ const x = _nullishCoalesce(ox, () => ( cx));
3856
+ measured(out, x, from, x, to);
3857
+ if (ox === null) extension(out, x, to, x < B.x0 ? B.x0 : B.x1, to);
3858
+ }
3859
+ return out;
3860
+ }
3861
+ function measureToLine(a, orientation, at) {
3862
+ const out = [];
3863
+ const A = toBox(a);
3864
+ if (!finiteBox(A) || !Number.isFinite(at)) return out;
3865
+ const vertical = orientation === "vertical";
3866
+ const cx = (A.x0 + A.x1) / 2;
3867
+ const cy = (A.y0 + A.y1) / 2;
3868
+ const [lo, hi] = vertical ? [A.x0, A.x1] : [A.y0, A.y1];
3869
+ const seg = (from, to) => vertical ? measured(out, from, cy, to, cy) : measured(out, cx, from, cx, to);
3870
+ if (at >= hi) seg(hi, at);
3871
+ else if (at <= lo) seg(at, lo);
3872
+ else {
3873
+ seg(lo, at);
3874
+ seg(at, hi);
3875
+ }
3876
+ return out;
3877
+ }
3878
+ function measureSelection(nodes, selectedIds, hoveredId, options = {}) {
3879
+ const none = (selection2 = null) => ({ guides: [], target: null, selection: selection2 });
3880
+ const lookup = createNodeLookup(nodes);
3881
+ const selected = [...new Set(selectedIds)].map((id) => lookup.get(id)).filter((n) => !!n && n.hidden !== true);
3882
+ if (selected.length === 0) return none();
3883
+ const selection = _chunkWADCJ7A7cjs.boundsOf.call(void 0, selected.map((n) => getNodeRect(n, lookup, options)));
3884
+ if (!selection) return none();
3885
+ const selectedSet = new Set(selected.map((n) => n.id));
3886
+ let targetId = _nullishCoalesce(hoveredId, () => ( null));
3887
+ if (targetId === null || selectedSet.has(targetId)) {
3888
+ const parentId = selected[0].parentId;
3889
+ const sameParent = selected.every((n) => n.parentId === parentId);
3890
+ targetId = parentId && sameParent && !selectedSet.has(parentId) ? parentId : null;
3891
+ }
3892
+ const target = targetId !== null ? lookup.get(targetId) : void 0;
3893
+ if (!target || target.hidden === true) return none(selection);
3894
+ const rect = getNodeRect(target, lookup, options);
3895
+ return { guides: measureBetween(selection, rect), target: rect, selection };
3896
+ }
3897
+ function isMeasureModifierHeld(event) {
3898
+ if (!event) return false;
3899
+ if (event.type === "keyup" && event.key === "Alt") return false;
3900
+ return event.altKey === true || event.type === "keydown" && event.key === "Alt";
3901
+ }
3902
+
3903
+
3904
+
3905
+
3906
+
3907
+
3908
+
3909
+
3910
+
3911
+
3912
+
3913
+
3914
+
3915
+
3916
+
3917
+
3918
+
3919
+
3920
+
3921
+
3126
3922
 
3127
3923
 
3128
3924
 
@@ -3234,5 +4030,5 @@ function createCanvasArrangeController(options) {
3234
4030
 
3235
4031
 
3236
4032
 
3237
- 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.SHAPE_DATA_KEY = SHAPE_DATA_KEY; exports.SHAPE_KINDS = SHAPE_KINDS; exports.SHAPE_NODE_TYPE = SHAPE_NODE_TYPE; exports.SHAPE_OPERATIONS = SHAPE_OPERATIONS; exports.StreamingLayoutManager = StreamingLayoutManager; exports.alignNodes = alignNodes; exports.applyNodeUpdates = applyNodeUpdates; exports.applyShapeCombination = applyShapeCombination; exports.blendLayout = blendLayout; exports.boundsOf = _chunkWADCJ7A7cjs.boundsOf; exports.calculateDagreReflowDisplacement = calculateDagreReflowDisplacement; exports.calculateDirectionalDisplacement = calculateDirectionalDisplacement; exports.canCombineShapeNodes = canCombineShapeNodes; exports.canvasHeight = canvasHeight; exports.centerNodes = _chunkWADCJ7A7cjs.centerNodes; exports.centre = _chunkWADCJ7A7cjs.centre; exports.collectDescendantIds = collectDescendantIds; exports.combineShapeNodes = combineShapeNodes; 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.dividePolygons = dividePolygons; exports.ensureLayout = _chunkWADCJ7A7cjs.ensureLayout; exports.estimateCanvasHeight = estimateCanvasHeight; exports.estimateNodeSize = _chunkWADCJ7A7cjs.estimateNodeSize; exports.findConnectorSnap = findConnectorSnap; exports.fitViewportToNodes = fitViewportToNodes; exports.fitViewportToRect = fitViewportToRect; exports.flattenSvgPath = flattenSvgPath; exports.flowSide = _chunkWADCJ7A7cjs.flowSide; exports.formatNumber = formatNumber; exports.getAbsolutePosition = getAbsolutePosition; exports.getCenteredNodePosition = _chunkWADCJ7A7cjs.getCenteredNodePosition; exports.getLayoutedNodes = _chunkWADCJ7A7cjs.getLayoutedNodes; exports.getNodeRect = getNodeRect; exports.getNodeShape = getNodeShape; exports.getNodeSize = getNodeSize; exports.getShapeRenderData = getShapeRenderData; exports.getShapeSvg = getShapeSvg; exports.handlePoint = handlePoint; exports.intersectPolygons = intersectPolygons; exports.invertNodeUpdates = invertNodeUpdates; exports.isEventFromTextInput = isEventFromTextInput; exports.isLocked = isLocked; exports.isShapeDescription = isShapeDescription; exports.isShapeNode = isShapeNode; 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.multiPolygonArea = multiPolygonArea; exports.multiPolygonBounds = multiPolygonBounds; exports.nearestHandlePositions = nearestHandlePositions; exports.oppositePosition = oppositePosition; exports.overlaps = _chunkWADCJ7A7cjs.overlaps; exports.pageHidden = pageHidden; exports.parseCanvasClipboardData = parseCanvasClipboardData; exports.parseCanvasScenes = parseCanvasScenes; exports.parseSvgPath = parseSvgPath; exports.placeBeside = _chunkWADCJ7A7cjs.placeBeside; exports.pointInMultiPolygon = pointInMultiPolygon; exports.pointInRings = pointInRings; exports.polygonArea = polygonArea; exports.polygonBoolean = polygonBoolean; exports.polygonToSvgPath = polygonToSvgPath; exports.positionToSide = positionToSide; exports.readStyleSize = readStyleSize; exports.realClock = realClock; exports.remapPastedNodes = remapPastedNodes; exports.reorderNodes = reorderNodes; exports.repositionNodesTo = repositionNodesTo; exports.revertShapeCombination = revertShapeCombination; exports.ringSignedArea = ringSignedArea; exports.runMultiNodeTransition = runMultiNodeTransition; exports.serializeCanvasNodes = serializeCanvasNodes; exports.shapeNodeToPolygon = shapeNodeToPolygon; exports.shapeToPolygon = shapeToPolygon; exports.sideToPosition = sideToPosition; exports.simplifyRing = simplifyRing; exports.snapNodeDrag = snapNodeDrag; exports.subtractPolygons = subtractPolygons; exports.toggleLockNodes = toggleLockNodes; exports.unionPolygons = unionPolygons; exports.unlockNodes = unlockNodes; exports.withStyleOpacity = withStyleOpacity; exports.withStyleSize = withStyleSize; exports.xorPolygons = xorPolygons;
4033
+ exports.CONNECTION_LINE_TYPES = CONNECTION_LINE_TYPES; exports.CanvasScenesStore = CanvasScenesStore; exports.DEFAULT_ARRANGE_SHORTCUTS = _chunk26BVFKHUcjs.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.RESIZE_HANDLES = RESIZE_HANDLES; exports.SHAPE_DATA_KEY = SHAPE_DATA_KEY; exports.SHAPE_KINDS = SHAPE_KINDS; exports.SHAPE_NODE_TYPE = SHAPE_NODE_TYPE; exports.SHAPE_OPERATIONS = SHAPE_OPERATIONS; exports.StreamingLayoutManager = StreamingLayoutManager; exports.alignNodes = alignNodes; exports.applyNodeUpdates = applyNodeUpdates; exports.applyShapeCombination = applyShapeCombination; exports.blendLayout = blendLayout; exports.boundsOf = _chunkWADCJ7A7cjs.boundsOf; exports.calculateDagreReflowDisplacement = calculateDagreReflowDisplacement; exports.calculateDirectionalDisplacement = calculateDirectionalDisplacement; exports.canCombineShapeNodes = canCombineShapeNodes; exports.canvasHeight = canvasHeight; exports.centerNodes = _chunkWADCJ7A7cjs.centerNodes; exports.centre = _chunkWADCJ7A7cjs.centre; exports.collectDescendantIds = collectDescendantIds; exports.combineShapeNodes = combineShapeNodes; 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.cubicPointAt = cubicPointAt; exports.cubicsToPathData = cubicsToPathData; exports.defaultEasing = defaultEasing; exports.distributeNodes = distributeNodes; exports.dividePolygons = dividePolygons; exports.ensureLayout = _chunkWADCJ7A7cjs.ensureLayout; exports.estimateCanvasHeight = estimateCanvasHeight; exports.estimateNodeSize = _chunkWADCJ7A7cjs.estimateNodeSize; exports.findConnectorSnap = findConnectorSnap; exports.fitCubicRun = fitCubicRun; exports.fitCubics = fitCubics; exports.fitFreehandPath = fitFreehandPath; exports.fitPathData = fitPathData; exports.fitViewportToNodes = fitViewportToNodes; exports.fitViewportToRect = fitViewportToRect; exports.flattenSvgPath = flattenSvgPath; exports.flowSide = _chunkWADCJ7A7cjs.flowSide; exports.formatNumber = formatNumber2; exports.getAbsolutePosition = getAbsolutePosition; exports.getCenteredNodePosition = _chunkWADCJ7A7cjs.getCenteredNodePosition; exports.getLayoutedNodes = _chunkWADCJ7A7cjs.getLayoutedNodes; exports.getNodeRect = getNodeRect; exports.getNodeShape = getNodeShape; exports.getNodeSize = getNodeSize; exports.getResizingNodeRect = getResizingNodeRect; exports.getShapeRenderData = getShapeRenderData; exports.getShapeSvg = getShapeSvg; exports.handlePoint = handlePoint; exports.inferResizeHandle = inferResizeHandle; exports.intersectPolygons = intersectPolygons; exports.invertNodeUpdates = invertNodeUpdates; exports.isEventFromTextInput = isEventFromTextInput; exports.isLocked = isLocked; exports.isMeasureModifierHeld = isMeasureModifierHeld; exports.isShapeDescription = isShapeDescription; exports.isShapeNode = isShapeNode; exports.isStraightCubic = isStraightCubic; 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 = _chunk26BVFKHUcjs.matchArrangeShortcut; exports.matchSize = matchSize; exports.measureBetween = measureBetween; exports.measureLabel = measureLabel; exports.measureSelection = measureSelection; exports.measureToLine = measureToLine; exports.multiPolygonArea = multiPolygonArea; exports.multiPolygonBounds = multiPolygonBounds; exports.nearestHandlePositions = nearestHandlePositions; exports.oppositePosition = oppositePosition; exports.overlaps = _chunkWADCJ7A7cjs.overlaps; exports.pageHidden = pageHidden; exports.parseCanvasClipboardData = parseCanvasClipboardData; exports.parseCanvasScenes = parseCanvasScenes; exports.parseSvgPath = parseSvgPath; exports.placeBeside = _chunkWADCJ7A7cjs.placeBeside; exports.pointInMultiPolygon = pointInMultiPolygon; exports.pointInRings = pointInRings; exports.polygonArea = polygonArea; exports.polygonBoolean = polygonBoolean; exports.polygonToSvgPath = polygonToSvgPath; exports.positionToSide = positionToSide; exports.readStyleSize = readStyleSize; exports.realClock = realClock; exports.remapPastedNodes = remapPastedNodes; exports.reorderNodes = reorderNodes; exports.repositionNodesTo = repositionNodesTo; exports.resizeHandleAxes = resizeHandleAxes; exports.revertShapeCombination = revertShapeCombination; exports.ringSignedArea = ringSignedArea; exports.runMultiNodeTransition = runMultiNodeTransition; exports.serializeCanvasNodes = serializeCanvasNodes; exports.shapeNodeToPolygon = shapeNodeToPolygon; exports.shapeToPolygon = shapeToPolygon; exports.sideToPosition = sideToPosition; exports.simplifyRing = simplifyRing; exports.snapNodeDrag = snapNodeDrag; exports.snapNodeResize = snapNodeResize; exports.snapResize = snapResize; exports.snapToGrid = snapToGrid; exports.subtractPolygons = subtractPolygons; exports.toggleLockNodes = toggleLockNodes; exports.unionPolygons = unionPolygons; exports.unlockNodes = unlockNodes; exports.withStyleOpacity = withStyleOpacity; exports.withStyleSize = withStyleSize; exports.xorPolygons = xorPolygons;
3238
4034
  //# sourceMappingURL=index.cjs.map