@pixerate/editor 0.24.0 → 0.25.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 (133) hide show
  1. package/README.md +71 -1
  2. package/THIRD_PARTY_NOTICES.md +29 -0
  3. package/dist/agent/index.cjs +10 -9
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +1 -1
  6. package/dist/agent/index.d.ts +1 -1
  7. package/dist/agent/index.js +4 -3
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/canvas/index.cjs +3173 -340
  10. package/dist/canvas/index.cjs.map +1 -1
  11. package/dist/canvas/index.d.cts +617 -4
  12. package/dist/canvas/index.d.ts +617 -4
  13. package/dist/canvas/index.js +3105 -272
  14. package/dist/canvas/index.js.map +1 -1
  15. package/dist/chunk-4BVP64JJ.cjs +1406 -0
  16. package/dist/chunk-4BVP64JJ.cjs.map +1 -0
  17. package/dist/{chunk-XNORY7M6.cjs → chunk-7WISYZFO.cjs} +105 -50
  18. package/dist/chunk-7WISYZFO.cjs.map +1 -0
  19. package/dist/{chunk-OLZJXL4R.cjs → chunk-AL6JMGWW.cjs} +59 -25
  20. package/dist/chunk-AL6JMGWW.cjs.map +1 -0
  21. package/dist/chunk-BVP3TSLH.cjs +69 -0
  22. package/dist/chunk-BVP3TSLH.cjs.map +1 -0
  23. package/dist/{chunk-MCSJFWAO.cjs → chunk-C7P22VIP.cjs} +670 -96
  24. package/dist/chunk-C7P22VIP.cjs.map +1 -0
  25. package/dist/{chunk-PGNZKFQS.js → chunk-ECCCYKGL.js} +76 -21
  26. package/dist/chunk-ECCCYKGL.js.map +1 -0
  27. package/dist/{chunk-3CN2WD3X.js → chunk-FH6F67DN.js} +646 -72
  28. package/dist/chunk-FH6F67DN.js.map +1 -0
  29. package/dist/chunk-HRMEDT2L.js +1406 -0
  30. package/dist/chunk-HRMEDT2L.js.map +1 -0
  31. package/dist/{chunk-ITBSKI26.js → chunk-IXHSYOVY.js} +941 -9
  32. package/dist/chunk-IXHSYOVY.js.map +1 -0
  33. package/dist/{chunk-FODNLX5N.js → chunk-NAXVVS5I.js} +38 -4
  34. package/dist/chunk-NAXVVS5I.js.map +1 -0
  35. package/dist/chunk-O5RYH2PG.js +69 -0
  36. package/dist/chunk-O5RYH2PG.js.map +1 -0
  37. package/dist/{chunk-SBCZ6RN5.cjs → chunk-PO6A6QQH.cjs} +1039 -107
  38. package/dist/chunk-PO6A6QQH.cjs.map +1 -0
  39. package/dist/{chunk-3LV6RRPH.js → chunk-QGYDWPRM.js} +2 -2
  40. package/dist/{chunk-U5KWZU4X.js → chunk-RR7F5GUM.js} +2632 -129
  41. package/dist/chunk-RR7F5GUM.js.map +1 -0
  42. package/dist/{chunk-5S3Z4PPF.js → chunk-UAKDG62Z.js} +232 -25
  43. package/dist/chunk-UAKDG62Z.js.map +1 -0
  44. package/dist/{chunk-SML64VJG.cjs → chunk-V3CHHWOE.cjs} +4 -4
  45. package/dist/{chunk-SML64VJG.cjs.map → chunk-V3CHHWOE.cjs.map} +1 -1
  46. package/dist/chunk-WSQKHXW7.cjs +5726 -0
  47. package/dist/chunk-WSQKHXW7.cjs.map +1 -0
  48. package/dist/{chunk-D27YFC46.cjs → chunk-X4N4WUKB.cjs} +267 -60
  49. package/dist/chunk-X4N4WUKB.cjs.map +1 -0
  50. package/dist/commands/index.cjs +74 -1
  51. package/dist/commands/index.cjs.map +1 -1
  52. package/dist/commands/index.d.cts +34 -1
  53. package/dist/commands/index.d.ts +34 -1
  54. package/dist/commands/index.js +73 -0
  55. package/dist/commands/index.js.map +1 -1
  56. package/dist/compare/index.cjs +3 -3
  57. package/dist/compare/index.d.cts +1 -1
  58. package/dist/compare/index.d.ts +1 -1
  59. package/dist/compare/index.js +2 -2
  60. package/dist/controller-BIJiNoVs.d.cts +1842 -0
  61. package/dist/controller-BIJiNoVs.d.ts +1842 -0
  62. package/dist/{documents-BQjzJNe2.d.ts → documents-CHT1U5Vs.d.ts} +10 -0
  63. package/dist/{documents-KRTPhvst.d.cts → documents-Gp7wb0Me.d.cts} +10 -0
  64. package/dist/extensions/index.cjs +53 -6
  65. package/dist/extensions/index.cjs.map +1 -1
  66. package/dist/extensions/index.d.cts +12 -4
  67. package/dist/extensions/index.d.ts +12 -4
  68. package/dist/extensions/index.js +53 -6
  69. package/dist/generation/index.cjs +1013 -69
  70. package/dist/generation/index.cjs.map +1 -1
  71. package/dist/generation/index.d.cts +474 -13
  72. package/dist/generation/index.d.ts +474 -13
  73. package/dist/generation/index.js +976 -32
  74. package/dist/generation/index.js.map +1 -1
  75. package/dist/image-editor/index.cjs +3385 -1275
  76. package/dist/image-editor/index.cjs.map +1 -1
  77. package/dist/image-editor/index.d.cts +693 -128
  78. package/dist/image-editor/index.d.ts +693 -128
  79. package/dist/image-editor/index.js +3325 -1215
  80. package/dist/image-editor/index.js.map +1 -1
  81. package/dist/{index-fJrlkJCd.d.ts → index-7a6bHTLy.d.ts} +494 -5
  82. package/dist/{index-BhJBSm2d.d.cts → index-Csd5qI8u.d.cts} +494 -5
  83. package/dist/index.cjs +1491 -45
  84. package/dist/index.cjs.map +1 -1
  85. package/dist/index.d.cts +110 -19
  86. package/dist/index.d.ts +110 -19
  87. package/dist/index.js +1464 -18
  88. package/dist/index.js.map +1 -1
  89. package/dist/mention-text-CDnCFd3c.d.cts +53 -0
  90. package/dist/mention-text-CDnCFd3c.d.ts +53 -0
  91. package/dist/model-C1zApQM8.d.cts +219 -0
  92. package/dist/model-C1zApQM8.d.ts +219 -0
  93. package/dist/persistence/index.d.cts +3 -120
  94. package/dist/persistence/index.d.ts +3 -120
  95. package/dist/{registry-GJI4gToU.d.cts → registry-CEgwXED1.d.cts} +12 -1
  96. package/dist/{registry-GJI4gToU.d.ts → registry-CEgwXED1.d.ts} +12 -1
  97. package/dist/serializers/index.cjs +12 -4
  98. package/dist/serializers/index.cjs.map +1 -1
  99. package/dist/serializers/index.d.cts +39 -12
  100. package/dist/serializers/index.d.ts +39 -12
  101. package/dist/serializers/index.js +12 -4
  102. package/dist/spreadsheet/index.cjs +127 -3
  103. package/dist/spreadsheet/index.cjs.map +1 -1
  104. package/dist/spreadsheet/index.d.cts +431 -11
  105. package/dist/spreadsheet/index.d.ts +431 -11
  106. package/dist/spreadsheet/index.js +127 -3
  107. package/dist/storage-BpFfspHm.d.cts +120 -0
  108. package/dist/storage-BpFfspHm.d.ts +120 -0
  109. package/dist/tokens/index.cjs +115 -0
  110. package/dist/tokens/index.cjs.map +1 -0
  111. package/dist/tokens/index.d.cts +212 -0
  112. package/dist/tokens/index.d.ts +212 -0
  113. package/dist/tokens/index.js +115 -0
  114. package/dist/tokens/index.js.map +1 -0
  115. package/dist/{track-changes-BK5sVf4_.d.cts → track-changes-D_VAPELi.d.cts} +95 -11
  116. package/dist/{track-changes-CDjCrwKe.d.ts → track-changes-Db_fGEvx.d.ts} +95 -11
  117. package/package.json +6 -1
  118. package/dist/chunk-3CN2WD3X.js.map +0 -1
  119. package/dist/chunk-5S3Z4PPF.js.map +0 -1
  120. package/dist/chunk-D27YFC46.cjs.map +0 -1
  121. package/dist/chunk-FODNLX5N.js.map +0 -1
  122. package/dist/chunk-ITBSKI26.js.map +0 -1
  123. package/dist/chunk-MA2F5KHF.cjs +0 -3223
  124. package/dist/chunk-MA2F5KHF.cjs.map +0 -1
  125. package/dist/chunk-MCSJFWAO.cjs.map +0 -1
  126. package/dist/chunk-OLZJXL4R.cjs.map +0 -1
  127. package/dist/chunk-PGNZKFQS.js.map +0 -1
  128. package/dist/chunk-SBCZ6RN5.cjs.map +0 -1
  129. package/dist/chunk-U5KWZU4X.js.map +0 -1
  130. package/dist/chunk-XNORY7M6.cjs.map +0 -1
  131. package/dist/controller-BhLLAoi8.d.cts +0 -1000
  132. package/dist/controller-BhLLAoi8.d.ts +0 -1000
  133. /package/dist/{chunk-3LV6RRPH.js.map → chunk-QGYDWPRM.js.map} +0 -0
@@ -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; var _class3; var _class4; var _class5; var _class6;
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; var _class6; var _class7;
2
2
 
3
3
 
4
4
  var _chunk26BVFKHUcjs = require('../chunk-26BVFKHU.cjs');
@@ -8,6 +8,13 @@ var _chunk26BVFKHUcjs = require('../chunk-26BVFKHU.cjs');
8
8
 
9
9
 
10
10
 
11
+ var _chunk4BVP64JJcjs = require('../chunk-4BVP64JJ.cjs');
12
+
13
+
14
+
15
+
16
+
17
+
11
18
 
12
19
 
13
20
 
@@ -129,11 +136,11 @@ function createFanOutTrajectory(options = {}) {
129
136
  const oneMinusT = 1 - t;
130
137
  const x = oneMinusT * oneMinusT * origin.x + 2 * oneMinusT * t * midX + t * t * target.x;
131
138
  const y = oneMinusT * oneMinusT * origin.y + 2 * oneMinusT * t * midY + t * t * target.y;
132
- const scale = startScale + (endScale - startScale) * progress;
139
+ const scale2 = startScale + (endScale - startScale) * progress;
133
140
  const opacity = startOpacity + (endOpacity - startOpacity) * progress;
134
141
  return {
135
142
  position: { x, y },
136
- scale,
143
+ scale: scale2,
137
144
  opacity
138
145
  };
139
146
  };
@@ -447,7 +454,7 @@ function isValidUrl(url) {
447
454
  try {
448
455
  const parsed = new URL(url);
449
456
  return parsed.protocol === "http:" || parsed.protocol === "https:";
450
- } catch (e2) {
457
+ } catch (e3) {
451
458
  return false;
452
459
  }
453
460
  }
@@ -466,7 +473,7 @@ function parseCanvasClipboardData(raw) {
466
473
  const edges = Array.isArray(parsed.edges) ? parsed.edges.filter(isValidCanvasEdge) : void 0;
467
474
  return { ...parsed, edges };
468
475
  }
469
- } catch (e3) {
476
+ } catch (e4) {
470
477
  }
471
478
  return null;
472
479
  }
@@ -1160,7 +1167,7 @@ function spacingCandidate(rects, moving, horizontal, tolerance) {
1160
1167
  return best2;
1161
1168
  };
1162
1169
  const crossMid = (a, b) => (Math.max(crossStart(a), crossStart(b)) + Math.min(crossEnd(a), crossEnd(b))) / 2;
1163
- 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 };
1170
+ const segment = (from, to, cross2) => horizontal ? { orientation: "horizontal", kind: "spacing", x1: from, y1: cross2, x2: to, y2: cross2 } : { orientation: "vertical", kind: "spacing", x1: cross2, y1: from, x2: cross2, y2: to };
1164
1171
  const candidates = [];
1165
1172
  if (before && after) {
1166
1173
  const b = before;
@@ -1474,7 +1481,7 @@ function parseCanvasScenes(input) {
1474
1481
  if (typeof input === "string") {
1475
1482
  try {
1476
1483
  value = JSON.parse(input);
1477
- } catch (e4) {
1484
+ } catch (e5) {
1478
1485
  return [];
1479
1486
  }
1480
1487
  }
@@ -1717,7 +1724,7 @@ function multiPolygonBounds(input) {
1717
1724
  return minX === Infinity ? null : { minX, minY, maxX, maxY };
1718
1725
  }
1719
1726
  function pointInRings(point, rings, fillRule = "nonzero") {
1720
- const [px, py] = point;
1727
+ const [px2, py] = point;
1721
1728
  let winding = 0;
1722
1729
  for (const ring of rings) {
1723
1730
  const n = ring.length;
@@ -1725,9 +1732,9 @@ function pointInRings(point, rings, fillRule = "nonzero") {
1725
1732
  const [ax, ay] = ring[i];
1726
1733
  const [bx, by] = ring[(i + 1) % n];
1727
1734
  if (ay <= py && by > py) {
1728
- if (ax + (py - ay) / (by - ay) * (bx - ax) > px) winding++;
1735
+ if (ax + (py - ay) / (by - ay) * (bx - ax) > px2) winding++;
1729
1736
  } else if (by <= py && ay > py) {
1730
- if (ax + (py - ay) / (by - ay) * (bx - ax) > px) winding--;
1737
+ if (ax + (py - ay) / (by - ay) * (bx - ax) > px2) winding--;
1731
1738
  }
1732
1739
  }
1733
1740
  }
@@ -1852,9 +1859,9 @@ function splitPass(segments, pool, eps) {
1852
1859
  ]) {
1853
1860
  for (const p of [other.a, other.b]) {
1854
1861
  if (p.id === seg.a.id || p.id === seg.b.id) continue;
1855
- const { t: t2, dist: dist2 } = project(seg.a, seg.b, p);
1862
+ const { t: t2, dist: dist3 } = project(seg.a, seg.b, p);
1856
1863
  const len = Math.hypot(seg.b.x - seg.a.x, seg.b.y - seg.a.y);
1857
- if (dist2 <= eps && t2 * len > eps && (1 - t2) * len > eps) {
1864
+ if (dist3 <= eps && t2 * len > eps && (1 - t2) * len > eps) {
1858
1865
  addSplit(split, t2, p);
1859
1866
  touched = true;
1860
1867
  }
@@ -1988,14 +1995,14 @@ function buildOverlay(inputs, options) {
1988
1995
  function insideFlags(windings, fillRules) {
1989
1996
  return windings.map((w, k) => fillRules[k] === "evenodd" ? (w & 1) === 1 : w !== 0);
1990
1997
  }
1991
- function traceRings(directed) {
1998
+ function traceRings(directed2) {
1992
1999
  const outgoing = /* @__PURE__ */ new Map();
1993
- for (const e of directed) {
2000
+ for (const e of directed2) {
1994
2001
  const list = outgoing.get(e.from.id);
1995
2002
  if (list) list.push(e);
1996
2003
  else outgoing.set(e.from.id, [e]);
1997
2004
  }
1998
- const TWO_PI = Math.PI * 2;
2005
+ const TWO_PI2 = Math.PI * 2;
1999
2006
  const next = (incoming) => {
2000
2007
  const candidates = outgoing.get(incoming.to.id);
2001
2008
  if (!candidates) return void 0;
@@ -2004,8 +2011,8 @@ function traceRings(directed) {
2004
2011
  let bestTurn = Infinity;
2005
2012
  for (const c of candidates) {
2006
2013
  let turn = back - c.angle;
2007
- turn -= Math.floor(turn / TWO_PI) * TWO_PI;
2008
- if (turn <= 1e-15) turn = TWO_PI;
2014
+ turn -= Math.floor(turn / TWO_PI2) * TWO_PI2;
2015
+ if (turn <= 1e-15) turn = TWO_PI2;
2009
2016
  if (turn < bestTurn) {
2010
2017
  bestTurn = turn;
2011
2018
  best = c;
@@ -2015,11 +2022,11 @@ function traceRings(directed) {
2015
2022
  };
2016
2023
  const used = /* @__PURE__ */ new Set();
2017
2024
  const rings = [];
2018
- for (const start of directed) {
2025
+ for (const start of directed2) {
2019
2026
  if (used.has(start)) continue;
2020
2027
  const ring = [];
2021
2028
  let edge = start;
2022
- let guard = directed.length + 1;
2029
+ let guard = directed2.length + 1;
2023
2030
  while (edge && !used.has(edge) && guard-- > 0) {
2024
2031
  used.add(edge);
2025
2032
  ring.push(edge.from);
@@ -2043,9 +2050,9 @@ function removeCollinear(ring, eps) {
2043
2050
  const dx = nxt[0] - prev[0];
2044
2051
  const dy = nxt[1] - prev[1];
2045
2052
  const len = Math.hypot(dx, dy);
2046
- const cross = (cur[0] - prev[0]) * dy - (cur[1] - prev[1]) * dx;
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) {
2053
+ const cross2 = (cur[0] - prev[0]) * dy - (cur[1] - prev[1]) * dx;
2054
+ const dot3 = (cur[0] - prev[0]) * dx + (cur[1] - prev[1]) * dy;
2055
+ if (len > 0 && Math.abs(cross2) / len <= eps && dot3 > 0 && dot3 < len * len) {
2049
2056
  changed = true;
2050
2057
  continue;
2051
2058
  }
@@ -2087,15 +2094,15 @@ function assemble(rings, eps) {
2087
2094
  return polygons;
2088
2095
  }
2089
2096
  function extract(overlay, isInside) {
2090
- const directed = [];
2097
+ const directed2 = [];
2091
2098
  overlay.edges.forEach((edge, i) => {
2092
2099
  const l = isInside(insideFlags(overlay.left[i], overlay.fillRules));
2093
2100
  const r = isInside(insideFlags(overlay.right[i], overlay.fillRules));
2094
2101
  if (l === r) return;
2095
2102
  const [from, to] = l ? [edge.a, edge.b] : [edge.b, edge.a];
2096
- directed.push({ from, to, angle: Math.atan2(to.y - from.y, to.x - from.x) });
2103
+ directed2.push({ from, to, angle: Math.atan2(to.y - from.y, to.x - from.x) });
2097
2104
  });
2098
- return assemble(traceRings(directed), overlay.eps);
2105
+ return assemble(traceRings(directed2), overlay.eps);
2099
2106
  }
2100
2107
  function predicate(operation) {
2101
2108
  switch (operation) {
@@ -2978,9 +2985,9 @@ function rdp(points, tolerance) {
2978
2985
  let maxDist = -1;
2979
2986
  let index = -1;
2980
2987
  for (let i = s + 1; i < e; i++) {
2981
- const dist2 = segmentDistance(points[i], points[s], points[e]);
2982
- if (dist2 > maxDist) {
2983
- maxDist = dist2;
2988
+ const dist3 = segmentDistance(points[i], points[s], points[e]);
2989
+ if (dist3 > maxDist) {
2990
+ maxDist = dist3;
2984
2991
  index = i;
2985
2992
  }
2986
2993
  }
@@ -2996,9 +3003,9 @@ function simplifyRing(ring, tolerance) {
2996
3003
  let far = 0;
2997
3004
  let farDist = -1;
2998
3005
  for (let i = 1; i < ring.length; i++) {
2999
- const dist2 = Math.hypot(ring[i][0] - ring[0][0], ring[i][1] - ring[0][1]);
3000
- if (dist2 > farDist) {
3001
- farDist = dist2;
3006
+ const dist3 = Math.hypot(ring[i][0] - ring[0][0], ring[i][1] - ring[0][1]);
3007
+ if (dist3 > farDist) {
3008
+ farDist = dist3;
3002
3009
  far = i;
3003
3010
  }
3004
3011
  }
@@ -3036,273 +3043,2559 @@ function polygonToSvgPath(input, options = {}) {
3036
3043
  return fit ? fitted : ringsToPath(rings, f);
3037
3044
  }
3038
3045
 
3039
- // src/canvas/shapeNodes.ts
3040
- var SHAPE_DATA_KEY = "shape";
3041
- var SHAPE_NODE_TYPE = "shape";
3042
- var SHAPE_OPERATIONS = ["unite", "intersect", "subtract", "exclude", "divide"];
3043
- var BOOLEAN_FOR = {
3044
- unite: "union",
3045
- intersect: "intersection",
3046
- subtract: "difference",
3047
- exclude: "xor"
3048
- };
3049
- function isShapeNode(node) {
3050
- return !!node && isShapeDescription(_optionalChain([node, 'access', _71 => _71.data, 'optionalAccess', _72 => _72[SHAPE_DATA_KEY]]));
3051
- }
3052
- function getNodeShape(node) {
3053
- const shape = _optionalChain([node, 'optionalAccess', _73 => _73.data, 'optionalAccess', _74 => _74[SHAPE_DATA_KEY]]);
3054
- return isShapeDescription(shape) ? shape : null;
3046
+ // src/canvas/pathops/bezier.ts
3047
+ var sub2 = (a, b) => [a[0] - b[0], a[1] - b[1]];
3048
+ var add2 = (a, b) => [a[0] + b[0], a[1] + b[1]];
3049
+ var scale = (a, s) => [a[0] * s, a[1] * s];
3050
+ var dot2 = (a, b) => a[0] * b[0] + a[1] * b[1];
3051
+ var cross = (a, b) => a[0] * b[1] - a[1] * b[0];
3052
+ var dist2 = (a, b) => Math.hypot(a[0] - b[0], a[1] - b[1]);
3053
+ var lerp = (a, b, t) => [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
3054
+ var samePoint = (a, b) => a[0] === b[0] && a[1] === b[1];
3055
+ function unit2(v) {
3056
+ const l = Math.hypot(v[0], v[1]);
3057
+ return l > 0 && Number.isFinite(l) ? [v[0] / l, v[1] / l] : null;
3058
+ }
3059
+ function segmentPoint(seg, t) {
3060
+ const n = seg.length;
3061
+ if (n === 2) return lerp(seg[0], seg[1], t);
3062
+ const mt = 1 - t;
3063
+ if (n === 3) {
3064
+ const a2 = mt * mt;
3065
+ const b2 = 2 * mt * t;
3066
+ const c2 = t * t;
3067
+ return [a2 * seg[0][0] + b2 * seg[1][0] + c2 * seg[2][0], a2 * seg[0][1] + b2 * seg[1][1] + c2 * seg[2][1]];
3068
+ }
3069
+ const a = mt * mt * mt;
3070
+ const b = 3 * mt * mt * t;
3071
+ const c = 3 * mt * t * t;
3072
+ const d = t * t * t;
3073
+ return [
3074
+ a * seg[0][0] + b * seg[1][0] + c * seg[2][0] + d * seg[3][0],
3075
+ a * seg[0][1] + b * seg[1][1] + c * seg[2][1] + d * seg[3][1]
3076
+ ];
3055
3077
  }
3056
- function shapeNodeToPolygon(node, lookup, options = {}) {
3057
- const shape = getNodeShape(node);
3058
- if (!shape) return null;
3059
- const size = getNodeSize(node, options);
3060
- const origin = node.parentId && lookup ? getAbsolutePosition(node, lookup) : node.position;
3061
- const { rings, fillRule } = shapeToPolygon(shape, size, { tolerance: options.tolerance });
3062
- return {
3063
- rings: rings.map((ring) => ring.map(([x, y]) => [x + origin.x, y + origin.y])),
3064
- fillRule
3065
- };
3078
+ function segmentDerivative(seg, t) {
3079
+ const n = seg.length;
3080
+ if (n === 2) return sub2(seg[1], seg[0]);
3081
+ if (n === 3) {
3082
+ const a2 = sub2(seg[1], seg[0]);
3083
+ const b2 = sub2(seg[2], seg[1]);
3084
+ return [2 * ((1 - t) * a2[0] + t * b2[0]), 2 * ((1 - t) * a2[1] + t * b2[1])];
3085
+ }
3086
+ const a = sub2(seg[1], seg[0]);
3087
+ const b = sub2(seg[2], seg[1]);
3088
+ const c = sub2(seg[3], seg[2]);
3089
+ const mt = 1 - t;
3090
+ return [
3091
+ 3 * (mt * mt * a[0] + 2 * mt * t * b[0] + t * t * c[0]),
3092
+ 3 * (mt * mt * a[1] + 2 * mt * t * b[1] + t * t * c[1])
3093
+ ];
3066
3094
  }
3067
- var idCounter = 0;
3068
- function defaultId2(index) {
3069
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
3070
- idCounter += 1;
3071
- return `shape-${Date.now().toString(36)}-${idCounter}-${index}`;
3095
+ function segmentSecondDerivative(seg, t) {
3096
+ const n = seg.length;
3097
+ if (n === 2) return [0, 0];
3098
+ if (n === 3) return [2 * (seg[2][0] - 2 * seg[1][0] + seg[0][0]), 2 * (seg[2][1] - 2 * seg[1][1] + seg[0][1])];
3099
+ const a = [seg[2][0] - 2 * seg[1][0] + seg[0][0], seg[2][1] - 2 * seg[1][1] + seg[0][1]];
3100
+ const b = [seg[3][0] - 2 * seg[2][0] + seg[1][0], seg[3][1] - 2 * seg[2][1] + seg[1][1]];
3101
+ return [6 * ((1 - t) * a[0] + t * b[0]), 6 * ((1 - t) * a[1] + t * b[1])];
3102
+ }
3103
+ function segmentTangent(seg, t) {
3104
+ const d = unit2(segmentDerivative(seg, t));
3105
+ if (d) return d;
3106
+ const h = t < 0.5 ? Math.min(1, t + 1e-6) : Math.max(0, t - 1e-6);
3107
+ const e = unit2(segmentDerivative(seg, h));
3108
+ if (e) return e;
3109
+ return _nullishCoalesce(unit2(sub2(seg[seg.length - 1], seg[0])), () => ( [1, 0]));
3110
+ }
3111
+ function segmentCurvature(seg, t) {
3112
+ if (seg.length === 2) return 0;
3113
+ let d = segmentDerivative(seg, t);
3114
+ let tt = t;
3115
+ if (Math.hypot(d[0], d[1]) < 1e-12) {
3116
+ tt = t < 0.5 ? Math.min(1, t + 1e-6) : Math.max(0, t - 1e-6);
3117
+ d = segmentDerivative(seg, tt);
3118
+ }
3119
+ const dd = segmentSecondDerivative(seg, tt);
3120
+ const len = Math.hypot(d[0], d[1]);
3121
+ if (!(len > 0)) return 0;
3122
+ return cross(d, dd) / (len * len * len);
3123
+ }
3124
+ function splitSegment(seg, t) {
3125
+ const n = seg.length;
3126
+ if (n === 2) {
3127
+ const m2 = lerp(seg[0], seg[1], t);
3128
+ return [
3129
+ [seg[0], m2],
3130
+ [m2, seg[1]]
3131
+ ];
3132
+ }
3133
+ if (n === 3) {
3134
+ const a2 = lerp(seg[0], seg[1], t);
3135
+ const b2 = lerp(seg[1], seg[2], t);
3136
+ const m2 = lerp(a2, b2, t);
3137
+ return [
3138
+ [seg[0], a2, m2],
3139
+ [m2, b2, seg[2]]
3140
+ ];
3141
+ }
3142
+ const a = lerp(seg[0], seg[1], t);
3143
+ const b = lerp(seg[1], seg[2], t);
3144
+ const c = lerp(seg[2], seg[3], t);
3145
+ const ab = lerp(a, b, t);
3146
+ const bc = lerp(b, c, t);
3147
+ const m = lerp(ab, bc, t);
3148
+ return [
3149
+ [seg[0], a, ab, m],
3150
+ [m, bc, c, seg[3]]
3151
+ ];
3072
3152
  }
3073
- function stackOrder(nodes, ids) {
3074
- return nodes.map((node, index) => ({ node, index, z: typeof node.zIndex === "number" ? node.zIndex : 0 })).filter((entry) => ids.has(entry.node.id)).sort((a, b) => a.z - b.z || a.index - b.index).map((entry) => entry.node);
3153
+ function subSegment(seg, t0, t1) {
3154
+ if (t1 < t0) return subSegment(seg, t1, t0).reverse();
3155
+ if (t0 <= 0 && t1 >= 1) return [...seg];
3156
+ let s = [...seg];
3157
+ if (t1 < 1) s = splitSegment(s, t1)[0];
3158
+ if (t0 > 0) s = splitSegment(s, t1 > 0 ? t0 / t1 : 0)[1];
3159
+ return s;
3160
+ }
3161
+ function isStraightSegment(seg, tol) {
3162
+ if (seg.length === 2) return true;
3163
+ const a = seg[0];
3164
+ const b = seg[seg.length - 1];
3165
+ const chord = sub2(b, a);
3166
+ const len = Math.hypot(chord[0], chord[1]);
3167
+ for (let i = 1; i < seg.length - 1; i++) {
3168
+ const v = sub2(seg[i], a);
3169
+ if (len === 0) {
3170
+ if (Math.hypot(v[0], v[1]) > tol) return false;
3171
+ continue;
3172
+ }
3173
+ if (Math.abs(cross(chord, v)) / len > tol) return false;
3174
+ const along = dot2(chord, v) / len;
3175
+ if (along < -tol || along > len + tol) return false;
3176
+ }
3177
+ return true;
3075
3178
  }
3076
- function canCombineShapeNodes(nodes, ids) {
3077
- const idSet = new Set(ids);
3078
- const shapes = nodes.filter((n) => idSet.has(n.id) && isShapeNode(n));
3079
- if (shapes.some((n) => isLocked(n))) return { ok: false, reason: "locked" };
3080
- if (shapes.length < 2) return { ok: false, reason: "too-few" };
3081
- return { ok: true, shapeIds: shapes.map((n) => n.id) };
3179
+ function quadraticRoots(a, b, c, out) {
3180
+ const push = (t) => {
3181
+ if (t > 1e-12 && t < 1 - 1e-12) out.push(t);
3182
+ };
3183
+ const scaleAbs = Math.max(Math.abs(a), Math.abs(b), Math.abs(c));
3184
+ if (scaleAbs === 0) return;
3185
+ if (Math.abs(a) <= 1e-12 * scaleAbs) {
3186
+ if (b !== 0) push(-c / b);
3187
+ return;
3188
+ }
3189
+ const disc = b * b - 4 * a * c;
3190
+ if (disc < 0) return;
3191
+ const sq = Math.sqrt(disc);
3192
+ const q = -0.5 * (b + (b >= 0 ? sq : -sq));
3193
+ push(q / a);
3194
+ if (q !== 0) push(c / q);
3082
3195
  }
3083
- function combineShapeNodes(nodes, ids, operation, options = {}) {
3084
- const idList = [...ids];
3085
- const check = canCombineShapeNodes(nodes, idList);
3086
- if (!check.ok) return { ok: false, operation, reason: check.reason };
3087
- const lookup = createNodeLookup(nodes);
3088
- const shapeIds = new Set(check.shapeIds);
3089
- const ordered = stackOrder(nodes, shapeIds);
3090
- const operands = ordered.map((node) => shapeNodeToPolygon(node, lookup, options));
3091
- const parentIds = new Set(ordered.map((n) => _nullishCoalesce(n.parentId, () => ( ""))));
3092
- const sharedParent = parentIds.size === 1 ? ordered[0].parentId : void 0;
3093
- const parentOrigin = sharedParent && lookup.get(sharedParent) ? getAbsolutePosition(lookup.get(sharedParent), lookup) : { x: 0, y: 0 };
3094
- const pickSource = () => {
3095
- const style = _nullishCoalesce(options.styleFrom, () => ( "bottom"));
3096
- if (style === "top") return ordered[ordered.length - 1];
3097
- if (style === "first") {
3098
- const first = idList.find((id) => shapeIds.has(id));
3099
- return first && lookup.get(first) || ordered[0];
3196
+ function segmentExtrema(seg, axis) {
3197
+ const out = [];
3198
+ if (seg.length === 3) {
3199
+ const d = seg[0][axis] - 2 * seg[1][axis] + seg[2][axis];
3200
+ if (d !== 0) {
3201
+ const t = (seg[0][axis] - seg[1][axis]) / d;
3202
+ if (t > 1e-12 && t < 1 - 1e-12) out.push(t);
3100
3203
  }
3101
- if (typeof style === "object") return shapeIds.has(style.id) && lookup.get(style.id) || ordered[0];
3102
- return ordered[0];
3103
- };
3104
- const createId = _nullishCoalesce(options.createId, () => ( defaultId2));
3105
- const build = (polygon, source, index) => {
3106
- const bounds = multiPolygonBounds(polygon);
3107
- if (!bounds) return null;
3108
- const width = bounds.maxX - bounds.minX;
3109
- const height = bounds.maxY - bounds.minY;
3110
- if (!(width > 0) || !(height > 0)) return null;
3111
- const d = polygonToSvgPath(polygon, {
3112
- precision: options.precision,
3113
- simplify: options.simplify,
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
3118
- });
3119
- if (!d) return null;
3120
- const sourceShape = getNodeShape(source);
3121
- const shape = {
3122
- kind: "path",
3123
- d,
3124
- viewBox: [0, 0, roundSize(width), roundSize(height)],
3125
- fillRule: "nonzero"
3126
- };
3127
- for (const key of ["fill", "stroke", "strokeWidth", "opacity"]) {
3128
- if (sourceShape[key] !== void 0) shape[key] = sourceShape[key];
3204
+ } else if (seg.length === 4) {
3205
+ const p0 = seg[0][axis];
3206
+ const p1 = seg[1][axis];
3207
+ const p2 = seg[2][axis];
3208
+ const p3 = seg[3][axis];
3209
+ const a = -p0 + 3 * p1 - 3 * p2 + p3;
3210
+ const b = 2 * (p0 - 2 * p1 + p2);
3211
+ const c = p1 - p0;
3212
+ quadraticRoots(a, b, c, out);
3213
+ }
3214
+ return out.sort((x, y) => x - y);
3215
+ }
3216
+ function segmentBounds(seg) {
3217
+ const a = seg[0];
3218
+ const b = seg[seg.length - 1];
3219
+ let minX = Math.min(a[0], b[0]);
3220
+ let maxX = Math.max(a[0], b[0]);
3221
+ let minY = Math.min(a[1], b[1]);
3222
+ let maxY = Math.max(a[1], b[1]);
3223
+ for (const axis of [0, 1]) {
3224
+ for (const t of segmentExtrema(seg, axis)) {
3225
+ const p = segmentPoint(seg, t);
3226
+ if (axis === 0) {
3227
+ minX = Math.min(minX, p[0]);
3228
+ maxX = Math.max(maxX, p[0]);
3229
+ } else {
3230
+ minY = Math.min(minY, p[1]);
3231
+ maxY = Math.max(maxY, p[1]);
3232
+ }
3129
3233
  }
3130
- const {
3131
- [LOCKED_DATA_KEY]: _locked,
3132
- [LOCKED_PREVIOUS_FLAGS_KEY]: _previous,
3133
- ...data
3134
- } = _nullishCoalesce(source.data, () => ( {}));
3135
- const {
3136
- measured: _measured,
3137
- selected: _selected,
3138
- dragging: _dragging,
3139
- positionAbsolute: _positionAbsolute,
3140
- internals: _internals,
3141
- parentId: _parentId,
3142
- ...rest
3143
- } = source;
3144
- const node = {
3145
- ...rest,
3146
- id: createId(index),
3147
- position: { x: bounds.minX - parentOrigin.x, y: bounds.minY - parentOrigin.y },
3148
- width,
3149
- height,
3150
- data: { ...data, [SHAPE_DATA_KEY]: shape }
3151
- };
3152
- if (sharedParent) node.parentId = sharedParent;
3153
- if (options.nodeType !== void 0) node.type = options.nodeType;
3154
- if (source.style) node.style = withStyleSize(source.style, { width, height });
3155
- if (options.select !== false) node.selected = true;
3156
- return node;
3157
- };
3158
- const created = [];
3159
- if (operation === "divide") {
3160
- const pieces = dividePolygons(operands, { epsilon: options.epsilon });
3161
- pieces.forEach((piece) => {
3162
- const source = ordered[piece.operands[piece.operands.length - 1]];
3163
- const node = build([piece.polygon], source, created.length);
3164
- if (node) created.push(node);
3165
- });
3166
- } else {
3167
- const result = polygonBoolean(BOOLEAN_FOR[operation], operands, { epsilon: options.epsilon });
3168
- const node = build(result, pickSource(), 0);
3169
- if (node) created.push(node);
3170
3234
  }
3171
- if (created.length === 0) return { ok: false, operation, reason: "empty" };
3172
- return { ok: true, operation, removeIds: ordered.map((n) => n.id), nodes: created };
3173
- }
3174
- function roundSize(value) {
3175
- return Math.round(value * 1e3) / 1e3;
3235
+ return { minX, minY, maxX, maxY };
3176
3236
  }
3177
- function applyShapeCombination(nodes, change, options = {}) {
3178
- const remove = new Set(change.removeIds);
3179
- const insertAt = nodes.findIndex((n) => remove.has(n.id));
3180
- const deselect = options.deselect !== false && change.nodes.some((n) => n.selected);
3237
+ function monotoneParams(seg) {
3238
+ if (seg.length === 2) return [];
3239
+ const ts = [...segmentExtrema(seg, 0), ...segmentExtrema(seg, 1)].sort((a, b) => a - b);
3181
3240
  const out = [];
3182
- nodes.forEach((node, index) => {
3183
- if (index === insertAt) out.push(...change.nodes);
3184
- if (remove.has(node.id)) return;
3185
- out.push(deselect && node.selected ? { ...node, selected: false } : node);
3186
- });
3187
- if (insertAt === -1) out.push(...change.nodes);
3188
- return out;
3189
- }
3190
- function revertShapeCombination(nodes, change, previous) {
3191
- const created = new Set(change.nodes.map((n) => n.id));
3192
- const removed = new Set(change.removeIds);
3193
- const out = nodes.filter((n) => !created.has(n.id));
3194
- previous.forEach((node, index) => {
3195
- if (!removed.has(node.id) || out.some((n) => n.id === node.id)) return;
3196
- out.splice(Math.min(index, out.length), 0, node);
3197
- });
3241
+ for (const t of ts) if (out.length === 0 || t - out[out.length - 1] > 1e-9) out.push(t);
3198
3242
  return out;
3199
3243
  }
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"
3244
+ function segmentAreaTerm(seg) {
3245
+ if (seg.length === 2) return (seg[0][0] * seg[1][1] - seg[1][0] * seg[0][1]) / 2;
3246
+ const nodes = [-Math.sqrt(3 / 5), 0, Math.sqrt(3 / 5)];
3247
+ const weights = [5 / 9, 8 / 9, 5 / 9];
3248
+ let sum = 0;
3249
+ for (let i = 0; i < 3; i++) {
3250
+ const t = (nodes[i] + 1) / 2;
3251
+ const p = segmentPoint(seg, t);
3252
+ const d = segmentDerivative(seg, t);
3253
+ sum += weights[i] * (p[0] * d[1] - p[1] * d[0]);
3254
+ }
3255
+ return sum / 4;
3256
+ }
3257
+ var GL_X = [
3258
+ -0.9602898564975363,
3259
+ -0.7966664774136267,
3260
+ -0.525532409916329,
3261
+ -0.1834346424956498,
3262
+ 0.1834346424956498,
3263
+ 0.525532409916329,
3264
+ 0.7966664774136267,
3265
+ 0.9602898564975363
3211
3266
  ];
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;
3267
+ var GL_W = [
3268
+ 0.1012285362903763,
3269
+ 0.2223810344533745,
3270
+ 0.3137066458778873,
3271
+ 0.362683783378362,
3272
+ 0.362683783378362,
3273
+ 0.3137066458778873,
3274
+ 0.2223810344533745,
3275
+ 0.1012285362903763
3276
+ ];
3277
+ function glLength(seg, t0, t1) {
3278
+ const half = (t1 - t0) / 2;
3279
+ const mid = (t0 + t1) / 2;
3280
+ let sum = 0;
3281
+ for (let i = 0; i < GL_X.length; i++) {
3282
+ const d = segmentDerivative(seg, mid + half * GL_X[i]);
3283
+ sum += GL_W[i] * Math.hypot(d[0], d[1]);
3284
+ }
3285
+ return sum * half;
3286
+ }
3287
+ function adaptiveLength(seg, t0, t1, whole, tol, depth) {
3288
+ const m = (t0 + t1) / 2;
3289
+ const left = glLength(seg, t0, m);
3290
+ const right = glLength(seg, m, t1);
3291
+ if (depth >= 18 || Math.abs(left + right - whole) <= tol) return left + right;
3292
+ return adaptiveLength(seg, t0, m, left, tol / 2, depth + 1) + adaptiveLength(seg, m, t1, right, tol / 2, depth + 1);
3293
+ }
3294
+ function segmentLength(seg, t0 = 0, t1 = 1, tolerance = 1e-9) {
3295
+ if (t1 < t0) return segmentLength(seg, t1, t0, tolerance);
3296
+ if (seg.length === 2) return dist2(seg[0], seg[1]) * (t1 - t0);
3297
+ const whole = glLength(seg, t0, t1);
3298
+ return adaptiveLength(seg, t0, t1, whole, Math.max(tolerance, whole * 1e-12), 0);
3299
+ }
3300
+ function segmentParamAtLength(seg, length, total = segmentLength(seg)) {
3301
+ if (!(total > 0) || length <= 0) return 0;
3302
+ if (length >= total) return 1;
3303
+ if (seg.length === 2) return length / total;
3230
3304
  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;
3305
+ let hi = 1;
3306
+ let t = length / total;
3307
+ for (let i = 0; i < 40; i++) {
3308
+ const err = segmentLength(seg, 0, t) - length;
3309
+ if (Math.abs(err) <= 1e-10 * Math.max(1, total)) break;
3310
+ if (err > 0) hi = t;
3311
+ else lo = t;
3312
+ const d = segmentDerivative(seg, t);
3313
+ const speed = Math.hypot(d[0], d[1]);
3314
+ let next = speed > 0 ? t - err / speed : (lo + hi) / 2;
3315
+ if (!(next > lo && next < hi)) next = (lo + hi) / 2;
3316
+ t = next;
3317
+ }
3318
+ return t;
3319
+ }
3320
+ function segmentNearest(seg, p) {
3321
+ if (seg.length === 2) {
3322
+ const d = sub2(seg[1], seg[0]);
3323
+ const len2 = dot2(d, d);
3324
+ const t = len2 === 0 ? 0 : Math.max(0, Math.min(1, dot2(sub2(p, seg[0]), d) / len2));
3325
+ return { t, distance: dist2(p, segmentPoint(seg, t)) };
3326
+ }
3327
+ const samples = 16;
3328
+ let best = { t: 0, distance: dist2(p, seg[0]) };
3329
+ const candidates = [];
3330
+ let prev = Infinity;
3331
+ let prevT = 0;
3332
+ let descending = false;
3333
+ for (let i = 0; i <= samples; i++) {
3334
+ const t = i / samples;
3335
+ const d = dist2(p, segmentPoint(seg, t));
3336
+ if (d < best.distance) best = { t, distance: d };
3337
+ if (i > 0 && d > prev && descending) candidates.push(prevT);
3338
+ descending = d < prev;
3339
+ prev = d;
3340
+ prevT = t;
3341
+ }
3342
+ candidates.push(best.t, 1);
3343
+ for (const start of candidates) {
3344
+ let t = start;
3345
+ for (let k = 0; k < 12; k++) {
3346
+ const q = segmentPoint(seg, t);
3347
+ const d1 = segmentDerivative(seg, t);
3348
+ const d2 = segmentSecondDerivative(seg, t);
3349
+ const diff = sub2(q, p);
3350
+ const f = dot2(diff, d1);
3351
+ const fp = dot2(d1, d1) + dot2(diff, d2);
3352
+ if (!(Math.abs(fp) > 1e-300)) break;
3353
+ const next = Math.max(0, Math.min(1, t - f / fp));
3354
+ if (Math.abs(next - t) < 1e-14) {
3355
+ t = next;
3356
+ break;
3357
+ }
3358
+ t = next;
3359
+ }
3360
+ const d = dist2(p, segmentPoint(seg, t));
3361
+ if (d < best.distance) best = { t, distance: d };
3236
3362
  }
3237
- const out = [];
3238
- for (let i = lo; i < values.length && values[i] <= v + tolerance; i++) out.push(values[i]);
3239
- return out;
3363
+ return best;
3240
3364
  }
3241
- function matching(axis, v, eps) {
3242
- const { values, rects } = axis;
3365
+ function arcToCubics(from, cmd) {
3366
+ const [x0, y0] = from;
3367
+ const { x, y } = cmd;
3368
+ if (x0 === x && y0 === y) return [];
3369
+ let rx = Math.abs(cmd.rx);
3370
+ let ry = Math.abs(cmd.ry);
3371
+ if (rx === 0 || ry === 0) return [[from, [x, y]]];
3372
+ const phi = cmd.rotation * Math.PI / 180;
3373
+ const cos = Math.cos(phi);
3374
+ const sin = Math.sin(phi);
3375
+ const dx = (x0 - x) / 2;
3376
+ const dy = (y0 - y) / 2;
3377
+ const x1p = cos * dx + sin * dy;
3378
+ const y1p = -sin * dx + cos * dy;
3379
+ const lambda = x1p * x1p / (rx * rx) + y1p * y1p / (ry * ry);
3380
+ if (lambda > 1) {
3381
+ const s = Math.sqrt(lambda);
3382
+ rx *= s;
3383
+ ry *= s;
3384
+ }
3385
+ const num = rx * rx * ry * ry - rx * rx * y1p * y1p - ry * ry * x1p * x1p;
3386
+ const den = rx * rx * y1p * y1p + ry * ry * x1p * x1p;
3387
+ let coef = den === 0 ? 0 : Math.sqrt(Math.max(0, num / den));
3388
+ if (cmd.largeArc === cmd.sweep) coef = -coef;
3389
+ const cxp = coef * rx * y1p / ry;
3390
+ const cyp = -coef * ry * x1p / rx;
3391
+ const cx = cos * cxp - sin * cyp + (x0 + x) / 2;
3392
+ const cy = sin * cxp + cos * cyp + (y0 + y) / 2;
3393
+ const angle = (ux, uy, vx, vy) => Math.atan2(ux * vy - uy * vx, ux * vx + uy * vy);
3394
+ const theta1 = angle(1, 0, (x1p - cxp) / rx, (y1p - cyp) / ry);
3395
+ let delta = angle((x1p - cxp) / rx, (y1p - cyp) / ry, (-x1p - cxp) / rx, (-y1p - cyp) / ry);
3396
+ if (!cmd.sweep && delta > 0) delta -= 2 * Math.PI;
3397
+ else if (cmd.sweep && delta < 0) delta += 2 * Math.PI;
3398
+ const n = Math.max(1, Math.ceil(Math.abs(delta) / (Math.PI / 2) - 1e-9));
3399
+ const step = delta / n;
3400
+ const k = 4 / 3 * Math.tan(step / 4);
3401
+ const map = (ux, uy) => {
3402
+ const ex = rx * ux;
3403
+ const ey = ry * uy;
3404
+ return [cos * ex - sin * ey + cx, sin * ex + cos * ey + cy];
3405
+ };
3243
3406
  const out = [];
3244
- for (let i = 0; i < values.length; i++) if (Math.abs(values[i] - v) <= eps) out.push(rects[i]);
3407
+ let prev = from;
3408
+ for (let i = 0; i < n; i++) {
3409
+ const a0 = theta1 + step * i;
3410
+ const a1 = a0 + step;
3411
+ const c0 = Math.cos(a0);
3412
+ const s0 = Math.sin(a0);
3413
+ const c1 = Math.cos(a1);
3414
+ const s1 = Math.sin(a1);
3415
+ const end = i === n - 1 ? [x, y] : map(c1, s1);
3416
+ out.push([prev, map(c0 - k * s0, s0 + k * c0), map(c1 + k * s1, s1 - k * c1), end]);
3417
+ prev = end;
3418
+ }
3245
3419
  return out;
3246
3420
  }
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");
3421
+ function isBezierCommandList(input) {
3422
+ return Array.isArray(input) && !input.some((c) => c && c.type === "A");
3423
+ }
3424
+ function toBezierPath(input) {
3425
+ const commands = typeof input === "string" ? parseSvgPath(input) : isBezierCommandList(input) ? input : input;
3426
+ const out = [];
3427
+ let current = [0, 0];
3428
+ let start = [0, 0];
3429
+ let open = false;
3430
+ const ensureMove = () => {
3431
+ if (!open) {
3432
+ out.push({ type: "M", x: start[0], y: start[1] });
3433
+ current = start;
3434
+ open = true;
3284
3435
  }
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
3436
  };
3299
- let hitX = bestHit(true);
3300
- let hitY = bestHit(false);
3301
- const ratio = rect.height > 0 ? rect.width / rect.height : 0;
3437
+ for (const cmd of commands) {
3438
+ switch (cmd.type) {
3439
+ case "M":
3440
+ start = [cmd.x, cmd.y];
3441
+ current = start;
3442
+ out.push({ type: "M", x: cmd.x, y: cmd.y });
3443
+ open = true;
3444
+ break;
3445
+ case "L":
3446
+ ensureMove();
3447
+ out.push({ type: "L", x: cmd.x, y: cmd.y });
3448
+ current = [cmd.x, cmd.y];
3449
+ break;
3450
+ case "Q":
3451
+ ensureMove();
3452
+ out.push({ type: "Q", x1: cmd.x1, y1: cmd.y1, x: cmd.x, y: cmd.y });
3453
+ current = [cmd.x, cmd.y];
3454
+ break;
3455
+ case "C":
3456
+ ensureMove();
3457
+ out.push({ type: "C", x1: cmd.x1, y1: cmd.y1, x2: cmd.x2, y2: cmd.y2, x: cmd.x, y: cmd.y });
3458
+ current = [cmd.x, cmd.y];
3459
+ break;
3460
+ case "A": {
3461
+ ensureMove();
3462
+ for (const c of arcToCubics(current, cmd)) {
3463
+ if (c.length === 2) out.push({ type: "L", x: c[1][0], y: c[1][1] });
3464
+ else out.push({ type: "C", x1: c[1][0], y1: c[1][1], x2: c[2][0], y2: c[2][1], x: c[3][0], y: c[3][1] });
3465
+ }
3466
+ current = [cmd.x, cmd.y];
3467
+ break;
3468
+ }
3469
+ case "Z":
3470
+ if (open) out.push({ type: "Z" });
3471
+ open = false;
3472
+ current = start;
3473
+ break;
3474
+ }
3475
+ }
3476
+ return out;
3477
+ }
3478
+ function pathToContours(input) {
3479
+ const path = toBezierPath(input);
3480
+ const contours = [];
3481
+ let current = null;
3482
+ let pen = [0, 0];
3483
+ let start = [0, 0];
3484
+ const push = (seg) => {
3485
+ if (!current) {
3486
+ current = { segments: [], closed: false };
3487
+ contours.push(current);
3488
+ }
3489
+ if (seg.every((p) => samePoint(p, seg[0]))) return;
3490
+ current.segments.push(seg);
3491
+ };
3492
+ for (const cmd of path) {
3493
+ switch (cmd.type) {
3494
+ case "M":
3495
+ start = [cmd.x, cmd.y];
3496
+ pen = start;
3497
+ current = { segments: [], closed: false };
3498
+ contours.push(current);
3499
+ break;
3500
+ case "L":
3501
+ push([pen, [cmd.x, cmd.y]]);
3502
+ pen = [cmd.x, cmd.y];
3503
+ break;
3504
+ case "Q":
3505
+ push([pen, [cmd.x1, cmd.y1], [cmd.x, cmd.y]]);
3506
+ pen = [cmd.x, cmd.y];
3507
+ break;
3508
+ case "C":
3509
+ push([pen, [cmd.x1, cmd.y1], [cmd.x2, cmd.y2], [cmd.x, cmd.y]]);
3510
+ pen = [cmd.x, cmd.y];
3511
+ break;
3512
+ case "Z":
3513
+ if (current) current.closed = true;
3514
+ current = null;
3515
+ pen = start;
3516
+ break;
3517
+ }
3518
+ }
3519
+ return contours;
3520
+ }
3521
+ function contoursToPath(contours) {
3522
+ const out = [];
3523
+ for (const contour of contours) {
3524
+ const segs = contour.segments;
3525
+ if (segs.length === 0) continue;
3526
+ out.push({ type: "M", x: segs[0][0][0], y: segs[0][0][1] });
3527
+ let count = segs.length;
3528
+ if (contour.closed && count > 1) {
3529
+ const last = segs[count - 1];
3530
+ if (last.length === 2 && samePoint(last[1], segs[0][0])) count--;
3531
+ }
3532
+ for (let i = 0; i < count; i++) {
3533
+ const s = segs[i];
3534
+ const end = s[s.length - 1];
3535
+ if (s.length === 2) out.push({ type: "L", x: end[0], y: end[1] });
3536
+ else if (s.length === 3) out.push({ type: "Q", x1: s[1][0], y1: s[1][1], x: end[0], y: end[1] });
3537
+ else out.push({ type: "C", x1: s[1][0], y1: s[1][1], x2: s[2][0], y2: s[2][1], x: end[0], y: end[1] });
3538
+ }
3539
+ if (contour.closed) out.push({ type: "Z" });
3540
+ }
3541
+ return out;
3542
+ }
3543
+ function bezierPathToSvg(input, options = {}) {
3544
+ const path = toBezierPath(input);
3545
+ const precision = _nullishCoalesce(options.precision, () => ( 3));
3546
+ const dx = _nullishCoalesce(_optionalChain([options, 'access', _71 => _71.offset, 'optionalAccess', _72 => _72.x]), () => ( 0));
3547
+ const dy = _nullishCoalesce(_optionalChain([options, 'access', _73 => _73.offset, 'optionalAccess', _74 => _74.y]), () => ( 0));
3548
+ const fx = (n) => formatNumber2(n + dx, precision);
3549
+ const fy = (n) => formatNumber2(n + dy, precision);
3550
+ let d = "";
3551
+ for (const c of path) {
3552
+ switch (c.type) {
3553
+ case "M":
3554
+ d += `M${fx(c.x)} ${fy(c.y)}`;
3555
+ break;
3556
+ case "L":
3557
+ d += `L${fx(c.x)} ${fy(c.y)}`;
3558
+ break;
3559
+ case "Q":
3560
+ d += `Q${fx(c.x1)} ${fy(c.y1)} ${fx(c.x)} ${fy(c.y)}`;
3561
+ break;
3562
+ case "C":
3563
+ d += `C${fx(c.x1)} ${fy(c.y1)} ${fx(c.x2)} ${fy(c.y2)} ${fx(c.x)} ${fy(c.y)}`;
3564
+ break;
3565
+ case "Z":
3566
+ d += "Z";
3567
+ break;
3568
+ }
3569
+ }
3570
+ return d;
3571
+ }
3572
+ function transformBezierPath(input, m) {
3573
+ const [a, b, c, d, e, f] = m;
3574
+ const X = (x, y) => a * x + c * y + e;
3575
+ const Y = (x, y) => b * x + d * y + f;
3576
+ return toBezierPath(input).map((cmd) => {
3577
+ switch (cmd.type) {
3578
+ case "M":
3579
+ case "L":
3580
+ return { type: cmd.type, x: X(cmd.x, cmd.y), y: Y(cmd.x, cmd.y) };
3581
+ case "Q":
3582
+ return { type: "Q", x1: X(cmd.x1, cmd.y1), y1: Y(cmd.x1, cmd.y1), x: X(cmd.x, cmd.y), y: Y(cmd.x, cmd.y) };
3583
+ case "C":
3584
+ return {
3585
+ type: "C",
3586
+ x1: X(cmd.x1, cmd.y1),
3587
+ y1: Y(cmd.x1, cmd.y1),
3588
+ x2: X(cmd.x2, cmd.y2),
3589
+ y2: Y(cmd.x2, cmd.y2),
3590
+ x: X(cmd.x, cmd.y),
3591
+ y: Y(cmd.x, cmd.y)
3592
+ };
3593
+ case "Z":
3594
+ return cmd;
3595
+ }
3596
+ });
3597
+ }
3598
+ function countPathSegments(input) {
3599
+ const out = { lines: 0, quads: 0, cubics: 0 };
3600
+ for (const contour of pathToContours(input)) {
3601
+ const segs = closeContour(contour);
3602
+ for (const s of segs) {
3603
+ if (s.length === 2) out.lines++;
3604
+ else if (s.length === 3) out.quads++;
3605
+ else out.cubics++;
3606
+ }
3607
+ }
3608
+ return out;
3609
+ }
3610
+ function closeContour(contour, force = false) {
3611
+ const segs = contour.segments;
3612
+ if (segs.length === 0) return [];
3613
+ if (!contour.closed && !force) return segs;
3614
+ const first = segs[0][0];
3615
+ const lastSeg = segs[segs.length - 1];
3616
+ const last = lastSeg[lastSeg.length - 1];
3617
+ return samePoint(first, last) ? segs : [...segs, [last, first]];
3618
+ }
3619
+ function bezierPathBounds(input) {
3620
+ let minX = Infinity;
3621
+ let minY = Infinity;
3622
+ let maxX = -Infinity;
3623
+ let maxY = -Infinity;
3624
+ const path = toBezierPath(input);
3625
+ let pen = null;
3626
+ for (const contour of pathToContours(path)) {
3627
+ for (const s of contour.segments) {
3628
+ const b = segmentBounds(s);
3629
+ minX = Math.min(minX, b.minX);
3630
+ minY = Math.min(minY, b.minY);
3631
+ maxX = Math.max(maxX, b.maxX);
3632
+ maxY = Math.max(maxY, b.maxY);
3633
+ }
3634
+ }
3635
+ for (const c of path) {
3636
+ if (c.type === "M") pen = [c.x, c.y];
3637
+ if (pen) {
3638
+ minX = Math.min(minX, pen[0]);
3639
+ minY = Math.min(minY, pen[1]);
3640
+ maxX = Math.max(maxX, pen[0]);
3641
+ maxY = Math.max(maxY, pen[1]);
3642
+ }
3643
+ }
3644
+ return minX === Infinity ? null : { minX, minY, maxX, maxY };
3645
+ }
3646
+ function bezierPathSignedArea(input) {
3647
+ let sum = 0;
3648
+ for (const contour of pathToContours(input)) sum += contourSignedArea(closeContour(contour, true));
3649
+ return sum;
3650
+ }
3651
+ function contourSignedArea(segs) {
3652
+ let sum = 0;
3653
+ for (const s of segs) sum += segmentAreaTerm(s);
3654
+ return sum;
3655
+ }
3656
+ function bezierPathLength(input) {
3657
+ let total = 0;
3658
+ for (const contour of pathToContours(input)) for (const s of closeContour(contour)) total += segmentLength(s);
3659
+ return total;
3660
+ }
3661
+ function bezierPathPointAtLength(input, length) {
3662
+ const contours = pathToContours(input);
3663
+ let remaining = Math.max(0, length);
3664
+ let last = null;
3665
+ for (let ci = 0; ci < contours.length; ci++) {
3666
+ const segs = closeContour(contours[ci]);
3667
+ for (let si = 0; si < segs.length; si++) {
3668
+ const s = segs[si];
3669
+ const len = segmentLength(s);
3670
+ if (remaining <= len) {
3671
+ const t = segmentParamAtLength(s, remaining, len);
3672
+ const tangent2 = segmentTangent(s, t);
3673
+ return { point: segmentPoint(s, t), tangent: tangent2, angle: Math.atan2(tangent2[1], tangent2[0]), contour: ci, segment: si, t };
3674
+ }
3675
+ remaining -= len;
3676
+ const tangent = segmentTangent(s, 1);
3677
+ last = { point: s[s.length - 1], tangent, angle: Math.atan2(tangent[1], tangent[0]), contour: ci, segment: si, t: 1 };
3678
+ }
3679
+ }
3680
+ return last;
3681
+ }
3682
+ function trimSegments(segs, from, to, lengths) {
3683
+ const lens = _nullishCoalesce(lengths, () => ( segs.map((s) => segmentLength(s))));
3684
+ const out = [];
3685
+ let at = 0;
3686
+ for (let i = 0; i < segs.length; i++) {
3687
+ const len = lens[i];
3688
+ const s0 = at;
3689
+ const s1 = at + len;
3690
+ at = s1;
3691
+ if (s1 <= from || s0 >= to || len <= 0) continue;
3692
+ const t0 = from > s0 ? segmentParamAtLength(segs[i], from - s0, len) : 0;
3693
+ const t1 = to < s1 ? segmentParamAtLength(segs[i], to - s0, len) : 1;
3694
+ if (t1 > t0) out.push(subSegment(segs[i], t0, t1));
3695
+ }
3696
+ return out;
3697
+ }
3698
+ function solveMonotone(seg, axis, value) {
3699
+ const a = seg[0][axis];
3700
+ const b = seg[seg.length - 1][axis];
3701
+ if (seg.length === 2) return b === a ? 0 : (value - a) / (b - a);
3702
+ const increasing = b > a;
3703
+ let lo = 0;
3704
+ let hi = 1;
3705
+ let t = b === a ? 0.5 : Math.max(0, Math.min(1, (value - a) / (b - a)));
3706
+ for (let i = 0; i < 60; i++) {
3707
+ const v = segmentPoint(seg, t)[axis] - value;
3708
+ if (v === 0) return t;
3709
+ if (v > 0 === increasing) hi = t;
3710
+ else lo = t;
3711
+ const d = segmentDerivative(seg, t)[axis];
3712
+ let next = d !== 0 ? t - v / d : (lo + hi) / 2;
3713
+ if (!(next > lo && next < hi)) next = (lo + hi) / 2;
3714
+ if (Math.abs(next - t) < 1e-15) return next;
3715
+ t = next;
3716
+ }
3717
+ return t;
3718
+ }
3719
+ function yMonotonePieces(segs) {
3720
+ const out = [];
3721
+ for (const s of segs) {
3722
+ if (s.length === 2) {
3723
+ out.push(s);
3724
+ continue;
3725
+ }
3726
+ const ts = segmentExtrema(s, 1);
3727
+ let prev = 0;
3728
+ for (const t of [...ts, 1]) {
3729
+ out.push(subSegment(s, prev, t));
3730
+ prev = t;
3731
+ }
3732
+ }
3733
+ return out;
3734
+ }
3735
+ function windingNumber(chains, point) {
3736
+ const [px2, py] = point;
3737
+ let winding = 0;
3738
+ for (const chain of chains) {
3739
+ for (const s of yMonotonePieces(chain)) {
3740
+ const ay = s[0][1];
3741
+ const by = s[s.length - 1][1];
3742
+ let dir = 0;
3743
+ if (ay <= py && by > py) dir = 1;
3744
+ else if (by <= py && ay > py) dir = -1;
3745
+ else continue;
3746
+ let minX = Infinity;
3747
+ let maxX = -Infinity;
3748
+ for (const p of s) {
3749
+ if (p[0] < minX) minX = p[0];
3750
+ if (p[0] > maxX) maxX = p[0];
3751
+ }
3752
+ if (minX > px2) {
3753
+ winding += dir;
3754
+ continue;
3755
+ }
3756
+ if (maxX <= px2) continue;
3757
+ const t = solveMonotone(s, 1, py);
3758
+ if (segmentPoint(s, t)[0] > px2) winding += dir;
3759
+ }
3760
+ }
3761
+ return winding;
3762
+ }
3763
+ function pointInBezierPath(input, point, fillRule = "nonzero") {
3764
+ const chains = pathToContours(input).map((c) => closeContour(c, true));
3765
+ const w = windingNumber(chains, point);
3766
+ return fillRule === "evenodd" ? (w & 1) === 1 : w !== 0;
3767
+ }
3768
+ function distanceToBezierPath(input, point) {
3769
+ const contours = Array.isArray(input) && input.length > 0 && input[0].segments ? input : pathToContours(input);
3770
+ let best = Infinity;
3771
+ for (const contour of contours) {
3772
+ for (const s of closeContour(contour)) {
3773
+ let minX = Infinity;
3774
+ let minY = Infinity;
3775
+ let maxX = -Infinity;
3776
+ let maxY = -Infinity;
3777
+ for (const p of s) {
3778
+ minX = Math.min(minX, p[0]);
3779
+ minY = Math.min(minY, p[1]);
3780
+ maxX = Math.max(maxX, p[0]);
3781
+ maxY = Math.max(maxY, p[1]);
3782
+ }
3783
+ const dx = Math.max(minX - point[0], 0, point[0] - maxX);
3784
+ const dy = Math.max(minY - point[1], 0, point[1] - maxY);
3785
+ if (Math.hypot(dx, dy) >= best) continue;
3786
+ best = Math.min(best, segmentNearest(s, point).distance);
3787
+ }
3788
+ if (contour.segments.length === 0) continue;
3789
+ }
3790
+ return best;
3791
+ }
3792
+ function flattenChain(segs, tolerance) {
3793
+ const out = [];
3794
+ for (const s of segs) {
3795
+ if (out.length === 0) out.push(s[0]);
3796
+ if (s.length === 2) {
3797
+ out.push(s[1]);
3798
+ continue;
3799
+ }
3800
+ let dd = 0;
3801
+ for (let i = 0; i + 2 < s.length; i++) {
3802
+ dd = Math.max(dd, Math.hypot(s[i][0] - 2 * s[i + 1][0] + s[i + 2][0], s[i][1] - 2 * s[i + 1][1] + s[i + 2][1]));
3803
+ }
3804
+ const deg = s.length - 1;
3805
+ const n = Math.max(1, Math.min(256, Math.ceil(Math.sqrt(deg * (deg - 1) * dd / (8 * tolerance)))));
3806
+ for (let k = 1; k <= n; k++) out.push(segmentPoint(s, k / n));
3807
+ }
3808
+ if (out.length > 1 && samePoint(out[0], out[out.length - 1])) out.pop();
3809
+ return out;
3810
+ }
3811
+
3812
+ // src/canvas/pathops/boolean.ts
3813
+ var PathOpsError = class extends Error {
3814
+ constructor(message) {
3815
+ super(message);
3816
+ this.name = "PathOpsError";
3817
+ }
3818
+ };
3819
+ function isOperandObject(input) {
3820
+ return !!input && typeof input === "object" && !Array.isArray(input) && "path" in input;
3821
+ }
3822
+ function normalizeOperand(input) {
3823
+ const path = isOperandObject(input) ? input.path : input;
3824
+ const fillRule = isOperandObject(input) ? _nullishCoalesce(input.fillRule, () => ( "nonzero")) : "nonzero";
3825
+ const chains = [];
3826
+ for (const contour of pathToContours(_nullishCoalesce(path, () => ( "")))) {
3827
+ const chain = closeContour(contour, true);
3828
+ if (chain.length === 0) continue;
3829
+ for (const seg of chain) {
3830
+ for (const p of seg) {
3831
+ if (!Number.isFinite(p[0]) || !Number.isFinite(p[1])) throw new PathOpsError(NON_FINITE);
3832
+ }
3833
+ }
3834
+ chains.push(chain);
3835
+ }
3836
+ return { chains, fillRule };
3837
+ }
3838
+ function scaleOf(operands) {
3839
+ let max = 0;
3840
+ for (const op of operands) {
3841
+ for (const chain of op.chains) {
3842
+ for (const seg of chain) {
3843
+ for (const [x, y] of seg) max = Math.max(max, Math.abs(x), Math.abs(y));
3844
+ }
3845
+ }
3846
+ }
3847
+ return Math.max(1, max);
3848
+ }
3849
+ var VertexPool = (_class6 = class {
3850
+ constructor(eps) {;_class6.prototype.__init15.call(this);_class6.prototype.__init16.call(this);
3851
+ this.eps = eps;
3852
+ }
3853
+
3854
+ __init15() {this.vertices = []}
3855
+ __init16() {this.cells = /* @__PURE__ */ new Map()}
3856
+ get(x, y) {
3857
+ const cx = Math.floor(x / this.eps);
3858
+ const cy = Math.floor(y / this.eps);
3859
+ let best = null;
3860
+ let bestDist = Infinity;
3861
+ for (let dx = -1; dx <= 1; dx++) {
3862
+ for (let dy = -1; dy <= 1; dy++) {
3863
+ const ids = this.cells.get(`${cx + dx},${cy + dy}`);
3864
+ if (!ids) continue;
3865
+ for (const id of ids) {
3866
+ const v = this.vertices[id];
3867
+ const d = Math.hypot(v.x - x, v.y - y);
3868
+ if (d <= this.eps && d < bestDist) {
3869
+ best = v;
3870
+ bestDist = d;
3871
+ }
3872
+ }
3873
+ }
3874
+ }
3875
+ if (best) return best;
3876
+ const vertex = { id: this.vertices.length, x, y, p: [x, y] };
3877
+ this.vertices.push(vertex);
3878
+ const key = `${cx},${cy}`;
3879
+ const bucket = this.cells.get(key);
3880
+ if (bucket) bucket.push(vertex.id);
3881
+ else this.cells.set(key, [vertex.id]);
3882
+ return vertex;
3883
+ }
3884
+ }, _class6);
3885
+ function hull(pts) {
3886
+ let minX = Infinity;
3887
+ let maxX = -Infinity;
3888
+ let minY = Infinity;
3889
+ let maxY = -Infinity;
3890
+ for (const [x, y] of pts) {
3891
+ if (x < minX) minX = x;
3892
+ if (x > maxX) maxX = x;
3893
+ if (y < minY) minY = y;
3894
+ if (y > maxY) maxY = y;
3895
+ }
3896
+ return { minX, maxX, minY, maxY };
3897
+ }
3898
+ function snapEnds(pts, a, b) {
3899
+ const n = pts.length;
3900
+ if (n === 2) return [a, b];
3901
+ const d0 = sub2(a, pts[0]);
3902
+ const d1 = sub2(b, pts[n - 1]);
3903
+ if (n === 3) {
3904
+ return [a, [pts[1][0] + (d0[0] + d1[0]) / 2, pts[1][1] + (d0[1] + d1[1]) / 2], b];
3905
+ }
3906
+ return [a, [pts[1][0] + d0[0], pts[1][1] + d0[1]], [pts[2][0] + d1[0], pts[2][1] + d1[1]], b];
3907
+ }
3908
+ function makePiece(pts, a, b, operand, src, s0, s1) {
3909
+ const snapped = snapEnds(pts, a.p, b.p);
3910
+ return { pts: snapped, a, b, operand, src, s0, s1, dirty: true, ...hull(snapped) };
3911
+ }
3912
+ var NON_FINITE = "non-finite coordinates";
3913
+ function flatness(pts) {
3914
+ if (pts.length === 2) return 0;
3915
+ const a = pts[0];
3916
+ const b = pts[pts.length - 1];
3917
+ const chord = sub2(b, a);
3918
+ const len = Math.hypot(chord[0], chord[1]);
3919
+ let worst = 0;
3920
+ for (let i = 1; i < pts.length - 1; i++) {
3921
+ const v = sub2(pts[i], a);
3922
+ const d = len > 0 ? Math.abs(cross(chord, v)) / len : Math.hypot(v[0], v[1]);
3923
+ const along = len > 0 ? dot2(chord, v) / len : 0;
3924
+ const over = Math.max(0, -along, along - len);
3925
+ worst = Math.max(worst, d, over);
3926
+ }
3927
+ return worst;
3928
+ }
3929
+ function split2(pts) {
3930
+ const n = pts.length;
3931
+ const mid = (p, q) => [(p[0] + q[0]) / 2, (p[1] + q[1]) / 2];
3932
+ if (n === 2) {
3933
+ const m2 = mid(pts[0], pts[1]);
3934
+ return [
3935
+ [pts[0], m2],
3936
+ [m2, pts[1]]
3937
+ ];
3938
+ }
3939
+ if (n === 3) {
3940
+ const a2 = mid(pts[0], pts[1]);
3941
+ const b2 = mid(pts[1], pts[2]);
3942
+ const m2 = mid(a2, b2);
3943
+ return [
3944
+ [pts[0], a2, m2],
3945
+ [m2, b2, pts[2]]
3946
+ ];
3947
+ }
3948
+ const a = mid(pts[0], pts[1]);
3949
+ const b = mid(pts[1], pts[2]);
3950
+ const c = mid(pts[2], pts[3]);
3951
+ const ab = mid(a, b);
3952
+ const bc = mid(b, c);
3953
+ const m = mid(ab, bc);
3954
+ return [
3955
+ [pts[0], a, ab, m],
3956
+ [m, bc, c, pts[3]]
3957
+ ];
3958
+ }
3959
+ function closestSegmentPoints(a0, a1, b0, b1) {
3960
+ const d1 = sub2(a1, a0);
3961
+ const d2 = sub2(b1, b0);
3962
+ const r = sub2(a0, b0);
3963
+ const a = dot2(d1, d1);
3964
+ const e = dot2(d2, d2);
3965
+ const f = dot2(d2, r);
3966
+ let s = 0;
3967
+ let u = 0;
3968
+ if (a <= 1e-300 && e <= 1e-300) return { s: 0, u: 0, d: dist2(a0, b0) };
3969
+ if (a <= 1e-300) {
3970
+ u = Math.max(0, Math.min(1, f / e));
3971
+ } else {
3972
+ const c = dot2(d1, r);
3973
+ if (e <= 1e-300) {
3974
+ s = Math.max(0, Math.min(1, -c / a));
3975
+ } else {
3976
+ const b = dot2(d1, d2);
3977
+ const denom = a * e - b * b;
3978
+ s = denom > 0 ? Math.max(0, Math.min(1, (b * f - c * e) / denom)) : 0;
3979
+ u = (b * s + f) / e;
3980
+ if (u < 0) {
3981
+ u = 0;
3982
+ s = Math.max(0, Math.min(1, -c / a));
3983
+ } else if (u > 1) {
3984
+ u = 1;
3985
+ s = Math.max(0, Math.min(1, (b - c) / a));
3986
+ }
3987
+ }
3988
+ }
3989
+ const pa = [a0[0] + d1[0] * s, a0[1] + d1[1] * s];
3990
+ const pb = [b0[0] + d2[0] * u, b0[1] + d2[1] * u];
3991
+ return { s, u, d: dist2(pa, pb) };
3992
+ }
3993
+ function polish(P, Q, s, u) {
3994
+ let best = { s, u, d: dist2(segmentPoint(P, s), segmentPoint(Q, u)) };
3995
+ for (let i = 0; i < 10 && best.d > 0; i++) {
3996
+ const f = sub2(segmentPoint(P, s), segmentPoint(Q, u));
3997
+ const dp = segmentDerivative(P, s);
3998
+ const dq = segmentDerivative(Q, u);
3999
+ const det = cross(dp, [-dq[0], -dq[1]]);
4000
+ if (!(Math.abs(det) > 1e-300)) break;
4001
+ const ds = cross([-f[0], -f[1]], [-dq[0], -dq[1]]) / det;
4002
+ const du = cross(dp, [-f[0], -f[1]]) / det;
4003
+ s = Math.max(0, Math.min(1, s + ds));
4004
+ u = Math.max(0, Math.min(1, u + du));
4005
+ const d = dist2(segmentPoint(P, s), segmentPoint(Q, u));
4006
+ if (d < best.d) best = { s, u, d };
4007
+ else break;
4008
+ }
4009
+ return best;
4010
+ }
4011
+ function intersectSubdivided(P, p0, p1, Q, q0, q1, fullP, fullQ, ctx, out, depth) {
4012
+ const hp = hull(P);
4013
+ const hq = hull(Q);
4014
+ const e = ctx.eps;
4015
+ if (hp.minX > hq.maxX + e || hq.minX > hp.maxX + e || hp.minY > hq.maxY + e || hq.minY > hp.maxY + e) return;
4016
+ const fp = flatness(P);
4017
+ const fq = flatness(Q);
4018
+ const flatTol = e * 0.5;
4019
+ if (fp <= flatTol && fq <= flatTol || depth >= 52) {
4020
+ if (++ctx.leaves > ctx.budget) throw new PathOpsError("curve intersection did not converge");
4021
+ const a0 = P[0];
4022
+ const a1 = P[P.length - 1];
4023
+ const b0 = Q[0];
4024
+ const b1 = Q[Q.length - 1];
4025
+ const d1 = sub2(a1, a0);
4026
+ const d2 = sub2(b1, b0);
4027
+ const denom = cross(d1, d2);
4028
+ let s = 0;
4029
+ let u = 0;
4030
+ let hit = false;
4031
+ const l1 = Math.hypot(d1[0], d1[1]);
4032
+ const l2 = Math.hypot(d2[0], d2[1]);
4033
+ if (Math.abs(denom) > 1e-12 * l1 * l2) {
4034
+ const r = sub2(b0, a0);
4035
+ s = cross(r, d2) / denom;
4036
+ u = cross(r, d1) / denom;
4037
+ const ts = l1 > 0 ? e / l1 : 1;
4038
+ const tu = l2 > 0 ? e / l2 : 1;
4039
+ hit = s >= -ts && s <= 1 + ts && u >= -tu && u <= 1 + tu;
4040
+ }
4041
+ if (!hit) {
4042
+ const c = closestSegmentPoints(a0, a1, b0, b1);
4043
+ if (c.d > e) return;
4044
+ s = c.s;
4045
+ u = c.u;
4046
+ }
4047
+ s = Math.max(0, Math.min(1, s));
4048
+ u = Math.max(0, Math.min(1, u));
4049
+ const best = polish(fullP, fullQ, p0 + (p1 - p0) * s, q0 + (q1 - q0) * u);
4050
+ if (best.d > e * 2) return;
4051
+ const a = segmentPoint(fullP, best.s);
4052
+ const b = segmentPoint(fullQ, best.u);
4053
+ out.push({ tp: best.s, tq: best.u, point: [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2] });
4054
+ return;
4055
+ }
4056
+ const splitP = fp > flatTol;
4057
+ const splitQ = fq > flatTol;
4058
+ const pm = (p0 + p1) / 2;
4059
+ const qm = (q0 + q1) / 2;
4060
+ if (splitP && splitQ) {
4061
+ const [pa, pb] = split2(P);
4062
+ const [qa, qb] = split2(Q);
4063
+ intersectSubdivided(pa, p0, pm, qa, q0, qm, fullP, fullQ, ctx, out, depth + 1);
4064
+ intersectSubdivided(pa, p0, pm, qb, qm, q1, fullP, fullQ, ctx, out, depth + 1);
4065
+ intersectSubdivided(pb, pm, p1, qa, q0, qm, fullP, fullQ, ctx, out, depth + 1);
4066
+ intersectSubdivided(pb, pm, p1, qb, qm, q1, fullP, fullQ, ctx, out, depth + 1);
4067
+ } else if (splitP) {
4068
+ const [pa, pb] = split2(P);
4069
+ intersectSubdivided(pa, p0, pm, Q, q0, q1, fullP, fullQ, ctx, out, depth + 1);
4070
+ intersectSubdivided(pb, pm, p1, Q, q0, q1, fullP, fullQ, ctx, out, depth + 1);
4071
+ } else {
4072
+ const [qa, qb] = split2(Q);
4073
+ intersectSubdivided(P, p0, p1, qa, q0, qm, fullP, fullQ, ctx, out, depth + 1);
4074
+ intersectSubdivided(P, p0, p1, qb, qm, q1, fullP, fullQ, ctx, out, depth + 1);
4075
+ }
4076
+ }
4077
+ function nearestOn(piece, p, eps) {
4078
+ if (p[0] < piece.minX - eps || p[0] > piece.maxX + eps || p[1] < piece.minY - eps || p[1] > piece.maxY + eps) return null;
4079
+ return segmentNearest(piece.pts, p);
4080
+ }
4081
+ function staysClose(P, Q, e1, e2, tol) {
4082
+ for (const f of [0.25, 0.5, 0.75]) {
4083
+ const tp = e1.tp + (e2.tp - e1.tp) * f;
4084
+ const q = segmentNearest(Q.pts, segmentPoint(P.pts, tp));
4085
+ if (q.distance > tol) return false;
4086
+ }
4087
+ return true;
4088
+ }
4089
+ function pairEvents(P, Q, ctx) {
4090
+ const eps = ctx.eps;
4091
+ const anchors = [];
4092
+ for (const [va, tp] of [
4093
+ [P.a, 0],
4094
+ [P.b, 1]
4095
+ ]) {
4096
+ if (va === Q.a) anchors.push({ tp, tq: 0, point: va.p, anchor: true, shared: true });
4097
+ else if (va === Q.b) anchors.push({ tp, tq: 1, point: va.p, anchor: true, shared: true });
4098
+ }
4099
+ for (const [v, tq] of [
4100
+ [Q.a, 0],
4101
+ [Q.b, 1]
4102
+ ]) {
4103
+ if (v === P.a || v === P.b) continue;
4104
+ const near = nearestOn(P, v.p, eps);
4105
+ if (near && near.distance <= eps) anchors.push({ tp: near.t, tq, point: v.p, anchor: true });
4106
+ }
4107
+ for (const [v, tp] of [
4108
+ [P.a, 0],
4109
+ [P.b, 1]
4110
+ ]) {
4111
+ if (v === Q.a || v === Q.b) continue;
4112
+ const near = nearestOn(Q, v.p, eps);
4113
+ if (near && near.distance <= eps) anchors.push({ tp, tq: near.t, point: v.p, anchor: true });
4114
+ }
4115
+ if (anchors.length >= 2) {
4116
+ const sorted = [...anchors].sort((x, y) => x.tp - y.tp);
4117
+ const first = sorted[0];
4118
+ const last = sorted[sorted.length - 1];
4119
+ if (dist2(first.point, last.point) > eps && staysClose(P, Q, first, last, eps * 4)) {
4120
+ return anchors.filter((a) => !a.shared);
4121
+ }
4122
+ }
4123
+ const found = [];
4124
+ if (P.pts.length === 2 && Q.pts.length === 2) {
4125
+ const a0 = P.pts[0];
4126
+ const d1 = sub2(P.pts[1], a0);
4127
+ const b0 = Q.pts[0];
4128
+ const d2 = sub2(Q.pts[1], b0);
4129
+ const denom = cross(d1, d2);
4130
+ const l1 = Math.hypot(d1[0], d1[1]);
4131
+ const l2 = Math.hypot(d2[0], d2[1]);
4132
+ if (Math.abs(denom) > 1e-12 * l1 * l2) {
4133
+ const r = sub2(b0, a0);
4134
+ const s = cross(r, d2) / denom;
4135
+ const u = cross(r, d1) / denom;
4136
+ const ts = eps / l1;
4137
+ const tu = eps / l2;
4138
+ if (s >= -ts && s <= 1 + ts && u >= -tu && u <= 1 + tu) {
4139
+ const sc = Math.max(0, Math.min(1, s));
4140
+ const uc = Math.max(0, Math.min(1, u));
4141
+ found.push({ tp: sc, tq: uc, point: [a0[0] + d1[0] * sc, a0[1] + d1[1] * sc] });
4142
+ }
4143
+ }
4144
+ } else {
4145
+ ctx.leaves = 0;
4146
+ intersectSubdivided(P.pts, 0, 1, Q.pts, 0, 1, P.pts, Q.pts, ctx, found, 0);
4147
+ }
4148
+ if (found.length === 0) return anchors.filter((a) => !a.shared);
4149
+ const all = [...anchors, ...found].sort((x, y) => x.tp - y.tp || x.tq - y.tq);
4150
+ const clusters = [];
4151
+ for (const ev of all) {
4152
+ const cluster = clusters[clusters.length - 1];
4153
+ const prev = _optionalChain([cluster, 'optionalAccess', _75 => _75[cluster.length - 1]]);
4154
+ if (prev && (dist2(prev.point, ev.point) <= eps * 2 || staysClose(P, Q, prev, ev, eps * 2))) cluster.push(ev);
4155
+ else clusters.push([ev]);
4156
+ }
4157
+ const out = [];
4158
+ for (const cluster of clusters) {
4159
+ const shared = cluster.find((e) => e.shared);
4160
+ if (shared) continue;
4161
+ const anchor = cluster.find((e) => e.anchor);
4162
+ out.push(_nullishCoalesce(anchor, () => ( cluster[Math.floor(cluster.length / 2)])));
4163
+ }
4164
+ return out;
4165
+ }
4166
+ function addSplit2(map, piece, t, v) {
4167
+ if (v === piece.a || v === piece.b) return;
4168
+ const list = map.get(piece);
4169
+ if (list) list.push({ t, v });
4170
+ else map.set(piece, [{ t, v }]);
4171
+ }
4172
+ function eventVertex(P, Q, ev, pool, eps) {
4173
+ for (const v of [P.a, P.b, Q.a, Q.b]) if (dist2(v.p, ev.point) <= eps) return v;
4174
+ return pool.get(ev.point[0], ev.point[1]);
4175
+ }
4176
+ function splitPass2(pieces, pool, ctx) {
4177
+ const eps = ctx.eps;
4178
+ const order = pieces.map((_, i) => i).sort((i, j) => pieces[i].minX - pieces[j].minX);
4179
+ const splits = /* @__PURE__ */ new Map();
4180
+ for (let oi = 0; oi < order.length; oi++) {
4181
+ const P = pieces[order[oi]];
4182
+ for (let oj = oi + 1; oj < order.length; oj++) {
4183
+ const Q = pieces[order[oj]];
4184
+ if (Q.minX > P.maxX + eps) break;
4185
+ if (!P.dirty && !Q.dirty) continue;
4186
+ if (Q.minY > P.maxY + eps || Q.maxY < P.minY - eps) continue;
4187
+ if (P.a === Q.a && P.b === Q.b && P.pts.length === 2 && Q.pts.length === 2) continue;
4188
+ if (P.a === Q.b && P.b === Q.a && P.pts.length === 2 && Q.pts.length === 2) continue;
4189
+ for (const ev of pairEvents(P, Q, ctx)) {
4190
+ const v = eventVertex(P, Q, ev, pool, eps);
4191
+ addSplit2(splits, P, ev.tp, v);
4192
+ addSplit2(splits, Q, ev.tq, v);
4193
+ }
4194
+ }
4195
+ }
4196
+ for (const p of pieces) p.dirty = false;
4197
+ if (splits.size === 0) return { pieces, changed: false };
4198
+ const out = [];
4199
+ for (const piece of pieces) {
4200
+ const list = splits.get(piece);
4201
+ if (!list) {
4202
+ out.push(piece);
4203
+ continue;
4204
+ }
4205
+ list.sort((x, y) => x.t - y.t);
4206
+ let prevT = 0;
4207
+ let prevV = piece.a;
4208
+ const range = piece.s1 - piece.s0;
4209
+ const emit = (t, v) => {
4210
+ if (v === prevV || t <= prevT) return;
4211
+ const pts = subSegment(piece.pts, prevT, t);
4212
+ out.push(makePiece(pts, prevV, v, piece.operand, piece.src, piece.s0 + range * prevT, piece.s0 + range * t));
4213
+ prevT = t;
4214
+ prevV = v;
4215
+ };
4216
+ const seen = /* @__PURE__ */ new Set();
4217
+ for (const { t, v } of list) {
4218
+ if (seen.has(v) || t <= 0 || t >= 1) continue;
4219
+ seen.add(v);
4220
+ emit(t, v);
4221
+ }
4222
+ if (prevV !== piece.b) {
4223
+ const pts = subSegment(piece.pts, prevT, 1);
4224
+ out.push(makePiece(pts, prevV, piece.b, piece.operand, piece.src, piece.s0 + range * prevT, piece.s1));
4225
+ }
4226
+ }
4227
+ return { pieces: out, changed: true };
4228
+ }
4229
+ function buildArrangement(inputs, options) {
4230
+ const operands = inputs.map(normalizeOperand);
4231
+ const scale2 = scaleOf(operands);
4232
+ const eps = options.epsilon && options.epsilon > 0 ? options.epsilon : 1e-9 * scale2;
4233
+ const pool = new VertexPool(eps);
4234
+ const sources = [];
4235
+ let pieces = [];
4236
+ operands.forEach((op, operand) => {
4237
+ for (const chain of op.chains) {
4238
+ for (const raw of chain) {
4239
+ const straight = raw.length > 2 && isStraightSegment(raw, eps * 0.01);
4240
+ const seg = straight ? [raw[0], raw[raw.length - 1]] : raw;
4241
+ const src = sources.length;
4242
+ sources.push({ seg, line: seg.length === 2 });
4243
+ const ts = [0, ...monotoneParams(seg), 1];
4244
+ for (let i = 0; i + 1 < ts.length; i++) {
4245
+ const pts = subSegment(seg, ts[i], ts[i + 1]);
4246
+ const a = pool.get(pts[0][0], pts[0][1]);
4247
+ const b = pool.get(pts[pts.length - 1][0], pts[pts.length - 1][1]);
4248
+ if (a === b) continue;
4249
+ pieces.push(makePiece(pts, a, b, operand, src, ts[i], ts[i + 1]));
4250
+ }
4251
+ }
4252
+ }
4253
+ });
4254
+ const ctx = { eps, leaves: 0, budget: _nullishCoalesce(options.subdivisionBudget, () => ( 2e4)) };
4255
+ let settled = false;
4256
+ for (let pass = 0; pass < 6; pass++) {
4257
+ const result = splitPass2(pieces, pool, ctx);
4258
+ pieces = result.pieces;
4259
+ if (!result.changed) {
4260
+ settled = true;
4261
+ break;
4262
+ }
4263
+ }
4264
+ if (!settled) throw new PathOpsError("intersections did not settle");
4265
+ const count = operands.length;
4266
+ const groups = /* @__PURE__ */ new Map();
4267
+ const edges = [];
4268
+ for (const piece of pieces) {
4269
+ const forward = piece.a.id < piece.b.id;
4270
+ const a = forward ? piece.a : piece.b;
4271
+ const b = forward ? piece.b : piece.a;
4272
+ const pts = forward ? piece.pts : [...piece.pts].reverse();
4273
+ const key = `${a.id},${b.id}`;
4274
+ const group = _nullishCoalesce(groups.get(key), () => ( []));
4275
+ if (!groups.has(key)) groups.set(key, group);
4276
+ const mid = segmentPoint(pts, 0.5);
4277
+ let edge = group.find((e) => {
4278
+ if (e.pts.length === 2 && pts.length === 2) return true;
4279
+ return segmentNearest(e.pts, mid).distance <= eps * 4 && segmentNearest(pts, segmentPoint(e.pts, 0.5)).distance <= eps * 4;
4280
+ });
4281
+ if (!edge) {
4282
+ edge = {
4283
+ a,
4284
+ b,
4285
+ pts,
4286
+ mult: new Array(count).fill(0),
4287
+ src: piece.src,
4288
+ sa: forward ? piece.s0 : piece.s1,
4289
+ sb: forward ? piece.s1 : piece.s0,
4290
+ ...hull(pts)
4291
+ };
4292
+ group.push(edge);
4293
+ edges.push(edge);
4294
+ }
4295
+ edge.mult[piece.operand] += forward ? 1 : -1;
4296
+ }
4297
+ const live = edges.filter((e) => e.mult.some((m) => m !== 0));
4298
+ const byY = new BandIndex(live, (e) => e.minY, (e) => e.maxY);
4299
+ const byX = new BandIndex(live, (e) => e.minX, (e) => e.maxX);
4300
+ const right = [];
4301
+ const left = [];
4302
+ for (let i = 0; i < live.length; i++) {
4303
+ const edge = live[i];
4304
+ const mid = segmentPoint(edge.pts, 0.5);
4305
+ const tan = segmentTangent(edge.pts, 0.5);
4306
+ const horizontal = Math.abs(tan[1]) < Math.abs(tan[0]);
4307
+ const winding = new Array(count).fill(0);
4308
+ const [mx, my] = mid;
4309
+ for (const j of horizontal ? byX.at(mx) : byY.at(my)) {
4310
+ if (j === i) continue;
4311
+ const o = live[j];
4312
+ let dir = 0;
4313
+ if (!horizontal) {
4314
+ if (o.maxX <= mx) continue;
4315
+ const ay = o.a.y;
4316
+ const by = o.b.y;
4317
+ if (ay <= my && by > my) dir = 1;
4318
+ else if (by <= my && ay > my) dir = -1;
4319
+ else continue;
4320
+ if (o.minX <= mx) {
4321
+ const t = solveMonotone(o.pts, 1, my);
4322
+ if (!(segmentPoint(o.pts, t)[0] > mx)) continue;
4323
+ }
4324
+ } else {
4325
+ if (o.maxY <= my) continue;
4326
+ const ax = o.a.x;
4327
+ const bx = o.b.x;
4328
+ if (bx < mx && mx <= ax) dir = 1;
4329
+ else if (ax < mx && mx <= bx) dir = -1;
4330
+ else continue;
4331
+ if (o.minY <= my) {
4332
+ const t = solveMonotone(o.pts, 0, mx);
4333
+ if (!(segmentPoint(o.pts, t)[1] > my)) continue;
4334
+ }
4335
+ }
4336
+ for (let k = 0; k < count; k++) if (o.mult[k] !== 0) winding[k] += dir * o.mult[k];
4337
+ }
4338
+ const sideIsRight = horizontal ? edge.b.x < edge.a.x : edge.b.y > edge.a.y;
4339
+ const r = sideIsRight ? winding : winding.map((w, k) => w - edge.mult[k]);
4340
+ right.push(r);
4341
+ left.push(r.map((w, k) => w + edge.mult[k]));
4342
+ }
4343
+ return { edges: live, left, right, fillRules: operands.map((o) => o.fillRule), sources, eps, scale: scale2 };
4344
+ }
4345
+ var BandIndex = class {
4346
+
4347
+
4348
+
4349
+ constructor(edges, lo, hi) {
4350
+ let min = Infinity;
4351
+ let max = -Infinity;
4352
+ for (const e of edges) {
4353
+ min = Math.min(min, lo(e));
4354
+ max = Math.max(max, hi(e));
4355
+ }
4356
+ const count = Math.max(1, Math.min(4096, Math.ceil(Math.sqrt(edges.length) * 2)));
4357
+ this.min = min;
4358
+ this.size = max > min ? (max - min) / count : 1;
4359
+ this.bands = Array.from({ length: count }, () => []);
4360
+ edges.forEach((e, i) => {
4361
+ const from = this.index(lo(e));
4362
+ const to = this.index(hi(e));
4363
+ for (let b = from; b <= to; b++) this.bands[b].push(i);
4364
+ });
4365
+ }
4366
+ index(v) {
4367
+ const k = Math.floor((v - this.min) / this.size);
4368
+ return Math.max(0, Math.min(this.bands.length - 1, Number.isFinite(k) ? k : 0));
4369
+ }
4370
+ at(v) {
4371
+ return _nullishCoalesce(this.bands[this.index(v)], () => ( []));
4372
+ }
4373
+ };
4374
+ function insideFlags2(windings, fillRules) {
4375
+ return windings.map((w, k) => fillRules[k] === "evenodd" ? (w & 1) === 1 : w !== 0);
4376
+ }
4377
+ var TWO_PI = Math.PI * 2;
4378
+ var TIE = 1e-3;
4379
+ function directed(edge, forward) {
4380
+ const pts = forward ? edge.pts : [...edge.pts].reverse();
4381
+ const out = segmentTangent(pts, 0);
4382
+ const end = segmentTangent(pts, 1);
4383
+ return {
4384
+ from: forward ? edge.a : edge.b,
4385
+ to: forward ? edge.b : edge.a,
4386
+ pts,
4387
+ src: edge.src,
4388
+ sFrom: forward ? edge.sa : edge.sb,
4389
+ sTo: forward ? edge.sb : edge.sa,
4390
+ outAngle: Math.atan2(out[1], out[0]),
4391
+ backAngle: Math.atan2(-end[1], -end[0]),
4392
+ length: dist2(pts[0], pts[pts.length - 1]) + (pts.length > 2 ? flatness(pts) : 0)
4393
+ };
4394
+ }
4395
+ function chordAngle(pts, t) {
4396
+ const p = segmentPoint(pts, t);
4397
+ return Math.atan2(p[1] - pts[0][1], p[0] - pts[0][0]);
4398
+ }
4399
+ function mod2pi(a) {
4400
+ const r = a - Math.floor(a / TWO_PI) * TWO_PI;
4401
+ return r >= TWO_PI ? 0 : r;
4402
+ }
4403
+ function traceRings2(edges, scale2) {
4404
+ const outgoing = /* @__PURE__ */ new Map();
4405
+ for (const e of edges) {
4406
+ const list = outgoing.get(e.from.id);
4407
+ if (list) list.push(e);
4408
+ else outgoing.set(e.from.id, [e]);
4409
+ }
4410
+ const next = (incoming) => {
4411
+ const candidates = _optionalChain([outgoing, 'access', _76 => _76.get, 'call', _77 => _77(incoming.to.id), 'optionalAccess', _78 => _78.filter, 'call', _79 => _79((c) => !used.has(c) || c === start)]);
4412
+ if (!candidates || candidates.length === 0) return void 0;
4413
+ if (candidates.length === 1) return candidates[0];
4414
+ const turns = candidates.map((c) => mod2pi(incoming.backAngle - c.outAngle));
4415
+ const tied = (x) => x < TIE || x > TWO_PI - TIE;
4416
+ let ambiguous = turns.some(tied);
4417
+ if (!ambiguous) {
4418
+ const sorted = [...turns].sort((a, b) => a - b);
4419
+ for (let i = 1; i < sorted.length; i++) if (sorted[i] - sorted[i - 1] < TIE) ambiguous = true;
4420
+ }
4421
+ if (ambiguous) {
4422
+ const back = [...incoming.pts].reverse();
4423
+ let delta = Math.min(incoming.length, ...candidates.map((c) => c.length));
4424
+ delta = Math.min(delta * 0.25, scale2 * 0.02);
4425
+ const frac = (e) => Math.min(1, Math.max(1e-6, delta / Math.max(e.length, 1e-300)));
4426
+ const backChord = chordAngle(back, frac(incoming));
4427
+ for (let i = 0; i < candidates.length; i++) {
4428
+ turns[i] = mod2pi(backChord - chordAngle(candidates[i].pts, frac(candidates[i])));
4429
+ if (turns[i] < 1e-12) turns[i] = TWO_PI;
4430
+ }
4431
+ } else {
4432
+ for (let i = 0; i < turns.length; i++) if (turns[i] < 1e-15) turns[i] = TWO_PI;
4433
+ }
4434
+ let best = 0;
4435
+ for (let i = 1; i < candidates.length; i++) if (turns[i] < turns[best]) best = i;
4436
+ return candidates[best];
4437
+ };
4438
+ const used = /* @__PURE__ */ new Set();
4439
+ const rings = [];
4440
+ let start = null;
4441
+ for (const first of edges) {
4442
+ if (used.has(first)) continue;
4443
+ start = first;
4444
+ const ring = [];
4445
+ let edge = first;
4446
+ let guard = edges.length + 1;
4447
+ let closed = false;
4448
+ while (edge && guard-- > 0) {
4449
+ used.add(edge);
4450
+ ring.push(edge);
4451
+ edge = next(edge);
4452
+ if (edge === first) {
4453
+ closed = true;
4454
+ break;
4455
+ }
4456
+ }
4457
+ if (!closed) throw new PathOpsError("result outline does not close");
4458
+ rings.push(ring);
4459
+ }
4460
+ return rings;
4461
+ }
4462
+ function mergeable(a, b, sources, eps) {
4463
+ if (a.src === b.src && Math.abs(a.sTo - b.sFrom) < 1e-9 && a.sTo - a.sFrom > 0 === b.sTo - b.sFrom > 0) return true;
4464
+ if (a.pts.length === 2 && b.pts.length === 2) {
4465
+ const p = a.pts[0];
4466
+ const q = b.pts[1];
4467
+ const m = a.pts[1];
4468
+ const chord = sub2(q, p);
4469
+ const len = Math.hypot(chord[0], chord[1]);
4470
+ if (len === 0) return false;
4471
+ const off = Math.abs(cross(chord, sub2(m, p))) / len;
4472
+ const along = dot2(chord, sub2(m, p));
4473
+ return off <= eps && along > 0 && along < len * len;
4474
+ }
4475
+ void sources;
4476
+ return false;
4477
+ }
4478
+ function rebuildRing(ring, sources, eps) {
4479
+ const n = ring.length;
4480
+ let startIndex = 0;
4481
+ for (let k = 0; k < n; k++) {
4482
+ if (!mergeable(ring[(k + n - 1) % n], ring[k], sources, eps)) {
4483
+ startIndex = k;
4484
+ break;
4485
+ }
4486
+ }
4487
+ const ordered = [...ring.slice(startIndex), ...ring.slice(0, startIndex)];
4488
+ const out = [];
4489
+ let i = 0;
4490
+ while (i < ordered.length) {
4491
+ const first = ordered[i];
4492
+ let j = i + 1;
4493
+ while (j < ordered.length && mergeable(ordered[j - 1], ordered[j], sources, eps)) j++;
4494
+ const last = ordered[j - 1];
4495
+ if (j - i === 1) {
4496
+ out.push(first.pts);
4497
+ } else if (first.pts.length === 2 && ordered.slice(i, j).every((e) => e.pts.length === 2)) {
4498
+ out.push([first.from.p, last.to.p]);
4499
+ } else {
4500
+ const source = sources[first.src];
4501
+ out.push(snapEnds(subSegment(source.seg, first.sFrom, last.sTo), first.from.p, last.to.p));
4502
+ }
4503
+ i = j;
4504
+ }
4505
+ return out;
4506
+ }
4507
+ function extractRings(arr, isInside) {
4508
+ const kept = [];
4509
+ arr.edges.forEach((edge, i) => {
4510
+ const l = isInside(insideFlags2(arr.left[i], arr.fillRules));
4511
+ const r = isInside(insideFlags2(arr.right[i], arr.fillRules));
4512
+ if (l === r) return;
4513
+ kept.push(directed(edge, l));
4514
+ });
4515
+ const rings = [];
4516
+ const sliver = Math.max(arr.eps * 10, 1e-7 * arr.scale);
4517
+ for (const ring of traceRings2(kept, arr.scale)) {
4518
+ const segs = rebuildRing(ring, arr.sources, arr.eps);
4519
+ const area = contourSignedArea(segs);
4520
+ let perimeter = 0;
4521
+ for (const s of segs) perimeter += s.length === 2 ? dist2(s[0], s[1]) : segmentLength(s, 0, 1, 1e-6);
4522
+ if (!(perimeter > 0) || 2 * Math.abs(area) / perimeter < sliver) continue;
4523
+ rings.push({ segs, area });
4524
+ }
4525
+ return rings;
4526
+ }
4527
+ function ringSample(ring) {
4528
+ let best = ring.segs[0];
4529
+ let bestLen = -1;
4530
+ for (const s of ring.segs) {
4531
+ const l = dist2(s[0], s[s.length - 1]);
4532
+ if (l > bestLen) {
4533
+ best = s;
4534
+ bestLen = l;
4535
+ }
4536
+ }
4537
+ return segmentPoint(best, 0.5);
4538
+ }
4539
+ function groupRings(rings) {
4540
+ const outers = rings.filter((r) => r.area > 0).sort((a, b) => b.area - a.area);
4541
+ const holes = rings.filter((r) => r.area < 0);
4542
+ const groups = outers.map((o) => [o]);
4543
+ for (const hole of holes) {
4544
+ const sample = ringSample(hole);
4545
+ for (let i = outers.length - 1; i >= 0; i--) {
4546
+ if (outers[i].area >= -hole.area && windingNumber([outers[i].segs], sample) !== 0) {
4547
+ groups[i].push(hole);
4548
+ break;
4549
+ }
4550
+ }
4551
+ }
4552
+ return groups;
4553
+ }
4554
+ function ringsToPath2(rings) {
4555
+ return contoursToPath(rings.map((r) => ({ segments: r.segs, closed: true })));
4556
+ }
4557
+ function predicate2(operation) {
4558
+ switch (operation) {
4559
+ case "union":
4560
+ return (f) => f.some(Boolean);
4561
+ case "intersection":
4562
+ return (f) => f.length > 0 && f.every(Boolean);
4563
+ case "difference":
4564
+ return (f) => f[0] === true && !f.slice(1).some(Boolean);
4565
+ case "xor":
4566
+ return (f) => f.filter(Boolean).length % 2 === 1;
4567
+ }
4568
+ }
4569
+ function flattenOperand(input, tolerance) {
4570
+ const path = isOperandObject(input) ? input.path : input;
4571
+ const fillRule = isOperandObject(input) ? _nullishCoalesce(input.fillRule, () => ( "nonzero")) : "nonzero";
4572
+ const rings = pathToContours(_nullishCoalesce(path, () => ( ""))).map((c) => flattenChain(closeContour(c, true), tolerance)).filter((r) => r.length >= 3 && r.every((p) => Number.isFinite(p[0]) && Number.isFinite(p[1])));
4573
+ return { rings, fillRule };
4574
+ }
4575
+ function multiToPath(multi, tolerance) {
4576
+ if (multi.length === 0) return [];
4577
+ return toBezierPath(polygonToSvgPath(multi, { curves: "fit", curveTolerance: tolerance, precision: 9 }));
4578
+ }
4579
+ function reasonOf(error) {
4580
+ return error instanceof Error ? error.message : String(error);
4581
+ }
4582
+ function pathBoolean(operation, operands, options = {}) {
4583
+ if (operands.length === 0) return { path: [], engine: "curve" };
4584
+ try {
4585
+ const arr = buildArrangement(operands, options);
4586
+ return { path: ringsToPath2(extractRings(arr, predicate2(operation))), engine: "curve" };
4587
+ } catch (error) {
4588
+ const reason = reasonOf(error);
4589
+ if (reason === NON_FINITE) return { path: [], engine: "curve", error: reason };
4590
+ if (options.fallback === false) throw error;
4591
+ _optionalChain([options, 'access', _80 => _80.onFallback, 'optionalCall', _81 => _81(reason)]);
4592
+ const tolerance = _nullishCoalesce(options.fallbackTolerance, () => ( 0.05));
4593
+ const multi = polygonBoolean(
4594
+ operation,
4595
+ operands.map((o) => flattenOperand(o, tolerance)),
4596
+ { epsilon: options.epsilon }
4597
+ );
4598
+ return { path: multiToPath(multi, tolerance), engine: "polygon", fallbackReason: reason };
4599
+ }
4600
+ }
4601
+ var unitePaths = (a, b, options) => pathBoolean("union", [a, b], options).path;
4602
+ var intersectPaths = (a, b, options) => pathBoolean("intersection", [a, b], options).path;
4603
+ var subtractPaths = (a, b, options) => pathBoolean("difference", [a, b], options).path;
4604
+ var excludePaths = (a, b, options) => pathBoolean("xor", [a, b], options).path;
4605
+ function dividePaths(operands, options = {}) {
4606
+ if (operands.length === 0) return { pieces: [], engine: "curve" };
4607
+ try {
4608
+ const arr = buildArrangement(operands, options);
4609
+ const signatures = /* @__PURE__ */ new Map();
4610
+ const note = (windings) => {
4611
+ const flags = insideFlags2(windings, arr.fillRules);
4612
+ if (!flags.some(Boolean)) return;
4613
+ const key = flags.map((f) => f ? "1" : "0").join("");
4614
+ if (!signatures.has(key)) signatures.set(key, flags.flatMap((f, k) => f ? [k] : []));
4615
+ };
4616
+ arr.edges.forEach((_, i) => {
4617
+ note(arr.left[i]);
4618
+ note(arr.right[i]);
4619
+ });
4620
+ const pieces = [];
4621
+ for (const key of [...signatures.keys()].sort()) {
4622
+ const rings = extractRings(arr, (flags) => flags.map((f) => f ? "1" : "0").join("") === key);
4623
+ const groups = groupRings(rings).sort((a, b) => b[0].area - a[0].area);
4624
+ for (const group of groups) pieces.push({ path: ringsToPath2(group), operands: signatures.get(key) });
4625
+ }
4626
+ return { pieces, engine: "curve" };
4627
+ } catch (error) {
4628
+ const reason = reasonOf(error);
4629
+ if (reason === NON_FINITE) return { pieces: [], engine: "curve", error: reason };
4630
+ if (options.fallback === false) throw error;
4631
+ _optionalChain([options, 'access', _82 => _82.onFallback, 'optionalCall', _83 => _83(reason)]);
4632
+ const tolerance = _nullishCoalesce(options.fallbackTolerance, () => ( 0.05));
4633
+ const pieces = dividePolygons(
4634
+ operands.map((o) => flattenOperand(o, tolerance)),
4635
+ { epsilon: options.epsilon }
4636
+ ).map((p) => ({ path: multiToPath([p.polygon], tolerance), operands: p.operands }));
4637
+ return { pieces, engine: "polygon", fallbackReason: reason };
4638
+ }
4639
+ }
4640
+ function normalizeBezierPath(path, fillRule = "nonzero", options = {}) {
4641
+ return pathBoolean("union", [{ path, fillRule }], options).path;
4642
+ }
4643
+ function bezierPathArea(path, fillRule = "nonzero", options = {}) {
4644
+ const normalized = normalizeBezierPath(path, fillRule, options);
4645
+ let sum = 0;
4646
+ for (const contour of pathToContours(normalized)) sum += contourSignedArea(closeContour(contour, true));
4647
+ return Math.abs(sum);
4648
+ }
4649
+ function pathBooleanRings(operation, operands, options = {}) {
4650
+ const arr = buildArrangement(operands, options);
4651
+ const rings = extractRings(arr, typeof operation === "function" ? operation : predicate2(operation));
4652
+ const order = rings.map((_, i) => i).sort((a, b) => Math.abs(rings[a].area) - Math.abs(rings[b].area));
4653
+ return rings.map((ring, i) => {
4654
+ const sample = ringSample(ring);
4655
+ let parent = -1;
4656
+ for (const j of order) {
4657
+ if (j === i || Math.abs(rings[j].area) <= Math.abs(ring.area)) continue;
4658
+ if (windingNumber([rings[j].segs], sample) !== 0) {
4659
+ parent = j;
4660
+ break;
4661
+ }
4662
+ }
4663
+ return { segments: ring.segs, area: ring.area, parent };
4664
+ });
4665
+ }
4666
+ function nestedRingsToPath(rings, keep = () => true) {
4667
+ const contours = [];
4668
+ rings.forEach((r, i) => {
4669
+ if (keep(i)) contours.push({ segments: r.segments, closed: true });
4670
+ });
4671
+ return contoursToPath(contours);
4672
+ }
4673
+
4674
+ // src/canvas/pathops/stroke.ts
4675
+ var DEFAULT_TOLERANCE = 0.01;
4676
+ var normal = (t) => [-t[1], t[0]];
4677
+ function raise(seg) {
4678
+ if (seg.length !== 3) return [...seg];
4679
+ const [p0, p1, p2] = seg;
4680
+ return [p0, [p0[0] + 2 / 3 * (p1[0] - p0[0]), p0[1] + 2 / 3 * (p1[1] - p0[1])], [p2[0] + 2 / 3 * (p1[0] - p2[0]), p2[1] + 2 / 3 * (p1[1] - p2[1])], p2];
4681
+ }
4682
+ function isDegenerate(seg, tol) {
4683
+ return seg.every((p) => dist2(p, seg[0]) <= tol);
4684
+ }
4685
+ function offsetSegment(seg, d, tol, out, depth = 0) {
4686
+ if (seg.length === 2) {
4687
+ const n = normal(segmentTangent(seg, 0));
4688
+ out.push([add2(seg[0], scale(n, d)), add2(seg[1], scale(n, d))]);
4689
+ return;
4690
+ }
4691
+ const c = raise(seg);
4692
+ const t0 = segmentTangent(c, 0);
4693
+ const t1 = segmentTangent(c, 1);
4694
+ const q0 = add2(c[0], scale(normal(t0), d));
4695
+ const q3 = add2(c[3], scale(normal(t1), d));
4696
+ const k0 = segmentCurvature(c, 0);
4697
+ const k1 = segmentCurvature(c, 1);
4698
+ const f0 = Number.isFinite(k0) ? 1 - d * k0 : 1;
4699
+ const f1 = Number.isFinite(k1) ? 1 - d * k1 : 1;
4700
+ const q1 = add2(q0, scale(sub2(c[1], c[0]), f0));
4701
+ const q2 = add2(q3, scale(sub2(c[2], c[3]), f1));
4702
+ const approx = [q0, q1, q2, q3];
4703
+ if (depth < 10) {
4704
+ let err = 0;
4705
+ for (const t of [0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875]) {
4706
+ const target = add2(segmentPoint(c, t), scale(normal(segmentTangent(c, t)), d));
4707
+ err = Math.max(err, segmentNearest(approx, target).distance);
4708
+ if (err > tol) break;
4709
+ }
4710
+ if (err <= tol) {
4711
+ const m = segmentPoint(approx, 0.5);
4712
+ const back = segmentNearest(c, m).distance;
4713
+ err = Math.max(err, Math.abs(back - Math.abs(d)));
4714
+ }
4715
+ if (err > tol) {
4716
+ const [a, b] = splitSegment(c, 0.5);
4717
+ offsetSegment(a, d, tol, out, depth + 1);
4718
+ offsetSegment(b, d, tol, out, depth + 1);
4719
+ return;
4720
+ }
4721
+ }
4722
+ out.push(approx);
4723
+ }
4724
+ function pushArc(out, center, radius, start, sweep, from, to) {
4725
+ const n = Math.max(1, Math.ceil(Math.abs(sweep) / (Math.PI / 2) - 1e-9));
4726
+ const step = sweep / n;
4727
+ const k = 4 / 3 * Math.tan(step / 4);
4728
+ let prev = from;
4729
+ for (let i = 0; i < n; i++) {
4730
+ const a0 = start + step * i;
4731
+ const a1 = a0 + step;
4732
+ const c0 = Math.cos(a0);
4733
+ const s0 = Math.sin(a0);
4734
+ const c1 = Math.cos(a1);
4735
+ const s1 = Math.sin(a1);
4736
+ const end = i === n - 1 ? to : [center[0] + radius * c1, center[1] + radius * s1];
4737
+ out.push([
4738
+ prev,
4739
+ [center[0] + radius * (c0 - k * s0), center[1] + radius * (s0 + k * c0)],
4740
+ [center[0] + radius * (c1 + k * s1), center[1] + radius * (s1 - k * c1)],
4741
+ end
4742
+ ]);
4743
+ prev = end;
4744
+ }
4745
+ }
4746
+ function lineTo(out, from, to) {
4747
+ if (!samePoint(from, to)) out.push([from, to]);
4748
+ }
4749
+ function addJoin(out, p, tin, tout, d, style) {
4750
+ const from = add2(p, scale(normal(tin), d));
4751
+ const to = add2(p, scale(normal(tout), d));
4752
+ const turn = cross(tin, tout);
4753
+ const cos = dot2(tin, tout);
4754
+ if (Math.abs(turn) < 1e-9 && cos > 0) {
4755
+ lineTo(out, from, to);
4756
+ return;
4757
+ }
4758
+ const reversal = Math.abs(turn) < 1e-9 && cos < 0;
4759
+ const inner = !reversal && turn > 0 === d > 0;
4760
+ if (inner) {
4761
+ lineTo(out, from, p);
4762
+ lineTo(out, p, to);
4763
+ return;
4764
+ }
4765
+ const theta = reversal ? d > 0 ? -Math.PI : Math.PI : Math.atan2(turn, cos);
4766
+ if (style.join === "round") {
4767
+ const v = sub2(from, p);
4768
+ pushArc(out, p, Math.abs(d), Math.atan2(v[1], v[0]), theta, from, to);
4769
+ return;
4770
+ }
4771
+ if (style.join === "miter" && !reversal) {
4772
+ const phi = Math.PI - Math.abs(theta);
4773
+ const ratio = 1 / Math.max(Math.sin(phi / 2), 1e-12);
4774
+ if (ratio <= style.miterLimit) {
4775
+ const nin = normal(tin);
4776
+ const nout = normal(tout);
4777
+ const s = d / (1 + dot2(nin, nout));
4778
+ const miter = add2(p, scale(add2(nin, nout), s));
4779
+ lineTo(out, from, miter);
4780
+ lineTo(out, miter, to);
4781
+ return;
4782
+ }
4783
+ }
4784
+ lineTo(out, from, to);
4785
+ }
4786
+ function offsetChain(segs, d, closed, style, tol) {
4787
+ const out = [];
4788
+ const pen = () => out.length > 0 ? out[out.length - 1][out[out.length - 1].length - 1] : null;
4789
+ for (let i = 0; i < segs.length; i++) {
4790
+ if (i > 0) addJoin(out, segs[i][0], segmentTangent(segs[i - 1], 1), segmentTangent(segs[i], 0), d, style);
4791
+ const pieces = [];
4792
+ offsetSegment(segs[i], d, tol, pieces);
4793
+ for (const piece of pieces) {
4794
+ const at = pen();
4795
+ if (at && !samePoint(at, piece[0])) lineTo(out, at, piece[0]);
4796
+ out.push(piece);
4797
+ }
4798
+ }
4799
+ if (closed && segs.length > 0) {
4800
+ const last = segs[segs.length - 1];
4801
+ addJoin(out, segs[0][0], segmentTangent(last, 1), segmentTangent(segs[0], 0), d, style);
4802
+ const at = pen();
4803
+ if (at && out.length > 0 && !samePoint(at, out[0][0])) lineTo(out, at, out[0][0]);
4804
+ }
4805
+ return out;
4806
+ }
4807
+ function reverseChain(chain) {
4808
+ return chain.map((s) => [...s].reverse()).reverse();
4809
+ }
4810
+ function addCap(out, p, t, h, cap) {
4811
+ const n = normal(t);
4812
+ const from = add2(p, scale(n, h));
4813
+ const to = add2(p, scale(n, -h));
4814
+ if (cap === "round") {
4815
+ pushArc(out, p, h, Math.atan2(n[1], n[0]), -Math.PI, from, to);
4816
+ } else if (cap === "square") {
4817
+ const a = add2(from, scale(t, h));
4818
+ const b = add2(to, scale(t, h));
4819
+ lineTo(out, from, a);
4820
+ lineTo(out, a, b);
4821
+ lineTo(out, b, to);
4822
+ } else {
4823
+ lineTo(out, from, to);
4824
+ }
4825
+ }
4826
+ function dotRings(p, t, h, cap) {
4827
+ if (cap === "butt") return [];
4828
+ const ring = [];
4829
+ addCap(ring, p, t, h, cap);
4830
+ addCap(ring, p, [-t[0], -t[1]], h, cap);
4831
+ return [ring];
4832
+ }
4833
+ function strokeContour(contour, h, style, tol) {
4834
+ const tiny = Math.max(1e-12, tol * 1e-6);
4835
+ const all = contour.closed ? closeContour(contour) : contour.segments;
4836
+ const segs = all.filter((s) => !isDegenerate(s, tiny));
4837
+ if (segs.length === 0) {
4838
+ const p = _optionalChain([contour, 'access', _84 => _84.segments, 'access', _85 => _85[0], 'optionalAccess', _86 => _86[0]]);
4839
+ return p ? dotRings(p, [1, 0], h, style.cap) : [];
4840
+ }
4841
+ if (contour.closed) {
4842
+ const left2 = offsetChain(segs, h, true, style, tol);
4843
+ const right2 = offsetChain(segs, -h, true, style, tol);
4844
+ return [left2, reverseChain(right2)];
4845
+ }
4846
+ const left = offsetChain(segs, h, false, style, tol);
4847
+ const right = reverseChain(offsetChain(segs, -h, false, style, tol));
4848
+ const ring = [...left];
4849
+ const last = segs[segs.length - 1];
4850
+ addCap(ring, last[last.length - 1], segmentTangent(last, 1), h, style.cap);
4851
+ const joinTo = (p) => {
4852
+ const at = ring[ring.length - 1][ring[ring.length - 1].length - 1];
4853
+ lineTo(ring, at, p);
4854
+ };
4855
+ if (right.length > 0) joinTo(right[0][0]);
4856
+ ring.push(...right);
4857
+ const first = segs[0];
4858
+ const t0 = segmentTangent(first, 0);
4859
+ addCap(ring, first[0], [-t0[0], -t0[1]], h, style.cap);
4860
+ if (ring.length > 0) joinTo(ring[0][0]);
4861
+ return [ring];
4862
+ }
4863
+ function ringsToPath3(rings) {
4864
+ return contoursToPath(rings.filter((r) => r.length > 0).map((segments) => ({ segments, closed: true })));
4865
+ }
4866
+ var MAX_DASHES = 2e5;
4867
+ var MIN_ENTRY = 1e-6;
4868
+ function dashContours(contours, pattern, offset = 0) {
4869
+ if (pattern.length === 0 || pattern.some((v) => !Number.isFinite(v) || v < 0) || !Number.isFinite(offset)) return null;
4870
+ if (!pattern.some((v) => v > MIN_ENTRY)) return null;
4871
+ const pat = pattern.length % 2 === 1 ? [...pattern, ...pattern] : [...pattern];
4872
+ const period = pat.reduce((s, v) => s + v, 0);
4873
+ const chains = contours.map((c) => {
4874
+ const segs = closeContour(c);
4875
+ const lengths = segs.map((s) => segmentLength(s));
4876
+ return { segs, lengths, total: lengths.reduce((s, v) => s + v, 0), closed: c.closed };
4877
+ });
4878
+ const totalLength = chains.reduce((s, c) => s + c.total, 0);
4879
+ if (totalLength / period * pat.length > MAX_DASHES) return null;
4880
+ let off = (offset % period + period) % period;
4881
+ let ix0 = 0;
4882
+ while (off > pat[ix0]) {
4883
+ off -= pat[ix0];
4884
+ ix0 = (ix0 + 1) % pat.length;
4885
+ }
4886
+ const out = { contours: [], dots: [] };
4887
+ for (const chain of chains) {
4888
+ if (chain.segs.length === 0 || !(chain.total > 0)) continue;
4889
+ let ix = ix0;
4890
+ let rem = pat[ix0] - off;
4891
+ let pos = 0;
4892
+ const dashes = [];
4893
+ let guard = 0;
4894
+ while (pos < chain.total && guard++ < MAX_DASHES * 2) {
4895
+ const step = Math.min(rem, chain.total - pos);
4896
+ const on = ix % 2 === 0;
4897
+ if (on) dashes.push({ from: pos, to: pos + step });
4898
+ pos += step;
4899
+ rem -= step;
4900
+ if (rem <= 1e-12) {
4901
+ ix = (ix + 1) % pat.length;
4902
+ rem = pat[ix];
4903
+ }
4904
+ }
4905
+ if (chain.closed && dashes.length > 1) {
4906
+ const first = dashes[0];
4907
+ const last = dashes[dashes.length - 1];
4908
+ if (first.from <= 1e-9 && last.to >= chain.total - 1e-9 && first.to > first.from && last.to > last.from) {
4909
+ dashes.pop();
4910
+ const tail = trimSegments(chain.segs, last.from, chain.total, chain.lengths);
4911
+ const head = trimSegments(chain.segs, 0, first.to, chain.lengths);
4912
+ dashes.shift();
4913
+ out.contours.push({ segments: [...tail, ...head], closed: false });
4914
+ }
4915
+ }
4916
+ for (const dash of dashes) {
4917
+ if (dash.to - dash.from <= 1e-12) {
4918
+ const at = locate(chain.segs, chain.lengths, dash.from);
4919
+ out.dots.push(at);
4920
+ continue;
4921
+ }
4922
+ const segments = trimSegments(chain.segs, dash.from, dash.to, chain.lengths);
4923
+ if (segments.length > 0) out.contours.push({ segments, closed: false });
4924
+ }
4925
+ }
4926
+ return out;
4927
+ }
4928
+ function locate(segs, lengths, at) {
4929
+ let acc = 0;
4930
+ for (let i = 0; i < segs.length; i++) {
4931
+ if (at <= acc + lengths[i] || i === segs.length - 1) {
4932
+ const piece = trimSegments([segs[i]], 0, Math.max(0, at - acc), [lengths[i]]);
4933
+ const t = piece.length > 0 ? 1 : 0;
4934
+ const point = piece.length > 0 ? piece[piece.length - 1][piece[piece.length - 1].length - 1] : segs[i][0];
4935
+ const tangent = segmentTangent(piece.length > 0 ? piece[piece.length - 1] : segs[i], t);
4936
+ return { point, tangent };
4937
+ }
4938
+ acc += lengths[i];
4939
+ }
4940
+ return { point: segs[0][0], tangent: segmentTangent(segs[0], 0) };
4941
+ }
4942
+ function deepPoint(rings) {
4943
+ let minX = Infinity;
4944
+ let minY = Infinity;
4945
+ let maxX = -Infinity;
4946
+ let maxY = -Infinity;
4947
+ for (const p of rings[0].flat()) {
4948
+ minX = Math.min(minX, p[0]);
4949
+ maxX = Math.max(maxX, p[0]);
4950
+ minY = Math.min(minY, p[1]);
4951
+ maxY = Math.max(maxY, p[1]);
4952
+ }
4953
+ const w = maxX - minX;
4954
+ const h = maxY - minY;
4955
+ if (!(w > 0 && h > 0)) return null;
4956
+ const tolerance = Math.max(1e-6, 2e-3 * Math.min(w, h));
4957
+ const polys = rings.map((r) => flattenChain(r, tolerance));
4958
+ let best = null;
4959
+ for (const f of [0.5, 0.3, 0.7, 0.15, 0.85]) {
4960
+ const y = minY + h * f;
4961
+ const xs = [];
4962
+ for (const poly of polys) {
4963
+ for (let i = 0; i < poly.length; i++) {
4964
+ const a = poly[i];
4965
+ const b = poly[(i + 1) % poly.length];
4966
+ if (a[1] <= y !== b[1] <= y) xs.push(a[0] + (y - a[1]) / (b[1] - a[1]) * (b[0] - a[0]));
4967
+ }
4968
+ }
4969
+ xs.sort((p, q) => p - q);
4970
+ for (let i = 0; i + 1 < xs.length; i += 2) {
4971
+ const span = xs[i + 1] - xs[i];
4972
+ if (!best || span > best.span) best = { span, p: [(xs[i] + xs[i + 1]) / 2, y] };
4973
+ }
4974
+ }
4975
+ return _nullishCoalesce(_optionalChain([best, 'optionalAccess', _87 => _87.p]), () => ( null));
4976
+ }
4977
+ function dropSpurious(rings, spurious) {
4978
+ const children = rings.map(() => []);
4979
+ rings.forEach((r, i) => {
4980
+ if (r.parent >= 0) children[r.parent].push(i);
4981
+ });
4982
+ const marked = rings.map((r, i) => spurious([r.segments, ...children[i].map((c) => rings[c].segments)], r));
4983
+ const hasMarkedAncestor = (i) => {
4984
+ for (let k = i; k >= 0; k = rings[k].parent) if (marked[k]) return true;
4985
+ return false;
4986
+ };
4987
+ return nestedRingsToPath(rings, (i) => !hasMarkedAncestor(i));
4988
+ }
4989
+ function mergeSmoothRuns(path, tolerance) {
4990
+ const contours = pathToContours(path).map((contour) => {
4991
+ const segs = closeContour(contour, true).map((s) => s.length === 3 ? raise(s) : [...s]);
4992
+ const n = segs.length;
4993
+ if (n < 2) return { segments: segs, closed: true };
4994
+ const smooth = (a, b) => {
4995
+ if (a.length !== 4 || b.length !== 4) return false;
4996
+ const ta = segmentTangent(a, 1);
4997
+ const tb = segmentTangent(b, 0);
4998
+ return dot2(ta, tb) > 0.9998 && Math.abs(cross(ta, tb)) < 0.02;
4999
+ };
5000
+ let start = 0;
5001
+ for (let k = 0; k < n; k++) {
5002
+ if (!smooth(segs[(k + n - 1) % n], segs[k])) {
5003
+ start = k;
5004
+ break;
5005
+ }
5006
+ }
5007
+ const ordered = [...segs.slice(start), ...segs.slice(0, start)];
5008
+ const out = [];
5009
+ let i = 0;
5010
+ while (i < ordered.length) {
5011
+ let current = ordered[i];
5012
+ let j = i + 1;
5013
+ while (j < ordered.length && smooth(ordered[j - 1], ordered[j])) {
5014
+ const run = ordered.slice(i, j + 1);
5015
+ const pts = [];
5016
+ run.forEach((s, k) => {
5017
+ for (let q = k === 0 ? 0 : 1; q <= 12; q++) pts.push(segmentPoint(s, q / 12));
5018
+ });
5019
+ const fit = fitCubicRun(pts, tolerance, segmentTangent(run[0], 0), segmentTangent(run[run.length - 1], 1));
5020
+ if (fit.length !== 1) break;
5021
+ const c = fit[0];
5022
+ current = [run[0][0], c.p1, c.p2, run[run.length - 1][3]];
5023
+ j++;
5024
+ }
5025
+ out.push(current);
5026
+ i = j;
5027
+ }
5028
+ return { segments: out, closed: true };
5029
+ });
5030
+ return contoursToPath(contours);
5031
+ }
5032
+ function joinStyle(join, miterLimit) {
5033
+ return {
5034
+ join: _nullishCoalesce(join, () => ( "miter")),
5035
+ miterLimit: miterLimit !== void 0 && Number.isFinite(miterLimit) ? Math.max(1, miterLimit) : 4
5036
+ };
5037
+ }
5038
+ function strokeOutlineRings(input, options) {
5039
+ const h = options.width / 2;
5040
+ if (!(h > 0) || !Number.isFinite(h)) return [];
5041
+ const tol = options.tolerance && options.tolerance > 0 ? options.tolerance : DEFAULT_TOLERANCE;
5042
+ const style = { ...joinStyle(options.join, options.miterLimit), cap: _nullishCoalesce(options.cap, () => ( "butt")) };
5043
+ let contours = pathToContours(input);
5044
+ const rings = [];
5045
+ if (options.dash && options.dash.length > 0) {
5046
+ const dashed = dashContours(contours, options.dash, _nullishCoalesce(options.dashOffset, () => ( 0)));
5047
+ if (dashed) {
5048
+ contours = dashed.contours;
5049
+ for (const dot3 of dashed.dots) rings.push(...dotRings(dot3.point, dot3.tangent, h, style.cap));
5050
+ }
5051
+ }
5052
+ for (const contour of contours) rings.push(...strokeContour(contour, h, style, tol));
5053
+ return ringsToPath3(rings);
5054
+ }
5055
+ function outlineStroke(input, options) {
5056
+ const h = options.width / 2;
5057
+ if (!(h > 0) || !Number.isFinite(h)) return [];
5058
+ let source;
5059
+ try {
5060
+ source = contoursToPath(pathToContours(input));
5061
+ } catch (e6) {
5062
+ return [];
5063
+ }
5064
+ if (source.some((c) => c.type !== "Z" && Object.values(c).some((v) => typeof v === "number" && !Number.isFinite(v)))) return [];
5065
+ const raw = strokeOutlineRings(source, options);
5066
+ if (raw.length === 0) return [];
5067
+ const tol = options.tolerance && options.tolerance > 0 ? options.tolerance : DEFAULT_TOLERANCE;
5068
+ const sourceContours = pathToContours(source);
5069
+ const operand = { path: raw, fillRule: "nonzero" };
5070
+ try {
5071
+ const rings = pathBooleanRings("union", [operand], options);
5072
+ const cleaned = dropSpurious(rings, (face, ring) => {
5073
+ if (ring.area >= 0) return false;
5074
+ const p = deepPoint(face);
5075
+ return !!p && distanceToBezierPath(sourceContours, p) < h * (1 - 1e-4) - 1e-6;
5076
+ });
5077
+ return mergeSmoothRuns(cleaned, tol);
5078
+ } catch (e7) {
5079
+ return pathBoolean("union", [operand], options).path;
5080
+ }
5081
+ }
5082
+ function offsetPath(input, distance, options = {}) {
5083
+ if (!Number.isFinite(distance)) return [];
5084
+ const contours = pathToContours(input);
5085
+ if (contours.some((c) => c.segments.some((s) => s.some((p) => !Number.isFinite(p[0]) || !Number.isFinite(p[1]))))) return [];
5086
+ const closed = contours.filter((c) => c.closed && c.segments.length > 0);
5087
+ const open = contours.filter((c) => !c.closed && c.segments.length > 0);
5088
+ const fillRule = _nullishCoalesce(options.fillRule, () => ( "nonzero"));
5089
+ const fill = { path: contoursToPath(closed), fillRule };
5090
+ const d = Math.abs(distance);
5091
+ const tol = options.tolerance && options.tolerance > 0 ? options.tolerance : DEFAULT_TOLERANCE;
5092
+ if (d === 0) return pathBoolean("union", [fill], options).path;
5093
+ const strokeOptions = { width: 2 * d, join: _nullishCoalesce(options.join, () => ( "miter")), miterLimit: options.miterLimit, cap: "butt", tolerance: tol };
5094
+ const ring = { path: strokeOutlineRings(contoursToPath(closed), strokeOptions), fillRule: "nonzero" };
5095
+ const openRing = {
5096
+ path: distance > 0 ? strokeOutlineRings(contoursToPath(open), strokeOptions) : [],
5097
+ fillRule: "nonzero"
5098
+ };
5099
+ const grow = distance > 0;
5100
+ const operands = [fill, ring, openRing];
5101
+ try {
5102
+ const rings = pathBooleanRings(grow ? (m) => m[0] || m[1] || m[2] : (m) => m[0] && !m[1], operands, options);
5103
+ const sourceContours = contours;
5104
+ const cleaned = dropSpurious(rings, (face, r) => {
5105
+ if (grow ? r.area >= 0 : r.area <= 0) return false;
5106
+ const p = deepPoint(face);
5107
+ return !!p && distanceToBezierPath(sourceContours, p) < d * (1 - 1e-4) - 1e-6;
5108
+ });
5109
+ return mergeSmoothRuns(cleaned, tol);
5110
+ } catch (e8) {
5111
+ return grow ? pathBoolean("union", operands, options).path : pathBoolean("difference", [fill, ring], options).path;
5112
+ }
5113
+ }
5114
+
5115
+ // src/canvas/shapeNodes.ts
5116
+ var SHAPE_DATA_KEY = "shape";
5117
+ var SHAPE_NODE_TYPE = "shape";
5118
+ var SHAPE_OPERATIONS = ["unite", "intersect", "subtract", "exclude", "divide"];
5119
+ var BOOLEAN_FOR = {
5120
+ unite: "union",
5121
+ intersect: "intersection",
5122
+ subtract: "difference",
5123
+ exclude: "xor"
5124
+ };
5125
+ function isShapeNode(node) {
5126
+ return !!node && isShapeDescription(_optionalChain([node, 'access', _88 => _88.data, 'optionalAccess', _89 => _89[SHAPE_DATA_KEY]]));
5127
+ }
5128
+ function getNodeShape(node) {
5129
+ const shape = _optionalChain([node, 'optionalAccess', _90 => _90.data, 'optionalAccess', _91 => _91[SHAPE_DATA_KEY]]);
5130
+ return isShapeDescription(shape) ? shape : null;
5131
+ }
5132
+ function shapeNodeToPolygon(node, lookup, options = {}) {
5133
+ const shape = getNodeShape(node);
5134
+ if (!shape) return null;
5135
+ const size = getNodeSize(node, options);
5136
+ const origin = node.parentId && lookup ? getAbsolutePosition(node, lookup) : node.position;
5137
+ const { rings, fillRule } = shapeToPolygon(shape, size, { tolerance: options.tolerance });
5138
+ return {
5139
+ rings: rings.map((ring) => ring.map(([x, y]) => [x + origin.x, y + origin.y])),
5140
+ fillRule
5141
+ };
5142
+ }
5143
+ function shapeToBezierPath(shape, size) {
5144
+ const { width: w, height: h } = size;
5145
+ if (!(w > 0) || !(h > 0)) return { path: [], fillRule: "nonzero" };
5146
+ const svg = getShapeSvg({ ...shape, rotation: 0 }, size);
5147
+ let path = toBezierPath(svg.d);
5148
+ if (shape.kind === "path" && shape.viewBox) {
5149
+ const vb = shape.viewBox;
5150
+ if (vb.length === 4 && vb.every(Number.isFinite) && vb[2] > 0 && vb[3] > 0) {
5151
+ const sx = w / vb[2];
5152
+ const sy = h / vb[3];
5153
+ path = transformBezierPath(path, [sx, 0, 0, sy, -vb[0] * sx, -vb[1] * sy]);
5154
+ }
5155
+ }
5156
+ const deg = _nullishCoalesce(shape.rotation, () => ( 0));
5157
+ if (deg && Number.isFinite(deg)) {
5158
+ const rad = deg * Math.PI / 180;
5159
+ const cos = Math.cos(rad);
5160
+ const sin = Math.sin(rad);
5161
+ const cx = w / 2;
5162
+ const cy = h / 2;
5163
+ const m = [cos, sin, -sin, cos, cx - cx * cos + cy * sin, cy - cx * sin - cy * cos];
5164
+ path = transformBezierPath(path, m);
5165
+ }
5166
+ return { path, fillRule: svg.fillRule };
5167
+ }
5168
+ function shapeNodeToBezierPath(node, lookup, options = {}) {
5169
+ const shape = getNodeShape(node);
5170
+ if (!shape) return null;
5171
+ const size = getNodeSize(node, options);
5172
+ const origin = node.parentId && lookup ? getAbsolutePosition(node, lookup) : node.position;
5173
+ const { path, fillRule } = shapeToBezierPath(shape, size);
5174
+ return { path: transformBezierPath(path, [1, 0, 0, 1, origin.x, origin.y]), fillRule };
5175
+ }
5176
+ var idCounter = 0;
5177
+ function defaultId2(index) {
5178
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
5179
+ idCounter += 1;
5180
+ return `shape-${Date.now().toString(36)}-${idCounter}-${index}`;
5181
+ }
5182
+ function stackOrder(nodes, ids) {
5183
+ return nodes.map((node, index) => ({ node, index, z: typeof node.zIndex === "number" ? node.zIndex : 0 })).filter((entry) => ids.has(entry.node.id)).sort((a, b) => a.z - b.z || a.index - b.index).map((entry) => entry.node);
5184
+ }
5185
+ function canCombineShapeNodes(nodes, ids) {
5186
+ const idSet = new Set(ids);
5187
+ const shapes = nodes.filter((n) => idSet.has(n.id) && isShapeNode(n));
5188
+ if (shapes.some((n) => isLocked(n))) return { ok: false, reason: "locked" };
5189
+ if (shapes.length < 2) return { ok: false, reason: "too-few" };
5190
+ return { ok: true, shapeIds: shapes.map((n) => n.id) };
5191
+ }
5192
+ function combineShapeNodes(nodes, ids, operation, options = {}) {
5193
+ const idList = [...ids];
5194
+ const check = canCombineShapeNodes(nodes, idList);
5195
+ if (!check.ok) return { ok: false, operation, reason: check.reason };
5196
+ const lookup = createNodeLookup(nodes);
5197
+ const shapeIds = new Set(check.shapeIds);
5198
+ const ordered = stackOrder(nodes, shapeIds);
5199
+ const parentIds = new Set(ordered.map((n) => _nullishCoalesce(n.parentId, () => ( ""))));
5200
+ const sharedParent = parentIds.size === 1 ? ordered[0].parentId : void 0;
5201
+ const parentOrigin = sharedParent && lookup.get(sharedParent) ? getAbsolutePosition(lookup.get(sharedParent), lookup) : { x: 0, y: 0 };
5202
+ const pickSource = () => {
5203
+ const style = _nullishCoalesce(options.styleFrom, () => ( "bottom"));
5204
+ if (style === "top") return ordered[ordered.length - 1];
5205
+ if (style === "first") {
5206
+ const first = idList.find((id) => shapeIds.has(id));
5207
+ return first && lookup.get(first) || ordered[0];
5208
+ }
5209
+ if (typeof style === "object") return shapeIds.has(style.id) && lookup.get(style.id) || ordered[0];
5210
+ return ordered[0];
5211
+ };
5212
+ const createId = _nullishCoalesce(options.createId, () => ( defaultId2));
5213
+ const buildOptions = {
5214
+ precision: options.precision,
5215
+ nodeType: options.nodeType,
5216
+ select: options.select,
5217
+ parentOrigin,
5218
+ sharedParent
5219
+ };
5220
+ const engine = _nullishCoalesce(options.engine, () => ( (options.curves === "lines" ? "polygon" : "curve")));
5221
+ const created = [];
5222
+ let report = { engine: "curve" };
5223
+ if (engine === "curve") {
5224
+ const operands = ordered.map((node) => shapeNodeToBezierPath(node, lookup, options));
5225
+ const pathOptions = { epsilon: options.epsilon, onFallback: options.onFallback, fallbackTolerance: options.tolerance };
5226
+ if (operation === "divide") {
5227
+ const result = dividePaths(operands, pathOptions);
5228
+ report = result;
5229
+ for (const piece of result.pieces) {
5230
+ const source = ordered[piece.operands[piece.operands.length - 1]];
5231
+ const node = buildPathNode(piece.path, source, createId(created.length), buildOptions);
5232
+ if (node) created.push(node);
5233
+ }
5234
+ } else {
5235
+ const result = pathBoolean(BOOLEAN_FOR[operation], operands, pathOptions);
5236
+ report = result;
5237
+ const node = buildPathNode(result.path, pickSource(), createId(0), buildOptions);
5238
+ if (node) created.push(node);
5239
+ }
5240
+ } else {
5241
+ report = { engine: "polygon" };
5242
+ const operands = ordered.map((node) => shapeNodeToPolygon(node, lookup, options));
5243
+ const write = (polygon) => toBezierPath(
5244
+ polygonToSvgPath(polygon, {
5245
+ precision: 9,
5246
+ simplify: options.simplify,
5247
+ curves: _nullishCoalesce(options.curves, () => ( "fit")),
5248
+ curveTolerance: _nullishCoalesce(_nullishCoalesce(options.curveTolerance, () => ( options.tolerance)), () => ( 0.25)),
5249
+ cornerAngleDeg: options.cornerAngleDeg
5250
+ })
5251
+ );
5252
+ if (operation === "divide") {
5253
+ for (const piece of dividePolygons(operands, { epsilon: options.epsilon })) {
5254
+ const source = ordered[piece.operands[piece.operands.length - 1]];
5255
+ const node = buildPathNode(write([piece.polygon]), source, createId(created.length), buildOptions);
5256
+ if (node) created.push(node);
5257
+ }
5258
+ } else {
5259
+ const result = polygonBoolean(BOOLEAN_FOR[operation], operands, { epsilon: options.epsilon });
5260
+ const node = buildPathNode(write(result), pickSource(), createId(0), buildOptions);
5261
+ if (node) created.push(node);
5262
+ }
5263
+ }
5264
+ if (created.length === 0) return { ok: false, operation, reason: "empty" };
5265
+ const done = {
5266
+ ok: true,
5267
+ operation,
5268
+ removeIds: ordered.map((n) => n.id),
5269
+ nodes: created,
5270
+ engine: report.engine
5271
+ };
5272
+ if (report.fallbackReason) done.fallbackReason = report.fallbackReason;
5273
+ return done;
5274
+ }
5275
+ function buildPathNode(path, source, id, options) {
5276
+ const bounds = bezierPathBounds(path);
5277
+ if (!bounds) return null;
5278
+ const width = bounds.maxX - bounds.minX;
5279
+ const height = bounds.maxY - bounds.minY;
5280
+ if (!(width > 0) || !(height > 0)) return null;
5281
+ const d = bezierPathToSvg(path, { precision: _nullishCoalesce(options.precision, () => ( 3)), offset: { x: -bounds.minX, y: -bounds.minY } });
5282
+ if (!d) return null;
5283
+ const sourceShape = getNodeShape(source);
5284
+ const shape = {
5285
+ kind: "path",
5286
+ d,
5287
+ viewBox: [0, 0, roundSize(width), roundSize(height)],
5288
+ fillRule: "nonzero"
5289
+ };
5290
+ for (const key of ["fill", "stroke", "strokeWidth", "opacity"]) {
5291
+ if (sourceShape[key] !== void 0) shape[key] = sourceShape[key];
5292
+ }
5293
+ for (const [key, value] of Object.entries(_nullishCoalesce(options.paint, () => ( {})))) {
5294
+ if (value === null) delete shape[key];
5295
+ else if (value !== void 0) shape[key] = value;
5296
+ }
5297
+ const {
5298
+ [LOCKED_DATA_KEY]: _locked,
5299
+ [LOCKED_PREVIOUS_FLAGS_KEY]: _previous,
5300
+ ...data
5301
+ } = _nullishCoalesce(source.data, () => ( {}));
5302
+ const {
5303
+ measured: _measured,
5304
+ selected: _selected,
5305
+ dragging: _dragging,
5306
+ positionAbsolute: _positionAbsolute,
5307
+ internals: _internals,
5308
+ parentId: _parentId,
5309
+ ...rest
5310
+ } = source;
5311
+ const node = {
5312
+ ...rest,
5313
+ id,
5314
+ position: { x: bounds.minX - options.parentOrigin.x, y: bounds.minY - options.parentOrigin.y },
5315
+ width,
5316
+ height,
5317
+ data: { ...data, [SHAPE_DATA_KEY]: shape }
5318
+ };
5319
+ if (options.sharedParent) node.parentId = options.sharedParent;
5320
+ if (options.nodeType !== void 0) node.type = options.nodeType;
5321
+ if (source.style) node.style = withStyleSize(source.style, { width, height });
5322
+ if (options.select !== false) node.selected = true;
5323
+ return node;
5324
+ }
5325
+ function roundSize(value) {
5326
+ return Math.round(value * 1e3) / 1e3;
5327
+ }
5328
+ function applyShapeCombination(nodes, change, options = {}) {
5329
+ const remove = new Set(change.removeIds);
5330
+ const insertAt = nodes.findIndex((n) => remove.has(n.id));
5331
+ const deselect = options.deselect !== false && change.nodes.some((n) => n.selected);
5332
+ const out = [];
5333
+ nodes.forEach((node, index) => {
5334
+ if (index === insertAt) out.push(...change.nodes);
5335
+ if (remove.has(node.id)) return;
5336
+ out.push(deselect && node.selected ? { ...node, selected: false } : node);
5337
+ });
5338
+ if (insertAt === -1) out.push(...change.nodes);
5339
+ return out;
5340
+ }
5341
+ function revertShapeCombination(nodes, change, previous) {
5342
+ const created = new Set(change.nodes.map((n) => n.id));
5343
+ const removed = new Set(change.removeIds);
5344
+ const out = nodes.filter((n) => !created.has(n.id));
5345
+ previous.forEach((node, index) => {
5346
+ if (!removed.has(node.id) || out.some((n) => n.id === node.id)) return;
5347
+ out.splice(Math.min(index, out.length), 0, node);
5348
+ });
5349
+ return out;
5350
+ }
5351
+ var INVISIBLE_PAINT = /* @__PURE__ */ new Set(["none", "transparent"]);
5352
+ function hasVisibleStroke(shape) {
5353
+ if (!shape || typeof shape.stroke !== "string" || INVISIBLE_PAINT.has(shape.stroke.trim().toLowerCase())) return false;
5354
+ const width = _nullishCoalesce(shape.strokeWidth, () => ( 1));
5355
+ return Number.isFinite(width) && width > 0;
5356
+ }
5357
+ function hasVisibleFill(shape) {
5358
+ return shape.fill === void 0 || !INVISIBLE_PAINT.has(String(shape.fill).trim().toLowerCase());
5359
+ }
5360
+ function shapeTargets(nodes, ids) {
5361
+ const idSet = new Set(ids);
5362
+ return nodes.filter((n) => idSet.has(n.id) && isShapeNode(n));
5363
+ }
5364
+ function canOffsetShapeNodes(nodes, ids) {
5365
+ const shapes = shapeTargets(nodes, ids);
5366
+ if (shapes.some((n) => isLocked(n))) return { ok: false, reason: "locked" };
5367
+ if (shapes.length === 0) return { ok: false, reason: "no-shapes" };
5368
+ return { ok: true, shapeIds: shapes.map((n) => n.id) };
5369
+ }
5370
+ function canOutlineShapeNodeStrokes(nodes, ids) {
5371
+ const shapes = shapeTargets(nodes, ids);
5372
+ if (shapes.some((n) => isLocked(n))) return { ok: false, reason: "locked" };
5373
+ if (shapes.length === 0) return { ok: false, reason: "no-shapes" };
5374
+ const stroked = shapes.filter((n) => hasVisibleStroke(getNodeShape(n)));
5375
+ if (stroked.length === 0) return { ok: false, reason: "no-stroke" };
5376
+ return { ok: true, shapeIds: stroked.map((n) => n.id) };
5377
+ }
5378
+ function editPlacement(node, lookup) {
5379
+ const parent = node.parentId ? lookup.get(node.parentId) : void 0;
5380
+ return {
5381
+ parentOrigin: parent ? getAbsolutePosition(parent, lookup) : { x: 0, y: 0 },
5382
+ sharedParent: parent ? node.parentId : void 0
5383
+ };
5384
+ }
5385
+ function finishEdit(operation, replacements) {
5386
+ if (replacements.length === 0) return { ok: false, operation, reason: "empty" };
5387
+ return {
5388
+ ok: true,
5389
+ operation,
5390
+ removeIds: replacements.map((r) => r.id),
5391
+ nodes: replacements.flatMap((r) => r.nodes),
5392
+ replacements
5393
+ };
5394
+ }
5395
+ function offsetShapeNodes(nodes, ids, distance, options = {}) {
5396
+ const operation = "offset";
5397
+ if (!Number.isFinite(distance)) return { ok: false, operation, reason: "invalid" };
5398
+ const check = canOffsetShapeNodes(nodes, ids);
5399
+ if (!check.ok) return { ok: false, operation, reason: check.reason };
5400
+ const lookup = createNodeLookup(nodes);
5401
+ const createId = _nullishCoalesce(options.createId, () => ( defaultId2));
5402
+ let index = 0;
5403
+ const replacements = [];
5404
+ for (const id of check.shapeIds) {
5405
+ const node = lookup.get(id);
5406
+ const outline = shapeNodeToBezierPath(node, lookup, options);
5407
+ const path = offsetPath(outline.path, distance, {
5408
+ join: options.join,
5409
+ miterLimit: options.miterLimit,
5410
+ fillRule: outline.fillRule,
5411
+ tolerance: options.tolerance,
5412
+ epsilon: options.epsilon,
5413
+ onFallback: options.onFallback
5414
+ });
5415
+ const created = buildPathNode(path, node, createId(index), {
5416
+ ...editPlacement(node, lookup),
5417
+ precision: options.precision,
5418
+ nodeType: options.nodeType,
5419
+ select: options.select
5420
+ });
5421
+ if (!created) continue;
5422
+ index++;
5423
+ const original = { ...node, selected: false };
5424
+ replacements.push({ id, nodes: options.keepOriginal ? [created, original] : [created] });
5425
+ }
5426
+ return finishEdit(operation, replacements);
5427
+ }
5428
+ function outlineShapeNodeStrokes(nodes, ids, options = {}) {
5429
+ const operation = "outlineStroke";
5430
+ if (options.width !== void 0 && !(Number.isFinite(options.width) && options.width > 0)) {
5431
+ return { ok: false, operation, reason: "invalid" };
5432
+ }
5433
+ const check = canOutlineShapeNodeStrokes(nodes, ids);
5434
+ if (!check.ok) return { ok: false, operation, reason: check.reason };
5435
+ const lookup = createNodeLookup(nodes);
5436
+ const createId = _nullishCoalesce(options.createId, () => ( defaultId2));
5437
+ let index = 0;
5438
+ const replacements = [];
5439
+ for (const id of check.shapeIds) {
5440
+ const node = lookup.get(id);
5441
+ const shape = getNodeShape(node);
5442
+ const outline = shapeNodeToBezierPath(node, lookup, options);
5443
+ const path = outlineStroke(outline.path, {
5444
+ width: _nullishCoalesce(_nullishCoalesce(options.width, () => ( shape.strokeWidth)), () => ( 1)),
5445
+ join: options.join,
5446
+ cap: options.cap,
5447
+ miterLimit: options.miterLimit,
5448
+ dash: options.dash,
5449
+ dashOffset: options.dashOffset,
5450
+ tolerance: options.tolerance,
5451
+ epsilon: options.epsilon,
5452
+ onFallback: options.onFallback
5453
+ });
5454
+ const created = buildPathNode(path, node, createId(index), {
5455
+ ...editPlacement(node, lookup),
5456
+ precision: options.precision,
5457
+ nodeType: options.nodeType,
5458
+ select: options.select,
5459
+ paint: { fill: shape.stroke, stroke: null, strokeWidth: null }
5460
+ });
5461
+ if (!created) continue;
5462
+ index++;
5463
+ const replacement = [];
5464
+ if (options.keepFill !== false && hasVisibleFill(shape)) {
5465
+ const { stroke: _stroke, strokeWidth: _width, ...rest } = shape;
5466
+ replacement.push({
5467
+ ...node,
5468
+ selected: options.select === false ? node.selected : false,
5469
+ data: { ...node.data, [SHAPE_DATA_KEY]: rest }
5470
+ });
5471
+ }
5472
+ replacement.push(created);
5473
+ replacements.push({ id, nodes: replacement });
5474
+ }
5475
+ return finishEdit(operation, replacements);
5476
+ }
5477
+ function applyShapeReplacement(nodes, change, options = {}) {
5478
+ const byId = new Map(change.replacements.map((r) => [r.id, r.nodes]));
5479
+ const created = new Set(change.replacements.flatMap((r) => r.nodes.map((n) => n.id)));
5480
+ const deselect = options.deselect !== false && change.replacements.some((r) => r.nodes.some((n) => n.selected));
5481
+ const out = [];
5482
+ for (const node of nodes) {
5483
+ const replacement = byId.get(node.id);
5484
+ if (replacement) {
5485
+ out.push(...replacement);
5486
+ continue;
5487
+ }
5488
+ if (created.has(node.id)) continue;
5489
+ out.push(deselect && node.selected ? { ...node, selected: false } : node);
5490
+ }
5491
+ return out;
5492
+ }
5493
+
5494
+ // src/canvas/resizeSnap.ts
5495
+ var RESIZE_HANDLES = [
5496
+ "top-left",
5497
+ "top",
5498
+ "top-right",
5499
+ "right",
5500
+ "bottom-right",
5501
+ "bottom",
5502
+ "bottom-left",
5503
+ "left"
5504
+ ];
5505
+ function resizeHandleAxes(handle) {
5506
+ const x = handle.includes("left") ? -1 : handle.includes("right") ? 1 : 0;
5507
+ const y = handle.includes("top") ? -1 : handle.includes("bottom") ? 1 : 0;
5508
+ return { x, y };
5509
+ }
5510
+ function inferResizeHandle(start, next, eps = 1e-6) {
5511
+ const moved = (a, b) => Math.abs(a - b) > eps;
5512
+ const left = moved(start.x, next.x);
5513
+ const right = moved(start.x + start.width, next.x + next.width);
5514
+ const top = moved(start.y, next.y);
5515
+ const bottom = moved(start.y + start.height, next.y + next.height);
5516
+ const h = left ? "left" : right ? "right" : "";
5517
+ const v = top ? "top" : bottom ? "bottom" : "";
5518
+ if (h && v) return `${v}-${h}`;
5519
+ return h || v || null;
5520
+ }
5521
+ function within(axis, v, tolerance) {
5522
+ const { values } = axis;
5523
+ let lo = 0;
5524
+ let hi = values.length;
5525
+ while (lo < hi) {
5526
+ const mid = lo + hi >>> 1;
5527
+ if (values[mid] < v - tolerance) lo = mid + 1;
5528
+ else hi = mid;
5529
+ }
5530
+ const out = [];
5531
+ for (let i = lo; i < values.length && values[i] <= v + tolerance; i++) out.push(values[i]);
5532
+ return out;
5533
+ }
5534
+ function matching(axis, v, eps) {
5535
+ const { values, rects } = axis;
5536
+ const out = [];
5537
+ for (let i = 0; i < values.length; i++) if (Math.abs(values[i] - v) <= eps) out.push(rects[i]);
5538
+ return out;
5539
+ }
5540
+ function snapResize(rect, handle, targets, options = {}) {
5541
+ const index = Array.isArray(targets) ? createGuideIndex(targets) : targets;
5542
+ const zoom = options.zoom && options.zoom > 0 ? options.zoom : 1;
5543
+ const tolerance = (_nullishCoalesce(options.threshold, () => ( 6))) / zoom;
5544
+ const eps = 0.5 / zoom;
5545
+ const useEdges = options.edges !== false;
5546
+ const useCentres = options.centres !== false;
5547
+ const grid = _nullishCoalesce(options.gridSize, () => ( 0));
5548
+ const axes = resizeHandleAxes(handle);
5549
+ const unchanged = { rect: { ...rect }, guides: [], snappedX: false, snappedY: false, changed: false };
5550
+ if (![rect.x, rect.y, rect.width, rect.height].every(Number.isFinite)) return unchanged;
5551
+ const x0 = rect.x;
5552
+ const x1 = rect.x + rect.width;
5553
+ const y0 = rect.y;
5554
+ const y1 = rect.y + rect.height;
5555
+ const bestHit = (horizontal) => {
5556
+ const dir = horizontal ? axes.x : axes.y;
5557
+ if (dir === 0) return null;
5558
+ const moving = horizontal ? dir < 0 ? x0 : x1 : dir < 0 ? y0 : y1;
5559
+ const fixed = horizontal ? dir < 0 ? x1 : x0 : dir < 0 ? y1 : y0;
5560
+ const min = _nullishCoalesce((horizontal ? options.minWidth : options.minHeight), () => ( 0));
5561
+ const valid = (t) => {
5562
+ const size = dir < 0 ? fixed - t : t - fixed;
5563
+ return Number.isFinite(size) && size > 1e-9 && size >= min;
5564
+ };
5565
+ let best = null;
5566
+ const consider = (values, kind) => {
5567
+ for (const t of values) {
5568
+ if (!valid(t)) continue;
5569
+ if (!best || Math.abs(t - moving) < Math.abs(best.value - moving)) best = { value: t, kind };
5570
+ }
5571
+ };
5572
+ if (useEdges) consider(within(horizontal ? index.edgeX : index.edgeY, moving, tolerance), "edge");
5573
+ if (useCentres) consider(within(horizontal ? index.centreX : index.centreY, moving, tolerance), "centre");
5574
+ if (!best && grid > 0) {
5575
+ const origin = horizontal ? _nullishCoalesce(_optionalChain([options, 'access', _92 => _92.gridOrigin, 'optionalAccess', _93 => _93.x]), () => ( 0)) : _nullishCoalesce(_optionalChain([options, 'access', _94 => _94.gridOrigin, 'optionalAccess', _95 => _95.y]), () => ( 0));
5576
+ consider([snapToGrid(moving, grid, origin)], "grid");
5577
+ }
5578
+ return best;
5579
+ };
5580
+ let nx0 = x0;
5581
+ let nx1 = x1;
5582
+ let ny0 = y0;
5583
+ let ny1 = y1;
5584
+ const setEdge = (horizontal, value) => {
5585
+ const dir = horizontal ? axes.x : axes.y;
5586
+ if (horizontal) {
5587
+ if (dir < 0) nx0 = value;
5588
+ else nx1 = value;
5589
+ } else if (dir < 0) ny0 = value;
5590
+ else ny1 = value;
5591
+ };
5592
+ let hitX = bestHit(true);
5593
+ let hitY = bestHit(false);
5594
+ const ratio = rect.height > 0 ? rect.width / rect.height : 0;
3302
5595
  if (options.keepAspectRatio && ratio > 0 && (hitX || hitY)) {
3303
5596
  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);
5597
+ const dist3 = (h, horizontal) => h ? Math.abs(h.value - (horizontal ? axes.x < 0 ? x0 : x1 : axes.y < 0 ? y0 : y1)) : Infinity;
5598
+ const useX = dist3(hitX, true) <= dist3(hitY, false);
3306
5599
  if (useX && hitX) {
3307
5600
  setEdge(true, hitX.value);
3308
5601
  const height = (nx1 - nx0) / ratio;
@@ -3403,25 +5696,25 @@ function clampLayoutSize(value, min, max) {
3403
5696
  }
3404
5697
  var finite = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
3405
5698
  function getAutoLayout(node) {
3406
- const layout2 = _optionalChain([node, 'optionalAccess', _79 => _79.data, 'optionalAccess', _80 => _80[AUTO_LAYOUT_DATA_KEY]]);
5699
+ const layout2 = _optionalChain([node, 'optionalAccess', _96 => _96.data, 'optionalAccess', _97 => _97[AUTO_LAYOUT_DATA_KEY]]);
3407
5700
  return layout2 && typeof layout2 === "object" && MODES.has(layout2.mode) ? layout2 : void 0;
3408
5701
  }
3409
5702
  function isAutoLayoutFrame(node) {
3410
5703
  return getAutoLayout(node) !== void 0;
3411
5704
  }
3412
5705
  function getChildLayout(node) {
3413
- const child = _optionalChain([node, 'optionalAccess', _81 => _81.data, 'optionalAccess', _82 => _82[CHILD_LAYOUT_DATA_KEY]]);
5706
+ const child = _optionalChain([node, 'optionalAccess', _98 => _98.data, 'optionalAccess', _99 => _99[CHILD_LAYOUT_DATA_KEY]]);
3414
5707
  return child && typeof child === "object" ? child : {};
3415
5708
  }
3416
5709
  function getLayoutSizing(node, axis) {
3417
- const value = _nullishCoalesce(_optionalChain([getChildLayout, 'call', _83 => _83(node), 'access', _84 => _84.sizing, 'optionalAccess', _85 => _85[axis]]), () => ( _optionalChain([getAutoLayout, 'call', _86 => _86(node), 'optionalAccess', _87 => _87.sizing, 'optionalAccess', _88 => _88[axis]])));
5710
+ const value = _nullishCoalesce(_optionalChain([getChildLayout, 'call', _100 => _100(node), 'access', _101 => _101.sizing, 'optionalAccess', _102 => _102[axis]]), () => ( _optionalChain([getAutoLayout, 'call', _103 => _103(node), 'optionalAccess', _104 => _104.sizing, 'optionalAccess', _105 => _105[axis]])));
3418
5711
  return value === "hug" || value === "fill" ? value : "fixed";
3419
5712
  }
3420
5713
  function limitsOf(node) {
3421
5714
  const child = getChildLayout(node);
3422
5715
  const layout2 = getAutoLayout(node);
3423
- const min = _nullishCoalesce(_nullishCoalesce(child.min, () => ( _optionalChain([layout2, 'optionalAccess', _89 => _89.min]))), () => ( {}));
3424
- const max = _nullishCoalesce(_nullishCoalesce(child.max, () => ( _optionalChain([layout2, 'optionalAccess', _90 => _90.max]))), () => ( {}));
5716
+ const min = _nullishCoalesce(_nullishCoalesce(child.min, () => ( _optionalChain([layout2, 'optionalAccess', _106 => _106.min]))), () => ( {}));
5717
+ const max = _nullishCoalesce(_nullishCoalesce(child.max, () => ( _optionalChain([layout2, 'optionalAccess', _107 => _107.max]))), () => ( {}));
3425
5718
  return { minW: min.width, maxW: max.width, minH: min.height, maxH: max.height };
3426
5719
  }
3427
5720
  function resolvePadding(padding) {
@@ -3433,21 +5726,21 @@ function resolvePadding(padding) {
3433
5726
  else sides = [0, 0, 0, 0];
3434
5727
  return sides.map((p) => Math.max(finite(p), 0));
3435
5728
  }
3436
- var LayoutState = (_class6 = class {
3437
- __init15() {this.boxes = /* @__PURE__ */ new Map()}
5729
+ var LayoutState = (_class7 = class {
5730
+ __init17() {this.boxes = /* @__PURE__ */ new Map()}
3438
5731
 
3439
- __init16() {this.visiting = /* @__PURE__ */ new Set()}
3440
- __init17() {this.original = /* @__PURE__ */ new Map()}
3441
- constructor(nodes, options = {}) {;_class6.prototype.__init15.call(this);_class6.prototype.__init16.call(this);_class6.prototype.__init17.call(this);
5732
+ __init18() {this.visiting = /* @__PURE__ */ new Set()}
5733
+ __init19() {this.original = /* @__PURE__ */ new Map()}
5734
+ constructor(nodes, options = {}) {;_class7.prototype.__init17.call(this);_class7.prototype.__init18.call(this);_class7.prototype.__init19.call(this);
3442
5735
  this.measure = _nullishCoalesce(options.measure, () => ( {}));
3443
5736
  for (const node of nodes) {
3444
- const size = _nullishCoalesce(_optionalChain([this, 'access', _91 => _91.measure, 'access', _92 => _92.size, 'optionalCall', _93 => _93(node)]), () => ( getNodeSize(node, options.rectOptions)));
5737
+ const size = _nullishCoalesce(_optionalChain([this, 'access', _108 => _108.measure, 'access', _109 => _109.size, 'optionalCall', _110 => _110(node)]), () => ( getNodeSize(node, options.rectOptions)));
3445
5738
  const box = {
3446
5739
  id: node.id,
3447
5740
  node,
3448
5741
  parent: node.parentId,
3449
- x: finite(_optionalChain([node, 'access', _94 => _94.position, 'optionalAccess', _95 => _95.x])),
3450
- y: finite(_optionalChain([node, 'access', _96 => _96.position, 'optionalAccess', _97 => _97.y])),
5742
+ x: finite(_optionalChain([node, 'access', _111 => _111.position, 'optionalAccess', _112 => _112.x])),
5743
+ y: finite(_optionalChain([node, 'access', _113 => _113.position, 'optionalAccess', _114 => _114.y])),
3451
5744
  w: finite(size.width),
3452
5745
  h: finite(size.height),
3453
5746
  kids: []
@@ -3456,7 +5749,7 @@ var LayoutState = (_class6 = class {
3456
5749
  this.original.set(node.id, { x: box.x, y: box.y, w: box.w, h: box.h });
3457
5750
  }
3458
5751
  for (const node of nodes) {
3459
- if (node.parentId && node.parentId !== node.id) _optionalChain([this, 'access', _98 => _98.boxes, 'access', _99 => _99.get, 'call', _100 => _100(node.parentId), 'optionalAccess', _101 => _101.kids, 'access', _102 => _102.push, 'call', _103 => _103(node.id)]);
5752
+ if (node.parentId && node.parentId !== node.id) _optionalChain([this, 'access', _115 => _115.boxes, 'access', _116 => _116.get, 'call', _117 => _117(node.parentId), 'optionalAccess', _118 => _118.kids, 'access', _119 => _119.push, 'call', _120 => _120(node.id)]);
3460
5753
  }
3461
5754
  }
3462
5755
  updates() {
@@ -3484,7 +5777,7 @@ var LayoutState = (_class6 = class {
3484
5777
  ancestors(id) {
3485
5778
  const out = [];
3486
5779
  const seen = /* @__PURE__ */ new Set([id]);
3487
- let parent = _optionalChain([this, 'access', _104 => _104.boxes, 'access', _105 => _105.get, 'call', _106 => _106(id), 'optionalAccess', _107 => _107.parent]);
5780
+ let parent = _optionalChain([this, 'access', _121 => _121.boxes, 'access', _122 => _122.get, 'call', _123 => _123(id), 'optionalAccess', _124 => _124.parent]);
3488
5781
  while (parent && !seen.has(parent) && this.boxes.has(parent)) {
3489
5782
  out.push(parent);
3490
5783
  seen.add(parent);
@@ -3492,7 +5785,7 @@ var LayoutState = (_class6 = class {
3492
5785
  }
3493
5786
  return out;
3494
5787
  }
3495
- }, _class6);
5788
+ }, _class7);
3496
5789
  function setSize(s, id, w, h) {
3497
5790
  const b = s.boxes.get(id);
3498
5791
  if (!b) return;
@@ -3522,10 +5815,10 @@ function fitHugText(s, id) {
3522
5815
  if (getLayoutSizing(b.node, "width") === "hug") {
3523
5816
  const w = clampLayoutSize(natural.width, minW, maxW);
3524
5817
  const limited = Math.abs(w - natural.width) > EPS;
3525
- const h = limited ? _nullishCoalesce(_optionalChain([s, 'access', _108 => _108.measure, 'access', _109 => _109.textHeight, 'optionalCall', _110 => _110(b.node, w)]), () => ( natural.height)) : natural.height;
5818
+ const h = limited ? _nullishCoalesce(_optionalChain([s, 'access', _125 => _125.measure, 'access', _126 => _126.textHeight, 'optionalCall', _127 => _127(b.node, w)]), () => ( natural.height)) : natural.height;
3526
5819
  setSize(s, id, w, h);
3527
5820
  } else if (getLayoutSizing(b.node, "height") === "hug") {
3528
- setSize(s, id, b.w, _nullishCoalesce(_optionalChain([s, 'access', _111 => _111.measure, 'access', _112 => _112.textHeight, 'optionalCall', _113 => _113(b.node, b.w)]), () => ( b.h)));
5821
+ setSize(s, id, b.w, _nullishCoalesce(_optionalChain([s, 'access', _128 => _128.measure, 'access', _129 => _129.textHeight, 'optionalCall', _130 => _130(b.node, b.w)]), () => ( b.h)));
3529
5822
  }
3530
5823
  }
3531
5824
  function enforceLimits(s, id) {
@@ -3543,7 +5836,7 @@ function itemBaseline(s, id, depth) {
3543
5836
  const b = s.boxes.get(id);
3544
5837
  if (!b) return void 0;
3545
5838
  if (isText(s, b)) {
3546
- const v = _optionalChain([s, 'access', _114 => _114.measure, 'access', _115 => _115.textBaseline, 'optionalCall', _116 => _116(b.node)]);
5839
+ const v = _optionalChain([s, 'access', _131 => _131.measure, 'access', _132 => _132.textBaseline, 'optionalCall', _133 => _133(b.node)]);
3547
5840
  return typeof v === "number" && Number.isFinite(v) ? v : void 0;
3548
5841
  }
3549
5842
  const layout2 = getAutoLayout(b.node);
@@ -3558,7 +5851,7 @@ function resizeChild(s, id, w, h) {
3558
5851
  const b = s.boxes.get(id);
3559
5852
  if (!b) return;
3560
5853
  if (isText(s, b) && getLayoutSizing(b.node, "height") === "hug") {
3561
- setSize(s, id, w, _nullishCoalesce(_optionalChain([s, 'access', _117 => _117.measure, 'access', _118 => _118.textHeight, 'optionalCall', _119 => _119(b.node, w)]), () => ( h)));
5854
+ setSize(s, id, w, _nullishCoalesce(_optionalChain([s, 'access', _134 => _134.measure, 'access', _135 => _135.textHeight, 'optionalCall', _136 => _136(b.node, w)]), () => ( h)));
3562
5855
  return;
3563
5856
  }
3564
5857
  const ow = b.w;
@@ -3667,7 +5960,7 @@ function layoutFrameInner(s, frame) {
3667
5960
  const b = s.boxes.get(id);
3668
5961
  return horizontal ? [b.w, b.h] : [b.h, b.w];
3669
5962
  };
3670
- const resize = (it, main, cross) => resizeChild(s, it.id, horizontal ? main : cross, horizontal ? cross : main);
5963
+ const resize = (it, main, cross2) => resizeChild(s, it.id, horizontal ? main : cross2, horizontal ? cross2 : main);
3671
5964
  if (!wraps) {
3672
5965
  for (const it of items) {
3673
5966
  if (!it.fillCross || it.fillMain) continue;
@@ -3681,13 +5974,13 @@ function layoutFrameInner(s, frame) {
3681
5974
  let used = 0;
3682
5975
  items.forEach((it, i) => {
3683
5976
  const sz = it.fillMain ? _nullishCoalesce(it.minMain, () => ( 0)) : it.main;
3684
- const add2 = cur.length === 0 ? sz : Math.max(gap, 0) + sz;
3685
- if (cur.length > 0 && used + add2 > innerMainFixed + 1e-6) {
5977
+ const add3 = cur.length === 0 ? sz : Math.max(gap, 0) + sz;
5978
+ if (cur.length > 0 && used + add3 > innerMainFixed + 1e-6) {
3686
5979
  lines.push(cur);
3687
5980
  cur = [];
3688
5981
  used = sz;
3689
5982
  } else {
3690
- used += add2;
5983
+ used += add3;
3691
5984
  }
3692
5985
  cur.push(i);
3693
5986
  });
@@ -3703,8 +5996,8 @@ function layoutFrameInner(s, frame) {
3703
5996
  }
3704
5997
  for (const it of items) {
3705
5998
  if (!it.fillMain) continue;
3706
- const cross = it.fillCross && !wraps ? clampLayoutSize(innerCrossFixed, it.minCross, it.maxCross) : it.cross;
3707
- resize(it, it.main, cross);
5999
+ const cross2 = it.fillCross && !wraps ? clampLayoutSize(innerCrossFixed, it.minCross, it.maxCross) : it.cross;
6000
+ resize(it, it.main, cross2);
3708
6001
  it.cross = sizeOf(it.id)[1];
3709
6002
  }
3710
6003
  if (baseline) {
@@ -3718,8 +6011,8 @@ function layoutFrameInner(s, frame) {
3718
6011
  const inLine = line2.map((i) => items[i]);
3719
6012
  const mainUsed = inLine.reduce((sum, it) => sum + it.main, 0) + gaps;
3720
6013
  const allFill = inLine.every((it) => it.fillCross);
3721
- const cross = inLine.filter((it) => allFill || !it.fillCross).reduce((m, it) => Math.max(m, it.baseOff + it.cross), 0);
3722
- extents.push([mainUsed, cross]);
6014
+ const cross2 = inLine.filter((it) => allFill || !it.fillCross).reduce((m, it) => Math.max(m, it.baseOff + it.cross), 0);
6015
+ extents.push([mainUsed, cross2]);
3723
6016
  }
3724
6017
  const contentMain = extents.reduce((m, l) => Math.max(m, l[0]), 0);
3725
6018
  let crossGap = al.rowGap !== void 0 ? finite(al.rowGap) : gap;
@@ -3805,16 +6098,16 @@ function trackSpec(tracks, i) {
3805
6098
  return { sizing: t.sizing, value };
3806
6099
  }
3807
6100
  function cellRect(g, c) {
3808
- const x0 = _nullishCoalesce(_optionalChain([g, 'access', _120 => _120.columns, 'access', _121 => _121[c.column], 'optionalAccess', _122 => _122[0]]), () => ( 0));
3809
- const x1 = _nullishCoalesce(_optionalChain([g, 'access', _123 => _123.columns, 'access', _124 => _124[c.column + c.columnSpan - 1], 'optionalAccess', _125 => _125[1]]), () => ( x0));
3810
- const y0 = _nullishCoalesce(_optionalChain([g, 'access', _126 => _126.rows, 'access', _127 => _127[c.row], 'optionalAccess', _128 => _128[0]]), () => ( 0));
3811
- const y1 = _nullishCoalesce(_optionalChain([g, 'access', _129 => _129.rows, 'access', _130 => _130[c.row + c.rowSpan - 1], 'optionalAccess', _131 => _131[1]]), () => ( y0));
6101
+ const x0 = _nullishCoalesce(_optionalChain([g, 'access', _137 => _137.columns, 'access', _138 => _138[c.column], 'optionalAccess', _139 => _139[0]]), () => ( 0));
6102
+ const x1 = _nullishCoalesce(_optionalChain([g, 'access', _140 => _140.columns, 'access', _141 => _141[c.column + c.columnSpan - 1], 'optionalAccess', _142 => _142[1]]), () => ( x0));
6103
+ const y0 = _nullishCoalesce(_optionalChain([g, 'access', _143 => _143.rows, 'access', _144 => _144[c.row], 'optionalAccess', _145 => _145[0]]), () => ( 0));
6104
+ const y1 = _nullishCoalesce(_optionalChain([g, 'access', _146 => _146.rows, 'access', _147 => _147[c.row + c.rowSpan - 1], 'optionalAccess', _148 => _148[1]]), () => ( y0));
3812
6105
  return { x: x0, y: y0, width: Math.max(x1, x0) - x0, height: Math.max(y1, y0) - y0 };
3813
6106
  }
3814
6107
  var toIndex = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? Math.floor(v) : void 0;
3815
6108
  function gridPlace(s, al, kids) {
3816
- const cols = trackList(_optionalChain([al, 'access', _132 => _132.grid, 'optionalAccess', _133 => _133.columns]), 2).count;
3817
- const minRows = trackList(_optionalChain([al, 'access', _134 => _134.grid, 'optionalAccess', _135 => _135.rows]), 1).count;
6109
+ const cols = trackList(_optionalChain([al, 'access', _149 => _149.grid, 'optionalAccess', _150 => _150.columns]), 2).count;
6110
+ const minRows = trackList(_optionalChain([al, 'access', _151 => _151.grid, 'optionalAccess', _152 => _152.rows]), 1).count;
3818
6111
  const maxRows = Math.min(Math.max(Math.floor(MAX_GRID_CELLS / cols), 1), MAX_TRACKS);
3819
6112
  const occ = [];
3820
6113
  const free = (c, r, cs, rs) => {
@@ -3905,11 +6198,11 @@ function resolveTracks(tracks, content, avail) {
3905
6198
  let used = out.reduce((sum, v, i) => trackSpec(tracks, i).sizing === "fill" ? sum : sum + v, 0);
3906
6199
  while (flex.length > 0) {
3907
6200
  const total = flex.reduce((sum, i) => sum + fr(i), 0);
3908
- const unit2 = total > 1e-12 ? Math.max(avail - used, 0) / total : 0;
3909
- const open = flex.filter((i) => unit2 * fr(i) >= out[i]);
3910
- const frozen = flex.filter((i) => unit2 * fr(i) < out[i]);
6201
+ const unit3 = total > 1e-12 ? Math.max(avail - used, 0) / total : 0;
6202
+ const open = flex.filter((i) => unit3 * fr(i) >= out[i]);
6203
+ const frozen = flex.filter((i) => unit3 * fr(i) < out[i]);
3911
6204
  if (frozen.length === 0) {
3912
- for (const i of open) out[i] = unit2 * fr(i);
6205
+ for (const i of open) out[i] = unit3 * fr(i);
3913
6206
  break;
3914
6207
  }
3915
6208
  used += frozen.reduce((sum, i) => sum + out[i], 0);
@@ -3957,8 +6250,8 @@ function gridGeometryOf(s, frame) {
3957
6250
  const [pt, pr, pb, pl] = resolvePadding(al.padding);
3958
6251
  const kids = flowChildren(s, frame);
3959
6252
  const { cells, rows } = gridPlace(s, al, kids);
3960
- const colSpec = trackList(_optionalChain([al, 'access', _136 => _136.grid, 'optionalAccess', _137 => _137.columns]), 2);
3961
- const rowSpec = trackList(_optionalChain([al, 'access', _138 => _138.grid, 'optionalAccess', _139 => _139.rows]), 1);
6253
+ const colSpec = trackList(_optionalChain([al, 'access', _153 => _153.grid, 'optionalAccess', _154 => _154.columns]), 2);
6254
+ const rowSpec = trackList(_optionalChain([al, 'access', _155 => _155.grid, 'optionalAccess', _156 => _156.rows]), 1);
3962
6255
  const cols = colSpec.count;
3963
6256
  const gx = Math.max(finite(al.gap), 0);
3964
6257
  const gy = Math.max(al.rowGap !== void 0 ? finite(al.rowGap) : gx, 0);
@@ -4060,7 +6353,7 @@ function constrain(s, id, ow, oh) {
4060
6353
  let y1 = c.y + c.h;
4061
6354
  const dx = nw - ow;
4062
6355
  const dy = nh - oh;
4063
- switch (_nullishCoalesce(_optionalChain([child, 'access', _140 => _140.constraints, 'optionalAccess', _141 => _141.horizontal]), () => ( "left"))) {
6356
+ switch (_nullishCoalesce(_optionalChain([child, 'access', _157 => _157.constraints, 'optionalAccess', _158 => _158.horizontal]), () => ( "left"))) {
4064
6357
  case "right":
4065
6358
  x0 += dx;
4066
6359
  x1 += dx;
@@ -4077,7 +6370,7 @@ function constrain(s, id, ow, oh) {
4077
6370
  x1 *= sx;
4078
6371
  break;
4079
6372
  }
4080
- switch (_nullishCoalesce(_optionalChain([child, 'access', _142 => _142.constraints, 'optionalAccess', _143 => _143.vertical]), () => ( "top"))) {
6373
+ switch (_nullishCoalesce(_optionalChain([child, 'access', _159 => _159.constraints, 'optionalAccess', _160 => _160.vertical]), () => ( "top"))) {
4081
6374
  case "bottom":
4082
6375
  y0 += dy;
4083
6376
  y1 += dy;
@@ -4117,7 +6410,7 @@ function postOrder(s, nodes) {
4117
6410
  const visit = (id) => {
4118
6411
  if (seen.has(id)) return;
4119
6412
  seen.add(id);
4120
- for (const k of _nullishCoalesce(_optionalChain([s, 'access', _144 => _144.boxes, 'access', _145 => _145.get, 'call', _146 => _146(id), 'optionalAccess', _147 => _147.kids]), () => ( []))) visit(k);
6413
+ for (const k of _nullishCoalesce(_optionalChain([s, 'access', _161 => _161.boxes, 'access', _162 => _162.get, 'call', _163 => _163(id), 'optionalAccess', _164 => _164.kids]), () => ( []))) visit(k);
4121
6414
  out.push(id);
4122
6415
  };
4123
6416
  const roots = nodes.filter((n) => !n.parentId || !s.boxes.has(n.parentId));
@@ -4156,7 +6449,7 @@ function getFlowChildren(nodes, frameId) {
4156
6449
  function getLayoutParent(nodes, id) {
4157
6450
  const lookup = createNodeLookup(nodes);
4158
6451
  const node = lookup.get(id);
4159
- if (!_optionalChain([node, 'optionalAccess', _148 => _148.parentId]) || getChildLayout(node).absolute) return void 0;
6452
+ if (!_optionalChain([node, 'optionalAccess', _165 => _165.parentId]) || getChildLayout(node).absolute) return void 0;
4160
6453
  const parent = lookup.get(node.parentId);
4161
6454
  return isAutoLayoutFrame(parent) ? parent : void 0;
4162
6455
  }
@@ -4169,7 +6462,7 @@ function makeSizingCoherent(nodes, id, options = {}) {
4169
6462
  if (!targets.has(node.id)) return node;
4170
6463
  const parent = node.parentId ? lookup.get(node.parentId) : void 0;
4171
6464
  const flowParent = parent && isAutoLayoutFrame(parent) && !getChildLayout(node).absolute ? parent : void 0;
4172
- const canHug = isAutoLayoutFrame(node) || _optionalChain([options, 'access', _149 => _149.measure, 'optionalAccess', _150 => _150.textSize, 'optionalCall', _151 => _151(node)]) !== void 0;
6465
+ const canHug = isAutoLayoutFrame(node) || _optionalChain([options, 'access', _166 => _166.measure, 'optionalAccess', _167 => _167.textSize, 'optionalCall', _168 => _168(node)]) !== void 0;
4173
6466
  const coherent = (axis) => {
4174
6467
  const sizing = getLayoutSizing(node, axis);
4175
6468
  if (sizing === "fill" && (!flowParent || getLayoutSizing(flowParent, axis) === "hug")) return "fixed";
@@ -4195,19 +6488,19 @@ function getAutoLayoutInsertTarget(nodes, frameId, point, options = {}) {
4195
6488
  if (!frame || !al) return void 0;
4196
6489
  const s = new LayoutState(nodes, options);
4197
6490
  const origin = getAbsolutePosition(frame, lookup);
4198
- const px = point.x - origin.x;
6491
+ const px2 = point.x - origin.x;
4199
6492
  const py = point.y - origin.y;
4200
6493
  const siblings = flowChildren(s, frameId).filter((id) => id !== options.excludeId).map((id) => s.boxes.get(id));
4201
6494
  const horizontal = al.mode !== "vertical";
4202
6495
  const main = (b) => horizontal ? b.x : b.y;
4203
6496
  const mainSize = (b) => horizontal ? b.w : b.h;
4204
- const cross = (b) => horizontal ? b.y : b.x;
6497
+ const cross2 = (b) => horizontal ? b.y : b.x;
4205
6498
  const crossSize = (b) => horizontal ? b.h : b.w;
4206
- const p = { x: px, y: py };
6499
+ const p = { x: px2, y: py };
4207
6500
  const multiLine = al.mode === "grid" || !!al.wrap;
4208
6501
  let index = 0;
4209
6502
  for (const b of siblings) {
4210
- const before = multiLine ? cross(b) + crossSize(b) <= cross(p) || cross(b) <= cross(p) && main(b) + mainSize(b) / 2 < main(p) : main(b) + mainSize(b) / 2 < main(p);
6503
+ const before = multiLine ? cross2(b) + crossSize(b) <= cross2(p) || cross2(b) <= cross2(p) && main(b) + mainSize(b) / 2 < main(p) : main(b) + mainSize(b) / 2 < main(p);
4211
6504
  if (before) index += 1;
4212
6505
  }
4213
6506
  const [pt, pr, pb, pl] = resolvePadding(al.padding);
@@ -4216,13 +6509,13 @@ function getAutoLayoutInsertTarget(nodes, frameId, point, options = {}) {
4216
6509
  const f = s.boxes.get(frameId);
4217
6510
  let guide;
4218
6511
  if (horizontal) {
4219
- const x = prev && next && Math.abs(cross(prev) - cross(next)) < 1e-6 ? (prev.x + prev.w + next.x) / 2 : prev ? prev.x + prev.w : next ? next.x : pl;
6512
+ const x = prev && next && Math.abs(cross2(prev) - cross2(next)) < 1e-6 ? (prev.x + prev.w + next.x) / 2 : prev ? prev.x + prev.w : next ? next.x : pl;
4220
6513
  const ref = _nullishCoalesce(next, () => ( prev));
4221
6514
  const y1 = ref ? ref.y : pt;
4222
6515
  const y2 = ref ? ref.y + ref.h : f.h - pb;
4223
6516
  guide = { orientation: "vertical", kind: "edge", x1: origin.x + x, y1: origin.y + y1, x2: origin.x + x, y2: origin.y + y2 };
4224
6517
  } else {
4225
- const y = prev && next && Math.abs(cross(prev) - cross(next)) < 1e-6 ? (prev.y + prev.h + next.y) / 2 : prev ? prev.y + prev.h : next ? next.y : pt;
6518
+ const y = prev && next && Math.abs(cross2(prev) - cross2(next)) < 1e-6 ? (prev.y + prev.h + next.y) / 2 : prev ? prev.y + prev.h : next ? next.y : pt;
4226
6519
  const ref = _nullishCoalesce(next, () => ( prev));
4227
6520
  const x1 = ref ? ref.x : pl;
4228
6521
  const x2 = ref ? ref.x + ref.w : f.w - pr;
@@ -4232,7 +6525,7 @@ function getAutoLayoutInsertTarget(nodes, frameId, point, options = {}) {
4232
6525
  }
4233
6526
  function moveLayoutChild(nodes, childId, index) {
4234
6527
  const child = nodes.find((n) => n.id === childId);
4235
- if (!_optionalChain([child, 'optionalAccess', _152 => _152.parentId])) return nodes;
6528
+ if (!_optionalChain([child, 'optionalAccess', _169 => _169.parentId])) return nodes;
4236
6529
  const siblings = nodes.filter((n) => n.parentId === child.parentId && n.id !== child.parentId);
4237
6530
  const flow = siblings.filter((n) => n.hidden !== true && !getChildLayout(n).absolute && n.id !== childId);
4238
6531
  const clamped = Math.min(Math.max(Math.floor(Number.isFinite(index) ? index : 0), 0), flow.length);
@@ -4280,11 +6573,11 @@ function createCanvasArrangeController(options) {
4280
6573
  let resizeStart = null;
4281
6574
  let resizeIndex = null;
4282
6575
  let lastResized = null;
4283
- const selectedIds = (ids) => ids ? [...ids] : _nullishCoalesce(_optionalChain([options, 'access', _153 => _153.getSelectedIds, 'optionalCall', _154 => _154()]), () => ( options.getNodes().filter((n) => n.selected).map((n) => n.id)));
6576
+ const selectedIds = (ids) => ids ? [...ids] : _nullishCoalesce(_optionalChain([options, 'access', _170 => _170.getSelectedIds, 'optionalCall', _171 => _171()]), () => ( options.getNodes().filter((n) => n.selected).map((n) => n.id)));
4284
6577
  const setGuides = (next) => {
4285
6578
  if (next.length === 0 && guides.length === 0) return;
4286
6579
  guides = next;
4287
- _optionalChain([options, 'access', _155 => _155.onGuidesChange, 'optionalCall', _156 => _156(guides)]);
6580
+ _optionalChain([options, 'access', _172 => _172.onGuidesChange, 'optionalCall', _173 => _173(guides)]);
4288
6581
  };
4289
6582
  function apply(name, updates) {
4290
6583
  if (updates.length === 0) return updates;
@@ -4381,6 +6674,41 @@ function createCanvasArrangeController(options) {
4381
6674
  divide: (ids, o) => controller.combineShapes("divide", ids, o),
4382
6675
  /** Whether the shape operations can run on `ids` (default: the selection). */
4383
6676
  canCombineShapes: (ids) => canCombineShapeNodes(options.getNodes(), selectedIds(ids)).ok,
6677
+ /**
6678
+ * Offset Path: grows (`distance > 0`) or shrinks (`distance < 0`) every shape among
6679
+ * `ids` (default: the selection) by `distance` flow units, keeping curves, as one
6680
+ * undoable step. Refuses without changing anything when a shape is locked, no shape is
6681
+ * selected or every result is empty.
6682
+ */
6683
+ offsetShapes(distance, ids, offsetOptions = {}) {
6684
+ const before = options.getNodes();
6685
+ const result = offsetShapeNodes(before, selectedIds(ids), distance, { ...rect(), ...offsetOptions });
6686
+ if (!result.ok) return result;
6687
+ const run = () => options.setNodes(applyShapeReplacement(options.getNodes(), result));
6688
+ const undo = () => options.setNodes(revertShapeCombination(options.getNodes(), result, before));
6689
+ if (options.history) options.history.execute({ name: "Offset Path", execute: run, undo });
6690
+ else run();
6691
+ return result;
6692
+ },
6693
+ /** Whether `offsetShapes` can run on `ids` (default: the selection). */
6694
+ canOffsetShapes: (ids) => canOffsetShapeNodes(options.getNodes(), selectedIds(ids)).ok,
6695
+ /**
6696
+ * Outline Stroke: converts the strokes of the shapes among `ids` (default: the
6697
+ * selection) to filled path shapes, as one undoable step. Refuses when a shape is
6698
+ * locked or no selected shape has a visible stroke.
6699
+ */
6700
+ outlineStroke(ids, outlineOptions = {}) {
6701
+ const before = options.getNodes();
6702
+ const result = outlineShapeNodeStrokes(before, selectedIds(ids), { ...rect(), ...outlineOptions });
6703
+ if (!result.ok) return result;
6704
+ const run = () => options.setNodes(applyShapeReplacement(options.getNodes(), result));
6705
+ const undo = () => options.setNodes(revertShapeCombination(options.getNodes(), result, before));
6706
+ if (options.history) options.history.execute({ name: "Outline Stroke", execute: run, undo });
6707
+ else run();
6708
+ return result;
6709
+ },
6710
+ /** Whether `outlineStroke` can run on `ids` (default: the selection). */
6711
+ canOutlineStroke: (ids) => canOutlineShapeNodeStrokes(options.getNodes(), selectedIds(ids)).ok,
4384
6712
  /**
4385
6713
  * Runs a shortcut action. Scene actions are not handled here (see the scenes store);
4386
6714
  * returns `false` for them and for unknown actions.
@@ -4452,7 +6780,7 @@ function createCanvasArrangeController(options) {
4452
6780
  const result = snapNodeDrag(options.getNodes(), list, {
4453
6781
  ...rect(),
4454
6782
  ...options.guides,
4455
- zoom: _nullishCoalesce(_optionalChain([options, 'access', _157 => _157.getZoom, 'optionalCall', _158 => _158()]), () => ( 1)),
6783
+ zoom: _nullishCoalesce(_optionalChain([options, 'access', _174 => _174.getZoom, 'optionalCall', _175 => _175()]), () => ( 1)),
4456
6784
  index: dragIndex
4457
6785
  });
4458
6786
  lastSnapped = /* @__PURE__ */ new Map();
@@ -4490,7 +6818,7 @@ function createCanvasArrangeController(options) {
4490
6818
  const result = snapNodeDrag(nodes, ids, {
4491
6819
  ...rect(),
4492
6820
  ...options.guides,
4493
- zoom: _nullishCoalesce(_optionalChain([options, 'access', _159 => _159.getZoom, 'optionalCall', _160 => _160()]), () => ( 1)),
6821
+ zoom: _nullishCoalesce(_optionalChain([options, 'access', _176 => _176.getZoom, 'optionalCall', _177 => _177()]), () => ( 1)),
4494
6822
  index: dragIndex
4495
6823
  });
4496
6824
  setGuides(result.guides);
@@ -4556,7 +6884,7 @@ function createCanvasArrangeController(options) {
4556
6884
  ...rect(),
4557
6885
  ...options.guides,
4558
6886
  ...options.resize,
4559
- zoom: _nullishCoalesce(_optionalChain([options, 'access', _161 => _161.getZoom, 'optionalCall', _162 => _162()]), () => ( 1)),
6887
+ zoom: _nullishCoalesce(_optionalChain([options, 'access', _178 => _178.getZoom, 'optionalCall', _179 => _179()]), () => ( 1)),
4560
6888
  index: resizeIndex
4561
6889
  });
4562
6890
  lastResized = result.updates.length > 0 ? result : null;
@@ -4575,7 +6903,7 @@ function createCanvasArrangeController(options) {
4575
6903
  resizeIndex = null;
4576
6904
  lastResized = null;
4577
6905
  setGuides([]);
4578
- const update = _optionalChain([last, 'optionalAccess', _163 => _163.updates, 'access', _164 => _164[0]]);
6906
+ const update = _optionalChain([last, 'optionalAccess', _180 => _180.updates, 'access', _181 => _181[0]]);
4579
6907
  if (!update) return;
4580
6908
  const node = options.getNodes().find((n) => n.id === update.id);
4581
6909
  if (!node) return;
@@ -4603,7 +6931,7 @@ function createCanvasArrangeController(options) {
4603
6931
  return changes.filter((c) => !isResizeChange(c));
4604
6932
  }
4605
6933
  if (dims.resizing === false) {
4606
- const last = _optionalChain([lastResized, 'optionalAccess', _165 => _165.updates, 'access', _166 => _166[0]]);
6934
+ const last = _optionalChain([lastResized, 'optionalAccess', _182 => _182.updates, 'access', _183 => _183[0]]);
4607
6935
  lastResized = null;
4608
6936
  controller.endResize();
4609
6937
  if (!last || last.id !== id) return changes;
@@ -4617,7 +6945,7 @@ function createCanvasArrangeController(options) {
4617
6945
  const posChange = changes.find((c) => c.id === id && c.type === "position" && !!c.position);
4618
6946
  const parent = node.parentId ? lookup.get(node.parentId) : void 0;
4619
6947
  const origin = parent ? getResizingNodeRect(parent, lookup, rect()) : { x: 0, y: 0 };
4620
- const position = _nullishCoalesce(_optionalChain([posChange, 'optionalAccess', _167 => _167.position]), () => ( node.position));
6948
+ const position = _nullishCoalesce(_optionalChain([posChange, 'optionalAccess', _184 => _184.position]), () => ( node.position));
4621
6949
  const proposed = {
4622
6950
  x: position.x + origin.x,
4623
6951
  y: position.y + origin.y,
@@ -4633,7 +6961,7 @@ function createCanvasArrangeController(options) {
4633
6961
  ...rect(),
4634
6962
  ...options.guides,
4635
6963
  ...options.resize,
4636
- zoom: _nullishCoalesce(_optionalChain([options, 'access', _168 => _168.getZoom, 'optionalCall', _169 => _169()]), () => ( 1)),
6964
+ zoom: _nullishCoalesce(_optionalChain([options, 'access', _185 => _185.getZoom, 'optionalCall', _186 => _186()]), () => ( 1)),
4637
6965
  index: resizeIndex
4638
6966
  });
4639
6967
  setGuides(result.guides);
@@ -4814,7 +7142,7 @@ function createCanvasAutoLayoutController(options) {
4814
7142
  const setGuides = (next) => {
4815
7143
  if (next.length === 0 && guides.length === 0) return;
4816
7144
  guides = next;
4817
- _optionalChain([options, 'access', _170 => _170.onGuidesChange, 'optionalCall', _171 => _171(guides)]);
7145
+ _optionalChain([options, 'access', _187 => _187.onGuidesChange, 'optionalCall', _188 => _188(guides)]);
4818
7146
  };
4819
7147
  function run(name, forward, backward, ids, extra = [], restore) {
4820
7148
  const before = options.getNodes();
@@ -4980,11 +7308,11 @@ function createCanvasAutoLayoutController(options) {
4980
7308
  const nodes = options.getNodes();
4981
7309
  const lookup = createNodeLookup(nodes);
4982
7310
  for (const c of changes) {
4983
- const id = _nullishCoalesce(c.id, () => ( _optionalChain([c, 'access', _172 => _172.item, 'optionalAccess', _173 => _173.id])));
7311
+ const id = _nullishCoalesce(c.id, () => ( _optionalChain([c, 'access', _189 => _189.item, 'optionalAccess', _190 => _190.id])));
4984
7312
  if (c.type === "add" && c.item) {
4985
7313
  pendingIds.add(c.item.id);
4986
7314
  } else if (c.type === "remove" && id) {
4987
- const parent = _optionalChain([lookup, 'access', _174 => _174.get, 'call', _175 => _175(id), 'optionalAccess', _176 => _176.parentId]);
7315
+ const parent = _optionalChain([lookup, 'access', _191 => _191.get, 'call', _192 => _192(id), 'optionalAccess', _193 => _193.parentId]);
4988
7316
  if (parent) pendingIds.add(parent);
4989
7317
  else pendingAll = true;
4990
7318
  } else if (c.type === "replace" && id) {
@@ -5071,6 +7399,511 @@ function restoreOrder(nodes, order) {
5071
7399
  return indexed.every((e, i) => e.n === nodes[i]) ? nodes : indexed.map((e) => e.n);
5072
7400
  }
5073
7401
 
7402
+ // src/canvas/tokenBindings.ts
7403
+ var TOKEN_BINDINGS_DATA_KEY = "tokenBindings";
7404
+ var TOKEN_MODES_DATA_KEY = "tokenModes";
7405
+ var kebab = (prop) => prop.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
7406
+ function parseDeclarations(style) {
7407
+ const parts = [];
7408
+ let depth = 0;
7409
+ let quote = "";
7410
+ let start = 0;
7411
+ for (let i = 0; i < style.length; i++) {
7412
+ const ch = style[i];
7413
+ if (quote) {
7414
+ if (ch === "\\") i++;
7415
+ else if (ch === quote) quote = "";
7416
+ } else if (ch === '"' || ch === "'") quote = ch;
7417
+ else if (ch === "(") depth++;
7418
+ else if (ch === ")") depth = Math.max(0, depth - 1);
7419
+ else if (ch === ";" && depth === 0) {
7420
+ parts.push(style.slice(start, i));
7421
+ start = i + 1;
7422
+ }
7423
+ }
7424
+ parts.push(style.slice(start));
7425
+ const out = [];
7426
+ for (const part of parts) {
7427
+ const colon = part.indexOf(":");
7428
+ if (colon < 0) continue;
7429
+ const name = part.slice(0, colon).trim();
7430
+ if (name) out.push([name, part.slice(colon + 1).trim()]);
7431
+ }
7432
+ return out;
7433
+ }
7434
+ function readNodeStyleProperty(style, prop) {
7435
+ if (!style) return void 0;
7436
+ if (typeof style === "object") return style[prop];
7437
+ const name = kebab(prop);
7438
+ let found;
7439
+ for (const [key, value] of parseDeclarations(style)) if (key.toLowerCase() === name) found = value;
7440
+ return found;
7441
+ }
7442
+ function writeNodeStyleProperty(style, prop, value, unitless = false) {
7443
+ if (typeof style === "string") {
7444
+ const name = kebab(prop);
7445
+ const text = value === void 0 ? void 0 : typeof value === "number" && !unitless ? `${value}px` : String(value);
7446
+ const decls = [];
7447
+ let placed = text === void 0;
7448
+ for (const [key, current] of parseDeclarations(style)) {
7449
+ if (key.toLowerCase() !== name) decls.push([key, current]);
7450
+ else if (!placed) {
7451
+ decls.push([name, text]);
7452
+ placed = true;
7453
+ }
7454
+ }
7455
+ if (!placed) decls.push([name, text]);
7456
+ return decls.map(([k, v]) => `${k}: ${v}`).join("; ");
7457
+ }
7458
+ const next = { ..._nullishCoalesce(style, () => ( {})) };
7459
+ if (value === void 0) delete next[prop];
7460
+ else next[prop] = value;
7461
+ return next;
7462
+ }
7463
+ function px(value) {
7464
+ if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
7465
+ if (typeof value === "string") {
7466
+ const n = parseFloat(value);
7467
+ return Number.isFinite(n) ? n : void 0;
7468
+ }
7469
+ return void 0;
7470
+ }
7471
+ function withStyle(node, prop, value, unitless = false) {
7472
+ const current = readNodeStyleProperty(node.style, prop);
7473
+ const written = typeof node.style === "string" && typeof value === "number" && !unitless ? `${value}px` : value;
7474
+ if (typeof node.style === "string" ? current === String(written) : current === value) return node;
7475
+ return { ...node, style: writeNodeStyleProperty(node.style, prop, value, unitless) };
7476
+ }
7477
+ function shapeOf(node) {
7478
+ const shape = _optionalChain([node, 'access', _194 => _194.data, 'optionalAccess', _195 => _195.shape]);
7479
+ return isShapeDescription(shape) ? shape : null;
7480
+ }
7481
+ function withShape(node, key, value) {
7482
+ const shape = shapeOf(node);
7483
+ if (shape[key] === value) return node;
7484
+ return { ...node, data: { ...node.data, shape: { ...shape, [key]: value } } };
7485
+ }
7486
+ var nonNegative = (v) => Math.max(0, v);
7487
+ function styleOrShape(key, styleProp, convert = (v) => v) {
7488
+ return {
7489
+ read(node) {
7490
+ const shape = shapeOf(node);
7491
+ if (shape) return shape[key];
7492
+ const value = readNodeStyleProperty(node.style, styleProp(node));
7493
+ return key === "strokeWidth" ? px(value) : value;
7494
+ },
7495
+ write(node, value) {
7496
+ const v = convert(value);
7497
+ if (shapeOf(node)) return withShape(node, key, v);
7498
+ let next = withStyle(node, styleProp(node), v);
7499
+ if (key === "strokeWidth" && readNodeStyleProperty(next.style, "borderStyle") === void 0) {
7500
+ next = { ...next, style: writeNodeStyleProperty(next.style, "borderStyle", "solid") };
7501
+ }
7502
+ return next;
7503
+ }
7504
+ };
7505
+ }
7506
+ function backgroundProp(node) {
7507
+ return readNodeStyleProperty(node.style, "backgroundColor") === void 0 && readNodeStyleProperty(node.style, "background") !== void 0 ? "background" : "backgroundColor";
7508
+ }
7509
+ function layoutProperty(key, label, read, write) {
7510
+ return {
7511
+ key,
7512
+ label,
7513
+ type: "number",
7514
+ scope: "GAP",
7515
+ appliesTo: (node) => getAutoLayout(node) !== void 0,
7516
+ read: (node) => {
7517
+ const layout2 = getAutoLayout(node);
7518
+ return layout2 ? read(layout2) : void 0;
7519
+ },
7520
+ write: (node, value) => {
7521
+ const layout2 = getAutoLayout(node);
7522
+ if (!layout2 || read(layout2) === value) return node;
7523
+ return { ...node, data: { ...node.data, [AUTO_LAYOUT_DATA_KEY]: write(layout2, value) } };
7524
+ }
7525
+ };
7526
+ }
7527
+ var SIDES = ["top", "right", "bottom", "left"];
7528
+ function paddingProperty(key, label, sides) {
7529
+ return layoutProperty(
7530
+ key,
7531
+ label,
7532
+ (layout2) => {
7533
+ const p = resolvePadding(layout2.padding);
7534
+ const values = sides.map((s) => p[SIDES.indexOf(s)]);
7535
+ return values.every((v) => v === values[0]) ? values[0] : void 0;
7536
+ },
7537
+ (layout2, value) => {
7538
+ const p = resolvePadding(layout2.padding);
7539
+ const v = Math.max(0, value);
7540
+ const padding = { top: p[0], right: p[1], bottom: p[2], left: p[3] };
7541
+ for (const s of sides) padding[s] = v;
7542
+ return { ...layout2, padding };
7543
+ }
7544
+ );
7545
+ }
7546
+ var CANVAS_TOKEN_PROPERTIES = [
7547
+ {
7548
+ key: "fill",
7549
+ label: "Fill",
7550
+ type: "color",
7551
+ scope: (node) => shapeOf(node) ? "SHAPE_FILL" : node.type === "text" ? "TEXT_FILL" : "FRAME_FILL",
7552
+ appliesTo: () => true,
7553
+ ...styleOrShape("fill", backgroundProp)
7554
+ },
7555
+ {
7556
+ key: "stroke",
7557
+ label: "Stroke",
7558
+ type: "color",
7559
+ scope: "STROKE_COLOR",
7560
+ appliesTo: () => true,
7561
+ ...styleOrShape("stroke", () => "borderColor")
7562
+ },
7563
+ {
7564
+ key: "strokeWidth",
7565
+ label: "Stroke width",
7566
+ type: "number",
7567
+ scope: "STROKE_FLOAT",
7568
+ appliesTo: () => true,
7569
+ ...styleOrShape("strokeWidth", () => "borderWidth", nonNegative)
7570
+ },
7571
+ {
7572
+ key: "opacity",
7573
+ label: "Opacity",
7574
+ type: "number",
7575
+ scope: "OPACITY",
7576
+ appliesTo: () => true,
7577
+ // Opacity variables are percentages (figcraft / Figma): 40 → 0.4, clamped to 0–100.
7578
+ read: (node) => {
7579
+ const v = px(readNodeStyleProperty(node.style, "opacity"));
7580
+ return v === void 0 ? void 0 : Math.round(v * 1e4) / 100;
7581
+ },
7582
+ write: (node, value) => withStyle(node, "opacity", Math.min(1, Math.max(0, value / 100)), true)
7583
+ },
7584
+ {
7585
+ key: "cornerRadius",
7586
+ label: "Corner radius",
7587
+ type: "number",
7588
+ scope: "CORNER_RADIUS",
7589
+ appliesTo: (node) => {
7590
+ const shape = shapeOf(node);
7591
+ return !shape || shape.kind === "rect";
7592
+ },
7593
+ read: (node) => {
7594
+ const shape = shapeOf(node);
7595
+ if (shape) return typeof shape.cornerRadius === "number" ? shape.cornerRadius : void 0;
7596
+ return px(readNodeStyleProperty(node.style, "borderRadius"));
7597
+ },
7598
+ write: (node, value) => {
7599
+ const v = Math.max(0, value);
7600
+ return shapeOf(node) ? withShape(node, "cornerRadius", v) : withStyle(node, "borderRadius", v);
7601
+ }
7602
+ },
7603
+ layoutProperty("gap", "Gap", (l) => typeof l.gap === "number" ? l.gap : 0, (l, v) => ({ ...l, gap: v })),
7604
+ layoutProperty("rowGap", "Row gap", (l) => typeof l.rowGap === "number" ? l.rowGap : void 0, (l, v) => ({ ...l, rowGap: v })),
7605
+ paddingProperty("padding", "Padding", ["top", "right", "bottom", "left"]),
7606
+ paddingProperty("paddingHorizontal", "Horizontal padding", ["left", "right"]),
7607
+ paddingProperty("paddingVertical", "Vertical padding", ["top", "bottom"]),
7608
+ paddingProperty("paddingTop", "Top padding", ["top"]),
7609
+ paddingProperty("paddingRight", "Right padding", ["right"]),
7610
+ paddingProperty("paddingBottom", "Bottom padding", ["bottom"]),
7611
+ paddingProperty("paddingLeft", "Left padding", ["left"]),
7612
+ {
7613
+ key: "textColor",
7614
+ label: "Text colour",
7615
+ type: "color",
7616
+ scope: "TEXT_FILL",
7617
+ appliesTo: (node) => !shapeOf(node),
7618
+ read: (node) => readNodeStyleProperty(node.style, "color"),
7619
+ write: (node, value) => withStyle(node, "color", value)
7620
+ },
7621
+ {
7622
+ key: "fontSize",
7623
+ label: "Font size",
7624
+ type: "number",
7625
+ scope: "FONT_SIZE",
7626
+ appliesTo: (node) => !shapeOf(node),
7627
+ read: (node) => px(readNodeStyleProperty(node.style, "fontSize")),
7628
+ write: (node, value) => withStyle(node, "fontSize", Math.max(0, value))
7629
+ },
7630
+ {
7631
+ key: "visible",
7632
+ label: "Visible",
7633
+ type: "boolean",
7634
+ appliesTo: () => true,
7635
+ read: (node) => !node.hidden,
7636
+ write: (node, value) => !node.hidden === value ? node : { ...node, hidden: !value }
7637
+ }
7638
+ ];
7639
+ var EMPTY = Object.freeze({});
7640
+ function stringRecord(value) {
7641
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return EMPTY;
7642
+ const out = {};
7643
+ for (const [k, v] of Object.entries(value)) if (typeof v === "string") out[k] = v;
7644
+ return out;
7645
+ }
7646
+ function getNodeTokenBindings(node) {
7647
+ return stringRecord(_optionalChain([node, 'optionalAccess', _196 => _196.data, 'optionalAccess', _197 => _197[TOKEN_BINDINGS_DATA_KEY]]));
7648
+ }
7649
+ function getNodeTokenModes(node) {
7650
+ return stringRecord(_optionalChain([node, 'optionalAccess', _198 => _198.data, 'optionalAccess', _199 => _199[TOKEN_MODES_DATA_KEY]]));
7651
+ }
7652
+ function getCanvasTokenProperty(key, options = {}) {
7653
+ return (_nullishCoalesce(options.properties, () => ( CANVAS_TOKEN_PROPERTIES))).find((p) => p.key === key);
7654
+ }
7655
+ function getBindableTokenProperties(node, options = {}) {
7656
+ return (_nullishCoalesce(options.properties, () => ( CANVAS_TOKEN_PROPERTIES))).filter((p) => p.appliesTo(node));
7657
+ }
7658
+ function getTokenPropertyScope(property, node) {
7659
+ return typeof property.scope === "function" ? property.scope(node) : property.scope;
7660
+ }
7661
+ function getTokensForProperty(state, property, node) {
7662
+ const scope = getTokenPropertyScope(property, node);
7663
+ return state.variables.filter((v) => v.type === property.type && _chunk4BVP64JJcjs.isTokenInScope.call(void 0, v, scope));
7664
+ }
7665
+ function lookupOf(nodes) {
7666
+ return new Map(nodes.map((n) => [n.id, n]));
7667
+ }
7668
+ function validModes(state, modes, into) {
7669
+ for (const [collectionId, modeId] of Object.entries(modes)) {
7670
+ if (state) {
7671
+ const collection = _chunk4BVP64JJcjs.getTokenCollection.call(void 0, state, collectionId);
7672
+ if (!collection || !collection.modes.some((m) => m.id === modeId)) continue;
7673
+ }
7674
+ into[collectionId] = modeId;
7675
+ }
7676
+ }
7677
+ function getEffectiveTokenModes(node, nodes, state, options = {}) {
7678
+ const lookup = nodes instanceof Map ? nodes : lookupOf(nodes);
7679
+ const chain = [];
7680
+ const seen = /* @__PURE__ */ new Set();
7681
+ for (let at = node; at && !seen.has(at.id); at = at.parentId ? lookup.get(at.parentId) : void 0) {
7682
+ seen.add(at.id);
7683
+ chain.push(at);
7684
+ }
7685
+ const out = {};
7686
+ if (options.modes) validModes(state, options.modes, out);
7687
+ for (let i = chain.length - 1; i >= 0; i--) validModes(state, getNodeTokenModes(chain[i]), out);
7688
+ return out;
7689
+ }
7690
+ function modesResolver(nodes, state, options) {
7691
+ const lookup = lookupOf(nodes);
7692
+ const memo = /* @__PURE__ */ new Map();
7693
+ const root = {};
7694
+ if (options.modes) validModes(state, options.modes, root);
7695
+ const visiting = /* @__PURE__ */ new Set();
7696
+ const modesOf = (node) => {
7697
+ const cached = memo.get(node.id);
7698
+ if (cached) return cached;
7699
+ let base = root;
7700
+ if (node.parentId && !visiting.has(node.id)) {
7701
+ const parent = lookup.get(node.parentId);
7702
+ if (parent) {
7703
+ visiting.add(node.id);
7704
+ base = modesOf(parent);
7705
+ visiting.delete(node.id);
7706
+ }
7707
+ }
7708
+ const own = getNodeTokenModes(node);
7709
+ let result = base;
7710
+ if (Object.keys(own).length > 0) {
7711
+ result = { ...base };
7712
+ validModes(state, own, result);
7713
+ }
7714
+ memo.set(node.id, result);
7715
+ return result;
7716
+ };
7717
+ return { lookup, modesOf };
7718
+ }
7719
+ function applyBindings(node, state, modes, options, only) {
7720
+ const bindings = getNodeTokenBindings(node);
7721
+ let next = node;
7722
+ for (const [key, variableId] of Object.entries(bindings)) {
7723
+ if (only && !only.has(variableId)) continue;
7724
+ const property = getCanvasTokenProperty(key, options);
7725
+ if (!property || !property.appliesTo(next)) continue;
7726
+ const resolved = _chunk4BVP64JJcjs.resolveToken.call(void 0, state, variableId, modes);
7727
+ if (!resolved.ok || resolved.type !== property.type) continue;
7728
+ next = property.write(next, resolved.value);
7729
+ }
7730
+ return next;
7731
+ }
7732
+ function resolveCanvasTokens(nodes, state, options = {}) {
7733
+ const { modesOf } = modesResolver(nodes, state, options);
7734
+ let changed = false;
7735
+ const out = nodes.map((node) => {
7736
+ if (Object.keys(getNodeTokenBindings(node)).length === 0) return node;
7737
+ const next = applyBindings(node, state, modesOf(node), options);
7738
+ if (next !== node) changed = true;
7739
+ return next;
7740
+ });
7741
+ return changed ? out : nodes;
7742
+ }
7743
+ function inspectNodeTokens(node, nodes, state, options = {}) {
7744
+ const modes = getEffectiveTokenModes(node, nodes, state, options);
7745
+ const out = [];
7746
+ for (const [key, variableId] of Object.entries(getNodeTokenBindings(node))) {
7747
+ const property = getCanvasTokenProperty(key, options);
7748
+ if (!property) continue;
7749
+ out.push({ property, variableId, variable: _chunk4BVP64JJcjs.getTokenVariable.call(void 0, state, variableId), resolution: _chunk4BVP64JJcjs.resolveToken.call(void 0, state, variableId, modes) });
7750
+ }
7751
+ return out;
7752
+ }
7753
+ function setDataRecord(node, key, record) {
7754
+ const data = { ...node.data };
7755
+ if (Object.keys(record).length === 0) delete data[key];
7756
+ else data[key] = record;
7757
+ return { ...node, data };
7758
+ }
7759
+ function bindCanvasToken(nodes, ids, propertyKey, variableId, state, options = {}) {
7760
+ const property = getCanvasTokenProperty(propertyKey, options);
7761
+ if (!property) throw new (0, _chunk4BVP64JJcjs.TokenError)("not-found", `No bindable property \`${propertyKey}\``);
7762
+ if (variableId !== null) {
7763
+ const variable = _chunk4BVP64JJcjs.getTokenVariable.call(void 0, state, variableId);
7764
+ if (!variable) throw new (0, _chunk4BVP64JJcjs.TokenError)("not-found", `No variable \`${variableId}\``);
7765
+ if (variable.type !== property.type) {
7766
+ throw new (0, _chunk4BVP64JJcjs.TokenError)("type-mismatch", `${property.label} takes a ${property.type} variable; \`${variable.name}\` is a ${variable.type}`);
7767
+ }
7768
+ }
7769
+ const targets = new Set(ids);
7770
+ let changed = false;
7771
+ const bound = nodes.map((node) => {
7772
+ if (!targets.has(node.id) || !property.appliesTo(node)) return node;
7773
+ const bindings = { ...getNodeTokenBindings(node) };
7774
+ if (variableId === null) {
7775
+ if (!(propertyKey in bindings)) return node;
7776
+ delete bindings[propertyKey];
7777
+ } else {
7778
+ if (bindings[propertyKey] === variableId) return node;
7779
+ bindings[propertyKey] = variableId;
7780
+ }
7781
+ changed = true;
7782
+ return setDataRecord(node, TOKEN_BINDINGS_DATA_KEY, bindings);
7783
+ });
7784
+ return changed ? resolveCanvasTokens(bound, state, options) : nodes;
7785
+ }
7786
+ function setCanvasTokenMode(nodes, ids, collectionId, modeId, state, options = {}) {
7787
+ if (modeId !== null) {
7788
+ const collection = _chunk4BVP64JJcjs.getTokenCollection.call(void 0, state, collectionId);
7789
+ if (!collection) throw new (0, _chunk4BVP64JJcjs.TokenError)("not-found", `No collection \`${collectionId}\``);
7790
+ if (!collection.modes.some((m) => m.id === modeId)) throw new (0, _chunk4BVP64JJcjs.TokenError)("not-found", `No mode \`${modeId}\` in \`${collection.name}\``);
7791
+ }
7792
+ const targets = new Set(ids);
7793
+ let changed = false;
7794
+ const next = nodes.map((node) => {
7795
+ if (!targets.has(node.id)) return node;
7796
+ const modes = { ...getNodeTokenModes(node) };
7797
+ if (modeId === null) {
7798
+ if (!(collectionId in modes)) return node;
7799
+ delete modes[collectionId];
7800
+ } else {
7801
+ if (modes[collectionId] === modeId) return node;
7802
+ modes[collectionId] = modeId;
7803
+ }
7804
+ changed = true;
7805
+ return setDataRecord(node, TOKEN_MODES_DATA_KEY, modes);
7806
+ });
7807
+ return changed ? resolveCanvasTokens(next, state, options) : nodes;
7808
+ }
7809
+ function detachTokenBindings(nodes, state, variableIds, options = {}) {
7810
+ const only = variableIds ? new Set(variableIds) : null;
7811
+ const isDetached = (id) => only ? only.has(id) : !_chunk4BVP64JJcjs.getTokenVariable.call(void 0, state, id);
7812
+ const { modesOf } = modesResolver(nodes, state, options);
7813
+ let changed = false;
7814
+ const out = nodes.map((node) => {
7815
+ const bindings = getNodeTokenBindings(node);
7816
+ const gone = Object.entries(bindings).filter(([, id]) => isDetached(id));
7817
+ if (gone.length === 0) return node;
7818
+ let next = applyBindings(node, state, modesOf(node), options, new Set(gone.map(([, id]) => id)));
7819
+ const kept = { ...bindings };
7820
+ for (const [key] of gone) delete kept[key];
7821
+ next = setDataRecord(next, TOKEN_BINDINGS_DATA_KEY, kept);
7822
+ changed = true;
7823
+ return next;
7824
+ });
7825
+ return changed ? out : nodes;
7826
+ }
7827
+ function pruneCanvasTokenModes(nodes, state) {
7828
+ let changed = false;
7829
+ const out = nodes.map((node) => {
7830
+ const modes = getNodeTokenModes(node);
7831
+ const valid = {};
7832
+ validModes(state, modes, valid);
7833
+ if (Object.keys(valid).length === Object.keys(modes).length) return node;
7834
+ changed = true;
7835
+ return setDataRecord(node, TOKEN_MODES_DATA_KEY, valid);
7836
+ });
7837
+ return changed ? out : nodes;
7838
+ }
7839
+
7840
+
7841
+
7842
+
7843
+
7844
+
7845
+
7846
+
7847
+
7848
+
7849
+
7850
+
7851
+
7852
+
7853
+
7854
+
7855
+
7856
+
7857
+
7858
+
7859
+
7860
+
7861
+
7862
+
7863
+
7864
+
7865
+
7866
+
7867
+
7868
+
7869
+
7870
+
7871
+
7872
+
7873
+
7874
+
7875
+
7876
+
7877
+
7878
+
7879
+
7880
+
7881
+
7882
+
7883
+
7884
+
7885
+
7886
+
7887
+
7888
+
7889
+
7890
+
7891
+
7892
+
7893
+
7894
+
7895
+
7896
+
7897
+
7898
+
7899
+
7900
+
7901
+
7902
+
7903
+
7904
+
7905
+
7906
+
5074
7907
 
5075
7908
 
5076
7909
 
@@ -5223,5 +8056,5 @@ function restoreOrder(nodes, order) {
5223
8056
 
5224
8057
 
5225
8058
 
5226
- exports.AUTO_LAYOUT_DATA_KEY = AUTO_LAYOUT_DATA_KEY; exports.CHILD_LAYOUT_DATA_KEY = CHILD_LAYOUT_DATA_KEY; 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.applyConstraints = applyConstraints; 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.clampLayoutSize = clampLayoutSize; exports.collectDescendantIds = collectDescendantIds; exports.combineShapeNodes = combineShapeNodes; exports.computeNodesBoundingBox = computeNodesBoundingBox; exports.computeSnapGuides = computeSnapGuides; exports.connectedOnly = connectedOnly; exports.createBezierTrajectory = createBezierTrajectory; exports.createCanvasArrangeController = createCanvasArrangeController; exports.createCanvasAutoLayoutController = createCanvasAutoLayoutController; 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.getAutoLayout = getAutoLayout; exports.getAutoLayoutGrid = getAutoLayoutGrid; exports.getAutoLayoutInsertTarget = getAutoLayoutInsertTarget; exports.getCenteredNodePosition = _chunkWADCJ7A7cjs.getCenteredNodePosition; exports.getChildLayout = getChildLayout; exports.getFlowChildren = getFlowChildren; exports.getLayoutParent = getLayoutParent; exports.getLayoutSizing = getLayoutSizing; 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.isAutoLayoutFrame = isAutoLayoutFrame; 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.layoutAll = layoutAll; exports.layoutBounds = layoutBounds; exports.layoutFrame = layoutFrame; exports.layoutUp = layoutUp; exports.layoutUpMany = layoutUpMany; exports.linearPositionTrajectory = linearPositionTrajectory; exports.linearTrajectory = linearTrajectory; exports.lockNodes = lockNodes; exports.makeSizingCoherent = makeSizingCoherent; exports.matchArrangeShortcut = _chunk26BVFKHUcjs.matchArrangeShortcut; exports.matchSize = matchSize; exports.measureBetween = measureBetween; exports.measureLabel = measureLabel; exports.measureSelection = measureSelection; exports.measureToLine = measureToLine; exports.mergeNodeUpdates = mergeNodeUpdates; exports.moveLayoutChild = moveLayoutChild; 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.relayoutUpdates = relayoutUpdates; exports.remapPastedNodes = remapPastedNodes; exports.reorderNodes = reorderNodes; exports.repositionNodesTo = repositionNodesTo; exports.resizeHandleAxes = resizeHandleAxes; exports.resolvePadding = resolvePadding; 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;
8059
+ exports.AUTO_LAYOUT_DATA_KEY = AUTO_LAYOUT_DATA_KEY; exports.CANVAS_TOKEN_PROPERTIES = CANVAS_TOKEN_PROPERTIES; exports.CHILD_LAYOUT_DATA_KEY = CHILD_LAYOUT_DATA_KEY; 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.PathOpsError = PathOpsError; 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.TOKEN_BINDINGS_DATA_KEY = TOKEN_BINDINGS_DATA_KEY; exports.TOKEN_MODES_DATA_KEY = TOKEN_MODES_DATA_KEY; exports.alignNodes = alignNodes; exports.applyConstraints = applyConstraints; exports.applyNodeUpdates = applyNodeUpdates; exports.applyShapeCombination = applyShapeCombination; exports.applyShapeReplacement = applyShapeReplacement; exports.arcToCubics = arcToCubics; exports.bezierPathArea = bezierPathArea; exports.bezierPathBounds = bezierPathBounds; exports.bezierPathLength = bezierPathLength; exports.bezierPathPointAtLength = bezierPathPointAtLength; exports.bezierPathSignedArea = bezierPathSignedArea; exports.bezierPathToSvg = bezierPathToSvg; exports.bindCanvasToken = bindCanvasToken; exports.blendLayout = blendLayout; exports.boundsOf = _chunkWADCJ7A7cjs.boundsOf; exports.calculateDagreReflowDisplacement = calculateDagreReflowDisplacement; exports.calculateDirectionalDisplacement = calculateDirectionalDisplacement; exports.canCombineShapeNodes = canCombineShapeNodes; exports.canOffsetShapeNodes = canOffsetShapeNodes; exports.canOutlineShapeNodeStrokes = canOutlineShapeNodeStrokes; exports.canvasHeight = canvasHeight; exports.centerNodes = _chunkWADCJ7A7cjs.centerNodes; exports.centre = _chunkWADCJ7A7cjs.centre; exports.clampLayoutSize = clampLayoutSize; exports.closeContour = closeContour; exports.collectDescendantIds = collectDescendantIds; exports.combineShapeNodes = combineShapeNodes; exports.computeNodesBoundingBox = computeNodesBoundingBox; exports.computeSnapGuides = computeSnapGuides; exports.connectedOnly = connectedOnly; exports.contourSignedArea = contourSignedArea; exports.contoursToPath = contoursToPath; exports.countPathSegments = countPathSegments; exports.createBezierTrajectory = createBezierTrajectory; exports.createCanvasArrangeController = createCanvasArrangeController; exports.createCanvasAutoLayoutController = createCanvasAutoLayoutController; exports.createCanvasScenesStore = createCanvasScenesStore; exports.createFanOutTrajectory = createFanOutTrajectory; exports.createGuideIndex = createGuideIndex; exports.createNodeGuideIndex = createNodeGuideIndex; exports.createNodeLookup = createNodeLookup; exports.cubicPointAt = cubicPointAt; exports.cubicsToPathData = cubicsToPathData; exports.dashContours = dashContours; exports.defaultEasing = defaultEasing; exports.detachTokenBindings = detachTokenBindings; exports.distanceToBezierPath = distanceToBezierPath; exports.distributeNodes = distributeNodes; exports.dividePaths = dividePaths; exports.dividePolygons = dividePolygons; exports.ensureLayout = _chunkWADCJ7A7cjs.ensureLayout; exports.estimateCanvasHeight = estimateCanvasHeight; exports.estimateNodeSize = _chunkWADCJ7A7cjs.estimateNodeSize; exports.excludePaths = excludePaths; 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.getAutoLayout = getAutoLayout; exports.getAutoLayoutGrid = getAutoLayoutGrid; exports.getAutoLayoutInsertTarget = getAutoLayoutInsertTarget; exports.getBindableTokenProperties = getBindableTokenProperties; exports.getCanvasTokenProperty = getCanvasTokenProperty; exports.getCenteredNodePosition = _chunkWADCJ7A7cjs.getCenteredNodePosition; exports.getChildLayout = getChildLayout; exports.getEffectiveTokenModes = getEffectiveTokenModes; exports.getFlowChildren = getFlowChildren; exports.getLayoutParent = getLayoutParent; exports.getLayoutSizing = getLayoutSizing; exports.getLayoutedNodes = _chunkWADCJ7A7cjs.getLayoutedNodes; exports.getNodeRect = getNodeRect; exports.getNodeShape = getNodeShape; exports.getNodeSize = getNodeSize; exports.getNodeTokenBindings = getNodeTokenBindings; exports.getNodeTokenModes = getNodeTokenModes; exports.getResizingNodeRect = getResizingNodeRect; exports.getShapeRenderData = getShapeRenderData; exports.getShapeSvg = getShapeSvg; exports.getTokenPropertyScope = getTokenPropertyScope; exports.getTokensForProperty = getTokensForProperty; exports.handlePoint = handlePoint; exports.hasVisibleStroke = hasVisibleStroke; exports.inferResizeHandle = inferResizeHandle; exports.inspectNodeTokens = inspectNodeTokens; exports.intersectPaths = intersectPaths; exports.intersectPolygons = intersectPolygons; exports.invertNodeUpdates = invertNodeUpdates; exports.isAutoLayoutFrame = isAutoLayoutFrame; 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.layoutAll = layoutAll; exports.layoutBounds = layoutBounds; exports.layoutFrame = layoutFrame; exports.layoutUp = layoutUp; exports.layoutUpMany = layoutUpMany; exports.linearPositionTrajectory = linearPositionTrajectory; exports.linearTrajectory = linearTrajectory; exports.lockNodes = lockNodes; exports.makeSizingCoherent = makeSizingCoherent; exports.matchArrangeShortcut = _chunk26BVFKHUcjs.matchArrangeShortcut; exports.matchSize = matchSize; exports.measureBetween = measureBetween; exports.measureLabel = measureLabel; exports.measureSelection = measureSelection; exports.measureToLine = measureToLine; exports.mergeNodeUpdates = mergeNodeUpdates; exports.moveLayoutChild = moveLayoutChild; exports.multiPolygonArea = multiPolygonArea; exports.multiPolygonBounds = multiPolygonBounds; exports.nearestHandlePositions = nearestHandlePositions; exports.normalizeBezierPath = normalizeBezierPath; exports.offsetPath = offsetPath; exports.offsetShapeNodes = offsetShapeNodes; exports.oppositePosition = oppositePosition; exports.outlineShapeNodeStrokes = outlineShapeNodeStrokes; exports.outlineStroke = outlineStroke; exports.overlaps = _chunkWADCJ7A7cjs.overlaps; exports.pageHidden = pageHidden; exports.parseCanvasClipboardData = parseCanvasClipboardData; exports.parseCanvasScenes = parseCanvasScenes; exports.parseSvgPath = parseSvgPath; exports.pathBoolean = pathBoolean; exports.pathToContours = pathToContours; exports.placeBeside = _chunkWADCJ7A7cjs.placeBeside; exports.pointInBezierPath = pointInBezierPath; exports.pointInMultiPolygon = pointInMultiPolygon; exports.pointInRings = pointInRings; exports.polygonArea = polygonArea; exports.polygonBoolean = polygonBoolean; exports.polygonToSvgPath = polygonToSvgPath; exports.positionToSide = positionToSide; exports.pruneCanvasTokenModes = pruneCanvasTokenModes; exports.readNodeStyleProperty = readNodeStyleProperty; exports.readStyleSize = readStyleSize; exports.realClock = realClock; exports.relayoutUpdates = relayoutUpdates; exports.remapPastedNodes = remapPastedNodes; exports.reorderNodes = reorderNodes; exports.repositionNodesTo = repositionNodesTo; exports.resizeHandleAxes = resizeHandleAxes; exports.resolveCanvasTokens = resolveCanvasTokens; exports.resolvePadding = resolvePadding; exports.revertShapeCombination = revertShapeCombination; exports.ringSignedArea = ringSignedArea; exports.runMultiNodeTransition = runMultiNodeTransition; exports.segmentBounds = segmentBounds; exports.segmentCurvature = segmentCurvature; exports.segmentDerivative = segmentDerivative; exports.segmentExtrema = segmentExtrema; exports.segmentLength = segmentLength; exports.segmentNearest = segmentNearest; exports.segmentParamAtLength = segmentParamAtLength; exports.segmentPoint = segmentPoint; exports.segmentTangent = segmentTangent; exports.serializeCanvasNodes = serializeCanvasNodes; exports.setCanvasTokenMode = setCanvasTokenMode; exports.shapeNodeToBezierPath = shapeNodeToBezierPath; exports.shapeNodeToPolygon = shapeNodeToPolygon; exports.shapeToBezierPath = shapeToBezierPath; exports.shapeToPolygon = shapeToPolygon; exports.sideToPosition = sideToPosition; exports.simplifyRing = simplifyRing; exports.snapNodeDrag = snapNodeDrag; exports.snapNodeResize = snapNodeResize; exports.snapResize = snapResize; exports.snapToGrid = snapToGrid; exports.splitSegment = splitSegment; exports.strokeOutlineRings = strokeOutlineRings; exports.subSegment = subSegment; exports.subtractPaths = subtractPaths; exports.subtractPolygons = subtractPolygons; exports.toBezierPath = toBezierPath; exports.toggleLockNodes = toggleLockNodes; exports.transformBezierPath = transformBezierPath; exports.trimSegments = trimSegments; exports.unionPolygons = unionPolygons; exports.unitePaths = unitePaths; exports.unlockNodes = unlockNodes; exports.windingNumber = windingNumber; exports.withStyleOpacity = withStyleOpacity; exports.withStyleSize = withStyleSize; exports.writeNodeStyleProperty = writeNodeStyleProperty; exports.xorPolygons = xorPolygons;
5227
8060
  //# sourceMappingURL=index.cjs.map