@pixerate/editor 0.37.0 → 0.38.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,32 @@ var _chunkQKLRAA4Tcjs = require('../chunk-QKLRAA4T.cjs');
34
34
 
35
35
 
36
36
 
37
- var _chunkGVB7ZPLZcjs = require('../chunk-GVB7ZPLZ.cjs');
37
+
38
+
39
+ var _chunk7EDLVBOOcjs = require('../chunk-7EDLVBOO.cjs');
38
40
 
39
41
  // src/vector/types.ts
40
42
  var VECTOR_CORNER_KINDS = ["round", "inverted", "chamfer"];
41
43
  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"];
44
+ var VECTOR_TOOLS = [
45
+ "select",
46
+ "direct",
47
+ "pen",
48
+ "pencil",
49
+ "rect",
50
+ "ellipse",
51
+ "polygon",
52
+ "star",
53
+ "line",
54
+ "scissors",
55
+ "knife",
56
+ "eraser",
57
+ "width",
58
+ "shapeBuilder",
59
+ "paintBucket"
60
+ ];
43
61
  var VECTOR_TRANSFORM_HANDLES = ["nw", "n", "ne", "e", "se", "s", "sw", "w", "rotate"];
62
+ var VECTOR_PATHFINDER_OPERATIONS = ["divide", "trim", "merge", "crop", "outline", "minusBack"];
44
63
 
45
64
  // src/vector/corners.ts
46
65
  var EPS = 1e-9;
@@ -61,7 +80,7 @@ var Side = class {
61
80
  constructor(a, h1, h2, b) {
62
81
  this.straight = onAnchor(a, h1) && onAnchor(b, h2);
63
82
  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);
83
+ this.length = this.straight ? Math.hypot(b.x - a.x, b.y - a.y) : _chunk7EDLVBOOcjs.segmentLength.call(void 0, this.curve);
65
84
  }
66
85
  /** Unit direction the side leaves the corner in (towards its first control point off the corner). */
67
86
  direction() {
@@ -79,10 +98,10 @@ var Side = class {
79
98
  const t2 = this.length > EPS ? Math.min(1, Math.max(0, s / this.length)) : 0;
80
99
  return { t: t2, p: add(vec(this.curve[0]), mul(u, s)), dir: u };
81
100
  }
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));
101
+ const t = _chunk7EDLVBOOcjs.segmentParamAtLength.call(void 0, this.curve, s, this.length);
102
+ const d = vec(_chunk7EDLVBOOcjs.segmentDerivative.call(void 0, this.curve, t));
84
103
  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 };
104
+ return { t, p: vec(_chunk7EDLVBOOcjs.segmentPoint.call(void 0, this.curve, t)), dir: l > EPS ? mul(d, 1 / l) : u };
86
105
  }
87
106
  };
88
107
  function cornerOf(sp, s, i) {
@@ -155,7 +174,7 @@ function cutCorner(c, radius, kind) {
155
174
  return { tu: a.t, tv: b.t, start: a.p, out: add(a.p, mul(d1, k)), in: add(b.p, mul(d2, k)), end: b.p };
156
175
  }
157
176
  var radiusOf = (a) => {
158
- const r = _optionalChain([a, 'access', _2 => _2.corner, 'optionalAccess', _3 => _3.radius]);
177
+ const r = _optionalChain([a, 'access', _3 => _3.corner, 'optionalAccess', _4 => _4.radius]);
159
178
  return typeof r === "number" && r > 0 && Number.isFinite(r) ? r : 0;
160
179
  };
161
180
  function hasVectorCorners(subpaths) {
@@ -169,7 +188,7 @@ function expandVectorCornersOf(sp, subpath = 0) {
169
188
  const c = cornerOf(sp, subpath, i);
170
189
  if (!c) return null;
171
190
  const fitted = fitCornerRadius(c, r);
172
- return fitted > EPS ? cutCorner(c, fitted, _nullishCoalesce(_optionalChain([a, 'access', _4 => _4.corner, 'optionalAccess', _5 => _5.kind]), () => ( "round"))) : null;
191
+ return fitted > EPS ? cutCorner(c, fitted, _nullishCoalesce(_optionalChain([a, 'access', _5 => _5.corner, 'optionalAccess', _6 => _6.kind]), () => ( "round"))) : null;
173
192
  });
174
193
  if (!cuts.some(Boolean)) return { subpath: { closed: sp.closed, anchors: sp.anchors.map(plain) }, sources: sp.anchors.map((_, i) => i) };
175
194
  const trimmed = sp.anchors.map((a, j) => {
@@ -183,7 +202,7 @@ function expandVectorCornersOf(sp, subpath = 0) {
183
202
  const s0 = from ? from.tv : 0;
184
203
  const s1 = to ? 1 - to.tu : 1;
185
204
  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));
205
+ const part = _chunk7EDLVBOOcjs.subSegment.call(void 0, seg, s0, Math.max(s0, s1));
187
206
  return { out: vec(part[1]), in: vec(part[2]) };
188
207
  });
189
208
  const anchors = [];
@@ -237,7 +256,7 @@ function expandVectorCorners(subpaths) {
237
256
  function setAnchorCorner(a, radius, kind) {
238
257
  const { corner, ...rest } = a;
239
258
  const r = Number.isFinite(radius) ? Math.max(0, radius) : 0;
240
- const k = _nullishCoalesce(kind, () => ( _optionalChain([corner, 'optionalAccess', _6 => _6.kind])));
259
+ const k = _nullishCoalesce(kind, () => ( _optionalChain([corner, 'optionalAccess', _7 => _7.kind])));
241
260
  if (r <= 0 && !kind) return rest;
242
261
  return { ...rest, corner: { radius: r, ...k && k !== "round" ? { kind: k } : {} } };
243
262
  }
@@ -286,7 +305,7 @@ function sanitizeWidthProfile(points) {
286
305
  return out.map((p, i) => [p, i]).sort((a, b) => a[0].t - b[0].t || a[1] - b[1]).map(([p]) => p);
287
306
  }
288
307
  function isUniformWidthProfile(points) {
289
- return !_optionalChain([points, 'optionalAccess', _7 => _7.length]) || points.every((p) => p.left === 1 && p.right === 1);
308
+ return !_optionalChain([points, 'optionalAccess', _8 => _8.length]) || points.every((p) => p.left === 1 && p.right === 1);
290
309
  }
291
310
  function secant(pts, i, k) {
292
311
  const a = pts[i];
@@ -319,11 +338,11 @@ function interp(pts, t, k) {
319
338
  return Math.max(0, w);
320
339
  }
321
340
  function widthProfileAt(points, t) {
322
- if (!_optionalChain([points, 'optionalAccess', _8 => _8.length])) return { left: 1, right: 1 };
341
+ if (!_optionalChain([points, 'optionalAccess', _9 => _9.length])) return { left: 1, right: 1 };
323
342
  return { left: interp(points, t, "left"), right: interp(points, t, "right") };
324
343
  }
325
344
  function widthProfileMaxScale(points) {
326
- if (!_optionalChain([points, 'optionalAccess', _9 => _9.length])) return 1;
345
+ if (!_optionalChain([points, 'optionalAccess', _10 => _10.length])) return 1;
327
346
  return points.reduce((m, p) => Math.max(m, p.left, p.right), 0);
328
347
  }
329
348
  function widthProfilePreset(id) {
@@ -333,7 +352,7 @@ function widthProfilePreset(id) {
333
352
  function widthProfilePresetId(points) {
334
353
  if (isUniformWidthProfile(points)) return "uniform";
335
354
  const same = (a, b) => a.length === b.length && a.every((p, i) => Math.abs(p.t - b[i].t) < 1e-9 && Math.abs(p.left - b[i].left) < 1e-9 && Math.abs(p.right - b[i].right) < 1e-9);
336
- return _nullishCoalesce(_optionalChain([VECTOR_WIDTH_PRESETS, 'access', _10 => _10.find, 'call', _11 => _11((p) => p.points.length && same(points, p.points)), 'optionalAccess', _12 => _12.id]), () => ( "custom"));
355
+ return _nullishCoalesce(_optionalChain([VECTOR_WIDTH_PRESETS, 'access', _11 => _11.find, 'call', _12 => _12((p) => p.points.length && same(points, p.points)), 'optionalAccess', _13 => _13.id]), () => ( "custom"));
337
356
  }
338
357
  function reverseWidthProfile(points) {
339
358
  return points.map((p) => ({ t: 1 - p.t, left: p.right, right: p.left })).reverse();
@@ -342,16 +361,16 @@ function mirrorWidthProfile(points) {
342
361
  return points.map((p) => ({ t: p.t, left: p.right, right: p.left }));
343
362
  }
344
363
  function editable(points) {
345
- return _optionalChain([points, 'optionalAccess', _13 => _13.length]) ? points.map((p) => ({ ...p })) : [sym(0, 1), sym(1, 1)];
364
+ return _optionalChain([points, 'optionalAccess', _14 => _14.length]) ? points.map((p) => ({ ...p })) : [sym(0, 1), sym(1, 1)];
346
365
  }
347
- function insertWidthPoint(points, t, sides = {}, options = {}) {
366
+ function insertWidthPoint(points, t, sides2 = {}, options = {}) {
348
367
  const pts = editable(points);
349
368
  const tt = Math.min(Math.max(Number.isFinite(t) ? t : 0, 0), 1);
350
- const here = widthProfileAt(_optionalChain([points, 'optionalAccess', _14 => _14.length]) ? points : null, tt);
369
+ const here = widthProfileAt(_optionalChain([points, 'optionalAccess', _15 => _15.length]) ? points : null, tt);
351
370
  const p = {
352
371
  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))
372
+ left: _nullishCoalesce(clean(sides2.left, VECTOR_WIDTH_PROFILE_MAX_SCALE), () => ( here.left)),
373
+ right: _nullishCoalesce(clean(sides2.right, VECTOR_WIDTH_PROFILE_MAX_SCALE), () => ( here.right))
355
374
  };
356
375
  const same = pts.findIndex((q) => Math.abs(q.t - tt) <= VECTOR_WIDTH_SAME_T);
357
376
  if (same >= 0 && !options.step) {
@@ -418,7 +437,7 @@ function generateWidthProfile(options) {
418
437
  const n = Math.max(8, Math.min(VECTOR_WIDTH_PROFILE_MAX_POINTS * 4, _nullishCoalesce(options.samples, () => ( Math.ceil(32 + cycles * 16)))));
419
438
  const raw = [];
420
439
  for (let i = 0; i <= n; i++) raw.push([i / n, taperWaveFactor(i / n, options.taper, options.wave)]);
421
- const ts = [_optionalChain([options, 'access', _15 => _15.taper, 'optionalAccess', _16 => _16.startLength]), _optionalChain([options, 'access', _17 => _17.taper, 'optionalAccess', _18 => _18.endLength]) !== void 0 ? 1 - options.taper.endLength : void 0];
440
+ const ts = [_optionalChain([options, 'access', _16 => _16.taper, 'optionalAccess', _17 => _17.startLength]), _optionalChain([options, 'access', _18 => _18.taper, 'optionalAccess', _19 => _19.endLength]) !== void 0 ? 1 - options.taper.endLength : void 0];
422
441
  for (const t of ts) if (typeof t === "number" && t > 0 && t < 1) raw.push([t, taperWaveFactor(t, options.taper, options.wave)]);
423
442
  raw.sort((a, b) => a[0] - b[0]);
424
443
  const kept = simplifySamples(raw, _nullishCoalesce(options.tolerance, () => ( 0.01)), VECTOR_WIDTH_PROFILE_MAX_POINTS);
@@ -486,7 +505,7 @@ function flatten(segments, closed, tol) {
486
505
  corner.push(isCorner);
487
506
  };
488
507
  for (const seg of segments) {
489
- const flat = _chunkGVB7ZPLZcjs.flattenChain.call(void 0, [seg], tol);
508
+ const flat = _chunk7EDLVBOOcjs.flattenChain.call(void 0, [seg], tol);
490
509
  if (dist(seg[0], seg[seg.length - 1]) <= 1e-12 && flat.length > 1) flat.push(seg[seg.length - 1]);
491
510
  flat.forEach((p, i) => push(p, i === 0 || i === flat.length - 1));
492
511
  }
@@ -576,16 +595,16 @@ function variableStrokeRings(path, options) {
576
595
  const last = out[out.length - 1];
577
596
  if (!last || dist(last, p) > 1e-12) out.push(p);
578
597
  };
579
- for (const contour of _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path)) {
598
+ for (const contour of _chunk7EDLVBOOcjs.pathToContours.call(void 0, path)) {
580
599
  if (!contour.segments.length) continue;
581
600
  const poly = flatten(contour.segments, contour.closed, Math.min(tol, half) / 4);
582
601
  if (!poly) continue;
583
602
  const len2 = poly.s[poly.s.length - 1];
584
- const sides = (s) => {
603
+ const sides2 = (s) => {
585
604
  const w = widthProfileAt(options.profile, s / len2);
586
605
  return [w.left * half, w.right * half];
587
606
  };
588
- const intervals = _optionalChain([options, 'access', _19 => _19.dash, 'optionalAccess', _20 => _20.some, 'call', _21 => _21((v2) => v2 > 0)]) ? dashIntervals(options.dash, _nullishCoalesce(options.dashOffset, () => ( 0)), len2) : [[0, len2]];
607
+ const intervals = _optionalChain([options, 'access', _20 => _20.dash, 'optionalAccess', _21 => _21.some, 'call', _22 => _22((v2) => v2 > 0)]) ? dashIntervals(options.dash, _nullishCoalesce(options.dashOffset, () => ( 0)), len2) : [[0, len2]];
589
608
  const whole = intervals.length === 1 && intervals[0][0] <= 0 && intervals[0][1] >= len2;
590
609
  for (const [a, b] of intervals) {
591
610
  const [pa, ia] = at(poly, a);
@@ -595,7 +614,7 @@ function variableStrokeRings(path, options) {
595
614
  pts.push({ p: pb, s: b, corner: false });
596
615
  const run = pts.filter((q, i) => i === 0 || dist(q.p, pts[i - 1].p) > 1e-9);
597
616
  if (run.length < 2) {
598
- const [l, r] = sides(a);
617
+ const [l, r] = sides2(a);
599
618
  const w2 = (l + r) / 2;
600
619
  if (cap === "round" && w2 > 0) rings.push([[pa[0] + w2, pa[1]], ...arcPoints(pa, 0, 2 * Math.PI, w2, w2, tol)]);
601
620
  continue;
@@ -605,7 +624,7 @@ function variableStrokeRings(path, options) {
605
624
  const dirs = [];
606
625
  for (let i = 0; i < m; i++) dirs.push(unitOf(sub2(run[i + 1].p, run[i].p)));
607
626
  const normals = dirs.map(leftNormal);
608
- const w = run.map((q) => sides(q.s));
627
+ const w = run.map((q) => sides2(q.s));
609
628
  const side = (sigma) => {
610
629
  const k = sigma > 0 ? 0 : 1;
611
630
  const S = (i) => along(run[i].p, normals[i], sigma * w[i][k]);
@@ -702,7 +721,7 @@ function variableStrokeOutline(path, options) {
702
721
  const tol = options.tolerance && options.tolerance > 0 ? options.tolerance : 0.05;
703
722
  let polygons;
704
723
  try {
705
- polygons = _chunkGVB7ZPLZcjs.polygonBoolean.call(void 0, "union", [{ rings: pieces, fillRule: "nonzero" }]);
724
+ polygons = _chunk7EDLVBOOcjs.polygonBoolean.call(void 0, "union", [{ rings: pieces, fillRule: "nonzero" }]);
706
725
  } catch (e2) {
707
726
  return [];
708
727
  }
@@ -710,11 +729,11 @@ function variableStrokeOutline(path, options) {
710
729
  for (const polygon2 of polygons) {
711
730
  for (const ring of polygon2) {
712
731
  if (ring.length < 3) continue;
713
- const cubics = _chunkGVB7ZPLZcjs.fitCubics.call(void 0, ring, tol, { closed: true, cornerAngleDeg: 25 });
732
+ const cubics = _chunk7EDLVBOOcjs.fitCubics.call(void 0, ring, tol, { closed: true, cornerAngleDeg: 25 });
714
733
  if (!cubics.length) continue;
715
734
  out.push({ type: "M", x: cubics[0].p0[0], y: cubics[0].p0[1] });
716
735
  cubics.forEach((c, i) => {
717
- if (_chunkGVB7ZPLZcjs.isStraightCubic.call(void 0, c, tol * 0.02)) {
736
+ if (_chunk7EDLVBOOcjs.isStraightCubic.call(void 0, c, tol * 0.02)) {
718
737
  if (i < cubics.length - 1) out.push({ type: "L", x: c.p3[0], y: c.p3[1] });
719
738
  } 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
739
  });
@@ -725,17 +744,17 @@ function variableStrokeOutline(path, options) {
725
744
  }
726
745
  function nearestStrokePosition(path, p, only) {
727
746
  let best = null;
728
- _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path).forEach((c, ci) => {
747
+ _chunk7EDLVBOOcjs.pathToContours.call(void 0, path).forEach((c, ci) => {
729
748
  if (!c.segments.length || only !== void 0 && ci !== only) return;
730
- const lengths = c.segments.map((s) => _chunkGVB7ZPLZcjs.segmentLength.call(void 0, s));
749
+ const lengths = c.segments.map((s) => _chunk7EDLVBOOcjs.segmentLength.call(void 0, s));
731
750
  const total = lengths.reduce((a, b) => a + b, 0);
732
751
  if (!(total > 0)) return;
733
752
  let acc = 0;
734
753
  c.segments.forEach((seg, si) => {
735
- const near2 = _chunkGVB7ZPLZcjs.segmentNearest.call(void 0, seg, p);
754
+ const near2 = _chunk7EDLVBOOcjs.segmentNearest.call(void 0, seg, p);
736
755
  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);
756
+ const s = acc + _chunk7EDLVBOOcjs.segmentLength.call(void 0, seg, 0, near2.t);
757
+ const tan = _chunk7EDLVBOOcjs.segmentTangent.call(void 0, seg, near2.t);
739
758
  const pt2 = seg.length === 2 ? lerp(seg[0], seg[1], near2.t) : evalSeg(seg, near2.t);
740
759
  const n = leftNormal([tan[0], tan[1]]);
741
760
  const side = (p[0] - pt2[0]) * n[0] + (p[1] - pt2[1]) * n[1] >= 0 ? "left" : "right";
@@ -752,9 +771,9 @@ function evalSeg(seg, t) {
752
771
  return pts[0];
753
772
  }
754
773
  function strokePositionPoint(path, index, t) {
755
- const c = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path)[index];
756
- 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));
774
+ const c = _chunk7EDLVBOOcjs.pathToContours.call(void 0, path)[index];
775
+ if (!_optionalChain([c, 'optionalAccess', _23 => _23.segments, 'access', _24 => _24.length])) return null;
776
+ const lengths = c.segments.map((s) => _chunk7EDLVBOOcjs.segmentLength.call(void 0, s));
758
777
  const total = lengths.reduce((a, b) => a + b, 0);
759
778
  let want = Math.min(Math.max(t, 0), 1) * total;
760
779
  for (let i = 0; i < c.segments.length; i++) {
@@ -765,11 +784,11 @@ function strokePositionPoint(path, index, t) {
765
784
  const target = Math.min(want, lengths[i]);
766
785
  for (let k = 0; k < 40; k++) {
767
786
  const mid = (lo + hi) / 2;
768
- if (_chunkGVB7ZPLZcjs.segmentLength.call(void 0, seg, 0, mid) < target) lo = mid;
787
+ if (_chunk7EDLVBOOcjs.segmentLength.call(void 0, seg, 0, mid) < target) lo = mid;
769
788
  else hi = mid;
770
789
  }
771
790
  const u = (lo + hi) / 2;
772
- const tan = _chunkGVB7ZPLZcjs.segmentTangent.call(void 0, seg, u);
791
+ const tan = _chunk7EDLVBOOcjs.segmentTangent.call(void 0, seg, u);
773
792
  return { point: evalSeg(seg, u), tangent: [tan[0], tan[1]] };
774
793
  }
775
794
  want -= lengths[i];
@@ -781,7 +800,7 @@ function strokePositionPoint(path, index, t) {
781
800
  var KAPPA = 0.5522847498307936;
782
801
  var NOTCH = 0.7;
783
802
  function isClosedBezierShape(path) {
784
- const contours = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path).filter((c) => c.segments.length > 0);
803
+ const contours = _chunk7EDLVBOOcjs.pathToContours.call(void 0, path).filter((c) => c.segments.length > 0);
785
804
  return contours.length > 0 && contours.every((c) => c.closed);
786
805
  }
787
806
  function effectiveStrokeAlign(style, closedShape) {
@@ -789,7 +808,7 @@ function effectiveStrokeAlign(style, closedShape) {
789
808
  return closedShape ? a : "center";
790
809
  }
791
810
  function strokeWidthProfileOf(style) {
792
- if (!_optionalChain([style, 'access', _24 => _24.strokeWidthProfile, 'optionalAccess', _25 => _25.length])) return null;
811
+ if (!_optionalChain([style, 'access', _25 => _25.strokeWidthProfile, 'optionalAccess', _26 => _26.length])) return null;
793
812
  const p = sanitizeWidthProfile(style.strokeWidthProfile);
794
813
  return isUniformWidthProfile(p) ? null : p;
795
814
  }
@@ -798,11 +817,11 @@ function hasStrokeExtras(style) {
798
817
  }
799
818
  function vectorStrokeLineArea(parts, style, tolerance) {
800
819
  const profile = strokeWidthProfileOf(style);
801
- const dash = _optionalChain([style, 'access', _26 => _26.strokeDasharray, 'optionalAccess', _27 => _27.length]) ? { dash: style.strokeDasharray } : {};
820
+ const dash = _optionalChain([style, 'access', _27 => _27.strokeDasharray, 'optionalAccess', _28 => _28.length]) ? { dash: style.strokeDasharray } : {};
802
821
  const join = _nullishCoalesce(style.strokeLinejoin, () => ( "miter"));
803
822
  const cap = _nullishCoalesce(style.strokeLinecap, () => ( "butt"));
804
823
  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 } : {} });
824
+ return _chunk7EDLVBOOcjs.outlineStroke.call(void 0, parts.line, { width: parts.drawWidth, join, cap, ...dash, ...tolerance ? { tolerance } : {} });
806
825
  }
807
826
  var capExtent = (style, width) => style.strokeLinecap === "round" || style.strokeLinecap === "square" ? width / 2 : 0;
808
827
  function arrowheadWeight(style, end) {
@@ -879,16 +898,16 @@ function arrowheadPath(kind, tip, dir, hw) {
879
898
  }
880
899
  }
881
900
  var toVec = (p) => ({ x: p[0], y: p[1] });
882
- var segLen = (s) => _chunkGVB7ZPLZcjs.segmentLength.call(void 0, s);
901
+ var segLen = (s) => _chunk7EDLVBOOcjs.segmentLength.call(void 0, s);
883
902
  function endOf(segs, atStart) {
884
903
  const long = (s2) => segLen(s2) > 1e-9;
885
904
  if (atStart) {
886
905
  const s2 = _nullishCoalesce(segs.find(long), () => ( segs[0]));
887
- const t2 = _chunkGVB7ZPLZcjs.segmentTangent.call(void 0, s2, 0);
906
+ const t2 = _chunk7EDLVBOOcjs.segmentTangent.call(void 0, s2, 0);
888
907
  return { p: toVec(segs[0][0]), out: v(-t2[0], -t2[1]) };
889
908
  }
890
909
  const s = _nullishCoalesce([...segs].reverse().find(long), () => ( segs[segs.length - 1]));
891
- const t = _chunkGVB7ZPLZcjs.segmentTangent.call(void 0, s, 1);
910
+ const t = _chunk7EDLVBOOcjs.segmentTangent.call(void 0, s, 1);
892
911
  const last = segs[segs.length - 1];
893
912
  return { p: toVec(last[last.length - 1]), out: v(t[0], t[1]) };
894
913
  }
@@ -899,7 +918,7 @@ function pointAlong(segs, fromStart, dist4) {
899
918
  const l = segLen(s);
900
919
  if (acc + l >= dist4) {
901
920
  const want = fromStart ? dist4 - acc : l - (dist4 - acc);
902
- const pts = _chunkGVB7ZPLZcjs.trimSegments.call(void 0, [s], 0, want);
921
+ const pts = _chunk7EDLVBOOcjs.trimSegments.call(void 0, [s], 0, want);
903
922
  const p = pts.length ? pts[0][pts[0].length - 1] : s[0];
904
923
  return toVec(p);
905
924
  }
@@ -909,7 +928,7 @@ function pointAlong(segs, fromStart, dist4) {
909
928
  }
910
929
  function vectorStrokeParts(path, style) {
911
930
  const width = _nullishCoalesce(style.strokeWidth, () => ( 1));
912
- const contours = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, path).filter((c) => c.segments.length > 0);
931
+ const contours = _chunk7EDLVBOOcjs.pathToContours.call(void 0, path).filter((c) => c.segments.length > 0);
913
932
  const closedShape = contours.length > 0 && contours.every((c) => c.closed);
914
933
  const align = effectiveStrokeAlign(style, closedShape);
915
934
  const drawWidth = align === "center" ? width : width * 2;
@@ -949,26 +968,26 @@ function vectorStrokeParts(path, style) {
949
968
  if (!s0 && !s1) return c;
950
969
  const lengths = c.segments.map(segLen);
951
970
  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) : [] };
971
+ return { closed: false, segments: total - s1 > s0 ? _chunk7EDLVBOOcjs.trimSegments.call(void 0, c.segments, s0, total - s1, lengths) : [] };
953
972
  });
954
- return { align, line: _chunkGVB7ZPLZcjs.contoursToPath.call(void 0, trimmed), drawWidth, heads };
973
+ return { align, line: _chunk7EDLVBOOcjs.contoursToPath.call(void 0, trimmed), drawWidth, heads };
955
974
  }
956
975
  function vectorStrokeOutlinePath(path, style) {
957
976
  const parts = vectorStrokeParts(path, style);
958
977
  const stroke = vectorStrokeLineArea(parts, style);
959
978
  const fill = { path, fillRule: _nullishCoalesce(style.fillRule, () => ( "nonzero")) };
960
979
  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;
980
+ if (parts.align === "inside") area = _chunk7EDLVBOOcjs.pathBoolean.call(void 0, "intersection", [stroke, fill]).path;
981
+ else if (parts.align === "outside") area = _chunk7EDLVBOOcjs.pathBoolean.call(void 0, "difference", [stroke, fill]).path;
963
982
  if (!parts.heads.length) return area;
964
- return _chunkGVB7ZPLZcjs.pathBoolean.call(void 0, "union", [area, ...parts.heads.map((h) => h.path)]).path;
983
+ return _chunk7EDLVBOOcjs.pathBoolean.call(void 0, "union", [area, ...parts.heads.map((h) => h.path)]).path;
965
984
  }
966
985
  function hitTestVectorStroke(path, p, style, tolerance = 0) {
967
986
  const parts = vectorStrokeParts(path, style);
968
987
  const point = [p.x, p.y];
969
988
  const width = _nullishCoalesce(style.strokeWidth, () => ( 1));
970
989
  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;
990
+ if (_chunk7EDLVBOOcjs.pointInBezierPath.call(void 0, h.path, point) || tolerance > 0 && _chunk7EDLVBOOcjs.distanceToBezierPath.call(void 0, h.path, point) <= tolerance) return true;
972
991
  }
973
992
  if (!parts.line.length) return false;
974
993
  const profile = strokeWidthProfileOf(style);
@@ -986,13 +1005,13 @@ function hitTestVectorStroke(path, p, style, tolerance = 0) {
986
1005
  reach = Math.max(reach, width / 2 * (w.left + w.right) / 2);
987
1006
  }
988
1007
  } else {
989
- d = _chunkGVB7ZPLZcjs.distanceToBezierPath.call(void 0, parts.line, point);
1008
+ d = _chunk7EDLVBOOcjs.distanceToBezierPath.call(void 0, parts.line, point);
990
1009
  if (parts.align !== "center") reach = width;
991
1010
  }
992
1011
  if (parts.align === "center") return d <= reach + tolerance;
993
1012
  if (d > reach + tolerance) return false;
994
1013
  if (d <= tolerance) return true;
995
- const inside = _chunkGVB7ZPLZcjs.pointInBezierPath.call(void 0, path, point, _nullishCoalesce(style.fillRule, () => ( "nonzero")));
1014
+ const inside = _chunk7EDLVBOOcjs.pointInBezierPath.call(void 0, path, point, _nullishCoalesce(style.fillRule, () => ( "nonzero")));
996
1015
  return parts.align === "inside" ? inside : !inside;
997
1016
  }
998
1017
  function vectorStrokeReach(style) {
@@ -1068,7 +1087,7 @@ function vectorNodeToBezier(node) {
1068
1087
  }
1069
1088
  function vectorPathData(input, precision = 3) {
1070
1089
  const subpaths = Array.isArray(input) ? input : input.subpaths;
1071
- return _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, subpathsToBezier(subpaths), { precision });
1090
+ return _chunk7EDLVBOOcjs.bezierPathToSvg.call(void 0, subpathsToBezier(subpaths), { precision });
1072
1091
  }
1073
1092
  function inferAnchorType(a) {
1074
1093
  if (isOnAnchor(a, a.in) || isOnAnchor(a, a.out)) return "corner";
@@ -1084,7 +1103,7 @@ function inferAnchorType(a) {
1084
1103
  return Math.abs(li - lo) <= 1e-3 * Math.max(li, lo) ? "symmetric" : "smooth";
1085
1104
  }
1086
1105
  function bezierToSubpaths(input) {
1087
- const path = _chunkGVB7ZPLZcjs.toBezierPath.call(void 0, input);
1106
+ const path = _chunk7EDLVBOOcjs.toBezierPath.call(void 0, input);
1088
1107
  const out = [];
1089
1108
  let current = null;
1090
1109
  const last = () => current.anchors[current.anchors.length - 1];
@@ -1181,14 +1200,14 @@ function nodeMatrix(node) {
1181
1200
  function vectorPathWorldBezier(node, parent = IDENTITY_MATRIX) {
1182
1201
  const m = multiplyMatrices(nodeMatrix(node), parent);
1183
1202
  const path = subpathsToBezier(node.subpaths);
1184
- return isIdentityMatrix(m) ? path : _chunkGVB7ZPLZcjs.transformBezierPath.call(void 0, path, m);
1203
+ return isIdentityMatrix(m) ? path : _chunk7EDLVBOOcjs.transformBezierPath.call(void 0, path, m);
1185
1204
  }
1186
1205
  function vectorNodeBounds(node, parent = IDENTITY_MATRIX) {
1187
1206
  if (node.type === "group") {
1188
1207
  const m = multiplyMatrices(nodeMatrix(node), parent);
1189
1208
  return unionBounds(node.children.map((c) => vectorNodeBounds(c, m)));
1190
1209
  }
1191
- const b = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, vectorPathWorldBezier(node, parent));
1210
+ const b = _chunk7EDLVBOOcjs.bezierPathBounds.call(void 0, vectorPathWorldBezier(node, parent));
1192
1211
  if (!b) return null;
1193
1212
  return { x: b.minX, y: b.minY, width: b.maxX - b.minX, height: b.maxY - b.minY };
1194
1213
  }
@@ -1222,9 +1241,9 @@ function hitTestVectorNode(node, p, tolerance = 0, parent = IDENTITY_MATRIX) {
1222
1241
  const path = vectorPathWorldBezier(node, parent);
1223
1242
  if (path.length === 0) return false;
1224
1243
  const point = [p.x, p.y];
1225
- if (hasPaint(node.fill) && _chunkGVB7ZPLZcjs.pointInBezierPath.call(void 0, path, point, _nullishCoalesce(node.fillRule, () => ( "nonzero")))) return true;
1244
+ if (hasPaint(node.fill) && _chunk7EDLVBOOcjs.pointInBezierPath.call(void 0, path, point, _nullishCoalesce(node.fillRule, () => ( "nonzero")))) return true;
1226
1245
  if (hasPaint(node.stroke)) return hitTestVectorStroke(path, p, node, tolerance);
1227
- return _chunkGVB7ZPLZcjs.distanceToBezierPath.call(void 0, path, point) <= tolerance;
1246
+ return _chunk7EDLVBOOcjs.distanceToBezierPath.call(void 0, path, point) <= tolerance;
1228
1247
  }
1229
1248
  function vectorStrokeOutline(node, parent = IDENTITY_MATRIX) {
1230
1249
  if (!hasPaint(node.stroke) || !((_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0)) return [];
@@ -1244,9 +1263,9 @@ function nearestSegment(node, p) {
1244
1263
  const count = subpathSegmentCount(sp);
1245
1264
  for (let i = 0; i < count; i++) {
1246
1265
  const seg = subpathSegment(sp, i);
1247
- const hit = _chunkGVB7ZPLZcjs.segmentNearest.call(void 0, seg, [p.x, p.y]);
1266
+ const hit = _chunk7EDLVBOOcjs.segmentNearest.call(void 0, seg, [p.x, p.y]);
1248
1267
  if (!best || hit.distance < best.distance) {
1249
- const pt2 = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, hit.t);
1268
+ const pt2 = _chunk7EDLVBOOcjs.segmentPoint.call(void 0, seg, hit.t);
1250
1269
  best = { subpath: s, segment: i, t: hit.t, point: { x: pt2[0], y: pt2[1] }, distance: hit.distance };
1251
1270
  }
1252
1271
  }
@@ -1306,7 +1325,7 @@ function bakeIntoGeometry(node, m) {
1306
1325
  if (isIdentityMatrix(m)) return node;
1307
1326
  if (node.type === "group") return { ...node, children: node.children.map((c) => transformVectorNode(c, m)) };
1308
1327
  const path = node;
1309
- const mirrored = m[0] * m[3] - m[1] * m[2] < 0 && _optionalChain([path, 'access', _28 => _28.strokeWidthProfile, 'optionalAccess', _29 => _29.length]);
1328
+ const mirrored = m[0] * m[3] - m[1] * m[2] < 0 && _optionalChain([path, 'access', _29 => _29.strokeWidthProfile, 'optionalAccess', _30 => _30.length]);
1310
1329
  return {
1311
1330
  ...path,
1312
1331
  ...mirrored ? { strokeWidthProfile: mirrorWidthProfile(path.strokeWidthProfile) } : {},
@@ -1420,7 +1439,7 @@ function insertAnchor(sp, segment, t) {
1420
1439
  const ia = segment;
1421
1440
  const ib = (segment + 1) % n;
1422
1441
  const seg = subpathSegment(sp, segment);
1423
- const [left, right] = _chunkGVB7ZPLZcjs.splitSegment.call(void 0, seg, t);
1442
+ const [left, right] = _chunk7EDLVBOOcjs.splitSegment.call(void 0, seg, t);
1424
1443
  const mid = left[left.length - 1];
1425
1444
  const anchor = { x: mid[0], y: mid[1] };
1426
1445
  if (seg.length === 4) {
@@ -1474,8 +1493,8 @@ function ellipseSubpath(b) {
1474
1493
  ]
1475
1494
  };
1476
1495
  }
1477
- function polygonSubpath(b, sides = 6) {
1478
- const n = Math.max(3, Math.round(sides));
1496
+ function polygonSubpath(b, sides2 = 6) {
1497
+ const n = Math.max(3, Math.round(sides2));
1479
1498
  const cx = b.x + b.width / 2;
1480
1499
  const cy = b.y + b.height / 2;
1481
1500
  const anchors = [];
@@ -1516,7 +1535,7 @@ function vectorCornersAttribute(subpaths, precision = 3) {
1516
1535
  subpaths.forEach(
1517
1536
  (sp, s) => sp.anchors.forEach((a, i) => {
1518
1537
  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}` : ""}`);
1538
+ out.push(`${s}.${i}:${_chunk7EDLVBOOcjs.formatNumber.call(void 0, a.corner.radius, precision)}${a.corner.kind && a.corner.kind !== "round" ? `:${a.corner.kind}` : ""}`);
1520
1539
  })
1521
1540
  );
1522
1541
  return out.join(" ");
@@ -1525,7 +1544,7 @@ function applyVectorCornersAttribute(subpaths, value) {
1525
1544
  for (const item of value.trim().split(/\s+/)) {
1526
1545
  const m = /^(\d+)\.(\d+):([\d.eE+-]+)(?::([a-z]+))?$/.exec(item);
1527
1546
  if (!m) continue;
1528
- const a = _optionalChain([subpaths, 'access', _30 => _30[+m[1]], 'optionalAccess', _31 => _31.anchors, 'access', _32 => _32[+m[2]]]);
1547
+ const a = _optionalChain([subpaths, 'access', _31 => _31[+m[1]], 'optionalAccess', _32 => _32.anchors, 'access', _33 => _33[+m[2]]]);
1529
1548
  const radius = parseFloat(m[3]);
1530
1549
  if (!a || !(radius > 0)) continue;
1531
1550
  const kind = VECTOR_CORNER_KINDS.includes(m[4]) ? m[4] : void 0;
@@ -1537,7 +1556,7 @@ var escapeAttr = (value) => value.replace(/&/g, "&amp;").replace(/"/g, "&quot;")
1537
1556
  function vectorPaintToSvg(paint, gradientId) {
1538
1557
  if (!hasPaint(paint)) return { value: "none", gradient: null };
1539
1558
  if (typeof paint === "string") return { value: paint, gradient: null };
1540
- return { value: `url(#${gradientId})`, gradient: _chunkGVB7ZPLZcjs.gradientToSvgDef.call(void 0, paint, gradientId) };
1559
+ return { value: `url(#${gradientId})`, gradient: _chunk7EDLVBOOcjs.gradientToSvgDef.call(void 0, paint, gradientId) };
1541
1560
  }
1542
1561
  var partsCache = /* @__PURE__ */ new WeakMap();
1543
1562
  function vectorStrokeSvgParts(node, clipId, precision = 3) {
@@ -1555,22 +1574,22 @@ function computeStrokeSvgParts(node, clipId, precision) {
1555
1574
  if (parts.align === "center" && !parts.heads.length && !profiled) return void 0;
1556
1575
  let clip = null;
1557
1576
  if (parts.align !== "center") {
1558
- const b = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, path);
1577
+ const b = _chunk7EDLVBOOcjs.bezierPathBounds.call(void 0, path);
1559
1578
  const pad = vectorStrokeReach(node) + 1;
1560
1579
  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
1580
  clip = { kind: parts.align === "inside" ? "clip" : "mask", id: clipId, bounds };
1562
1581
  }
1563
1582
  return {
1564
1583
  align: parts.align,
1565
- d: _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, parts.line, { precision }),
1584
+ d: _chunk7EDLVBOOcjs.bezierPathToSvg.call(void 0, parts.line, { precision }),
1566
1585
  width: parts.drawWidth,
1567
- ...profiled && (_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0 ? { outline: _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, vectorStrokeLineArea(parts, node), { precision }) } : {},
1586
+ ...profiled && (_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0 ? { outline: _chunk7EDLVBOOcjs.bezierPathToSvg.call(void 0, vectorStrokeLineArea(parts, node), { precision }) } : {},
1568
1587
  clip,
1569
- heads: parts.heads.map((h) => _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, h.path, { precision }))
1588
+ heads: parts.heads.map((h) => _chunk7EDLVBOOcjs.bezierPathToSvg.call(void 0, h.path, { precision }))
1570
1589
  };
1571
1590
  }
1572
1591
  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(";");
1592
+ return points.map((p) => [p.t, p.left, p.right].map((n) => _chunk7EDLVBOOcjs.formatNumber.call(void 0, n, precision)).join(",")).join(";");
1574
1593
  }
1575
1594
  function widthProfileFromAttribute(value) {
1576
1595
  if (!value) return [];
@@ -1594,11 +1613,11 @@ function vectorDocumentToSvg(doc, options = {}) {
1594
1613
  const pretty = options.pretty !== false;
1595
1614
  const defs = [];
1596
1615
  const lines = [];
1597
- const num = (n) => _chunkGVB7ZPLZcjs.formatNumber.call(void 0, n, precision);
1616
+ const num = (n) => _chunk7EDLVBOOcjs.formatNumber.call(void 0, n, precision);
1598
1617
  const indent = (depth) => pretty ? " ".repeat(depth) : "";
1599
1618
  const common = (node) => {
1600
1619
  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(" ")})"`;
1620
+ if (node.transform) out2 += ` transform="matrix(${node.transform.map((n) => _chunk7EDLVBOOcjs.formatNumber.call(void 0, n, 6)).join(" ")})"`;
1602
1621
  if (node.opacity !== void 0 && node.opacity < 1) out2 += ` opacity="${num(node.opacity)}"`;
1603
1622
  if (node.visible === false) out2 += ` display="none"`;
1604
1623
  return out2;
@@ -1617,13 +1636,13 @@ function vectorDocumentToSvg(doc, options = {}) {
1617
1636
  if (stroke.gradient) defs.push(gradientMarkup(stroke.gradient));
1618
1637
  const d = vectorPathData(node, precision);
1619
1638
  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}"` : "";
1639
+ const live = corners2 ? ` data-vector-d="${_chunk7EDLVBOOcjs.bezierPathToSvg.call(void 0, subpathsToBezier(node.subpaths, { corners: false }), { precision })}" data-vector-corners="${corners2}"` : "";
1621
1640
  const fillAttrs = ` fill="${escapeAttr(fill.value)}"${node.fillRule === "evenodd" ? ` fill-rule="evenodd"` : ""}`;
1622
1641
  const lineAttrs = (width) => {
1623
1642
  let out2 = ` stroke="${escapeAttr(stroke.value)}" stroke-width="${num(width)}"`;
1624
1643
  if (node.strokeLinecap && node.strokeLinecap !== "butt") out2 += ` stroke-linecap="${node.strokeLinecap}"`;
1625
1644
  if (node.strokeLinejoin && node.strokeLinejoin !== "miter") out2 += ` stroke-linejoin="${node.strokeLinejoin}"`;
1626
- if (_optionalChain([node, 'access', _33 => _33.strokeDasharray, 'optionalAccess', _34 => _34.length])) out2 += ` stroke-dasharray="${node.strokeDasharray.map(num).join(" ")}"`;
1645
+ if (_optionalChain([node, 'access', _34 => _34.strokeDasharray, 'optionalAccess', _35 => _35.length])) out2 += ` stroke-dasharray="${node.strokeDasharray.map(num).join(" ")}"`;
1627
1646
  return out2;
1628
1647
  };
1629
1648
  const parts = stroke.value !== "none" ? vectorStrokeSvgParts(node, `${prefix}clip-${node.id}`, precision) : void 0;
@@ -1643,12 +1662,12 @@ function vectorDocumentToSvg(doc, options = {}) {
1643
1662
  data += ` data-vector-width-profile="${widthProfileToAttribute(profile)}"`;
1644
1663
  if (node.strokeLinecap && node.strokeLinecap !== "butt") data += ` data-vector-stroke-linecap="${node.strokeLinecap}"`;
1645
1664
  if (node.strokeLinejoin && node.strokeLinejoin !== "miter") data += ` data-vector-stroke-linejoin="${node.strokeLinejoin}"`;
1646
- if (_optionalChain([node, 'access', _35 => _35.strokeDasharray, 'optionalAccess', _36 => _36.length])) data += ` data-vector-stroke-dasharray="${node.strokeDasharray.map(num).join(" ")}"`;
1665
+ if (_optionalChain([node, 'access', _36 => _36.strokeDasharray, 'optionalAccess', _37 => _37.length])) data += ` data-vector-stroke-dasharray="${node.strokeDasharray.map(num).join(" ")}"`;
1647
1666
  }
1648
1667
  lines.push(`${indent(depth)}<g${common(node)}${data}>`);
1649
1668
  lines.push(`${indent(depth + 1)}<path data-vector-part="fill" d="${d}"${fillAttrs}${live}/>`);
1650
1669
  if (options.strokes === "outline") {
1651
- const area = _chunkGVB7ZPLZcjs.bezierPathToSvg.call(void 0, vectorStrokeOutlinePath(subpathsToBezier(node.subpaths), node), { precision });
1670
+ const area = _chunk7EDLVBOOcjs.bezierPathToSvg.call(void 0, vectorStrokeOutlinePath(subpathsToBezier(node.subpaths), node), { precision });
1652
1671
  lines.push(`${indent(depth + 1)}<path data-vector-part="stroke-outline" d="${area}" fill="${escapeAttr(stroke.value)}"/>`);
1653
1672
  } else {
1654
1673
  let clip = "";
@@ -1812,7 +1831,7 @@ function resolveGradient(id, raw, seen = /* @__PURE__ */ new Set()) {
1812
1831
  seen.add(id);
1813
1832
  let stops = readStops(el);
1814
1833
  const href = _nullishCoalesce(el.attrs.href, () => ( el.attrs["xlink:href"]));
1815
- if (!stops.length && _optionalChain([href, 'optionalAccess', _37 => _37.startsWith, 'call', _38 => _38("#")])) stops = _nullishCoalesce(_optionalChain([resolveGradient, 'call', _39 => _39(href.slice(1), raw, seen), 'optionalAccess', _40 => _40.stops]), () => ( []));
1834
+ if (!stops.length && _optionalChain([href, 'optionalAccess', _38 => _38.startsWith, 'call', _39 => _39("#")])) stops = _nullishCoalesce(_optionalChain([resolveGradient, 'call', _40 => _40(href.slice(1), raw, seen), 'optionalAccess', _41 => _41.stops]), () => ( []));
1816
1835
  if (!stops.length) return null;
1817
1836
  if (el.name === "radialGradient") {
1818
1837
  return { type: "radial", cx: fraction(el.attrs.cx, 0.5), cy: fraction(el.attrs.cy, 0.5), r: fraction(el.attrs.r, 0.5), stops };
@@ -1916,7 +1935,7 @@ function parseVectorSvg(svg, options = {}) {
1916
1935
  const part = (name) => g.children.find((c) => c.name === "path" && c.attrs["data-vector-part"] === name);
1917
1936
  const fillEl = part("fill");
1918
1937
  const subpaths = fillEl ? shapeOf(fillEl) : null;
1919
- if (!fillEl || !_optionalChain([subpaths, 'optionalAccess', _41 => _41.length])) return null;
1938
+ if (!fillEl || !_optionalChain([subpaths, 'optionalAccess', _42 => _42.length])) return null;
1920
1939
  const a = g.attrs;
1921
1940
  const fs = readStyle(fillEl, style);
1922
1941
  const strokeEl = part("stroke");
@@ -1953,7 +1972,7 @@ function parseVectorSvg(svg, options = {}) {
1953
1972
  ...profile.length ? { strokeWidthProfile: profile } : {},
1954
1973
  ...keptCap ? { strokeLinecap: keptCap } : {},
1955
1974
  ...keptJoin ? { strokeLinejoin: keptJoin } : {},
1956
- ..._optionalChain([keptDash, 'optionalAccess', _42 => _42.length]) ? { strokeDasharray: keptDash } : {}
1975
+ ..._optionalChain([keptDash, 'optionalAccess', _43 => _43.length]) ? { strokeDasharray: keptDash } : {}
1957
1976
  };
1958
1977
  return placed(node, m);
1959
1978
  };
@@ -2007,7 +2026,7 @@ function parseVectorSvg(svg, options = {}) {
2007
2026
  // src/vector/snap.ts
2008
2027
  var VECTOR_CONSTRUCTION_ANGLES = [0, 45, 90, 135];
2009
2028
  function constrainToLeave(leave, p) {
2010
- if (!_optionalChain([leave, 'optionalAccess', _43 => _43.constrain])) return p;
2029
+ if (!_optionalChain([leave, 'optionalAccess', _44 => _44.constrain])) return p;
2011
2030
  const dx = p.x - leave.at.x;
2012
2031
  const dy = p.y - leave.at.y;
2013
2032
  switch (leave.constrain) {
@@ -2118,7 +2137,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
2118
2137
  moving.set(r.nodeId, set);
2119
2138
  }
2120
2139
  const t = _VectorSnapTargets.collect(doc, new Set(moving.keys()), "segments", false);
2121
- t.pushPaths(doc, new Set(moving.keys()), (id, s, i) => !!_optionalChain([moving, 'access', _44 => _44.get, 'call', _45 => _45(id), 'optionalAccess', _46 => _46.has, 'call', _47 => _47(`${s}:${i}`)]), true);
2140
+ t.pushPaths(doc, new Set(moving.keys()), (id, s, i) => !!_optionalChain([moving, 'access', _45 => _45.get, 'call', _46 => _46(id), 'optionalAccess', _47 => _47.has, 'call', _48 => _48(`${s}:${i}`)]), true);
2122
2141
  return t.index();
2123
2142
  }
2124
2143
  /**
@@ -2236,7 +2255,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
2236
2255
  }
2237
2256
  const b = vectorNodeBounds(n, parent);
2238
2257
  const f = nodeFrame(n, parent, b);
2239
- if (b) self.pushRect(b, "edge", _nullishCoalesce(_optionalChain([f, 'optionalAccess', _48 => _48.centre]), () => ( null)));
2258
+ if (b) self.pushRect(b, "edge", _nullishCoalesce(_optionalChain([f, 'optionalAccess', _49 => _49.centre]), () => ( null)));
2240
2259
  }
2241
2260
  };
2242
2261
  visit(doc.nodes, IDENTITY_MATRIX);
@@ -2281,7 +2300,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
2281
2300
  lines: lines2,
2282
2301
  labels: [this.label(q, kind)]
2283
2302
  });
2284
- if (_optionalChain([leave, 'optionalAccess', _49 => _49.constrain])) {
2303
+ if (_optionalChain([leave, 'optionalAccess', _50 => _50.constrain])) {
2285
2304
  const q = constrainToLeave(leave, p);
2286
2305
  const hit = this.slide(leave.at, { x: q.x - leave.at.x, y: q.y - leave.at.y }, q, tol, true);
2287
2306
  return hit ? { point: hit.point, x: true, y: true, ...this.linedUp(hit.point, hit.from) } : none(q);
@@ -2297,7 +2316,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
2297
2316
  }
2298
2317
  const on = this.onSegment(near2);
2299
2318
  if (on) return at2(on, "path");
2300
- if (_optionalChain([leave, 'optionalAccess', _50 => _50.angles, 'optionalAccess', _51 => _51.length])) {
2319
+ if (_optionalChain([leave, 'optionalAccess', _51 => _51.angles, 'optionalAccess', _52 => _52.length])) {
2301
2320
  const c = construction(leave, p, tol);
2302
2321
  if (c) {
2303
2322
  const hit = this.slide(leave.at, c.dir, c.point, tol, false);
@@ -2373,13 +2392,13 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
2373
2392
  const pt2 = toPoint(p);
2374
2393
  for (const s of this.segments) {
2375
2394
  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);
2395
+ const hit = _chunk7EDLVBOOcjs.segmentNearest.call(void 0, s.seg, pt2);
2377
2396
  if (hit.distance <= tol) out.push({ seg: s.seg, t: hit.t, distance: hit.distance });
2378
2397
  }
2379
2398
  return out.sort((a, b) => a.distance - b.distance);
2380
2399
  }
2381
2400
  onSegment(near2) {
2382
- return near2.length ? toVec2(_chunkGVB7ZPLZcjs.segmentPoint.call(void 0, near2[0].seg, near2[0].t)) : null;
2401
+ return near2.length ? toVec2(_chunk7EDLVBOOcjs.segmentPoint.call(void 0, near2[0].seg, near2[0].t)) : null;
2383
2402
  }
2384
2403
  /** Where two of the target segments near `p` cross, the crossing nearest `p` within `tol`. */
2385
2404
  crossing(near2, p, tol) {
@@ -2388,7 +2407,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
2388
2407
  let bestD = Infinity;
2389
2408
  for (let i = 0; i < list.length; i++) {
2390
2409
  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)) {
2410
+ for (const hit of _chunk7EDLVBOOcjs.segmentIntersections.call(void 0, list[i].seg, list[j].seg)) {
2392
2411
  const q = toVec2(hit.point);
2393
2412
  const d = distance(q, p);
2394
2413
  if (d <= tol && d < bestD) {
@@ -2427,7 +2446,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
2427
2446
  * with nothing spaces the box evenly in its row or column. Returns the correction and guides.
2428
2447
  */
2429
2448
  snapRect(r, tol, options = {}) {
2430
- const axes = { x: _optionalChain([options, 'access', _52 => _52.axes, 'optionalAccess', _53 => _53.x]) !== false, y: _optionalChain([options, 'access', _54 => _54.axes, 'optionalAccess', _55 => _55.y]) !== false };
2449
+ const axes = { x: _optionalChain([options, 'access', _53 => _53.axes, 'optionalAccess', _54 => _54.x]) !== false, y: _optionalChain([options, 'access', _55 => _55.axes, 'optionalAccess', _56 => _56.y]) !== false };
2431
2450
  const nearest = (lines, values) => {
2432
2451
  let best = null;
2433
2452
  for (const v2 of values) for (const l of linesNear(lines, v2, tol)) if (!best || Math.abs(l.v - v2) < Math.abs(best.d)) best = { d: l.v - v2, from: l.from };
@@ -2435,7 +2454,7 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
2435
2454
  };
2436
2455
  const bx = axes.x ? nearest(this.xs, [r.x, r.x + r.width / 2, r.x + r.width]) : null;
2437
2456
  const by = axes.y ? nearest(this.ys, [r.y, r.y + r.height / 2, r.y + r.height]) : null;
2438
- const out = { dx: _nullishCoalesce(_optionalChain([bx, 'optionalAccess', _56 => _56.d]), () => ( 0)), dy: _nullishCoalesce(_optionalChain([by, 'optionalAccess', _57 => _57.d]), () => ( 0)), x: !!bx, y: !!by, lines: [], labels: [] };
2457
+ const out = { dx: _nullishCoalesce(_optionalChain([bx, 'optionalAccess', _57 => _57.d]), () => ( 0)), dy: _nullishCoalesce(_optionalChain([by, 'optionalAccess', _58 => _58.d]), () => ( 0)), x: !!bx, y: !!by, lines: [], labels: [] };
2439
2458
  const done = { ...r, x: r.x + out.dx, y: r.y + out.dy };
2440
2459
  if (bx) {
2441
2460
  const x = bx.from.x;
@@ -2558,9 +2577,9 @@ var VectorSnapTargets = (_class = class _VectorSnapTargets {
2558
2577
  const on = this.nearestPoint(p, tol);
2559
2578
  const tries = [];
2560
2579
  if (on) tries.push({ tx: on.p.x, ty: on.p.y, s: { hx: null, hy: null, on } });
2561
- tries.push({ tx: _nullishCoalesce(_optionalChain([hx, 'optionalAccess', _58 => _58.v]), () => ( null)), ty: _nullishCoalesce(_optionalChain([hy, 'optionalAccess', _59 => _59.v]), () => ( null)), s: { hx, hy, on: null } });
2562
- tries.push({ tx: _nullishCoalesce(_optionalChain([hx, 'optionalAccess', _60 => _60.v]), () => ( null)), ty: null, s: { hx, hy: null, on: null } });
2563
- tries.push({ tx: null, ty: _nullishCoalesce(_optionalChain([hy, 'optionalAccess', _61 => _61.v]), () => ( null)), s: { hx: null, hy, on: null } });
2580
+ tries.push({ tx: _nullishCoalesce(_optionalChain([hx, 'optionalAccess', _59 => _59.v]), () => ( null)), ty: _nullishCoalesce(_optionalChain([hy, 'optionalAccess', _60 => _60.v]), () => ( null)), s: { hx, hy, on: null } });
2581
+ tries.push({ tx: _nullishCoalesce(_optionalChain([hx, 'optionalAccess', _61 => _61.v]), () => ( null)), ty: null, s: { hx, hy: null, on: null } });
2582
+ tries.push({ tx: null, ty: _nullishCoalesce(_optionalChain([hy, 'optionalAccess', _62 => _62.v]), () => ( null)), s: { hx: null, hy, on: null } });
2564
2583
  for (const { tx, ty, s } of tries) {
2565
2584
  if (tx === null && ty === null) continue;
2566
2585
  const q = applyMatrix(toLocal, { x: _nullishCoalesce(tx, () => ( p.x)), y: _nullishCoalesce(ty, () => ( p.y)) });
@@ -2710,15 +2729,15 @@ var crossCondition = (r, d) => r[0] * d[1] - r[1] * d[0];
2710
2729
  function solveOnSegment(seg, base, cond) {
2711
2730
  const b = [base.x, base.y];
2712
2731
  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));
2732
+ const p = _chunk7EDLVBOOcjs.segmentPoint.call(void 0, seg, t);
2733
+ return cond([p[0] - b[0], p[1] - b[1]], _chunk7EDLVBOOcjs.segmentDerivative.call(void 0, seg, t));
2715
2734
  };
2716
2735
  const vals = [];
2717
2736
  let scale = 0;
2718
2737
  for (let i = 0; i <= CURVE_SAMPLES; i++) {
2719
2738
  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);
2739
+ const p = _chunk7EDLVBOOcjs.segmentPoint.call(void 0, seg, t);
2740
+ const d = _chunk7EDLVBOOcjs.segmentDerivative.call(void 0, seg, t);
2722
2741
  const r = [p[0] - b[0], p[1] - b[1]];
2723
2742
  vals.push(cond(r, d));
2724
2743
  scale = Math.max(scale, Math.hypot(r[0], r[1]) * Math.hypot(d[0], d[1]));
@@ -2745,8 +2764,8 @@ function solveOnSegment(seg, base, cond) {
2745
2764
  } else hi = m;
2746
2765
  }
2747
2766
  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);
2767
+ const p = _chunk7EDLVBOOcjs.segmentPoint.call(void 0, seg, t);
2768
+ const dv = _chunk7EDLVBOOcjs.segmentDerivative.call(void 0, seg, t);
2750
2769
  const r = Math.hypot(p[0] - b[0], p[1] - b[1]);
2751
2770
  const dl = Math.hypot(dv[0], dv[1]);
2752
2771
  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 +2802,7 @@ function endTangent(c) {
2783
2802
  return [1, 0];
2784
2803
  }
2785
2804
  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));
2805
+ for (let i = withStart ? 0 : 1; i <= n; i++) out.push(_chunk7EDLVBOOcjs.segmentPoint.call(void 0, c, i / n));
2787
2806
  }
2788
2807
  var onAnchor2 = (a, h) => !h || Math.abs(h.x - a.x) < EPS3 && Math.abs(h.y - a.y) < EPS3;
2789
2808
  function tidy(a, keepType = true) {
@@ -2829,7 +2848,7 @@ function fitAcross(pts, N, t0, t1) {
2829
2848
  const u = [];
2830
2849
  for (let i = 0; i <= N; i++) u.push(k * i / N);
2831
2850
  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);
2851
+ return _chunk7EDLVBOOcjs.fitCubicWithTangents.call(void 0, pts, u, t0, t1);
2833
2852
  };
2834
2853
  return goldenMin(fit, 0, 1);
2835
2854
  }
@@ -2889,7 +2908,7 @@ function bendSegment(sp, segment, t, p) {
2889
2908
  return { anchors, closed: sp.closed };
2890
2909
  }
2891
2910
  function subpathPointAt(sp, segment, t) {
2892
- const [x, y] = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, subpathSegment(sp, segment), t);
2911
+ const [x, y] = _chunk7EDLVBOOcjs.segmentPoint.call(void 0, subpathSegment(sp, segment), t);
2893
2912
  return { x, y };
2894
2913
  }
2895
2914
  function curvatureMoveAnchor(sp, index, q) {
@@ -3150,20 +3169,20 @@ function removeRedundantPoints(sp, tolerance) {
3150
3169
  }
3151
3170
 
3152
3171
  // src/vector/pathCut.ts
3153
- var loopArea = (l) => _chunkGVB7ZPLZcjs.contourSignedArea.call(void 0, l.segs);
3172
+ var loopArea = (l) => _chunk7EDLVBOOcjs.contourSignedArea.call(void 0, l.segs);
3154
3173
  function loopSample(l) {
3155
3174
  const k = l.chord.findIndex((c) => !c);
3156
- return _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, l.segs[k >= 0 ? k : 0], 0.5);
3175
+ return _chunk7EDLVBOOcjs.segmentPoint.call(void 0, l.segs[k >= 0 ? k : 0], 0.5);
3157
3176
  }
3158
- var contains2 = (l, p) => _chunkGVB7ZPLZcjs.windingNumber.call(void 0, [l.segs], p) !== 0;
3177
+ var contains2 = (l, p) => _chunk7EDLVBOOcjs.windingNumber.call(void 0, [l.segs], p) !== 0;
3159
3178
  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);
3179
+ const usable2 = loops.filter((l) => l.segs.length && Math.abs(loopArea(l)) > 1e-12);
3180
+ if (!usable2.length) return [];
3181
+ const largest = usable2.reduce((a, b) => Math.abs(loopArea(b)) > Math.abs(loopArea(a)) ? b : a);
3163
3182
  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)));
3183
+ const outers = usable2.filter((l) => Math.sign(loopArea(l)) === sign).sort((a, b) => Math.abs(loopArea(a)) - Math.abs(loopArea(b)));
3165
3184
  const faces = new Map(outers.map((o) => [o, { loops: [o] }]));
3166
- for (const hole of usable.filter((l) => Math.sign(loopArea(l)) !== sign)) {
3185
+ for (const hole of usable2.filter((l) => Math.sign(loopArea(l)) !== sign)) {
3167
3186
  const p = loopSample(hole);
3168
3187
  const parent = outers.find((o) => Math.abs(loopArea(o)) > Math.abs(loopArea(hole)) && contains2(o, p));
3169
3188
  if (parent) faces.get(parent).loops.push(hole);
@@ -3171,12 +3190,12 @@ function groupFaces(loops) {
3171
3190
  return outers.reverse().map((o) => faces.get(o));
3172
3191
  }
3173
3192
  function faceToPath(face) {
3174
- return _chunkGVB7ZPLZcjs.contoursToPath.call(void 0, face.loops.map((l) => ({ segments: l.segs, closed: true })));
3193
+ return _chunk7EDLVBOOcjs.contoursToPath.call(void 0, face.loops.map((l) => ({ segments: l.segs, closed: true })));
3175
3194
  }
3176
3195
  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());
3196
+ const normalized = _chunk7EDLVBOOcjs.normalizeBezierPath.call(void 0, path, fillRule);
3197
+ const loops = _chunk7EDLVBOOcjs.pathToContours.call(void 0, normalized).map((c) => {
3198
+ const segs = _chunk7EDLVBOOcjs.closeContour.call(void 0, c, true).map((s) => s.slice());
3180
3199
  return { segs, chord: segs.map(() => false) };
3181
3200
  });
3182
3201
  return groupFaces(loops);
@@ -3246,7 +3265,7 @@ function lineHits(p, q, seg) {
3246
3265
  const scale = Math.sqrt(len2) * Math.max(1, ...seg.map((pt2) => Math.abs(pt2[0]) + Math.abs(pt2[1])));
3247
3266
  const out = [];
3248
3267
  for (const t of rootsInUnit(...coeffs, scale)) {
3249
- const point = _chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, t);
3268
+ const point = _chunk7EDLVBOOcjs.segmentPoint.call(void 0, seg, t);
3250
3269
  const s = ((point[0] - p[0]) * dx + (point[1] - p[1]) * dy) / len2;
3251
3270
  if (s >= -1e-9 && s <= 1 + 1e-9) out.push({ s: Math.min(1, Math.max(0, s)), t, point });
3252
3271
  }
@@ -3259,7 +3278,7 @@ function arc(l, a, b, eps) {
3259
3278
  const segs = [];
3260
3279
  const chord = [];
3261
3280
  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);
3281
+ const piece = t0 <= 0 && t1 >= 1 ? l.segs[k].slice() : _chunk7EDLVBOOcjs.subSegment.call(void 0, l.segs[k], t0, t1);
3263
3282
  if (!degenerate(piece, eps)) {
3264
3283
  segs.push(piece);
3265
3284
  chord.push(l.chord[k]);
@@ -3284,7 +3303,7 @@ function knifePath(path, fillRule, knife) {
3284
3303
  if (pts.length < 2) return null;
3285
3304
  let faces = facesOf(path, fillRule);
3286
3305
  if (!faces.length) return null;
3287
- const b = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, path);
3306
+ const b = _chunk7EDLVBOOcjs.bezierPathBounds.call(void 0, path);
3288
3307
  const size = b ? Math.max(b.maxX - b.minX, b.maxY - b.minY, 1) : 1;
3289
3308
  const eps = size * 1e-9;
3290
3309
  let cursor = -Infinity;
@@ -3298,7 +3317,7 @@ function knifePath(path, fillRule, knife) {
3298
3317
  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
3318
  face2.loops.forEach(
3300
3319
  (l, li) => l.segs.forEach((seg, si) => {
3301
- const sb = _chunkGVB7ZPLZcjs.segmentBounds.call(void 0, seg);
3320
+ const sb = _chunk7EDLVBOOcjs.segmentBounds.call(void 0, seg);
3302
3321
  if (sb.maxX < kb.minX - eps || sb.minX > kb.maxX + eps || sb.maxY < kb.minY - eps || sb.minY > kb.maxY + eps) return;
3303
3322
  for (const h of lineHits(pts[m], pts[m + 1], seg)) {
3304
3323
  const s = m + h.s;
@@ -3313,7 +3332,7 @@ function knifePath(path, fillRule, knife) {
3313
3332
  const m = Math.min(pts.length - 2, Math.floor(s));
3314
3333
  const u = s - m;
3315
3334
  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;
3335
+ return _chunk7EDLVBOOcjs.windingNumber.call(void 0, face2.loops.map((l) => l.segs), q) !== 0;
3317
3336
  };
3318
3337
  for (let i = 0; i < unique.length - 1; i++) {
3319
3338
  const from2 = unique[i];
@@ -3373,33 +3392,33 @@ function eraserRegion(points, width) {
3373
3392
  ];
3374
3393
  }
3375
3394
  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" });
3395
+ return _chunk7EDLVBOOcjs.outlineStroke.call(void 0, line2, { width, cap: "round", join: "round" });
3377
3396
  }
3378
3397
  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;
3398
+ const overlap = _chunk7EDLVBOOcjs.pathBoolean.call(void 0, "intersection", [{ path, fillRule }, { path: region }]).path;
3399
+ if (!_chunk7EDLVBOOcjs.pathToContours.call(void 0, overlap).some((c) => Math.abs(_chunk7EDLVBOOcjs.contourSignedArea.call(void 0, _chunk7EDLVBOOcjs.closeContour.call(void 0, c, true))) > 1e-9)) return null;
3400
+ const rest = _chunk7EDLVBOOcjs.pathBoolean.call(void 0, "difference", [{ path, fillRule }, { path: region }]).path;
3382
3401
  return splitIntoFaces(rest);
3383
3402
  }
3384
3403
  function eraseFromOutline(sp, region) {
3385
- const regionSegs = _chunkGVB7ZPLZcjs.pathToContours.call(void 0, region).flatMap((c) => _chunkGVB7ZPLZcjs.closeContour.call(void 0, c, true));
3404
+ const regionSegs = _chunk7EDLVBOOcjs.pathToContours.call(void 0, region).flatMap((c) => _chunk7EDLVBOOcjs.closeContour.call(void 0, c, true));
3386
3405
  if (!regionSegs.length) return null;
3387
- const rb = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, region);
3406
+ const rb = _chunk7EDLVBOOcjs.bezierPathBounds.call(void 0, region);
3388
3407
  const count = subpathSegmentCount(sp);
3389
3408
  if (!rb || count === 0) return null;
3390
- const removed = (p) => _chunkGVB7ZPLZcjs.pointInBezierPath.call(void 0, region, p, "nonzero");
3409
+ const removed = (p) => _chunk7EDLVBOOcjs.pointInBezierPath.call(void 0, region, p, "nonzero");
3391
3410
  const runs = [];
3392
3411
  let cur = [];
3393
3412
  let any = false;
3394
3413
  for (let i = 0; i < count; i++) {
3395
3414
  const seg = subpathSegment(sp, i);
3396
- const sb = _chunkGVB7ZPLZcjs.segmentBounds.call(void 0, seg);
3415
+ const sb = _chunk7EDLVBOOcjs.segmentBounds.call(void 0, seg);
3397
3416
  const ts = [0, 1];
3398
3417
  if (!(sb.maxX < rb.minX || sb.minX > rb.maxX || sb.maxY < rb.minY || sb.minY > rb.maxY)) {
3399
3418
  for (const r of regionSegs) {
3400
- const b = _chunkGVB7ZPLZcjs.segmentBounds.call(void 0, r);
3419
+ const b = _chunk7EDLVBOOcjs.segmentBounds.call(void 0, r);
3401
3420
  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);
3421
+ for (const hit of _chunk7EDLVBOOcjs.segmentIntersections.call(void 0, seg, r)) if (hit.ta > 1e-9 && hit.ta < 1 - 1e-9) ts.push(hit.ta);
3403
3422
  }
3404
3423
  }
3405
3424
  ts.sort((a, b) => a - b);
@@ -3407,7 +3426,7 @@ function eraseFromOutline(sp, region) {
3407
3426
  const t0 = ts[k];
3408
3427
  const t1 = ts[k + 1];
3409
3428
  if (t1 - t0 < 1e-9) continue;
3410
- if (removed(_chunkGVB7ZPLZcjs.segmentPoint.call(void 0, seg, (t0 + t1) / 2))) {
3429
+ if (removed(_chunk7EDLVBOOcjs.segmentPoint.call(void 0, seg, (t0 + t1) / 2))) {
3411
3430
  any = true;
3412
3431
  if (cur.length) runs.push(cur);
3413
3432
  cur = [];
@@ -3426,7 +3445,7 @@ function eraseFromOutline(sp, region) {
3426
3445
  for (const run of runs) {
3427
3446
  const anchors = [];
3428
3447
  for (const { seg, t0, t1 } of run) {
3429
- const c = _chunkGVB7ZPLZcjs.subSegment.call(void 0, subpathSegment(sp, seg), t0, t1);
3448
+ const c = _chunk7EDLVBOOcjs.subSegment.call(void 0, subpathSegment(sp, seg), t0, t1);
3430
3449
  const line2 = c.length === 2;
3431
3450
  const start = c[0];
3432
3451
  const end = c[c.length - 1];
@@ -3715,15 +3734,187 @@ function recognizeInkShape(points, options = {}) {
3715
3734
  return roundish && rms < 0.1 ? ellipse() : null;
3716
3735
  }
3717
3736
 
3737
+ // src/vector/builder.ts
3738
+ function vectorPathEntries(doc, roots, options = {}) {
3739
+ const out = [];
3740
+ const visit = (node, parent, inside) => {
3741
+ if (node.visible === false || node.locked && !options.locked) return;
3742
+ const picked = inside || roots === null || roots.includes(node.id);
3743
+ if (node.type === "group") {
3744
+ const m = multiplyMatrices(nodeMatrix(node), parent);
3745
+ for (const c of node.children) visit(c, m, picked);
3746
+ } else if (picked) out.push({ node, parent });
3747
+ };
3748
+ for (const n of doc.nodes) visit(n, IDENTITY_MATRIX, false);
3749
+ return out;
3750
+ }
3751
+ var usable = (sp) => sp.anchors.length > 1;
3752
+ function worldOf(entry, subpaths) {
3753
+ return vectorPathWorldBezier({ ...entry.node, subpaths }, entry.parent);
3754
+ }
3755
+ function subpathEnclosesArea(sp) {
3756
+ const contour = _chunk7EDLVBOOcjs.pathToContours.call(void 0, subpathsToBezier([{ ...sp, closed: true }]))[0];
3757
+ if (!contour) return false;
3758
+ const segs = _chunk7EDLVBOOcjs.closeContour.call(void 0, contour, true);
3759
+ const b = _chunk7EDLVBOOcjs.bezierPathBounds.call(void 0, _chunk7EDLVBOOcjs.contoursToPath.call(void 0, [{ segments: segs, closed: true }]));
3760
+ if (!b) return false;
3761
+ const w = b.maxX - b.minX;
3762
+ const h = b.maxY - b.minY;
3763
+ return Math.abs(_chunk7EDLVBOOcjs.contourSignedArea.call(void 0, segs)) > 1e-9 * (w * w + h * h);
3764
+ }
3765
+ var paintKey = (paint) => typeof paint === "string" ? paint.trim().toLowerCase() : JSON.stringify(_nullishCoalesce(paint, () => ( null)));
3766
+ function vectorPathfinderShape(entry, op) {
3767
+ const { node } = entry;
3768
+ const subpaths = node.subpaths.filter(usable);
3769
+ const closed = subpaths.map((s) => ({ ...s, closed: true }));
3770
+ const fillRule = _nullishCoalesce(node.fillRule, () => ( "nonzero"));
3771
+ if (hasPaint(node.fill)) return { path: worldOf(entry, closed), fillRule, key: `fill:${paintKey(node.fill)}`, paint: "fill" };
3772
+ const open = subpaths.length > 0 && subpaths.every((s) => !s.closed);
3773
+ if (op === "divide" && open) return { path: worldOf(entry, subpaths), line: true, paint: "line" };
3774
+ if (hasPaint(node.stroke) && (_nullishCoalesce(node.strokeWidth, () => ( 1))) > 0) {
3775
+ const path = vectorStrokeOutline({ ...node, subpaths }, entry.parent);
3776
+ return { path, fillRule: "nonzero", key: `fill:${paintKey(node.stroke)}`, paint: "stroke" };
3777
+ }
3778
+ return { path: worldOf(entry, closed), fillRule, key: "none", paint: "outline" };
3779
+ }
3780
+ var STROKE_KEYS = [
3781
+ "stroke",
3782
+ "strokeWidth",
3783
+ "strokeLinecap",
3784
+ "strokeLinejoin",
3785
+ "strokeDasharray",
3786
+ "strokeAlign",
3787
+ "startArrow",
3788
+ "endArrow",
3789
+ "arrowAlign",
3790
+ "startArrowScale",
3791
+ "endArrowScale",
3792
+ "strokeWidthProfile"
3793
+ ];
3794
+ function vectorResultStyle(node, paint, edge = false) {
3795
+ const { id: _id, subpaths: _s, transform: _t, ...rest } = node;
3796
+ const base = { ...rest, fillRule: "nonzero" };
3797
+ if (edge) {
3798
+ for (const k of STROKE_KEYS) delete base[k];
3799
+ const stroke = paint === "stroke" || !hasPaint(node.fill) ? node.stroke : node.fill;
3800
+ return { ...base, fill: null, stroke: _nullishCoalesce(stroke, () => ( "#000000")), strokeWidth: _nullishCoalesce(node.strokeWidth, () => ( 1)) };
3801
+ }
3802
+ if (paint === "stroke") {
3803
+ for (const k of STROKE_KEYS) delete base[k];
3804
+ return { ...base, fill: _nullishCoalesce(node.stroke, () => ( null)), stroke: null };
3805
+ }
3806
+ return base;
3807
+ }
3808
+ function vectorShapeBuilderMap(entries) {
3809
+ const lines = [];
3810
+ const inputs = entries.map((entry) => {
3811
+ const filled = hasPaint(entry.node.fill);
3812
+ const subpaths = entry.node.subpaths.filter(usable).map((sp) => !sp.closed && filled && subpathEnclosesArea(sp) ? { ...sp, closed: true } : sp);
3813
+ lines.push(!subpaths.some((s) => s.closed));
3814
+ return { path: worldOf(entry, subpaths), fillRule: _nullishCoalesce(entry.node.fillRule, () => ( "nonzero")) };
3815
+ });
3816
+ const map = _chunk7EDLVBOOcjs.PlanarMap.build(inputs);
3817
+ if (!map) return null;
3818
+ const pieces = map.chains().filter((c) => lines[c.source] && !c.closed).map((c) => {
3819
+ const path = _chunk7EDLVBOOcjs.contoursToPath.call(void 0, [{ segments: c.segments, closed: false }]);
3820
+ return { path, segments: c.segments, source: c.source, bounds: _chunk7EDLVBOOcjs.bezierPathBounds.call(void 0, path) };
3821
+ });
3822
+ return { entries: [...entries], map, lines, pieces };
3823
+ }
3824
+ function vectorShapeBuilderHit(m, p, lineTolerance = null) {
3825
+ const point = [p.x, p.y];
3826
+ if (lineTolerance !== null && lineTolerance > 0) {
3827
+ let best = -1;
3828
+ let bestD = lineTolerance;
3829
+ m.pieces.forEach((piece, i) => {
3830
+ const b = piece.bounds;
3831
+ if (p.x < b.minX - bestD || p.x > b.maxX + bestD || p.y < b.minY - bestD || p.y > b.maxY + bestD) return;
3832
+ const d = _chunk7EDLVBOOcjs.distanceToBezierPath.call(void 0, piece.path, point);
3833
+ if (d <= bestD) {
3834
+ best = i;
3835
+ bestD = d;
3836
+ }
3837
+ });
3838
+ if (best >= 0) return { line: best };
3839
+ }
3840
+ const face = m.map.faceAt(point);
3841
+ return face >= 0 ? { face } : null;
3842
+ }
3843
+ function samplePolyline(points, step) {
3844
+ const out = [];
3845
+ const s = Math.max(step, 1e-3);
3846
+ points.forEach((p, i) => {
3847
+ if (i > 0) {
3848
+ const a = points[i - 1];
3849
+ const n = Math.min(4e3, Math.ceil(Math.hypot(p.x - a.x, p.y - a.y) / s));
3850
+ 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 });
3851
+ }
3852
+ out.push(p);
3853
+ });
3854
+ return out;
3855
+ }
3856
+ function addBuilderHit(touched, hit) {
3857
+ if (!hit) return false;
3858
+ const [list, i] = "face" in hit ? [touched.faces, hit.face] : [touched.lines, hit.line];
3859
+ if (list.includes(i)) return false;
3860
+ list.push(i);
3861
+ return true;
3862
+ }
3863
+ function sides(m, piece) {
3864
+ const seg = piece.segments[Math.floor(piece.segments.length / 2)];
3865
+ const mid = _chunk7EDLVBOOcjs.segmentPoint.call(void 0, seg, 0.5);
3866
+ const t = _chunk7EDLVBOOcjs.segmentTangent.call(void 0, seg, 0.5);
3867
+ const chord = Math.hypot(seg[seg.length - 1][0] - seg[0][0], seg[seg.length - 1][1] - seg[0][1]);
3868
+ const off = Math.max(1e-6, Math.min(0.05, 0.05 * chord));
3869
+ 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])];
3870
+ }
3871
+ function planShapeBuilder(m, touched, erase) {
3872
+ const replace = /* @__PURE__ */ new Map();
3873
+ const picked = new Set(touched.faces);
3874
+ const faces = m.map.faces;
3875
+ const sourcesOf = faces.map((_, i) => m.map.faceSources(i));
3876
+ m.entries.forEach((_, i) => {
3877
+ if (m.lines[i]) {
3878
+ const own = m.pieces.flatMap((piece, k) => piece.source === i ? [k] : []);
3879
+ const keep = own.filter((k) => !touched.lines.includes(k) && !sides(m, m.pieces[k]).every((f) => f >= 0 && picked.has(f)));
3880
+ if (keep.length === own.length) return;
3881
+ replace.set(i, keep.length ? { kind: "pieces", paths: keep.map((k) => m.pieces[k].path) } : null);
3882
+ return;
3883
+ }
3884
+ if (!touched.faces.some((f) => sourcesOf[f].includes(i))) return;
3885
+ const kept = faces.flatMap((_2, f) => sourcesOf[f].includes(i) && !picked.has(f) ? [f] : []);
3886
+ const rest = kept.length ? m.map.merge(kept) : [];
3887
+ replace.set(i, rest.length ? { kind: "fill", path: rest } : null);
3888
+ });
3889
+ let merged = null;
3890
+ if (!erase && touched.faces.length) {
3891
+ const path = m.map.merge(touched.faces);
3892
+ const covered = touched.faces.map((f) => sourcesOf[f]).find((s) => s.length);
3893
+ const lastShape = m.lines.lastIndexOf(false);
3894
+ const style = covered ? covered[covered.length - 1] : lastShape >= 0 ? lastShape : m.entries.length - 1;
3895
+ if (path.length) merged = { path, style, currentFill: !covered };
3896
+ }
3897
+ return { replace, merged };
3898
+ }
3899
+ function vectorFillMap(doc, gap = 0) {
3900
+ const entries = vectorPathEntries(doc, null, { locked: true });
3901
+ return _chunk7EDLVBOOcjs.PlanarMap.build(
3902
+ entries.map((e) => ({ path: worldOf(e, e.node.subpaths.filter(usable)), fills: false })),
3903
+ { gap, maxSegments: 2e4 }
3904
+ );
3905
+ }
3906
+
3718
3907
  // src/vector/controller.ts
3719
3908
  var DEFAULT_VECTOR_SNAP = { grid: 0, objects: true, guides: true, threshold: 5, angles: VECTOR_CONSTRUCTION_ANGLES };
3909
+ var VECTOR_FILL_GAP = 6;
3720
3910
  var DEFAULT_VECTOR_PATH_EDIT = {
3721
3911
  keepShapeOnDelete: true,
3722
3912
  curvatureMoves: false,
3723
3913
  pencilSmoothing: 0,
3724
3914
  recognizeShapes: false,
3725
3915
  eraserSize: 10,
3726
- pencilPressure: "pen"
3916
+ pencilPressure: "pen",
3917
+ fillGap: 0
3727
3918
  };
3728
3919
  var VECTOR_PENCIL_STRING_PX = 100;
3729
3920
  var VECTOR_STYLE_KEYS = [
@@ -3769,7 +3960,7 @@ function getEditablePathIds(state) {
3769
3960
  }
3770
3961
  }
3771
3962
  }
3772
- return [...ids].filter((id) => _optionalChain([findVectorNode, 'call', _62 => _62(state.document.nodes, id), 'optionalAccess', _63 => _63.type]) === "path");
3963
+ return [...ids].filter((id) => _optionalChain([findVectorNode, 'call', _63 => _63(state.document.nodes, id), 'optionalAccess', _64 => _64.type]) === "path");
3773
3964
  }
3774
3965
  function getVisibleAnchors(state) {
3775
3966
  const out = [];
@@ -3784,7 +3975,7 @@ function getVisibleHandles(state) {
3784
3975
  const seen = /* @__PURE__ */ new Set();
3785
3976
  const push = (node, s, i, handle) => {
3786
3977
  const sp = node.subpaths[s];
3787
- const a = _optionalChain([sp, 'optionalAccess', _64 => _64.anchors, 'access', _65 => _65[i]]);
3978
+ const a = _optionalChain([sp, 'optionalAccess', _65 => _65.anchors, 'access', _66 => _66[i]]);
3788
3979
  if (!a || !a[handle]) return;
3789
3980
  const key = `${node.id}:${s}:${i}:${handle}`;
3790
3981
  if (seen.has(key)) return;
@@ -3793,8 +3984,8 @@ function getVisibleHandles(state) {
3793
3984
  };
3794
3985
  if (state.tool === "pen" && state.pen) {
3795
3986
  const node = findVectorNode(state.document.nodes, state.pen.nodeId);
3796
- const sp = _optionalChain([node, 'optionalAccess', _66 => _66.type]) === "path" ? node.subpaths[state.pen.subpath] : void 0;
3797
- if (_optionalChain([node, 'optionalAccess', _67 => _67.type]) === "path" && sp) {
3987
+ const sp = _optionalChain([node, 'optionalAccess', _67 => _67.type]) === "path" ? node.subpaths[state.pen.subpath] : void 0;
3988
+ if (_optionalChain([node, 'optionalAccess', _68 => _68.type]) === "path" && sp) {
3798
3989
  const last = sp.anchors.length - 1;
3799
3990
  push(node, state.pen.subpath, last, "in");
3800
3991
  push(node, state.pen.subpath, last, "out");
@@ -3832,11 +4023,11 @@ function getVectorCornerWidgets(state) {
3832
4023
  const side = Math.min(c.lu, c.lv);
3833
4024
  if (side * zoom < 3 * VECTOR_CORNER_WIDGET_INSET) continue;
3834
4025
  const a = node.subpaths[c.subpath].anchors[c.index];
3835
- const radius = _nullishCoalesce(_optionalChain([a, 'access', _68 => _68.corner, 'optionalAccess', _69 => _69.radius]), () => ( 0));
4026
+ const radius = _nullishCoalesce(_optionalChain([a, 'access', _69 => _69.corner, 'optionalAccess', _70 => _70.radius]), () => ( 0));
3836
4027
  const drawn = fitCornerRadius(c, radius);
3837
4028
  const k = Math.min(Math.max(drawn / c.sin, VECTOR_CORNER_WIDGET_INSET / (zoom * Math.sqrt(1 + c.cos))), side / 2);
3838
4029
  const p = applyMatrix(m, cornerBisectorPoint(c, k));
3839
- out.push({ ref: { nodeId: id, subpath: c.subpath, index: c.index }, x: p.x, y: p.y, radius, drawnRadius: drawn, kind: _nullishCoalesce(_optionalChain([a, 'access', _70 => _70.corner, 'optionalAccess', _71 => _71.kind]), () => ( "round")), corner: c });
4030
+ out.push({ ref: { nodeId: id, subpath: c.subpath, index: c.index }, x: p.x, y: p.y, radius, drawnRadius: drawn, kind: _nullishCoalesce(_optionalChain([a, 'access', _71 => _71.corner, 'optionalAccess', _72 => _72.kind]), () => ( "round")), corner: c });
3840
4031
  }
3841
4032
  }
3842
4033
  return out;
@@ -3853,13 +4044,13 @@ function getVectorWidthHandles(state) {
3853
4044
  const n = findVectorNode(state.document.nodes, id);
3854
4045
  if (n) for (const p of collectPathNodes(n)) ids.add(p.id);
3855
4046
  }
3856
- if (_optionalChain([state, 'access', _72 => _72.hover, 'optionalAccess', _73 => _73.nodeId])) ids.add(state.hover.nodeId);
3857
- if (_optionalChain([state, 'access', _74 => _74.interaction, 'optionalAccess', _75 => _75.type]) === "width") ids.add(state.interaction.ref.nodeId);
4047
+ if (_optionalChain([state, 'access', _73 => _73.hover, 'optionalAccess', _74 => _74.nodeId])) ids.add(state.hover.nodeId);
4048
+ if (_optionalChain([state, 'access', _75 => _75.interaction, 'optionalAccess', _76 => _76.type]) === "width") ids.add(state.interaction.ref.nodeId);
3858
4049
  if (state.selectedWidthPoint) ids.add(state.selectedWidthPoint.nodeId);
3859
4050
  const out = [];
3860
4051
  for (const id of ids) {
3861
4052
  const node = findVectorNode(state.document.nodes, id);
3862
- if (_optionalChain([node, 'optionalAccess', _76 => _76.type]) !== "path" || node.visible === false || !_optionalChain([node, 'access', _77 => _77.strokeWidthProfile, 'optionalAccess', _78 => _78.length])) continue;
4053
+ if (_optionalChain([node, 'optionalAccess', _77 => _77.type]) !== "path" || node.visible === false || !_optionalChain([node, 'access', _78 => _78.strokeWidthProfile, 'optionalAccess', _79 => _79.length])) continue;
3863
4054
  const g = vectorStrokeWidthGeometry(node);
3864
4055
  if (!g) continue;
3865
4056
  const profile = sanitizeWidthProfile(node.strokeWidthProfile);
@@ -3893,7 +4084,7 @@ function getVectorWidthHandles(state) {
3893
4084
  }
3894
4085
  function getAnchor(doc, ref) {
3895
4086
  const node = findVectorNode(doc.nodes, ref.nodeId);
3896
- return _optionalChain([node, 'optionalAccess', _79 => _79.type]) === "path" ? _optionalChain([node, 'access', _80 => _80.subpaths, 'access', _81 => _81[ref.subpath], 'optionalAccess', _82 => _82.anchors, 'access', _83 => _83[ref.index]]) : void 0;
4087
+ return _optionalChain([node, 'optionalAccess', _80 => _80.type]) === "path" ? _optionalChain([node, 'access', _81 => _81.subpaths, 'access', _82 => _82[ref.subpath], 'optionalAccess', _83 => _83.anchors, 'access', _84 => _84[ref.index]]) : void 0;
3897
4088
  }
3898
4089
  function getAnchorWorld(doc, ref) {
3899
4090
  const a = getAnchor(doc, ref);
@@ -3962,9 +4153,27 @@ var TOOL_LABELS = {
3962
4153
  scissors: "Scissors",
3963
4154
  knife: "Knife",
3964
4155
  eraser: "Eraser",
3965
- width: "Width"
4156
+ width: "Width",
4157
+ shapeBuilder: "Shape Builder",
4158
+ paintBucket: "Paint Bucket"
4159
+ };
4160
+ var TOOL_KEYS = {
4161
+ v: "select",
4162
+ a: "direct",
4163
+ p: "pen",
4164
+ n: "pencil",
4165
+ r: "rect",
4166
+ o: "ellipse",
4167
+ y: "polygon",
4168
+ s: "star",
4169
+ l: "line",
4170
+ c: "scissors",
4171
+ k: "knife",
4172
+ e: "eraser",
4173
+ w: "width",
4174
+ m: "shapeBuilder",
4175
+ b: "paintBucket"
3966
4176
  };
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
4177
  function vectorToolLabel(tool) {
3969
4178
  return TOOL_LABELS[tool];
3970
4179
  }
@@ -3981,7 +4190,9 @@ var VECTOR_TOOL_SHORTCUTS = {
3981
4190
  scissors: "C",
3982
4191
  knife: "K",
3983
4192
  eraser: "E",
3984
- width: "W"
4193
+ width: "W",
4194
+ shapeBuilder: "M",
4195
+ paintBucket: "B"
3985
4196
  };
3986
4197
  var VECTOR_TOOL_GLYPHS = {
3987
4198
  select: "\u2196",
@@ -3996,7 +4207,9 @@ var VECTOR_TOOL_GLYPHS = {
3996
4207
  scissors: "\u2702",
3997
4208
  knife: "\u27CB",
3998
4209
  eraser: "\u232B",
3999
- width: "\u21F9"
4210
+ width: "\u21F9",
4211
+ shapeBuilder: "\u2295",
4212
+ paintBucket: "\u25CD"
4000
4213
  };
4001
4214
  var SHAPE_TOOLS = /* @__PURE__ */ new Set(["rect", "ellipse", "polygon", "star", "line"]);
4002
4215
  var BOOLEAN_OPS = {
@@ -4006,6 +4219,14 @@ var BOOLEAN_OPS = {
4006
4219
  exclude: "xor"
4007
4220
  };
4008
4221
  var BOOLEAN_LABELS = { union: "Union", subtract: "Subtract", intersect: "Intersect", exclude: "Exclude" };
4222
+ var VECTOR_PATHFINDER_LABELS = {
4223
+ divide: "Divide",
4224
+ trim: "Trim",
4225
+ merge: "Merge",
4226
+ crop: "Crop",
4227
+ outline: "Outline",
4228
+ minusBack: "Minus Back"
4229
+ };
4009
4230
  function mapTree(nodes, fn) {
4010
4231
  let changed = false;
4011
4232
  const out = [];
@@ -4070,16 +4291,23 @@ var VectorEditorController = (_class3 = class {
4070
4291
  __init20() {this.hoverTargets = null}
4071
4292
  __init21() {this.spaceHeld = false}
4072
4293
  __init22() {this.clipboard = null}
4294
+ /** Shape Builder map of the selection, kept while the document and the selection stay the same. */
4295
+ __init23() {this.builderCache = null}
4296
+ /** Paint bucket map of the visible outlines. */
4297
+ __init24() {this.fillCache = null}
4298
+ __init25() {this.builderPreview = null}
4299
+ /** What the highlight shows, to skip notifying when the pointer stays over the same face. */
4300
+ __init26() {this.builderHoverKey = null}
4073
4301
 
4074
4302
 
4075
- __init23() {this.listeners = /* @__PURE__ */ new Set()}
4076
- __init24() {this.cleanups = []}
4077
- __init25() {this.applying = false}
4303
+ __init27() {this.listeners = /* @__PURE__ */ new Set()}
4304
+ __init28() {this.cleanups = []}
4305
+ __init29() {this.applying = false}
4078
4306
  /** 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}
4307
+ __init30() {this.committing = false}
4308
+ __init31() {this.revision = 0}
4081
4309
 
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);
4310
+ 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
4311
  this.history = _nullishCoalesce(options.history, () => ( new (0, _chunkQKLRAA4Tcjs.HistoryManager)()));
4084
4312
  this.doc = options.document ? cloneVectorDocument(options.document) : { width: 800, height: 600, nodes: [] };
4085
4313
  this.tool = _nullishCoalesce(options.tool, () => ( "select"));
@@ -4108,9 +4336,9 @@ var VectorEditorController = (_class3 = class {
4108
4336
  // State
4109
4337
  // -------------------------------------------------------------------------
4110
4338
  /** The current snapshot (stable until the next change). */
4111
- __init28() {this.getState = () => this.state}
4339
+ __init32() {this.getState = () => this.state}
4112
4340
  /** Calls `listener` after every change. Returns an unsubscribe function. */
4113
- __init29() {this.subscribe = (listener) => {
4341
+ __init33() {this.subscribe = (listener) => {
4114
4342
  this.listeners.add(listener);
4115
4343
  return () => {
4116
4344
  this.listeners.delete(listener);
@@ -4144,6 +4372,7 @@ var VectorEditorController = (_class3 = class {
4144
4372
  interaction: this.interaction,
4145
4373
  pen: this.pen,
4146
4374
  pointer: this.pointer,
4375
+ builder: this.builderPreview,
4147
4376
  canUndo: h.canUndo,
4148
4377
  canRedo: h.canRedo,
4149
4378
  undoLabel: h.undoName,
@@ -4154,7 +4383,7 @@ var VectorEditorController = (_class3 = class {
4154
4383
  notify(docChanged = false) {
4155
4384
  this.revision++;
4156
4385
  this.state = this.computeState();
4157
- if (docChanged) _optionalChain([this, 'access', _84 => _84.onChange, 'optionalCall', _85 => _85(this.doc)]);
4386
+ if (docChanged) _optionalChain([this, 'access', _85 => _85.onChange, 'optionalCall', _86 => _86(this.doc)]);
4158
4387
  const state = this.state;
4159
4388
  this.listeners.forEach((listener) => {
4160
4389
  try {
@@ -4184,24 +4413,29 @@ var VectorEditorController = (_class3 = class {
4184
4413
  return applyMatrix(invertMatrix(this.worldOf(id, doc)), p);
4185
4414
  }
4186
4415
  cursorFor() {
4187
- if (_optionalChain([this, 'access', _86 => _86.drag, 'optionalAccess', _87 => _87.kind]) === "pan" || this.spaceHeld) return this.drag ? "grabbing" : "grab";
4188
- if (_optionalChain([this, 'access', _88 => _88.drag, 'optionalAccess', _89 => _89.kind]) === "rotate") return "grabbing";
4189
- if (_optionalChain([this, 'access', _90 => _90.drag, 'optionalAccess', _91 => _91.kind]) === "move") return "move";
4416
+ if (_optionalChain([this, 'access', _87 => _87.drag, 'optionalAccess', _88 => _88.kind]) === "pan" || this.spaceHeld) return this.drag ? "grabbing" : "grab";
4417
+ if (_optionalChain([this, 'access', _89 => _89.drag, 'optionalAccess', _90 => _90.kind]) === "rotate") return "grabbing";
4418
+ if (_optionalChain([this, 'access', _91 => _91.drag, 'optionalAccess', _92 => _92.kind]) === "move") return "move";
4190
4419
  const h = this.hover;
4191
4420
  switch (this.tool) {
4192
4421
  case "select":
4193
- if (_optionalChain([h, 'optionalAccess', _92 => _92.transformHandle])) return vectorResizeCursor(h.transformHandle, _nullishCoalesce(_optionalChain([this, 'access', _93 => _93.frameOf, 'call', _94 => _94(this.selectedRoots()), 'optionalAccess', _95 => _95.angle]), () => ( 0)));
4194
- return _optionalChain([h, 'optionalAccess', _96 => _96.nodeId]) ? "move" : "default";
4422
+ if (_optionalChain([h, 'optionalAccess', _93 => _93.transformHandle])) return vectorResizeCursor(h.transformHandle, _nullishCoalesce(_optionalChain([this, 'access', _94 => _94.frameOf, 'call', _95 => _95(this.selectedRoots()), 'optionalAccess', _96 => _96.angle]), () => ( 0)));
4423
+ return _optionalChain([h, 'optionalAccess', _97 => _97.nodeId]) ? "move" : "default";
4195
4424
  case "direct":
4196
- if (_optionalChain([h, 'optionalAccess', _97 => _97.anchor]) || _optionalChain([h, 'optionalAccess', _98 => _98.handle]) || _optionalChain([h, 'optionalAccess', _99 => _99.corner])) return "pointer";
4197
- if (_optionalChain([h, 'optionalAccess', _100 => _100.segment])) return "copy";
4198
- return _optionalChain([h, 'optionalAccess', _101 => _101.nodeId]) ? "move" : "default";
4425
+ if (_optionalChain([h, 'optionalAccess', _98 => _98.anchor]) || _optionalChain([h, 'optionalAccess', _99 => _99.handle]) || _optionalChain([h, 'optionalAccess', _100 => _100.corner])) return "pointer";
4426
+ if (_optionalChain([h, 'optionalAccess', _101 => _101.segment])) return "copy";
4427
+ return _optionalChain([h, 'optionalAccess', _102 => _102.nodeId]) ? "move" : "default";
4199
4428
  case "pen":
4200
- return _optionalChain([h, 'optionalAccess', _102 => _102.anchor]) ? "pointer" : "crosshair";
4429
+ return _optionalChain([h, 'optionalAccess', _103 => _103.anchor]) ? "pointer" : "crosshair";
4201
4430
  case "width":
4202
- if (_optionalChain([this, 'access', _103 => _103.drag, 'optionalAccess', _104 => _104.kind]) === "width") return this.drag.mode === "move" ? "grabbing" : "ew-resize";
4203
- if (_optionalChain([h, 'optionalAccess', _105 => _105.widthPoint])) return h.widthPoint.part === "center" ? "grab" : "ew-resize";
4204
- return _optionalChain([h, 'optionalAccess', _106 => _106.strokeSpot]) ? "copy" : "default";
4431
+ if (_optionalChain([this, 'access', _104 => _104.drag, 'optionalAccess', _105 => _105.kind]) === "width") return this.drag.mode === "move" ? "grabbing" : "ew-resize";
4432
+ if (_optionalChain([h, 'optionalAccess', _106 => _106.widthPoint])) return h.widthPoint.part === "center" ? "grab" : "ew-resize";
4433
+ return _optionalChain([h, 'optionalAccess', _107 => _107.strokeSpot]) ? "copy" : "default";
4434
+ case "shapeBuilder":
4435
+ if (!_optionalChain([this, 'access', _108 => _108.builderPreview, 'optionalAccess', _109 => _109.faces, 'access', _110 => _110.length]) && !_optionalChain([this, 'access', _111 => _111.builderPreview, 'optionalAccess', _112 => _112.lines, 'access', _113 => _113.length])) return "crosshair";
4436
+ return this.builderPreview.mode === "erase" ? "not-allowed" : "cell";
4437
+ case "paintBucket":
4438
+ return this.builderPreview ? "cell" : "crosshair";
4205
4439
  default:
4206
4440
  return "crosshair";
4207
4441
  }
@@ -4221,7 +4455,7 @@ var VectorEditorController = (_class3 = class {
4221
4455
  this.selection = s.selection.filter((id) => this.getNode(id));
4222
4456
  this.anchors = s.anchors.filter((r) => getAnchor(this.doc, r));
4223
4457
  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;
4458
+ this.pen = s.pen && _optionalChain([this, 'access', _114 => _114.getNode, 'call', _115 => _115(s.pen.nodeId), 'optionalAccess', _116 => _116.subpaths, 'optionalAccess', _117 => _117[s.pen.subpath]]) ? s.pen : null;
4225
4459
  } finally {
4226
4460
  this.applying = false;
4227
4461
  }
@@ -4328,6 +4562,8 @@ var VectorEditorController = (_class3 = class {
4328
4562
  this.hover = null;
4329
4563
  this.guides = null;
4330
4564
  this.widthPoint = null;
4565
+ this.builderPreview = null;
4566
+ this.builderHoverKey = null;
4331
4567
  if (tool !== "direct") {
4332
4568
  this.anchors = [];
4333
4569
  this.editingId = null;
@@ -4386,7 +4622,7 @@ var VectorEditorController = (_class3 = class {
4386
4622
  if (res.kind) {
4387
4623
  this.snappedToObject = true;
4388
4624
  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) };
4625
+ return _optionalChain([leave, 'optionalAccess', _118 => _118.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
4626
  }
4391
4627
  }
4392
4628
  this.setGuides(null);
@@ -4404,14 +4640,14 @@ var VectorEditorController = (_class3 = class {
4404
4640
  /** Where the pointer at `p` would place a point with the pen or a shape tool (and the guides showing why). */
4405
4641
  hoverSnap(p, input) {
4406
4642
  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])) {
4643
+ const sp = this.pen ? _optionalChain([this, 'access', _119 => _119.getNode, 'call', _120 => _120(this.pen.nodeId), 'optionalAccess', _121 => _121.subpaths, 'access', _122 => _122[this.pen.subpath]]) : void 0;
4644
+ if (this.pen && sp && _optionalChain([this, 'access', _123 => _123.hover, 'optionalAccess', _124 => _124.anchor])) {
4409
4645
  this.setGuides(null);
4410
4646
  return p;
4411
4647
  }
4412
4648
  const last = this.pen && sp ? getAnchorWorld(this.doc, { nodeId: this.pen.nodeId, subpath: this.pen.subpath, index: sp.anchors.length - 1 }) : void 0;
4413
4649
  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))));
4650
+ return this.snapDrawn(p, leave, input, () => this.drawingTargets(_nullishCoalesce(_optionalChain([this, 'access', _125 => _125.pen, 'optionalAccess', _126 => _126.nodeId]), () => ( null))));
4415
4651
  }
4416
4652
  if (SHAPE_TOOLS.has(this.tool)) return this.snapDrawn(p, null, input, () => this.drawingTargets(null));
4417
4653
  this.setGuides(null);
@@ -4559,7 +4795,7 @@ var VectorEditorController = (_class3 = class {
4559
4795
  if (d.fillRule) out.fillRule = d.fillRule;
4560
4796
  if (d.strokeAlign && d.strokeAlign !== "center") out.strokeAlign = d.strokeAlign;
4561
4797
  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 }));
4798
+ if (_optionalChain([d, 'access', _127 => _127.strokeWidthProfile, 'optionalAccess', _128 => _128.length])) out.strokeWidthProfile = d.strokeWidthProfile.map((p) => ({ ...p }));
4563
4799
  return out;
4564
4800
  }
4565
4801
  /** Merges `patch` into a node (paths take style and geometry; groups name / visibility / opacity). */
@@ -4607,7 +4843,7 @@ var VectorEditorController = (_class3 = class {
4607
4843
  /** Removes one width point of a path's profile (the width tool's Delete). */
4608
4844
  removeWidthPoint(ref) {
4609
4845
  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." };
4846
+ if (_optionalChain([node, 'optionalAccess', _129 => _129.type]) !== "path" || !_optionalChain([node, 'access', _130 => _130.strokeWidthProfile, 'optionalAccess', _131 => _131[ref.index]])) return { ok: false, message: "There is no such width point." };
4611
4847
  const rest = removeWidthPoints(sanitizeWidthProfile(node.strokeWidthProfile), [ref.index]);
4612
4848
  this.widthPoint = null;
4613
4849
  this.change("Delete Width Point", () => this.replaceNode(node.id, withStyle(node, { strokeWidthProfile: rest.length ? rest : null })));
@@ -4632,7 +4868,7 @@ var VectorEditorController = (_class3 = class {
4632
4868
  const refs = this.cornerTargets(options);
4633
4869
  if (!refs.length) return { ok: false, message: "Nothing is selected." };
4634
4870
  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));
4871
+ this.doc = this.updateAnchors(this.doc, refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access', _132 => _132.corner, 'optionalAccess', _133 => _133.radius]), () => ( 0)), kind));
4636
4872
  });
4637
4873
  return { ok: true };
4638
4874
  }
@@ -4771,10 +5007,10 @@ var VectorEditorController = (_class3 = class {
4771
5007
  return this.selection.filter((id) => {
4772
5008
  let covered = false;
4773
5009
  const loc = locateVectorNode(this.doc.nodes, id);
4774
- let parent = _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _127 => _127.parent]), () => ( null));
5010
+ let parent = _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _134 => _134.parent]), () => ( null));
4775
5011
  while (parent) {
4776
5012
  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));
5013
+ parent = _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _135 => _135(this.doc.nodes, parent.id), 'optionalAccess', _136 => _136.parent]), () => ( null));
4778
5014
  }
4779
5015
  return !covered;
4780
5016
  });
@@ -4957,8 +5193,8 @@ var VectorEditorController = (_class3 = class {
4957
5193
  if (!ids.length) return null;
4958
5194
  const locs = ids.map((id2) => locateVectorNode(this.doc.nodes, id2));
4959
5195
  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;
5196
+ const parent = _nullishCoalesce(_optionalChain([locs, 'access', _137 => _137[0], 'access', _138 => _138.parent, 'optionalAccess', _139 => _139.id]), () => ( null));
5197
+ if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _140 => _140.parent, 'optionalAccess', _141 => _141.id]), () => ( null))) !== parent)) return null;
4962
5198
  const id = this.newId();
4963
5199
  this.change("Group", () => {
4964
5200
  const set = new Set(ids);
@@ -4981,7 +5217,7 @@ var VectorEditorController = (_class3 = class {
4981
5217
  }
4982
5218
  /** Replaces selected groups with their children. */
4983
5219
  ungroup(options = {}) {
4984
- const groups = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _135 => _135.type]) === "group");
5220
+ const groups = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _142 => _142.type]) === "group");
4985
5221
  if (!groups.length) return { ok: false, message: "Select a group to ungroup." };
4986
5222
  const set = new Set(groups.map((g) => g.id));
4987
5223
  this.change("Ungroup", () => {
@@ -5041,7 +5277,7 @@ var VectorEditorController = (_class3 = class {
5041
5277
  });
5042
5278
  const paths = [...new Set(order)].map((id2) => this.getNode(id2));
5043
5279
  if (paths.length < 2) return null;
5044
- const result = _chunkGVB7ZPLZcjs.pathBoolean.call(void 0,
5280
+ const result = _chunk7EDLVBOOcjs.pathBoolean.call(void 0,
5045
5281
  BOOLEAN_OPS[op],
5046
5282
  paths.map((p) => ({
5047
5283
  path: vectorPathWorldBezier(
@@ -5091,11 +5327,11 @@ var VectorEditorController = (_class3 = class {
5091
5327
  /** A document-space path mapped into the parent space of node `id`. */
5092
5328
  intoParentSpace(id, path) {
5093
5329
  const parent = _nullishCoalesce(vectorParentMatrix(this.doc.nodes, id), () => ( IDENTITY_MATRIX));
5094
- return isRoot(parent) ? path : _chunkGVB7ZPLZcjs.transformBezierPath.call(void 0, path, invertMatrix(parent));
5330
+ return isRoot(parent) ? path : _chunk7EDLVBOOcjs.transformBezierPath.call(void 0, path, invertMatrix(parent));
5095
5331
  }
5096
5332
  /** Splits selected compound paths into one path per subpath. */
5097
5333
  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);
5334
+ const paths = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _143 => _143.type]) === "path" && n.subpaths.length > 1);
5099
5335
  if (!paths.length) return { ok: false, message: "Select a compound path to break apart." };
5100
5336
  const created = [];
5101
5337
  const set = new Set(paths.map((p) => p.id));
@@ -5115,6 +5351,248 @@ var VectorEditorController = (_class3 = class {
5115
5351
  return { ok: true };
5116
5352
  }
5117
5353
  // -------------------------------------------------------------------------
5354
+ // Pathfinder, Shape Builder and paint bucket
5355
+ // -------------------------------------------------------------------------
5356
+ /**
5357
+ * Pathfinder: Divide, Trim, Merge, Crop, Outline or Minus Back over the selected (or given)
5358
+ * paths, in document space (rotated nodes and groups included, live corners cut). Unfilled
5359
+ * stroked paths take part as the area their stroke paints (Divide: open ones cut instead).
5360
+ * The results replace the operands at the place of the top-most one, grouped when there are
5361
+ * several; each keeps the style of the operand whose area it is. Returns the new path ids,
5362
+ * or an empty list when nothing came out.
5363
+ */
5364
+ pathfinder(op, options = {}) {
5365
+ const roots = _nullishCoalesce(options.ids, () => ( this.selectedRoots()));
5366
+ const entries = vectorPathEntries(this.doc, roots);
5367
+ if (entries.length < (op === "divide" || op === "outline" ? 1 : 2)) return [];
5368
+ const shapes = entries.map((e) => vectorPathfinderShape(e, op));
5369
+ const result = _chunk7EDLVBOOcjs.pathfinder.call(void 0, op, shapes);
5370
+ if (result.error || !result.pieces.length) return [];
5371
+ const last = entries[entries.length - 1].node.id;
5372
+ const topRoot = _nullishCoalesce([...roots].reverse().find((r) => {
5373
+ const n = this.getNode(r);
5374
+ return !!n && !!findVectorNode([n], last);
5375
+ }), () => ( last));
5376
+ const nodes = [];
5377
+ for (const piece of result.pieces) {
5378
+ const subpaths = bezierToSubpaths(this.intoParentSpace(topRoot, piece.path)).map((sp) => piece.open ? { ...sp, closed: false } : sp);
5379
+ if (!subpaths.length) continue;
5380
+ const source = entries[piece.source].node;
5381
+ const style = vectorResultStyle(source, shapes[piece.source].paint, op === "outline");
5382
+ nodes.push({ ...style, type: "path", id: this.newId(), name: _nullishCoalesce(source.name, () => ( "Path")), subpaths });
5383
+ }
5384
+ if (!nodes.length) return [];
5385
+ const label = VECTOR_PATHFINDER_LABELS[op];
5386
+ const container = nodes.length > 1 ? { id: this.newId(), type: "group", name: label, children: nodes } : nodes[0];
5387
+ const drop = /* @__PURE__ */ new Set([...entries.map((e) => e.node.id), ...roots]);
5388
+ this.change(label, () => {
5389
+ this.setDoc(mapTree(this.doc.nodes, (n) => n.id === topRoot ? container : drop.has(n.id) ? null : n));
5390
+ this.selection = [container.id];
5391
+ this.anchors = [];
5392
+ this.editingId = null;
5393
+ });
5394
+ return nodes.map((n) => n.id);
5395
+ }
5396
+ /** The Shape Builder map of the selected (or given) paths, cached per document and selection. */
5397
+ shapeBuilderMap(ids) {
5398
+ const roots = _nullishCoalesce(ids, () => ( this.selectedRoots()));
5399
+ const key = roots.join("\0");
5400
+ if (_optionalChain([this, 'access', _144 => _144.builderCache, 'optionalAccess', _145 => _145.doc]) === this.doc && this.builderCache.key === key) return this.builderCache.map;
5401
+ const entries = roots.length ? vectorPathEntries(this.doc, roots) : [];
5402
+ const map = entries.length ? vectorShapeBuilderMap(entries) : null;
5403
+ this.builderCache = { doc: this.doc, key, map };
5404
+ return map;
5405
+ }
5406
+ /** The faces the Shape Builder offers for the selected (or given) paths (document units). */
5407
+ getShapeBuilderFaces(options = {}) {
5408
+ const m = this.shapeBuilderMap(options.ids);
5409
+ if (!m) return [];
5410
+ return m.map.faces.map((f, index) => {
5411
+ const p = m.map.faceInterior(index);
5412
+ return {
5413
+ index,
5414
+ d: _chunk7EDLVBOOcjs.bezierPathToSvg.call(void 0, f.path, { precision: 3 }),
5415
+ area: f.area,
5416
+ sources: m.map.faceSources(index).map((i) => m.entries[i].node.id),
5417
+ point: p ? { x: p[0], y: p[1] } : null
5418
+ };
5419
+ });
5420
+ }
5421
+ /** Pick distance of the Shape Builder's erase for line pieces (document units). */
5422
+ builderLineTolerance() {
5423
+ return Math.max(this.hitRadius, 4) / this.viewport.zoom;
5424
+ }
5425
+ /**
5426
+ * Shape Builder gesture along `points` (document units; one point is a click) over the faces
5427
+ * the selected (or given) paths make. Merges the faces touched into one shape styled like the
5428
+ * top-most shape over the first face (the current fill for a face only outlines enclose);
5429
+ * with `erase` deletes them, and the pieces of unfilled open paths within `tolerance`. Every
5430
+ * shape covering a touched face loses that area. One undo step.
5431
+ */
5432
+ shapeBuilder(points, options = {}) {
5433
+ const none = (message) => ({ ok: false, message, merged: null, faces: 0, lines: 0 });
5434
+ if (!points.length || !points.every((p) => Number.isFinite(p.x) && Number.isFinite(p.y))) return none("Give the points of the gesture.");
5435
+ const m = this.shapeBuilderMap(options.ids);
5436
+ if (!m) return none("Select paths that make faces.");
5437
+ const erase = !!options.erase;
5438
+ const tol = erase ? _nullishCoalesce(options.tolerance, () => ( this.builderLineTolerance())) : null;
5439
+ const touched = { faces: [], lines: [] };
5440
+ const size = m.map.faces.reduce((s, f) => Math.max(s, f.bounds.maxX - f.bounds.minX, f.bounds.maxY - f.bounds.minY), 1);
5441
+ for (const p of samplePolyline(points, Math.max(size / 2e3, 0.25 / this.viewport.zoom))) addBuilderHit(touched, vectorShapeBuilderHit(m, p, tol));
5442
+ if (!touched.faces.length && !touched.lines.length) return none("There is no face under the pointer.");
5443
+ return this.applyShapeBuilder(m, touched, erase);
5444
+ }
5445
+ applyShapeBuilder(m, touched, erase) {
5446
+ const plan = planShapeBuilder(m, touched, erase);
5447
+ let mergedId = null;
5448
+ const created = /* @__PURE__ */ new Map();
5449
+ this.change(erase ? "Shape Builder Delete" : "Shape Builder", () => {
5450
+ let nodes = this.doc.nodes;
5451
+ m.entries.forEach((entry, i) => {
5452
+ const node = entry.node;
5453
+ const toLocal = (path) => _chunk7EDLVBOOcjs.transformBezierPath.call(void 0, path, invertMatrix(multiplyMatrices(nodeMatrix(node), entry.parent)));
5454
+ const list = [];
5455
+ const r = plan.replace.get(i);
5456
+ if (r === void 0) list.push(node);
5457
+ else if (_optionalChain([r, 'optionalAccess', _146 => _146.kind]) === "fill") list.push({ ...node, fillRule: "nonzero", subpaths: bezierToSubpaths(toLocal(r.path)) });
5458
+ else if (_optionalChain([r, 'optionalAccess', _147 => _147.kind]) === "pieces") {
5459
+ r.paths.forEach(
5460
+ (path, k) => list.push({ ...node, id: k === 0 ? node.id : this.newId(), subpaths: bezierToSubpaths(toLocal(path)).map((sp) => ({ ...sp, closed: false })) })
5461
+ );
5462
+ }
5463
+ if (plan.merged && plan.merged.style === i) {
5464
+ mergedId = this.newId();
5465
+ const merged = {
5466
+ ...vectorResultStyle(node, "fill"),
5467
+ type: "path",
5468
+ id: mergedId,
5469
+ name: "Shape",
5470
+ ...node.transform ? { transform: node.transform } : {},
5471
+ subpaths: bezierToSubpaths(toLocal(plan.merged.path))
5472
+ };
5473
+ if (plan.merged.currentFill || !hasPaint(merged.fill)) merged.fill = hasPaint(this.defaults.fill) ? this.defaults.fill : "#808080";
5474
+ list.push(merged);
5475
+ }
5476
+ if (r === void 0 && list.length === 1) return;
5477
+ created.set(node.id, list.map((n) => n.id));
5478
+ nodes = spliceTree(nodes, node.id, list);
5479
+ });
5480
+ this.setDoc(nodes);
5481
+ const selection = this.selection.flatMap((id) => _nullishCoalesce(created.get(id), () => ( [id])));
5482
+ if (mergedId && !selection.includes(mergedId)) selection.push(mergedId);
5483
+ this.selection = selection.filter((id, k) => !!this.getNode(id) && selection.indexOf(id) === k);
5484
+ this.anchors = [];
5485
+ this.editingId = null;
5486
+ });
5487
+ this.builderCache = null;
5488
+ return { ok: true, merged: mergedId, faces: touched.faces.length, lines: touched.lines.length };
5489
+ }
5490
+ /** The paint bucket's map of the visible outlines, cached per document and gap. */
5491
+ fillMap(gap) {
5492
+ if (_optionalChain([this, 'access', _148 => _148.fillCache, 'optionalAccess', _149 => _149.doc]) === this.doc && this.fillCache.gap === gap) return this.fillCache.map;
5493
+ const map = vectorFillMap(this.doc, gap);
5494
+ this.fillCache = { doc: this.doc, gap, map };
5495
+ return map;
5496
+ }
5497
+ /**
5498
+ * Paint bucket: the region the visible outlines enclose around `point` (document units),
5499
+ * crossings split and islands left as holes, becomes a new path filled with the current fill
5500
+ * default, placed just below the selection (or on top when nothing is selected). `gap`
5501
+ * (default `editing.fillGap`) closes gaps up to that size between loose ends. Returns the new
5502
+ * path's id, or null when nothing encloses the point.
5503
+ */
5504
+ fillRegion(point, options = {}) {
5505
+ if (!Number.isFinite(point.x) || !Number.isFinite(point.y)) return null;
5506
+ 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])]);
5507
+ if (!_optionalChain([region, 'optionalAccess', _154 => _154.length])) return null;
5508
+ let below = null;
5509
+ const roots = new Set(this.selectedRoots());
5510
+ walkVectorNodes(this.doc.nodes, (n) => {
5511
+ if (!below && roots.has(n.id)) below = n.id;
5512
+ });
5513
+ const subpaths = bezierToSubpaths(below ? this.intoParentSpace(below, region) : region);
5514
+ if (!subpaths.length) return null;
5515
+ const id = this.newId();
5516
+ const node = { id, type: "path", name: "Fill", ...this.styleFor(false), stroke: null, fillRule: "nonzero", subpaths };
5517
+ if (!hasPaint(node.fill)) node.fill = "#808080";
5518
+ const target = below;
5519
+ this.change("Fill Region", () => {
5520
+ if (target) {
5521
+ const current = this.getNode(target);
5522
+ this.setDoc(spliceTree(this.doc.nodes, target, [node, current]));
5523
+ } else this.setDoc([...this.doc.nodes, node]);
5524
+ if (!target) this.selection = [id];
5525
+ this.anchors = [];
5526
+ this.editingId = null;
5527
+ });
5528
+ return id;
5529
+ }
5530
+ /** Updates the Shape Builder / paint bucket highlight for the pointer at `p`; true when it changed. */
5531
+ hoverBuilder(p, alt) {
5532
+ if (this.tool === "paintBucket") {
5533
+ 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));
5534
+ const key2 = region ? _chunk7EDLVBOOcjs.bezierPathToSvg.call(void 0, region, { precision: 2 }) : null;
5535
+ if (key2 === this.builderHoverKey) return false;
5536
+ this.builderHoverKey = key2;
5537
+ this.builderPreview = region ? { mode: "fill", faces: [region], lines: [], trail: null } : null;
5538
+ return true;
5539
+ }
5540
+ const m = this.selectedRoots().length ? this.shapeBuilderMap() : null;
5541
+ const hit = m ? vectorShapeBuilderHit(m, p, alt ? this.builderLineTolerance() : null) : null;
5542
+ const key = hit ? `${alt ? "erase" : "merge"}:${JSON.stringify(hit)}` : null;
5543
+ if (key === this.builderHoverKey) return false;
5544
+ this.builderHoverKey = key;
5545
+ this.builderPreview = hit && m ? this.builderPreviewOf(m, "face" in hit ? { faces: [hit.face], lines: [] } : { faces: [], lines: [hit.line] }, alt, null) : null;
5546
+ return true;
5547
+ }
5548
+ builderPreviewOf(m, touched, erase, trail) {
5549
+ const faces = m.map.faces;
5550
+ return {
5551
+ mode: erase ? "erase" : "merge",
5552
+ faces: touched.faces.map((f) => faces[f].path),
5553
+ lines: touched.lines.map((k) => m.pieces[k].path),
5554
+ trail
5555
+ };
5556
+ }
5557
+ downBuilder(p, input) {
5558
+ this.builderHoverKey = null;
5559
+ if (this.tool === "paintBucket") {
5560
+ this.fillRegion(p);
5561
+ this.builderPreview = null;
5562
+ this.hoverBuilder(p, false);
5563
+ this.notify();
5564
+ return;
5565
+ }
5566
+ const m = this.selectedRoots().length ? this.shapeBuilderMap() : null;
5567
+ if (!m) return;
5568
+ const erase = !!input.alt;
5569
+ const touched = { faces: [], lines: [] };
5570
+ addBuilderHit(touched, vectorShapeBuilderHit(m, p, erase ? this.builderLineTolerance() : null));
5571
+ this.drag = { kind: "builder", erase, points: [p], touched, map: m };
5572
+ this.interaction = { type: "builder", mode: erase ? "erase" : "merge", points: [p] };
5573
+ this.builderPreview = this.builderPreviewOf(m, touched, erase, [p]);
5574
+ this.notify();
5575
+ }
5576
+ moveBuilder(drag, p) {
5577
+ const last = drag.points[drag.points.length - 1];
5578
+ if (Math.hypot(p.x - last.x, p.y - last.y) * this.viewport.zoom < 1) return;
5579
+ const tol = drag.erase ? this.builderLineTolerance() : null;
5580
+ for (const q of samplePolyline([last, p], 2 / this.viewport.zoom)) addBuilderHit(drag.touched, vectorShapeBuilderHit(drag.map, q, tol));
5581
+ drag.points.push(p);
5582
+ this.interaction = { type: "builder", mode: drag.erase ? "erase" : "merge", points: drag.points.slice() };
5583
+ this.builderPreview = this.builderPreviewOf(drag.map, drag.touched, drag.erase, drag.points.slice());
5584
+ this.notify();
5585
+ }
5586
+ upBuilder(drag) {
5587
+ this.builderPreview = null;
5588
+ this.builderHoverKey = null;
5589
+ if (!drag.touched.faces.length && !drag.touched.lines.length) {
5590
+ this.notify();
5591
+ return;
5592
+ }
5593
+ this.applyShapeBuilder(drag.map, drag.touched, drag.erase);
5594
+ }
5595
+ // -------------------------------------------------------------------------
5118
5596
  // Anchor editing
5119
5597
  // -------------------------------------------------------------------------
5120
5598
  updateAnchors(doc, refs, fn) {
@@ -5157,7 +5635,7 @@ var VectorEditorController = (_class3 = class {
5157
5635
  /** `doc` with anchor `ref` moved to document point `to` by a Curvature-tool move. */
5158
5636
  curvatureMoved(doc, ref, to) {
5159
5637
  const node = findVectorNode(doc.nodes, ref.nodeId);
5160
- if (_optionalChain([node, 'optionalAccess', _137 => _137.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
5638
+ if (_optionalChain([node, 'optionalAccess', _159 => _159.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
5161
5639
  const q = this.toLocal(ref.nodeId, to, doc);
5162
5640
  const subpaths = node.subpaths.map((sp, i) => i === ref.subpath ? curvatureMoveAnchor(sp, ref.index, q) : sp);
5163
5641
  const nodes = mapTree(doc.nodes, (n) => n.id === ref.nodeId ? { ...node, subpaths } : n);
@@ -5166,7 +5644,7 @@ var VectorEditorController = (_class3 = class {
5166
5644
  /** `doc` with segment `ref` bent through document point `p` at parameter `t`. */
5167
5645
  bent(doc, ref, t, p) {
5168
5646
  const node = findVectorNode(doc.nodes, ref.nodeId);
5169
- if (_optionalChain([node, 'optionalAccess', _138 => _138.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
5647
+ if (_optionalChain([node, 'optionalAccess', _160 => _160.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
5170
5648
  const q = this.toLocal(ref.nodeId, p, doc);
5171
5649
  const subpaths = node.subpaths.map((sp, i) => i === ref.subpath ? bendSegment(sp, ref.segment, t, q) : sp);
5172
5650
  return { ...doc, nodes: mapTree(doc.nodes, (n) => n.id === ref.nodeId ? { ...node, subpaths } : n) };
@@ -5177,7 +5655,7 @@ var VectorEditorController = (_class3 = class {
5177
5655
  */
5178
5656
  bendSegment(ref, to, t = 0.5) {
5179
5657
  const node = this.getNode(ref.nodeId);
5180
- const sp = _optionalChain([node, 'optionalAccess', _139 => _139.type]) === "path" ? node.subpaths[ref.subpath] : void 0;
5658
+ const sp = _optionalChain([node, 'optionalAccess', _161 => _161.type]) === "path" ? node.subpaths[ref.subpath] : void 0;
5181
5659
  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
5660
  if (node.locked) return { ok: false, message: "The path is locked." };
5183
5661
  this.change("Bend Segment", () => {
@@ -5212,7 +5690,7 @@ var VectorEditorController = (_class3 = class {
5212
5690
  /** Adds an anchor on the nearest segment of `nodeId` to document point `point` (shape unchanged). */
5213
5691
  insertAnchorAt(nodeId, point) {
5214
5692
  const node = this.getNode(nodeId);
5215
- if (_optionalChain([node, 'optionalAccess', _140 => _140.type]) !== "path") return null;
5693
+ if (_optionalChain([node, 'optionalAccess', _162 => _162.type]) !== "path") return null;
5216
5694
  const hit = nearestSegment(node, this.toLocal(nodeId, point));
5217
5695
  if (!hit) return null;
5218
5696
  const { subpath, index } = insertAnchor(node.subpaths[hit.subpath], hit.segment, hit.t);
@@ -5256,7 +5734,7 @@ var VectorEditorController = (_class3 = class {
5256
5734
  setClosed(closed, nodeId) {
5257
5735
  const targets = nodeId ? (() => {
5258
5736
  const n = this.getNode(nodeId);
5259
- return _optionalChain([n, 'optionalAccess', _141 => _141.type]) === "path" ? n.subpaths.map((_, s) => ({ nodeId, subpath: s })) : [];
5737
+ return _optionalChain([n, 'optionalAccess', _163 => _163.type]) === "path" ? n.subpaths.map((_, s) => ({ nodeId, subpath: s })) : [];
5260
5738
  })() : this.anchors.map((r) => ({ nodeId: r.nodeId, subpath: r.subpath }));
5261
5739
  if (!targets.length) return { ok: false, message: "Select a path or points." };
5262
5740
  this.change(closed ? "Close Path" : "Open Path", () => {
@@ -5277,7 +5755,7 @@ var VectorEditorController = (_class3 = class {
5277
5755
  this.setDoc(
5278
5756
  mapTree(
5279
5757
  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
5758
+ (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
5759
  )
5282
5760
  );
5283
5761
  this.anchors = [];
@@ -5415,7 +5893,7 @@ var VectorEditorController = (_class3 = class {
5415
5893
  */
5416
5894
  cutPathAt(nodeId, point) {
5417
5895
  const node = this.getNode(nodeId);
5418
- if (_optionalChain([node, 'optionalAccess', _144 => _144.type]) !== "path" || node.locked) return null;
5896
+ if (_optionalChain([node, 'optionalAccess', _166 => _166.type]) !== "path" || node.locked) return null;
5419
5897
  const local = this.toLocal(nodeId, point);
5420
5898
  const hit = nearestSegment(node, local);
5421
5899
  if (!hit) return null;
@@ -5465,7 +5943,7 @@ var VectorEditorController = (_class3 = class {
5465
5943
  if (n.visible === false || n.locked || parent && blocked.has(parent.id)) blocked.add(n.id);
5466
5944
  });
5467
5945
  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);
5946
+ if (_optionalChain([ids, 'optionalAccess', _167 => _167.length]) || this.selection.length) return this.pathTargets(_nullishCoalesce(ids, () => ( this.selection))).filter(visible);
5469
5947
  const box = polylineBounds(points.map(toPoint2), pad);
5470
5948
  if (!box) return [];
5471
5949
  const out = [];
@@ -5521,10 +5999,10 @@ var VectorEditorController = (_class3 = class {
5521
5999
  const region = eraserRegion(pts, width);
5522
6000
  if (!region.length) return [];
5523
6001
  const plan = [];
5524
- const rb = _chunkGVB7ZPLZcjs.bezierPathBounds.call(void 0, region);
6002
+ const rb = _chunk7EDLVBOOcjs.bezierPathBounds.call(void 0, region);
5525
6003
  const reach = rb ? [{ x: rb.minX, y: rb.minY }, { x: rb.maxX, y: rb.maxY }] : points;
5526
6004
  for (const node of this.strokeTargets(reach, options.ids, 0)) {
5527
- const local = _chunkGVB7ZPLZcjs.transformBezierPath.call(void 0, region, invertMatrix(this.worldOf(node.id)));
6005
+ const local = _chunk7EDLVBOOcjs.transformBezierPath.call(void 0, region, invertMatrix(this.worldOf(node.id)));
5528
6006
  const live = node.subpaths.filter((sp) => sp.anchors.length > 1);
5529
6007
  if (!live.length) continue;
5530
6008
  if (hasPaint(node.fill) && live.every((sp) => sp.closed)) {
@@ -5551,7 +6029,7 @@ var VectorEditorController = (_class3 = class {
5551
6029
  finishPath() {
5552
6030
  if (!this.pen) return;
5553
6031
  const node = this.getNode(this.pen.nodeId);
5554
- const sp = _optionalChain([node, 'optionalAccess', _146 => _146.subpaths, 'access', _147 => _147[this.pen.subpath]]);
6032
+ const sp = _optionalChain([node, 'optionalAccess', _168 => _168.subpaths, 'access', _169 => _169[this.pen.subpath]]);
5555
6033
  const pen = this.pen;
5556
6034
  this.pen = null;
5557
6035
  this.pointer = null;
@@ -5595,7 +6073,7 @@ var VectorEditorController = (_class3 = class {
5595
6073
  if (trimmed.startsWith("{")) {
5596
6074
  try {
5597
6075
  const data = JSON.parse(trimmed);
5598
- if (_optionalChain([data, 'optionalAccess', _148 => _148.type]) === VECTOR_CLIPBOARD_TYPE && Array.isArray(data.nodes)) nodes = data.nodes;
6076
+ if (_optionalChain([data, 'optionalAccess', _170 => _170.type]) === VECTOR_CLIPBOARD_TYPE && Array.isArray(data.nodes)) nodes = data.nodes;
5599
6077
  } catch (e3) {
5600
6078
  nodes = null;
5601
6079
  }
@@ -5607,7 +6085,7 @@ var VectorEditorController = (_class3 = class {
5607
6085
  }
5608
6086
  }
5609
6087
  } else nodes = this.clipboard;
5610
- if (!_optionalChain([nodes, 'optionalAccess', _149 => _149.length])) return [];
6088
+ if (!_optionalChain([nodes, 'optionalAccess', _171 => _171.length])) return [];
5611
6089
  const offset = _nullishCoalesce(options.offset, () => ( (text && !text.trim().startsWith("{") ? { x: 0, y: 0 } : { x: 10, y: 10 })));
5612
6090
  const copies = nodes.map((n) => transformVectorNode(this.freshIds(n), translateMatrix(offset.x, offset.y)));
5613
6091
  this.change("Paste", () => {
@@ -5651,14 +6129,14 @@ var VectorEditorController = (_class3 = class {
5651
6129
  if (!frame) return null;
5652
6130
  const { box, handles } = getVectorSelectionBoxGeometry(frame, this.viewport);
5653
6131
  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;
6132
+ const usable2 = box.width < 2 * r || box.height < 2 * r ? handles.filter((h) => h.handle.length === 2 || h.handle === "rotate") : handles;
6133
+ 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
6134
  return null;
5657
6135
  }
5658
6136
  hitHandle(screen) {
5659
6137
  for (const ref of getVisibleHandles(this.view()).reverse()) {
5660
6138
  const a = getAnchorWorld(this.doc, ref);
5661
- const h = _optionalChain([a, 'optionalAccess', _150 => _150[ref.handle]]);
6139
+ const h = _optionalChain([a, 'optionalAccess', _172 => _172[ref.handle]]);
5662
6140
  if (!h) continue;
5663
6141
  const s = this.documentToScreen(h);
5664
6142
  if (Math.hypot(s.x - screen.x, s.y - screen.y) <= this.hitRadius) return ref;
@@ -5828,9 +6306,9 @@ var VectorEditorController = (_class3 = class {
5828
6306
  downWidth(screen, p, input) {
5829
6307
  const hit = this.hitWidthHandle(screen);
5830
6308
  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])));
6309
+ const nodeId = _nullishCoalesce(_optionalChain([hit, 'optionalAccess', _173 => _173.ref, 'access', _174 => _174.nodeId]), () => ( _optionalChain([spot, 'optionalAccess', _175 => _175.nodeId])));
5832
6310
  const node = nodeId ? this.getNode(nodeId) : void 0;
5833
- const g = _optionalChain([node, 'optionalAccess', _154 => _154.type]) === "path" ? vectorStrokeWidthGeometry(node) : null;
6311
+ const g = _optionalChain([node, 'optionalAccess', _176 => _176.type]) === "path" ? vectorStrokeWidthGeometry(node) : null;
5834
6312
  if (!node || node.type !== "path" || !g) {
5835
6313
  if (this.widthPoint) {
5836
6314
  this.widthPoint = null;
@@ -5849,7 +6327,7 @@ var VectorEditorController = (_class3 = class {
5849
6327
  if (hit) {
5850
6328
  profile = sanitizeWidthProfile(node.strokeWidthProfile);
5851
6329
  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));
6330
+ t = _nullishCoalesce(_optionalChain([profile, 'access', _177 => _177[ref.index], 'optionalAccess', _178 => _178.t]), () => ( 0));
5853
6331
  subpath = hit.ref.subpath;
5854
6332
  if (hit.ref.part === "center") mode = "move";
5855
6333
  else if (input.alt) side = hit.ref.part;
@@ -5936,6 +6414,9 @@ var VectorEditorController = (_class3 = class {
5936
6414
  return this.downPencil(p, input);
5937
6415
  case "width":
5938
6416
  return this.downWidth(screen, p, input);
6417
+ case "shapeBuilder":
6418
+ case "paintBucket":
6419
+ return this.downBuilder(p, input);
5939
6420
  case "scissors": {
5940
6421
  const seg = this.nearestOutline(p);
5941
6422
  if (seg) this.cutPathAt(seg.nodeId, seg.point);
@@ -6071,7 +6552,7 @@ var VectorEditorController = (_class3 = class {
6071
6552
  }
6072
6553
  downPen(screen, p, input) {
6073
6554
  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;
6555
+ 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
6556
  if (this.pen && sp) {
6076
6557
  const pen = this.pen;
6077
6558
  const first = { nodeId: pen.nodeId, subpath: pen.subpath, index: 0 };
@@ -6165,6 +6646,11 @@ var VectorEditorController = (_class3 = class {
6165
6646
  pointerMove(screen, input = {}) {
6166
6647
  const p = this.screenToDocument(screen);
6167
6648
  const drag = this.drag;
6649
+ if (!drag && (this.tool === "shapeBuilder" || this.tool === "paintBucket")) {
6650
+ this.pointer = p;
6651
+ if (this.hoverBuilder(p, !!input.alt)) this.notify();
6652
+ return;
6653
+ }
6168
6654
  if (!drag) {
6169
6655
  const hover = this.computeHover(screen);
6170
6656
  const pointerMatters = this.tool === "pen" && !!this.pen;
@@ -6296,6 +6782,8 @@ var VectorEditorController = (_class3 = class {
6296
6782
  this.notify(true);
6297
6783
  return;
6298
6784
  }
6785
+ case "builder":
6786
+ return this.moveBuilder(drag, p);
6299
6787
  case "stroke": {
6300
6788
  const last = drag.points[drag.points.length - 1];
6301
6789
  if (Math.hypot(p.x - last.x, p.y - last.y) * this.viewport.zoom < 1.5) return;
@@ -6326,7 +6814,7 @@ var VectorEditorController = (_class3 = class {
6326
6814
  }
6327
6815
  case "shape": {
6328
6816
  const node = this.getNode(drag.nodeId);
6329
- if (_optionalChain([node, 'optionalAccess', _161 => _161.type]) !== "path") return;
6817
+ if (_optionalChain([node, 'optionalAccess', _183 => _183.type]) !== "path") return;
6330
6818
  const leave = { at: drag.start, constrain: input.shift ? drag.tool === "line" ? "angle" : "square" : null, curves: false };
6331
6819
  let end = this.snapDrawn(p, leave, input, () => drag.targets ??= this.drawingTargets(null));
6332
6820
  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 +6872,14 @@ var VectorEditorController = (_class3 = class {
6384
6872
  for (const q of drag.lazy.push([p.x, p.y])) {
6385
6873
  if (Math.hypot(q[0] - last[0], q[1] - last[1]) * this.viewport.zoom < 1.5) continue;
6386
6874
  drag.points.push(q);
6387
- _optionalChain([drag, 'access', _162 => _162.pressures, 'optionalAccess', _163 => _163.push, 'call', _164 => _164(drag.pressure)]);
6875
+ _optionalChain([drag, 'access', _184 => _184.pressures, 'optionalAccess', _185 => _185.push, 'call', _186 => _186(drag.pressure)]);
6388
6876
  moved = true;
6389
6877
  }
6390
6878
  const string = drag.lazy.string();
6391
6879
  const node = this.getNode(drag.nodeId);
6392
- if (_optionalChain([node, 'optionalAccess', _165 => _165.type]) !== "path") return;
6880
+ if (_optionalChain([node, 'optionalAccess', _187 => _187.type]) !== "path") return;
6393
6881
  if (!moved) {
6394
- if (string && _optionalChain([this, 'access', _166 => _166.interaction, 'optionalAccess', _167 => _167.type]) === "draw") {
6882
+ if (string && _optionalChain([this, 'access', _188 => _188.interaction, 'optionalAccess', _189 => _189.type]) === "draw") {
6395
6883
  this.interaction = { ...this.interaction, string: [{ x: string[0][0], y: string[0][1] }, { x: string[1][0], y: string[1][1] }] };
6396
6884
  this.notify();
6397
6885
  }
@@ -6427,8 +6915,8 @@ var VectorEditorController = (_class3 = class {
6427
6915
  }
6428
6916
  this.setGuides(res);
6429
6917
  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
6918
+ dx: _optionalChain([res, 'optionalAccess', _190 => _190.x]) ? dx + res.dx : axes.x ? this.gridValue(origin.x + dx) - origin.x : dx,
6919
+ dy: _optionalChain([res, 'optionalAccess', _191 => _191.y]) ? dy + res.dy : axes.y ? this.gridValue(origin.y + dy) - origin.y : dy
6432
6920
  };
6433
6921
  }
6434
6922
  /** The anchor a point drag snaps by, where it started: the grabbed one, else the moving one nearest the press. */
@@ -6507,7 +6995,7 @@ var VectorEditorController = (_class3 = class {
6507
6995
  if (drag.moved) return this.commit("Corner Radius", drag.before);
6508
6996
  if (drag.alt) {
6509
6997
  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));
6998
+ 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
6999
  return this.commit("Corner Kind", drag.before);
6512
7000
  }
6513
7001
  const ref = drag.widget.ref;
@@ -6526,6 +7014,8 @@ var VectorEditorController = (_class3 = class {
6526
7014
  } else this.notify();
6527
7015
  return;
6528
7016
  }
7017
+ case "builder":
7018
+ return this.upBuilder(drag);
6529
7019
  case "stroke": {
6530
7020
  this.notify();
6531
7021
  if (drag.tool === "knife") this.knife(drag.points);
@@ -6551,14 +7041,14 @@ var VectorEditorController = (_class3 = class {
6551
7041
  }
6552
7042
  case "pencil": {
6553
7043
  const node = this.getNode(drag.nodeId);
6554
- if (_optionalChain([node, 'optionalAccess', _172 => _172.type]) !== "path" || drag.points.length < 2) {
7044
+ if (_optionalChain([node, 'optionalAccess', _194 => _194.type]) !== "path" || drag.points.length < 2) {
6555
7045
  this.doc = drag.before.doc;
6556
7046
  this.notify(true);
6557
7047
  return;
6558
7048
  }
6559
7049
  for (const q of drag.lazy.finish()) {
6560
7050
  drag.points.push(q);
6561
- _optionalChain([drag, 'access', _173 => _173.pressures, 'optionalAccess', _174 => _174.push, 'call', _175 => _175(drag.pressure)]);
7051
+ _optionalChain([drag, 'access', _195 => _195.pressures, 'optionalAccess', _196 => _196.push, 'call', _197 => _197(drag.pressure)]);
6562
7052
  }
6563
7053
  const shape = this.editing.recognizeShapes ? recognizeInkShape(drag.points, { minSize: 6 / this.viewport.zoom }) : null;
6564
7054
  if (shape) {
@@ -6566,7 +7056,7 @@ var VectorEditorController = (_class3 = class {
6566
7056
  this.selection = [drag.nodeId];
6567
7057
  return this.commit(`Draw ${inkShapeLabel(shape)}`, drag.before);
6568
7058
  }
6569
- const fitted = _chunkGVB7ZPLZcjs.fitCubics.call(void 0, drag.points, 1.5 / this.viewport.zoom, { cornerAngleDeg: 60 });
7059
+ const fitted = _chunk7EDLVBOOcjs.fitCubics.call(void 0, drag.points, 1.5 / this.viewport.zoom, { cornerAngleDeg: 60 });
6570
7060
  const anchors = [];
6571
7061
  for (const c of fitted) {
6572
7062
  if (!anchors.length) anchors.push({ x: c.p0[0], y: c.p0[1] });
@@ -6597,7 +7087,8 @@ var VectorEditorController = (_class3 = class {
6597
7087
  this.drag = null;
6598
7088
  this.interaction = null;
6599
7089
  this.guides = null;
6600
- if (drag.kind === "pan") {
7090
+ if (drag.kind === "pan" || drag.kind === "builder") {
7091
+ if (drag.kind === "builder") this.builderPreview = null;
6601
7092
  this.notify();
6602
7093
  return;
6603
7094
  }
@@ -6629,7 +7120,7 @@ var VectorEditorController = (_class3 = class {
6629
7120
  this.convertAnchors(a.in || a.out ? "corner" : "smooth", [anchor]);
6630
7121
  return;
6631
7122
  }
6632
- const id = _nullishCoalesce(_optionalChain([this, 'access', _176 => _176.hover, 'optionalAccess', _177 => _177.segment, 'optionalAccess', _178 => _178.nodeId]), () => ( this.editingId));
7123
+ const id = _nullishCoalesce(_optionalChain([this, 'access', _198 => _198.hover, 'optionalAccess', _199 => _199.segment, 'optionalAccess', _200 => _200.nodeId]), () => ( this.editingId));
6633
7124
  if (id) {
6634
7125
  const node = this.getNode(id);
6635
7126
  const seg = node ? nearestSegment(node, this.toLocal(id, p)) : null;
@@ -6712,7 +7203,7 @@ var VectorEditorController = (_class3 = class {
6712
7203
  this.finishPath();
6713
7204
  return true;
6714
7205
  }
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") {
7206
+ 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
7207
  this.tool = "direct";
6717
7208
  this.editingId = this.selection[0];
6718
7209
  this.notify();
@@ -6854,7 +7345,7 @@ function renderNode(node, defs, idPrefix) {
6854
7345
  strokeWidth: _nullishCoalesce(node.strokeWidth, () => ( 1)),
6855
7346
  ...node.strokeLinecap ? { strokeLinecap: node.strokeLinecap } : {},
6856
7347
  ...node.strokeLinejoin ? { strokeLinejoin: node.strokeLinejoin } : {},
6857
- ..._optionalChain([node, 'access', _182 => _182.strokeDasharray, 'optionalAccess', _183 => _183.length]) ? { strokeDasharray: node.strokeDasharray.join(" ") } : {},
7348
+ ..._optionalChain([node, 'access', _204 => _204.strokeDasharray, 'optionalAccess', _205 => _205.length]) ? { strokeDasharray: node.strokeDasharray.join(" ") } : {},
6858
7349
  fillRule: _nullishCoalesce(node.fillRule, () => ( "nonzero")),
6859
7350
  opacity: _nullishCoalesce(node.opacity, () => ( 1))
6860
7351
  };
@@ -6878,7 +7369,7 @@ function screenOutline(state, node) {
6878
7369
  const v2 = state.viewport;
6879
7370
  const view = [v2.zoom, 0, 0, v2.zoom, v2.x, v2.y];
6880
7371
  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(" ");
7372
+ return collectWithMatrix(node, parent).map(({ path, parent: m }) => _chunk7EDLVBOOcjs.bezierPathToSvg.call(void 0, _chunk7EDLVBOOcjs.transformBezierPath.call(void 0, vectorPathWorldBezier(path, m), view), { precision: 2 })).join(" ");
6882
7373
  }
6883
7374
  function collectWithMatrix(node, parent) {
6884
7375
  if (node.type === "path") return [{ path: node, parent }];
@@ -6903,9 +7394,9 @@ function getVectorOverlayRenderData(state) {
6903
7394
  };
6904
7395
  for (const id of state.selection) outline(id, true);
6905
7396
  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);
7397
+ if (_optionalChain([state, 'access', _206 => _206.hover, 'optionalAccess', _207 => _207.nodeId]) && !state.interaction) outline(state.hover.nodeId, false);
6907
7398
  let selectionBox = null;
6908
- if (state.tool === "select" && state.selectionFrame && _optionalChain([state, 'access', _186 => _186.interaction, 'optionalAccess', _187 => _187.type]) !== "marquee") {
7399
+ if (state.tool === "select" && state.selectionFrame && _optionalChain([state, 'access', _208 => _208.interaction, 'optionalAccess', _209 => _209.type]) !== "marquee") {
6909
7400
  const g = getVectorSelectionBoxGeometry(state.selectionFrame, state.viewport);
6910
7401
  selectionBox = { ...g.box, angle: g.angle, transform: g.transform, corners: g.corners, handles: g.handles };
6911
7402
  }
@@ -6915,9 +7406,9 @@ function getVectorOverlayRenderData(state) {
6915
7406
  const a = getAnchorWorld(doc, ref);
6916
7407
  const s = toScreen(state, a);
6917
7408
  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 };
7409
+ 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
7410
  });
6920
- if (state.tool === "pen" && !state.pen && _optionalChain([state, 'access', _190 => _190.hover, 'optionalAccess', _191 => _191.anchor])) {
7411
+ if (state.tool === "pen" && !state.pen && _optionalChain([state, 'access', _212 => _212.hover, 'optionalAccess', _213 => _213.anchor])) {
6921
7412
  const a = getAnchorWorld(doc, state.hover.anchor);
6922
7413
  if (a) {
6923
7414
  const s = toScreen(state, a);
@@ -6926,15 +7417,15 @@ function getVectorOverlayRenderData(state) {
6926
7417
  }
6927
7418
  const handles = getVisibleHandles(state).flatMap((ref) => {
6928
7419
  const a = getAnchorWorld(doc, ref);
6929
- const h = _optionalChain([a, 'optionalAccess', _192 => _192[ref.handle]]);
7420
+ const h = _optionalChain([a, 'optionalAccess', _214 => _214[ref.handle]]);
6930
7421
  if (!a || !h) return [];
6931
7422
  const s = toScreen(state, h);
6932
7423
  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;
7424
+ const hovered = !!_optionalChain([state, 'access', _215 => _215.hover, 'optionalAccess', _216 => _216.handle]) && sameAnchor(state.hover.handle, ref) && state.hover.handle.handle === ref.handle;
6934
7425
  return [{ ref, x: s.x, y: s.y, anchorX: sa.x, anchorY: sa.y, hovered }];
6935
7426
  });
6936
7427
  let marquee = null;
6937
- if (_optionalChain([state, 'access', _195 => _195.interaction, 'optionalAccess', _196 => _196.type]) === "marquee") {
7428
+ if (_optionalChain([state, 'access', _217 => _217.interaction, 'optionalAccess', _218 => _218.type]) === "marquee") {
6938
7429
  const b = state.interaction.bounds;
6939
7430
  const tl = toScreen(state, b);
6940
7431
  marquee = { x: tl.x, y: tl.y, width: b.width * z, height: b.height * z };
@@ -6942,7 +7433,7 @@ function getVectorOverlayRenderData(state) {
6942
7433
  let penPreview = null;
6943
7434
  if (state.tool === "pen" && state.pen && state.pointer && !state.interaction) {
6944
7435
  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;
7436
+ const sp = _optionalChain([node, 'optionalAccess', _219 => _219.type]) === "path" ? node.subpaths[state.pen.subpath] : void 0;
6946
7437
  const last = sp ? getAnchorWorld(doc, { nodeId: state.pen.nodeId, subpath: state.pen.subpath, index: sp.anchors.length - 1 }) : void 0;
6947
7438
  if (last) {
6948
7439
  const a = toScreen(state, last);
@@ -6955,9 +7446,9 @@ function getVectorOverlayRenderData(state) {
6955
7446
  const artboard = { x: origin.x, y: origin.y, width: doc.width * z, height: doc.height * z };
6956
7447
  let status = null;
6957
7448
  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") {
7449
+ if (_optionalChain([it, 'optionalAccess', _220 => _220.type]) === "rotate") status = `${Math.round(it.angle)}\xB0`;
7450
+ else if (_optionalChain([it, 'optionalAccess', _221 => _221.type]) === "move" || _optionalChain([it, 'optionalAccess', _222 => _222.type]) === "anchors") status = `\u0394 ${fmt(it.dx)}, ${fmt(it.dy)}`;
7451
+ else if (_optionalChain([it, 'optionalAccess', _223 => _223.type]) === "scale" || _optionalChain([it, 'optionalAccess', _224 => _224.type]) === "draw") {
6961
7452
  const b = it.type === "draw" ? findVectorNode(doc.nodes, it.nodeId) ? vectorNodeBounds(findVectorNode(doc.nodes, it.nodeId)) : null : state.selectionFrame;
6962
7453
  if (b) status = `W ${fmt(b.width)} \xD7 H ${fmt(b.height)}`;
6963
7454
  }
@@ -6974,24 +7465,24 @@ function getVectorOverlayRenderData(state) {
6974
7465
  }
6975
7466
  }
6976
7467
  let toolStroke = null;
6977
- if (_optionalChain([it, 'optionalAccess', _203 => _203.type]) === "stroke") {
7468
+ if (_optionalChain([it, 'optionalAccess', _225 => _225.type]) === "stroke") {
6978
7469
  const pts = it.points.map((q) => toScreen(state, q));
6979
7470
  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
7471
  toolStroke = { tool: it.tool, d, width: fmt(it.width * z) };
6981
7472
  }
6982
7473
  let pencilString = null;
6983
- if (_optionalChain([it, 'optionalAccess', _204 => _204.type]) === "draw" && it.string) {
7474
+ if (_optionalChain([it, 'optionalAccess', _226 => _226.type]) === "draw" && it.string) {
6984
7475
  const a = toScreen(state, it.string[0]);
6985
7476
  const b = toScreen(state, it.string[1]);
6986
7477
  pencilString = { x1: fmt(a.x), y1: fmt(a.y), x2: fmt(b.x), y2: fmt(b.y) };
6987
7478
  }
6988
- const dragged = _optionalChain([it, 'optionalAccess', _205 => _205.type]) === "corner" ? it.ref : null;
7479
+ const dragged = _optionalChain([it, 'optionalAccess', _227 => _227.type]) === "corner" ? it.ref : null;
6989
7480
  const cornerWidgets = getVectorCornerWidgets(state).map((w) => {
6990
7481
  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 };
7482
+ 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
7483
  });
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;
7484
+ if (_optionalChain([it, 'optionalAccess', _230 => _230.type]) === "corner") status = `R ${fmt(it.radius)}`;
7485
+ 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
7486
  const sc = (p) => {
6996
7487
  const q = toScreen(state, p);
6997
7488
  return { x: fmt(q.x), y: fmt(q.y) };
@@ -6999,14 +7490,26 @@ function getVectorOverlayRenderData(state) {
6999
7490
  const sameWidth = (a, b) => !!a && a.nodeId === b.nodeId && a.index === b.index;
7000
7491
  const widthPoints = getVectorWidthHandles(state).map((h) => {
7001
7492
  const c = sc(h);
7002
- const hw = _optionalChain([state, 'access', _211 => _211.hover, 'optionalAccess', _212 => _212.widthPoint]);
7493
+ const hw = _optionalChain([state, 'access', _233 => _233.hover, 'optionalAccess', _234 => _234.widthPoint]);
7003
7494
  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) };
7495
+ 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
7496
  });
7006
- const spot = state.tool === "width" && !it ? _optionalChain([state, 'access', _214 => _214.hover, 'optionalAccess', _215 => _215.strokeSpot]) : null;
7497
+ const spot = state.tool === "width" && !it ? _optionalChain([state, 'access', _236 => _236.hover, 'optionalAccess', _237 => _237.strokeSpot]) : null;
7007
7498
  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 };
7499
+ if (_optionalChain([it, 'optionalAccess', _238 => _238.type]) === "width") status = it.mode === "move" ? "Move width point" : `W ${fmt(it.width)}`;
7500
+ let builder = null;
7501
+ if (state.builder) {
7502
+ const v2 = state.viewport;
7503
+ const view = [v2.zoom, 0, 0, v2.zoom, v2.x, v2.y];
7504
+ const d = (path) => _chunk7EDLVBOOcjs.bezierPathToSvg.call(void 0, _chunk7EDLVBOOcjs.transformBezierPath.call(void 0, path, view), { precision: 2 });
7505
+ 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;
7506
+ builder = { mode: state.builder.mode, faces: state.builder.faces.map(d), lines: state.builder.lines.map(d), trail };
7507
+ if (state.builder.mode !== "fill" && _optionalChain([it, 'optionalAccess', _239 => _239.type]) === "builder") {
7508
+ const n = state.builder.faces.length;
7509
+ status = state.builder.mode === "erase" ? `Delete ${n} ${n === 1 ? "face" : "faces"}` : `Merge ${n} ${n === 1 ? "face" : "faces"}`;
7510
+ }
7511
+ }
7512
+ return { outlines, selectionBox, anchors, handles, marquee, penPreview, artboard, guides, status, toolStroke, pencilString, cutPoint, cornerWidgets, widthPoints, widthSpot, builder };
7010
7513
  }
7011
7514
  var VECTOR_OVERLAY_THEME = {
7012
7515
  accent: "#0ea5e9",
@@ -7022,7 +7525,12 @@ var VECTOR_OVERLAY_THEME = {
7022
7525
  /** Radius of a live corner widget (a ring with a dot). */
7023
7526
  cornerWidgetRadius: 4,
7024
7527
  /** Half the diagonal of a width point's diamond. */
7025
- widthPointSize: 5
7528
+ widthPointSize: 5,
7529
+ /** Shape Builder faces to merge and paint bucket regions. */
7530
+ builderFill: "rgba(14, 165, 233, 0.22)",
7531
+ /** Shape Builder faces and line pieces an Alt gesture deletes. */
7532
+ builderErase: "#ef4444",
7533
+ builderEraseFill: "rgba(239, 68, 68, 0.22)"
7026
7534
  };
7027
7535
  function vectorDiamondPath(x, y, r = VECTOR_OVERLAY_THEME.widthPointSize) {
7028
7536
  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 +7554,7 @@ function isVectorTextTarget(target) {
7046
7554
  if (!el || typeof el !== "object") return false;
7047
7555
  const tag = (_nullishCoalesce(el.tagName, () => ( ""))).toUpperCase();
7048
7556
  if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
7049
- return !!el.isContentEditable || _optionalChain([el, 'access', _217 => _217.getAttribute, 'optionalCall', _218 => _218("contenteditable")]) === "true";
7557
+ return !!el.isContentEditable || _optionalChain([el, 'access', _240 => _240.getAttribute, 'optionalCall', _241 => _241("contenteditable")]) === "true";
7050
7558
  }
7051
7559
  function getVectorSelectionStyle(state) {
7052
7560
  const paths = [];
@@ -7054,12 +7562,12 @@ function getVectorSelectionStyle(state) {
7054
7562
  const node = findVectorNode(state.document.nodes, id);
7055
7563
  if (node) paths.push(...collect(node));
7056
7564
  }
7057
- const anchorMode = state.tool === "direct" && !!_optionalChain([state, 'access', _219 => _219.selectedAnchors, 'optionalAccess', _220 => _220.length]);
7565
+ const anchorMode = state.tool === "direct" && !!_optionalChain([state, 'access', _242 => _242.selectedAnchors, 'optionalAccess', _243 => _243.length]);
7058
7566
  if (anchorMode) {
7059
7567
  for (const r of state.selectedAnchors) {
7060
7568
  if (paths.some((p) => p.id === r.nodeId)) continue;
7061
7569
  const node = findVectorNode(state.document.nodes, r.nodeId);
7062
- if (_optionalChain([node, 'optionalAccess', _221 => _221.type]) === "path") paths.push(node);
7570
+ if (_optionalChain([node, 'optionalAccess', _244 => _244.type]) === "path") paths.push(node);
7063
7571
  }
7064
7572
  }
7065
7573
  if (!paths.length) return null;
@@ -7070,7 +7578,7 @@ function getVectorSelectionStyle(state) {
7070
7578
  for (const c of vectorCorners(p.subpaths)) {
7071
7579
  if (anchorMode && !state.selectedAnchors.some((r) => r.nodeId === p.id && r.subpath === c.subpath && r.index === c.index)) continue;
7072
7580
  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")) });
7581
+ corners2.push({ radius: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _245 => _245.radius]), () => ( 0)), kind: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _246 => _246.kind]), () => ( "round")) });
7074
7582
  }
7075
7583
  }
7076
7584
  const c0 = _nullishCoalesce(corners2[0], () => ( { radius: 0, kind: "round" }));
@@ -7138,6 +7646,14 @@ var VECTOR_PATH_ACTIONS = [
7138
7646
  { id: "smooth", label: "\u223F", title: "Smooth", enabled: (s, p) => s + p > 0, run: (c) => c.smoothPaths() },
7139
7647
  { id: "outline", label: "\u22A1", title: "Outline Stroke", enabled: (s) => s > 0, run: (c) => c.outlineStroke() }
7140
7648
  ];
7649
+ var VECTOR_PATHFINDER_ACTIONS = [
7650
+ { id: "divide", label: "\u229E", title: "Divide", min: 1 },
7651
+ { id: "trim", label: "\u29C9", title: "Trim", min: 2 },
7652
+ { id: "merge", label: "\u29C8", title: "Merge", min: 2 },
7653
+ { id: "crop", label: "\u2317", title: "Crop", min: 2 },
7654
+ { id: "outline", label: "\u2B1A", title: "Outline", min: 1 },
7655
+ { id: "minusBack", label: "\u2296", title: "Minus Back", min: 2 }
7656
+ ];
7141
7657
  var VECTOR_EDIT_TOGGLES = [
7142
7658
  { key: "keepShapeOnDelete", label: "Keep", title: "Keep shape when deleting points" },
7143
7659
  { key: "curvatureMoves", label: "Curv", title: "Curvature point moves (Alt flips while dragging)" },
@@ -7210,17 +7726,17 @@ function createVectorCommands(controller, options = {}) {
7210
7726
  const base = { group, ...options.scope ? { scope: options.scope } : {} };
7211
7727
  const hasSelection = () => controller.getState().selection.length ? true : "Nothing is selected.";
7212
7728
  const ids = (params) => {
7213
- const list2 = _nullishCoalesce(_optionalChain([params, 'optionalAccess', _224 => _224.ids]), () => ( controller.getState().selection));
7729
+ const list2 = _nullishCoalesce(_optionalChain([params, 'optionalAccess', _247 => _247.ids]), () => ( controller.getState().selection));
7214
7730
  for (const id of list2) if (!controller.getNode(id)) fail(`There is no node "${id}".`);
7215
7731
  if (!list2.length) fail("Nothing is selected; pass ids.");
7216
7732
  return list2;
7217
7733
  };
7218
- const enabledFor = (_, params) => _optionalChain([params, 'optionalAccess', _225 => _225.ids, 'optionalAccess', _226 => _226.length]) ? true : hasSelection();
7734
+ const enabledFor = (_, params) => _optionalChain([params, 'optionalAccess', _248 => _248.ids, 'optionalAccess', _249 => _249.length]) ? true : hasSelection();
7219
7735
  const anchorsOf = (refs) => {
7220
7736
  if (!refs) return [...controller.getState().selectedAnchors];
7221
7737
  for (const r of refs) {
7222
7738
  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}".`);
7739
+ 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
7740
  }
7225
7741
  return refs;
7226
7742
  };
@@ -7311,7 +7827,7 @@ function createVectorCommands(controller, options = {}) {
7311
7827
  run: (_ctx, params) => {
7312
7828
  const id = controller.addPath(params.d, { ...pickStyle(params), ...params.name ? { name: params.name } : {} });
7313
7829
  const node = controller.getNode(id);
7314
- if (_optionalChain([node, 'optionalAccess', _232 => _232.type]) === "path" && !node.subpaths.length) {
7830
+ if (_optionalChain([node, 'optionalAccess', _255 => _255.type]) === "path" && !node.subpaths.length) {
7315
7831
  controller.undo();
7316
7832
  fail("The path data has no points.");
7317
7833
  }
@@ -7343,10 +7859,10 @@ function createVectorCommands(controller, options = {}) {
7343
7859
  params: { type: "object", properties: { radius: { type: "number", minimum: 0 }, kind: { type: "string", enum: VECTOR_CORNER_KINDS }, ids: IDS, anchors: ANCHORS } },
7344
7860
  undoable: true,
7345
7861
  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));
7862
+ const refs = _optionalChain([params, 'optionalAccess', _256 => _256.anchors]) ? anchorsOf(params.anchors) : void 0;
7863
+ const target = { refs, ids: _optionalChain([params, 'optionalAccess', _257 => _257.ids]) ? ids(params) : void 0 };
7864
+ if (_optionalChain([params, 'optionalAccess', _258 => _258.radius]) !== void 0) check(controller.setCornerRadius(params.radius, { ...target, kind: params.kind }));
7865
+ else if (_optionalChain([params, 'optionalAccess', _259 => _259.kind])) check(controller.setCornerKind(params.kind, target));
7350
7866
  else fail("Pass `radius` and / or `kind`.");
7351
7867
  return { ok: true };
7352
7868
  }
@@ -7381,12 +7897,12 @@ function createVectorCommands(controller, options = {}) {
7381
7897
  undoable: true,
7382
7898
  run: (_ctx, params) => {
7383
7899
  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));
7900
+ if (_optionalChain([params, 'optionalAccess', _260 => _260.preset])) check(controller.setWidthProfile(params.preset, target));
7901
+ else if (_optionalChain([params, 'optionalAccess', _261 => _261.points]) !== void 0) check(controller.setWidthProfile(_nullishCoalesce(params.points, () => ( null)), target));
7902
+ 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
7903
  else fail("Pass `preset`, `points`, `taper` or `wave`.");
7388
7904
  const node = controller.getNode(target.ids[0]);
7389
- return { ok: true, points: _optionalChain([node, 'optionalAccess', _241 => _241.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
7905
+ return { ok: true, points: _optionalChain([node, 'optionalAccess', _264 => _264.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
7390
7906
  }
7391
7907
  },
7392
7908
  {
@@ -7399,7 +7915,7 @@ function createVectorCommands(controller, options = {}) {
7399
7915
  enabled: enabledFor,
7400
7916
  undoable: true,
7401
7917
  run: (_ctx, params) => {
7402
- const created = controller.outlineStroke({ ids: _optionalChain([params, 'optionalAccess', _242 => _242.ids]) ? ids(params) : void 0 });
7918
+ const created = controller.outlineStroke({ ids: _optionalChain([params, 'optionalAccess', _265 => _265.ids]) ? ids(params) : void 0 });
7403
7919
  if (!created.length) fail("No selected path has a stroke.");
7404
7920
  return { ids: created };
7405
7921
  }
@@ -7461,6 +7977,62 @@ function createVectorCommands(controller, options = {}) {
7461
7977
  return { id };
7462
7978
  }
7463
7979
  },
7980
+ {
7981
+ ...base,
7982
+ id: `${prefix}pathfinder`,
7983
+ label: "Pathfinder\u2026",
7984
+ keywords: ["divide", "trim", "merge", "crop", "outline", "minus back", "split", "faces"],
7985
+ 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.",
7986
+ params: { type: "object", properties: { operation: { type: "string", enum: [...VECTOR_PATHFINDER_OPERATIONS] }, ids: IDS }, required: ["operation"] },
7987
+ undoable: true,
7988
+ run: (_ctx, params) => {
7989
+ if (!VECTOR_PATHFINDER_OPERATIONS.includes(params.operation)) fail(`Unknown Pathfinder operation "${params.operation}".`);
7990
+ const created = controller.pathfinder(params.operation, { ids: ids(params) });
7991
+ if (!created.length) fail("Nothing came out: select paths that overlap (two or more, except for divide and outline).");
7992
+ return { ids: created, selection: [...controller.getState().selection] };
7993
+ }
7994
+ },
7995
+ {
7996
+ ...base,
7997
+ id: `${prefix}shapeBuilderFaces`,
7998
+ label: "List Shape Builder Faces",
7999
+ keywords: ["shape builder", "regions", "faces", "planar"],
8000
+ 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).",
8001
+ params: { type: "object", properties: { ids: IDS } },
8002
+ run: (_ctx, params) => ({ faces: controller.getShapeBuilderFaces({ ids: ids(params) }) })
8003
+ },
8004
+ {
8005
+ ...base,
8006
+ id: `${prefix}shapeBuilder`,
8007
+ label: "Shape Builder",
8008
+ keywords: ["merge faces", "build shape", "combine regions", "delete region"],
8009
+ 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 and the pieces of unfilled open paths within `tolerance`. Shapes covering those faces lose that area.",
8010
+ params: {
8011
+ type: "object",
8012
+ properties: { points: POINTS, erase: { type: "boolean" }, tolerance: { type: "number", minimum: 0 }, ids: IDS },
8013
+ required: ["points"]
8014
+ },
8015
+ undoable: true,
8016
+ run: (_ctx, params) => {
8017
+ const result = controller.shapeBuilder(params.points.map(([x, y]) => ({ x, y })), { ids: ids(params), erase: params.erase, tolerance: params.tolerance });
8018
+ check(result);
8019
+ return { merged: result.merged, faces: result.faces, lines: result.lines };
8020
+ }
8021
+ },
8022
+ {
8023
+ ...base,
8024
+ id: `${prefix}fillRegion`,
8025
+ label: "Fill Region",
8026
+ keywords: ["paint bucket", "live paint", "fill area", "enclosed"],
8027
+ 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.",
8028
+ 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"] },
8029
+ undoable: true,
8030
+ run: (_ctx, params) => {
8031
+ const id = controller.fillRegion({ x: params.point[0], y: params.point[1] }, { gap: params.gap });
8032
+ if (!id) fail("No closed region surrounds that point.");
8033
+ return { id };
8034
+ }
8035
+ },
7464
8036
  {
7465
8037
  ...base,
7466
8038
  id: `${prefix}align`,
@@ -7514,7 +8086,7 @@ function createVectorCommands(controller, options = {}) {
7514
8086
  enabled: enabledFor,
7515
8087
  undoable: true,
7516
8088
  run: (_ctx, params) => {
7517
- const id = controller.group({ ids: ids(params), name: _optionalChain([params, 'optionalAccess', _243 => _243.name]) });
8089
+ const id = controller.group({ ids: ids(params), name: _optionalChain([params, 'optionalAccess', _266 => _266.name]) });
7518
8090
  if (!id) fail("Only nodes that share a parent can be grouped.");
7519
8091
  return { id };
7520
8092
  }
@@ -7542,7 +8114,7 @@ function createVectorCommands(controller, options = {}) {
7542
8114
  params: { type: "object", properties: { anchors: ANCHORS, keepShape: { type: "boolean" } } },
7543
8115
  undoable: true,
7544
8116
  run: (_ctx, params) => {
7545
- check(controller.deleteAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _244 => _244.anchors])), { keepShape: _optionalChain([params, 'optionalAccess', _245 => _245.keepShape]) }));
8117
+ check(controller.deleteAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _267 => _267.anchors])), { keepShape: _optionalChain([params, 'optionalAccess', _268 => _268.keepShape]) }));
7546
8118
  return { ok: true };
7547
8119
  }
7548
8120
  },
@@ -7597,7 +8169,7 @@ function createVectorCommands(controller, options = {}) {
7597
8169
  params: { type: "object", properties: { ids: IDS, tolerance: { type: "number", minimum: 0 } } },
7598
8170
  undoable: true,
7599
8171
  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]) }));
8172
+ check(controller.joinPaths({ ids: _optionalChain([params, 'optionalAccess', _269 => _269.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _270 => _270.tolerance]) }));
7601
8173
  return { selection: controller.getState().selection };
7602
8174
  }
7603
8175
  },
@@ -7611,7 +8183,7 @@ function createVectorCommands(controller, options = {}) {
7611
8183
  params: { type: "object", properties: { axis: { type: "string", enum: ["horizontal", "vertical", "both"] }, anchors: ANCHORS } },
7612
8184
  undoable: true,
7613
8185
  run: (_ctx, params) => {
7614
- check(controller.averageAnchors(_nullishCoalesce(_optionalChain([params, 'optionalAccess', _248 => _248.axis]), () => ( "both")), anchorsOf(_optionalChain([params, 'optionalAccess', _249 => _249.anchors]))));
8186
+ check(controller.averageAnchors(_nullishCoalesce(_optionalChain([params, 'optionalAccess', _271 => _271.axis]), () => ( "both")), anchorsOf(_optionalChain([params, 'optionalAccess', _272 => _272.anchors]))));
7615
8187
  return { ok: true };
7616
8188
  }
7617
8189
  },
@@ -7625,7 +8197,7 @@ function createVectorCommands(controller, options = {}) {
7625
8197
  enabled: enabledFor,
7626
8198
  undoable: true,
7627
8199
  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]) }));
8200
+ check(controller.removeRedundantPoints({ ids: _optionalChain([params, 'optionalAccess', _273 => _273.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _274 => _274.tolerance]) }));
7629
8201
  return { ok: true };
7630
8202
  }
7631
8203
  },
@@ -7638,7 +8210,7 @@ function createVectorCommands(controller, options = {}) {
7638
8210
  params: { type: "object", properties: { ids: IDS, amount: { type: "number", minimum: 0, maximum: 1 }, anchors: ANCHORS } },
7639
8211
  undoable: true,
7640
8212
  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]) }));
8213
+ 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
8214
  return { ok: true };
7643
8215
  }
7644
8216
  },
@@ -7651,14 +8223,14 @@ function createVectorCommands(controller, options = {}) {
7651
8223
  params: { type: "object", properties: { nodeId: { type: "string" }, x: { type: "number" }, y: { type: "number" }, anchors: ANCHORS } },
7652
8224
  undoable: true,
7653
8225
  run: (_ctx, params) => {
7654
- if (_optionalChain([params, 'optionalAccess', _255 => _255.nodeId]) !== void 0) {
8226
+ if (_optionalChain([params, 'optionalAccess', _278 => _278.nodeId]) !== void 0) {
7655
8227
  if (!controller.getNode(params.nodeId)) fail(`There is no node "${params.nodeId}".`);
7656
8228
  if (params.x === void 0 || params.y === void 0) fail("Pass x and y with nodeId.");
7657
8229
  const created = controller.cutPathAt(params.nodeId, { x: params.x, y: params.y });
7658
8230
  if (!created) fail("Nothing to cut there (the end of an open path, or a locked path).");
7659
8231
  return { ids: created };
7660
8232
  }
7661
- check(controller.cutAtAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _256 => _256.anchors]))));
8233
+ check(controller.cutAtAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _279 => _279.anchors]))));
7662
8234
  return { ids: controller.getState().selection };
7663
8235
  }
7664
8236
  },
@@ -7709,7 +8281,7 @@ function createVectorCommands(controller, options = {}) {
7709
8281
  },
7710
8282
  run: (_ctx, params) => {
7711
8283
  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];
8284
+ for (const key of ["keepShapeOnDelete", "curvatureMoves", "pencilSmoothing", "recognizeShapes", "eraserSize", "pencilPressure"]) if (_optionalChain([params, 'optionalAccess', _280 => _280[key]]) !== void 0) patch[key] = params[key];
7713
8285
  controller.setEditing(patch);
7714
8286
  return { editing: controller.getState().editing };
7715
8287
  }
@@ -7734,7 +8306,7 @@ function createVectorCommands(controller, options = {}) {
7734
8306
  keywords: ["download", "save", "markup"],
7735
8307
  description: "Returns the document as SVG markup.",
7736
8308
  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]) }) })
8309
+ run: (_ctx, params) => ({ svg: controller.toSvg({ precision: _optionalChain([params, 'optionalAccess', _281 => _281.precision]) }) })
7738
8310
  },
7739
8311
  {
7740
8312
  ...base,
@@ -7932,5 +8504,19 @@ function createVectorCommands(controller, options = {}) {
7932
8504
 
7933
8505
 
7934
8506
 
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;
8507
+
8508
+
8509
+
8510
+
8511
+
8512
+
8513
+
8514
+
8515
+
8516
+
8517
+
8518
+
8519
+
8520
+
8521
+ 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_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.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
8522
  //# sourceMappingURL=index.cjs.map