@pixerate/editor 0.37.0 → 0.39.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.
@@ -34,13 +34,34 @@ var _chunkQKLRAA4Tcjs = require('../chunk-QKLRAA4T.cjs');
34
34
 
35
35
 
36
36
 
37
- var _chunkGVB7ZPLZcjs = require('../chunk-GVB7ZPLZ.cjs');
37
+
38
+
39
+
40
+
41
+ var _chunkVNYRI265cjs = require('../chunk-VNYRI265.cjs');
38
42
 
39
43
  // src/vector/types.ts
40
44
  var VECTOR_CORNER_KINDS = ["round", "inverted", "chamfer"];
41
45
  var VECTOR_ARROWHEADS = ["triangle", "arrow", "open", "circle", "square", "bar"];
42
- var VECTOR_TOOLS = ["select", "direct", "pen", "pencil", "rect", "ellipse", "polygon", "star", "line", "scissors", "knife", "eraser", "width"];
46
+ var VECTOR_TOOLS = [
47
+ "select",
48
+ "direct",
49
+ "pen",
50
+ "pencil",
51
+ "rect",
52
+ "ellipse",
53
+ "polygon",
54
+ "star",
55
+ "line",
56
+ "scissors",
57
+ "knife",
58
+ "eraser",
59
+ "width",
60
+ "shapeBuilder",
61
+ "paintBucket"
62
+ ];
43
63
  var VECTOR_TRANSFORM_HANDLES = ["nw", "n", "ne", "e", "se", "s", "sw", "w", "rotate"];
64
+ var VECTOR_PATHFINDER_OPERATIONS = ["divide", "trim", "merge", "crop", "outline", "minusBack"];
44
65
 
45
66
  // src/vector/corners.ts
46
67
  var EPS = 1e-9;
@@ -61,7 +82,7 @@ var Side = class {
61
82
  constructor(a, h1, h2, b) {
62
83
  this.straight = onAnchor(a, h1) && onAnchor(b, h2);
63
84
  this.curve = this.straight ? [pt(a), pt(b)] : [pt(a), pt(_nullishCoalesce(h1, () => ( a))), pt(_nullishCoalesce(h2, () => ( b))), pt(b)];
64
- this.length = this.straight ? Math.hypot(b.x - a.x, b.y - a.y) : _chunkGVB7ZPLZcjs.segmentLength.call(void 0, this.curve);
85
+ this.length = this.straight ? Math.hypot(b.x - a.x, b.y - a.y) : _chunkVNYRI265cjs.segmentLength.call(void 0, this.curve);
65
86
  }
66
87
  /** Unit direction the side leaves the corner in (towards its first control point off the corner). */
67
88
  direction() {
@@ -79,10 +100,10 @@ var Side = class {
79
100
  const t2 = this.length > EPS ? Math.min(1, Math.max(0, s / this.length)) : 0;
80
101
  return { t: t2, p: add(vec(this.curve[0]), mul(u, s)), dir: u };
81
102
  }
82
- const t = _chunkGVB7ZPLZcjs.segmentParamAtLength.call(void 0, this.curve, s, this.length);
83
- const d = vec(_chunkGVB7ZPLZcjs.segmentDerivative.call(void 0, this.curve, t));
103
+ const t = _chunkVNYRI265cjs.segmentParamAtLength.call(void 0, this.curve, s, this.length);
104
+ const d = vec(_chunkVNYRI265cjs.segmentDerivative.call(void 0, this.curve, t));
84
105
  const l = len(d);
85
- return { t, p: vec(_chunkGVB7ZPLZcjs.segmentPoint.call(void 0, this.curve, t)), dir: l > EPS ? mul(d, 1 / l) : u };
106
+ return { t, p: vec(_chunkVNYRI265cjs.segmentPoint.call(void 0, this.curve, t)), dir: l > EPS ? mul(d, 1 / l) : u };
86
107
  }
87
108
  };
88
109
  function cornerOf(sp, s, i) {
@@ -183,7 +204,7 @@ function expandVectorCornersOf(sp, subpath = 0) {
183
204
  const s0 = from ? from.tv : 0;
184
205
  const s1 = to ? 1 - to.tu : 1;
185
206
  const seg = [pt(a), pt(_nullishCoalesce(a.out, () => ( a))), pt(_nullishCoalesce(b.in, () => ( b))), pt(b)];
186
- const part = _chunkGVB7ZPLZcjs.subSegment.call(void 0, seg, s0, Math.max(s0, s1));
207
+ const part = _chunkVNYRI265cjs.subSegment.call(void 0, seg, s0, Math.max(s0, s1));
187
208
  return { out: vec(part[1]), in: vec(part[2]) };
188
209
  });
189
210
  const anchors = [];
@@ -344,14 +365,14 @@ function mirrorWidthProfile(points) {
344
365
  function editable(points) {
345
366
  return _optionalChain([points, 'optionalAccess', _13 => _13.length]) ? points.map((p) => ({ ...p })) : [sym(0, 1), sym(1, 1)];
346
367
  }
347
- function insertWidthPoint(points, t, sides = {}, options = {}) {
368
+ function insertWidthPoint(points, t, sides2 = {}, options = {}) {
348
369
  const pts = editable(points);
349
370
  const tt = Math.min(Math.max(Number.isFinite(t) ? t : 0, 0), 1);
350
371
  const here = widthProfileAt(_optionalChain([points, 'optionalAccess', _14 => _14.length]) ? points : null, tt);
351
372
  const p = {
352
373
  t: tt,
353
- left: _nullishCoalesce(clean(sides.left, VECTOR_WIDTH_PROFILE_MAX_SCALE), () => ( here.left)),
354
- right: _nullishCoalesce(clean(sides.right, VECTOR_WIDTH_PROFILE_MAX_SCALE), () => ( here.right))
374
+ left: _nullishCoalesce(clean(sides2.left, VECTOR_WIDTH_PROFILE_MAX_SCALE), () => ( here.left)),
375
+ right: _nullishCoalesce(clean(sides2.right, VECTOR_WIDTH_PROFILE_MAX_SCALE), () => ( here.right))
355
376
  };
356
377
  const same = pts.findIndex((q) => Math.abs(q.t - tt) <= VECTOR_WIDTH_SAME_T);
357
378
  if (same >= 0 && !options.step) {
@@ -486,7 +507,7 @@ function flatten(segments, closed, tol) {
486
507
  corner.push(isCorner);
487
508
  };
488
509
  for (const seg of segments) {
489
- const flat = _chunkGVB7ZPLZcjs.flattenChain.call(void 0, [seg], tol);
510
+ const flat = _chunkVNYRI265cjs.flattenChain.call(void 0, [seg], tol);
490
511
  if (dist(seg[0], seg[seg.length - 1]) <= 1e-12 && flat.length > 1) flat.push(seg[seg.length - 1]);
491
512
  flat.forEach((p, i) => push(p, i === 0 || i === flat.length - 1));
492
513
  }
@@ -576,12 +597,12 @@ function variableStrokeRings(path, options) {
576
597
  const last = out[out.length - 1];
577
598
  if (!last || dist(last, p) > 1e-12) out.push(p);
578
599
  };
579
- for (const contour of _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path)) {
600
+ for (const contour of _chunkVNYRI265cjs.pathToContours.call(void 0, path)) {
580
601
  if (!contour.segments.length) continue;
581
602
  const poly = flatten(contour.segments, contour.closed, Math.min(tol, half) / 4);
582
603
  if (!poly) continue;
583
604
  const len2 = poly.s[poly.s.length - 1];
584
- const sides = (s) => {
605
+ const sides2 = (s) => {
585
606
  const w = widthProfileAt(options.profile, s / len2);
586
607
  return [w.left * half, w.right * half];
587
608
  };
@@ -595,7 +616,7 @@ function variableStrokeRings(path, options) {
595
616
  pts.push({ p: pb, s: b, corner: false });
596
617
  const run = pts.filter((q, i) => i === 0 || dist(q.p, pts[i - 1].p) > 1e-9);
597
618
  if (run.length < 2) {
598
- const [l, r] = sides(a);
619
+ const [l, r] = sides2(a);
599
620
  const w2 = (l + r) / 2;
600
621
  if (cap === "round" && w2 > 0) rings.push([[pa[0] + w2, pa[1]], ...arcPoints(pa, 0, 2 * Math.PI, w2, w2, tol)]);
601
622
  continue;
@@ -605,7 +626,7 @@ function variableStrokeRings(path, options) {
605
626
  const dirs = [];
606
627
  for (let i = 0; i < m; i++) dirs.push(unitOf(sub2(run[i + 1].p, run[i].p)));
607
628
  const normals = dirs.map(leftNormal);
608
- const w = run.map((q) => sides(q.s));
629
+ const w = run.map((q) => sides2(q.s));
609
630
  const side = (sigma) => {
610
631
  const k = sigma > 0 ? 0 : 1;
611
632
  const S = (i) => along(run[i].p, normals[i], sigma * w[i][k]);
@@ -702,7 +723,7 @@ function variableStrokeOutline(path, options) {
702
723
  const tol = options.tolerance && options.tolerance > 0 ? options.tolerance : 0.05;
703
724
  let polygons;
704
725
  try {
705
- polygons = _chunkGVB7ZPLZcjs.polygonBoolean.call(void 0, "union", [{ rings: pieces, fillRule: "nonzero" }]);
726
+ polygons = _chunkVNYRI265cjs.polygonBoolean.call(void 0, "union", [{ rings: pieces, fillRule: "nonzero" }]);
706
727
  } catch (e2) {
707
728
  return [];
708
729
  }
@@ -710,11 +731,11 @@ function variableStrokeOutline(path, options) {
710
731
  for (const polygon2 of polygons) {
711
732
  for (const ring of polygon2) {
712
733
  if (ring.length < 3) continue;
713
- const cubics = _chunkGVB7ZPLZcjs.fitCubics.call(void 0, ring, tol, { closed: true, cornerAngleDeg: 25 });
734
+ const cubics = _chunkVNYRI265cjs.fitCubics.call(void 0, ring, tol, { closed: true, cornerAngleDeg: 25 });
714
735
  if (!cubics.length) continue;
715
736
  out.push({ type: "M", x: cubics[0].p0[0], y: cubics[0].p0[1] });
716
737
  cubics.forEach((c, i) => {
717
- if (_chunkGVB7ZPLZcjs.isStraightCubic.call(void 0, c, tol * 0.02)) {
738
+ if (_chunkVNYRI265cjs.isStraightCubic.call(void 0, c, tol * 0.02)) {
718
739
  if (i < cubics.length - 1) out.push({ type: "L", x: c.p3[0], y: c.p3[1] });
719
740
  } else out.push({ type: "C", x1: c.p1[0], y1: c.p1[1], x2: c.p2[0], y2: c.p2[1], x: c.p3[0], y: c.p3[1] });
720
741
  });
@@ -725,17 +746,17 @@ function variableStrokeOutline(path, options) {
725
746
  }
726
747
  function nearestStrokePosition(path, p, only) {
727
748
  let best = null;
728
- _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path).forEach((c, ci) => {
749
+ _chunkVNYRI265cjs.pathToContours.call(void 0, path).forEach((c, ci) => {
729
750
  if (!c.segments.length || only !== void 0 && ci !== only) return;
730
- const lengths = c.segments.map((s) => _chunkGVB7ZPLZcjs.segmentLength.call(void 0, s));
751
+ const lengths = c.segments.map((s) => _chunkVNYRI265cjs.segmentLength.call(void 0, s));
731
752
  const total = lengths.reduce((a, b) => a + b, 0);
732
753
  if (!(total > 0)) return;
733
754
  let acc = 0;
734
755
  c.segments.forEach((seg, si) => {
735
- const near2 = _chunkGVB7ZPLZcjs.segmentNearest.call(void 0, seg, p);
756
+ const near2 = _chunkVNYRI265cjs.segmentNearest.call(void 0, seg, p);
736
757
  if (!best || near2.distance < best.distance) {
737
- const s = acc + _chunkGVB7ZPLZcjs.segmentLength.call(void 0, seg, 0, near2.t);
738
- const tan = _chunkGVB7ZPLZcjs.segmentTangent.call(void 0, seg, near2.t);
758
+ const s = acc + _chunkVNYRI265cjs.segmentLength.call(void 0, seg, 0, near2.t);
759
+ const tan = _chunkVNYRI265cjs.segmentTangent.call(void 0, seg, near2.t);
739
760
  const pt2 = seg.length === 2 ? lerp(seg[0], seg[1], near2.t) : evalSeg(seg, near2.t);
740
761
  const n = leftNormal([tan[0], tan[1]]);
741
762
  const side = (p[0] - pt2[0]) * n[0] + (p[1] - pt2[1]) * n[1] >= 0 ? "left" : "right";
@@ -752,9 +773,9 @@ function evalSeg(seg, t) {
752
773
  return pts[0];
753
774
  }
754
775
  function strokePositionPoint(path, index, t) {
755
- const c = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path)[index];
776
+ const c = _chunkVNYRI265cjs.pathToContours.call(void 0, path)[index];
756
777
  if (!_optionalChain([c, 'optionalAccess', _22 => _22.segments, 'access', _23 => _23.length])) return null;
757
- const lengths = c.segments.map((s) => _chunkGVB7ZPLZcjs.segmentLength.call(void 0, s));
778
+ const lengths = c.segments.map((s) => _chunkVNYRI265cjs.segmentLength.call(void 0, s));
758
779
  const total = lengths.reduce((a, b) => a + b, 0);
759
780
  let want = Math.min(Math.max(t, 0), 1) * total;
760
781
  for (let i = 0; i < c.segments.length; i++) {
@@ -765,11 +786,11 @@ function strokePositionPoint(path, index, t) {
765
786
  const target = Math.min(want, lengths[i]);
766
787
  for (let k = 0; k < 40; k++) {
767
788
  const mid = (lo + hi) / 2;
768
- if (_chunkGVB7ZPLZcjs.segmentLength.call(void 0, seg, 0, mid) < target) lo = mid;
789
+ if (_chunkVNYRI265cjs.segmentLength.call(void 0, seg, 0, mid) < target) lo = mid;
769
790
  else hi = mid;
770
791
  }
771
792
  const u = (lo + hi) / 2;
772
- const tan = _chunkGVB7ZPLZcjs.segmentTangent.call(void 0, seg, u);
793
+ const tan = _chunkVNYRI265cjs.segmentTangent.call(void 0, seg, u);
773
794
  return { point: evalSeg(seg, u), tangent: [tan[0], tan[1]] };
774
795
  }
775
796
  want -= lengths[i];
@@ -781,7 +802,7 @@ function strokePositionPoint(path, index, t) {
781
802
  var KAPPA = 0.5522847498307936;
782
803
  var NOTCH = 0.7;
783
804
  function isClosedBezierShape(path) {
784
- const contours = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path).filter((c) => c.segments.length > 0);
805
+ const contours = _chunkVNYRI265cjs.pathToContours.call(void 0, path).filter((c) => c.segments.length > 0);
785
806
  return contours.length > 0 && contours.every((c) => c.closed);
786
807
  }
787
808
  function effectiveStrokeAlign(style, closedShape) {
@@ -802,7 +823,7 @@ function vectorStrokeLineArea(parts, style, tolerance) {
802
823
  const join = _nullishCoalesce(style.strokeLinejoin, () => ( "miter"));
803
824
  const cap = _nullishCoalesce(style.strokeLinecap, () => ( "butt"));
804
825
  if (profile) return variableStrokeOutline(parts.line, { width: parts.drawWidth, profile, join, cap, ...dash, ...tolerance ? { tolerance } : {} });
805
- return _chunkGVB7ZPLZcjs.outlineStroke.call(void 0, parts.line, { width: parts.drawWidth, join, cap, ...dash, ...tolerance ? { tolerance } : {} });
826
+ return _chunkVNYRI265cjs.outlineStroke.call(void 0, parts.line, { width: parts.drawWidth, join, cap, ...dash, ...tolerance ? { tolerance } : {} });
806
827
  }
807
828
  var capExtent = (style, width) => style.strokeLinecap === "round" || style.strokeLinecap === "square" ? width / 2 : 0;
808
829
  function arrowheadWeight(style, end) {
@@ -879,16 +900,16 @@ function arrowheadPath(kind, tip, dir, hw) {
879
900
  }
880
901
  }
881
902
  var toVec = (p) => ({ x: p[0], y: p[1] });
882
- var segLen = (s) => _chunkGVB7ZPLZcjs.segmentLength.call(void 0, s);
903
+ var segLen = (s) => _chunkVNYRI265cjs.segmentLength.call(void 0, s);
883
904
  function endOf(segs, atStart) {
884
905
  const long = (s2) => segLen(s2) > 1e-9;
885
906
  if (atStart) {
886
907
  const s2 = _nullishCoalesce(segs.find(long), () => ( segs[0]));
887
- const t2 = _chunkGVB7ZPLZcjs.segmentTangent.call(void 0, s2, 0);
908
+ const t2 = _chunkVNYRI265cjs.segmentTangent.call(void 0, s2, 0);
888
909
  return { p: toVec(segs[0][0]), out: v(-t2[0], -t2[1]) };
889
910
  }
890
911
  const s = _nullishCoalesce([...segs].reverse().find(long), () => ( segs[segs.length - 1]));
891
- const t = _chunkGVB7ZPLZcjs.segmentTangent.call(void 0, s, 1);
912
+ const t = _chunkVNYRI265cjs.segmentTangent.call(void 0, s, 1);
892
913
  const last = segs[segs.length - 1];
893
914
  return { p: toVec(last[last.length - 1]), out: v(t[0], t[1]) };
894
915
  }
@@ -899,7 +920,7 @@ function pointAlong(segs, fromStart, dist4) {
899
920
  const l = segLen(s);
900
921
  if (acc + l >= dist4) {
901
922
  const want = fromStart ? dist4 - acc : l - (dist4 - acc);
902
- const pts = _chunkGVB7ZPLZcjs.trimSegments.call(void 0, [s], 0, want);
923
+ const pts = _chunkVNYRI265cjs.trimSegments.call(void 0, [s], 0, want);
903
924
  const p = pts.length ? pts[0][pts[0].length - 1] : s[0];
904
925
  return toVec(p);
905
926
  }
@@ -909,7 +930,7 @@ function pointAlong(segs, fromStart, dist4) {
909
930
  }
910
931
  function vectorStrokeParts(path, style) {
911
932
  const width = _nullishCoalesce(style.strokeWidth, () => ( 1));
912
- const contours = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path).filter((c) => c.segments.length > 0);
933
+ const contours = _chunkVNYRI265cjs.pathToContours.call(void 0, path).filter((c) => c.segments.length > 0);
913
934
  const closedShape = contours.length > 0 && contours.every((c) => c.closed);
914
935
  const align = effectiveStrokeAlign(style, closedShape);
915
936
  const drawWidth = align === "center" ? width : width * 2;
@@ -949,26 +970,26 @@ function vectorStrokeParts(path, style) {
949
970
  if (!s0 && !s1) return c;
950
971
  const lengths = c.segments.map(segLen);
951
972
  const total = lengths.reduce((a, b) => a + b, 0);
952
- return { closed: false, segments: total - s1 > s0 ? _chunkGVB7ZPLZcjs.trimSegments.call(void 0, c.segments, s0, total - s1, lengths) : [] };
973
+ return { closed: false, segments: total - s1 > s0 ? _chunkVNYRI265cjs.trimSegments.call(void 0, c.segments, s0, total - s1, lengths) : [] };
953
974
  });
954
- return { align, line: _chunkGVB7ZPLZcjs.contoursToPath.call(void 0, trimmed), drawWidth, heads };
975
+ return { align, line: _chunkVNYRI265cjs.contoursToPath.call(void 0, trimmed), drawWidth, heads };
955
976
  }
956
977
  function vectorStrokeOutlinePath(path, style) {
957
978
  const parts = vectorStrokeParts(path, style);
958
979
  const stroke = vectorStrokeLineArea(parts, style);
959
980
  const fill = { path, fillRule: _nullishCoalesce(style.fillRule, () => ( "nonzero")) };
960
981
  let area = stroke;
961
- if (parts.align === "inside") area = _chunkGVB7ZPLZcjs.pathBoolean.call(void 0, "intersection", [stroke, fill]).path;
962
- else if (parts.align === "outside") area = _chunkGVB7ZPLZcjs.pathBoolean.call(void 0, "difference", [stroke, fill]).path;
982
+ if (parts.align === "inside") area = _chunkVNYRI265cjs.pathBoolean.call(void 0, "intersection", [stroke, fill]).path;
983
+ else if (parts.align === "outside") area = _chunkVNYRI265cjs.pathBoolean.call(void 0, "difference", [stroke, fill]).path;
963
984
  if (!parts.heads.length) return area;
964
- return _chunkGVB7ZPLZcjs.pathBoolean.call(void 0, "union", [area, ...parts.heads.map((h) => h.path)]).path;
985
+ return _chunkVNYRI265cjs.pathBoolean.call(void 0, "union", [area, ...parts.heads.map((h) => h.path)]).path;
965
986
  }
966
987
  function hitTestVectorStroke(path, p, style, tolerance = 0) {
967
988
  const parts = vectorStrokeParts(path, style);
968
989
  const point = [p.x, p.y];
969
990
  const width = _nullishCoalesce(style.strokeWidth, () => ( 1));
970
991
  for (const h of parts.heads) {
971
- if (_chunkGVB7ZPLZcjs.pointInBezierPath.call(void 0, h.path, point) || tolerance > 0 && _chunkGVB7ZPLZcjs.distanceToBezierPath.call(void 0, h.path, point) <= tolerance) return true;
992
+ if (_chunkVNYRI265cjs.pointInBezierPath.call(void 0, h.path, point) || tolerance > 0 && _chunkVNYRI265cjs.distanceToBezierPath.call(void 0, h.path, point) <= tolerance) return true;
972
993
  }
973
994
  if (!parts.line.length) return false;
974
995
  const profile = strokeWidthProfileOf(style);
@@ -986,13 +1007,13 @@ function hitTestVectorStroke(path, p, style, tolerance = 0) {
986
1007
  reach = Math.max(reach, width / 2 * (w.left + w.right) / 2);
987
1008
  }
988
1009
  } else {
989
- d = _chunkGVB7ZPLZcjs.distanceToBezierPath.call(void 0, parts.line, point);
1010
+ d = _chunkVNYRI265cjs.distanceToBezierPath.call(void 0, parts.line, point);
990
1011
  if (parts.align !== "center") reach = width;
991
1012
  }
992
1013
  if (parts.align === "center") return d <= reach + tolerance;
993
1014
  if (d > reach + tolerance) return false;
994
1015
  if (d <= tolerance) return true;
995
- const inside = _chunkGVB7ZPLZcjs.pointInBezierPath.call(void 0, path, point, _nullishCoalesce(style.fillRule, () => ( "nonzero")));
1016
+ const inside = _chunkVNYRI265cjs.pointInBezierPath.call(void 0, path, point, _nullishCoalesce(style.fillRule, () => ( "nonzero")));
996
1017
  return parts.align === "inside" ? inside : !inside;
997
1018
  }
998
1019
  function vectorStrokeReach(style) {
@@ -1068,7 +1089,7 @@ function vectorNodeToBezier(node) {
1068
1089
  }
1069
1090
  function vectorPathData(input, precision = 3) {
1070
1091
  const subpaths = Array.isArray(input) ? input : input.subpaths;
1071
- return _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, subpathsToBezier(subpaths), { precision });
1092
+ return _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, subpathsToBezier(subpaths), { precision });
1072
1093
  }
1073
1094
  function inferAnchorType(a) {
1074
1095
  if (isOnAnchor(a, a.in) || isOnAnchor(a, a.out)) return "corner";
@@ -1084,7 +1105,7 @@ function inferAnchorType(a) {
1084
1105
  return Math.abs(li - lo) <= 1e-3 * Math.max(li, lo) ? "symmetric" : "smooth";
1085
1106
  }
1086
1107
  function bezierToSubpaths(input) {
1087
- const path = _chunkGVB7ZPLZcjs.toBezierPath.call(void 0, input);
1108
+ const path = _chunkVNYRI265cjs.toBezierPath.call(void 0, input);
1088
1109
  const out = [];
1089
1110
  let current = null;
1090
1111
  const last = () => current.anchors[current.anchors.length - 1];
@@ -1181,14 +1202,14 @@ function nodeMatrix(node) {
1181
1202
  function vectorPathWorldBezier(node, parent = IDENTITY_MATRIX) {
1182
1203
  const m = multiplyMatrices(nodeMatrix(node), parent);
1183
1204
  const path = subpathsToBezier(node.subpaths);
1184
- return isIdentityMatrix(m) ? path : _chunkGVB7ZPLZcjs.transformBezierPath.call(void 0, path, m);
1205
+ return isIdentityMatrix(m) ? path : _chunkVNYRI265cjs.transformBezierPath.call(void 0, path, m);
1185
1206
  }
1186
1207
  function vectorNodeBounds(node, parent = IDENTITY_MATRIX) {
1187
1208
  if (node.type === "group") {
1188
1209
  const m = multiplyMatrices(nodeMatrix(node), parent);
1189
1210
  return unionBounds(node.children.map((c) => vectorNodeBounds(c, m)));
1190
1211
  }
1191
- const b = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, vectorPathWorldBezier(node, parent));
1212
+ const b = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, vectorPathWorldBezier(node, parent));
1192
1213
  if (!b) return null;
1193
1214
  return { x: b.minX, y: b.minY, width: b.maxX - b.minX, height: b.maxY - b.minY };
1194
1215
  }
@@ -1222,9 +1243,9 @@ function hitTestVectorNode(node, p, tolerance = 0, parent = IDENTITY_MATRIX) {
1222
1243
  const path = vectorPathWorldBezier(node, parent);
1223
1244
  if (path.length === 0) return false;
1224
1245
  const point = [p.x, p.y];
1225
- if (hasPaint(node.fill) && _chunkGVB7ZPLZcjs.pointInBezierPath.call(void 0, path, point, _nullishCoalesce(node.fillRule, () => ( "nonzero")))) return true;
1246
+ if (hasPaint(node.fill) && _chunkVNYRI265cjs.pointInBezierPath.call(void 0, path, point, _nullishCoalesce(node.fillRule, () => ( "nonzero")))) return true;
1226
1247
  if (hasPaint(node.stroke)) return hitTestVectorStroke(path, p, node, tolerance);
1227
- return _chunkGVB7ZPLZcjs.distanceToBezierPath.call(void 0, path, point) <= tolerance;
1248
+ return _chunkVNYRI265cjs.distanceToBezierPath.call(void 0, path, point) <= tolerance;
1228
1249
  }
1229
1250
  function vectorStrokeOutline(node, parent = IDENTITY_MATRIX) {
1230
1251
  if (!hasPaint(node.stroke) || !((_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0)) return [];
@@ -1244,9 +1265,9 @@ function nearestSegment(node, p) {
1244
1265
  const count = subpathSegmentCount(sp);
1245
1266
  for (let i = 0; i < count; i++) {
1246
1267
  const seg = subpathSegment(sp, i);
1247
- const hit = _chunkGVB7ZPLZcjs.segmentNearest.call(void 0, seg, [p.x, p.y]);
1268
+ const hit = _chunkVNYRI265cjs.segmentNearest.call(void 0, seg, [p.x, p.y]);
1248
1269
  if (!best || hit.distance < best.distance) {
1249
- const pt2 = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, hit.t);
1270
+ const pt2 = _chunkVNYRI265cjs.segmentPoint.call(void 0, seg, hit.t);
1250
1271
  best = { subpath: s, segment: i, t: hit.t, point: { x: pt2[0], y: pt2[1] }, distance: hit.distance };
1251
1272
  }
1252
1273
  }
@@ -1420,7 +1441,7 @@ function insertAnchor(sp, segment, t) {
1420
1441
  const ia = segment;
1421
1442
  const ib = (segment + 1) % n;
1422
1443
  const seg = subpathSegment(sp, segment);
1423
- const [left, right] = _chunkGVB7ZPLZcjs.splitSegment.call(void 0, seg, t);
1444
+ const [left, right] = _chunkVNYRI265cjs.splitSegment.call(void 0, seg, t);
1424
1445
  const mid = left[left.length - 1];
1425
1446
  const anchor = { x: mid[0], y: mid[1] };
1426
1447
  if (seg.length === 4) {
@@ -1474,8 +1495,8 @@ function ellipseSubpath(b) {
1474
1495
  ]
1475
1496
  };
1476
1497
  }
1477
- function polygonSubpath(b, sides = 6) {
1478
- const n = Math.max(3, Math.round(sides));
1498
+ function polygonSubpath(b, sides2 = 6) {
1499
+ const n = Math.max(3, Math.round(sides2));
1479
1500
  const cx = b.x + b.width / 2;
1480
1501
  const cy = b.y + b.height / 2;
1481
1502
  const anchors = [];
@@ -1516,7 +1537,7 @@ function vectorCornersAttribute(subpaths, precision = 3) {
1516
1537
  subpaths.forEach(
1517
1538
  (sp, s) => sp.anchors.forEach((a, i) => {
1518
1539
  if (!a.corner || !(a.corner.radius > 0)) return;
1519
- out.push(`${s}.${i}:${_chunkGVB7ZPLZcjs.formatNumber.call(void 0, a.corner.radius, precision)}${a.corner.kind && a.corner.kind !== "round" ? `:${a.corner.kind}` : ""}`);
1540
+ out.push(`${s}.${i}:${_chunkVNYRI265cjs.formatNumber.call(void 0, a.corner.radius, precision)}${a.corner.kind && a.corner.kind !== "round" ? `:${a.corner.kind}` : ""}`);
1520
1541
  })
1521
1542
  );
1522
1543
  return out.join(" ");
@@ -1537,7 +1558,7 @@ var escapeAttr = (value) => value.replace(/&/g, "&amp;").replace(/"/g, "&quot;")
1537
1558
  function vectorPaintToSvg(paint, gradientId) {
1538
1559
  if (!hasPaint(paint)) return { value: "none", gradient: null };
1539
1560
  if (typeof paint === "string") return { value: paint, gradient: null };
1540
- return { value: `url(#${gradientId})`, gradient: _chunkGVB7ZPLZcjs.gradientToSvgDef.call(void 0, paint, gradientId) };
1561
+ return { value: `url(#${gradientId})`, gradient: _chunkVNYRI265cjs.gradientToSvgDef.call(void 0, paint, gradientId) };
1541
1562
  }
1542
1563
  var partsCache = /* @__PURE__ */ new WeakMap();
1543
1564
  function vectorStrokeSvgParts(node, clipId, precision = 3) {
@@ -1555,22 +1576,22 @@ function computeStrokeSvgParts(node, clipId, precision) {
1555
1576
  if (parts.align === "center" && !parts.heads.length && !profiled) return void 0;
1556
1577
  let clip = null;
1557
1578
  if (parts.align !== "center") {
1558
- const b = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, path);
1579
+ const b = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, path);
1559
1580
  const pad = vectorStrokeReach(node) + 1;
1560
1581
  const bounds = b ? { x: round2(b.minX - pad), y: round2(b.minY - pad), width: round2(b.maxX - b.minX + 2 * pad), height: round2(b.maxY - b.minY + 2 * pad) } : { x: 0, y: 0, width: 0, height: 0 };
1561
1582
  clip = { kind: parts.align === "inside" ? "clip" : "mask", id: clipId, bounds };
1562
1583
  }
1563
1584
  return {
1564
1585
  align: parts.align,
1565
- d: _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, parts.line, { precision }),
1586
+ d: _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, parts.line, { precision }),
1566
1587
  width: parts.drawWidth,
1567
- ...profiled && (_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0 ? { outline: _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, vectorStrokeLineArea(parts, node), { precision }) } : {},
1588
+ ...profiled && (_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0 ? { outline: _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, vectorStrokeLineArea(parts, node), { precision }) } : {},
1568
1589
  clip,
1569
- heads: parts.heads.map((h) => _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, h.path, { precision }))
1590
+ heads: parts.heads.map((h) => _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, h.path, { precision }))
1570
1591
  };
1571
1592
  }
1572
1593
  function widthProfileToAttribute(points, precision = 4) {
1573
- return points.map((p) => [p.t, p.left, p.right].map((n) => _chunkGVB7ZPLZcjs.formatNumber.call(void 0, n, precision)).join(",")).join(";");
1594
+ return points.map((p) => [p.t, p.left, p.right].map((n) => _chunkVNYRI265cjs.formatNumber.call(void 0, n, precision)).join(",")).join(";");
1574
1595
  }
1575
1596
  function widthProfileFromAttribute(value) {
1576
1597
  if (!value) return [];
@@ -1594,11 +1615,11 @@ function vectorDocumentToSvg(doc, options = {}) {
1594
1615
  const pretty = options.pretty !== false;
1595
1616
  const defs = [];
1596
1617
  const lines = [];
1597
- const num = (n) => _chunkGVB7ZPLZcjs.formatNumber.call(void 0, n, precision);
1618
+ const num = (n) => _chunkVNYRI265cjs.formatNumber.call(void 0, n, precision);
1598
1619
  const indent = (depth) => pretty ? " ".repeat(depth) : "";
1599
1620
  const common = (node) => {
1600
1621
  let out2 = ` id="${escapeAttr(node.id)}"`;
1601
- if (node.transform) out2 += ` transform="matrix(${node.transform.map((n) => _chunkGVB7ZPLZcjs.formatNumber.call(void 0, n, 6)).join(" ")})"`;
1622
+ if (node.transform) out2 += ` transform="matrix(${node.transform.map((n) => _chunkVNYRI265cjs.formatNumber.call(void 0, n, 6)).join(" ")})"`;
1602
1623
  if (node.opacity !== void 0 && node.opacity < 1) out2 += ` opacity="${num(node.opacity)}"`;
1603
1624
  if (node.visible === false) out2 += ` display="none"`;
1604
1625
  return out2;
@@ -1617,7 +1638,7 @@ function vectorDocumentToSvg(doc, options = {}) {
1617
1638
  if (stroke.gradient) defs.push(gradientMarkup(stroke.gradient));
1618
1639
  const d = vectorPathData(node, precision);
1619
1640
  const corners2 = vectorCornersAttribute(node.subpaths, precision);
1620
- const live = corners2 ? ` data-vector-d="${_chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, subpathsToBezier(node.subpaths, { corners: false }), { precision })}" data-vector-corners="${corners2}"` : "";
1641
+ const live = corners2 ? ` data-vector-d="${_chunkVNYRI265cjs.bezierPathToSvg.call(void 0, subpathsToBezier(node.subpaths, { corners: false }), { precision })}" data-vector-corners="${corners2}"` : "";
1621
1642
  const fillAttrs = ` fill="${escapeAttr(fill.value)}"${node.fillRule === "evenodd" ? ` fill-rule="evenodd"` : ""}`;
1622
1643
  const lineAttrs = (width) => {
1623
1644
  let out2 = ` stroke="${escapeAttr(stroke.value)}" stroke-width="${num(width)}"`;
@@ -1648,7 +1669,7 @@ function vectorDocumentToSvg(doc, options = {}) {
1648
1669
  lines.push(`${indent(depth)}<g${common(node)}${data}>`);
1649
1670
  lines.push(`${indent(depth + 1)}<path data-vector-part="fill" d="${d}"${fillAttrs}${live}/>`);
1650
1671
  if (options.strokes === "outline") {
1651
- const area = _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, vectorStrokeOutlinePath(subpathsToBezier(node.subpaths), node), { precision });
1672
+ const area = _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, vectorStrokeOutlinePath(subpathsToBezier(node.subpaths), node), { precision });
1652
1673
  lines.push(`${indent(depth + 1)}<path data-vector-part="stroke-outline" d="${area}" fill="${escapeAttr(stroke.value)}"/>`);
1653
1674
  } else {
1654
1675
  let clip = "";
@@ -2373,13 +2394,13 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
2373
2394
  const pt2 = toPoint(p);
2374
2395
  for (const s of this.segments) {
2375
2396
  if (p.x < s.minX - tol || p.x > s.maxX + tol || p.y < s.minY - tol || p.y > s.maxY + tol) continue;
2376
- const hit = _chunkGVB7ZPLZcjs.segmentNearest.call(void 0, s.seg, pt2);
2397
+ const hit = _chunkVNYRI265cjs.segmentNearest.call(void 0, s.seg, pt2);
2377
2398
  if (hit.distance <= tol) out.push({ seg: s.seg, t: hit.t, distance: hit.distance });
2378
2399
  }
2379
2400
  return out.sort((a, b) => a.distance - b.distance);
2380
2401
  }
2381
2402
  onSegment(near2) {
2382
- return near2.length ? toVec2(_chunkGVB7ZPLZcjs.segmentPoint.call(void 0, near2[0].seg, near2[0].t)) : null;
2403
+ return near2.length ? toVec2(_chunkVNYRI265cjs.segmentPoint.call(void 0, near2[0].seg, near2[0].t)) : null;
2383
2404
  }
2384
2405
  /** Where two of the target segments near `p` cross, the crossing nearest `p` within `tol`. */
2385
2406
  crossing(near2, p, tol) {
@@ -2388,7 +2409,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
2388
2409
  let bestD = Infinity;
2389
2410
  for (let i = 0; i < list.length; i++) {
2390
2411
  for (let j = i + 1; j < list.length; j++) {
2391
- for (const hit of _chunkGVB7ZPLZcjs.segmentIntersections.call(void 0, list[i].seg, list[j].seg)) {
2412
+ for (const hit of _chunkVNYRI265cjs.segmentIntersections.call(void 0, list[i].seg, list[j].seg)) {
2392
2413
  const q = toVec2(hit.point);
2393
2414
  const d = distance(q, p);
2394
2415
  if (d <= tol && d < bestD) {
@@ -2710,15 +2731,15 @@ var crossCondition = (r, d) => r[0] * d[1] - r[1] * d[0];
2710
2731
  function solveOnSegment(seg, base, cond) {
2711
2732
  const b = [base.x, base.y];
2712
2733
  const g = (t) => {
2713
- const p = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, t);
2714
- return cond([p[0] - b[0], p[1] - b[1]], _chunkGVB7ZPLZcjs.segmentDerivative.call(void 0, seg, t));
2734
+ const p = _chunkVNYRI265cjs.segmentPoint.call(void 0, seg, t);
2735
+ return cond([p[0] - b[0], p[1] - b[1]], _chunkVNYRI265cjs.segmentDerivative.call(void 0, seg, t));
2715
2736
  };
2716
2737
  const vals = [];
2717
2738
  let scale = 0;
2718
2739
  for (let i = 0; i <= CURVE_SAMPLES; i++) {
2719
2740
  const t = i / CURVE_SAMPLES;
2720
- const p = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, t);
2721
- const d = _chunkGVB7ZPLZcjs.segmentDerivative.call(void 0, seg, t);
2741
+ const p = _chunkVNYRI265cjs.segmentPoint.call(void 0, seg, t);
2742
+ const d = _chunkVNYRI265cjs.segmentDerivative.call(void 0, seg, t);
2722
2743
  const r = [p[0] - b[0], p[1] - b[1]];
2723
2744
  vals.push(cond(r, d));
2724
2745
  scale = Math.max(scale, Math.hypot(r[0], r[1]) * Math.hypot(d[0], d[1]));
@@ -2745,8 +2766,8 @@ function solveOnSegment(seg, base, cond) {
2745
2766
  } else hi = m;
2746
2767
  }
2747
2768
  const t = (lo + hi) / 2;
2748
- const p = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, t);
2749
- const dv = _chunkGVB7ZPLZcjs.segmentDerivative.call(void 0, seg, t);
2769
+ const p = _chunkVNYRI265cjs.segmentPoint.call(void 0, seg, t);
2770
+ const dv = _chunkVNYRI265cjs.segmentDerivative.call(void 0, seg, t);
2750
2771
  const r = Math.hypot(p[0] - b[0], p[1] - b[1]);
2751
2772
  const dl = Math.hypot(dv[0], dv[1]);
2752
2773
  if (!(r > 1e-9 && dl > 0) || Math.abs(cond([p[0] - b[0], p[1] - b[1]], dv)) > 1e-6 * r * dl) continue;
@@ -2783,7 +2804,7 @@ function endTangent(c) {
2783
2804
  return [1, 0];
2784
2805
  }
2785
2806
  function sample(c, n, out, withStart) {
2786
- for (let i = withStart ? 0 : 1; i <= n; i++) out.push(_chunkGVB7ZPLZcjs.segmentPoint.call(void 0, c, i / n));
2807
+ for (let i = withStart ? 0 : 1; i <= n; i++) out.push(_chunkVNYRI265cjs.segmentPoint.call(void 0, c, i / n));
2787
2808
  }
2788
2809
  var onAnchor2 = (a, h) => !h || Math.abs(h.x - a.x) < EPS3 && Math.abs(h.y - a.y) < EPS3;
2789
2810
  function tidy(a, keepType = true) {
@@ -2829,7 +2850,7 @@ function fitAcross(pts, N, t0, t1) {
2829
2850
  const u = [];
2830
2851
  for (let i = 0; i <= N; i++) u.push(k * i / N);
2831
2852
  for (let i = 1; i <= N; i++) u.push(k + (1 - k) * i / N);
2832
- return _chunkGVB7ZPLZcjs.fitCubicWithTangents.call(void 0, pts, u, t0, t1);
2853
+ return _chunkVNYRI265cjs.fitCubicWithTangents.call(void 0, pts, u, t0, t1);
2833
2854
  };
2834
2855
  return goldenMin(fit, 0, 1);
2835
2856
  }
@@ -2889,7 +2910,7 @@ function bendSegment(sp, segment, t, p) {
2889
2910
  return { anchors, closed: sp.closed };
2890
2911
  }
2891
2912
  function subpathPointAt(sp, segment, t) {
2892
- const [x, y] = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, subpathSegment(sp, segment), t);
2913
+ const [x, y] = _chunkVNYRI265cjs.segmentPoint.call(void 0, subpathSegment(sp, segment), t);
2893
2914
  return { x, y };
2894
2915
  }
2895
2916
  function curvatureMoveAnchor(sp, index, q) {
@@ -3150,20 +3171,20 @@ function removeRedundantPoints(sp, tolerance) {
3150
3171
  }
3151
3172
 
3152
3173
  // src/vector/pathCut.ts
3153
- var loopArea = (l) => _chunkGVB7ZPLZcjs.contourSignedArea.call(void 0, l.segs);
3174
+ var loopArea = (l) => _chunkVNYRI265cjs.contourSignedArea.call(void 0, l.segs);
3154
3175
  function loopSample(l) {
3155
3176
  const k = l.chord.findIndex((c) => !c);
3156
- return _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, l.segs[k >= 0 ? k : 0], 0.5);
3177
+ return _chunkVNYRI265cjs.segmentPoint.call(void 0, l.segs[k >= 0 ? k : 0], 0.5);
3157
3178
  }
3158
- var contains2 = (l, p) => _chunkGVB7ZPLZcjs.windingNumber.call(void 0, [l.segs], p) !== 0;
3179
+ var contains2 = (l, p) => _chunkVNYRI265cjs.windingNumber.call(void 0, [l.segs], p) !== 0;
3159
3180
  function groupFaces(loops) {
3160
- const usable = loops.filter((l) => l.segs.length && Math.abs(loopArea(l)) > 1e-12);
3161
- if (!usable.length) return [];
3162
- const largest = usable.reduce((a, b) => Math.abs(loopArea(b)) > Math.abs(loopArea(a)) ? b : a);
3181
+ const usable2 = loops.filter((l) => l.segs.length && Math.abs(loopArea(l)) > 1e-12);
3182
+ if (!usable2.length) return [];
3183
+ const largest = usable2.reduce((a, b) => Math.abs(loopArea(b)) > Math.abs(loopArea(a)) ? b : a);
3163
3184
  const sign = Math.sign(loopArea(largest));
3164
- const outers = usable.filter((l) => Math.sign(loopArea(l)) === sign).sort((a, b) => Math.abs(loopArea(a)) - Math.abs(loopArea(b)));
3185
+ const outers = usable2.filter((l) => Math.sign(loopArea(l)) === sign).sort((a, b) => Math.abs(loopArea(a)) - Math.abs(loopArea(b)));
3165
3186
  const faces = new Map(outers.map((o) => [o, { loops: [o] }]));
3166
- for (const hole of usable.filter((l) => Math.sign(loopArea(l)) !== sign)) {
3187
+ for (const hole of usable2.filter((l) => Math.sign(loopArea(l)) !== sign)) {
3167
3188
  const p = loopSample(hole);
3168
3189
  const parent = outers.find((o) => Math.abs(loopArea(o)) > Math.abs(loopArea(hole)) && contains2(o, p));
3169
3190
  if (parent) faces.get(parent).loops.push(hole);
@@ -3171,12 +3192,12 @@ function groupFaces(loops) {
3171
3192
  return outers.reverse().map((o) => faces.get(o));
3172
3193
  }
3173
3194
  function faceToPath(face) {
3174
- return _chunkGVB7ZPLZcjs.contoursToPath.call(void 0, face.loops.map((l) => ({ segments: l.segs, closed: true })));
3195
+ return _chunkVNYRI265cjs.contoursToPath.call(void 0, face.loops.map((l) => ({ segments: l.segs, closed: true })));
3175
3196
  }
3176
3197
  function facesOf(path, fillRule) {
3177
- const normalized = _chunkGVB7ZPLZcjs.normalizeBezierPath.call(void 0, path, fillRule);
3178
- const loops = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, normalized).map((c) => {
3179
- const segs = _chunkGVB7ZPLZcjs.closeContour.call(void 0, c, true).map((s) => s.slice());
3198
+ const normalized = _chunkVNYRI265cjs.normalizeBezierPath.call(void 0, path, fillRule);
3199
+ const loops = _chunkVNYRI265cjs.pathToContours.call(void 0, normalized).map((c) => {
3200
+ const segs = _chunkVNYRI265cjs.closeContour.call(void 0, c, true).map((s) => s.slice());
3180
3201
  return { segs, chord: segs.map(() => false) };
3181
3202
  });
3182
3203
  return groupFaces(loops);
@@ -3246,7 +3267,7 @@ function lineHits(p, q, seg) {
3246
3267
  const scale = Math.sqrt(len2) * Math.max(1, ...seg.map((pt2) => Math.abs(pt2[0]) + Math.abs(pt2[1])));
3247
3268
  const out = [];
3248
3269
  for (const t of rootsInUnit(...coeffs, scale)) {
3249
- const point = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, t);
3270
+ const point = _chunkVNYRI265cjs.segmentPoint.call(void 0, seg, t);
3250
3271
  const s = ((point[0] - p[0]) * dx + (point[1] - p[1]) * dy) / len2;
3251
3272
  if (s >= -1e-9 && s <= 1 + 1e-9) out.push({ s: Math.min(1, Math.max(0, s)), t, point });
3252
3273
  }
@@ -3259,7 +3280,7 @@ function arc(l, a, b, eps) {
3259
3280
  const segs = [];
3260
3281
  const chord = [];
3261
3282
  const push = (k, t0, t1) => {
3262
- const piece = t0 <= 0 && t1 >= 1 ? l.segs[k].slice() : _chunkGVB7ZPLZcjs.subSegment.call(void 0, l.segs[k], t0, t1);
3283
+ const piece = t0 <= 0 && t1 >= 1 ? l.segs[k].slice() : _chunkVNYRI265cjs.subSegment.call(void 0, l.segs[k], t0, t1);
3263
3284
  if (!degenerate(piece, eps)) {
3264
3285
  segs.push(piece);
3265
3286
  chord.push(l.chord[k]);
@@ -3284,7 +3305,7 @@ function knifePath(path, fillRule, knife) {
3284
3305
  if (pts.length < 2) return null;
3285
3306
  let faces = facesOf(path, fillRule);
3286
3307
  if (!faces.length) return null;
3287
- const b = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, path);
3308
+ const b = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, path);
3288
3309
  const size = b ? Math.max(b.maxX - b.minX, b.maxY - b.minY, 1) : 1;
3289
3310
  const eps = size * 1e-9;
3290
3311
  let cursor = -Infinity;
@@ -3298,7 +3319,7 @@ function knifePath(path, fillRule, knife) {
3298
3319
  const kb = { minX: Math.min(pts[m][0], pts[m + 1][0]), maxX: Math.max(pts[m][0], pts[m + 1][0]), minY: Math.min(pts[m][1], pts[m + 1][1]), maxY: Math.max(pts[m][1], pts[m + 1][1]) };
3299
3320
  face2.loops.forEach(
3300
3321
  (l, li) => l.segs.forEach((seg, si) => {
3301
- const sb = _chunkGVB7ZPLZcjs.segmentBounds.call(void 0, seg);
3322
+ const sb = _chunkVNYRI265cjs.segmentBounds.call(void 0, seg);
3302
3323
  if (sb.maxX < kb.minX - eps || sb.minX > kb.maxX + eps || sb.maxY < kb.minY - eps || sb.minY > kb.maxY + eps) return;
3303
3324
  for (const h of lineHits(pts[m], pts[m + 1], seg)) {
3304
3325
  const s = m + h.s;
@@ -3313,7 +3334,7 @@ function knifePath(path, fillRule, knife) {
3313
3334
  const m = Math.min(pts.length - 2, Math.floor(s));
3314
3335
  const u = s - m;
3315
3336
  const q = [pts[m][0] + (pts[m + 1][0] - pts[m][0]) * u, pts[m][1] + (pts[m + 1][1] - pts[m][1]) * u];
3316
- return _chunkGVB7ZPLZcjs.windingNumber.call(void 0, face2.loops.map((l) => l.segs), q) !== 0;
3337
+ return _chunkVNYRI265cjs.windingNumber.call(void 0, face2.loops.map((l) => l.segs), q) !== 0;
3317
3338
  };
3318
3339
  for (let i = 0; i < unique.length - 1; i++) {
3319
3340
  const from2 = unique[i];
@@ -3373,33 +3394,33 @@ function eraserRegion(points, width) {
3373
3394
  ];
3374
3395
  }
3375
3396
  const line2 = [{ type: "M", x: pts[0][0], y: pts[0][1] }, ...pts.slice(1).map((p) => ({ type: "L", x: p[0], y: p[1] }))];
3376
- return _chunkGVB7ZPLZcjs.outlineStroke.call(void 0, line2, { width, cap: "round", join: "round" });
3397
+ return _chunkVNYRI265cjs.outlineStroke.call(void 0, line2, { width, cap: "round", join: "round" });
3377
3398
  }
3378
3399
  function eraseFromFill(path, fillRule, region) {
3379
- const overlap = _chunkGVB7ZPLZcjs.pathBoolean.call(void 0, "intersection", [{ path, fillRule }, { path: region }]).path;
3380
- if (!_chunkGVB7ZPLZcjs.pathToContours.call(void 0, overlap).some((c) => Math.abs(_chunkGVB7ZPLZcjs.contourSignedArea.call(void 0, _chunkGVB7ZPLZcjs.closeContour.call(void 0, c, true))) > 1e-9)) return null;
3381
- const rest = _chunkGVB7ZPLZcjs.pathBoolean.call(void 0, "difference", [{ path, fillRule }, { path: region }]).path;
3400
+ const overlap = _chunkVNYRI265cjs.pathBoolean.call(void 0, "intersection", [{ path, fillRule }, { path: region }]).path;
3401
+ if (!_chunkVNYRI265cjs.pathToContours.call(void 0, overlap).some((c) => Math.abs(_chunkVNYRI265cjs.contourSignedArea.call(void 0, _chunkVNYRI265cjs.closeContour.call(void 0, c, true))) > 1e-9)) return null;
3402
+ const rest = _chunkVNYRI265cjs.pathBoolean.call(void 0, "difference", [{ path, fillRule }, { path: region }]).path;
3382
3403
  return splitIntoFaces(rest);
3383
3404
  }
3384
3405
  function eraseFromOutline(sp, region) {
3385
- const regionSegs = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, region).flatMap((c) => _chunkGVB7ZPLZcjs.closeContour.call(void 0, c, true));
3406
+ const regionSegs = _chunkVNYRI265cjs.pathToContours.call(void 0, region).flatMap((c) => _chunkVNYRI265cjs.closeContour.call(void 0, c, true));
3386
3407
  if (!regionSegs.length) return null;
3387
- const rb = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, region);
3408
+ const rb = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, region);
3388
3409
  const count = subpathSegmentCount(sp);
3389
3410
  if (!rb || count === 0) return null;
3390
- const removed = (p) => _chunkGVB7ZPLZcjs.pointInBezierPath.call(void 0, region, p, "nonzero");
3411
+ const removed = (p) => _chunkVNYRI265cjs.pointInBezierPath.call(void 0, region, p, "nonzero");
3391
3412
  const runs = [];
3392
3413
  let cur = [];
3393
3414
  let any = false;
3394
3415
  for (let i = 0; i < count; i++) {
3395
3416
  const seg = subpathSegment(sp, i);
3396
- const sb = _chunkGVB7ZPLZcjs.segmentBounds.call(void 0, seg);
3417
+ const sb = _chunkVNYRI265cjs.segmentBounds.call(void 0, seg);
3397
3418
  const ts = [0, 1];
3398
3419
  if (!(sb.maxX < rb.minX || sb.minX > rb.maxX || sb.maxY < rb.minY || sb.minY > rb.maxY)) {
3399
3420
  for (const r of regionSegs) {
3400
- const b = _chunkGVB7ZPLZcjs.segmentBounds.call(void 0, r);
3421
+ const b = _chunkVNYRI265cjs.segmentBounds.call(void 0, r);
3401
3422
  if (b.maxX < sb.minX || b.minX > sb.maxX || b.maxY < sb.minY || b.minY > sb.maxY) continue;
3402
- for (const hit of _chunkGVB7ZPLZcjs.segmentIntersections.call(void 0, seg, r)) if (hit.ta > 1e-9 && hit.ta < 1 - 1e-9) ts.push(hit.ta);
3423
+ for (const hit of _chunkVNYRI265cjs.segmentIntersections.call(void 0, seg, r)) if (hit.ta > 1e-9 && hit.ta < 1 - 1e-9) ts.push(hit.ta);
3403
3424
  }
3404
3425
  }
3405
3426
  ts.sort((a, b) => a - b);
@@ -3407,7 +3428,7 @@ function eraseFromOutline(sp, region) {
3407
3428
  const t0 = ts[k];
3408
3429
  const t1 = ts[k + 1];
3409
3430
  if (t1 - t0 < 1e-9) continue;
3410
- if (removed(_chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, (t0 + t1) / 2))) {
3431
+ if (removed(_chunkVNYRI265cjs.segmentPoint.call(void 0, seg, (t0 + t1) / 2))) {
3411
3432
  any = true;
3412
3433
  if (cur.length) runs.push(cur);
3413
3434
  cur = [];
@@ -3426,7 +3447,7 @@ function eraseFromOutline(sp, region) {
3426
3447
  for (const run of runs) {
3427
3448
  const anchors = [];
3428
3449
  for (const { seg, t0, t1 } of run) {
3429
- const c = _chunkGVB7ZPLZcjs.subSegment.call(void 0, subpathSegment(sp, seg), t0, t1);
3450
+ const c = _chunkVNYRI265cjs.subSegment.call(void 0, subpathSegment(sp, seg), t0, t1);
3430
3451
  const line2 = c.length === 2;
3431
3452
  const start = c[0];
3432
3453
  const end = c[c.length - 1];
@@ -3715,15 +3736,226 @@ function recognizeInkShape(points, options = {}) {
3715
3736
  return roundish && rms < 0.1 ? ellipse() : null;
3716
3737
  }
3717
3738
 
3739
+ // src/vector/builder.ts
3740
+ function vectorPathEntries(doc, roots, options = {}) {
3741
+ const out = [];
3742
+ const visit = (node, parent, inside) => {
3743
+ if (node.visible === false || node.locked && !options.locked) return;
3744
+ const picked = inside || roots === null || roots.includes(node.id);
3745
+ if (node.type === "group") {
3746
+ const m = multiplyMatrices(nodeMatrix(node), parent);
3747
+ for (const c of node.children) visit(c, m, picked);
3748
+ } else if (picked) out.push({ node, parent });
3749
+ };
3750
+ for (const n of doc.nodes) visit(n, IDENTITY_MATRIX, false);
3751
+ return out;
3752
+ }
3753
+ var usable = (sp) => sp.anchors.length > 1;
3754
+ function worldOf(entry, subpaths) {
3755
+ return vectorPathWorldBezier({ ...entry.node, subpaths }, entry.parent);
3756
+ }
3757
+ function subpathEnclosesArea(sp) {
3758
+ const contour = _chunkVNYRI265cjs.pathToContours.call(void 0, subpathsToBezier([{ ...sp, closed: true }]))[0];
3759
+ if (!contour) return false;
3760
+ const segs = _chunkVNYRI265cjs.closeContour.call(void 0, contour, true);
3761
+ const b = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, _chunkVNYRI265cjs.contoursToPath.call(void 0, [{ segments: segs, closed: true }]));
3762
+ if (!b) return false;
3763
+ const w = b.maxX - b.minX;
3764
+ const h = b.maxY - b.minY;
3765
+ return Math.abs(_chunkVNYRI265cjs.contourSignedArea.call(void 0, segs)) > 1e-9 * (w * w + h * h);
3766
+ }
3767
+ var paintKey = (paint) => typeof paint === "string" ? paint.trim().toLowerCase() : JSON.stringify(_nullishCoalesce(paint, () => ( null)));
3768
+ function vectorPathfinderShape(entry, op) {
3769
+ const { node } = entry;
3770
+ const subpaths = node.subpaths.filter(usable);
3771
+ const closed = subpaths.map((s) => ({ ...s, closed: true }));
3772
+ const fillRule = _nullishCoalesce(node.fillRule, () => ( "nonzero"));
3773
+ if (hasPaint(node.fill)) return { path: worldOf(entry, closed), fillRule, key: `fill:${paintKey(node.fill)}`, paint: "fill" };
3774
+ const open = subpaths.length > 0 && subpaths.every((s) => !s.closed);
3775
+ if (op === "divide" && open) return { path: worldOf(entry, subpaths), line: true, paint: "line" };
3776
+ if (hasPaint(node.stroke) && (_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0) {
3777
+ const path = vectorStrokeOutline({ ...node, subpaths }, entry.parent);
3778
+ return { path, fillRule: "nonzero", key: `fill:${paintKey(node.stroke)}`, paint: "stroke" };
3779
+ }
3780
+ return { path: worldOf(entry, closed), fillRule, key: "none", paint: "outline" };
3781
+ }
3782
+ var STROKE_KEYS = [
3783
+ "stroke",
3784
+ "strokeWidth",
3785
+ "strokeLinecap",
3786
+ "strokeLinejoin",
3787
+ "strokeDasharray",
3788
+ "strokeAlign",
3789
+ "startArrow",
3790
+ "endArrow",
3791
+ "arrowAlign",
3792
+ "startArrowScale",
3793
+ "endArrowScale",
3794
+ "strokeWidthProfile"
3795
+ ];
3796
+ function vectorResultStyle(node, paint, edge = false) {
3797
+ const { id: _id, subpaths: _s, transform: _t, ...rest } = node;
3798
+ const base = { ...rest, fillRule: "nonzero" };
3799
+ if (edge) {
3800
+ for (const k of STROKE_KEYS) delete base[k];
3801
+ const stroke = paint === "stroke" || !hasPaint(node.fill) ? node.stroke : node.fill;
3802
+ return { ...base, fill: null, stroke: _nullishCoalesce(stroke, () => ( "#000000")), strokeWidth: _nullishCoalesce(node.strokeWidth, () => ( 1)) };
3803
+ }
3804
+ if (paint === "stroke") {
3805
+ for (const k of STROKE_KEYS) delete base[k];
3806
+ return { ...base, fill: _nullishCoalesce(node.stroke, () => ( null)), stroke: null };
3807
+ }
3808
+ return base;
3809
+ }
3810
+ function vectorShapeBuilderMap(entries) {
3811
+ const lines = [];
3812
+ const inputs = entries.map((entry) => {
3813
+ const filled = hasPaint(entry.node.fill);
3814
+ const subpaths = entry.node.subpaths.filter(usable).map((sp) => !sp.closed && filled && subpathEnclosesArea(sp) ? { ...sp, closed: true } : sp);
3815
+ lines.push(!subpaths.some((s) => s.closed));
3816
+ return { path: worldOf(entry, subpaths), fillRule: _nullishCoalesce(entry.node.fillRule, () => ( "nonzero")) };
3817
+ });
3818
+ const map = _chunkVNYRI265cjs.PlanarMap.build(inputs);
3819
+ if (!map) return null;
3820
+ let chains = null;
3821
+ const runs = (line2) => (chains ??= map.chains()).filter((c) => lines[c.source] === line2 && !(line2 && c.closed)).map((c) => {
3822
+ const path = _chunkVNYRI265cjs.contoursToPath.call(void 0, [{ segments: c.segments, closed: c.closed }]);
3823
+ return { path, segments: c.segments, closed: c.closed, source: c.source, bounds: _chunkVNYRI265cjs.bezierPathBounds.call(void 0, path) };
3824
+ });
3825
+ const pieces = lines.some(Boolean) ? runs(true) : [];
3826
+ let edges = null;
3827
+ let size = 0;
3828
+ for (const input of inputs) {
3829
+ const b = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, input.path);
3830
+ if (b) size = Math.max(size, b.maxX - b.minX, b.maxY - b.minY);
3831
+ }
3832
+ return {
3833
+ entries: [...entries],
3834
+ map,
3835
+ lines,
3836
+ pieces,
3837
+ get edges() {
3838
+ return edges ??= runs(false);
3839
+ },
3840
+ tolerance: 0.2 * Math.max(size / 2e3, 0.25)
3841
+ };
3842
+ }
3843
+ function pieceNear(pieces, p, tol) {
3844
+ const point = [p.x, p.y];
3845
+ let best = null;
3846
+ pieces.forEach((piece, index) => {
3847
+ const b = piece.bounds;
3848
+ if (p.x < b.minX - tol || p.x > b.maxX + tol || p.y < b.minY - tol || p.y > b.maxY + tol) return;
3849
+ const d = _chunkVNYRI265cjs.distanceToBezierPath.call(void 0, piece.path, point);
3850
+ if (d <= tol && (!best || d < best.d)) best = { index, d };
3851
+ });
3852
+ return best;
3853
+ }
3854
+ function vectorShapeBuilderHit(m, p, lineTolerance = null) {
3855
+ if (lineTolerance !== null && lineTolerance > 0) {
3856
+ const line2 = pieceNear(m.pieces, p, lineTolerance);
3857
+ const edge = pieceNear(m.edges, p, lineTolerance);
3858
+ if (edge && (!line2 || edge.d < line2.d)) return { edge: edge.index };
3859
+ if (line2) return { line: line2.index };
3860
+ }
3861
+ const face = m.map.faceAt([p.x, p.y]);
3862
+ return face >= 0 ? { face } : null;
3863
+ }
3864
+ function samplePolyline(points, step) {
3865
+ const out = [];
3866
+ const s = Math.max(step, 1e-3);
3867
+ points.forEach((p, i) => {
3868
+ if (i > 0) {
3869
+ const a = points[i - 1];
3870
+ const n = Math.min(4e3, Math.ceil(Math.hypot(p.x - a.x, p.y - a.y) / s));
3871
+ for (let k = 1; k < n; k++) out.push({ x: a.x + (p.x - a.x) * k / n, y: a.y + (p.y - a.y) * k / n });
3872
+ }
3873
+ out.push(p);
3874
+ });
3875
+ return out;
3876
+ }
3877
+ function addBuilderHit(touched, hit) {
3878
+ if (!hit) return false;
3879
+ const [list, i] = "face" in hit ? [touched.faces, hit.face] : "line" in hit ? [touched.lines, hit.line] : [touched.edges, hit.edge];
3880
+ if (list.includes(i)) return false;
3881
+ list.push(i);
3882
+ return true;
3883
+ }
3884
+ function sides(m, piece) {
3885
+ const seg = piece.segments[Math.floor(piece.segments.length / 2)];
3886
+ const mid = _chunkVNYRI265cjs.segmentPoint.call(void 0, seg, 0.5);
3887
+ const t = _chunkVNYRI265cjs.segmentTangent.call(void 0, seg, 0.5);
3888
+ const chord = Math.hypot(seg[seg.length - 1][0] - seg[0][0], seg[seg.length - 1][1] - seg[0][1]);
3889
+ const off = Math.max(1e-6, Math.min(0.05, 0.05 * chord));
3890
+ return [m.map.faceAt([mid[0] - t[1] * off, mid[1] + t[0] * off]), m.map.faceAt([mid[0] + t[1] * off, mid[1] - t[0] * off])];
3891
+ }
3892
+ function vectorBuilderErasedEdges(m, touched) {
3893
+ if (!touched.edges.length) return [];
3894
+ const faces = new Set(touched.faces);
3895
+ return touched.edges.filter((k) => m.edges[k] && !sides(m, m.edges[k]).some((f) => f >= 0 && faces.has(f)));
3896
+ }
3897
+ function planShapeBuilder(m, touched, erase) {
3898
+ const replace = /* @__PURE__ */ new Map();
3899
+ const picked = new Set(touched.faces);
3900
+ const faces = m.map.faces;
3901
+ const sourcesOf = faces.map((_, i) => m.map.faceSources(i));
3902
+ const cuts = erase ? vectorBuilderErasedEdges(m, touched).map((k) => m.edges[k]) : [];
3903
+ m.entries.forEach((entry, i) => {
3904
+ if (m.lines[i]) {
3905
+ const own = m.pieces.flatMap((piece, k) => piece.source === i ? [k] : []);
3906
+ const keep = own.filter((k) => !touched.lines.includes(k) && !sides(m, m.pieces[k]).every((f) => f >= 0 && picked.has(f)));
3907
+ if (keep.length === own.length) return;
3908
+ replace.set(i, keep.length ? { kind: "pieces", paths: keep.map((k) => m.pieces[k].path) } : null);
3909
+ return;
3910
+ }
3911
+ const inUnion = touched.faces.some((f) => sourcesOf[f].includes(i));
3912
+ if (!inUnion && !cuts.length) return;
3913
+ let rest;
3914
+ if (inUnion) {
3915
+ const kept = faces.flatMap((_, f) => sourcesOf[f].includes(i) && !picked.has(f) ? [f] : []);
3916
+ rest = kept.length ? m.map.merge(kept) : [];
3917
+ } else rest = worldOf(entry, entry.node.subpaths.filter(usable));
3918
+ const fillCloses = hasPaint(entry.node.fill);
3919
+ let cut = false;
3920
+ for (const piece of cuts) {
3921
+ const r = rest.length ? _chunkVNYRI265cjs.cutOutPiece.call(void 0, rest, piece, fillCloses, m.tolerance) : null;
3922
+ if (r) {
3923
+ rest = r;
3924
+ cut = true;
3925
+ }
3926
+ }
3927
+ if (!inUnion && !cut) return;
3928
+ replace.set(i, rest.length ? { kind: inUnion ? "fill" : "outline", path: rest } : null);
3929
+ });
3930
+ let merged = null;
3931
+ if (!erase && touched.faces.length) {
3932
+ const path = m.map.merge(touched.faces);
3933
+ const covered = touched.faces.map((f) => sourcesOf[f]).find((s) => s.length);
3934
+ const lastShape = m.lines.lastIndexOf(false);
3935
+ const style = covered ? covered[covered.length - 1] : lastShape >= 0 ? lastShape : m.entries.length - 1;
3936
+ if (path.length) merged = { path, style, currentFill: !covered };
3937
+ }
3938
+ return { replace, merged };
3939
+ }
3940
+ function vectorFillMap(doc, gap = 0) {
3941
+ const entries = vectorPathEntries(doc, null, { locked: true });
3942
+ return _chunkVNYRI265cjs.PlanarMap.build(
3943
+ entries.map((e) => ({ path: worldOf(e, e.node.subpaths.filter(usable)), fills: false })),
3944
+ { gap, maxSegments: 2e4 }
3945
+ );
3946
+ }
3947
+
3718
3948
  // src/vector/controller.ts
3719
3949
  var DEFAULT_VECTOR_SNAP = { grid: 0, objects: true, guides: true, threshold: 5, angles: VECTOR_CONSTRUCTION_ANGLES };
3950
+ var VECTOR_FILL_GAP = 6;
3720
3951
  var DEFAULT_VECTOR_PATH_EDIT = {
3721
3952
  keepShapeOnDelete: true,
3722
3953
  curvatureMoves: false,
3723
3954
  pencilSmoothing: 0,
3724
3955
  recognizeShapes: false,
3725
3956
  eraserSize: 10,
3726
- pencilPressure: "pen"
3957
+ pencilPressure: "pen",
3958
+ fillGap: 0
3727
3959
  };
3728
3960
  var VECTOR_PENCIL_STRING_PX = 100;
3729
3961
  var VECTOR_STYLE_KEYS = [
@@ -3962,9 +4194,27 @@ var TOOL_LABELS = {
3962
4194
  scissors: "Scissors",
3963
4195
  knife: "Knife",
3964
4196
  eraser: "Eraser",
3965
- width: "Width"
4197
+ width: "Width",
4198
+ shapeBuilder: "Shape Builder",
4199
+ paintBucket: "Paint Bucket"
4200
+ };
4201
+ var TOOL_KEYS = {
4202
+ v: "select",
4203
+ a: "direct",
4204
+ p: "pen",
4205
+ n: "pencil",
4206
+ r: "rect",
4207
+ o: "ellipse",
4208
+ y: "polygon",
4209
+ s: "star",
4210
+ l: "line",
4211
+ c: "scissors",
4212
+ k: "knife",
4213
+ e: "eraser",
4214
+ w: "width",
4215
+ m: "shapeBuilder",
4216
+ b: "paintBucket"
3966
4217
  };
3967
- var TOOL_KEYS = { v: "select", a: "direct", p: "pen", n: "pencil", r: "rect", o: "ellipse", y: "polygon", s: "star", l: "line", c: "scissors", k: "knife", e: "eraser", w: "width" };
3968
4218
  function vectorToolLabel(tool) {
3969
4219
  return TOOL_LABELS[tool];
3970
4220
  }
@@ -3981,7 +4231,9 @@ var VECTOR_TOOL_SHORTCUTS = {
3981
4231
  scissors: "C",
3982
4232
  knife: "K",
3983
4233
  eraser: "E",
3984
- width: "W"
4234
+ width: "W",
4235
+ shapeBuilder: "M",
4236
+ paintBucket: "B"
3985
4237
  };
3986
4238
  var VECTOR_TOOL_GLYPHS = {
3987
4239
  select: "\u2196",
@@ -3996,7 +4248,9 @@ var VECTOR_TOOL_GLYPHS = {
3996
4248
  scissors: "\u2702",
3997
4249
  knife: "\u27CB",
3998
4250
  eraser: "\u232B",
3999
- width: "\u21F9"
4251
+ width: "\u21F9",
4252
+ shapeBuilder: "\u2295",
4253
+ paintBucket: "\u25CD"
4000
4254
  };
4001
4255
  var SHAPE_TOOLS = /* @__PURE__ */ new Set(["rect", "ellipse", "polygon", "star", "line"]);
4002
4256
  var BOOLEAN_OPS = {
@@ -4006,6 +4260,14 @@ var BOOLEAN_OPS = {
4006
4260
  exclude: "xor"
4007
4261
  };
4008
4262
  var BOOLEAN_LABELS = { union: "Union", subtract: "Subtract", intersect: "Intersect", exclude: "Exclude" };
4263
+ var VECTOR_PATHFINDER_LABELS = {
4264
+ divide: "Divide",
4265
+ trim: "Trim",
4266
+ merge: "Merge",
4267
+ crop: "Crop",
4268
+ outline: "Outline",
4269
+ minusBack: "Minus Back"
4270
+ };
4009
4271
  function mapTree(nodes, fn) {
4010
4272
  let changed = false;
4011
4273
  const out = [];
@@ -4070,16 +4332,23 @@ var VectorEditorController = (_class3 = class {
4070
4332
  __init20() {this.hoverTargets = null}
4071
4333
  __init21() {this.spaceHeld = false}
4072
4334
  __init22() {this.clipboard = null}
4335
+ /** Shape Builder map of the selection, kept while the document and the selection stay the same. */
4336
+ __init23() {this.builderCache = null}
4337
+ /** Paint bucket map of the visible outlines. */
4338
+ __init24() {this.fillCache = null}
4339
+ __init25() {this.builderPreview = null}
4340
+ /** What the highlight shows, to skip notifying when the pointer stays over the same face. */
4341
+ __init26() {this.builderHoverKey = null}
4073
4342
 
4074
4343
 
4075
- __init23() {this.listeners = /* @__PURE__ */ new Set()}
4076
- __init24() {this.cleanups = []}
4077
- __init25() {this.applying = false}
4344
+ __init27() {this.listeners = /* @__PURE__ */ new Set()}
4345
+ __init28() {this.cleanups = []}
4346
+ __init29() {this.applying = false}
4078
4347
  /** Set while a commit records a change that was already applied, so `restore` still reports it. */
4079
- __init26() {this.committing = false}
4080
- __init27() {this.revision = 0}
4348
+ __init30() {this.committing = false}
4349
+ __init31() {this.revision = 0}
4081
4350
 
4082
- constructor(options = {}) {;_class3.prototype.__init9.call(this);_class3.prototype.__init10.call(this);_class3.prototype.__init11.call(this);_class3.prototype.__init12.call(this);_class3.prototype.__init13.call(this);_class3.prototype.__init14.call(this);_class3.prototype.__init15.call(this);_class3.prototype.__init16.call(this);_class3.prototype.__init17.call(this);_class3.prototype.__init18.call(this);_class3.prototype.__init19.call(this);_class3.prototype.__init20.call(this);_class3.prototype.__init21.call(this);_class3.prototype.__init22.call(this);_class3.prototype.__init23.call(this);_class3.prototype.__init24.call(this);_class3.prototype.__init25.call(this);_class3.prototype.__init26.call(this);_class3.prototype.__init27.call(this);_class3.prototype.__init28.call(this);_class3.prototype.__init29.call(this);
4351
+ constructor(options = {}) {;_class3.prototype.__init9.call(this);_class3.prototype.__init10.call(this);_class3.prototype.__init11.call(this);_class3.prototype.__init12.call(this);_class3.prototype.__init13.call(this);_class3.prototype.__init14.call(this);_class3.prototype.__init15.call(this);_class3.prototype.__init16.call(this);_class3.prototype.__init17.call(this);_class3.prototype.__init18.call(this);_class3.prototype.__init19.call(this);_class3.prototype.__init20.call(this);_class3.prototype.__init21.call(this);_class3.prototype.__init22.call(this);_class3.prototype.__init23.call(this);_class3.prototype.__init24.call(this);_class3.prototype.__init25.call(this);_class3.prototype.__init26.call(this);_class3.prototype.__init27.call(this);_class3.prototype.__init28.call(this);_class3.prototype.__init29.call(this);_class3.prototype.__init30.call(this);_class3.prototype.__init31.call(this);_class3.prototype.__init32.call(this);_class3.prototype.__init33.call(this);
4083
4352
  this.history = _nullishCoalesce(options.history, () => ( new (0, _chunkQKLRAA4Tcjs.HistoryManager)()));
4084
4353
  this.doc = options.document ? cloneVectorDocument(options.document) : { width: 800, height: 600, nodes: [] };
4085
4354
  this.tool = _nullishCoalesce(options.tool, () => ( "select"));
@@ -4108,9 +4377,9 @@ var VectorEditorController = (_class3 = class {
4108
4377
  // State
4109
4378
  // -------------------------------------------------------------------------
4110
4379
  /** The current snapshot (stable until the next change). */
4111
- __init28() {this.getState = () => this.state}
4380
+ __init32() {this.getState = () => this.state}
4112
4381
  /** Calls `listener` after every change. Returns an unsubscribe function. */
4113
- __init29() {this.subscribe = (listener) => {
4382
+ __init33() {this.subscribe = (listener) => {
4114
4383
  this.listeners.add(listener);
4115
4384
  return () => {
4116
4385
  this.listeners.delete(listener);
@@ -4144,6 +4413,7 @@ var VectorEditorController = (_class3 = class {
4144
4413
  interaction: this.interaction,
4145
4414
  pen: this.pen,
4146
4415
  pointer: this.pointer,
4416
+ builder: this.builderPreview,
4147
4417
  canUndo: h.canUndo,
4148
4418
  canRedo: h.canRedo,
4149
4419
  undoLabel: h.undoName,
@@ -4202,6 +4472,11 @@ var VectorEditorController = (_class3 = class {
4202
4472
  if (_optionalChain([this, 'access', _103 => _103.drag, 'optionalAccess', _104 => _104.kind]) === "width") return this.drag.mode === "move" ? "grabbing" : "ew-resize";
4203
4473
  if (_optionalChain([h, 'optionalAccess', _105 => _105.widthPoint])) return h.widthPoint.part === "center" ? "grab" : "ew-resize";
4204
4474
  return _optionalChain([h, 'optionalAccess', _106 => _106.strokeSpot]) ? "copy" : "default";
4475
+ case "shapeBuilder":
4476
+ if (!_optionalChain([this, 'access', _107 => _107.builderPreview, 'optionalAccess', _108 => _108.faces, 'access', _109 => _109.length]) && !_optionalChain([this, 'access', _110 => _110.builderPreview, 'optionalAccess', _111 => _111.lines, 'access', _112 => _112.length])) return "crosshair";
4477
+ return this.builderPreview.mode === "erase" ? "not-allowed" : "cell";
4478
+ case "paintBucket":
4479
+ return this.builderPreview ? "cell" : "crosshair";
4205
4480
  default:
4206
4481
  return "crosshair";
4207
4482
  }
@@ -4221,7 +4496,7 @@ var VectorEditorController = (_class3 = class {
4221
4496
  this.selection = s.selection.filter((id) => this.getNode(id));
4222
4497
  this.anchors = s.anchors.filter((r) => getAnchor(this.doc, r));
4223
4498
  this.editingId = s.editingId && this.getNode(s.editingId) ? s.editingId : null;
4224
- this.pen = s.pen && _optionalChain([this, 'access', _107 => _107.getNode, 'call', _108 => _108(s.pen.nodeId), 'optionalAccess', _109 => _109.subpaths, 'optionalAccess', _110 => _110[s.pen.subpath]]) ? s.pen : null;
4499
+ this.pen = s.pen && _optionalChain([this, 'access', _113 => _113.getNode, 'call', _114 => _114(s.pen.nodeId), 'optionalAccess', _115 => _115.subpaths, 'optionalAccess', _116 => _116[s.pen.subpath]]) ? s.pen : null;
4225
4500
  } finally {
4226
4501
  this.applying = false;
4227
4502
  }
@@ -4328,6 +4603,8 @@ var VectorEditorController = (_class3 = class {
4328
4603
  this.hover = null;
4329
4604
  this.guides = null;
4330
4605
  this.widthPoint = null;
4606
+ this.builderPreview = null;
4607
+ this.builderHoverKey = null;
4331
4608
  if (tool !== "direct") {
4332
4609
  this.anchors = [];
4333
4610
  this.editingId = null;
@@ -4386,7 +4663,7 @@ var VectorEditorController = (_class3 = class {
4386
4663
  if (res.kind) {
4387
4664
  this.snappedToObject = true;
4388
4665
  this.setGuides(res);
4389
- return _optionalChain([leave, 'optionalAccess', _111 => _111.constrain]) ? res.point : { x: res.x ? res.point.x : this.gridValue(res.point.x), y: res.y ? res.point.y : this.gridValue(res.point.y) };
4666
+ return _optionalChain([leave, 'optionalAccess', _117 => _117.constrain]) ? res.point : { x: res.x ? res.point.x : this.gridValue(res.point.x), y: res.y ? res.point.y : this.gridValue(res.point.y) };
4390
4667
  }
4391
4668
  }
4392
4669
  this.setGuides(null);
@@ -4404,14 +4681,14 @@ var VectorEditorController = (_class3 = class {
4404
4681
  /** Where the pointer at `p` would place a point with the pen or a shape tool (and the guides showing why). */
4405
4682
  hoverSnap(p, input) {
4406
4683
  if (this.tool === "pen") {
4407
- const sp = this.pen ? _optionalChain([this, 'access', _112 => _112.getNode, 'call', _113 => _113(this.pen.nodeId), 'optionalAccess', _114 => _114.subpaths, 'access', _115 => _115[this.pen.subpath]]) : void 0;
4408
- if (this.pen && sp && _optionalChain([this, 'access', _116 => _116.hover, 'optionalAccess', _117 => _117.anchor])) {
4684
+ const sp = this.pen ? _optionalChain([this, 'access', _118 => _118.getNode, 'call', _119 => _119(this.pen.nodeId), 'optionalAccess', _120 => _120.subpaths, 'access', _121 => _121[this.pen.subpath]]) : void 0;
4685
+ if (this.pen && sp && _optionalChain([this, 'access', _122 => _122.hover, 'optionalAccess', _123 => _123.anchor])) {
4409
4686
  this.setGuides(null);
4410
4687
  return p;
4411
4688
  }
4412
4689
  const last = this.pen && sp ? getAnchorWorld(this.doc, { nodeId: this.pen.nodeId, subpath: this.pen.subpath, index: sp.anchors.length - 1 }) : void 0;
4413
4690
  const leave = last ? { at: { x: last.x, y: last.y }, constrain: input.shift ? "angle" : null } : null;
4414
- return this.snapDrawn(p, leave, input, () => this.drawingTargets(_nullishCoalesce(_optionalChain([this, 'access', _118 => _118.pen, 'optionalAccess', _119 => _119.nodeId]), () => ( null))));
4691
+ return this.snapDrawn(p, leave, input, () => this.drawingTargets(_nullishCoalesce(_optionalChain([this, 'access', _124 => _124.pen, 'optionalAccess', _125 => _125.nodeId]), () => ( null))));
4415
4692
  }
4416
4693
  if (SHAPE_TOOLS.has(this.tool)) return this.snapDrawn(p, null, input, () => this.drawingTargets(null));
4417
4694
  this.setGuides(null);
@@ -4559,7 +4836,7 @@ var VectorEditorController = (_class3 = class {
4559
4836
  if (d.fillRule) out.fillRule = d.fillRule;
4560
4837
  if (d.strokeAlign && d.strokeAlign !== "center") out.strokeAlign = d.strokeAlign;
4561
4838
  for (const key of ["startArrow", "endArrow", "arrowAlign", "startArrowScale", "endArrowScale"]) if (d[key]) out[key] = d[key];
4562
- if (_optionalChain([d, 'access', _120 => _120.strokeWidthProfile, 'optionalAccess', _121 => _121.length])) out.strokeWidthProfile = d.strokeWidthProfile.map((p) => ({ ...p }));
4839
+ if (_optionalChain([d, 'access', _126 => _126.strokeWidthProfile, 'optionalAccess', _127 => _127.length])) out.strokeWidthProfile = d.strokeWidthProfile.map((p) => ({ ...p }));
4563
4840
  return out;
4564
4841
  }
4565
4842
  /** Merges `patch` into a node (paths take style and geometry; groups name / visibility / opacity). */
@@ -4607,7 +4884,7 @@ var VectorEditorController = (_class3 = class {
4607
4884
  /** Removes one width point of a path's profile (the width tool's Delete). */
4608
4885
  removeWidthPoint(ref) {
4609
4886
  const node = this.getNode(ref.nodeId);
4610
- if (_optionalChain([node, 'optionalAccess', _122 => _122.type]) !== "path" || !_optionalChain([node, 'access', _123 => _123.strokeWidthProfile, 'optionalAccess', _124 => _124[ref.index]])) return { ok: false, message: "There is no such width point." };
4887
+ if (_optionalChain([node, 'optionalAccess', _128 => _128.type]) !== "path" || !_optionalChain([node, 'access', _129 => _129.strokeWidthProfile, 'optionalAccess', _130 => _130[ref.index]])) return { ok: false, message: "There is no such width point." };
4611
4888
  const rest = removeWidthPoints(sanitizeWidthProfile(node.strokeWidthProfile), [ref.index]);
4612
4889
  this.widthPoint = null;
4613
4890
  this.change("Delete Width Point", () => this.replaceNode(node.id, withStyle(node, { strokeWidthProfile: rest.length ? rest : null })));
@@ -4632,7 +4909,7 @@ var VectorEditorController = (_class3 = class {
4632
4909
  const refs = this.cornerTargets(options);
4633
4910
  if (!refs.length) return { ok: false, message: "Nothing is selected." };
4634
4911
  this.change("Corner Kind", () => {
4635
- this.doc = this.updateAnchors(this.doc, refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access', _125 => _125.corner, 'optionalAccess', _126 => _126.radius]), () => ( 0)), kind));
4912
+ this.doc = this.updateAnchors(this.doc, refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access', _131 => _131.corner, 'optionalAccess', _132 => _132.radius]), () => ( 0)), kind));
4636
4913
  });
4637
4914
  return { ok: true };
4638
4915
  }
@@ -4771,10 +5048,10 @@ var VectorEditorController = (_class3 = class {
4771
5048
  return this.selection.filter((id) => {
4772
5049
  let covered = false;
4773
5050
  const loc = locateVectorNode(this.doc.nodes, id);
4774
- let parent = _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _127 => _127.parent]), () => ( null));
5051
+ let parent = _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _133 => _133.parent]), () => ( null));
4775
5052
  while (parent) {
4776
5053
  if (this.selection.includes(parent.id)) covered = true;
4777
- parent = _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _128 => _128(this.doc.nodes, parent.id), 'optionalAccess', _129 => _129.parent]), () => ( null));
5054
+ parent = _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _134 => _134(this.doc.nodes, parent.id), 'optionalAccess', _135 => _135.parent]), () => ( null));
4778
5055
  }
4779
5056
  return !covered;
4780
5057
  });
@@ -4957,8 +5234,8 @@ var VectorEditorController = (_class3 = class {
4957
5234
  if (!ids.length) return null;
4958
5235
  const locs = ids.map((id2) => locateVectorNode(this.doc.nodes, id2));
4959
5236
  if (locs.some((l) => !l)) return null;
4960
- const parent = _nullishCoalesce(_optionalChain([locs, 'access', _130 => _130[0], 'access', _131 => _131.parent, 'optionalAccess', _132 => _132.id]), () => ( null));
4961
- if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _133 => _133.parent, 'optionalAccess', _134 => _134.id]), () => ( null))) !== parent)) return null;
5237
+ const parent = _nullishCoalesce(_optionalChain([locs, 'access', _136 => _136[0], 'access', _137 => _137.parent, 'optionalAccess', _138 => _138.id]), () => ( null));
5238
+ if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _139 => _139.parent, 'optionalAccess', _140 => _140.id]), () => ( null))) !== parent)) return null;
4962
5239
  const id = this.newId();
4963
5240
  this.change("Group", () => {
4964
5241
  const set = new Set(ids);
@@ -4981,7 +5258,7 @@ var VectorEditorController = (_class3 = class {
4981
5258
  }
4982
5259
  /** Replaces selected groups with their children. */
4983
5260
  ungroup(options = {}) {
4984
- const groups = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _135 => _135.type]) === "group");
5261
+ const groups = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _141 => _141.type]) === "group");
4985
5262
  if (!groups.length) return { ok: false, message: "Select a group to ungroup." };
4986
5263
  const set = new Set(groups.map((g) => g.id));
4987
5264
  this.change("Ungroup", () => {
@@ -5041,7 +5318,7 @@ var VectorEditorController = (_class3 = class {
5041
5318
  });
5042
5319
  const paths = [...new Set(order)].map((id2) => this.getNode(id2));
5043
5320
  if (paths.length < 2) return null;
5044
- const result = _chunkGVB7ZPLZcjs.pathBoolean.call(void 0,
5321
+ const result = _chunkVNYRI265cjs.pathBoolean.call(void 0,
5045
5322
  BOOLEAN_OPS[op],
5046
5323
  paths.map((p) => ({
5047
5324
  path: vectorPathWorldBezier(
@@ -5091,11 +5368,11 @@ var VectorEditorController = (_class3 = class {
5091
5368
  /** A document-space path mapped into the parent space of node `id`. */
5092
5369
  intoParentSpace(id, path) {
5093
5370
  const parent = _nullishCoalesce(vectorParentMatrix(this.doc.nodes, id), () => ( IDENTITY_MATRIX));
5094
- return isRoot(parent) ? path : _chunkGVB7ZPLZcjs.transformBezierPath.call(void 0, path, invertMatrix(parent));
5371
+ return isRoot(parent) ? path : _chunkVNYRI265cjs.transformBezierPath.call(void 0, path, invertMatrix(parent));
5095
5372
  }
5096
5373
  /** Splits selected compound paths into one path per subpath. */
5097
5374
  breakApart(options = {}) {
5098
- const paths = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _136 => _136.type]) === "path" && n.subpaths.length > 1);
5375
+ const paths = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _142 => _142.type]) === "path" && n.subpaths.length > 1);
5099
5376
  if (!paths.length) return { ok: false, message: "Select a compound path to break apart." };
5100
5377
  const created = [];
5101
5378
  const set = new Set(paths.map((p) => p.id));
@@ -5115,6 +5392,255 @@ var VectorEditorController = (_class3 = class {
5115
5392
  return { ok: true };
5116
5393
  }
5117
5394
  // -------------------------------------------------------------------------
5395
+ // Pathfinder, Shape Builder and paint bucket
5396
+ // -------------------------------------------------------------------------
5397
+ /**
5398
+ * Pathfinder: Divide, Trim, Merge, Crop, Outline or Minus Back over the selected (or given)
5399
+ * paths, in document space (rotated nodes and groups included, live corners cut). Unfilled
5400
+ * stroked paths take part as the area their stroke paints (Divide: open ones cut instead).
5401
+ * The results replace the operands at the place of the top-most one, grouped when there are
5402
+ * several; each keeps the style of the operand whose area it is. Returns the new path ids,
5403
+ * or an empty list when nothing came out.
5404
+ */
5405
+ pathfinder(op, options = {}) {
5406
+ const roots = _nullishCoalesce(options.ids, () => ( this.selectedRoots()));
5407
+ const entries = vectorPathEntries(this.doc, roots);
5408
+ if (entries.length < (op === "divide" || op === "outline" ? 1 : 2)) return [];
5409
+ const shapes = entries.map((e) => vectorPathfinderShape(e, op));
5410
+ const result = _chunkVNYRI265cjs.pathfinder.call(void 0, op, shapes);
5411
+ if (result.error || !result.pieces.length) return [];
5412
+ const last = entries[entries.length - 1].node.id;
5413
+ const topRoot = _nullishCoalesce([...roots].reverse().find((r) => {
5414
+ const n = this.getNode(r);
5415
+ return !!n && !!findVectorNode([n], last);
5416
+ }), () => ( last));
5417
+ const nodes = [];
5418
+ for (const piece of result.pieces) {
5419
+ const subpaths = bezierToSubpaths(this.intoParentSpace(topRoot, piece.path)).map((sp) => piece.open ? { ...sp, closed: false } : sp);
5420
+ if (!subpaths.length) continue;
5421
+ const source = entries[piece.source].node;
5422
+ const style = vectorResultStyle(source, shapes[piece.source].paint, op === "outline");
5423
+ nodes.push({ ...style, type: "path", id: this.newId(), name: _nullishCoalesce(source.name, () => ( "Path")), subpaths });
5424
+ }
5425
+ if (!nodes.length) return [];
5426
+ const label = VECTOR_PATHFINDER_LABELS[op];
5427
+ const container = nodes.length > 1 ? { id: this.newId(), type: "group", name: label, children: nodes } : nodes[0];
5428
+ const drop = /* @__PURE__ */ new Set([...entries.map((e) => e.node.id), ...roots]);
5429
+ this.change(label, () => {
5430
+ this.setDoc(mapTree(this.doc.nodes, (n) => n.id === topRoot ? container : drop.has(n.id) ? null : n));
5431
+ this.selection = [container.id];
5432
+ this.anchors = [];
5433
+ this.editingId = null;
5434
+ });
5435
+ return nodes.map((n) => n.id);
5436
+ }
5437
+ /** The Shape Builder map of the selected (or given) paths, cached per document and selection. */
5438
+ shapeBuilderMap(ids) {
5439
+ const roots = _nullishCoalesce(ids, () => ( this.selectedRoots()));
5440
+ const key = roots.join("\0");
5441
+ if (_optionalChain([this, 'access', _143 => _143.builderCache, 'optionalAccess', _144 => _144.doc]) === this.doc && this.builderCache.key === key) return this.builderCache.map;
5442
+ const entries = roots.length ? vectorPathEntries(this.doc, roots) : [];
5443
+ const map = entries.length ? vectorShapeBuilderMap(entries) : null;
5444
+ this.builderCache = { doc: this.doc, key, map };
5445
+ return map;
5446
+ }
5447
+ /** The faces the Shape Builder offers for the selected (or given) paths (document units). */
5448
+ getShapeBuilderFaces(options = {}) {
5449
+ const m = this.shapeBuilderMap(options.ids);
5450
+ if (!m) return [];
5451
+ return m.map.faces.map((f, index) => {
5452
+ const p = m.map.faceInterior(index);
5453
+ return {
5454
+ index,
5455
+ d: _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, f.path, { precision: 3 }),
5456
+ area: f.area,
5457
+ sources: m.map.faceSources(index).map((i) => m.entries[i].node.id),
5458
+ point: p ? { x: p[0], y: p[1] } : null
5459
+ };
5460
+ });
5461
+ }
5462
+ /** Pick distance of the Shape Builder's erase for line pieces (document units). */
5463
+ builderLineTolerance() {
5464
+ return Math.max(this.hitRadius, 4) / this.viewport.zoom;
5465
+ }
5466
+ /**
5467
+ * Shape Builder gesture along `points` (document units; one point is a click) over the faces
5468
+ * the selected (or given) paths make. Merges the faces touched into one shape styled like the
5469
+ * top-most shape over the first face (the current fill for a face only outlines enclose);
5470
+ * with `erase` deletes them, the pieces of unfilled open paths and the edges of other outlines
5471
+ * (cut where paths meet) within `tolerance`: a deleted edge opens a closed subpath there,
5472
+ * splits an open one or takes a subpath it runs all the way round, and edges bounding a face
5473
+ * deleted in the same gesture go with the face. Every shape covering a touched face loses
5474
+ * that area; paths keep their own transforms. One undo step.
5475
+ */
5476
+ shapeBuilder(points, options = {}) {
5477
+ const none = (message) => ({ ok: false, message, merged: null, faces: 0, lines: 0, edges: 0 });
5478
+ if (!points.length || !points.every((p) => Number.isFinite(p.x) && Number.isFinite(p.y))) return none("Give the points of the gesture.");
5479
+ const m = this.shapeBuilderMap(options.ids);
5480
+ if (!m) return none("Select paths that make faces.");
5481
+ const erase = !!options.erase;
5482
+ const tol = erase ? _nullishCoalesce(options.tolerance, () => ( this.builderLineTolerance())) : null;
5483
+ const touched = { faces: [], lines: [], edges: [] };
5484
+ const size = m.map.faces.reduce((s, f) => Math.max(s, f.bounds.maxX - f.bounds.minX, f.bounds.maxY - f.bounds.minY), 1);
5485
+ for (const p of samplePolyline(points, Math.max(size / 2e3, 0.25 / this.viewport.zoom))) addBuilderHit(touched, vectorShapeBuilderHit(m, p, tol));
5486
+ if (!touched.faces.length && !touched.lines.length && !touched.edges.length) return none("There is no face under the pointer.");
5487
+ return this.applyShapeBuilder(m, touched, erase);
5488
+ }
5489
+ applyShapeBuilder(m, touched, erase) {
5490
+ const plan = planShapeBuilder(m, touched, erase);
5491
+ let mergedId = null;
5492
+ const created = /* @__PURE__ */ new Map();
5493
+ this.change(erase ? "Shape Builder Delete" : "Shape Builder", () => {
5494
+ let nodes = this.doc.nodes;
5495
+ m.entries.forEach((entry, i) => {
5496
+ const node = entry.node;
5497
+ const toLocal = (path) => _chunkVNYRI265cjs.transformBezierPath.call(void 0, path, invertMatrix(multiplyMatrices(nodeMatrix(node), entry.parent)));
5498
+ const list = [];
5499
+ const r = plan.replace.get(i);
5500
+ if (r === void 0) list.push(node);
5501
+ else if (_optionalChain([r, 'optionalAccess', _145 => _145.kind]) === "fill") list.push({ ...node, fillRule: "nonzero", subpaths: bezierToSubpaths(toLocal(r.path)) });
5502
+ else if (_optionalChain([r, 'optionalAccess', _146 => _146.kind]) === "outline") list.push({ ...node, subpaths: bezierToSubpaths(toLocal(r.path)) });
5503
+ else if (_optionalChain([r, 'optionalAccess', _147 => _147.kind]) === "pieces") {
5504
+ r.paths.forEach(
5505
+ (path, k) => list.push({ ...node, id: k === 0 ? node.id : this.newId(), subpaths: bezierToSubpaths(toLocal(path)).map((sp) => ({ ...sp, closed: false })) })
5506
+ );
5507
+ }
5508
+ if (plan.merged && plan.merged.style === i) {
5509
+ mergedId = this.newId();
5510
+ const merged = {
5511
+ ...vectorResultStyle(node, "fill"),
5512
+ type: "path",
5513
+ id: mergedId,
5514
+ name: "Shape",
5515
+ ...node.transform ? { transform: node.transform } : {},
5516
+ subpaths: bezierToSubpaths(toLocal(plan.merged.path))
5517
+ };
5518
+ if (plan.merged.currentFill || !hasPaint(merged.fill)) merged.fill = hasPaint(this.defaults.fill) ? this.defaults.fill : "#808080";
5519
+ list.push(merged);
5520
+ }
5521
+ if (r === void 0 && list.length === 1) return;
5522
+ created.set(node.id, list.map((n) => n.id));
5523
+ nodes = spliceTree(nodes, node.id, list);
5524
+ });
5525
+ this.setDoc(nodes);
5526
+ const selection = this.selection.flatMap((id) => _nullishCoalesce(created.get(id), () => ( [id])));
5527
+ if (mergedId && !selection.includes(mergedId)) selection.push(mergedId);
5528
+ this.selection = selection.filter((id, k) => !!this.getNode(id) && selection.indexOf(id) === k);
5529
+ this.anchors = [];
5530
+ this.editingId = null;
5531
+ });
5532
+ this.builderCache = null;
5533
+ return { ok: true, merged: mergedId, faces: touched.faces.length, lines: touched.lines.length, edges: erase ? vectorBuilderErasedEdges(m, touched).length : 0 };
5534
+ }
5535
+ /** The paint bucket's map of the visible outlines, cached per document and gap. */
5536
+ fillMap(gap) {
5537
+ if (_optionalChain([this, 'access', _148 => _148.fillCache, 'optionalAccess', _149 => _149.doc]) === this.doc && this.fillCache.gap === gap) return this.fillCache.map;
5538
+ const map = vectorFillMap(this.doc, gap);
5539
+ this.fillCache = { doc: this.doc, gap, map };
5540
+ return map;
5541
+ }
5542
+ /**
5543
+ * Paint bucket: the region the visible outlines enclose around `point` (document units),
5544
+ * crossings split and islands left as holes, becomes a new path filled with the current fill
5545
+ * default, placed just below the selection (or on top when nothing is selected). `gap`
5546
+ * (default `editing.fillGap`) closes gaps up to that size between loose ends. Returns the new
5547
+ * path's id, or null when nothing encloses the point.
5548
+ */
5549
+ fillRegion(point, options = {}) {
5550
+ if (!Number.isFinite(point.x) || !Number.isFinite(point.y)) return null;
5551
+ const region = _optionalChain([this, 'access', _150 => _150.fillMap, 'call', _151 => _151(_nullishCoalesce(options.gap, () => ( this.editing.fillGap))), 'optionalAccess', _152 => _152.regionAt, 'call', _153 => _153([point.x, point.y])]);
5552
+ if (!_optionalChain([region, 'optionalAccess', _154 => _154.length])) return null;
5553
+ let below = null;
5554
+ const roots = new Set(this.selectedRoots());
5555
+ walkVectorNodes(this.doc.nodes, (n) => {
5556
+ if (!below && roots.has(n.id)) below = n.id;
5557
+ });
5558
+ const subpaths = bezierToSubpaths(below ? this.intoParentSpace(below, region) : region);
5559
+ if (!subpaths.length) return null;
5560
+ const id = this.newId();
5561
+ const node = { id, type: "path", name: "Fill", ...this.styleFor(false), stroke: null, fillRule: "nonzero", subpaths };
5562
+ if (!hasPaint(node.fill)) node.fill = "#808080";
5563
+ const target = below;
5564
+ this.change("Fill Region", () => {
5565
+ if (target) {
5566
+ const current = this.getNode(target);
5567
+ this.setDoc(spliceTree(this.doc.nodes, target, [node, current]));
5568
+ } else this.setDoc([...this.doc.nodes, node]);
5569
+ if (!target) this.selection = [id];
5570
+ this.anchors = [];
5571
+ this.editingId = null;
5572
+ });
5573
+ return id;
5574
+ }
5575
+ /** Updates the Shape Builder / paint bucket highlight for the pointer at `p`; true when it changed. */
5576
+ hoverBuilder(p, alt) {
5577
+ if (this.tool === "paintBucket") {
5578
+ const region = _nullishCoalesce(_optionalChain([this, 'access', _155 => _155.fillMap, 'call', _156 => _156(this.editing.fillGap), 'optionalAccess', _157 => _157.regionAt, 'call', _158 => _158([p.x, p.y])]), () => ( null));
5579
+ const key2 = region ? _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, region, { precision: 2 }) : null;
5580
+ if (key2 === this.builderHoverKey) return false;
5581
+ this.builderHoverKey = key2;
5582
+ this.builderPreview = region ? { mode: "fill", faces: [region], lines: [], trail: null } : null;
5583
+ return true;
5584
+ }
5585
+ const m = this.selectedRoots().length ? this.shapeBuilderMap() : null;
5586
+ const hit = m ? vectorShapeBuilderHit(m, p, alt ? this.builderLineTolerance() : null) : null;
5587
+ const key = hit ? `${alt ? "erase" : "merge"}:${JSON.stringify(hit)}` : null;
5588
+ if (key === this.builderHoverKey) return false;
5589
+ this.builderHoverKey = key;
5590
+ const touched = { faces: [], lines: [], edges: [] };
5591
+ addBuilderHit(touched, hit);
5592
+ this.builderPreview = hit && m ? this.builderPreviewOf(m, touched, alt, null) : null;
5593
+ return true;
5594
+ }
5595
+ builderPreviewOf(m, touched, erase, trail) {
5596
+ const faces = m.map.faces;
5597
+ return {
5598
+ mode: erase ? "erase" : "merge",
5599
+ faces: touched.faces.map((f) => faces[f].path),
5600
+ // Edges bounding a face touched too go with the face, so they are not shown apart.
5601
+ lines: [...touched.lines.map((k) => m.pieces[k].path), ...erase ? vectorBuilderErasedEdges(m, touched).map((k) => m.edges[k].path) : []],
5602
+ trail
5603
+ };
5604
+ }
5605
+ downBuilder(p, input) {
5606
+ this.builderHoverKey = null;
5607
+ if (this.tool === "paintBucket") {
5608
+ this.fillRegion(p);
5609
+ this.builderPreview = null;
5610
+ this.hoverBuilder(p, false);
5611
+ this.notify();
5612
+ return;
5613
+ }
5614
+ const m = this.selectedRoots().length ? this.shapeBuilderMap() : null;
5615
+ if (!m) return;
5616
+ const erase = !!input.alt;
5617
+ const touched = { faces: [], lines: [], edges: [] };
5618
+ addBuilderHit(touched, vectorShapeBuilderHit(m, p, erase ? this.builderLineTolerance() : null));
5619
+ this.drag = { kind: "builder", erase, points: [p], touched, map: m };
5620
+ this.interaction = { type: "builder", mode: erase ? "erase" : "merge", points: [p] };
5621
+ this.builderPreview = this.builderPreviewOf(m, touched, erase, [p]);
5622
+ this.notify();
5623
+ }
5624
+ moveBuilder(drag, p) {
5625
+ const last = drag.points[drag.points.length - 1];
5626
+ if (Math.hypot(p.x - last.x, p.y - last.y) * this.viewport.zoom < 1) return;
5627
+ const tol = drag.erase ? this.builderLineTolerance() : null;
5628
+ for (const q of samplePolyline([last, p], 2 / this.viewport.zoom)) addBuilderHit(drag.touched, vectorShapeBuilderHit(drag.map, q, tol));
5629
+ drag.points.push(p);
5630
+ this.interaction = { type: "builder", mode: drag.erase ? "erase" : "merge", points: drag.points.slice() };
5631
+ this.builderPreview = this.builderPreviewOf(drag.map, drag.touched, drag.erase, drag.points.slice());
5632
+ this.notify();
5633
+ }
5634
+ upBuilder(drag) {
5635
+ this.builderPreview = null;
5636
+ this.builderHoverKey = null;
5637
+ if (!drag.touched.faces.length && !drag.touched.lines.length && !drag.touched.edges.length) {
5638
+ this.notify();
5639
+ return;
5640
+ }
5641
+ this.applyShapeBuilder(drag.map, drag.touched, drag.erase);
5642
+ }
5643
+ // -------------------------------------------------------------------------
5118
5644
  // Anchor editing
5119
5645
  // -------------------------------------------------------------------------
5120
5646
  updateAnchors(doc, refs, fn) {
@@ -5157,7 +5683,7 @@ var VectorEditorController = (_class3 = class {
5157
5683
  /** `doc` with anchor `ref` moved to document point `to` by a Curvature-tool move. */
5158
5684
  curvatureMoved(doc, ref, to) {
5159
5685
  const node = findVectorNode(doc.nodes, ref.nodeId);
5160
- if (_optionalChain([node, 'optionalAccess', _137 => _137.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
5686
+ if (_optionalChain([node, 'optionalAccess', _159 => _159.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
5161
5687
  const q = this.toLocal(ref.nodeId, to, doc);
5162
5688
  const subpaths = node.subpaths.map((sp, i) => i === ref.subpath ? curvatureMoveAnchor(sp, ref.index, q) : sp);
5163
5689
  const nodes = mapTree(doc.nodes, (n) => n.id === ref.nodeId ? { ...node, subpaths } : n);
@@ -5166,7 +5692,7 @@ var VectorEditorController = (_class3 = class {
5166
5692
  /** `doc` with segment `ref` bent through document point `p` at parameter `t`. */
5167
5693
  bent(doc, ref, t, p) {
5168
5694
  const node = findVectorNode(doc.nodes, ref.nodeId);
5169
- if (_optionalChain([node, 'optionalAccess', _138 => _138.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
5695
+ if (_optionalChain([node, 'optionalAccess', _160 => _160.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
5170
5696
  const q = this.toLocal(ref.nodeId, p, doc);
5171
5697
  const subpaths = node.subpaths.map((sp, i) => i === ref.subpath ? bendSegment(sp, ref.segment, t, q) : sp);
5172
5698
  return { ...doc, nodes: mapTree(doc.nodes, (n) => n.id === ref.nodeId ? { ...node, subpaths } : n) };
@@ -5177,7 +5703,7 @@ var VectorEditorController = (_class3 = class {
5177
5703
  */
5178
5704
  bendSegment(ref, to, t = 0.5) {
5179
5705
  const node = this.getNode(ref.nodeId);
5180
- const sp = _optionalChain([node, 'optionalAccess', _139 => _139.type]) === "path" ? node.subpaths[ref.subpath] : void 0;
5706
+ const sp = _optionalChain([node, 'optionalAccess', _161 => _161.type]) === "path" ? node.subpaths[ref.subpath] : void 0;
5181
5707
  if (!sp || ref.segment < 0 || ref.segment >= (sp.closed ? sp.anchors.length : sp.anchors.length - 1) || sp.anchors.length < 2) return { ok: false, message: "There is no such segment." };
5182
5708
  if (node.locked) return { ok: false, message: "The path is locked." };
5183
5709
  this.change("Bend Segment", () => {
@@ -5212,7 +5738,7 @@ var VectorEditorController = (_class3 = class {
5212
5738
  /** Adds an anchor on the nearest segment of `nodeId` to document point `point` (shape unchanged). */
5213
5739
  insertAnchorAt(nodeId, point) {
5214
5740
  const node = this.getNode(nodeId);
5215
- if (_optionalChain([node, 'optionalAccess', _140 => _140.type]) !== "path") return null;
5741
+ if (_optionalChain([node, 'optionalAccess', _162 => _162.type]) !== "path") return null;
5216
5742
  const hit = nearestSegment(node, this.toLocal(nodeId, point));
5217
5743
  if (!hit) return null;
5218
5744
  const { subpath, index } = insertAnchor(node.subpaths[hit.subpath], hit.segment, hit.t);
@@ -5256,7 +5782,7 @@ var VectorEditorController = (_class3 = class {
5256
5782
  setClosed(closed, nodeId) {
5257
5783
  const targets = nodeId ? (() => {
5258
5784
  const n = this.getNode(nodeId);
5259
- return _optionalChain([n, 'optionalAccess', _141 => _141.type]) === "path" ? n.subpaths.map((_, s) => ({ nodeId, subpath: s })) : [];
5785
+ return _optionalChain([n, 'optionalAccess', _163 => _163.type]) === "path" ? n.subpaths.map((_, s) => ({ nodeId, subpath: s })) : [];
5260
5786
  })() : this.anchors.map((r) => ({ nodeId: r.nodeId, subpath: r.subpath }));
5261
5787
  if (!targets.length) return { ok: false, message: "Select a path or points." };
5262
5788
  this.change(closed ? "Close Path" : "Open Path", () => {
@@ -5277,7 +5803,7 @@ var VectorEditorController = (_class3 = class {
5277
5803
  this.setDoc(
5278
5804
  mapTree(
5279
5805
  this.doc.nodes,
5280
- (n) => n.type === "path" && set.has(n.id) ? { ...n, subpaths: n.subpaths.map(reverseSubpath), ..._optionalChain([n, 'access', _142 => _142.strokeWidthProfile, 'optionalAccess', _143 => _143.length]) ? { strokeWidthProfile: reverseWidthProfile(n.strokeWidthProfile) } : {} } : n
5806
+ (n) => n.type === "path" && set.has(n.id) ? { ...n, subpaths: n.subpaths.map(reverseSubpath), ..._optionalChain([n, 'access', _164 => _164.strokeWidthProfile, 'optionalAccess', _165 => _165.length]) ? { strokeWidthProfile: reverseWidthProfile(n.strokeWidthProfile) } : {} } : n
5281
5807
  )
5282
5808
  );
5283
5809
  this.anchors = [];
@@ -5415,7 +5941,7 @@ var VectorEditorController = (_class3 = class {
5415
5941
  */
5416
5942
  cutPathAt(nodeId, point) {
5417
5943
  const node = this.getNode(nodeId);
5418
- if (_optionalChain([node, 'optionalAccess', _144 => _144.type]) !== "path" || node.locked) return null;
5944
+ if (_optionalChain([node, 'optionalAccess', _166 => _166.type]) !== "path" || node.locked) return null;
5419
5945
  const local = this.toLocal(nodeId, point);
5420
5946
  const hit = nearestSegment(node, local);
5421
5947
  if (!hit) return null;
@@ -5465,7 +5991,7 @@ var VectorEditorController = (_class3 = class {
5465
5991
  if (n.visible === false || n.locked || parent && blocked.has(parent.id)) blocked.add(n.id);
5466
5992
  });
5467
5993
  const visible = (p) => !blocked.has(p.id);
5468
- if (_optionalChain([ids, 'optionalAccess', _145 => _145.length]) || this.selection.length) return this.pathTargets(_nullishCoalesce(ids, () => ( this.selection))).filter(visible);
5994
+ if (_optionalChain([ids, 'optionalAccess', _167 => _167.length]) || this.selection.length) return this.pathTargets(_nullishCoalesce(ids, () => ( this.selection))).filter(visible);
5469
5995
  const box = polylineBounds(points.map(toPoint2), pad);
5470
5996
  if (!box) return [];
5471
5997
  const out = [];
@@ -5521,10 +6047,10 @@ var VectorEditorController = (_class3 = class {
5521
6047
  const region = eraserRegion(pts, width);
5522
6048
  if (!region.length) return [];
5523
6049
  const plan = [];
5524
- const rb = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, region);
6050
+ const rb = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, region);
5525
6051
  const reach = rb ? [{ x: rb.minX, y: rb.minY }, { x: rb.maxX, y: rb.maxY }] : points;
5526
6052
  for (const node of this.strokeTargets(reach, options.ids, 0)) {
5527
- const local = _chunkGVB7ZPLZcjs.transformBezierPath.call(void 0, region, invertMatrix(this.worldOf(node.id)));
6053
+ const local = _chunkVNYRI265cjs.transformBezierPath.call(void 0, region, invertMatrix(this.worldOf(node.id)));
5528
6054
  const live = node.subpaths.filter((sp) => sp.anchors.length > 1);
5529
6055
  if (!live.length) continue;
5530
6056
  if (hasPaint(node.fill) && live.every((sp) => sp.closed)) {
@@ -5551,7 +6077,7 @@ var VectorEditorController = (_class3 = class {
5551
6077
  finishPath() {
5552
6078
  if (!this.pen) return;
5553
6079
  const node = this.getNode(this.pen.nodeId);
5554
- const sp = _optionalChain([node, 'optionalAccess', _146 => _146.subpaths, 'access', _147 => _147[this.pen.subpath]]);
6080
+ const sp = _optionalChain([node, 'optionalAccess', _168 => _168.subpaths, 'access', _169 => _169[this.pen.subpath]]);
5555
6081
  const pen = this.pen;
5556
6082
  this.pen = null;
5557
6083
  this.pointer = null;
@@ -5595,7 +6121,7 @@ var VectorEditorController = (_class3 = class {
5595
6121
  if (trimmed.startsWith("{")) {
5596
6122
  try {
5597
6123
  const data = JSON.parse(trimmed);
5598
- if (_optionalChain([data, 'optionalAccess', _148 => _148.type]) === VECTOR_CLIPBOARD_TYPE && Array.isArray(data.nodes)) nodes = data.nodes;
6124
+ if (_optionalChain([data, 'optionalAccess', _170 => _170.type]) === VECTOR_CLIPBOARD_TYPE && Array.isArray(data.nodes)) nodes = data.nodes;
5599
6125
  } catch (e3) {
5600
6126
  nodes = null;
5601
6127
  }
@@ -5607,7 +6133,7 @@ var VectorEditorController = (_class3 = class {
5607
6133
  }
5608
6134
  }
5609
6135
  } else nodes = this.clipboard;
5610
- if (!_optionalChain([nodes, 'optionalAccess', _149 => _149.length])) return [];
6136
+ if (!_optionalChain([nodes, 'optionalAccess', _171 => _171.length])) return [];
5611
6137
  const offset = _nullishCoalesce(options.offset, () => ( (text && !text.trim().startsWith("{") ? { x: 0, y: 0 } : { x: 10, y: 10 })));
5612
6138
  const copies = nodes.map((n) => transformVectorNode(this.freshIds(n), translateMatrix(offset.x, offset.y)));
5613
6139
  this.change("Paste", () => {
@@ -5651,14 +6177,14 @@ var VectorEditorController = (_class3 = class {
5651
6177
  if (!frame) return null;
5652
6178
  const { box, handles } = getVectorSelectionBoxGeometry(frame, this.viewport);
5653
6179
  const r = this.hitRadius + 2;
5654
- const usable = box.width < 2 * r || box.height < 2 * r ? handles.filter((h) => h.handle.length === 2 || h.handle === "rotate") : handles;
5655
- for (const h of usable) if (Math.hypot(h.screen.x - screen.x, h.screen.y - screen.y) <= r * Math.SQRT2) return h.handle;
6180
+ const usable2 = box.width < 2 * r || box.height < 2 * r ? handles.filter((h) => h.handle.length === 2 || h.handle === "rotate") : handles;
6181
+ for (const h of usable2) if (Math.hypot(h.screen.x - screen.x, h.screen.y - screen.y) <= r * Math.SQRT2) return h.handle;
5656
6182
  return null;
5657
6183
  }
5658
6184
  hitHandle(screen) {
5659
6185
  for (const ref of getVisibleHandles(this.view()).reverse()) {
5660
6186
  const a = getAnchorWorld(this.doc, ref);
5661
- const h = _optionalChain([a, 'optionalAccess', _150 => _150[ref.handle]]);
6187
+ const h = _optionalChain([a, 'optionalAccess', _172 => _172[ref.handle]]);
5662
6188
  if (!h) continue;
5663
6189
  const s = this.documentToScreen(h);
5664
6190
  if (Math.hypot(s.x - screen.x, s.y - screen.y) <= this.hitRadius) return ref;
@@ -5828,9 +6354,9 @@ var VectorEditorController = (_class3 = class {
5828
6354
  downWidth(screen, p, input) {
5829
6355
  const hit = this.hitWidthHandle(screen);
5830
6356
  const spot = hit ? null : this.strokeSpotAt(p);
5831
- const nodeId = _nullishCoalesce(_optionalChain([hit, 'optionalAccess', _151 => _151.ref, 'access', _152 => _152.nodeId]), () => ( _optionalChain([spot, 'optionalAccess', _153 => _153.nodeId])));
6357
+ const nodeId = _nullishCoalesce(_optionalChain([hit, 'optionalAccess', _173 => _173.ref, 'access', _174 => _174.nodeId]), () => ( _optionalChain([spot, 'optionalAccess', _175 => _175.nodeId])));
5832
6358
  const node = nodeId ? this.getNode(nodeId) : void 0;
5833
- const g = _optionalChain([node, 'optionalAccess', _154 => _154.type]) === "path" ? vectorStrokeWidthGeometry(node) : null;
6359
+ const g = _optionalChain([node, 'optionalAccess', _176 => _176.type]) === "path" ? vectorStrokeWidthGeometry(node) : null;
5834
6360
  if (!node || node.type !== "path" || !g) {
5835
6361
  if (this.widthPoint) {
5836
6362
  this.widthPoint = null;
@@ -5849,7 +6375,7 @@ var VectorEditorController = (_class3 = class {
5849
6375
  if (hit) {
5850
6376
  profile = sanitizeWidthProfile(node.strokeWidthProfile);
5851
6377
  ref = { nodeId: node.id, index: hit.ref.index, subpath: hit.ref.subpath };
5852
- t = _nullishCoalesce(_optionalChain([profile, 'access', _155 => _155[ref.index], 'optionalAccess', _156 => _156.t]), () => ( 0));
6378
+ t = _nullishCoalesce(_optionalChain([profile, 'access', _177 => _177[ref.index], 'optionalAccess', _178 => _178.t]), () => ( 0));
5853
6379
  subpath = hit.ref.subpath;
5854
6380
  if (hit.ref.part === "center") mode = "move";
5855
6381
  else if (input.alt) side = hit.ref.part;
@@ -5936,6 +6462,9 @@ var VectorEditorController = (_class3 = class {
5936
6462
  return this.downPencil(p, input);
5937
6463
  case "width":
5938
6464
  return this.downWidth(screen, p, input);
6465
+ case "shapeBuilder":
6466
+ case "paintBucket":
6467
+ return this.downBuilder(p, input);
5939
6468
  case "scissors": {
5940
6469
  const seg = this.nearestOutline(p);
5941
6470
  if (seg) this.cutPathAt(seg.nodeId, seg.point);
@@ -6071,7 +6600,7 @@ var VectorEditorController = (_class3 = class {
6071
6600
  }
6072
6601
  downPen(screen, p, input) {
6073
6602
  const before = this.snapshot();
6074
- const sp = this.pen ? _optionalChain([this, 'access', _157 => _157.getNode, 'call', _158 => _158(this.pen.nodeId), 'optionalAccess', _159 => _159.subpaths, 'access', _160 => _160[this.pen.subpath]]) : void 0;
6603
+ const sp = this.pen ? _optionalChain([this, 'access', _179 => _179.getNode, 'call', _180 => _180(this.pen.nodeId), 'optionalAccess', _181 => _181.subpaths, 'access', _182 => _182[this.pen.subpath]]) : void 0;
6075
6604
  if (this.pen && sp) {
6076
6605
  const pen = this.pen;
6077
6606
  const first = { nodeId: pen.nodeId, subpath: pen.subpath, index: 0 };
@@ -6165,6 +6694,11 @@ var VectorEditorController = (_class3 = class {
6165
6694
  pointerMove(screen, input = {}) {
6166
6695
  const p = this.screenToDocument(screen);
6167
6696
  const drag = this.drag;
6697
+ if (!drag && (this.tool === "shapeBuilder" || this.tool === "paintBucket")) {
6698
+ this.pointer = p;
6699
+ if (this.hoverBuilder(p, !!input.alt)) this.notify();
6700
+ return;
6701
+ }
6168
6702
  if (!drag) {
6169
6703
  const hover = this.computeHover(screen);
6170
6704
  const pointerMatters = this.tool === "pen" && !!this.pen;
@@ -6296,6 +6830,8 @@ var VectorEditorController = (_class3 = class {
6296
6830
  this.notify(true);
6297
6831
  return;
6298
6832
  }
6833
+ case "builder":
6834
+ return this.moveBuilder(drag, p);
6299
6835
  case "stroke": {
6300
6836
  const last = drag.points[drag.points.length - 1];
6301
6837
  if (Math.hypot(p.x - last.x, p.y - last.y) * this.viewport.zoom < 1.5) return;
@@ -6326,7 +6862,7 @@ var VectorEditorController = (_class3 = class {
6326
6862
  }
6327
6863
  case "shape": {
6328
6864
  const node = this.getNode(drag.nodeId);
6329
- if (_optionalChain([node, 'optionalAccess', _161 => _161.type]) !== "path") return;
6865
+ if (_optionalChain([node, 'optionalAccess', _183 => _183.type]) !== "path") return;
6330
6866
  const leave = { at: drag.start, constrain: input.shift ? drag.tool === "line" ? "angle" : "square" : null, curves: false };
6331
6867
  let end = this.snapDrawn(p, leave, input, () => drag.targets ??= this.drawingTargets(null));
6332
6868
  if (!this.snappedToObject && drag.tool !== "line" && !input.shift && !input.mod && this.snap.objects && drag.targets) end = this.matchShapeSize(drag.targets, drag.start, end, input.alt);
@@ -6384,14 +6920,14 @@ var VectorEditorController = (_class3 = class {
6384
6920
  for (const q of drag.lazy.push([p.x, p.y])) {
6385
6921
  if (Math.hypot(q[0] - last[0], q[1] - last[1]) * this.viewport.zoom < 1.5) continue;
6386
6922
  drag.points.push(q);
6387
- _optionalChain([drag, 'access', _162 => _162.pressures, 'optionalAccess', _163 => _163.push, 'call', _164 => _164(drag.pressure)]);
6923
+ _optionalChain([drag, 'access', _184 => _184.pressures, 'optionalAccess', _185 => _185.push, 'call', _186 => _186(drag.pressure)]);
6388
6924
  moved = true;
6389
6925
  }
6390
6926
  const string = drag.lazy.string();
6391
6927
  const node = this.getNode(drag.nodeId);
6392
- if (_optionalChain([node, 'optionalAccess', _165 => _165.type]) !== "path") return;
6928
+ if (_optionalChain([node, 'optionalAccess', _187 => _187.type]) !== "path") return;
6393
6929
  if (!moved) {
6394
- if (string && _optionalChain([this, 'access', _166 => _166.interaction, 'optionalAccess', _167 => _167.type]) === "draw") {
6930
+ if (string && _optionalChain([this, 'access', _188 => _188.interaction, 'optionalAccess', _189 => _189.type]) === "draw") {
6395
6931
  this.interaction = { ...this.interaction, string: [{ x: string[0][0], y: string[0][1] }, { x: string[1][0], y: string[1][1] }] };
6396
6932
  this.notify();
6397
6933
  }
@@ -6427,8 +6963,8 @@ var VectorEditorController = (_class3 = class {
6427
6963
  }
6428
6964
  this.setGuides(res);
6429
6965
  return {
6430
- dx: _optionalChain([res, 'optionalAccess', _168 => _168.x]) ? dx + res.dx : axes.x ? this.gridValue(origin.x + dx) - origin.x : dx,
6431
- dy: _optionalChain([res, 'optionalAccess', _169 => _169.y]) ? dy + res.dy : axes.y ? this.gridValue(origin.y + dy) - origin.y : dy
6966
+ dx: _optionalChain([res, 'optionalAccess', _190 => _190.x]) ? dx + res.dx : axes.x ? this.gridValue(origin.x + dx) - origin.x : dx,
6967
+ dy: _optionalChain([res, 'optionalAccess', _191 => _191.y]) ? dy + res.dy : axes.y ? this.gridValue(origin.y + dy) - origin.y : dy
6432
6968
  };
6433
6969
  }
6434
6970
  /** The anchor a point drag snaps by, where it started: the grabbed one, else the moving one nearest the press. */
@@ -6507,7 +7043,7 @@ var VectorEditorController = (_class3 = class {
6507
7043
  if (drag.moved) return this.commit("Corner Radius", drag.before);
6508
7044
  if (drag.alt) {
6509
7045
  const kind = nextVectorCornerKind(drag.widget.kind);
6510
- this.doc = this.updateAnchors(drag.base, drag.refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access', _170 => _170.corner, 'optionalAccess', _171 => _171.radius]), () => ( 0)), kind));
7046
+ this.doc = this.updateAnchors(drag.base, drag.refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access', _192 => _192.corner, 'optionalAccess', _193 => _193.radius]), () => ( 0)), kind));
6511
7047
  return this.commit("Corner Kind", drag.before);
6512
7048
  }
6513
7049
  const ref = drag.widget.ref;
@@ -6526,6 +7062,8 @@ var VectorEditorController = (_class3 = class {
6526
7062
  } else this.notify();
6527
7063
  return;
6528
7064
  }
7065
+ case "builder":
7066
+ return this.upBuilder(drag);
6529
7067
  case "stroke": {
6530
7068
  this.notify();
6531
7069
  if (drag.tool === "knife") this.knife(drag.points);
@@ -6551,14 +7089,14 @@ var VectorEditorController = (_class3 = class {
6551
7089
  }
6552
7090
  case "pencil": {
6553
7091
  const node = this.getNode(drag.nodeId);
6554
- if (_optionalChain([node, 'optionalAccess', _172 => _172.type]) !== "path" || drag.points.length < 2) {
7092
+ if (_optionalChain([node, 'optionalAccess', _194 => _194.type]) !== "path" || drag.points.length < 2) {
6555
7093
  this.doc = drag.before.doc;
6556
7094
  this.notify(true);
6557
7095
  return;
6558
7096
  }
6559
7097
  for (const q of drag.lazy.finish()) {
6560
7098
  drag.points.push(q);
6561
- _optionalChain([drag, 'access', _173 => _173.pressures, 'optionalAccess', _174 => _174.push, 'call', _175 => _175(drag.pressure)]);
7099
+ _optionalChain([drag, 'access', _195 => _195.pressures, 'optionalAccess', _196 => _196.push, 'call', _197 => _197(drag.pressure)]);
6562
7100
  }
6563
7101
  const shape = this.editing.recognizeShapes ? recognizeInkShape(drag.points, { minSize: 6 / this.viewport.zoom }) : null;
6564
7102
  if (shape) {
@@ -6566,7 +7104,7 @@ var VectorEditorController = (_class3 = class {
6566
7104
  this.selection = [drag.nodeId];
6567
7105
  return this.commit(`Draw ${inkShapeLabel(shape)}`, drag.before);
6568
7106
  }
6569
- const fitted = _chunkGVB7ZPLZcjs.fitCubics.call(void 0, drag.points, 1.5 / this.viewport.zoom, { cornerAngleDeg: 60 });
7107
+ const fitted = _chunkVNYRI265cjs.fitCubics.call(void 0, drag.points, 1.5 / this.viewport.zoom, { cornerAngleDeg: 60 });
6570
7108
  const anchors = [];
6571
7109
  for (const c of fitted) {
6572
7110
  if (!anchors.length) anchors.push({ x: c.p0[0], y: c.p0[1] });
@@ -6597,7 +7135,8 @@ var VectorEditorController = (_class3 = class {
6597
7135
  this.drag = null;
6598
7136
  this.interaction = null;
6599
7137
  this.guides = null;
6600
- if (drag.kind === "pan") {
7138
+ if (drag.kind === "pan" || drag.kind === "builder") {
7139
+ if (drag.kind === "builder") this.builderPreview = null;
6601
7140
  this.notify();
6602
7141
  return;
6603
7142
  }
@@ -6629,7 +7168,7 @@ var VectorEditorController = (_class3 = class {
6629
7168
  this.convertAnchors(a.in || a.out ? "corner" : "smooth", [anchor]);
6630
7169
  return;
6631
7170
  }
6632
- const id = _nullishCoalesce(_optionalChain([this, 'access', _176 => _176.hover, 'optionalAccess', _177 => _177.segment, 'optionalAccess', _178 => _178.nodeId]), () => ( this.editingId));
7171
+ const id = _nullishCoalesce(_optionalChain([this, 'access', _198 => _198.hover, 'optionalAccess', _199 => _199.segment, 'optionalAccess', _200 => _200.nodeId]), () => ( this.editingId));
6633
7172
  if (id) {
6634
7173
  const node = this.getNode(id);
6635
7174
  const seg = node ? nearestSegment(node, this.toLocal(id, p)) : null;
@@ -6712,7 +7251,7 @@ var VectorEditorController = (_class3 = class {
6712
7251
  this.finishPath();
6713
7252
  return true;
6714
7253
  }
6715
- if (this.tool === "select" && this.selection.length === 1 && _optionalChain([this, 'access', _179 => _179.getNode, 'call', _180 => _180(this.selection[0]), 'optionalAccess', _181 => _181.type]) === "path") {
7254
+ if (this.tool === "select" && this.selection.length === 1 && _optionalChain([this, 'access', _201 => _201.getNode, 'call', _202 => _202(this.selection[0]), 'optionalAccess', _203 => _203.type]) === "path") {
6716
7255
  this.tool = "direct";
6717
7256
  this.editingId = this.selection[0];
6718
7257
  this.notify();
@@ -6832,6 +7371,7 @@ function pencilPressureProfile(points, pressures) {
6832
7371
  // src/vector/render.ts
6833
7372
  var fmt = (n) => Math.round(n * 100) / 100;
6834
7373
  var fmtMatrix = (m) => `matrix(${m.map((n) => Math.round(n * 1e6) / 1e6).join(" ")})`;
7374
+ var VECTOR_BUILDER_HATCH_GAP = 6;
6835
7375
  function renderNode(node, defs, idPrefix) {
6836
7376
  if (node.visible === false) return null;
6837
7377
  if (node.type === "group") {
@@ -6854,7 +7394,7 @@ function renderNode(node, defs, idPrefix) {
6854
7394
  strokeWidth: _nullishCoalesce(node.strokeWidth, () => ( 1)),
6855
7395
  ...node.strokeLinecap ? { strokeLinecap: node.strokeLinecap } : {},
6856
7396
  ...node.strokeLinejoin ? { strokeLinejoin: node.strokeLinejoin } : {},
6857
- ..._optionalChain([node, 'access', _182 => _182.strokeDasharray, 'optionalAccess', _183 => _183.length]) ? { strokeDasharray: node.strokeDasharray.join(" ") } : {},
7397
+ ..._optionalChain([node, 'access', _204 => _204.strokeDasharray, 'optionalAccess', _205 => _205.length]) ? { strokeDasharray: node.strokeDasharray.join(" ") } : {},
6858
7398
  fillRule: _nullishCoalesce(node.fillRule, () => ( "nonzero")),
6859
7399
  opacity: _nullishCoalesce(node.opacity, () => ( 1))
6860
7400
  };
@@ -6878,7 +7418,7 @@ function screenOutline(state, node) {
6878
7418
  const v2 = state.viewport;
6879
7419
  const view = [v2.zoom, 0, 0, v2.zoom, v2.x, v2.y];
6880
7420
  const parent = _nullishCoalesce(vectorParentMatrix(state.document.nodes, node.id), () => ( IDENTITY_MATRIX));
6881
- return collectWithMatrix(node, parent).map(({ path, parent: m }) => _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, _chunkGVB7ZPLZcjs.transformBezierPath.call(void 0, vectorPathWorldBezier(path, m), view), { precision: 2 })).join(" ");
7421
+ return collectWithMatrix(node, parent).map(({ path, parent: m }) => _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, _chunkVNYRI265cjs.transformBezierPath.call(void 0, vectorPathWorldBezier(path, m), view), { precision: 2 })).join(" ");
6882
7422
  }
6883
7423
  function collectWithMatrix(node, parent) {
6884
7424
  if (node.type === "path") return [{ path: node, parent }];
@@ -6903,9 +7443,9 @@ function getVectorOverlayRenderData(state) {
6903
7443
  };
6904
7444
  for (const id of state.selection) outline(id, true);
6905
7445
  if (state.editingId) outline(state.editingId, true);
6906
- if (_optionalChain([state, 'access', _184 => _184.hover, 'optionalAccess', _185 => _185.nodeId]) && !state.interaction) outline(state.hover.nodeId, false);
7446
+ if (_optionalChain([state, 'access', _206 => _206.hover, 'optionalAccess', _207 => _207.nodeId]) && !state.interaction) outline(state.hover.nodeId, false);
6907
7447
  let selectionBox = null;
6908
- if (state.tool === "select" && state.selectionFrame && _optionalChain([state, 'access', _186 => _186.interaction, 'optionalAccess', _187 => _187.type]) !== "marquee") {
7448
+ if (state.tool === "select" && state.selectionFrame && _optionalChain([state, 'access', _208 => _208.interaction, 'optionalAccess', _209 => _209.type]) !== "marquee") {
6909
7449
  const g = getVectorSelectionBoxGeometry(state.selectionFrame, state.viewport);
6910
7450
  selectionBox = { ...g.box, angle: g.angle, transform: g.transform, corners: g.corners, handles: g.handles };
6911
7451
  }
@@ -6915,9 +7455,9 @@ function getVectorOverlayRenderData(state) {
6915
7455
  const a = getAnchorWorld(doc, ref);
6916
7456
  const s = toScreen(state, a);
6917
7457
  const closes = !!state.pen && state.pen.nodeId === ref.nodeId && state.pen.subpath === ref.subpath && ref.index === 0;
6918
- return { ref, x: s.x, y: s.y, type: _nullishCoalesce(a.type, () => ( inferAnchorType(a))), selected: selected(ref), hovered: sameAnchor(_optionalChain([state, 'access', _188 => _188.hover, 'optionalAccess', _189 => _189.anchor]), ref), closes };
7458
+ return { ref, x: s.x, y: s.y, type: _nullishCoalesce(a.type, () => ( inferAnchorType(a))), selected: selected(ref), hovered: sameAnchor(_optionalChain([state, 'access', _210 => _210.hover, 'optionalAccess', _211 => _211.anchor]), ref), closes };
6919
7459
  });
6920
- if (state.tool === "pen" && !state.pen && _optionalChain([state, 'access', _190 => _190.hover, 'optionalAccess', _191 => _191.anchor])) {
7460
+ if (state.tool === "pen" && !state.pen && _optionalChain([state, 'access', _212 => _212.hover, 'optionalAccess', _213 => _213.anchor])) {
6921
7461
  const a = getAnchorWorld(doc, state.hover.anchor);
6922
7462
  if (a) {
6923
7463
  const s = toScreen(state, a);
@@ -6926,15 +7466,15 @@ function getVectorOverlayRenderData(state) {
6926
7466
  }
6927
7467
  const handles = getVisibleHandles(state).flatMap((ref) => {
6928
7468
  const a = getAnchorWorld(doc, ref);
6929
- const h = _optionalChain([a, 'optionalAccess', _192 => _192[ref.handle]]);
7469
+ const h = _optionalChain([a, 'optionalAccess', _214 => _214[ref.handle]]);
6930
7470
  if (!a || !h) return [];
6931
7471
  const s = toScreen(state, h);
6932
7472
  const sa = toScreen(state, a);
6933
- const hovered = !!_optionalChain([state, 'access', _193 => _193.hover, 'optionalAccess', _194 => _194.handle]) && sameAnchor(state.hover.handle, ref) && state.hover.handle.handle === ref.handle;
7473
+ const hovered = !!_optionalChain([state, 'access', _215 => _215.hover, 'optionalAccess', _216 => _216.handle]) && sameAnchor(state.hover.handle, ref) && state.hover.handle.handle === ref.handle;
6934
7474
  return [{ ref, x: s.x, y: s.y, anchorX: sa.x, anchorY: sa.y, hovered }];
6935
7475
  });
6936
7476
  let marquee = null;
6937
- if (_optionalChain([state, 'access', _195 => _195.interaction, 'optionalAccess', _196 => _196.type]) === "marquee") {
7477
+ if (_optionalChain([state, 'access', _217 => _217.interaction, 'optionalAccess', _218 => _218.type]) === "marquee") {
6938
7478
  const b = state.interaction.bounds;
6939
7479
  const tl = toScreen(state, b);
6940
7480
  marquee = { x: tl.x, y: tl.y, width: b.width * z, height: b.height * z };
@@ -6942,7 +7482,7 @@ function getVectorOverlayRenderData(state) {
6942
7482
  let penPreview = null;
6943
7483
  if (state.tool === "pen" && state.pen && state.pointer && !state.interaction) {
6944
7484
  const node = findVectorNode(doc.nodes, state.pen.nodeId);
6945
- const sp = _optionalChain([node, 'optionalAccess', _197 => _197.type]) === "path" ? node.subpaths[state.pen.subpath] : void 0;
7485
+ const sp = _optionalChain([node, 'optionalAccess', _219 => _219.type]) === "path" ? node.subpaths[state.pen.subpath] : void 0;
6946
7486
  const last = sp ? getAnchorWorld(doc, { nodeId: state.pen.nodeId, subpath: state.pen.subpath, index: sp.anchors.length - 1 }) : void 0;
6947
7487
  if (last) {
6948
7488
  const a = toScreen(state, last);
@@ -6955,9 +7495,9 @@ function getVectorOverlayRenderData(state) {
6955
7495
  const artboard = { x: origin.x, y: origin.y, width: doc.width * z, height: doc.height * z };
6956
7496
  let status = null;
6957
7497
  const it = state.interaction;
6958
- if (_optionalChain([it, 'optionalAccess', _198 => _198.type]) === "rotate") status = `${Math.round(it.angle)}\xB0`;
6959
- else if (_optionalChain([it, 'optionalAccess', _199 => _199.type]) === "move" || _optionalChain([it, 'optionalAccess', _200 => _200.type]) === "anchors") status = `\u0394 ${fmt(it.dx)}, ${fmt(it.dy)}`;
6960
- else if (_optionalChain([it, 'optionalAccess', _201 => _201.type]) === "scale" || _optionalChain([it, 'optionalAccess', _202 => _202.type]) === "draw") {
7498
+ if (_optionalChain([it, 'optionalAccess', _220 => _220.type]) === "rotate") status = `${Math.round(it.angle)}\xB0`;
7499
+ else if (_optionalChain([it, 'optionalAccess', _221 => _221.type]) === "move" || _optionalChain([it, 'optionalAccess', _222 => _222.type]) === "anchors") status = `\u0394 ${fmt(it.dx)}, ${fmt(it.dy)}`;
7500
+ else if (_optionalChain([it, 'optionalAccess', _223 => _223.type]) === "scale" || _optionalChain([it, 'optionalAccess', _224 => _224.type]) === "draw") {
6961
7501
  const b = it.type === "draw" ? findVectorNode(doc.nodes, it.nodeId) ? vectorNodeBounds(findVectorNode(doc.nodes, it.nodeId)) : null : state.selectionFrame;
6962
7502
  if (b) status = `W ${fmt(b.width)} \xD7 H ${fmt(b.height)}`;
6963
7503
  }
@@ -6974,24 +7514,24 @@ function getVectorOverlayRenderData(state) {
6974
7514
  }
6975
7515
  }
6976
7516
  let toolStroke = null;
6977
- if (_optionalChain([it, 'optionalAccess', _203 => _203.type]) === "stroke") {
7517
+ if (_optionalChain([it, 'optionalAccess', _225 => _225.type]) === "stroke") {
6978
7518
  const pts = it.points.map((q) => toScreen(state, q));
6979
7519
  const d = pts.map((q, i) => `${i ? "L" : "M"}${fmt(q.x)} ${fmt(q.y)}`).join("") + (pts.length === 1 ? `L${fmt(pts[0].x)} ${fmt(pts[0].y)}` : "");
6980
7520
  toolStroke = { tool: it.tool, d, width: fmt(it.width * z) };
6981
7521
  }
6982
7522
  let pencilString = null;
6983
- if (_optionalChain([it, 'optionalAccess', _204 => _204.type]) === "draw" && it.string) {
7523
+ if (_optionalChain([it, 'optionalAccess', _226 => _226.type]) === "draw" && it.string) {
6984
7524
  const a = toScreen(state, it.string[0]);
6985
7525
  const b = toScreen(state, it.string[1]);
6986
7526
  pencilString = { x1: fmt(a.x), y1: fmt(a.y), x2: fmt(b.x), y2: fmt(b.y) };
6987
7527
  }
6988
- const dragged = _optionalChain([it, 'optionalAccess', _205 => _205.type]) === "corner" ? it.ref : null;
7528
+ const dragged = _optionalChain([it, 'optionalAccess', _227 => _227.type]) === "corner" ? it.ref : null;
6989
7529
  const cornerWidgets = getVectorCornerWidgets(state).map((w) => {
6990
7530
  const s = toScreen(state, w);
6991
- return { ref: w.ref, x: fmt(s.x), y: fmt(s.y), radius: w.radius, kind: w.kind, hovered: sameAnchor(_optionalChain([state, 'access', _206 => _206.hover, 'optionalAccess', _207 => _207.corner]), w.ref), active: !!dragged };
7531
+ return { ref: w.ref, x: fmt(s.x), y: fmt(s.y), radius: w.radius, kind: w.kind, hovered: sameAnchor(_optionalChain([state, 'access', _228 => _228.hover, 'optionalAccess', _229 => _229.corner]), w.ref), active: !!dragged };
6992
7532
  });
6993
- if (_optionalChain([it, 'optionalAccess', _208 => _208.type]) === "corner") status = `R ${fmt(it.radius)}`;
6994
- const cutPoint = state.tool === "scissors" && _optionalChain([state, 'access', _209 => _209.hover, 'optionalAccess', _210 => _210.segment]) && !it ? (({ x, y }) => ({ x: fmt(x), y: fmt(y) }))(toScreen(state, state.hover.segment.point)) : null;
7533
+ if (_optionalChain([it, 'optionalAccess', _230 => _230.type]) === "corner") status = `R ${fmt(it.radius)}`;
7534
+ const cutPoint = state.tool === "scissors" && _optionalChain([state, 'access', _231 => _231.hover, 'optionalAccess', _232 => _232.segment]) && !it ? (({ x, y }) => ({ x: fmt(x), y: fmt(y) }))(toScreen(state, state.hover.segment.point)) : null;
6995
7535
  const sc = (p) => {
6996
7536
  const q = toScreen(state, p);
6997
7537
  return { x: fmt(q.x), y: fmt(q.y) };
@@ -6999,14 +7539,34 @@ function getVectorOverlayRenderData(state) {
6999
7539
  const sameWidth = (a, b) => !!a && a.nodeId === b.nodeId && a.index === b.index;
7000
7540
  const widthPoints = getVectorWidthHandles(state).map((h) => {
7001
7541
  const c = sc(h);
7002
- const hw = _optionalChain([state, 'access', _211 => _211.hover, 'optionalAccess', _212 => _212.widthPoint]);
7542
+ const hw = _optionalChain([state, 'access', _233 => _233.hover, 'optionalAccess', _234 => _234.widthPoint]);
7003
7543
  const hovered = hw && sameWidth(hw, h.ref) && hw.subpath === h.ref.subpath ? hw.part : null;
7004
- return { ref: h.ref, x: c.x, y: c.y, left: sc(h.left), right: sc(h.right), selected: h.selected, hovered, active: _optionalChain([it, 'optionalAccess', _213 => _213.type]) === "width" && sameWidth(it.ref, h.ref) };
7544
+ return { ref: h.ref, x: c.x, y: c.y, left: sc(h.left), right: sc(h.right), selected: h.selected, hovered, active: _optionalChain([it, 'optionalAccess', _235 => _235.type]) === "width" && sameWidth(it.ref, h.ref) };
7005
7545
  });
7006
- const spot = state.tool === "width" && !it ? _optionalChain([state, 'access', _214 => _214.hover, 'optionalAccess', _215 => _215.strokeSpot]) : null;
7546
+ const spot = state.tool === "width" && !it ? _optionalChain([state, 'access', _236 => _236.hover, 'optionalAccess', _237 => _237.strokeSpot]) : null;
7007
7547
  const widthSpot = spot ? { ...sc(spot.point), left: sc(spot.left), right: sc(spot.right) } : null;
7008
- if (_optionalChain([it, 'optionalAccess', _216 => _216.type]) === "width") status = it.mode === "move" ? "Move width point" : `W ${fmt(it.width)}`;
7009
- return { outlines, selectionBox, anchors, handles, marquee, penPreview, artboard, guides, status, toolStroke, pencilString, cutPoint, cornerWidgets, widthPoints, widthSpot };
7548
+ if (_optionalChain([it, 'optionalAccess', _238 => _238.type]) === "width") status = it.mode === "move" ? "Move width point" : `W ${fmt(it.width)}`;
7549
+ let builder = null;
7550
+ if (state.builder) {
7551
+ const v2 = state.viewport;
7552
+ const view = [v2.zoom, 0, 0, v2.zoom, v2.x, v2.y];
7553
+ const svg = (path) => _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, path, { precision: 2 });
7554
+ const screen = state.builder.faces.map((f) => _chunkVNYRI265cjs.transformBezierPath.call(void 0, f, view));
7555
+ const hatch = state.builder.mode !== "fill";
7556
+ const trail = state.builder.trail && state.builder.trail.length > 1 ? state.builder.trail.map((q, i) => `${i ? "L" : "M"}${sc(q).x} ${sc(q).y}`).join("") : null;
7557
+ builder = {
7558
+ mode: state.builder.mode,
7559
+ faces: screen.map(svg),
7560
+ hatches: screen.map((f) => hatch ? svg(_chunkVNYRI265cjs.hatchPath.call(void 0, f, { gap: VECTOR_BUILDER_HATCH_GAP })) : ""),
7561
+ lines: state.builder.lines.map((l) => svg(_chunkVNYRI265cjs.transformBezierPath.call(void 0, l, view))),
7562
+ trail
7563
+ };
7564
+ if (state.builder.mode !== "fill" && _optionalChain([it, 'optionalAccess', _239 => _239.type]) === "builder") {
7565
+ const n = state.builder.faces.length;
7566
+ status = state.builder.mode === "erase" ? `Delete ${n} ${n === 1 ? "face" : "faces"}` : `Merge ${n} ${n === 1 ? "face" : "faces"}`;
7567
+ }
7568
+ }
7569
+ return { outlines, selectionBox, anchors, handles, marquee, penPreview, artboard, guides, status, toolStroke, pencilString, cutPoint, cornerWidgets, widthPoints, widthSpot, builder };
7010
7570
  }
7011
7571
  var VECTOR_OVERLAY_THEME = {
7012
7572
  accent: "#0ea5e9",
@@ -7022,7 +7582,14 @@ var VECTOR_OVERLAY_THEME = {
7022
7582
  /** Radius of a live corner widget (a ring with a dot). */
7023
7583
  cornerWidgetRadius: 4,
7024
7584
  /** Half the diagonal of a width point's diamond. */
7025
- widthPointSize: 5
7585
+ widthPointSize: 5,
7586
+ /** Shape Builder faces to merge and paint bucket regions. */
7587
+ builderFill: "rgba(14, 165, 233, 0.22)",
7588
+ /** Shape Builder faces and line pieces an Alt gesture deletes. */
7589
+ builderErase: "#ef4444",
7590
+ builderEraseFill: "rgba(239, 68, 68, 0.22)",
7591
+ /** Opacity of the hatch lines over Shape Builder faces (drawn in the face's outline colour). */
7592
+ builderHatchOpacity: 0.6
7026
7593
  };
7027
7594
  function vectorDiamondPath(x, y, r = VECTOR_OVERLAY_THEME.widthPointSize) {
7028
7595
  return `M${fmt(x)} ${fmt(y - r)}L${fmt(x + r)} ${fmt(y)}L${fmt(x)} ${fmt(y + r)}L${fmt(x - r)} ${fmt(y)}Z`;
@@ -7046,7 +7613,7 @@ function isVectorTextTarget(target) {
7046
7613
  if (!el || typeof el !== "object") return false;
7047
7614
  const tag = (_nullishCoalesce(el.tagName, () => ( ""))).toUpperCase();
7048
7615
  if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
7049
- return !!el.isContentEditable || _optionalChain([el, 'access', _217 => _217.getAttribute, 'optionalCall', _218 => _218("contenteditable")]) === "true";
7616
+ return !!el.isContentEditable || _optionalChain([el, 'access', _240 => _240.getAttribute, 'optionalCall', _241 => _241("contenteditable")]) === "true";
7050
7617
  }
7051
7618
  function getVectorSelectionStyle(state) {
7052
7619
  const paths = [];
@@ -7054,12 +7621,12 @@ function getVectorSelectionStyle(state) {
7054
7621
  const node = findVectorNode(state.document.nodes, id);
7055
7622
  if (node) paths.push(...collect(node));
7056
7623
  }
7057
- const anchorMode = state.tool === "direct" && !!_optionalChain([state, 'access', _219 => _219.selectedAnchors, 'optionalAccess', _220 => _220.length]);
7624
+ const anchorMode = state.tool === "direct" && !!_optionalChain([state, 'access', _242 => _242.selectedAnchors, 'optionalAccess', _243 => _243.length]);
7058
7625
  if (anchorMode) {
7059
7626
  for (const r of state.selectedAnchors) {
7060
7627
  if (paths.some((p) => p.id === r.nodeId)) continue;
7061
7628
  const node = findVectorNode(state.document.nodes, r.nodeId);
7062
- if (_optionalChain([node, 'optionalAccess', _221 => _221.type]) === "path") paths.push(node);
7629
+ if (_optionalChain([node, 'optionalAccess', _244 => _244.type]) === "path") paths.push(node);
7063
7630
  }
7064
7631
  }
7065
7632
  if (!paths.length) return null;
@@ -7070,7 +7637,7 @@ function getVectorSelectionStyle(state) {
7070
7637
  for (const c of vectorCorners(p.subpaths)) {
7071
7638
  if (anchorMode && !state.selectedAnchors.some((r) => r.nodeId === p.id && r.subpath === c.subpath && r.index === c.index)) continue;
7072
7639
  const corner = p.subpaths[c.subpath].anchors[c.index].corner;
7073
- corners2.push({ radius: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _222 => _222.radius]), () => ( 0)), kind: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _223 => _223.kind]), () => ( "round")) });
7640
+ corners2.push({ radius: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _245 => _245.radius]), () => ( 0)), kind: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _246 => _246.kind]), () => ( "round")) });
7074
7641
  }
7075
7642
  }
7076
7643
  const c0 = _nullishCoalesce(corners2[0], () => ( { radius: 0, kind: "round" }));
@@ -7138,6 +7705,14 @@ var VECTOR_PATH_ACTIONS = [
7138
7705
  { id: "smooth", label: "\u223F", title: "Smooth", enabled: (s, p) => s + p > 0, run: (c) => c.smoothPaths() },
7139
7706
  { id: "outline", label: "\u22A1", title: "Outline Stroke", enabled: (s) => s > 0, run: (c) => c.outlineStroke() }
7140
7707
  ];
7708
+ var VECTOR_PATHFINDER_ACTIONS = [
7709
+ { id: "divide", label: "\u229E", title: "Divide", min: 1 },
7710
+ { id: "trim", label: "\u29C9", title: "Trim", min: 2 },
7711
+ { id: "merge", label: "\u29C8", title: "Merge", min: 2 },
7712
+ { id: "crop", label: "\u2317", title: "Crop", min: 2 },
7713
+ { id: "outline", label: "\u2B1A", title: "Outline", min: 1 },
7714
+ { id: "minusBack", label: "\u2296", title: "Minus Back", min: 2 }
7715
+ ];
7141
7716
  var VECTOR_EDIT_TOGGLES = [
7142
7717
  { key: "keepShapeOnDelete", label: "Keep", title: "Keep shape when deleting points" },
7143
7718
  { key: "curvatureMoves", label: "Curv", title: "Curvature point moves (Alt flips while dragging)" },
@@ -7210,17 +7785,17 @@ function createVectorCommands(controller, options = {}) {
7210
7785
  const base = { group, ...options.scope ? { scope: options.scope } : {} };
7211
7786
  const hasSelection = () => controller.getState().selection.length ? true : "Nothing is selected.";
7212
7787
  const ids = (params) => {
7213
- const list2 = _nullishCoalesce(_optionalChain([params, 'optionalAccess', _224 => _224.ids]), () => ( controller.getState().selection));
7788
+ const list2 = _nullishCoalesce(_optionalChain([params, 'optionalAccess', _247 => _247.ids]), () => ( controller.getState().selection));
7214
7789
  for (const id of list2) if (!controller.getNode(id)) fail(`There is no node "${id}".`);
7215
7790
  if (!list2.length) fail("Nothing is selected; pass ids.");
7216
7791
  return list2;
7217
7792
  };
7218
- const enabledFor = (_, params) => _optionalChain([params, 'optionalAccess', _225 => _225.ids, 'optionalAccess', _226 => _226.length]) ? true : hasSelection();
7793
+ const enabledFor = (_, params) => _optionalChain([params, 'optionalAccess', _248 => _248.ids, 'optionalAccess', _249 => _249.length]) ? true : hasSelection();
7219
7794
  const anchorsOf = (refs) => {
7220
7795
  if (!refs) return [...controller.getState().selectedAnchors];
7221
7796
  for (const r of refs) {
7222
7797
  const node = controller.getNode(r.nodeId);
7223
- if (_optionalChain([node, 'optionalAccess', _227 => _227.type]) !== "path" || !_optionalChain([node, 'access', _228 => _228.subpaths, 'access', _229 => _229[r.subpath], 'optionalAccess', _230 => _230.anchors, 'access', _231 => _231[r.index]])) fail(`There is no anchor ${r.index} on subpath ${r.subpath} of "${r.nodeId}".`);
7798
+ if (_optionalChain([node, 'optionalAccess', _250 => _250.type]) !== "path" || !_optionalChain([node, 'access', _251 => _251.subpaths, 'access', _252 => _252[r.subpath], 'optionalAccess', _253 => _253.anchors, 'access', _254 => _254[r.index]])) fail(`There is no anchor ${r.index} on subpath ${r.subpath} of "${r.nodeId}".`);
7224
7799
  }
7225
7800
  return refs;
7226
7801
  };
@@ -7311,7 +7886,7 @@ function createVectorCommands(controller, options = {}) {
7311
7886
  run: (_ctx, params) => {
7312
7887
  const id = controller.addPath(params.d, { ...pickStyle(params), ...params.name ? { name: params.name } : {} });
7313
7888
  const node = controller.getNode(id);
7314
- if (_optionalChain([node, 'optionalAccess', _232 => _232.type]) === "path" && !node.subpaths.length) {
7889
+ if (_optionalChain([node, 'optionalAccess', _255 => _255.type]) === "path" && !node.subpaths.length) {
7315
7890
  controller.undo();
7316
7891
  fail("The path data has no points.");
7317
7892
  }
@@ -7343,10 +7918,10 @@ function createVectorCommands(controller, options = {}) {
7343
7918
  params: { type: "object", properties: { radius: { type: "number", minimum: 0 }, kind: { type: "string", enum: VECTOR_CORNER_KINDS }, ids: IDS, anchors: ANCHORS } },
7344
7919
  undoable: true,
7345
7920
  run: (_ctx, params) => {
7346
- const refs = _optionalChain([params, 'optionalAccess', _233 => _233.anchors]) ? anchorsOf(params.anchors) : void 0;
7347
- const target = { refs, ids: _optionalChain([params, 'optionalAccess', _234 => _234.ids]) ? ids(params) : void 0 };
7348
- if (_optionalChain([params, 'optionalAccess', _235 => _235.radius]) !== void 0) check(controller.setCornerRadius(params.radius, { ...target, kind: params.kind }));
7349
- else if (_optionalChain([params, 'optionalAccess', _236 => _236.kind])) check(controller.setCornerKind(params.kind, target));
7921
+ const refs = _optionalChain([params, 'optionalAccess', _256 => _256.anchors]) ? anchorsOf(params.anchors) : void 0;
7922
+ const target = { refs, ids: _optionalChain([params, 'optionalAccess', _257 => _257.ids]) ? ids(params) : void 0 };
7923
+ if (_optionalChain([params, 'optionalAccess', _258 => _258.radius]) !== void 0) check(controller.setCornerRadius(params.radius, { ...target, kind: params.kind }));
7924
+ else if (_optionalChain([params, 'optionalAccess', _259 => _259.kind])) check(controller.setCornerKind(params.kind, target));
7350
7925
  else fail("Pass `radius` and / or `kind`.");
7351
7926
  return { ok: true };
7352
7927
  }
@@ -7381,12 +7956,12 @@ function createVectorCommands(controller, options = {}) {
7381
7956
  undoable: true,
7382
7957
  run: (_ctx, params) => {
7383
7958
  const target = { ids: ids(params) };
7384
- if (_optionalChain([params, 'optionalAccess', _237 => _237.preset])) check(controller.setWidthProfile(params.preset, target));
7385
- else if (_optionalChain([params, 'optionalAccess', _238 => _238.points]) !== void 0) check(controller.setWidthProfile(_nullishCoalesce(params.points, () => ( null)), target));
7386
- else if (_optionalChain([params, 'optionalAccess', _239 => _239.taper]) || _optionalChain([params, 'optionalAccess', _240 => _240.wave])) check(controller.setWidthProfile({ taper: params.taper, wave: params.wave }, target));
7959
+ if (_optionalChain([params, 'optionalAccess', _260 => _260.preset])) check(controller.setWidthProfile(params.preset, target));
7960
+ else if (_optionalChain([params, 'optionalAccess', _261 => _261.points]) !== void 0) check(controller.setWidthProfile(_nullishCoalesce(params.points, () => ( null)), target));
7961
+ else if (_optionalChain([params, 'optionalAccess', _262 => _262.taper]) || _optionalChain([params, 'optionalAccess', _263 => _263.wave])) check(controller.setWidthProfile({ taper: params.taper, wave: params.wave }, target));
7387
7962
  else fail("Pass `preset`, `points`, `taper` or `wave`.");
7388
7963
  const node = controller.getNode(target.ids[0]);
7389
- return { ok: true, points: _optionalChain([node, 'optionalAccess', _241 => _241.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
7964
+ return { ok: true, points: _optionalChain([node, 'optionalAccess', _264 => _264.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
7390
7965
  }
7391
7966
  },
7392
7967
  {
@@ -7399,7 +7974,7 @@ function createVectorCommands(controller, options = {}) {
7399
7974
  enabled: enabledFor,
7400
7975
  undoable: true,
7401
7976
  run: (_ctx, params) => {
7402
- const created = controller.outlineStroke({ ids: _optionalChain([params, 'optionalAccess', _242 => _242.ids]) ? ids(params) : void 0 });
7977
+ const created = controller.outlineStroke({ ids: _optionalChain([params, 'optionalAccess', _265 => _265.ids]) ? ids(params) : void 0 });
7403
7978
  if (!created.length) fail("No selected path has a stroke.");
7404
7979
  return { ids: created };
7405
7980
  }
@@ -7461,6 +8036,62 @@ function createVectorCommands(controller, options = {}) {
7461
8036
  return { id };
7462
8037
  }
7463
8038
  },
8039
+ {
8040
+ ...base,
8041
+ id: `${prefix}pathfinder`,
8042
+ label: "Pathfinder\u2026",
8043
+ keywords: ["divide", "trim", "merge", "crop", "outline", "minus back", "split", "faces"],
8044
+ description: "Pathfinder over the given paths (bottom to top): divide (every face its own shape, painted like the top-most shape over it; open unfilled paths cut), trim (hidden parts removed), merge (trim, then touching parts of one fill joined), crop (the top shape crops the others), outline (outlines cut into open strokes where they meet) or minusBack (the top shape minus everything below). Results replace the paths, grouped when there are several.",
8045
+ params: { type: "object", properties: { operation: { type: "string", enum: [...VECTOR_PATHFINDER_OPERATIONS] }, ids: IDS }, required: ["operation"] },
8046
+ undoable: true,
8047
+ run: (_ctx, params) => {
8048
+ if (!VECTOR_PATHFINDER_OPERATIONS.includes(params.operation)) fail(`Unknown Pathfinder operation "${params.operation}".`);
8049
+ const created = controller.pathfinder(params.operation, { ids: ids(params) });
8050
+ if (!created.length) fail("Nothing came out: select paths that overlap (two or more, except for divide and outline).");
8051
+ return { ids: created, selection: [...controller.getState().selection] };
8052
+ }
8053
+ },
8054
+ {
8055
+ ...base,
8056
+ id: `${prefix}shapeBuilderFaces`,
8057
+ label: "List Shape Builder Faces",
8058
+ keywords: ["shape builder", "regions", "faces", "planar"],
8059
+ description: "Lists the faces the given paths divide the plane into: path data, area, a point inside and the ids of the paths filling each (empty when only outlines enclose it).",
8060
+ params: { type: "object", properties: { ids: IDS } },
8061
+ run: (_ctx, params) => ({ faces: controller.getShapeBuilderFaces({ ids: ids(params) }) })
8062
+ },
8063
+ {
8064
+ ...base,
8065
+ id: `${prefix}shapeBuilder`,
8066
+ label: "Shape Builder",
8067
+ keywords: ["merge faces", "build shape", "combine regions", "delete region"],
8068
+ description: "Shape Builder gesture over the faces of the given paths: `points` is the pointer path in document units (one point is a click; [[x, y], \u2026]; use the points from shapeBuilderFaces). Merges the faces it touches into one shape, or with `erase: true` deletes them, the pieces of unfilled open paths and the edges of other outlines (cut where paths meet) within `tolerance`; a deleted edge opens its path there, and edges bounding a deleted face go with it. Shapes covering those faces lose that area. Returns the counts of faces, line pieces and edges.",
8069
+ params: {
8070
+ type: "object",
8071
+ properties: { points: POINTS, erase: { type: "boolean" }, tolerance: { type: "number", minimum: 0 }, ids: IDS },
8072
+ required: ["points"]
8073
+ },
8074
+ undoable: true,
8075
+ run: (_ctx, params) => {
8076
+ const result = controller.shapeBuilder(params.points.map(([x, y]) => ({ x, y })), { ids: ids(params), erase: params.erase, tolerance: params.tolerance });
8077
+ check(result);
8078
+ return { merged: result.merged, faces: result.faces, lines: result.lines, edges: result.edges };
8079
+ }
8080
+ },
8081
+ {
8082
+ ...base,
8083
+ id: `${prefix}fillRegion`,
8084
+ label: "Fill Region",
8085
+ keywords: ["paint bucket", "live paint", "fill area", "enclosed"],
8086
+ description: "Paint bucket: fills the area the visible outlines enclose around `point` (crossings split, nested shapes left as holes) with a new path in the current fill, below the selection or on top. `gap` closes gaps up to that size between loose ends.",
8087
+ params: { type: "object", properties: { point: { type: "array", items: { type: "number" }, minItems: 2, maxItems: 2, description: "[x, y] in document units." }, gap: { type: "number", minimum: 0 } }, required: ["point"] },
8088
+ undoable: true,
8089
+ run: (_ctx, params) => {
8090
+ const id = controller.fillRegion({ x: params.point[0], y: params.point[1] }, { gap: params.gap });
8091
+ if (!id) fail("No closed region surrounds that point.");
8092
+ return { id };
8093
+ }
8094
+ },
7464
8095
  {
7465
8096
  ...base,
7466
8097
  id: `${prefix}align`,
@@ -7514,7 +8145,7 @@ function createVectorCommands(controller, options = {}) {
7514
8145
  enabled: enabledFor,
7515
8146
  undoable: true,
7516
8147
  run: (_ctx, params) => {
7517
- const id = controller.group({ ids: ids(params), name: _optionalChain([params, 'optionalAccess', _243 => _243.name]) });
8148
+ const id = controller.group({ ids: ids(params), name: _optionalChain([params, 'optionalAccess', _266 => _266.name]) });
7518
8149
  if (!id) fail("Only nodes that share a parent can be grouped.");
7519
8150
  return { id };
7520
8151
  }
@@ -7542,7 +8173,7 @@ function createVectorCommands(controller, options = {}) {
7542
8173
  params: { type: "object", properties: { anchors: ANCHORS, keepShape: { type: "boolean" } } },
7543
8174
  undoable: true,
7544
8175
  run: (_ctx, params) => {
7545
- check(controller.deleteAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _244 => _244.anchors])), { keepShape: _optionalChain([params, 'optionalAccess', _245 => _245.keepShape]) }));
8176
+ check(controller.deleteAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _267 => _267.anchors])), { keepShape: _optionalChain([params, 'optionalAccess', _268 => _268.keepShape]) }));
7546
8177
  return { ok: true };
7547
8178
  }
7548
8179
  },
@@ -7597,7 +8228,7 @@ function createVectorCommands(controller, options = {}) {
7597
8228
  params: { type: "object", properties: { ids: IDS, tolerance: { type: "number", minimum: 0 } } },
7598
8229
  undoable: true,
7599
8230
  run: (_ctx, params) => {
7600
- check(controller.joinPaths({ ids: _optionalChain([params, 'optionalAccess', _246 => _246.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _247 => _247.tolerance]) }));
8231
+ check(controller.joinPaths({ ids: _optionalChain([params, 'optionalAccess', _269 => _269.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _270 => _270.tolerance]) }));
7601
8232
  return { selection: controller.getState().selection };
7602
8233
  }
7603
8234
  },
@@ -7611,7 +8242,7 @@ function createVectorCommands(controller, options = {}) {
7611
8242
  params: { type: "object", properties: { axis: { type: "string", enum: ["horizontal", "vertical", "both"] }, anchors: ANCHORS } },
7612
8243
  undoable: true,
7613
8244
  run: (_ctx, params) => {
7614
- check(controller.averageAnchors(_nullishCoalesce(_optionalChain([params, 'optionalAccess', _248 => _248.axis]), () => ( "both")), anchorsOf(_optionalChain([params, 'optionalAccess', _249 => _249.anchors]))));
8245
+ check(controller.averageAnchors(_nullishCoalesce(_optionalChain([params, 'optionalAccess', _271 => _271.axis]), () => ( "both")), anchorsOf(_optionalChain([params, 'optionalAccess', _272 => _272.anchors]))));
7615
8246
  return { ok: true };
7616
8247
  }
7617
8248
  },
@@ -7625,7 +8256,7 @@ function createVectorCommands(controller, options = {}) {
7625
8256
  enabled: enabledFor,
7626
8257
  undoable: true,
7627
8258
  run: (_ctx, params) => {
7628
- check(controller.removeRedundantPoints({ ids: _optionalChain([params, 'optionalAccess', _250 => _250.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _251 => _251.tolerance]) }));
8259
+ check(controller.removeRedundantPoints({ ids: _optionalChain([params, 'optionalAccess', _273 => _273.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _274 => _274.tolerance]) }));
7629
8260
  return { ok: true };
7630
8261
  }
7631
8262
  },
@@ -7638,7 +8269,7 @@ function createVectorCommands(controller, options = {}) {
7638
8269
  params: { type: "object", properties: { ids: IDS, amount: { type: "number", minimum: 0, maximum: 1 }, anchors: ANCHORS } },
7639
8270
  undoable: true,
7640
8271
  run: (_ctx, params) => {
7641
- check(controller.smoothPaths({ ids: _optionalChain([params, 'optionalAccess', _252 => _252.ids]) ? ids(params) : void 0, amount: _optionalChain([params, 'optionalAccess', _253 => _253.amount]), refs: _optionalChain([params, 'optionalAccess', _254 => _254.anchors]) }));
8272
+ check(controller.smoothPaths({ ids: _optionalChain([params, 'optionalAccess', _275 => _275.ids]) ? ids(params) : void 0, amount: _optionalChain([params, 'optionalAccess', _276 => _276.amount]), refs: _optionalChain([params, 'optionalAccess', _277 => _277.anchors]) }));
7642
8273
  return { ok: true };
7643
8274
  }
7644
8275
  },
@@ -7651,14 +8282,14 @@ function createVectorCommands(controller, options = {}) {
7651
8282
  params: { type: "object", properties: { nodeId: { type: "string" }, x: { type: "number" }, y: { type: "number" }, anchors: ANCHORS } },
7652
8283
  undoable: true,
7653
8284
  run: (_ctx, params) => {
7654
- if (_optionalChain([params, 'optionalAccess', _255 => _255.nodeId]) !== void 0) {
8285
+ if (_optionalChain([params, 'optionalAccess', _278 => _278.nodeId]) !== void 0) {
7655
8286
  if (!controller.getNode(params.nodeId)) fail(`There is no node "${params.nodeId}".`);
7656
8287
  if (params.x === void 0 || params.y === void 0) fail("Pass x and y with nodeId.");
7657
8288
  const created = controller.cutPathAt(params.nodeId, { x: params.x, y: params.y });
7658
8289
  if (!created) fail("Nothing to cut there (the end of an open path, or a locked path).");
7659
8290
  return { ids: created };
7660
8291
  }
7661
- check(controller.cutAtAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _256 => _256.anchors]))));
8292
+ check(controller.cutAtAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _279 => _279.anchors]))));
7662
8293
  return { ids: controller.getState().selection };
7663
8294
  }
7664
8295
  },
@@ -7709,7 +8340,7 @@ function createVectorCommands(controller, options = {}) {
7709
8340
  },
7710
8341
  run: (_ctx, params) => {
7711
8342
  const patch = {};
7712
- for (const key of ["keepShapeOnDelete", "curvatureMoves", "pencilSmoothing", "recognizeShapes", "eraserSize", "pencilPressure"]) if (_optionalChain([params, 'optionalAccess', _257 => _257[key]]) !== void 0) patch[key] = params[key];
8343
+ for (const key of ["keepShapeOnDelete", "curvatureMoves", "pencilSmoothing", "recognizeShapes", "eraserSize", "pencilPressure"]) if (_optionalChain([params, 'optionalAccess', _280 => _280[key]]) !== void 0) patch[key] = params[key];
7713
8344
  controller.setEditing(patch);
7714
8345
  return { editing: controller.getState().editing };
7715
8346
  }
@@ -7734,7 +8365,7 @@ function createVectorCommands(controller, options = {}) {
7734
8365
  keywords: ["download", "save", "markup"],
7735
8366
  description: "Returns the document as SVG markup.",
7736
8367
  params: { type: "object", properties: { precision: { type: "integer", minimum: 0, maximum: 8 } } },
7737
- run: (_ctx, params) => ({ svg: controller.toSvg({ precision: _optionalChain([params, 'optionalAccess', _258 => _258.precision]) }) })
8368
+ run: (_ctx, params) => ({ svg: controller.toSvg({ precision: _optionalChain([params, 'optionalAccess', _281 => _281.precision]) }) })
7738
8369
  },
7739
8370
  {
7740
8371
  ...base,
@@ -7932,5 +8563,21 @@ function createVectorCommands(controller, options = {}) {
7932
8563
 
7933
8564
 
7934
8565
 
7935
- exports.DEFAULT_VECTOR_PATH_EDIT = DEFAULT_VECTOR_PATH_EDIT; exports.DEFAULT_VECTOR_SNAP = DEFAULT_VECTOR_SNAP; exports.IDENTITY_MATRIX = IDENTITY_MATRIX; exports.KAPPA = KAPPA2; exports.LazyMouse = LazyMouse; exports.VECTOR_ARROWHEADS = VECTOR_ARROWHEADS; exports.VECTOR_ARROWHEAD_LABELS = VECTOR_ARROWHEAD_LABELS; exports.VECTOR_CLIPBOARD_TYPE = VECTOR_CLIPBOARD_TYPE; exports.VECTOR_CONSTRUCTION_ANGLES = VECTOR_CONSTRUCTION_ANGLES; exports.VECTOR_CORNER_KINDS = VECTOR_CORNER_KINDS; exports.VECTOR_CORNER_KIND_LABELS = VECTOR_CORNER_KIND_LABELS; exports.VECTOR_CORNER_WIDGET_INSET = VECTOR_CORNER_WIDGET_INSET; exports.VECTOR_EDIT_TOGGLES = VECTOR_EDIT_TOGGLES; exports.VECTOR_INK_MAX_CORNERS = VECTOR_INK_MAX_CORNERS; exports.VECTOR_OVERLAY_THEME = VECTOR_OVERLAY_THEME; exports.VECTOR_PATH_ACTIONS = VECTOR_PATH_ACTIONS; exports.VECTOR_PENCIL_STRING_PX = VECTOR_PENCIL_STRING_PX; exports.VECTOR_PRESSURE_NOMINAL = VECTOR_PRESSURE_NOMINAL; exports.VECTOR_ROTATE_HANDLE_OFFSET = VECTOR_ROTATE_HANDLE_OFFSET; exports.VECTOR_STROKE_ALIGN_LABELS = VECTOR_STROKE_ALIGN_LABELS; exports.VECTOR_STYLE_KEYS = VECTOR_STYLE_KEYS; exports.VECTOR_TOOLS = VECTOR_TOOLS; exports.VECTOR_TOOL_GLYPHS = VECTOR_TOOL_GLYPHS; exports.VECTOR_TOOL_SHORTCUTS = VECTOR_TOOL_SHORTCUTS; exports.VECTOR_TRANSFORM_HANDLES = VECTOR_TRANSFORM_HANDLES; exports.VECTOR_WIDTH_PRESETS = VECTOR_WIDTH_PRESETS; exports.VECTOR_WIDTH_PRESET_IDS = VECTOR_WIDTH_PRESET_IDS; exports.VECTOR_WIDTH_PROFILE_MAX_POINTS = VECTOR_WIDTH_PROFILE_MAX_POINTS; exports.VECTOR_WIDTH_PROFILE_MAX_SCALE = VECTOR_WIDTH_PROFILE_MAX_SCALE; exports.VECTOR_WIDTH_SAME_T = VECTOR_WIDTH_SAME_T; exports.VectorEditorController = VectorEditorController; exports.VectorSnapTargets = VectorSnapTargets; exports.applyMatrix = applyMatrix; exports.applyMatrixLinear = applyMatrixLinear; exports.applyVectorCornersAttribute = applyVectorCornersAttribute; exports.arrowheadInset = arrowheadInset; exports.arrowheadPath = arrowheadPath; exports.arrowheadWeight = arrowheadWeight; exports.bendSegment = bendSegment; exports.bezierToSubpaths = bezierToSubpaths; exports.boundsFromPoints = boundsFromPoints; exports.boundsIntersect = boundsIntersect; exports.cloneAnchor = cloneAnchor; exports.cloneSubpath = cloneSubpath; exports.cloneVectorDocument = cloneVectorDocument; exports.cloneVectorNode = cloneVectorNode; exports.collectPathNodes = collectPathNodes; exports.constrainToLeave = constrainToLeave; exports.convertAnchor = convertAnchor; exports.cornerBisectorPoint = cornerBisectorPoint; exports.cornerRadiusChange = cornerRadiusChange; exports.cornerSetback = cornerSetback; exports.createVectorCommands = createVectorCommands; exports.curvatureMoveAnchor = curvatureMoveAnchor; exports.cutSubpathAt = cutSubpathAt; exports.dashIntervals = dashIntervals; exports.decomposeRigid = decomposeRigid; exports.effectiveStrokeAlign = effectiveStrokeAlign; exports.ellipseSubpath = ellipseSubpath; exports.eraseFromFill = eraseFromFill; exports.eraseFromOutline = eraseFromOutline; exports.eraserRegion = eraserRegion; exports.expandVectorCorners = expandVectorCorners; exports.expandVectorCornersOf = expandVectorCornersOf; exports.findVectorNode = findVectorNode; exports.fitCornerRadius = fitCornerRadius; exports.generateWidthProfile = generateWidthProfile; exports.getAnchor = getAnchor; exports.getAnchorWorld = getAnchorWorld; exports.getEditablePathIds = getEditablePathIds; exports.getTransformHandlePositions = getTransformHandlePositions; exports.getVectorCornerWidgets = getVectorCornerWidgets; exports.getVectorOverlayRenderData = getVectorOverlayRenderData; exports.getVectorSceneRenderData = getVectorSceneRenderData; exports.getVectorSelectionBoxGeometry = getVectorSelectionBoxGeometry; exports.getVectorSelectionFrame = getVectorSelectionFrame; exports.getVectorSelectionStyle = getVectorSelectionStyle; exports.getVectorWidthHandles = getVectorWidthHandles; exports.getVisibleAnchors = getVisibleAnchors; exports.getVisibleHandles = getVisibleHandles; exports.hasPaint = hasPaint; exports.hasStrokeExtras = hasStrokeExtras; exports.hasVectorCorners = hasVectorCorners; exports.hitTestVectorNode = hitTestVectorNode; exports.hitTestVectorNodes = hitTestVectorNodes; exports.hitTestVectorStroke = hitTestVectorStroke; exports.inferAnchorType = inferAnchorType; exports.insertAnchor = insertAnchor; exports.insertWidthPoint = insertWidthPoint; exports.invertMatrix = invertMatrix; exports.isClosedBezierShape = isClosedBezierShape; exports.isIdentityMatrix = isIdentityMatrix; exports.isUniformWidthProfile = isUniformWidthProfile; exports.isVectorTextTarget = isVectorTextTarget; exports.joinSubpaths = joinSubpaths; exports.knifePath = knifePath; exports.lineSubpath = lineSubpath; exports.locateVectorNode = locateVectorNode; exports.matrixRotation = matrixRotation; exports.mirrorWidthProfile = mirrorWidthProfile; exports.moveAnchorHandle = moveAnchorHandle; exports.multiplyMatrices = multiplyMatrices; exports.nearestSegment = nearestSegment; exports.nearestStrokePosition = nearestStrokePosition; exports.nextVectorCornerKind = nextVectorCornerKind; exports.nodeMatrix = nodeMatrix; exports.parseSvgTransform = parseSvgTransform; exports.parseVectorSvg = parseVectorSvg; exports.polygonSubpath = polygonSubpath; exports.polylineBounds = polylineBounds; exports.pressureWidthProfile = pressureWidthProfile; exports.recognizeInkShape = recognizeInkShape; exports.rectSubpath = rectSubpath; exports.removeAnchorKeepingShape = removeAnchorKeepingShape; exports.removeAnchors = removeAnchors; exports.removeAnchorsKeepingShape = removeAnchorsKeepingShape; exports.removeRedundantPoints = removeRedundantPoints; exports.removeWidthPoints = removeWidthPoints; exports.reverseSubpath = reverseSubpath; exports.reverseWidthProfile = reverseWidthProfile; exports.rotateMatrix = rotateMatrix; exports.roundSubpaths = roundSubpaths; exports.sanitizeWidthProfile = sanitizeWidthProfile; exports.scaleFor = scaleFor; exports.scaleMatrix = scaleMatrix; exports.setAnchorCorner = setAnchorCorner; exports.setSubpathCorners = setSubpathCorners; exports.setWidthPoint = setWidthPoint; exports.simplifyPolyline = simplifyPolyline; exports.smoothSubpath = smoothSubpath; exports.splitIntoFaces = splitIntoFaces; exports.splitSubpathAt = splitSubpathAt; exports.starSubpath = starSubpath; exports.strokePositionPoint = strokePositionPoint; exports.strokeWidthProfileOf = strokeWidthProfileOf; exports.subpathPointAt = subpathPointAt; exports.subpathSegment = subpathSegment; exports.subpathSegmentCount = subpathSegmentCount; exports.subpathsToBezier = subpathsToBezier; exports.taperWaveFactor = taperWaveFactor; exports.toVectorKeyInput = toVectorKeyInput; exports.toVectorModifiers = toVectorModifiers; exports.toVectorPointerInput = toVectorPointerInput; exports.transformVectorNode = transformVectorNode; exports.translateAnchor = translateAnchor; exports.translateMatrix = translateMatrix; exports.unionBounds = unionBounds; exports.variableStrokeOutline = variableStrokeOutline; exports.variableStrokeRings = variableStrokeRings; exports.vectorCornerAt = vectorCornerAt; exports.vectorCorners = vectorCorners; exports.vectorCornersAttribute = vectorCornersAttribute; exports.vectorDiamondPath = vectorDiamondPath; exports.vectorDocumentToSvg = vectorDocumentToSvg; exports.vectorInkShapeName = vectorInkShapeName; exports.vectorNodeBounds = vectorNodeBounds; exports.vectorNodeRotation = vectorNodeRotation; exports.vectorNodeToBezier = vectorNodeToBezier; exports.vectorPaintToHex = vectorPaintToHex; exports.vectorPaintToSvg = vectorPaintToSvg; exports.vectorParentMatrix = vectorParentMatrix; exports.vectorPathData = vectorPathData; exports.vectorPathWorldBezier = vectorPathWorldBezier; exports.vectorResizeCursor = vectorResizeCursor; exports.vectorStrokeLineArea = vectorStrokeLineArea; exports.vectorStrokeOutline = vectorStrokeOutline; exports.vectorStrokeOutlinePath = vectorStrokeOutlinePath; exports.vectorStrokeParts = vectorStrokeParts; exports.vectorStrokeReach = vectorStrokeReach; exports.vectorStrokeSvgParts = vectorStrokeSvgParts; exports.vectorStrokeWidthGeometry = vectorStrokeWidthGeometry; exports.vectorToolLabel = vectorToolLabel; exports.vectorWorldMatrix = vectorWorldMatrix; exports.walkVectorNodes = walkVectorNodes; exports.widthProfileAt = widthProfileAt; exports.widthProfileFromAttribute = widthProfileFromAttribute; exports.widthProfileMaxScale = widthProfileMaxScale; exports.widthProfilePreset = widthProfilePreset; exports.widthProfilePresetId = widthProfilePresetId; exports.widthProfileToAttribute = widthProfileToAttribute;
8566
+
8567
+
8568
+
8569
+
8570
+
8571
+
8572
+
8573
+
8574
+
8575
+
8576
+
8577
+
8578
+
8579
+
8580
+
8581
+
8582
+ exports.DEFAULT_VECTOR_PATH_EDIT = DEFAULT_VECTOR_PATH_EDIT; exports.DEFAULT_VECTOR_SNAP = DEFAULT_VECTOR_SNAP; exports.IDENTITY_MATRIX = IDENTITY_MATRIX; exports.KAPPA = KAPPA2; exports.LazyMouse = LazyMouse; exports.VECTOR_ARROWHEADS = VECTOR_ARROWHEADS; exports.VECTOR_ARROWHEAD_LABELS = VECTOR_ARROWHEAD_LABELS; exports.VECTOR_BUILDER_HATCH_GAP = VECTOR_BUILDER_HATCH_GAP; exports.VECTOR_CLIPBOARD_TYPE = VECTOR_CLIPBOARD_TYPE; exports.VECTOR_CONSTRUCTION_ANGLES = VECTOR_CONSTRUCTION_ANGLES; exports.VECTOR_CORNER_KINDS = VECTOR_CORNER_KINDS; exports.VECTOR_CORNER_KIND_LABELS = VECTOR_CORNER_KIND_LABELS; exports.VECTOR_CORNER_WIDGET_INSET = VECTOR_CORNER_WIDGET_INSET; exports.VECTOR_EDIT_TOGGLES = VECTOR_EDIT_TOGGLES; exports.VECTOR_FILL_GAP = VECTOR_FILL_GAP; exports.VECTOR_INK_MAX_CORNERS = VECTOR_INK_MAX_CORNERS; exports.VECTOR_OVERLAY_THEME = VECTOR_OVERLAY_THEME; exports.VECTOR_PATHFINDER_ACTIONS = VECTOR_PATHFINDER_ACTIONS; exports.VECTOR_PATHFINDER_LABELS = VECTOR_PATHFINDER_LABELS; exports.VECTOR_PATHFINDER_OPERATIONS = VECTOR_PATHFINDER_OPERATIONS; exports.VECTOR_PATH_ACTIONS = VECTOR_PATH_ACTIONS; exports.VECTOR_PENCIL_STRING_PX = VECTOR_PENCIL_STRING_PX; exports.VECTOR_PRESSURE_NOMINAL = VECTOR_PRESSURE_NOMINAL; exports.VECTOR_ROTATE_HANDLE_OFFSET = VECTOR_ROTATE_HANDLE_OFFSET; exports.VECTOR_STROKE_ALIGN_LABELS = VECTOR_STROKE_ALIGN_LABELS; exports.VECTOR_STYLE_KEYS = VECTOR_STYLE_KEYS; exports.VECTOR_TOOLS = VECTOR_TOOLS; exports.VECTOR_TOOL_GLYPHS = VECTOR_TOOL_GLYPHS; exports.VECTOR_TOOL_SHORTCUTS = VECTOR_TOOL_SHORTCUTS; exports.VECTOR_TRANSFORM_HANDLES = VECTOR_TRANSFORM_HANDLES; exports.VECTOR_WIDTH_PRESETS = VECTOR_WIDTH_PRESETS; exports.VECTOR_WIDTH_PRESET_IDS = VECTOR_WIDTH_PRESET_IDS; exports.VECTOR_WIDTH_PROFILE_MAX_POINTS = VECTOR_WIDTH_PROFILE_MAX_POINTS; exports.VECTOR_WIDTH_PROFILE_MAX_SCALE = VECTOR_WIDTH_PROFILE_MAX_SCALE; exports.VECTOR_WIDTH_SAME_T = VECTOR_WIDTH_SAME_T; exports.VectorEditorController = VectorEditorController; exports.VectorSnapTargets = VectorSnapTargets; exports.addBuilderHit = addBuilderHit; exports.applyMatrix = applyMatrix; exports.applyMatrixLinear = applyMatrixLinear; exports.applyVectorCornersAttribute = applyVectorCornersAttribute; exports.arrowheadInset = arrowheadInset; exports.arrowheadPath = arrowheadPath; exports.arrowheadWeight = arrowheadWeight; exports.bendSegment = bendSegment; exports.bezierToSubpaths = bezierToSubpaths; exports.boundsFromPoints = boundsFromPoints; exports.boundsIntersect = boundsIntersect; exports.cloneAnchor = cloneAnchor; exports.cloneSubpath = cloneSubpath; exports.cloneVectorDocument = cloneVectorDocument; exports.cloneVectorNode = cloneVectorNode; exports.collectPathNodes = collectPathNodes; exports.constrainToLeave = constrainToLeave; exports.convertAnchor = convertAnchor; exports.cornerBisectorPoint = cornerBisectorPoint; exports.cornerRadiusChange = cornerRadiusChange; exports.cornerSetback = cornerSetback; exports.createVectorCommands = createVectorCommands; exports.curvatureMoveAnchor = curvatureMoveAnchor; exports.cutSubpathAt = cutSubpathAt; exports.dashIntervals = dashIntervals; exports.decomposeRigid = decomposeRigid; exports.effectiveStrokeAlign = effectiveStrokeAlign; exports.ellipseSubpath = ellipseSubpath; exports.eraseFromFill = eraseFromFill; exports.eraseFromOutline = eraseFromOutline; exports.eraserRegion = eraserRegion; exports.expandVectorCorners = expandVectorCorners; exports.expandVectorCornersOf = expandVectorCornersOf; exports.findVectorNode = findVectorNode; exports.fitCornerRadius = fitCornerRadius; exports.generateWidthProfile = generateWidthProfile; exports.getAnchor = getAnchor; exports.getAnchorWorld = getAnchorWorld; exports.getEditablePathIds = getEditablePathIds; exports.getTransformHandlePositions = getTransformHandlePositions; exports.getVectorCornerWidgets = getVectorCornerWidgets; exports.getVectorOverlayRenderData = getVectorOverlayRenderData; exports.getVectorSceneRenderData = getVectorSceneRenderData; exports.getVectorSelectionBoxGeometry = getVectorSelectionBoxGeometry; exports.getVectorSelectionFrame = getVectorSelectionFrame; exports.getVectorSelectionStyle = getVectorSelectionStyle; exports.getVectorWidthHandles = getVectorWidthHandles; exports.getVisibleAnchors = getVisibleAnchors; exports.getVisibleHandles = getVisibleHandles; exports.hasPaint = hasPaint; exports.hasStrokeExtras = hasStrokeExtras; exports.hasVectorCorners = hasVectorCorners; exports.hitTestVectorNode = hitTestVectorNode; exports.hitTestVectorNodes = hitTestVectorNodes; exports.hitTestVectorStroke = hitTestVectorStroke; exports.inferAnchorType = inferAnchorType; exports.insertAnchor = insertAnchor; exports.insertWidthPoint = insertWidthPoint; exports.invertMatrix = invertMatrix; exports.isClosedBezierShape = isClosedBezierShape; exports.isIdentityMatrix = isIdentityMatrix; exports.isUniformWidthProfile = isUniformWidthProfile; exports.isVectorTextTarget = isVectorTextTarget; exports.joinSubpaths = joinSubpaths; exports.knifePath = knifePath; exports.lineSubpath = lineSubpath; exports.locateVectorNode = locateVectorNode; exports.matrixRotation = matrixRotation; exports.mirrorWidthProfile = mirrorWidthProfile; exports.moveAnchorHandle = moveAnchorHandle; exports.multiplyMatrices = multiplyMatrices; exports.nearestSegment = nearestSegment; exports.nearestStrokePosition = nearestStrokePosition; exports.nextVectorCornerKind = nextVectorCornerKind; exports.nodeMatrix = nodeMatrix; exports.parseSvgTransform = parseSvgTransform; exports.parseVectorSvg = parseVectorSvg; exports.planShapeBuilder = planShapeBuilder; exports.polygonSubpath = polygonSubpath; exports.polylineBounds = polylineBounds; exports.pressureWidthProfile = pressureWidthProfile; exports.recognizeInkShape = recognizeInkShape; exports.rectSubpath = rectSubpath; exports.removeAnchorKeepingShape = removeAnchorKeepingShape; exports.removeAnchors = removeAnchors; exports.removeAnchorsKeepingShape = removeAnchorsKeepingShape; exports.removeRedundantPoints = removeRedundantPoints; exports.removeWidthPoints = removeWidthPoints; exports.reverseSubpath = reverseSubpath; exports.reverseWidthProfile = reverseWidthProfile; exports.rotateMatrix = rotateMatrix; exports.roundSubpaths = roundSubpaths; exports.samplePolyline = samplePolyline; exports.sanitizeWidthProfile = sanitizeWidthProfile; exports.scaleFor = scaleFor; exports.scaleMatrix = scaleMatrix; exports.setAnchorCorner = setAnchorCorner; exports.setSubpathCorners = setSubpathCorners; exports.setWidthPoint = setWidthPoint; exports.simplifyPolyline = simplifyPolyline; exports.smoothSubpath = smoothSubpath; exports.splitIntoFaces = splitIntoFaces; exports.splitSubpathAt = splitSubpathAt; exports.starSubpath = starSubpath; exports.strokePositionPoint = strokePositionPoint; exports.strokeWidthProfileOf = strokeWidthProfileOf; exports.subpathEnclosesArea = subpathEnclosesArea; exports.subpathPointAt = subpathPointAt; exports.subpathSegment = subpathSegment; exports.subpathSegmentCount = subpathSegmentCount; exports.subpathsToBezier = subpathsToBezier; exports.taperWaveFactor = taperWaveFactor; exports.toVectorKeyInput = toVectorKeyInput; exports.toVectorModifiers = toVectorModifiers; exports.toVectorPointerInput = toVectorPointerInput; exports.transformVectorNode = transformVectorNode; exports.translateAnchor = translateAnchor; exports.translateMatrix = translateMatrix; exports.unionBounds = unionBounds; exports.variableStrokeOutline = variableStrokeOutline; exports.variableStrokeRings = variableStrokeRings; exports.vectorBuilderErasedEdges = vectorBuilderErasedEdges; exports.vectorCornerAt = vectorCornerAt; exports.vectorCorners = vectorCorners; exports.vectorCornersAttribute = vectorCornersAttribute; exports.vectorDiamondPath = vectorDiamondPath; exports.vectorDocumentToSvg = vectorDocumentToSvg; exports.vectorFillMap = vectorFillMap; exports.vectorInkShapeName = vectorInkShapeName; exports.vectorNodeBounds = vectorNodeBounds; exports.vectorNodeRotation = vectorNodeRotation; exports.vectorNodeToBezier = vectorNodeToBezier; exports.vectorPaintToHex = vectorPaintToHex; exports.vectorPaintToSvg = vectorPaintToSvg; exports.vectorParentMatrix = vectorParentMatrix; exports.vectorPathData = vectorPathData; exports.vectorPathEntries = vectorPathEntries; exports.vectorPathWorldBezier = vectorPathWorldBezier; exports.vectorPathfinderShape = vectorPathfinderShape; exports.vectorResizeCursor = vectorResizeCursor; exports.vectorResultStyle = vectorResultStyle; exports.vectorShapeBuilderHit = vectorShapeBuilderHit; exports.vectorShapeBuilderMap = vectorShapeBuilderMap; exports.vectorStrokeLineArea = vectorStrokeLineArea; exports.vectorStrokeOutline = vectorStrokeOutline; exports.vectorStrokeOutlinePath = vectorStrokeOutlinePath; exports.vectorStrokeParts = vectorStrokeParts; exports.vectorStrokeReach = vectorStrokeReach; exports.vectorStrokeSvgParts = vectorStrokeSvgParts; exports.vectorStrokeWidthGeometry = vectorStrokeWidthGeometry; exports.vectorToolLabel = vectorToolLabel; exports.vectorWorldMatrix = vectorWorldMatrix; exports.walkVectorNodes = walkVectorNodes; exports.widthProfileAt = widthProfileAt; exports.widthProfileFromAttribute = widthProfileFromAttribute; exports.widthProfileMaxScale = widthProfileMaxScale; exports.widthProfilePreset = widthProfilePreset; exports.widthProfilePresetId = widthProfilePresetId; exports.widthProfileToAttribute = widthProfileToAttribute;
7936
8583
  //# sourceMappingURL=index.cjs.map