@pixerate/editor 0.43.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +27 -2
  2. package/THIRD_PARTY_NOTICES.md +4 -0
  3. package/dist/agent/index.cjs +548 -45
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +47 -17
  6. package/dist/agent/index.d.ts +47 -17
  7. package/dist/agent/index.js +536 -33
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/{builtins-BLud97fC.d.cts → builtins-CZW-aYKS.d.cts} +1 -1
  10. package/dist/{builtins-D0BDyAgw.d.ts → builtins-DghNQbT-.d.ts} +1 -1
  11. package/dist/{chunk-I6BZB5ZH.cjs → chunk-EFDCLENW.cjs} +73 -6
  12. package/dist/chunk-EFDCLENW.cjs.map +1 -0
  13. package/dist/chunk-HHQ4XJWT.js +826 -0
  14. package/dist/chunk-HHQ4XJWT.js.map +1 -0
  15. package/dist/chunk-J3R2OWOE.cjs +1465 -0
  16. package/dist/chunk-J3R2OWOE.cjs.map +1 -0
  17. package/dist/chunk-K2LVZ4FA.cjs +826 -0
  18. package/dist/chunk-K2LVZ4FA.cjs.map +1 -0
  19. package/dist/{chunk-6MDQKHRH.cjs → chunk-N4MLNJPO.cjs} +21 -899
  20. package/dist/chunk-N4MLNJPO.cjs.map +1 -0
  21. package/dist/chunk-PQM5W7ZN.js +168 -0
  22. package/dist/chunk-PQM5W7ZN.js.map +1 -0
  23. package/dist/{chunk-DDADOHJW.js → chunk-Q25ZS4F7.js} +5 -883
  24. package/dist/chunk-Q25ZS4F7.js.map +1 -0
  25. package/dist/chunk-TK2XZK6Z.js +1465 -0
  26. package/dist/chunk-TK2XZK6Z.js.map +1 -0
  27. package/dist/commands/index.cjs +3 -2
  28. package/dist/commands/index.cjs.map +1 -1
  29. package/dist/commands/index.d.cts +5 -5
  30. package/dist/commands/index.d.ts +5 -5
  31. package/dist/commands/index.js +2 -1
  32. package/dist/commands/index.js.map +1 -1
  33. package/dist/extensions/index.cjs +4 -4
  34. package/dist/extensions/index.cjs.map +1 -1
  35. package/dist/extensions/index.d.cts +3 -3
  36. package/dist/extensions/index.d.ts +3 -3
  37. package/dist/extensions/index.js +12 -12
  38. package/dist/generation/index.cjs +2 -2
  39. package/dist/generation/index.d.cts +4 -4
  40. package/dist/generation/index.d.ts +4 -4
  41. package/dist/generation/index.js +1 -1
  42. package/dist/image-editor/index.cjs +24 -24
  43. package/dist/image-editor/index.cjs.map +1 -1
  44. package/dist/image-editor/index.d.cts +2 -2
  45. package/dist/image-editor/index.d.ts +2 -2
  46. package/dist/image-editor/index.js +24 -24
  47. package/dist/image-editor/index.js.map +1 -1
  48. package/dist/{index-C6gaQRH0.d.cts → index-CfOQf70b.d.cts} +1 -1
  49. package/dist/{index-DXAv_R08.d.ts → index-jwJ_onWf.d.ts} +1 -1
  50. package/dist/index.cjs +9 -9
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.cts +4 -4
  53. package/dist/index.d.ts +4 -4
  54. package/dist/index.js +12 -12
  55. package/dist/parameters/index.d.cts +2 -2
  56. package/dist/parameters/index.d.ts +2 -2
  57. package/dist/{registry-DnzpgY27.d.cts → registry-B4l-lYts.d.cts} +1 -1
  58. package/dist/{registry-DhVUZioj.d.ts → registry-BfVD-vVg.d.ts} +1 -1
  59. package/dist/{registry-BDe-vlv3.d.ts → registry-CSlH4iUn.d.ts} +1 -1
  60. package/dist/{registry-D0GADKc7.d.cts → registry-vz6HOiiy.d.cts} +1 -1
  61. package/dist/{schema-DYDGdYL9.d.cts → schema-Di0CS6Pe.d.cts} +26 -2
  62. package/dist/{schema-DYDGdYL9.d.ts → schema-Di0CS6Pe.d.ts} +26 -2
  63. package/dist/tools/index.cjs +37 -3
  64. package/dist/tools/index.cjs.map +1 -1
  65. package/dist/tools/index.d.cts +871 -11
  66. package/dist/tools/index.d.ts +871 -11
  67. package/dist/tools/index.js +36 -2
  68. package/dist/vector/index.cjs +1982 -301
  69. package/dist/vector/index.cjs.map +1 -1
  70. package/dist/vector/index.d.cts +624 -154
  71. package/dist/vector/index.d.ts +624 -154
  72. package/dist/vector/index.js +1755 -74
  73. package/dist/vector/index.js.map +1 -1
  74. package/package.json +1 -1
  75. package/dist/chunk-36BLROHV.js +0 -438
  76. package/dist/chunk-36BLROHV.js.map +0 -1
  77. package/dist/chunk-5H2OPMXZ.js +0 -586
  78. package/dist/chunk-5H2OPMXZ.js.map +0 -1
  79. package/dist/chunk-6MDQKHRH.cjs.map +0 -1
  80. package/dist/chunk-D6S5M7HV.js +0 -101
  81. package/dist/chunk-D6S5M7HV.js.map +0 -1
  82. package/dist/chunk-DDADOHJW.js.map +0 -1
  83. package/dist/chunk-I6BZB5ZH.cjs.map +0 -1
  84. package/dist/chunk-MC2LQN5S.cjs +0 -586
  85. package/dist/chunk-MC2LQN5S.cjs.map +0 -1
  86. package/dist/chunk-V7CC7RZ6.cjs +0 -438
  87. package/dist/chunk-V7CC7RZ6.cjs.map +0 -1
@@ -37,6 +37,7 @@ var _chunkQKLRAA4Tcjs = require('../chunk-QKLRAA4T.cjs');
37
37
 
38
38
 
39
39
 
40
+
40
41
 
41
42
 
42
43
  var _chunkVNYRI265cjs = require('../chunk-VNYRI265.cjs');
@@ -79,11 +80,12 @@ var VECTOR_TOOLS = [
79
80
  "shapeBuilder",
80
81
  "paintBucket",
81
82
  "blend",
82
- "gradient"
83
+ "gradient",
84
+ "envelope"
83
85
  ];
84
86
  var VECTOR_TRANSFORM_HANDLES = ["nw", "n", "ne", "e", "se", "s", "sw", "w", "rotate"];
85
87
  var VECTOR_PATHFINDER_OPERATIONS = ["divide", "trim", "merge", "crop", "outline", "minusBack"];
86
- var VECTOR_EFFECT_TYPES = ["trim", "roundCorners", "puckerBloat", "twist", "zigzag", "wiggle", "offset", "merge", "repeater"];
88
+ var VECTOR_EFFECT_TYPES = ["trim", "roundCorners", "puckerBloat", "twist", "zigzag", "wiggle", "offset", "merge", "repeater", "envelope"];
87
89
  var VECTOR_MERGE_MODES = ["merge", "add", "subtract", "intersect", "exclude"];
88
90
 
89
91
  // src/vector/gradient.ts
@@ -482,6 +484,14 @@ function transformVectorGradient(g, m) {
482
484
  const p = vectorGradientPoints(g);
483
485
  return { ...g, start: apply(m, p.start), end: apply(m, p.end), width: apply(m, p.width), ...p.focal ? { focal: apply(m, p.focal) } : {} };
484
486
  }
487
+ function mapVectorGradient(g, f) {
488
+ if (!hasExplicitGradientGeometry(g) || g.units !== "userSpaceOnUse") return g;
489
+ const p = vectorGradientPoints(g);
490
+ return { ...g, start: f(p.start), end: f(p.end), width: f(p.width), ...p.focal ? { focal: f(p.focal) } : {} };
491
+ }
492
+ function mapVectorPaint(paint, f) {
493
+ return isVectorGradient(paint) ? mapVectorGradient(paint, f) : paint;
494
+ }
485
495
  function transformVectorPaint(paint, m) {
486
496
  return isVectorGradient(paint) ? transformVectorGradient(paint, m) : paint;
487
497
  }
@@ -1179,8 +1189,8 @@ function widthProfilePreset(id) {
1179
1189
  }
1180
1190
  function widthProfilePresetId(points) {
1181
1191
  if (isUniformWidthProfile(points)) return "uniform";
1182
- 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);
1183
- return _nullishCoalesce(_optionalChain([VECTOR_WIDTH_PRESETS, 'access', _20 => _20.find, 'call', _21 => _21((p) => p.points.length && same(points, p.points)), 'optionalAccess', _22 => _22.id]), () => ( "custom"));
1192
+ const same2 = (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);
1193
+ return _nullishCoalesce(_optionalChain([VECTOR_WIDTH_PRESETS, 'access', _20 => _20.find, 'call', _21 => _21((p) => p.points.length && same2(points, p.points)), 'optionalAccess', _22 => _22.id]), () => ( "custom"));
1184
1194
  }
1185
1195
  function reverseWidthProfile(points) {
1186
1196
  return points.map((p) => ({ t: 1 - p.t, left: p.right, right: p.left })).reverse();
@@ -1200,10 +1210,10 @@ function insertWidthPoint(points, t, sides2 = {}, options = {}) {
1200
1210
  left: _nullishCoalesce(clean(sides2.left, VECTOR_WIDTH_PROFILE_MAX_SCALE), () => ( here.left)),
1201
1211
  right: _nullishCoalesce(clean(sides2.right, VECTOR_WIDTH_PROFILE_MAX_SCALE), () => ( here.right))
1202
1212
  };
1203
- const same = pts.findIndex((q) => Math.abs(q.t - tt) <= VECTOR_WIDTH_SAME_T);
1204
- if (same >= 0 && !options.step) {
1205
- pts[same] = { ...p, t: pts[same].t };
1206
- return { points: pts, index: same };
1213
+ const same2 = pts.findIndex((q) => Math.abs(q.t - tt) <= VECTOR_WIDTH_SAME_T);
1214
+ if (same2 >= 0 && !options.step) {
1215
+ pts[same2] = { ...p, t: pts[same2].t };
1216
+ return { points: pts, index: same2 };
1207
1217
  }
1208
1218
  let i = 0;
1209
1219
  while (i < pts.length && pts[i].t <= tt) i++;
@@ -1743,13 +1753,13 @@ function endOf(segs, atStart) {
1743
1753
  const last = segs[segs.length - 1];
1744
1754
  return { p: toVec(last[last.length - 1]), out: v(t[0], t[1]) };
1745
1755
  }
1746
- function pointAlong(segs, fromStart, dist4) {
1756
+ function pointAlong(segs, fromStart, dist5) {
1747
1757
  const order = fromStart ? segs : [...segs].reverse();
1748
1758
  let acc = 0;
1749
1759
  for (const s of order) {
1750
1760
  const l = segLen(s);
1751
- if (acc + l >= dist4) {
1752
- const want = fromStart ? dist4 - acc : l - (dist4 - acc);
1761
+ if (acc + l >= dist5) {
1762
+ const want = fromStart ? dist5 - acc : l - (dist5 - acc);
1753
1763
  const pts = _chunkVNYRI265cjs.trimSegments.call(void 0, [s], 0, want);
1754
1764
  const p = pts.length ? pts[0][pts[0].length - 1] : s[0];
1755
1765
  return toVec(p);
@@ -2231,6 +2241,846 @@ function pathsCenter(paths) {
2231
2241
  return b ? { x: (b.minX + b.maxX) / 2, y: (b.minY + b.maxY) / 2 } : { x: 0, y: 0 };
2232
2242
  }
2233
2243
 
2244
+ // src/vector/pathMap.ts
2245
+ var MAX_PIECES = 1 << 20;
2246
+ var MAX_DEPTH = 6;
2247
+ var PROBES = [0.25, 0.5, 0.75];
2248
+ var lerp2 = (a, b, t) => ({ x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t });
2249
+ var dist2 = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
2250
+ var same = (a, b) => Math.abs(a.x - b.x) < 1e-9 && Math.abs(a.y - b.y) < 1e-9;
2251
+ function evalCubic(s, t) {
2252
+ const ab = lerp2(s[0], s[1], t);
2253
+ const bc = lerp2(s[1], s[2], t);
2254
+ const cd = lerp2(s[2], s[3], t);
2255
+ return lerp2(lerp2(ab, bc, t), lerp2(bc, cd, t), t);
2256
+ }
2257
+ function halves(s) {
2258
+ const ab = lerp2(s[0], s[1], 0.5);
2259
+ const bc = lerp2(s[1], s[2], 0.5);
2260
+ const cd = lerp2(s[2], s[3], 0.5);
2261
+ const abc = lerp2(ab, bc, 0.5);
2262
+ const bcd = lerp2(bc, cd, 0.5);
2263
+ const m = lerp2(abc, bcd, 0.5);
2264
+ return [
2265
+ [s[0], ab, abc, m],
2266
+ [m, bcd, cd, s[3]]
2267
+ ];
2268
+ }
2269
+ function offLine(p, a, b) {
2270
+ const l = dist2(a, b);
2271
+ return l < 1e-12 ? dist2(p, a) : Math.abs((b.x - a.x) * (a.y - p.y) - (a.x - p.x) * (b.y - a.y)) / l;
2272
+ }
2273
+ var mapAnchorPoints = (a, f) => {
2274
+ const p = f(a);
2275
+ return {
2276
+ x: p.x,
2277
+ y: p.y,
2278
+ ...a.in ? { in: f(a.in) } : {},
2279
+ ...a.out ? { out: f(a.out) } : {},
2280
+ ...a.type && a.type !== "corner" ? { type: a.type } : {},
2281
+ ...a.corner ? { corner: { ...a.corner } } : {}
2282
+ };
2283
+ };
2284
+ function mapVectorPoints(subpaths, f) {
2285
+ return subpaths.map((sp) => ({ closed: sp.closed, anchors: sp.anchors.map((a) => mapAnchorPoints(a, f)) }));
2286
+ }
2287
+ function splitMapped(seg, f, tol, depth, out) {
2288
+ const mapped = seg.map(f);
2289
+ const fits = PROBES.every((t) => dist2(f(evalCubic(seg, t)), evalCubic(mapped, t)) <= tol);
2290
+ if (fits || depth === 0) {
2291
+ out.push(mapped);
2292
+ return;
2293
+ }
2294
+ const [a, b] = halves(seg);
2295
+ splitMapped(a, f, tol, depth - 1, out);
2296
+ splitMapped(b, f, tol, depth - 1, out);
2297
+ }
2298
+ var toPoint = (p) => [p.x, p.y];
2299
+ var toVec2 = (p) => ({ x: p[0], y: p[1] });
2300
+ function refit(seg, pieces, f, tol) {
2301
+ if (pieces.length < 3) return pieces;
2302
+ const n = pieces.length * 4;
2303
+ const samples = [];
2304
+ for (let i = 0; i <= n; i++) samples.push(toPoint(f(evalCubic(seg, i / n))));
2305
+ const first = pieces[0];
2306
+ const last = pieces[pieces.length - 1];
2307
+ const t0 = !same(first[1], first[0]) ? first[1] : first[2];
2308
+ const t1 = !same(last[2], last[3]) ? last[2] : last[1];
2309
+ const fitted = _chunkVNYRI265cjs.fitCubicRun.call(void 0, samples, tol / 2, [t0.x - first[0].x, t0.y - first[0].y], [last[3].x - t1.x, last[3].y - t1.y]);
2310
+ if (!fitted.length || fitted.length >= pieces.length) return pieces;
2311
+ const chain = fitted.map((c) => [c.p0, c.p1, c.p2, c.p3]);
2312
+ for (let i = 0; i < n; i++) {
2313
+ const q = toPoint(f(evalCubic(seg, (i + 0.5) / n)));
2314
+ let best = Infinity;
2315
+ for (const c of chain) best = Math.min(best, _chunkVNYRI265cjs.segmentNearest.call(void 0, c, q).distance);
2316
+ if (best > tol) return pieces;
2317
+ }
2318
+ return fitted.map((c) => [toVec2(c.p0), toVec2(c.p1), toVec2(c.p2), toVec2(c.p3)]);
2319
+ }
2320
+ function mapSegment(seg, f, tol, depth, fit) {
2321
+ if (same(seg[1], seg[0]) && same(seg[2], seg[3])) {
2322
+ const a = f(seg[0]);
2323
+ const b = f(seg[3]);
2324
+ if (PROBES.every((t) => offLine(f(lerp2(seg[0], seg[3], t)), a, b) <= tol)) return [[a, a, b, b]];
2325
+ const line2 = [seg[0], lerp2(seg[0], seg[3], 1 / 3), lerp2(seg[0], seg[3], 2 / 3), seg[3]];
2326
+ const out2 = [];
2327
+ splitMapped(line2, f, tol, depth, out2);
2328
+ return fit ? refit(line2, out2, f, tol) : out2;
2329
+ }
2330
+ const out = [];
2331
+ splitMapped(seg, f, tol, depth, out);
2332
+ return fit ? refit(seg, out, f, tol) : out;
2333
+ }
2334
+ function realign(a) {
2335
+ if (!a.in || !a.out || same(a.in, a) || same(a.out, a)) return a;
2336
+ const li = dist2(a.in, a);
2337
+ const lo = dist2(a.out, a);
2338
+ const dx = (a.x - a.in.x) / li + (a.out.x - a.x) / lo;
2339
+ const dy = (a.y - a.in.y) / li + (a.out.y - a.y) / lo;
2340
+ const l = Math.hypot(dx, dy);
2341
+ if (l < 1e-12) return a;
2342
+ const u = { x: dx / l, y: dy / l };
2343
+ const type = a.type === "symmetric" && Math.abs(li - lo) > 1e-6 * Math.max(li, lo) ? "smooth" : a.type;
2344
+ return { ...a, in: { x: a.x - u.x * li, y: a.y - u.y * li }, out: { x: a.x + u.x * lo, y: a.y + u.y * lo }, ...type ? { type } : {} };
2345
+ }
2346
+ var segmentOf = (sp, i) => {
2347
+ const a = sp.anchors[i];
2348
+ const b = sp.anchors[(i + 1) % sp.anchors.length];
2349
+ return [{ x: a.x, y: a.y }, _nullishCoalesce(a.out, () => ( { x: a.x, y: a.y })), _nullishCoalesce(b.in, () => ( { x: b.x, y: b.y })), { x: b.x, y: b.y }];
2350
+ };
2351
+ function mapSubpath(sp, f, tol, depth, fit) {
2352
+ const n = sp.anchors.length;
2353
+ const count = n < 2 ? 0 : sp.closed ? n : n - 1;
2354
+ if (!count) return mapVectorPoints([sp], f)[0];
2355
+ const pieces = [];
2356
+ for (let i = 0; i < count; i++) pieces.push(mapSegment(segmentOf(sp, i), f, tol, depth, fit));
2357
+ const anchors = [];
2358
+ const put = (a) => {
2359
+ if (a.in && same(a.in, a)) delete a.in;
2360
+ if (a.out && same(a.out, a)) delete a.out;
2361
+ anchors.push(a.type === "smooth" || a.type === "symmetric" ? realign(a) : a);
2362
+ };
2363
+ sp.anchors.forEach((k, i) => {
2364
+ const incoming = i > 0 ? pieces[i - 1] : sp.closed ? pieces[n - 1] : void 0;
2365
+ const outgoing = pieces[i];
2366
+ const p = f(k);
2367
+ const a = { x: p.x, y: p.y };
2368
+ const inCtrl = incoming ? incoming[incoming.length - 1][2] : k.in ? f(k.in) : null;
2369
+ const outCtrl = outgoing ? outgoing[0][1] : k.out ? f(k.out) : null;
2370
+ if (inCtrl) a.in = inCtrl;
2371
+ if (outCtrl) a.out = outCtrl;
2372
+ if (k.type && k.type !== "corner") a.type = k.type;
2373
+ if (k.corner) a.corner = { ...k.corner };
2374
+ put(a);
2375
+ if (outgoing) for (let w = 1; w < outgoing.length; w++) put({ x: outgoing[w][0].x, y: outgoing[w][0].y, in: outgoing[w - 1][2], out: outgoing[w][1], type: "smooth" });
2376
+ });
2377
+ return { closed: sp.closed, anchors };
2378
+ }
2379
+ function mapVectorSubpaths(subpaths, f, tolerance = 0.1, options = {}) {
2380
+ const tol = Number.isFinite(tolerance) && tolerance > 0 ? tolerance : 0.1;
2381
+ const segments = subpaths.reduce((s, sp) => s + sp.anchors.length, 0);
2382
+ let depth = MAX_DEPTH;
2383
+ while (depth > 0 && segments * 2 ** depth > MAX_PIECES) depth--;
2384
+ return subpaths.map((sp) => mapSubpath(sp, f, tol, depth, options.refit !== false));
2385
+ }
2386
+ function mapBezierPath(path, f, tolerance = 0.1, options = {}) {
2387
+ return subpathsToBezier(mapVectorSubpaths(bezierToSubpaths(path), f, tolerance, options), { corners: false });
2388
+ }
2389
+
2390
+ // src/vector/warp.ts
2391
+ var VECTOR_WARP_STYLES = [
2392
+ "arc",
2393
+ "arcLower",
2394
+ "arcUpper",
2395
+ "arch",
2396
+ "bulge",
2397
+ "shellLower",
2398
+ "shellUpper",
2399
+ "flag",
2400
+ "wave",
2401
+ "fish",
2402
+ "rise",
2403
+ "fisheye",
2404
+ "inflate",
2405
+ "squeeze",
2406
+ "twist"
2407
+ ];
2408
+ var VECTOR_WARP_STYLE_LABELS = {
2409
+ arc: "Arc",
2410
+ arcLower: "Arc Lower",
2411
+ arcUpper: "Arc Upper",
2412
+ arch: "Arch",
2413
+ bulge: "Bulge",
2414
+ shellLower: "Shell Lower",
2415
+ shellUpper: "Shell Upper",
2416
+ flag: "Flag",
2417
+ wave: "Wave",
2418
+ fish: "Fish",
2419
+ rise: "Rise",
2420
+ fisheye: "Fisheye",
2421
+ inflate: "Inflate",
2422
+ squeeze: "Squeeze",
2423
+ twist: "Twist"
2424
+ };
2425
+ function restGrid() {
2426
+ return [0, 1, 2, 3].map((j) => [0, 1, 2, 3].map((i) => [i / 3, j / 3]));
2427
+ }
2428
+ function edgeArc(y, b, up, h) {
2429
+ if (Math.abs(b) < 1e-9) return [0, 1, 2, 3].map((i) => [i / 3, y]);
2430
+ const th = Math.abs(b) * Math.PI;
2431
+ const k = 4 / 3 * Math.tan(th / 4) * 0.5 / Math.sin(th / 2);
2432
+ const s = b > 0 === up ? -1 : 1;
2433
+ const c = Math.cos(th / 2);
2434
+ const n = Math.sin(th / 2);
2435
+ const dy = s * k * n / h;
2436
+ return [
2437
+ [0, y],
2438
+ [k * c, y + dy],
2439
+ [1 - k * c, y + dy],
2440
+ [1, y]
2441
+ ];
2442
+ }
2443
+ function arcGrid(b, h) {
2444
+ if (Math.abs(b) < 1e-9) return restGrid();
2445
+ const up = b > 0;
2446
+ const th = Math.abs(b) * Math.PI;
2447
+ const r = 0.5 / Math.sin(th / 2);
2448
+ const k = 4 / 3 * Math.tan(th / 4);
2449
+ const s = up ? -1 : 1;
2450
+ const cy = up ? h + r * Math.cos(th / 2) : -r * Math.cos(th / 2);
2451
+ return [0, 1, 2, 3].map((j) => {
2452
+ const v2 = j / 3;
2453
+ const big = r + h * (up ? 1 - v2 : v2);
2454
+ const at2 = (a) => [0.5 + big * Math.sin(a), cy + s * big * Math.cos(a)];
2455
+ const tangent2 = (a) => [Math.cos(a), -s * Math.sin(a)];
2456
+ const p0 = at2(-th / 2);
2457
+ const p3 = at2(th / 2);
2458
+ const t0 = tangent2(-th / 2);
2459
+ const t1 = tangent2(th / 2);
2460
+ const l = k * big;
2461
+ const pts = [p0, [p0[0] + l * t0[0], p0[1] + l * t0[1]], [p3[0] - l * t1[0], p3[1] - l * t1[1]], p3];
2462
+ return pts.map((p) => [p[0], p[1] / h]);
2463
+ });
2464
+ }
2465
+ function blendRows(top, bottom) {
2466
+ return [0, 1, 2, 3].map((j) => {
2467
+ const t = j / 3;
2468
+ return [0, 1, 2, 3].map((i) => [top[i][0] + (bottom[i][0] - top[i][0]) * t, top[i][1] + (bottom[i][1] - top[i][1]) * t]);
2469
+ });
2470
+ }
2471
+ var INNER = [
2472
+ [1, 1, -1, -1],
2473
+ [1, 2, 1, -1],
2474
+ [2, 1, -1, 1],
2475
+ [2, 2, 1, 1]
2476
+ ];
2477
+ function vectorWarpPresetGrid(style, b, hd, vd, vertical, aspect) {
2478
+ const h = vertical ? 1 / aspect : aspect;
2479
+ if (vertical) [hd, vd] = [vd, hd];
2480
+ let g = restGrid();
2481
+ switch (style) {
2482
+ case "arc":
2483
+ g = arcGrid(b, h);
2484
+ break;
2485
+ case "arch":
2486
+ g = [0, 1, 2, 3].map((j) => edgeArc(j / 3, b, true, h));
2487
+ break;
2488
+ case "bulge":
2489
+ g = blendRows(edgeArc(0, b, true, h), edgeArc(1, b, false, h));
2490
+ break;
2491
+ case "arcLower":
2492
+ g = blendRows(g[0], edgeArc(1, b, false, h));
2493
+ break;
2494
+ case "arcUpper":
2495
+ g = blendRows(edgeArc(0, b, true, h), g[3]);
2496
+ break;
2497
+ // The bulging edge and the outer points of the row next to it come from Arc (bent the other
2498
+ // way for Shell Lower); the rest stays put.
2499
+ case "shellLower": {
2500
+ const a = arcGrid(-b, h);
2501
+ g[3] = a[3];
2502
+ g[2][0] = a[2][0];
2503
+ g[2][3] = a[2][3];
2504
+ break;
2505
+ }
2506
+ case "shellUpper": {
2507
+ const a = arcGrid(b, h);
2508
+ g[0] = a[0];
2509
+ g[1][0] = a[1][0];
2510
+ g[1][3] = a[1][3];
2511
+ break;
2512
+ }
2513
+ case "flag":
2514
+ for (const row of g) {
2515
+ row[1][1] -= 2 * b;
2516
+ row[2][1] += 2 * b;
2517
+ }
2518
+ break;
2519
+ case "wave":
2520
+ for (const row of g.slice(1, 3)) {
2521
+ row[1][1] += 4 / 3 * b;
2522
+ row[2][1] -= 4 / 3 * b;
2523
+ }
2524
+ break;
2525
+ case "fish":
2526
+ [-2, -2 / 3, 2 / 3, 2].forEach((f, j) => {
2527
+ g[j][1][1] += f * b;
2528
+ g[j][2][1] -= f * b;
2529
+ });
2530
+ break;
2531
+ case "rise":
2532
+ for (const row of g) {
2533
+ row[0][1] += 2 * b;
2534
+ row[1][1] += 2 * b;
2535
+ }
2536
+ break;
2537
+ case "fisheye":
2538
+ for (const [j, i, dx, dy] of INNER) {
2539
+ g[j][i][0] += dx * 2 * b / 3;
2540
+ g[j][i][1] += dy * 2 * b / 3;
2541
+ }
2542
+ break;
2543
+ // Edge midpoints move out (Inflate) or the sides in (Squeeze) by b/3, the inner points by b/9.
2544
+ case "inflate":
2545
+ case "squeeze": {
2546
+ const s = style === "inflate" ? 1 : -1;
2547
+ for (const p of g[0].slice(1, 3)) p[1] -= b / 3;
2548
+ for (const p of g[3].slice(1, 3)) p[1] += b / 3;
2549
+ for (const row of g.slice(1, 3)) {
2550
+ row[0][0] -= s * b / 3;
2551
+ row[3][0] += s * b / 3;
2552
+ }
2553
+ for (const [j, i, dx, dy] of INNER) {
2554
+ g[j][i][0] += s * dx * b / 9;
2555
+ g[j][i][1] += dy * b / 9;
2556
+ }
2557
+ break;
2558
+ }
2559
+ // The inner points turn round the centre (the other way for a negative bend).
2560
+ case "twist": {
2561
+ const a = Math.abs(b);
2562
+ if (b >= 0) {
2563
+ g[1][1][0] += a;
2564
+ g[1][2][1] += a;
2565
+ g[2][1][1] -= a;
2566
+ g[2][2][0] -= a;
2567
+ } else {
2568
+ g[1][1][1] += a;
2569
+ g[1][2][0] -= a;
2570
+ g[2][1][0] += a;
2571
+ g[2][2][1] -= a;
2572
+ }
2573
+ break;
2574
+ }
2575
+ }
2576
+ if (vd !== 0) {
2577
+ const moved = (row, s) => {
2578
+ const m = [(row[0][0] + row[3][0]) / 2, (row[0][1] + row[3][1]) / 2];
2579
+ return row.map((p) => [m[0] + (p[0] - m[0]) * s - p[0], m[1] + (p[1] - m[1]) * s - p[1]]);
2580
+ };
2581
+ const d0 = moved(g[0], 1 - vd);
2582
+ const d3 = moved(g[3], 1 + vd);
2583
+ g.forEach((row, j) => {
2584
+ const t = j / 3;
2585
+ row.forEach((p, i) => {
2586
+ p[0] += d0[i][0] + (d3[i][0] - d0[i][0]) * t;
2587
+ p[1] += d0[i][1] + (d3[i][1] - d0[i][1]) * t;
2588
+ });
2589
+ });
2590
+ }
2591
+ if (hd !== 0) {
2592
+ for (let i = 0; i < 4; i++) {
2593
+ const s = 1 + hd * (2 * i / 3 - 1);
2594
+ const m = [(g[0][i][0] + g[3][i][0]) / 2, (g[0][i][1] + g[3][i][1]) / 2];
2595
+ for (const row of g) row[i] = [m[0] + (row[i][0] - m[0]) * s, m[1] + (row[i][1] - m[1]) * s];
2596
+ }
2597
+ }
2598
+ if (vertical) g = [0, 1, 2, 3].map((j) => [0, 1, 2, 3].map((i) => [g[i][j][1], g[i][j][0]]));
2599
+ return g;
2600
+ }
2601
+ function bernstein(t) {
2602
+ const s = 1 - t;
2603
+ return [s * s * s, 3 * s * s * t, 3 * s * t * t, t * t * t];
2604
+ }
2605
+ var lerp3 = (a, b, t) => ({ x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t });
2606
+ function splitCubic(p, t) {
2607
+ const a = lerp3(p[0], p[1], t);
2608
+ const b = lerp3(p[1], p[2], t);
2609
+ const c = lerp3(p[2], p[3], t);
2610
+ const d = lerp3(a, b, t);
2611
+ const e = lerp3(b, c, t);
2612
+ return [p[0], a, d, lerp3(d, e, t), e, c, p[3]];
2613
+ }
2614
+ var BERN_INV = [
2615
+ [1, 0, 0, 0],
2616
+ [-5 / 6, 3, -1.5, 1 / 3],
2617
+ [1 / 3, -1.5, 3, -5 / 6],
2618
+ [0, 0, 0, 1]
2619
+ ];
2620
+ var pct = (v2) => typeof v2 === "number" && Number.isFinite(v2) ? Math.min(1, Math.max(-1, v2 / 100)) : 0;
2621
+ function vectorWarpPresetMesh(preset, bounds) {
2622
+ if (!VECTOR_WARP_STYLES.includes(preset.style)) return null;
2623
+ const { x, y, width: w, height: h } = bounds;
2624
+ if (!(w > 0 && h > 0)) return null;
2625
+ const b = pct(preset.bend);
2626
+ const hd = pct(preset.horizontal);
2627
+ const vd = pct(preset.vertical);
2628
+ if (b === 0 && hd === 0 && vd === 0) return null;
2629
+ const grid = vectorWarpPresetGrid(preset.style, b, hd, vd, preset.orientation === "vertical", h / w);
2630
+ return { us: [0, 1], vs: [0, 1], points: grid.flat().map((p) => ({ x: x + p[0] * w, y: y + p[1] * h })) };
2631
+ }
2632
+ var vectorMeshColumns = (m) => 3 * (m.us.length - 1) + 1;
2633
+ var vectorMeshRows = (m) => 3 * (m.vs.length - 1) + 1;
2634
+ function isValidVectorMesh(m) {
2635
+ if (!m || typeof m !== "object") return false;
2636
+ const { us, vs, points } = m;
2637
+ const knots = (k) => Array.isArray(k) && k.length >= 2 && k.length <= 65 && k[0] === 0 && k[k.length - 1] === 1 && k.every((v2, i) => typeof v2 === "number" && (i === 0 || v2 > k[i - 1]));
2638
+ if (!knots(us) || !knots(vs) || !Array.isArray(points)) return false;
2639
+ return points.length === (3 * (us.length - 1) + 1) * (3 * (vs.length - 1) + 1) && points.every((p) => !!p && Number.isFinite(p.x) && Number.isFinite(p.y));
2640
+ }
2641
+ function fitVectorMesh(f, us, vs) {
2642
+ const pc = us.length - 1;
2643
+ const pr = vs.length - 1;
2644
+ const nx = 3 * pc + 1;
2645
+ const points = new Array((3 * pr + 1) * nx);
2646
+ for (let pj = 0; pj < pr; pj++) {
2647
+ for (let pi = 0; pi < pc; pi++) {
2648
+ const s = [0, 1, 2, 3].map(
2649
+ (j) => [0, 1, 2, 3].map((i) => f(us[pi] + (us[pi + 1] - us[pi]) * i / 3, vs[pj] + (vs[pj + 1] - vs[pj]) * j / 3))
2650
+ );
2651
+ for (let j = 0; j < 4; j++) {
2652
+ for (let i = 0; i < 4; i++) {
2653
+ let x = 0;
2654
+ let y = 0;
2655
+ for (let a = 0; a < 4; a++) {
2656
+ for (let b = 0; b < 4; b++) {
2657
+ const k = BERN_INV[j][a] * BERN_INV[i][b];
2658
+ x += k * s[a][b].x;
2659
+ y += k * s[a][b].y;
2660
+ }
2661
+ }
2662
+ points[(3 * pj + j) * nx + 3 * pi + i] = { x, y };
2663
+ }
2664
+ }
2665
+ }
2666
+ }
2667
+ return { us: us.slice(), vs: vs.slice(), points };
2668
+ }
2669
+ var evenKnots = (n) => Array.from({ length: n + 1 }, (_, i) => i / n);
2670
+ var clampCount = (n) => Math.min(64, Math.max(1, Math.round(Number.isFinite(n) ? n : 1)));
2671
+ function vectorIdentityMesh(bounds, columns = 1, rows = 1) {
2672
+ return fitVectorMesh((s, t) => ({ x: bounds.x + s * bounds.width, y: bounds.y + t * bounds.height }), evenKnots(clampCount(columns)), evenKnots(clampCount(rows)));
2673
+ }
2674
+ function locate(knots, s) {
2675
+ const n = knots.length - 1;
2676
+ let i = 0;
2677
+ while (i + 1 < n && s > knots[i + 1]) i++;
2678
+ const w = knots[i + 1] - knots[i];
2679
+ return [i, w > 0 ? (s - knots[i]) / w : 0];
2680
+ }
2681
+ function evalVectorMesh(m, s, t) {
2682
+ const [pi, a] = locate(m.us, s);
2683
+ const [pj, b] = locate(m.vs, t);
2684
+ const ba = bernstein(a);
2685
+ const bb = bernstein(b);
2686
+ const nx = vectorMeshColumns(m);
2687
+ let x = 0;
2688
+ let y = 0;
2689
+ for (let j = 0; j < 4; j++) {
2690
+ for (let i = 0; i < 4; i++) {
2691
+ const p = m.points[(3 * pj + j) * nx + 3 * pi + i];
2692
+ const k = ba[i] * bb[j];
2693
+ x += p.x * k;
2694
+ y += p.y * k;
2695
+ }
2696
+ }
2697
+ return { x, y };
2698
+ }
2699
+ function transposeMesh(m) {
2700
+ const nx = vectorMeshColumns(m);
2701
+ const ny = vectorMeshRows(m);
2702
+ const points = new Array(nx * ny);
2703
+ for (let j = 0; j < ny; j++) for (let i = 0; i < nx; i++) points[i * ny + j] = m.points[j * nx + i];
2704
+ return { us: m.vs.slice(), vs: m.us.slice(), points };
2705
+ }
2706
+ function splitVectorMeshU(m, s) {
2707
+ const [pi, a] = locate(m.us, s);
2708
+ if (!(a >= 0.01 && a <= 0.99)) return null;
2709
+ const nx = vectorMeshColumns(m);
2710
+ const ny = vectorMeshRows(m);
2711
+ const points = [];
2712
+ for (let j = 0; j < ny; j++) {
2713
+ const row = m.points.slice(j * nx, (j + 1) * nx);
2714
+ points.push(...row.slice(0, 3 * pi), ...splitCubic(row.slice(3 * pi, 3 * pi + 4), a), ...row.slice(3 * pi + 4));
2715
+ }
2716
+ const us = m.us.slice();
2717
+ us.splice(pi + 1, 0, Math.min(1, Math.max(0, s)));
2718
+ return { us, vs: m.vs.slice(), points };
2719
+ }
2720
+ function splitVectorMeshV(m, t) {
2721
+ const out = splitVectorMeshU(transposeMesh(m), t);
2722
+ return out && transposeMesh(out);
2723
+ }
2724
+ function removeVectorMeshSplitU(m, k) {
2725
+ if (k <= 0 || k + 1 >= m.us.length) return null;
2726
+ const a = (m.us[k] - m.us[k - 1]) / (m.us[k + 1] - m.us[k - 1]);
2727
+ const nx = vectorMeshColumns(m);
2728
+ const ny = vectorMeshRows(m);
2729
+ const c0 = 3 * (k - 1);
2730
+ const points = [];
2731
+ for (let j = 0; j < ny; j++) {
2732
+ const row = m.points.slice(j * nx, (j + 1) * nx);
2733
+ const [p0, q1, r2, p3] = [row[c0], row[c0 + 1], row[c0 + 5], row[c0 + 6]];
2734
+ const p1 = { x: (q1.x - (1 - a) * p0.x) / a, y: (q1.y - (1 - a) * p0.y) / a };
2735
+ const p2 = { x: (r2.x - a * p3.x) / (1 - a), y: (r2.y - a * p3.y) / (1 - a) };
2736
+ points.push(...row.slice(0, c0), p0, p1, p2, p3, ...row.slice(c0 + 7));
2737
+ }
2738
+ const us = m.us.slice();
2739
+ us.splice(k, 1);
2740
+ return { us, vs: m.vs.slice(), points };
2741
+ }
2742
+ function removeVectorMeshSplitV(m, k) {
2743
+ const out = removeVectorMeshSplitU(transposeMesh(m), k);
2744
+ return out && transposeMesh(out);
2745
+ }
2746
+ function mapVectorMeshPoints(m, f) {
2747
+ return { us: m.us.slice(), vs: m.vs.slice(), points: m.points.map((p) => f(p)) };
2748
+ }
2749
+ function resizeVectorMesh(m, columns, rows) {
2750
+ const cols = clampCount(columns);
2751
+ const rws = clampCount(rows);
2752
+ if (m.us.length - 1 === cols && m.vs.length - 1 === rws) return m;
2753
+ const us = evenKnots(cols);
2754
+ const vs = evenKnots(rws);
2755
+ const has = (list, v2) => list.some((k) => Math.abs(k - v2) < 1e-12);
2756
+ if (m.us.every((u) => has(us, u)) && m.vs.every((v2) => has(vs, v2))) {
2757
+ let out = m;
2758
+ for (const u of us) if (!has(out.us, u)) out = _nullishCoalesce(splitVectorMeshU(out, u), () => ( out));
2759
+ for (const v2 of vs) if (!has(out.vs, v2)) out = _nullishCoalesce(splitVectorMeshV(out, v2), () => ( out));
2760
+ return out;
2761
+ }
2762
+ return fitVectorMesh((s, t) => evalVectorMesh(m, s, t), us, vs);
2763
+ }
2764
+ function vectorMeshControlBounds(m) {
2765
+ let minX = Infinity;
2766
+ let minY = Infinity;
2767
+ let maxX = -Infinity;
2768
+ let maxY = -Infinity;
2769
+ for (const p of m.points) {
2770
+ minX = Math.min(minX, p.x);
2771
+ minY = Math.min(minY, p.y);
2772
+ maxX = Math.max(maxX, p.x);
2773
+ maxY = Math.max(maxY, p.y);
2774
+ }
2775
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
2776
+ }
2777
+ function vectorMeshParamAt(m, p) {
2778
+ const n = 48;
2779
+ let best = { s: 0.5, t: 0.5, d: Infinity };
2780
+ for (let j = 0; j <= n; j++) {
2781
+ for (let i = 0; i <= n; i++) {
2782
+ const q2 = evalVectorMesh(m, i / n, j / n);
2783
+ const d = (q2.x - p.x) ** 2 + (q2.y - p.y) ** 2;
2784
+ if (d < best.d) best = { s: i / n, t: j / n, d };
2785
+ }
2786
+ }
2787
+ let { s, t } = best;
2788
+ for (let k = 0; k < 12; k++) {
2789
+ const h = 1e-5;
2790
+ const q2 = evalVectorMesh(m, s, t);
2791
+ const qs = evalVectorMesh(m, s + h, t);
2792
+ const qt = evalVectorMesh(m, s, t + h);
2793
+ const a = (qs.x - q2.x) / h;
2794
+ const b = (qt.x - q2.x) / h;
2795
+ const c = (qs.y - q2.y) / h;
2796
+ const d = (qt.y - q2.y) / h;
2797
+ const det = a * d - b * c;
2798
+ if (Math.abs(det) < 1e-12) break;
2799
+ const ex = p.x - q2.x;
2800
+ const ey = p.y - q2.y;
2801
+ s = Math.min(1, Math.max(0, s + (d * ex - b * ey) / det));
2802
+ t = Math.min(1, Math.max(0, t + (a * ey - c * ex) / det));
2803
+ }
2804
+ const q = evalVectorMesh(m, s, t);
2805
+ return { s, t, distance: Math.hypot(q.x - p.x, q.y - p.y) };
2806
+ }
2807
+ function smoothLines(m, i0, i1, j0, j1) {
2808
+ const nx = vectorMeshColumns(m);
2809
+ i1 = Math.min(i1, nx);
2810
+ j1 = Math.min(j1, vectorMeshRows(m));
2811
+ const triples = [];
2812
+ for (let a = 1; a < m.us.length - 1; a++) {
2813
+ if (3 * a >= i0 && 3 * a < i1)
2814
+ for (let j = j0; j < j1; j++) triples.push([j * nx + 3 * a - 1, j * nx + 3 * a, j * nx + 3 * a + 1, m.us[a] - m.us[a - 1], m.us[a + 1] - m.us[a]]);
2815
+ }
2816
+ for (let b = 1; b < m.vs.length - 1; b++) {
2817
+ if (3 * b >= j0 && 3 * b < j1)
2818
+ for (let i = i0; i < i1; i++) triples.push([(3 * b - 1) * nx + i, 3 * b * nx + i, (3 * b + 1) * nx + i, m.vs[b] - m.vs[b - 1], m.vs[b + 1] - m.vs[b]]);
2819
+ }
2820
+ for (const [l, c, r, hl, hr] of triples) {
2821
+ const pl = m.points[l];
2822
+ const pc = m.points[c];
2823
+ const pr = m.points[r];
2824
+ const tx = ((pc.x - pl.x) / hl + (pr.x - pc.x) / hr) / 2;
2825
+ const ty = ((pc.y - pl.y) / hl + (pr.y - pc.y) / hr) / 2;
2826
+ m.points[l] = { x: pc.x - tx * hl, y: pc.y - ty * hl };
2827
+ m.points[r] = { x: pc.x + tx * hr, y: pc.y + ty * hr };
2828
+ }
2829
+ }
2830
+ function dragVectorMeshPoint(base, index, d) {
2831
+ if (index < 0 || index >= base.points.length || !Number.isFinite(d.x) || !Number.isFinite(d.y)) return base;
2832
+ const out = { us: base.us.slice(), vs: base.vs.slice(), points: base.points.slice() };
2833
+ const nx = vectorMeshColumns(base);
2834
+ const ny = vectorMeshRows(base);
2835
+ const i = index % nx;
2836
+ const j = Math.floor(index / nx);
2837
+ const shift = (ii, jj, v2) => {
2838
+ if (ii < 0 || jj < 0 || ii >= nx || jj >= ny) return;
2839
+ const p = out.points[jj * nx + ii];
2840
+ out.points[jj * nx + ii] = { x: p.x + v2.x, y: p.y + v2.y };
2841
+ };
2842
+ const span = (knots, k) => k > 0 && k + 1 < knots.length ? [knots[k] - knots[k - 1], knots[k + 1] - knots[k]] : null;
2843
+ const ri = i % 3;
2844
+ const rj = j % 3;
2845
+ if (ri === 0 && rj === 0) {
2846
+ for (let dj = -1; dj <= 1; dj++) for (let di = -1; di <= 1; di++) shift(i + di, j + dj, d);
2847
+ } else if (ri === 0) {
2848
+ for (let di = -1; di <= 1; di++) shift(i + di, j, d);
2849
+ const sp = span(base.vs, Math.floor(j / 3) + (rj === 2 ? 1 : 0));
2850
+ if (sp) {
2851
+ const [other, k] = rj === 1 ? [j - 2, sp[0] / sp[1]] : [j + 2, sp[1] / sp[0]];
2852
+ for (let di = -1; di <= 1; di++) shift(i + di, other, { x: -d.x * k, y: -d.y * k });
2853
+ }
2854
+ } else if (rj === 0) {
2855
+ for (let dj = -1; dj <= 1; dj++) shift(i, j + dj, d);
2856
+ const sp = span(base.us, Math.floor(i / 3) + (ri === 2 ? 1 : 0));
2857
+ if (sp) {
2858
+ const [other, k] = ri === 1 ? [i - 2, sp[0] / sp[1]] : [i + 2, sp[1] / sp[0]];
2859
+ for (let dj = -1; dj <= 1; dj++) shift(other, j + dj, { x: -d.x * k, y: -d.y * k });
2860
+ }
2861
+ } else shift(i, j, d);
2862
+ return out;
2863
+ }
2864
+ function pullVectorMesh(base, s, t, d) {
2865
+ const BORDER_ZONE = 0.12;
2866
+ const REACH = 1.8;
2867
+ if (!Number.isFinite(d.x) || !Number.isFinite(d.y)) return base;
2868
+ const m = { us: base.us.slice(), vs: base.vs.slice(), points: base.points.slice() };
2869
+ const cols = m.us.length - 1;
2870
+ const rows = m.vs.length - 1;
2871
+ const [pi, a] = locate(m.us, s);
2872
+ const [pj, b] = locate(m.vs, t);
2873
+ const ba = bernstein(a);
2874
+ const bb = bernstein(b);
2875
+ const nx = vectorMeshColumns(m);
2876
+ const ny = vectorMeshRows(m);
2877
+ const anchor = (ai, aj) => _nullishCoalesce(base.points[3 * aj * nx + 3 * ai], () => ( { x: 0, y: 0 }));
2878
+ const at0 = evalVectorMesh(base, s, t);
2879
+ const target = { x: at0.x + d.x, y: at0.y + d.y };
2880
+ let size = 1;
2881
+ for (const k of ["x", "y"]) {
2882
+ const vals = [anchor(pi, pj)[k], anchor(pi + 1, pj)[k], anchor(pi, pj + 1)[k], anchor(pi + 1, pj + 1)[k]];
2883
+ size = Math.max(size, Math.max(...vals) - Math.min(...vals));
2884
+ }
2885
+ const radius = REACH * size;
2886
+ const innerW = (ba[1] + ba[2]) * (bb[1] + bb[2]);
2887
+ const interior = Math.min(1, Math.max(0, innerW / 0.5625));
2888
+ const toBorder = Math.min(s, 1 - s, t, 1 - t);
2889
+ const nearBorder = Math.min(1, Math.max(0, 1 - toBorder / BORDER_ZONE));
2890
+ const meshCorner = (ai, aj) => (ai === 0 || ai === cols) && (aj === 0 || aj === rows);
2891
+ const onBorder = (ai, aj) => ai === 0 || ai === cols || aj === 0 || aj === rows;
2892
+ const reach = (ai, aj, wa, wb) => meshCorner(ai, aj) ? 0 : wa * wb * (onBorder(ai, aj) ? nearBorder : 1);
2893
+ const corner = [
2894
+ [pi, pj, reach(pi, pj, ba[0] + ba[1], bb[0] + bb[1])],
2895
+ [pi + 1, pj, reach(pi + 1, pj, ba[2] + ba[3], bb[0] + bb[1])],
2896
+ [pi, pj + 1, reach(pi, pj + 1, ba[0] + ba[1], bb[2] + bb[3])],
2897
+ [pi + 1, pj + 1, reach(pi + 1, pj + 1, ba[2] + ba[3], bb[2] + bb[3])]
2898
+ ];
2899
+ const share = new Array((cols + 1) * (rows + 1)).fill(0);
2900
+ for (let aj = 0; aj <= rows; aj++) {
2901
+ for (let ai = 0; ai <= cols; ai++) {
2902
+ const p = anchor(ai, aj);
2903
+ const x = Math.min(1, Math.max(0, Math.hypot(p.x - at0.x, p.y - at0.y) / radius));
2904
+ const fall = 0.5 * (1 + Math.cos(Math.PI * x));
2905
+ const edge = meshCorner(ai, aj) ? 0 : onBorder(ai, aj) ? nearBorder : 1;
2906
+ share[aj * (cols + 1) + ai] = fall * edge;
2907
+ }
2908
+ }
2909
+ for (const [ai, aj, w] of corner) share[aj * (cols + 1) + ai] = Math.max(share[aj * (cols + 1) + ai], (1 - interior) * w);
2910
+ const move = (idx, k, v2) => {
2911
+ const p = m.points[idx];
2912
+ m.points[idx] = { x: p.x + v2.x * k, y: p.y + v2.y * k };
2913
+ };
2914
+ for (let j = 0; j < ny; j++) {
2915
+ for (let i = 0; i < nx; i++) {
2916
+ const ai = Math.min(cols, Math.floor((i + 1) / 3));
2917
+ const aj = Math.min(rows, Math.floor((j + 1) / 3));
2918
+ move(j * nx + i, share[aj * (cols + 1) + ai], d);
2919
+ }
2920
+ }
2921
+ let norm = 0;
2922
+ for (const j of [1, 2]) for (const i of [1, 2]) norm += (ba[i] * bb[j]) ** 2;
2923
+ const cornerNorm = corner.reduce((acc, c) => acc + c[2] * c[2], 0);
2924
+ const innerPart = cornerNorm > 1e-12 ? Math.min(1, innerW / 0.15) : 1;
2925
+ const edgeHandles = [];
2926
+ for (const k of [1, 2]) {
2927
+ if (pi === 0) edgeHandles.push([(3 * pj + k) * nx + 3 * pi, ba[0] * bb[k]]);
2928
+ if (pi + 1 === cols) edgeHandles.push([(3 * pj + k) * nx + 3 * pi + 3, ba[3] * bb[k]]);
2929
+ if (pj === 0) edgeHandles.push([3 * pj * nx + 3 * pi + k, ba[k] * bb[0]]);
2930
+ if (pj + 1 === rows) edgeHandles.push([(3 * pj + 3) * nx + 3 * pi + k, ba[k] * bb[3]]);
2931
+ }
2932
+ const edgeNorm = edgeHandles.reduce((acc, e) => acc + e[1] * e[1], 0);
2933
+ const edgePart = edgeNorm > 1e-12 ? nearBorder : 0;
2934
+ const innerShare = (1 - edgePart) * innerPart;
2935
+ const cornerShare = (1 - edgePart) * (1 - innerPart);
2936
+ for (let iter = 0; iter < 60; iter++) {
2937
+ const now = evalVectorMesh(m, s, t);
2938
+ const rem = { x: target.x - now.x, y: target.y - now.y };
2939
+ if (Math.hypot(rem.x, rem.y) < 1e-9) break;
2940
+ if (innerShare > 0 && norm > 0) for (const j of [1, 2]) for (const i of [1, 2]) move((3 * pj + j) * nx + 3 * pi + i, ba[i] * bb[j] / norm * innerShare, rem);
2941
+ if (edgePart > 0) for (const [idx, w] of edgeHandles) move(idx, w / edgeNorm * edgePart, rem);
2942
+ if (cornerShare > 0 && cornerNorm > 0) {
2943
+ for (const [ai, aj, w] of corner) {
2944
+ const k = w / cornerNorm * cornerShare;
2945
+ for (let dj = -1; dj <= 1; dj++) {
2946
+ for (let di = -1; di <= 1; di++) {
2947
+ const i = 3 * ai + di;
2948
+ const j = 3 * aj + dj;
2949
+ if (i >= 0 && j >= 0 && i < nx && j < ny) move(j * nx + i, k, rem);
2950
+ }
2951
+ }
2952
+ }
2953
+ }
2954
+ for (let k = 0; k < 3; k++) smoothLines(m, Math.max(0, 3 * pi - 3), 3 * pi + 7, Math.max(0, 3 * pj - 3), 3 * pj + 7);
2955
+ }
2956
+ return m;
2957
+ }
2958
+ function polylineAt(pts) {
2959
+ const acc = [0];
2960
+ for (let i = 1; i < pts.length; i++) acc.push(acc[i - 1] + Math.hypot(pts[i].x - pts[i - 1].x, pts[i].y - pts[i - 1].y));
2961
+ const total = acc[acc.length - 1];
2962
+ return (u) => {
2963
+ if (!(total > 0)) return pts[0];
2964
+ const L = Math.min(1, Math.max(0, u)) * total;
2965
+ let i = 1;
2966
+ while (i < acc.length - 1 && acc[i] < L) i++;
2967
+ const seg = acc[i] - acc[i - 1];
2968
+ return lerp3(pts[i - 1], pts[i], seg > 0 ? (L - acc[i - 1]) / seg : 0);
2969
+ };
2970
+ }
2971
+ function sampleSubpath(sp, per = 24) {
2972
+ const n = sp.anchors.length;
2973
+ const out = [];
2974
+ for (let i = 0; i < n; i++) {
2975
+ const a = sp.anchors[i];
2976
+ const b = sp.anchors[(i + 1) % n];
2977
+ const c = [{ x: a.x, y: a.y }, _nullishCoalesce(a.out, () => ( a)), _nullishCoalesce(b.in, () => ( b)), { x: b.x, y: b.y }];
2978
+ for (let k = 0; k < per; k++) {
2979
+ const t = k / per;
2980
+ const ab = lerp3(c[0], c[1], t);
2981
+ const bc = lerp3(c[1], c[2], t);
2982
+ const cd = lerp3(c[2], c[3], t);
2983
+ out.push(lerp3(lerp3(ab, bc, t), lerp3(bc, cd, t), t));
2984
+ }
2985
+ }
2986
+ return out;
2987
+ }
2988
+ function vectorMeshFromOutline(sp, columns = 4, rows = 4) {
2989
+ if (!sp.closed || sp.anchors.length < 2) return null;
2990
+ let ring = sampleSubpath(sp);
2991
+ const xs = ring.map((p) => p.x);
2992
+ const ys = ring.map((p) => p.y);
2993
+ const box = { x0: Math.min(...xs), y0: Math.min(...ys), x1: Math.max(...xs), y1: Math.max(...ys) };
2994
+ if (!(box.x1 - box.x0 > 1e-9 && box.y1 - box.y0 > 1e-9)) return null;
2995
+ const nearest = (c2) => {
2996
+ let best = 0;
2997
+ for (let i = 1; i < ring.length; i++) if (Math.hypot(ring[i].x - c2.x, ring[i].y - c2.y) < Math.hypot(ring[best].x - c2.x, ring[best].y - c2.y)) best = i;
2998
+ return best;
2999
+ };
3000
+ const cornersOf = () => [
3001
+ { x: box.x0, y: box.y0 },
3002
+ { x: box.x1, y: box.y0 },
3003
+ { x: box.x1, y: box.y1 },
3004
+ { x: box.x0, y: box.y1 }
3005
+ ].map(nearest);
3006
+ let c = cornersOf();
3007
+ const n = ring.length;
3008
+ const fwd = (from, to) => (to - from + n) % n;
3009
+ if (!(fwd(c[0], c[1]) < fwd(c[0], c[2]) && fwd(c[0], c[2]) < fwd(c[0], c[3]))) {
3010
+ ring = ring.slice().reverse();
3011
+ c = cornersOf();
3012
+ if (!(fwd(c[0], c[1]) < fwd(c[0], c[2]) && fwd(c[0], c[2]) < fwd(c[0], c[3]))) return null;
3013
+ }
3014
+ if (new Set(c).size < 4) return null;
3015
+ const walk = (from, to) => {
3016
+ const out = [];
3017
+ for (let i = from; ; i = (i + 1) % n) {
3018
+ out.push(ring[i]);
3019
+ if (i === to) break;
3020
+ }
3021
+ return out;
3022
+ };
3023
+ const top = polylineAt(walk(c[0], c[1]));
3024
+ const right = polylineAt(walk(c[1], c[2]));
3025
+ const bottomLR = polylineAt(walk(c[2], c[3]).reverse());
3026
+ const leftTB = polylineAt(walk(c[3], c[0]).reverse());
3027
+ const p00 = top(0);
3028
+ const p10 = top(1);
3029
+ const p01 = bottomLR(0);
3030
+ const p11 = bottomLR(1);
3031
+ const coons = (s, t) => {
3032
+ const T = top(s);
3033
+ const B = bottomLR(s);
3034
+ const L = leftTB(t);
3035
+ const R = right(t);
3036
+ return {
3037
+ x: (1 - t) * T.x + t * B.x + (1 - s) * L.x + s * R.x - ((1 - s) * (1 - t) * p00.x + s * (1 - t) * p10.x + (1 - s) * t * p01.x + s * t * p11.x),
3038
+ y: (1 - t) * T.y + t * B.y + (1 - s) * L.y + s * R.y - ((1 - s) * (1 - t) * p00.y + s * (1 - t) * p10.y + (1 - s) * t * p01.y + s * t * p11.y)
3039
+ };
3040
+ };
3041
+ return fitVectorMesh(coons, evenKnots(clampCount(columns)), evenKnots(clampCount(rows)));
3042
+ }
3043
+ function vectorMeshOutline(m) {
3044
+ const nx = vectorMeshColumns(m);
3045
+ const ny = vectorMeshRows(m);
3046
+ const pt2 = (i, j) => m.points[j * nx + i];
3047
+ const runs = [];
3048
+ for (let i = 0; i + 3 < nx; i += 3) runs.push([pt2(i, 0), pt2(i + 1, 0), pt2(i + 2, 0), pt2(i + 3, 0)]);
3049
+ for (let j = 0; j + 3 < ny; j += 3) runs.push([pt2(nx - 1, j), pt2(nx - 1, j + 1), pt2(nx - 1, j + 2), pt2(nx - 1, j + 3)]);
3050
+ for (let i = nx - 1; i - 3 >= 0; i -= 3) runs.push([pt2(i, ny - 1), pt2(i - 1, ny - 1), pt2(i - 2, ny - 1), pt2(i - 3, ny - 1)]);
3051
+ for (let j = ny - 1; j - 3 >= 0; j -= 3) runs.push([pt2(0, j), pt2(0, j - 1), pt2(0, j - 2), pt2(0, j - 3)]);
3052
+ const anchors = runs.map((r, k) => {
3053
+ const prev = runs[(k + runs.length - 1) % runs.length];
3054
+ return { x: r[0].x, y: r[0].y, in: { ...prev[2] }, out: { ...r[1] } };
3055
+ });
3056
+ return { closed: true, anchors };
3057
+ }
3058
+ function vectorMeshEditPoints(m) {
3059
+ const nx = vectorMeshColumns(m);
3060
+ const ny = vectorMeshRows(m);
3061
+ const anchors = [];
3062
+ const handles = [];
3063
+ for (let j = 0; j < ny; j++) {
3064
+ for (let i = 0; i < nx; i++) {
3065
+ const ri = i % 3;
3066
+ const rj = j % 3;
3067
+ if (ri === 0 && rj === 0) anchors.push(j * nx + i);
3068
+ else if (ri === 0) handles.push({ index: j * nx + i, anchor: (rj === 1 ? j - 1 : j + 1) * nx + i });
3069
+ else if (rj === 0) handles.push({ index: j * nx + i, anchor: j * nx + (ri === 1 ? i - 1 : i + 1) });
3070
+ }
3071
+ }
3072
+ return { anchors, handles };
3073
+ }
3074
+ function vectorMeshGridCurves(m) {
3075
+ const nx = vectorMeshColumns(m);
3076
+ const ny = vectorMeshRows(m);
3077
+ const pt2 = (i, j) => m.points[j * nx + i];
3078
+ const out = [];
3079
+ for (let j = 0; j < ny; j += 3) for (let i = 0; i + 3 < nx; i += 3) out.push([pt2(i, j), pt2(i + 1, j), pt2(i + 2, j), pt2(i + 3, j)]);
3080
+ for (let i = 0; i < nx; i += 3) for (let j = 0; j + 3 < ny; j += 3) out.push([pt2(i, j), pt2(i, j + 1), pt2(i, j + 2), pt2(i, j + 3)]);
3081
+ return out;
3082
+ }
3083
+
2234
3084
  // src/vector/appearance.ts
2235
3085
  var VECTOR_EFFECT_DEFAULTS = {
2236
3086
  trim: { start: 0, end: 50, offset: 0, mode: "simultaneous" },
@@ -2251,7 +3101,8 @@ var VECTOR_EFFECT_DEFAULTS = {
2251
3101
  startOpacity: 100,
2252
3102
  endOpacity: 100,
2253
3103
  composite: "below"
2254
- }
3104
+ },
3105
+ envelope: { style: "arc", bend: 50, horizontal: 0, vertical: 0, orientation: "horizontal", rows: 2, columns: 2, mesh: null }
2255
3106
  };
2256
3107
  var VECTOR_EFFECT_LABELS = {
2257
3108
  trim: "Trim Paths",
@@ -2262,7 +3113,8 @@ var VECTOR_EFFECT_LABELS = {
2262
3113
  wiggle: "Wiggle Paths",
2263
3114
  offset: "Offset Paths",
2264
3115
  merge: "Merge Paths",
2265
- repeater: "Repeater"
3116
+ repeater: "Repeater",
3117
+ envelope: "Envelope"
2266
3118
  };
2267
3119
  var VECTOR_EFFECT_PARAM_SPECS = {
2268
3120
  trim: [
@@ -2348,8 +3200,65 @@ var VECTOR_EFFECT_PARAM_SPECS = {
2348
3200
  { value: "above", label: "Above" }
2349
3201
  ]
2350
3202
  }
3203
+ ],
3204
+ envelope: [
3205
+ {
3206
+ key: "style",
3207
+ label: "Warp",
3208
+ kind: "select",
3209
+ options: [...VECTOR_WARP_STYLES.map((value) => ({ value, label: VECTOR_WARP_STYLE_LABELS[value] })), { value: "mesh", label: "Mesh" }]
3210
+ },
3211
+ { key: "bend", label: "Bend %", kind: "number", min: -100, max: 100, step: 1, slider: true },
3212
+ { key: "horizontal", label: "Horizontal distortion %", kind: "number", min: -100, max: 100, step: 1, slider: true },
3213
+ { key: "vertical", label: "Vertical distortion %", kind: "number", min: -100, max: 100, step: 1, slider: true },
3214
+ {
3215
+ key: "orientation",
3216
+ label: "Orientation",
3217
+ kind: "select",
3218
+ options: [
3219
+ { value: "horizontal", label: "Horizontal" },
3220
+ { value: "vertical", label: "Vertical" }
3221
+ ]
3222
+ },
3223
+ { key: "rows", label: "Mesh rows", kind: "number", min: 1, max: 16, step: 1 },
3224
+ { key: "columns", label: "Mesh columns", kind: "number", min: 1, max: 16, step: 1 }
2351
3225
  ]
2352
3226
  };
3227
+ var cloneMesh = (m) => ({ us: m.us.slice(), vs: m.vs.slice(), points: m.points.map((p) => ({ x: p.x, y: p.y })) });
3228
+ function vectorEnvelopeMesh(params, bounds) {
3229
+ if (params.style === "mesh") return _nullishCoalesce(params.mesh, () => ( vectorIdentityMesh(bounds, params.columns, params.rows)));
3230
+ const preset = vectorWarpPresetMesh({ style: params.style, bend: params.bend, horizontal: params.horizontal, vertical: params.vertical, orientation: params.orientation }, bounds);
3231
+ return preset ? resizeVectorMesh(preset, params.columns, params.rows) : vectorIdentityMesh(bounds, params.columns, params.rows);
3232
+ }
3233
+ function vectorEnvelopeMap(params, bounds) {
3234
+ if (!bounds || !(bounds.width > 0 && bounds.height > 0)) return null;
3235
+ const mesh = params.style === "mesh" ? params.mesh : vectorWarpPresetMesh({ style: params.style, bend: params.bend, horizontal: params.horizontal, vertical: params.vertical, orientation: params.orientation }, bounds);
3236
+ if (!mesh) return null;
3237
+ const { x, y, width, height } = bounds;
3238
+ return (p) => evalVectorMesh(mesh, (p.x - x) / width, (p.y - y) / height);
3239
+ }
3240
+ function pathsBounds(paths) {
3241
+ let minX = Infinity;
3242
+ let minY = Infinity;
3243
+ let maxX = -Infinity;
3244
+ let maxY = -Infinity;
3245
+ for (const p of paths) {
3246
+ const b = _chunkVNYRI265cjs.bezierPathBounds.call(void 0, p);
3247
+ if (!b) continue;
3248
+ minX = Math.min(minX, b.minX);
3249
+ minY = Math.min(minY, b.minY);
3250
+ maxX = Math.max(maxX, b.maxX);
3251
+ maxY = Math.max(maxY, b.maxY);
3252
+ }
3253
+ return minX <= maxX ? { x: minX, y: minY, width: maxX - minX, height: maxY - minY } : null;
3254
+ }
3255
+ function envelopePaths(paths, params) {
3256
+ const bounds = pathsBounds(paths);
3257
+ const f = vectorEnvelopeMap(params, bounds);
3258
+ if (!f || !bounds) return paths;
3259
+ const tol = Math.min(0.25, Math.max(0.01, Math.hypot(bounds.width, bounds.height) / 2e3));
3260
+ return paths.map((p) => p.length ? mapBezierPath(p, f, tol) : p);
3261
+ }
2353
3262
  var isVec2 = (v2) => !!v2 && typeof v2 === "object" && Number.isFinite(v2.x) && Number.isFinite(v2.y);
2354
3263
  function normalizeVectorEffectParams(type, params, base) {
2355
3264
  const defaults = VECTOR_EFFECT_DEFAULTS[type];
@@ -2363,6 +3272,19 @@ function normalizeVectorEffectParams(type, params, base) {
2363
3272
  else if (spec.kind === "vec2" && isVec2(v2)) out[spec.key] = { x: v2.x, y: v2.y };
2364
3273
  else if (spec.kind === "select" && spec.options.some((o) => o.value === v2)) out[spec.key] = v2;
2365
3274
  }
3275
+ if (type === "envelope") {
3276
+ const o = out;
3277
+ o.rows = Math.round(o.rows);
3278
+ o.columns = Math.round(o.columns);
3279
+ const given = _optionalChain([params, 'optionalAccess', _52 => _52.mesh]);
3280
+ let mesh = given !== void 0 ? isValidVectorMesh(given) ? cloneMesh(given) : null : o.mesh;
3281
+ if (o.style !== "mesh") mesh = null;
3282
+ if (mesh && given !== void 0) {
3283
+ o.columns = mesh.us.length - 1;
3284
+ o.rows = mesh.vs.length - 1;
3285
+ } else if (mesh) mesh = resizeVectorMesh(mesh, o.columns, o.rows);
3286
+ o.mesh = mesh;
3287
+ }
2366
3288
  return out;
2367
3289
  }
2368
3290
  function createVectorEffect(type, id, params) {
@@ -2371,10 +3293,10 @@ function createVectorEffect(type, id, params) {
2371
3293
  }
2372
3294
  var isEnabled = (e) => e.enabled !== false && !!VECTOR_EFFECT_DEFAULTS[e.type];
2373
3295
  function activeVectorEffects(node) {
2374
- return _nullishCoalesce(_optionalChain([node, 'access', _52 => _52.effects, 'optionalAccess', _53 => _53.filter, 'call', _54 => _54(isEnabled)]), () => ( []));
3296
+ return _nullishCoalesce(_optionalChain([node, 'access', _53 => _53.effects, 'optionalAccess', _54 => _54.filter, 'call', _55 => _55(isEnabled)]), () => ( []));
2375
3297
  }
2376
3298
  function hasOwnVectorAppearance(node) {
2377
- return node.type === "group" && !!node.liveBoolean || !!_optionalChain([node, 'access', _55 => _55.effects, 'optionalAccess', _56 => _56.some, 'call', _57 => _57(isEnabled)]);
3299
+ return node.type === "group" && !!node.liveBoolean || !!_optionalChain([node, 'access', _56 => _56.effects, 'optionalAccess', _57 => _57.some, 'call', _58 => _58(isEnabled)]);
2378
3300
  }
2379
3301
  var liveCache = /* @__PURE__ */ new WeakMap();
2380
3302
  function hasVectorAppearance(node) {
@@ -2386,7 +3308,7 @@ function hasVectorAppearance(node) {
2386
3308
  return v2;
2387
3309
  }
2388
3310
  function isVectorLiveBoolean(node) {
2389
- return _optionalChain([node, 'optionalAccess', _58 => _58.type]) === "group" && !!node.liveBoolean;
3311
+ return _optionalChain([node, 'optionalAccess', _59 => _59.type]) === "group" && !!node.liveBoolean;
2390
3312
  }
2391
3313
  function vectorOperandOperation(group, child) {
2392
3314
  return _nullishCoalesce(_nullishCoalesce(child.booleanOperation, () => ( group.liveBoolean)), () => ( "union"));
@@ -2503,7 +3425,7 @@ var compareOrder = (a, b) => {
2503
3425
  for (let i = 0; i < n; i++) if (a[i] !== b[i]) return a[i] - b[i];
2504
3426
  return a.length - b.length;
2505
3427
  };
2506
- var add3 = (a, b) => ({ x: a.x + (_nullishCoalesce(_optionalChain([b, 'optionalAccess', _59 => _59.x]), () => ( 0))), y: a.y + (_nullishCoalesce(_optionalChain([b, 'optionalAccess', _60 => _60.y]), () => ( 0))) });
3428
+ var add3 = (a, b) => ({ x: a.x + (_nullishCoalesce(_optionalChain([b, 'optionalAccess', _60 => _60.x]), () => ( 0))), y: a.y + (_nullishCoalesce(_optionalChain([b, 'optionalAccess', _61 => _61.y]), () => ( 0))) });
2507
3429
  var mapPaths = (shapes, fn) => {
2508
3430
  const out = fn(shapes.map((s) => s.path));
2509
3431
  return shapes.map((s, i) => ({ ...s, path: _nullishCoalesce(out[i], () => ( [])) }));
@@ -2543,6 +3465,11 @@ function applyVectorEffects(shapes, effects) {
2543
3465
  list = [{ ...first, path: mergePaths(list.map((s) => s.path), e.params.mode) }];
2544
3466
  break;
2545
3467
  }
3468
+ case "envelope": {
3469
+ const params = e.params;
3470
+ list = mapPaths(list, (p) => envelopePaths(p, params));
3471
+ break;
3472
+ }
2546
3473
  case "repeater": {
2547
3474
  const r = e.params;
2548
3475
  const copies = repeatPaths(
@@ -2589,14 +3516,35 @@ function liveBooleanShapes(group) {
2589
3516
  return [{ source, path: foldVectorBooleanOperands(operands), opacity: 1, order: [0] }];
2590
3517
  }
2591
3518
  var shapeCache = /* @__PURE__ */ new WeakMap();
3519
+ function baseShapes(node) {
3520
+ if (node.type === "path") return [{ source: node, path: subpathsToBezier(node.subpaths), opacity: 1, order: [] }];
3521
+ if (node.liveBoolean) return liveBooleanShapes(node);
3522
+ return node.children.flatMap((c, i) => childShapes(c, i));
3523
+ }
3524
+ function vectorEffectInputPaths(node, effectId) {
3525
+ const list = _nullishCoalesce(node.effects, () => ( []));
3526
+ const i = list.findIndex((e) => e.id === effectId);
3527
+ if (i < 0) return null;
3528
+ return applyVectorEffects(baseShapes(node), list.slice(0, i)).map((s) => s.path);
3529
+ }
3530
+ function vectorEffectInputBounds(node, effectId) {
3531
+ const paths = vectorEffectInputPaths(node, effectId);
3532
+ return paths ? pathsBounds(paths) : null;
3533
+ }
3534
+ function vectorNodeEnvelope(node) {
3535
+ return _nullishCoalesce(_optionalChain([node, 'optionalAccess', _62 => _62.effects, 'optionalAccess', _63 => _63.find, 'call', _64 => _64((e) => e.type === "envelope" && e.enabled !== false)]), () => ( null));
3536
+ }
3537
+ function vectorEnvelopeFrame(node, effectId) {
3538
+ const e = effectId ? _optionalChain([node, 'access', _65 => _65.effects, 'optionalAccess', _66 => _66.find, 'call', _67 => _67((x) => x.id === effectId)]) : vectorNodeEnvelope(node);
3539
+ if (!e || e.type !== "envelope") return null;
3540
+ const bounds = vectorEffectInputBounds(node, e.id);
3541
+ if (!bounds || !(bounds.width > 0 && bounds.height > 0)) return null;
3542
+ return { effectId: e.id, bounds, mesh: vectorEnvelopeMesh(e.params, bounds) };
3543
+ }
2592
3544
  function vectorAppearanceShapes(node) {
2593
3545
  const hit = shapeCache.get(node);
2594
3546
  if (hit) return hit;
2595
- let base;
2596
- if (node.type === "path") base = [{ source: node, path: subpathsToBezier(node.subpaths), opacity: 1, order: [] }];
2597
- else if (node.liveBoolean) base = liveBooleanShapes(node);
2598
- else base = node.children.flatMap((c, i) => childShapes(c, i));
2599
- const out = applyVectorEffects(base, node.effects).sort((a, b) => compareOrder(a.order, b.order));
3547
+ const out = applyVectorEffects(baseShapes(node), node.effects).sort((a, b) => compareOrder(a.order, b.order));
2600
3548
  shapeCache.set(node, out);
2601
3549
  return out;
2602
3550
  }
@@ -2693,10 +3641,19 @@ function sanitizeVectorEffects(value) {
2693
3641
  }
2694
3642
  return out;
2695
3643
  }
2696
- function transformVectorEffects(effects, m) {
3644
+ function transformVectorEffects(effects, m, node) {
2697
3645
  const lin = (v2) => ({ x: m[0] * v2.x + m[2] * v2.y, y: m[1] * v2.x + m[3] * v2.y });
3646
+ const full = (v2) => ({ x: m[0] * v2.x + m[2] * v2.y + m[4], y: m[1] * v2.x + m[3] * v2.y + m[5] });
2698
3647
  const mirror = m[0] * m[3] - m[1] * m[2] < 0 ? -1 : 1;
3648
+ const axisScale = Math.abs(m[1]) < 1e-12 && Math.abs(m[2]) < 1e-12 && m[0] > 0 && m[3] > 0;
2699
3649
  return effects.map((e) => {
3650
+ if (e.type === "envelope") {
3651
+ if (e.params.style === "mesh") return e.params.mesh ? { ...e, params: { ...e.params, mesh: mapVectorMeshPoints(e.params.mesh, full) } } : e;
3652
+ if (axisScale || !node) return e;
3653
+ const bounds = vectorEffectInputBounds(node, e.id);
3654
+ if (!bounds || !vectorEnvelopeMap(e.params, bounds)) return e;
3655
+ return { ...e, params: { ...e.params, style: "mesh", mesh: mapVectorMeshPoints(vectorEnvelopeMesh(e.params, bounds), full) } };
3656
+ }
2700
3657
  if (e.type === "twist") return { ...e, params: { ...e.params, center: lin(e.params.center), angle: e.params.angle * mirror } };
2701
3658
  if (e.type === "repeater")
2702
3659
  return { ...e, params: { ...e.params, position: lin(e.params.position), anchor: lin(e.params.anchor), rotation: e.params.rotation * mirror } };
@@ -2931,7 +3888,7 @@ function boundsFromPoints(a, b) {
2931
3888
  }
2932
3889
  function hitTestVectorNode(node, p, tolerance = 0, parent = IDENTITY_MATRIX, options = {}) {
2933
3890
  if (node.visible === false) return false;
2934
- if (!(node.type === "group" && (!hasOwnVectorAppearance(node) || _optionalChain([options, 'access', _61 => _61.entered, 'optionalAccess', _62 => _62.has, 'call', _63 => _63(node.id)])))) node = expandVectorAppearance(node);
3891
+ if (!(node.type === "group" && (!hasOwnVectorAppearance(node) || _optionalChain([options, 'access', _68 => _68.entered, 'optionalAccess', _69 => _69.has, 'call', _70 => _70(node.id)])))) node = expandVectorAppearance(node);
2935
3892
  if (node.type === "group") {
2936
3893
  const m = multiplyMatrices(nodeMatrix(node), parent);
2937
3894
  return node.children.some((c) => hitTestVectorNode(c, p, tolerance, m, options));
@@ -3030,17 +3987,17 @@ function mapAnchor(a, m) {
3030
3987
  }
3031
3988
  function bakeIntoGeometry(node, m) {
3032
3989
  if (isIdentityMatrix(m)) return node;
3033
- if (_optionalChain([node, 'access', _64 => _64.effects, 'optionalAccess', _65 => _65.length])) node = { ...node, effects: transformVectorEffects(node.effects, m) };
3990
+ if (_optionalChain([node, 'access', _71 => _71.effects, 'optionalAccess', _72 => _72.length])) node = { ...node, effects: transformVectorEffects(node.effects, m, node) };
3034
3991
  if (node.type === "group") {
3035
3992
  const group = node;
3036
3993
  const children = group.children.map((c) => transformVectorNode(c, m));
3037
- const spine = _optionalChain([group, 'access', _66 => _66.blend, 'optionalAccess', _67 => _67.spine]);
3994
+ const spine = _optionalChain([group, 'access', _73 => _73.blend, 'optionalAccess', _74 => _74.spine]);
3038
3995
  if (!spine) return { ...group, children };
3039
3996
  const moved = { closed: spine.closed, anchors: spine.anchors.map((a) => mapAnchor(a, m)) };
3040
3997
  return { ...group, children, blend: { ...group.blend, spine: moved } };
3041
3998
  }
3042
3999
  const path = node;
3043
- const mirrored = m[0] * m[3] - m[1] * m[2] < 0 && _optionalChain([path, 'access', _68 => _68.strokeWidthProfile, 'optionalAccess', _69 => _69.length]);
4000
+ const mirrored = m[0] * m[3] - m[1] * m[2] < 0 && _optionalChain([path, 'access', _75 => _75.strokeWidthProfile, 'optionalAccess', _76 => _76.length]);
3044
4001
  return {
3045
4002
  ...path,
3046
4003
  ...mirrored ? { strokeWidthProfile: mirrorWidthProfile(path.strokeWidthProfile) } : {},
@@ -3414,7 +4371,7 @@ function applyVectorCornersAttribute(subpaths, value) {
3414
4371
  for (const item of value.trim().split(/\s+/)) {
3415
4372
  const m = /^(\d+)\.(\d+):([\d.eE+-]+)(?::([a-z]+))?$/.exec(item);
3416
4373
  if (!m) continue;
3417
- const a = _optionalChain([subpaths, 'access', _70 => _70[+m[1]], 'optionalAccess', _71 => _71.anchors, 'access', _72 => _72[+m[2]]]);
4374
+ const a = _optionalChain([subpaths, 'access', _77 => _77[+m[1]], 'optionalAccess', _78 => _78.anchors, 'access', _79 => _79[+m[2]]]);
3418
4375
  const radius = parseFloat(m[3]);
3419
4376
  if (!a || !(radius > 0)) continue;
3420
4377
  const kind = VECTOR_CORNER_KINDS.includes(m[4]) ? m[4] : void 0;
@@ -3436,7 +4393,7 @@ function vectorPaintToSvg(paint, gradientId, options = {}) {
3436
4393
  const precision = _nullishCoalesce(options.precision, () => ( 3));
3437
4394
  const key = `${gradientId}|${role}|${precision}`;
3438
4395
  const owner = _nullishCoalesce(options.node, () => ( paint));
3439
- const cached = _optionalChain([paintCache, 'access', _73 => _73.get, 'call', _74 => _74(owner), 'optionalAccess', _75 => _75.get, 'call', _76 => _76(key)]);
4396
+ const cached = _optionalChain([paintCache, 'access', _80 => _80.get, 'call', _81 => _81(owner), 'optionalAccess', _82 => _82.get, 'call', _83 => _83(key)]);
3440
4397
  if (cached && (!options.node || (role === "fill" ? options.node.fill : options.node.stroke) === paint)) return { value: `url(#${gradientId})`, defs: cached };
3441
4398
  const node = options.node;
3442
4399
  const bounds = node ? vectorPathLocalBounds(node) : null;
@@ -3555,7 +4512,7 @@ function vectorDocumentToSvg(doc, options = {}) {
3555
4512
  if (hasOwnVectorAppearance(node)) {
3556
4513
  const live2 = {
3557
4514
  kind: node.type,
3558
- ..._optionalChain([node, 'access', _77 => _77.effects, 'optionalAccess', _78 => _78.length]) ? { effects: node.effects } : {},
4515
+ ..._optionalChain([node, 'access', _84 => _84.effects, 'optionalAccess', _85 => _85.length]) ? { effects: node.effects } : {},
3559
4516
  ...node.type === "group" && node.liveBoolean ? { liveBoolean: node.liveBoolean } : {}
3560
4517
  };
3561
4518
  lines.push(`${indent(depth)}<g${common(node)} data-vector-live="${escapeAttr(JSON.stringify(live2))}">`);
@@ -3588,7 +4545,7 @@ function vectorDocumentToSvg(doc, options = {}) {
3588
4545
  let out2 = ` stroke="${escapeAttr(stroke.value)}" stroke-width="${num2(width)}"`;
3589
4546
  if (node.strokeLinecap && node.strokeLinecap !== "butt") out2 += ` stroke-linecap="${node.strokeLinecap}"`;
3590
4547
  if (node.strokeLinejoin && node.strokeLinejoin !== "miter") out2 += ` stroke-linejoin="${node.strokeLinejoin}"`;
3591
- if (_optionalChain([node, 'access', _79 => _79.strokeDasharray, 'optionalAccess', _80 => _80.length])) out2 += ` stroke-dasharray="${node.strokeDasharray.map(num2).join(" ")}"`;
4548
+ if (_optionalChain([node, 'access', _86 => _86.strokeDasharray, 'optionalAccess', _87 => _87.length])) out2 += ` stroke-dasharray="${node.strokeDasharray.map(num2).join(" ")}"`;
3592
4549
  return out2;
3593
4550
  };
3594
4551
  const parts = stroke.value !== "none" ? vectorStrokeSvgParts(node, `${prefix}clip-${node.id}`, precision) : void 0;
@@ -3608,7 +4565,7 @@ function vectorDocumentToSvg(doc, options = {}) {
3608
4565
  data += ` data-vector-width-profile="${widthProfileToAttribute(profile)}"`;
3609
4566
  if (node.strokeLinecap && node.strokeLinecap !== "butt") data += ` data-vector-stroke-linecap="${node.strokeLinecap}"`;
3610
4567
  if (node.strokeLinejoin && node.strokeLinejoin !== "miter") data += ` data-vector-stroke-linejoin="${node.strokeLinejoin}"`;
3611
- if (_optionalChain([node, 'access', _81 => _81.strokeDasharray, 'optionalAccess', _82 => _82.length])) data += ` data-vector-stroke-dasharray="${node.strokeDasharray.map(num2).join(" ")}"`;
4568
+ if (_optionalChain([node, 'access', _88 => _88.strokeDasharray, 'optionalAccess', _89 => _89.length])) data += ` data-vector-stroke-dasharray="${node.strokeDasharray.map(num2).join(" ")}"`;
3612
4569
  }
3613
4570
  lines.push(`${indent(depth)}<g${common(node)}${data}>`);
3614
4571
  lines.push(`${indent(depth + 1)}<path data-vector-part="fill" d="${d}"${fillAttrs}${live}/>`);
@@ -3791,9 +4748,9 @@ function resolveGradient(id, raw) {
3791
4748
  for (let el = first; el && !chain.includes(el) && chain.length < 32; ) {
3792
4749
  chain.push(el);
3793
4750
  const href = _nullishCoalesce(el.attrs.href, () => ( el.attrs["xlink:href"]));
3794
- el = _optionalChain([href, 'optionalAccess', _83 => _83.startsWith, 'call', _84 => _84("#")]) ? raw.get(href.slice(1)) : void 0;
4751
+ el = _optionalChain([href, 'optionalAccess', _90 => _90.startsWith, 'call', _91 => _91("#")]) ? raw.get(href.slice(1)) : void 0;
3795
4752
  }
3796
- const attr = (name) => _optionalChain([chain, 'access', _85 => _85.find, 'call', _86 => _86((el) => el.attrs[name] !== void 0), 'optionalAccess', _87 => _87.attrs, 'access', _88 => _88[name]]);
4753
+ const attr = (name) => _optionalChain([chain, 'access', _92 => _92.find, 'call', _93 => _93((el) => el.attrs[name] !== void 0), 'optionalAccess', _94 => _94.attrs, 'access', _95 => _95[name]]);
3797
4754
  const stops = _nullishCoalesce(chain.map(readStops).find((s) => s.length), () => ( []));
3798
4755
  if (!stops.length) return null;
3799
4756
  const user = attr("gradientUnits") === "userSpaceOnUse";
@@ -3835,8 +4792,8 @@ function resolveGradient(id, raw) {
3835
4792
  const len2 = Math.hypot(x2 - x1, y2 - y1);
3836
4793
  const d = len2 > 0 ? { x: (x2 - x1) / len2, y: (y2 - y1) / len2 } : { x: 0, y: 1 };
3837
4794
  const along2 = (x, y) => x * d.x + y * d.y;
3838
- const same = len2 > 0 && Math.abs((c.x2 - c.x1) * d.y - (c.y2 - c.y1) * d.x) < 1e-3 && Math.abs(along2(c.x1, c.y1) - along2(x1, y1)) < 1e-3 && Math.abs(along2(c.x2, c.y2) - along2(x2, y2)) < 1e-3;
3839
- if (same) return { type: "linear", angle, stops, ...spread };
4795
+ const same2 = len2 > 0 && Math.abs((c.x2 - c.x1) * d.y - (c.y2 - c.y1) * d.x) < 1e-3 && Math.abs(along2(c.x1, c.y1) - along2(x1, y1)) < 1e-3 && Math.abs(along2(c.x2, c.y2) - along2(x2, y2)) < 1e-3;
4796
+ if (same2) return { type: "linear", angle, stops, ...spread };
3840
4797
  }
3841
4798
  const start = { x: x1, y: y1 };
3842
4799
  const end = { x: x2, y: y2 };
@@ -3943,7 +4900,7 @@ function parseVectorSvg(svg, options = {}) {
3943
4900
  const part = (name) => g.children.find((c) => c.name === "path" && c.attrs["data-vector-part"] === name);
3944
4901
  const fillEl = part("fill");
3945
4902
  const subpaths = fillEl ? shapeOf(fillEl) : null;
3946
- if (!fillEl || !_optionalChain([subpaths, 'optionalAccess', _89 => _89.length])) return null;
4903
+ if (!fillEl || !_optionalChain([subpaths, 'optionalAccess', _96 => _96.length])) return null;
3947
4904
  const a = g.attrs;
3948
4905
  const fs = readStyle(fillEl, style);
3949
4906
  const strokeEl = part("stroke");
@@ -3980,7 +4937,7 @@ function parseVectorSvg(svg, options = {}) {
3980
4937
  ...profile.length ? { strokeWidthProfile: profile } : {},
3981
4938
  ...keptCap ? { strokeLinecap: keptCap } : {},
3982
4939
  ...keptJoin ? { strokeLinejoin: keptJoin } : {},
3983
- ..._optionalChain([keptDash, 'optionalAccess', _90 => _90.length]) ? { strokeDasharray: keptDash } : {}
4940
+ ..._optionalChain([keptDash, 'optionalAccess', _97 => _97.length]) ? { strokeDasharray: keptDash } : {}
3984
4941
  };
3985
4942
  return placed(node, m);
3986
4943
  };
@@ -4653,7 +5610,7 @@ function interpolateVectorPaint(a, b, t) {
4653
5610
  return t < 0.5 ? a : b;
4654
5611
  }
4655
5612
  function interpolateWidthProfiles(a, b, t) {
4656
- if (!_optionalChain([a, 'optionalAccess', _91 => _91.length]) && !_optionalChain([b, 'optionalAccess', _92 => _92.length])) return null;
5613
+ if (!_optionalChain([a, 'optionalAccess', _98 => _98.length]) && !_optionalChain([b, 'optionalAccess', _99 => _99.length])) return null;
4657
5614
  const at2 = [..._nullishCoalesce(a, () => ( [])), ..._nullishCoalesce(b, () => ( [])), { t: 0 }, { t: 1 }].map((p) => p.t).sort((x, y) => x - y);
4658
5615
  const ts = at2.filter((v2, i) => i === 0 || v2 - at2[i - 1] > 1e-6);
4659
5616
  return ts.map((pos) => {
@@ -4663,7 +5620,7 @@ function interpolateWidthProfiles(a, b, t) {
4663
5620
  });
4664
5621
  }
4665
5622
  function lerpDashes(a, b, t) {
4666
- const dashed = (d) => !!_optionalChain([d, 'optionalAccess', _93 => _93.length]) && d.some((v2) => v2 > 0);
5623
+ const dashed = (d) => !!_optionalChain([d, 'optionalAccess', _100 => _100.length]) && d.some((v2) => v2 > 0);
4667
5624
  if (!dashed(a) && !dashed(b)) return t < 0.5 ? a : b;
4668
5625
  const even = (p) => p.length % 2 ? [...p, ...p] : p;
4669
5626
  const solid = (p) => {
@@ -4690,7 +5647,7 @@ function interpolateVectorStyle(a, b, t) {
4690
5647
  for (const key of ["startArrowScale", "endArrowScale"])
4691
5648
  if (a[key] !== void 0 || b[key] !== void 0) out[key] = lerpN(_nullishCoalesce(a[key], () => ( 1)), _nullishCoalesce(b[key], () => ( 1)), t);
4692
5649
  const dash = lerpDashes(a.strokeDasharray, b.strokeDasharray, t);
4693
- if (_optionalChain([dash, 'optionalAccess', _94 => _94.length])) out.strokeDasharray = dash;
5650
+ if (_optionalChain([dash, 'optionalAccess', _101 => _101.length])) out.strokeDasharray = dash;
4694
5651
  const profile = interpolateWidthProfiles(a.strokeWidthProfile, b.strokeWidthProfile, t);
4695
5652
  if (profile) out.strokeWidthProfile = profile;
4696
5653
  return out;
@@ -4701,7 +5658,7 @@ function reversedStyle(s) {
4701
5658
  out.endArrow = s.startArrow;
4702
5659
  out.startArrowScale = s.endArrowScale;
4703
5660
  out.endArrowScale = s.startArrowScale;
4704
- if (_optionalChain([s, 'access', _95 => _95.strokeWidthProfile, 'optionalAccess', _96 => _96.length])) out.strokeWidthProfile = reverseWidthProfile(s.strokeWidthProfile);
5661
+ if (_optionalChain([s, 'access', _102 => _102.strokeWidthProfile, 'optionalAccess', _103 => _103.length])) out.strokeWidthProfile = reverseWidthProfile(s.strokeWidthProfile);
4705
5662
  for (const k of ["startArrow", "endArrow", "startArrowScale", "endArrowScale"]) if (out[k] === void 0) delete out[k];
4706
5663
  return out;
4707
5664
  }
@@ -4847,11 +5804,11 @@ function vectorBlendKeys(group) {
4847
5804
  }
4848
5805
  function resolveVectorBlendOptions(options) {
4849
5806
  return {
4850
- spacing: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _97 => _97.spacing]), () => ( "steps")),
4851
- steps: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _98 => _98.steps]), () => ( DEFAULT_VECTOR_BLEND_STEPS)),
4852
- distance: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _99 => _99.distance]), () => ( DEFAULT_VECTOR_BLEND_DISTANCE)),
4853
- orientToSpine: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _100 => _100.orientToSpine]), () => ( false)),
4854
- linear: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _101 => _101.linear]), () => ( false))
5807
+ spacing: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _104 => _104.spacing]), () => ( "steps")),
5808
+ steps: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _105 => _105.steps]), () => ( DEFAULT_VECTOR_BLEND_STEPS)),
5809
+ distance: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _106 => _106.distance]), () => ( DEFAULT_VECTOR_BLEND_DISTANCE)),
5810
+ orientToSpine: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _107 => _107.orientToSpine]), () => ( false)),
5811
+ linear: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _108 => _108.linear]), () => ( false))
4855
5812
  };
4856
5813
  }
4857
5814
  function paintColors(p) {
@@ -4893,8 +5850,8 @@ function vectorBlendStepCount(a, b, options, length2) {
4893
5850
  if (cd > 1 / 255) return Math.min(VECTOR_BLEND_MAX_SMOOTH_STEPS, Math.max(1, Math.ceil(cd * 255 / 2)));
4894
5851
  const ba = vectorNodeBounds(a);
4895
5852
  const bb = vectorNodeBounds(b);
4896
- const dist4 = ba && bb ? Math.max(Math.abs(ba.x - bb.x), Math.abs(ba.y - bb.y), Math.abs(ba.x + ba.width - bb.x - bb.width), Math.abs(ba.y + ba.height - bb.y - bb.height)) : length2;
4897
- return Math.min(VECTOR_BLEND_MAX_SMOOTH_STEPS, Math.max(1, Math.ceil(dist4 / 2)));
5853
+ const dist5 = ba && bb ? Math.max(Math.abs(ba.x - bb.x), Math.abs(ba.y - bb.y), Math.abs(ba.x + ba.width - bb.x - bb.width), Math.abs(ba.y + ba.height - bb.y - bb.height)) : length2;
5854
+ return Math.min(VECTOR_BLEND_MAX_SMOOTH_STEPS, Math.max(1, Math.ceil(dist5 / 2)));
4898
5855
  }
4899
5856
  return Math.min(VECTOR_BLEND_MAX_STEPS, Math.max(1, Math.round(Number.isFinite(o.steps) ? o.steps : DEFAULT_VECTOR_BLEND_STEPS)));
4900
5857
  }
@@ -4939,7 +5896,7 @@ function vectorBlendRailAt(rail, s) {
4939
5896
  function vectorBlendSpine(group) {
4940
5897
  const keys = vectorBlendKeys(group);
4941
5898
  if (keys.length < 2) return null;
4942
- const stored = _optionalChain([group, 'access', _102 => _102.blend, 'optionalAccess', _103 => _103.spine]);
5899
+ const stored = _optionalChain([group, 'access', _109 => _109.blend, 'optionalAccess', _110 => _110.spine]);
4943
5900
  if (stored && stored.anchors.length >= 2) {
4944
5901
  const rail2 = vectorBlendRail(stored);
4945
5902
  if (rail2) {
@@ -4960,7 +5917,7 @@ function vectorBlendKeyTargets(group) {
4960
5917
  }
4961
5918
  var morphCache = /* @__PURE__ */ new WeakMap();
4962
5919
  function morphFor(a, b, blend) {
4963
- const starts = [_nullishCoalesce(_optionalChain([blend, 'access', _104 => _104.starts, 'optionalAccess', _105 => _105[a.id]]), () => ( null)), _nullishCoalesce(_optionalChain([blend, 'access', _106 => _106.starts, 'optionalAccess', _107 => _107[b.id]]), () => ( null))];
5920
+ const starts = [_nullishCoalesce(_optionalChain([blend, 'access', _111 => _111.starts, 'optionalAccess', _112 => _112[a.id]]), () => ( null)), _nullishCoalesce(_optionalChain([blend, 'access', _113 => _113.starts, 'optionalAccess', _114 => _114[b.id]]), () => ( null))];
4964
5921
  const key = JSON.stringify([!!blend.linear, starts]);
4965
5922
  let inner = morphCache.get(a);
4966
5923
  if (!inner) morphCache.set(a, inner = /* @__PURE__ */ new WeakMap());
@@ -5059,16 +6016,179 @@ function releaseVectorBlend(group, newId) {
5059
6016
  const m = nodeMatrix(group);
5060
6017
  const opacity = group.opacity;
5061
6018
  const keys = vectorBlendKeys(group).map((c) => group.transform ? transformVectorNode(c, m) : c).map((c) => opacity !== void 0 && opacity < 1 ? { ...c, opacity: (_nullishCoalesce(c.opacity, () => ( 1))) * opacity } : c);
5062
- const spine = _optionalChain([group, 'access', _108 => _108.blend, 'optionalAccess', _109 => _109.spine]);
6019
+ const spine = _optionalChain([group, 'access', _115 => _115.blend, 'optionalAccess', _116 => _116.spine]);
5063
6020
  if (!spine || spine.anchors.length < 2) return keys;
5064
6021
  const path = { id: newId(), type: "path", name: "Spine", fill: null, stroke: null, subpaths: [{ closed: spine.closed, anchors: spine.anchors.map((a) => ({ ...a })) }] };
5065
6022
  return [...keys, group.transform ? transformVectorNode(path, m) : path];
5066
6023
  }
5067
6024
 
6025
+ // src/vector/perspective.ts
6026
+ function solve8(rows) {
6027
+ const m = rows.map((r) => r.slice());
6028
+ for (let col = 0; col < 8; col++) {
6029
+ let pivot = col;
6030
+ for (let r = col + 1; r < 8; r++) if (Math.abs(m[r][col]) > Math.abs(m[pivot][col])) pivot = r;
6031
+ if (!(Math.abs(m[pivot][col]) >= 1e-12)) return null;
6032
+ [m[col], m[pivot]] = [m[pivot], m[col]];
6033
+ const p = m[col];
6034
+ for (let r = 0; r < 8; r++) {
6035
+ if (r === col) continue;
6036
+ const f = m[r][col] / p[col];
6037
+ if (f !== 0) for (let k = 0; k < 9; k++) m[r][k] -= f * p[k];
6038
+ }
6039
+ }
6040
+ const out = [];
6041
+ for (let i = 0; i < 8; i++) {
6042
+ const v2 = m[i][8] / m[i][i];
6043
+ if (!Number.isFinite(v2)) return null;
6044
+ out.push(v2);
6045
+ }
6046
+ return out;
6047
+ }
6048
+ function applyVectorHomography(h, p) {
6049
+ const w = h[6] * p.x + h[7] * p.y + h[8];
6050
+ if (!Number.isFinite(w) || Math.abs(w) < 1e-12) return null;
6051
+ const x = (h[0] * p.x + h[1] * p.y + h[2]) / w;
6052
+ const y = (h[3] * p.x + h[4] * p.y + h[5]) / w;
6053
+ return Number.isFinite(x) && Number.isFinite(y) ? { x, y } : null;
6054
+ }
6055
+ var finite = (p) => Number.isFinite(p.x) && Number.isFinite(p.y);
6056
+ function vectorHomography(from, to) {
6057
+ if (from.length !== 4 || to.length !== 4 || ![...from, ...to].every(finite)) return null;
6058
+ const rows = [];
6059
+ for (let i = 0; i < 4; i++) {
6060
+ const { x, y } = from[i];
6061
+ const { x: u, y: v2 } = to[i];
6062
+ rows.push([x, y, 1, 0, 0, 0, -u * x, -u * y, u]);
6063
+ rows.push([0, 0, 0, x, y, 1, -v2 * x, -v2 * y, v2]);
6064
+ }
6065
+ const h = solve8(rows);
6066
+ if (!h) return null;
6067
+ const out = [h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], 1];
6068
+ for (let i = 0; i < 4; i++) {
6069
+ const r = applyVectorHomography(out, from[i]);
6070
+ const q = to[i];
6071
+ const scale3 = 1 + Math.max(Math.abs(q.x), Math.abs(q.y));
6072
+ if (!r || Math.abs(r.x - q.x) > 1e-6 * scale3 || Math.abs(r.y - q.y) > 1e-6 * scale3) return null;
6073
+ }
6074
+ return out;
6075
+ }
6076
+ function vectorHomographyKeepsQuad(h, quad) {
6077
+ const ws = quad.map((p) => h[6] * p.x + h[7] * p.y + h[8]);
6078
+ return ws.every((w) => w > 1e-9) || ws.every((w) => w < -1e-9);
6079
+ }
6080
+ function orderVectorQuad(points) {
6081
+ if (points.length !== 4 || !points.every(finite)) return null;
6082
+ const cx = points.reduce((s, p) => s + p.x, 0) / 4;
6083
+ const cy = points.reduce((s, p) => s + p.y, 0) / 4;
6084
+ const q = points.slice().sort((a, b) => Math.atan2(a.y - cy, a.x - cx) - Math.atan2(b.y - cy, b.x - cx));
6085
+ let first = 0;
6086
+ for (let i = 1; i < 4; i++) if (q[i].x + q[i].y < q[first].x + q[first].y) first = i;
6087
+ const ordered = [...q.slice(first), ...q.slice(0, first)];
6088
+ const cross2 = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
6089
+ const turns = ordered.map((_, i) => cross2(ordered[i], ordered[(i + 1) % 4], ordered[(i + 2) % 4]));
6090
+ const area = turns.reduce((s, t) => s + t, 0) / 2;
6091
+ const xs = ordered.map((p) => p.x);
6092
+ const ys = ordered.map((p) => p.y);
6093
+ const size = Math.max(Math.max(...xs) - Math.min(...xs), Math.max(...ys) - Math.min(...ys));
6094
+ const convex = turns.every((t) => t > 1e-9 * size * size);
6095
+ return convex && area > 1e-6 * size * size ? ordered : null;
6096
+ }
6097
+
6098
+ // src/vector/distort.ts
6099
+ var VECTOR_DISTORT_TOLERANCE = 0.05;
6100
+ var CORNER_INDEX = { nw: 0, ne: 1, se: 2, sw: 3 };
6101
+ var SIDE_CORNERS = { n: [0, 1], e: [1, 2], s: [2, 3], w: [3, 0] };
6102
+ var vectorBoxCorners = (b) => [
6103
+ { x: b.x, y: b.y },
6104
+ { x: b.x + b.width, y: b.y },
6105
+ { x: b.x + b.width, y: b.y + b.height },
6106
+ { x: b.x, y: b.y + b.height }
6107
+ ];
6108
+ function vectorDistortQuad(b, handle, d, mode = "distort") {
6109
+ const q = vectorBoxCorners(b);
6110
+ const i = CORNER_INDEX[handle];
6111
+ if (i !== void 0) {
6112
+ if (mode === "perspective") {
6113
+ if (Math.abs(d.x) >= Math.abs(d.y)) {
6114
+ const partner = [1, 0, 3, 2][i];
6115
+ q[i].x += d.x;
6116
+ q[partner].x -= d.x;
6117
+ } else {
6118
+ const partner = [3, 2, 1, 0][i];
6119
+ q[i].y += d.y;
6120
+ q[partner].y -= d.y;
6121
+ }
6122
+ } else {
6123
+ q[i].x += d.x;
6124
+ q[i].y += d.y;
6125
+ }
6126
+ return q;
6127
+ }
6128
+ const side = SIDE_CORNERS[handle];
6129
+ if (side) for (const k of side) q[k] = { x: q[k].x + d.x, y: q[k].y + d.y };
6130
+ return q;
6131
+ }
6132
+ var about = (o, m) => multiplyMatrices(multiplyMatrices([1, 0, 0, 1, -o.x, -o.y], m), [1, 0, 0, 1, o.x, o.y]);
6133
+ function vectorShearForSide(b, handle, d, fromCenter = false) {
6134
+ const center = { x: b.x + b.width / 2, y: b.y + b.height / 2 };
6135
+ if (handle === "n" || handle === "s") {
6136
+ const o = fromCenter ? center : { x: center.x, y: handle === "n" ? b.y + b.height : b.y };
6137
+ const lever = (handle === "n" ? b.y : b.y + b.height) - o.y;
6138
+ return about(o, [1, 0, Math.abs(lever) > 1e-9 ? d.x / lever : 0, 1, 0, 0]);
6139
+ }
6140
+ if (handle === "e" || handle === "w") {
6141
+ const o = fromCenter ? center : { x: handle === "w" ? b.x + b.width : b.x, y: center.y };
6142
+ const lever = (handle === "w" ? b.x : b.x + b.width) - o.x;
6143
+ return about(o, [1, Math.abs(lever) > 1e-9 ? d.y / lever : 0, 0, 1, 0, 0]);
6144
+ }
6145
+ return [1, 0, 0, 1, 0, 0];
6146
+ }
6147
+ function vectorSkewMatrix(ax, ay, origin = { x: 0, y: 0 }) {
6148
+ const tx = Math.tan(ax * Math.PI / 180);
6149
+ const ty = Math.tan(ay * Math.PI / 180);
6150
+ return about(origin, [1, ty, tx, 1, 0, 0]);
6151
+ }
6152
+ function mapEffects(node, f) {
6153
+ if (!_optionalChain([node, 'access', _117 => _117.effects, 'optionalAccess', _118 => _118.length])) return void 0;
6154
+ return node.effects.map((e) => {
6155
+ if (e.type !== "envelope") return e;
6156
+ if (e.params.style === "mesh") return e.params.mesh ? { ...e, params: { ...e.params, mesh: mapVectorMeshPoints(e.params.mesh, f) } } : e;
6157
+ const bounds = vectorEffectInputBounds(node, e.id);
6158
+ if (!bounds || !vectorEnvelopeMap(e.params, bounds)) return e;
6159
+ return { ...e, params: { ...e.params, style: "mesh", mesh: mapVectorMeshPoints(vectorEnvelopeMesh(e.params, bounds), f) } };
6160
+ });
6161
+ }
6162
+ function distortVectorNode(node, parentToDoc, f, tolerance = VECTOR_DISTORT_TOLERANCE) {
6163
+ const toDoc = multiplyMatrices(nodeMatrix(node), parentToDoc);
6164
+ const inv = invertMatrix(toDoc);
6165
+ const local = (p) => applyMatrix(inv, f(applyMatrix(toDoc, p)));
6166
+ const effects = mapEffects(node, local);
6167
+ if (node.type === "group") {
6168
+ const group = node;
6169
+ const children = group.children.map((c) => distortVectorNode(c, toDoc, f, tolerance));
6170
+ const spine = _optionalChain([group, 'access', _119 => _119.blend, 'optionalAccess', _120 => _120.spine]);
6171
+ return {
6172
+ ...group,
6173
+ children,
6174
+ ...effects ? { effects } : {},
6175
+ ...spine ? { blend: { ...group.blend, spine: mapVectorSubpaths([spine], local, tolerance)[0] } } : {}
6176
+ };
6177
+ }
6178
+ const path = node;
6179
+ return {
6180
+ ...path,
6181
+ ...effects ? { effects } : {},
6182
+ ...path.fill !== void 0 ? { fill: mapVectorPaint(path.fill, local) } : {},
6183
+ ...path.stroke !== void 0 ? { stroke: mapVectorPaint(path.stroke, local) } : {},
6184
+ subpaths: mapVectorSubpaths(path.subpaths, local, tolerance)
6185
+ };
6186
+ }
6187
+
5068
6188
  // src/vector/snap.ts
5069
6189
  var VECTOR_CONSTRUCTION_ANGLES = [0, 45, 90, 135];
5070
6190
  function constrainToLeave(leave, p) {
5071
- if (!_optionalChain([leave, 'optionalAccess', _110 => _110.constrain])) return p;
6191
+ if (!_optionalChain([leave, 'optionalAccess', _121 => _121.constrain])) return p;
5072
6192
  const dx = p.x - leave.at.x;
5073
6193
  const dy = p.y - leave.at.y;
5074
6194
  switch (leave.constrain) {
@@ -5106,8 +6226,8 @@ function within(sorted, key, v2, tol) {
5106
6226
  }
5107
6227
  var linesNear = (lines, v2, tol) => within(lines, (l) => l.v, v2, tol);
5108
6228
  var distance = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
5109
- var toPoint = (p) => [p.x, p.y];
5110
- var toVec2 = (p) => ({ x: p[0], y: p[1] });
6229
+ var toPoint2 = (p) => [p.x, p.y];
6230
+ var toVec3 = (p) => ({ x: p[0], y: p[1] });
5111
6231
  var LABELS = {
5112
6232
  anchor: "anchor",
5113
6233
  centre: "centre",
@@ -5179,7 +6299,7 @@ var VectorSnapTargets = (_class3 = class _VectorSnapTargets {
5179
6299
  moving.set(r.nodeId, set);
5180
6300
  }
5181
6301
  const t = _VectorSnapTargets.collect(doc, new Set(moving.keys()), "segments", false);
5182
- t.pushPaths(doc, new Set(moving.keys()), (id, s, i) => !!_optionalChain([moving, 'access', _111 => _111.get, 'call', _112 => _112(id), 'optionalAccess', _113 => _113.has, 'call', _114 => _114(`${s}:${i}`)]), true);
6302
+ t.pushPaths(doc, new Set(moving.keys()), (id, s, i) => !!_optionalChain([moving, 'access', _122 => _122.get, 'call', _123 => _123(id), 'optionalAccess', _124 => _124.has, 'call', _125 => _125(`${s}:${i}`)]), true);
5183
6303
  return t.index();
5184
6304
  }
5185
6305
  /**
@@ -5225,7 +6345,7 @@ var VectorSnapTargets = (_class3 = class _VectorSnapTargets {
5225
6345
  const count = subpathSegmentCount(sp);
5226
6346
  for (let i = 0; i < count && budget > 0; i++) {
5227
6347
  if (moving(i) || moving((i + 1) % n)) continue;
5228
- const seg = subpathSegment(sp, i).map((q) => toPoint(applyMatrix(m, toVec2(q))));
6348
+ const seg = subpathSegment(sp, i).map((q) => toPoint2(applyMatrix(m, toVec3(q))));
5229
6349
  let minX = Infinity;
5230
6350
  let minY = Infinity;
5231
6351
  let maxX = -Infinity;
@@ -5298,7 +6418,7 @@ var VectorSnapTargets = (_class3 = class _VectorSnapTargets {
5298
6418
  }
5299
6419
  const b = vectorNodeBounds(n, parent);
5300
6420
  const f = nodeFrame(n, parent, b);
5301
- if (b) self.pushRect(b, "edge", _nullishCoalesce(_optionalChain([f, 'optionalAccess', _115 => _115.centre]), () => ( null)));
6421
+ if (b) self.pushRect(b, "edge", _nullishCoalesce(_optionalChain([f, 'optionalAccess', _126 => _126.centre]), () => ( null)));
5302
6422
  }
5303
6423
  };
5304
6424
  visit(doc.nodes, IDENTITY_MATRIX);
@@ -5343,7 +6463,7 @@ var VectorSnapTargets = (_class3 = class _VectorSnapTargets {
5343
6463
  lines: lines2,
5344
6464
  labels: [this.label(q, kind)]
5345
6465
  });
5346
- if (_optionalChain([leave, 'optionalAccess', _116 => _116.constrain])) {
6466
+ if (_optionalChain([leave, 'optionalAccess', _127 => _127.constrain])) {
5347
6467
  const q = constrainToLeave(leave, p);
5348
6468
  const hit = this.slide(leave.at, { x: q.x - leave.at.x, y: q.y - leave.at.y }, q, tol, true);
5349
6469
  return hit ? { point: hit.point, x: true, y: true, ...this.linedUp(hit.point, hit.from) } : none(q);
@@ -5359,7 +6479,7 @@ var VectorSnapTargets = (_class3 = class _VectorSnapTargets {
5359
6479
  }
5360
6480
  const on = this.onSegment(near2);
5361
6481
  if (on) return at2(on, "path");
5362
- if (_optionalChain([leave, 'optionalAccess', _117 => _117.angles, 'optionalAccess', _118 => _118.length])) {
6482
+ if (_optionalChain([leave, 'optionalAccess', _128 => _128.angles, 'optionalAccess', _129 => _129.length])) {
5363
6483
  const c = construction(leave, p, tol);
5364
6484
  if (c) {
5365
6485
  const hit = this.slide(leave.at, c.dir, c.point, tol, false);
@@ -5432,7 +6552,7 @@ var VectorSnapTargets = (_class3 = class _VectorSnapTargets {
5432
6552
  /** Target segments whose control box reaches `p` and which pass within `tol` of it, nearest first. */
5433
6553
  segmentsNear(p, tol) {
5434
6554
  const out = [];
5435
- const pt2 = toPoint(p);
6555
+ const pt2 = toPoint2(p);
5436
6556
  for (const s of this.segments) {
5437
6557
  if (p.x < s.minX - tol || p.x > s.maxX + tol || p.y < s.minY - tol || p.y > s.maxY + tol) continue;
5438
6558
  const hit = _chunkVNYRI265cjs.segmentNearest.call(void 0, s.seg, pt2);
@@ -5441,7 +6561,7 @@ var VectorSnapTargets = (_class3 = class _VectorSnapTargets {
5441
6561
  return out.sort((a, b) => a.distance - b.distance);
5442
6562
  }
5443
6563
  onSegment(near2) {
5444
- return near2.length ? toVec2(_chunkVNYRI265cjs.segmentPoint.call(void 0, near2[0].seg, near2[0].t)) : null;
6564
+ return near2.length ? toVec3(_chunkVNYRI265cjs.segmentPoint.call(void 0, near2[0].seg, near2[0].t)) : null;
5445
6565
  }
5446
6566
  /** Where two of the target segments near `p` cross, the crossing nearest `p` within `tol`. */
5447
6567
  crossing(near2, p, tol) {
@@ -5451,7 +6571,7 @@ var VectorSnapTargets = (_class3 = class _VectorSnapTargets {
5451
6571
  for (let i = 0; i < list.length; i++) {
5452
6572
  for (let j = i + 1; j < list.length; j++) {
5453
6573
  for (const hit of _chunkVNYRI265cjs.segmentIntersections.call(void 0, list[i].seg, list[j].seg)) {
5454
- const q = toVec2(hit.point);
6574
+ const q = toVec3(hit.point);
5455
6575
  const d = distance(q, p);
5456
6576
  if (d <= tol && d < bestD) {
5457
6577
  best = q;
@@ -5489,7 +6609,7 @@ var VectorSnapTargets = (_class3 = class _VectorSnapTargets {
5489
6609
  * with nothing spaces the box evenly in its row or column. Returns the correction and guides.
5490
6610
  */
5491
6611
  snapRect(r, tol, options = {}) {
5492
- const axes = { x: _optionalChain([options, 'access', _119 => _119.axes, 'optionalAccess', _120 => _120.x]) !== false, y: _optionalChain([options, 'access', _121 => _121.axes, 'optionalAccess', _122 => _122.y]) !== false };
6612
+ const axes = { x: _optionalChain([options, 'access', _130 => _130.axes, 'optionalAccess', _131 => _131.x]) !== false, y: _optionalChain([options, 'access', _132 => _132.axes, 'optionalAccess', _133 => _133.y]) !== false };
5493
6613
  const nearest = (lines, values) => {
5494
6614
  let best = null;
5495
6615
  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 };
@@ -5497,7 +6617,7 @@ var VectorSnapTargets = (_class3 = class _VectorSnapTargets {
5497
6617
  };
5498
6618
  const bx = axes.x ? nearest(this.xs, [r.x, r.x + r.width / 2, r.x + r.width]) : null;
5499
6619
  const by = axes.y ? nearest(this.ys, [r.y, r.y + r.height / 2, r.y + r.height]) : null;
5500
- const out = { dx: _nullishCoalesce(_optionalChain([bx, 'optionalAccess', _123 => _123.d]), () => ( 0)), dy: _nullishCoalesce(_optionalChain([by, 'optionalAccess', _124 => _124.d]), () => ( 0)), x: !!bx, y: !!by, lines: [], labels: [] };
6620
+ const out = { dx: _nullishCoalesce(_optionalChain([bx, 'optionalAccess', _134 => _134.d]), () => ( 0)), dy: _nullishCoalesce(_optionalChain([by, 'optionalAccess', _135 => _135.d]), () => ( 0)), x: !!bx, y: !!by, lines: [], labels: [] };
5501
6621
  const done = { ...r, x: r.x + out.dx, y: r.y + out.dy };
5502
6622
  if (bx) {
5503
6623
  const x = bx.from.x;
@@ -5620,9 +6740,9 @@ var VectorSnapTargets = (_class3 = class _VectorSnapTargets {
5620
6740
  const on = this.nearestPoint(p, tol);
5621
6741
  const tries = [];
5622
6742
  if (on) tries.push({ tx: on.p.x, ty: on.p.y, s: { hx: null, hy: null, on } });
5623
- tries.push({ tx: _nullishCoalesce(_optionalChain([hx, 'optionalAccess', _125 => _125.v]), () => ( null)), ty: _nullishCoalesce(_optionalChain([hy, 'optionalAccess', _126 => _126.v]), () => ( null)), s: { hx, hy, on: null } });
5624
- tries.push({ tx: _nullishCoalesce(_optionalChain([hx, 'optionalAccess', _127 => _127.v]), () => ( null)), ty: null, s: { hx, hy: null, on: null } });
5625
- tries.push({ tx: null, ty: _nullishCoalesce(_optionalChain([hy, 'optionalAccess', _128 => _128.v]), () => ( null)), s: { hx: null, hy, on: null } });
6743
+ tries.push({ tx: _nullishCoalesce(_optionalChain([hx, 'optionalAccess', _136 => _136.v]), () => ( null)), ty: _nullishCoalesce(_optionalChain([hy, 'optionalAccess', _137 => _137.v]), () => ( null)), s: { hx, hy, on: null } });
6744
+ tries.push({ tx: _nullishCoalesce(_optionalChain([hx, 'optionalAccess', _138 => _138.v]), () => ( null)), ty: null, s: { hx, hy: null, on: null } });
6745
+ tries.push({ tx: null, ty: _nullishCoalesce(_optionalChain([hy, 'optionalAccess', _139 => _139.v]), () => ( null)), s: { hx: null, hy, on: null } });
5626
6746
  for (const { tx, ty, s } of tries) {
5627
6747
  if (tx === null && ty === null) continue;
5628
6748
  const q = applyMatrix(toLocal, { x: _nullishCoalesce(tx, () => ( p.x)), y: _nullishCoalesce(ty, () => ( p.y)) });
@@ -6030,7 +7150,7 @@ function splitSubpathAt(sp, segment, t, endTolerance = 1e-6) {
6030
7150
  return cutSubpathAt(subpath, [index]);
6031
7151
  }
6032
7152
  var endOf2 = (sp, last) => sp.anchors[last ? sp.anchors.length - 1 : 0];
6033
- var dist2 = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
7153
+ var dist3 = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
6034
7154
  function reverse(sp) {
6035
7155
  return {
6036
7156
  closed: sp.closed,
@@ -6057,7 +7177,7 @@ function joinSubpaths(subpaths, tolerance) {
6057
7177
  const sp = open[0];
6058
7178
  const first = sp.anchors[0];
6059
7179
  const last = sp.anchors[sp.anchors.length - 1];
6060
- if (sp.anchors.length > 2 && dist2(first, last) <= tolerance) {
7180
+ if (sp.anchors.length > 2 && dist3(first, last) <= tolerance) {
6061
7181
  sp.anchors.pop();
6062
7182
  sp.anchors[0] = tidy({ ...first, in: _nullishCoalesce(last.in, () => ( null)) }, false);
6063
7183
  } else {
@@ -6073,7 +7193,7 @@ function joinSubpaths(subpaths, tolerance) {
6073
7193
  for (let j = i + 1; j < open.length; j++) {
6074
7194
  for (const ei of [false, true]) {
6075
7195
  for (const ej of [false, true]) {
6076
- const d = dist2(endOf2(open[i], ei), endOf2(open[j], ej));
7196
+ const d = dist3(endOf2(open[i], ei), endOf2(open[j], ej));
6077
7197
  if (d < best.d) best = { d, i, j, ei, ej };
6078
7198
  }
6079
7199
  }
@@ -6113,8 +7233,8 @@ function smoothSubpath(sp, amount = 1, only) {
6113
7233
  const p = orig[i];
6114
7234
  const dir = unit4(next.x - prev.x, next.y - prev.y);
6115
7235
  if (!dir) continue;
6116
- const li = dist2(p, prev) / 3;
6117
- const lo = dist2(p, next) / 3;
7236
+ const li = dist3(p, prev) / 3;
7237
+ const lo = dist3(p, next) / 3;
6118
7238
  const hin = _nullishCoalesce(p.in, () => ( p));
6119
7239
  const hout = _nullishCoalesce(p.out, () => ( p));
6120
7240
  const target = (h, x, y) => ({ x: h.x + (x - h.x) * t, y: h.y + (y - h.y) * t });
@@ -6605,7 +7725,7 @@ function vectorInkShapeName(shape) {
6605
7725
  return shape.points.length === 3 ? "triangle" : "polygon";
6606
7726
  }
6607
7727
  }
6608
- var dist3 = (a, b) => Math.hypot(b[0] - a[0], b[1] - a[1]);
7728
+ var dist4 = (a, b) => Math.hypot(b[0] - a[0], b[1] - a[1]);
6609
7729
  function bbox(pts) {
6610
7730
  if (!pts.length) return [0, 0, 0, 0];
6611
7731
  let [x0, y0] = pts[0];
@@ -6623,7 +7743,7 @@ function segDistance(a, b, p) {
6623
7743
  const dy = b[1] - a[1];
6624
7744
  const len2 = dx * dx + dy * dy;
6625
7745
  const t = len2 > 0 ? Math.min(1, Math.max(0, ((p[0] - a[0]) * dx + (p[1] - a[1]) * dy) / len2)) : 0;
6626
- return dist3([a[0] + t * dx, a[1] + t * dy], p);
7746
+ return dist4([a[0] + t * dx, a[1] + t * dy], p);
6627
7747
  }
6628
7748
  function polygonDistance(c, p) {
6629
7749
  let best = Infinity;
@@ -6685,7 +7805,7 @@ function corners(p, diag) {
6685
7805
  let far = 0;
6686
7806
  let farD = 0;
6687
7807
  p.forEach((q, i) => {
6688
- const d = dist3(start, q);
7808
+ const d = dist4(start, q);
6689
7809
  if (d > farD) {
6690
7810
  farD = d;
6691
7811
  far = i;
@@ -6712,7 +7832,7 @@ function corners(p, diag) {
6712
7832
  }
6713
7833
  let short = -1;
6714
7834
  for (let j = 0; j < n; j++) {
6715
- if (dist3(ring[j], ring[(j + 1) % n]) < 0.1 * diag) {
7835
+ if (dist4(ring[j], ring[(j + 1) % n]) < 0.1 * diag) {
6716
7836
  short = j;
6717
7837
  break;
6718
7838
  }
@@ -6752,8 +7872,8 @@ function recognizeInkShape(points, options = {}) {
6752
7872
  const diag = Math.hypot(w, h);
6753
7873
  if (size < minSize) return null;
6754
7874
  let length2 = 0;
6755
- for (let i = 1; i < p.length; i++) length2 += dist3(p[i - 1], p[i]);
6756
- const gap = dist3(first, last);
7875
+ for (let i = 1; i < p.length; i++) length2 += dist4(p[i - 1], p[i]);
7876
+ const gap = dist4(first, last);
6757
7877
  if (gap > 0.85 * length2 && gap >= minSize) {
6758
7878
  const off = Math.max(...p.map((q) => segDistance(first, last, q)));
6759
7879
  if (off <= Math.max(0.06 * gap, 1.5 * minSize / 6)) return { kind: "line", a: first, b: last };
@@ -7052,7 +8172,7 @@ function getEditablePathIds(state) {
7052
8172
  }
7053
8173
  }
7054
8174
  }
7055
- return [...ids].filter((id) => _optionalChain([findVectorNode, 'call', _129 => _129(state.document.nodes, id), 'optionalAccess', _130 => _130.type]) === "path");
8175
+ return [...ids].filter((id) => _optionalChain([findVectorNode, 'call', _140 => _140(state.document.nodes, id), 'optionalAccess', _141 => _141.type]) === "path");
7056
8176
  }
7057
8177
  function getVisibleAnchors(state) {
7058
8178
  const out = [];
@@ -7067,7 +8187,7 @@ function getVisibleHandles(state) {
7067
8187
  const seen = /* @__PURE__ */ new Set();
7068
8188
  const push = (node, s, i, handle) => {
7069
8189
  const sp = node.subpaths[s];
7070
- const a = _optionalChain([sp, 'optionalAccess', _131 => _131.anchors, 'access', _132 => _132[i]]);
8190
+ const a = _optionalChain([sp, 'optionalAccess', _142 => _142.anchors, 'access', _143 => _143[i]]);
7071
8191
  if (!a || !a[handle]) return;
7072
8192
  const key = `${node.id}:${s}:${i}:${handle}`;
7073
8193
  if (seen.has(key)) return;
@@ -7076,8 +8196,8 @@ function getVisibleHandles(state) {
7076
8196
  };
7077
8197
  if (state.tool === "pen" && state.pen) {
7078
8198
  const node = findVectorNode(state.document.nodes, state.pen.nodeId);
7079
- const sp = _optionalChain([node, 'optionalAccess', _133 => _133.type]) === "path" ? node.subpaths[state.pen.subpath] : void 0;
7080
- if (_optionalChain([node, 'optionalAccess', _134 => _134.type]) === "path" && sp) {
8199
+ const sp = _optionalChain([node, 'optionalAccess', _144 => _144.type]) === "path" ? node.subpaths[state.pen.subpath] : void 0;
8200
+ if (_optionalChain([node, 'optionalAccess', _145 => _145.type]) === "path" && sp) {
7081
8201
  const last = sp.anchors.length - 1;
7082
8202
  push(node, state.pen.subpath, last, "in");
7083
8203
  push(node, state.pen.subpath, last, "out");
@@ -7115,11 +8235,11 @@ function getVectorCornerWidgets(state) {
7115
8235
  const side = Math.min(c.lu, c.lv);
7116
8236
  if (side * zoom < 3 * VECTOR_CORNER_WIDGET_INSET) continue;
7117
8237
  const a = node.subpaths[c.subpath].anchors[c.index];
7118
- const radius = _nullishCoalesce(_optionalChain([a, 'access', _135 => _135.corner, 'optionalAccess', _136 => _136.radius]), () => ( 0));
8238
+ const radius = _nullishCoalesce(_optionalChain([a, 'access', _146 => _146.corner, 'optionalAccess', _147 => _147.radius]), () => ( 0));
7119
8239
  const drawn = fitCornerRadius(c, radius);
7120
8240
  const k = Math.min(Math.max(drawn / c.sin, VECTOR_CORNER_WIDGET_INSET / (zoom * Math.sqrt(1 + c.cos))), side / 2);
7121
8241
  const p = applyMatrix(m, cornerBisectorPoint(c, k));
7122
- 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', _137 => _137.corner, 'optionalAccess', _138 => _138.kind]), () => ( "round")), corner: c });
8242
+ 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', _148 => _148.corner, 'optionalAccess', _149 => _149.kind]), () => ( "round")), corner: c });
7123
8243
  }
7124
8244
  }
7125
8245
  return out;
@@ -7142,13 +8262,13 @@ function getVectorWidthHandles(state) {
7142
8262
  const n = findVectorNode(state.document.nodes, id);
7143
8263
  if (n) for (const p of collectPathNodes(n)) ids.add(p.id);
7144
8264
  }
7145
- if (_optionalChain([state, 'access', _139 => _139.hover, 'optionalAccess', _140 => _140.nodeId])) ids.add(state.hover.nodeId);
7146
- if (_optionalChain([state, 'access', _141 => _141.interaction, 'optionalAccess', _142 => _142.type]) === "width") ids.add(state.interaction.ref.nodeId);
8265
+ if (_optionalChain([state, 'access', _150 => _150.hover, 'optionalAccess', _151 => _151.nodeId])) ids.add(state.hover.nodeId);
8266
+ if (_optionalChain([state, 'access', _152 => _152.interaction, 'optionalAccess', _153 => _153.type]) === "width") ids.add(state.interaction.ref.nodeId);
7147
8267
  for (const r of state.selectedWidthPoints) ids.add(r.nodeId);
7148
8268
  const out = [];
7149
8269
  for (const id of ids) {
7150
8270
  const node = findVectorNode(state.document.nodes, id);
7151
- if (_optionalChain([node, 'optionalAccess', _143 => _143.type]) !== "path" || node.visible === false || !_optionalChain([node, 'access', _144 => _144.strokeWidthProfile, 'optionalAccess', _145 => _145.length])) continue;
8271
+ if (_optionalChain([node, 'optionalAccess', _154 => _154.type]) !== "path" || node.visible === false || !_optionalChain([node, 'access', _155 => _155.strokeWidthProfile, 'optionalAccess', _156 => _156.length])) continue;
7152
8272
  const g = vectorStrokeWidthGeometry(node);
7153
8273
  if (!g) continue;
7154
8274
  const profile = sanitizeWidthProfile(node.strokeWidthProfile);
@@ -7181,7 +8301,7 @@ function getVectorWidthHandles(state) {
7181
8301
  }
7182
8302
  function getAnchor(doc, ref) {
7183
8303
  const node = findVectorNode(doc.nodes, ref.nodeId);
7184
- return _optionalChain([node, 'optionalAccess', _146 => _146.type]) === "path" ? _optionalChain([node, 'access', _147 => _147.subpaths, 'access', _148 => _148[ref.subpath], 'optionalAccess', _149 => _149.anchors, 'access', _150 => _150[ref.index]]) : void 0;
8304
+ return _optionalChain([node, 'optionalAccess', _157 => _157.type]) === "path" ? _optionalChain([node, 'access', _158 => _158.subpaths, 'access', _159 => _159[ref.subpath], 'optionalAccess', _160 => _160.anchors, 'access', _161 => _161[ref.index]]) : void 0;
7185
8305
  }
7186
8306
  function getAnchorWorld(doc, ref) {
7187
8307
  const a = getAnchor(doc, ref);
@@ -7194,8 +8314,8 @@ function getVectorSelectionFrame(doc, ids) {
7194
8314
  const nodes = ids.map((id) => ({ node: findVectorNode(doc.nodes, id), parent: _nullishCoalesce(vectorParentMatrix(doc.nodes, id), () => ( IDENTITY_MATRIX)) })).filter((n) => n.node);
7195
8315
  if (!nodes.length) return null;
7196
8316
  const angles = nodes.map((n) => matrixRotation(multiplyMatrices(nodeMatrix(n.node), n.parent)));
7197
- const same = angles.every((a) => Math.abs(normalizeAngle(a - angles[0])) < 1e-6);
7198
- const angle = same ? angles[0] : 0;
8317
+ const same2 = angles.every((a) => Math.abs(normalizeAngle(a - angles[0])) < 1e-6);
8318
+ const angle = same2 ? angles[0] : 0;
7199
8319
  const unrotate = rotateMatrix(-angle);
7200
8320
  const b = unionBounds(nodes.map((n) => vectorNodeBounds(n.node, multiplyMatrices(n.parent, unrotate))));
7201
8321
  return b ? { ...b, angle } : null;
@@ -7230,6 +8350,13 @@ function getVectorSelectionBoxGeometry(frame2, viewport) {
7230
8350
  const r = (n) => Math.round(n * 1e3) / 1e3;
7231
8351
  return { box, angle: frame2.angle, transform: frame2.angle ? `rotate(${r(frame2.angle)} ${r(viewport.x)} ${r(viewport.y)})` : "", handles, corners: corners2 };
7232
8352
  }
8353
+ function getVectorEnvelopeTarget(doc, selection) {
8354
+ if (selection.length !== 1) return null;
8355
+ const node = findVectorNode(doc.nodes, selection[0]);
8356
+ if (!node || !vectorNodeEnvelope(node)) return null;
8357
+ const frame2 = vectorEnvelopeFrame(node);
8358
+ return frame2 ? { node, frame: frame2, world: _nullishCoalesce(vectorWorldMatrix(doc.nodes, node.id), () => ( IDENTITY_MATRIX)) } : null;
8359
+ }
7233
8360
  var RESIZE_CURSOR_ORDER = ["ew-resize", "nwse-resize", "ns-resize", "nesw-resize"];
7234
8361
  var HANDLE_ANGLES = { e: 0, se: 45, s: 90, sw: 135, w: 180, nw: 225, n: 270, ne: 315 };
7235
8362
  function vectorResizeCursor(handle, angle = 0) {
@@ -7254,7 +8381,8 @@ var TOOL_LABELS = {
7254
8381
  shapeBuilder: "Shape Builder",
7255
8382
  paintBucket: "Paint Bucket",
7256
8383
  blend: "Blend",
7257
- gradient: "Gradient"
8384
+ gradient: "Gradient",
8385
+ envelope: "Envelope Mesh"
7258
8386
  };
7259
8387
  var TOOL_KEYS = {
7260
8388
  v: "select",
@@ -7273,7 +8401,8 @@ var TOOL_KEYS = {
7273
8401
  m: "shapeBuilder",
7274
8402
  b: "paintBucket",
7275
8403
  j: "blend",
7276
- g: "gradient"
8404
+ g: "gradient",
8405
+ u: "envelope"
7277
8406
  };
7278
8407
  function vectorToolLabel(tool) {
7279
8408
  return TOOL_LABELS[tool];
@@ -7295,7 +8424,8 @@ var VECTOR_TOOL_SHORTCUTS = {
7295
8424
  shapeBuilder: "M",
7296
8425
  paintBucket: "B",
7297
8426
  blend: "J",
7298
- gradient: "G"
8427
+ gradient: "G",
8428
+ envelope: "U"
7299
8429
  };
7300
8430
  var VECTOR_TOOL_GLYPHS = {
7301
8431
  select: "\u2196",
@@ -7314,7 +8444,8 @@ var VECTOR_TOOL_GLYPHS = {
7314
8444
  shapeBuilder: "\u2295",
7315
8445
  paintBucket: "\u25CD",
7316
8446
  blend: "\u29D3",
7317
- gradient: "\u25D0"
8447
+ gradient: "\u25D0",
8448
+ envelope: "\u2317"
7318
8449
  };
7319
8450
  var SHAPE_TOOLS = /* @__PURE__ */ new Set(["rect", "ellipse", "polygon", "star", "line"]);
7320
8451
  var BOOLEAN_OPS = {
@@ -7367,7 +8498,7 @@ function spliceTree(nodes, id, replacements) {
7367
8498
  }
7368
8499
  return changed ? out : nodes;
7369
8500
  }
7370
- var toPoint2 = (p) => [p.x, p.y];
8501
+ var toPoint3 = (p) => [p.x, p.y];
7371
8502
  var placementOf = (n) => ({
7372
8503
  ...n.transform ? { transform: n.transform } : {},
7373
8504
  ...n.visible === false ? { visible: false } : {},
@@ -7412,18 +8543,19 @@ var VectorEditorController = (_class5 = class {
7412
8543
  /** Options new blends get (the toolbars edit them along with the selected blend's). */
7413
8544
  __init31() {this.blendDefaults = {}}
7414
8545
  __init32() {this.gradientEdit = { target: "fill", stop: null }}
8546
+ __init33() {this.freeDistort = false}
7415
8547
  /** What the highlight shows, to skip notifying when the pointer stays over the same face. */
7416
- __init33() {this.builderHoverKey = null}
8548
+ __init34() {this.builderHoverKey = null}
7417
8549
 
7418
8550
 
7419
- __init34() {this.listeners = /* @__PURE__ */ new Set()}
7420
- __init35() {this.cleanups = []}
7421
- __init36() {this.applying = false}
8551
+ __init35() {this.listeners = /* @__PURE__ */ new Set()}
8552
+ __init36() {this.cleanups = []}
8553
+ __init37() {this.applying = false}
7422
8554
  /** Set while a commit records a change that was already applied, so `restore` still reports it. */
7423
- __init37() {this.committing = false}
7424
- __init38() {this.revision = 0}
8555
+ __init38() {this.committing = false}
8556
+ __init39() {this.revision = 0}
7425
8557
 
7426
- constructor(options = {}) {;_class5.prototype.__init12.call(this);_class5.prototype.__init13.call(this);_class5.prototype.__init14.call(this);_class5.prototype.__init15.call(this);_class5.prototype.__init16.call(this);_class5.prototype.__init17.call(this);_class5.prototype.__init18.call(this);_class5.prototype.__init19.call(this);_class5.prototype.__init20.call(this);_class5.prototype.__init21.call(this);_class5.prototype.__init22.call(this);_class5.prototype.__init23.call(this);_class5.prototype.__init24.call(this);_class5.prototype.__init25.call(this);_class5.prototype.__init26.call(this);_class5.prototype.__init27.call(this);_class5.prototype.__init28.call(this);_class5.prototype.__init29.call(this);_class5.prototype.__init30.call(this);_class5.prototype.__init31.call(this);_class5.prototype.__init32.call(this);_class5.prototype.__init33.call(this);_class5.prototype.__init34.call(this);_class5.prototype.__init35.call(this);_class5.prototype.__init36.call(this);_class5.prototype.__init37.call(this);_class5.prototype.__init38.call(this);_class5.prototype.__init39.call(this);_class5.prototype.__init40.call(this);
8558
+ constructor(options = {}) {;_class5.prototype.__init12.call(this);_class5.prototype.__init13.call(this);_class5.prototype.__init14.call(this);_class5.prototype.__init15.call(this);_class5.prototype.__init16.call(this);_class5.prototype.__init17.call(this);_class5.prototype.__init18.call(this);_class5.prototype.__init19.call(this);_class5.prototype.__init20.call(this);_class5.prototype.__init21.call(this);_class5.prototype.__init22.call(this);_class5.prototype.__init23.call(this);_class5.prototype.__init24.call(this);_class5.prototype.__init25.call(this);_class5.prototype.__init26.call(this);_class5.prototype.__init27.call(this);_class5.prototype.__init28.call(this);_class5.prototype.__init29.call(this);_class5.prototype.__init30.call(this);_class5.prototype.__init31.call(this);_class5.prototype.__init32.call(this);_class5.prototype.__init33.call(this);_class5.prototype.__init34.call(this);_class5.prototype.__init35.call(this);_class5.prototype.__init36.call(this);_class5.prototype.__init37.call(this);_class5.prototype.__init38.call(this);_class5.prototype.__init39.call(this);_class5.prototype.__init40.call(this);_class5.prototype.__init41.call(this);
7427
8559
  this.history = _nullishCoalesce(options.history, () => ( new (0, _chunkQKLRAA4Tcjs.HistoryManager)()));
7428
8560
  this.doc = options.document ? cloneVectorDocument(options.document) : { width: 800, height: 600, nodes: [] };
7429
8561
  this.doc = this.refreshed(this.doc);
@@ -7435,6 +8567,7 @@ var VectorEditorController = (_class5 = class {
7435
8567
  this.hitRadius = _nullishCoalesce(options.hitRadius, () => ( 6));
7436
8568
  this.createId = _nullishCoalesce(options.createId, () => ( defaultCreateId));
7437
8569
  this.onChange = options.onChange;
8570
+ this.freeDistort = !!options.freeDistort;
7438
8571
  this.state = this.computeState();
7439
8572
  this.connect();
7440
8573
  }
@@ -7464,9 +8597,9 @@ var VectorEditorController = (_class5 = class {
7464
8597
  // State
7465
8598
  // -------------------------------------------------------------------------
7466
8599
  /** The current snapshot (stable until the next change). */
7467
- __init39() {this.getState = () => this.state}
8600
+ __init40() {this.getState = () => this.state}
7468
8601
  /** Calls `listener` after every change. Returns an unsubscribe function. */
7469
- __init40() {this.subscribe = (listener) => {
8602
+ __init41() {this.subscribe = (listener) => {
7470
8603
  this.connect();
7471
8604
  this.listeners.add(listener);
7472
8605
  return () => {
@@ -7506,6 +8639,7 @@ var VectorEditorController = (_class5 = class {
7506
8639
  blendStart: this.blendStart,
7507
8640
  blendDefaults: this.blendDefaults,
7508
8641
  gradientEdit: this.gradientEdit,
8642
+ freeDistort: this.freeDistort,
7509
8643
  canUndo: h.canUndo,
7510
8644
  canRedo: h.canRedo,
7511
8645
  undoLabel: h.undoName,
@@ -7524,7 +8658,7 @@ var VectorEditorController = (_class5 = class {
7524
8658
  if (this.blendStart && !this.getNode(this.blendStart.nodeId)) this.blendStart = null;
7525
8659
  this.revision++;
7526
8660
  this.state = this.computeState();
7527
- if (docChanged) _optionalChain([this, 'access', _151 => _151.onChange, 'optionalCall', _152 => _152(this.doc)]);
8661
+ if (docChanged) _optionalChain([this, 'access', _162 => _162.onChange, 'optionalCall', _163 => _163(this.doc)]);
7528
8662
  const state = this.state;
7529
8663
  this.listeners.forEach((listener) => {
7530
8664
  try {
@@ -7554,33 +8688,38 @@ var VectorEditorController = (_class5 = class {
7554
8688
  return applyMatrix(invertMatrix(this.worldOf(id, doc)), p);
7555
8689
  }
7556
8690
  cursorFor() {
7557
- if (_optionalChain([this, 'access', _153 => _153.drag, 'optionalAccess', _154 => _154.kind]) === "pan" || this.spaceHeld) return this.drag ? "grabbing" : "grab";
7558
- if (_optionalChain([this, 'access', _155 => _155.drag, 'optionalAccess', _156 => _156.kind]) === "rotate") return "grabbing";
7559
- if (_optionalChain([this, 'access', _157 => _157.drag, 'optionalAccess', _158 => _158.kind]) === "move") return "move";
8691
+ if (_optionalChain([this, 'access', _164 => _164.drag, 'optionalAccess', _165 => _165.kind]) === "pan" || this.spaceHeld) return this.drag ? "grabbing" : "grab";
8692
+ if (_optionalChain([this, 'access', _166 => _166.drag, 'optionalAccess', _167 => _167.kind]) === "rotate") return "grabbing";
8693
+ if (_optionalChain([this, 'access', _168 => _168.drag, 'optionalAccess', _169 => _169.kind]) === "move") return "move";
7560
8694
  const h = this.hover;
7561
8695
  switch (this.tool) {
7562
8696
  case "select":
7563
- if (_optionalChain([h, 'optionalAccess', _159 => _159.transformHandle])) return vectorResizeCursor(h.transformHandle, _nullishCoalesce(_optionalChain([this, 'access', _160 => _160.frameOf, 'call', _161 => _161(this.selectedRoots()), 'optionalAccess', _162 => _162.angle]), () => ( 0)));
7564
- return _optionalChain([h, 'optionalAccess', _163 => _163.nodeId]) ? "move" : "default";
8697
+ if (_optionalChain([h, 'optionalAccess', _170 => _170.transformHandle]) && this.freeDistort && h.transformHandle !== "rotate") return "crosshair";
8698
+ if (_optionalChain([h, 'optionalAccess', _171 => _171.transformHandle])) return vectorResizeCursor(h.transformHandle, _nullishCoalesce(_optionalChain([this, 'access', _172 => _172.frameOf, 'call', _173 => _173(this.selectedRoots()), 'optionalAccess', _174 => _174.angle]), () => ( 0)));
8699
+ return _optionalChain([h, 'optionalAccess', _175 => _175.nodeId]) ? "move" : "default";
8700
+ case "envelope":
8701
+ if (_optionalChain([this, 'access', _176 => _176.drag, 'optionalAccess', _177 => _177.kind]) === "envelope") return "grabbing";
8702
+ if (_optionalChain([h, 'optionalAccess', _178 => _178.envelope])) return h.envelope.index === null ? "grab" : "pointer";
8703
+ return _optionalChain([h, 'optionalAccess', _179 => _179.nodeId]) ? "pointer" : "default";
7565
8704
  case "direct":
7566
- if (_optionalChain([h, 'optionalAccess', _164 => _164.anchor]) || _optionalChain([h, 'optionalAccess', _165 => _165.handle]) || _optionalChain([h, 'optionalAccess', _166 => _166.corner])) return "pointer";
7567
- if (_optionalChain([h, 'optionalAccess', _167 => _167.segment])) return "copy";
7568
- return _optionalChain([h, 'optionalAccess', _168 => _168.nodeId]) ? "move" : "default";
8705
+ if (_optionalChain([h, 'optionalAccess', _180 => _180.anchor]) || _optionalChain([h, 'optionalAccess', _181 => _181.handle]) || _optionalChain([h, 'optionalAccess', _182 => _182.corner])) return "pointer";
8706
+ if (_optionalChain([h, 'optionalAccess', _183 => _183.segment])) return "copy";
8707
+ return _optionalChain([h, 'optionalAccess', _184 => _184.nodeId]) ? "move" : "default";
7569
8708
  case "pen":
7570
- return _optionalChain([h, 'optionalAccess', _169 => _169.anchor]) ? "pointer" : "crosshair";
8709
+ return _optionalChain([h, 'optionalAccess', _185 => _185.anchor]) ? "pointer" : "crosshair";
7571
8710
  case "width":
7572
- if (_optionalChain([this, 'access', _170 => _170.drag, 'optionalAccess', _171 => _171.kind]) === "width") return this.drag.mode === "width" ? "ew-resize" : "grabbing";
7573
- if (_optionalChain([h, 'optionalAccess', _172 => _172.widthPoint])) return h.widthPoint.part === "center" ? "grab" : "ew-resize";
7574
- return _optionalChain([h, 'optionalAccess', _173 => _173.strokeSpot]) ? "copy" : "default";
8711
+ if (_optionalChain([this, 'access', _186 => _186.drag, 'optionalAccess', _187 => _187.kind]) === "width") return this.drag.mode === "width" ? "ew-resize" : "grabbing";
8712
+ if (_optionalChain([h, 'optionalAccess', _188 => _188.widthPoint])) return h.widthPoint.part === "center" ? "grab" : "ew-resize";
8713
+ return _optionalChain([h, 'optionalAccess', _189 => _189.strokeSpot]) ? "copy" : "default";
7575
8714
  case "shapeBuilder":
7576
- if (!_optionalChain([this, 'access', _174 => _174.builderPreview, 'optionalAccess', _175 => _175.faces, 'access', _176 => _176.length]) && !_optionalChain([this, 'access', _177 => _177.builderPreview, 'optionalAccess', _178 => _178.lines, 'access', _179 => _179.length])) return "crosshair";
8715
+ if (!_optionalChain([this, 'access', _190 => _190.builderPreview, 'optionalAccess', _191 => _191.faces, 'access', _192 => _192.length]) && !_optionalChain([this, 'access', _193 => _193.builderPreview, 'optionalAccess', _194 => _194.lines, 'access', _195 => _195.length])) return "crosshair";
7577
8716
  return this.builderPreview.mode === "erase" ? "not-allowed" : "cell";
7578
8717
  case "paintBucket":
7579
8718
  return this.builderPreview ? "cell" : "crosshair";
7580
8719
  case "blend":
7581
- return _optionalChain([h, 'optionalAccess', _180 => _180.nodeId]) ? this.blendStart && this.blendStart.nodeId !== h.nodeId ? "copy" : "pointer" : "crosshair";
8720
+ return _optionalChain([h, 'optionalAccess', _196 => _196.nodeId]) ? this.blendStart && this.blendStart.nodeId !== h.nodeId ? "copy" : "pointer" : "crosshair";
7582
8721
  case "gradient": {
7583
- const part = _optionalChain([this, 'access', _181 => _181.drag, 'optionalAccess', _182 => _182.kind]) === "gradient" ? this.drag.part : _optionalChain([h, 'optionalAccess', _183 => _183.gradient]);
8722
+ const part = _optionalChain([this, 'access', _197 => _197.drag, 'optionalAccess', _198 => _198.kind]) === "gradient" ? this.drag.part : _optionalChain([h, 'optionalAccess', _199 => _199.gradient]);
7584
8723
  if (!part) return "crosshair";
7585
8724
  if (part.kind === "bar") return this.drag ? "grabbing" : "copy";
7586
8725
  if (part.kind === "handle" && part.handle === "start") return this.drag ? "grabbing" : "move";
@@ -7606,11 +8745,11 @@ var VectorEditorController = (_class5 = class {
7606
8745
  this.selection = s.selection.filter((id) => this.getNode(id));
7607
8746
  this.anchors = s.anchors.filter((r) => getAnchor(this.doc, r));
7608
8747
  this.editingId = s.editingId && this.getNode(s.editingId) ? s.editingId : null;
7609
- this.pen = s.pen && _optionalChain([this, 'access', _184 => _184.getNode, 'call', _185 => _185(s.pen.nodeId), 'optionalAccess', _186 => _186.subpaths, 'optionalAccess', _187 => _187[s.pen.subpath]]) ? s.pen : null;
8748
+ this.pen = s.pen && _optionalChain([this, 'access', _200 => _200.getNode, 'call', _201 => _201(s.pen.nodeId), 'optionalAccess', _202 => _202.subpaths, 'optionalAccess', _203 => _203[s.pen.subpath]]) ? s.pen : null;
7610
8749
  if (this.widthPoints.length) {
7611
8750
  const kept = this.widthPoints.filter((r) => {
7612
8751
  const n = this.getNode(r.nodeId);
7613
- return _optionalChain([n, 'optionalAccess', _188 => _188.type]) === "path" && !!_optionalChain([n, 'access', _189 => _189.strokeWidthProfile, 'optionalAccess', _190 => _190[r.index]]);
8752
+ return _optionalChain([n, 'optionalAccess', _204 => _204.type]) === "path" && !!_optionalChain([n, 'access', _205 => _205.strokeWidthProfile, 'optionalAccess', _206 => _206[r.index]]);
7614
8753
  });
7615
8754
  if (kept.length !== this.widthPoints.length) this.widthPoints = kept;
7616
8755
  }
@@ -7792,7 +8931,7 @@ var VectorEditorController = (_class5 = class {
7792
8931
  if (res.kind) {
7793
8932
  this.snappedToObject = true;
7794
8933
  this.setGuides(res);
7795
- return _optionalChain([leave, 'optionalAccess', _191 => _191.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) };
8934
+ return _optionalChain([leave, 'optionalAccess', _207 => _207.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) };
7796
8935
  }
7797
8936
  }
7798
8937
  this.setGuides(null);
@@ -7810,14 +8949,14 @@ var VectorEditorController = (_class5 = class {
7810
8949
  /** Where the pointer at `p` would place a point with the pen or a shape tool (and the guides showing why). */
7811
8950
  hoverSnap(p, input) {
7812
8951
  if (this.tool === "pen") {
7813
- const sp = this.pen ? _optionalChain([this, 'access', _192 => _192.getNode, 'call', _193 => _193(this.pen.nodeId), 'optionalAccess', _194 => _194.subpaths, 'access', _195 => _195[this.pen.subpath]]) : void 0;
7814
- if (this.pen && sp && _optionalChain([this, 'access', _196 => _196.hover, 'optionalAccess', _197 => _197.anchor])) {
8952
+ const sp = this.pen ? _optionalChain([this, 'access', _208 => _208.getNode, 'call', _209 => _209(this.pen.nodeId), 'optionalAccess', _210 => _210.subpaths, 'access', _211 => _211[this.pen.subpath]]) : void 0;
8953
+ if (this.pen && sp && _optionalChain([this, 'access', _212 => _212.hover, 'optionalAccess', _213 => _213.anchor])) {
7815
8954
  this.setGuides(null);
7816
8955
  return p;
7817
8956
  }
7818
8957
  const last = this.pen && sp ? getAnchorWorld(this.doc, { nodeId: this.pen.nodeId, subpath: this.pen.subpath, index: sp.anchors.length - 1 }) : void 0;
7819
8958
  const leave = last ? { at: { x: last.x, y: last.y }, constrain: input.shift ? "angle" : null } : null;
7820
- return this.snapDrawn(p, leave, input, () => this.drawingTargets(_nullishCoalesce(_optionalChain([this, 'access', _198 => _198.pen, 'optionalAccess', _199 => _199.nodeId]), () => ( null))));
8959
+ return this.snapDrawn(p, leave, input, () => this.drawingTargets(_nullishCoalesce(_optionalChain([this, 'access', _214 => _214.pen, 'optionalAccess', _215 => _215.nodeId]), () => ( null))));
7821
8960
  }
7822
8961
  if (SHAPE_TOOLS.has(this.tool)) return this.snapDrawn(p, null, input, () => this.drawingTargets(null));
7823
8962
  this.setGuides(null);
@@ -7965,7 +9104,7 @@ var VectorEditorController = (_class5 = class {
7965
9104
  if (d.fillRule) out.fillRule = d.fillRule;
7966
9105
  if (d.strokeAlign && d.strokeAlign !== "center") out.strokeAlign = d.strokeAlign;
7967
9106
  for (const key of ["startArrow", "endArrow", "arrowAlign", "startArrowScale", "endArrowScale"]) if (d[key]) out[key] = d[key];
7968
- if (_optionalChain([d, 'access', _200 => _200.strokeWidthProfile, 'optionalAccess', _201 => _201.length])) out.strokeWidthProfile = d.strokeWidthProfile.map((p) => ({ ...p }));
9107
+ if (_optionalChain([d, 'access', _216 => _216.strokeWidthProfile, 'optionalAccess', _217 => _217.length])) out.strokeWidthProfile = d.strokeWidthProfile.map((p) => ({ ...p }));
7969
9108
  return out;
7970
9109
  }
7971
9110
  /** Merges `patch` into a node (paths take style and geometry; groups name / visibility / opacity). */
@@ -8059,7 +9198,7 @@ var VectorEditorController = (_class5 = class {
8059
9198
  next.set(path.id, { ...path, [target]: g });
8060
9199
  }
8061
9200
  this.change(_nullishCoalesce(options.label, () => ( "Gradient")), () => this.setDoc(mapTree(this.doc.nodes, (n) => _nullishCoalesce(next.get(n.id), () => ( n)))), options.merge);
8062
- const stops = _nullishCoalesce(_optionalChain([next, 'access', _202 => _202.values, 'call', _203 => _203(), 'access', _204 => _204.next, 'call', _205 => _205(), 'access', _206 => _206.value, 'optionalAccess', _207 => _207[target], 'optionalAccess', _208 => _208.stops, 'access', _209 => _209.length]), () => ( 0));
9201
+ const stops = _nullishCoalesce(_optionalChain([next, 'access', _218 => _218.values, 'call', _219 => _219(), 'access', _220 => _220.next, 'call', _221 => _221(), 'access', _222 => _222.value, 'optionalAccess', _223 => _223[target], 'optionalAccess', _224 => _224.stops, 'access', _225 => _225.length]), () => ( 0));
8063
9202
  if (this.gradientEdit.stop !== null && this.gradientEdit.stop >= stops) this.gradientEdit = { ...this.gradientEdit, stop: null };
8064
9203
  return { ok: true };
8065
9204
  }
@@ -8228,7 +9367,7 @@ var VectorEditorController = (_class5 = class {
8228
9367
  upGradient(drag) {
8229
9368
  const part = drag.part;
8230
9369
  if (!drag.moved) {
8231
- if (_optionalChain([part, 'optionalAccess', _210 => _210.kind]) === "bar") {
9370
+ if (_optionalChain([part, 'optionalAccess', _226 => _226.kind]) === "bar") {
8232
9371
  this.addGradientStop(part.offset);
8233
9372
  return;
8234
9373
  }
@@ -8247,7 +9386,7 @@ var VectorEditorController = (_class5 = class {
8247
9386
  const byNode = /* @__PURE__ */ new Map();
8248
9387
  for (const r of refs) {
8249
9388
  const node = this.getNode(r.nodeId);
8250
- if (_optionalChain([node, 'optionalAccess', _211 => _211.type]) !== "path" || !_optionalChain([node, 'access', _212 => _212.strokeWidthProfile, 'optionalAccess', _213 => _213[r.index]])) continue;
9389
+ if (_optionalChain([node, 'optionalAccess', _227 => _227.type]) !== "path" || !_optionalChain([node, 'access', _228 => _228.strokeWidthProfile, 'optionalAccess', _229 => _229[r.index]])) continue;
8251
9390
  byNode.set(r.nodeId, [..._nullishCoalesce(byNode.get(r.nodeId), () => ( [])), r.index]);
8252
9391
  }
8253
9392
  if (!byNode.size) return { ok: false, message: "There is no such width point." };
@@ -8265,12 +9404,12 @@ var VectorEditorController = (_class5 = class {
8265
9404
  }
8266
9405
  /** Selects width points (width tool); points on other paths than the first are dropped. */
8267
9406
  selectWidthPoints(refs) {
8268
- const first = _optionalChain([refs, 'access', _214 => _214[0], 'optionalAccess', _215 => _215.nodeId]);
9407
+ const first = _optionalChain([refs, 'access', _230 => _230[0], 'optionalAccess', _231 => _231.nodeId]);
8269
9408
  const next = [];
8270
9409
  for (const r of refs) {
8271
9410
  if (r.nodeId !== first || next.some((q) => q.index === r.index)) continue;
8272
9411
  const n = this.getNode(r.nodeId);
8273
- if (_optionalChain([n, 'optionalAccess', _216 => _216.type]) === "path" && _optionalChain([n, 'access', _217 => _217.strokeWidthProfile, 'optionalAccess', _218 => _218[r.index]])) next.push({ nodeId: r.nodeId, index: r.index, subpath: _nullishCoalesce(r.subpath, () => ( 0)) });
9412
+ if (_optionalChain([n, 'optionalAccess', _232 => _232.type]) === "path" && _optionalChain([n, 'access', _233 => _233.strokeWidthProfile, 'optionalAccess', _234 => _234[r.index]])) next.push({ nodeId: r.nodeId, index: r.index, subpath: _nullishCoalesce(r.subpath, () => ( 0)) });
8274
9413
  }
8275
9414
  this.widthPoints = next;
8276
9415
  this.notify();
@@ -8285,7 +9424,7 @@ var VectorEditorController = (_class5 = class {
8285
9424
  */
8286
9425
  setWidthPoint(target, values) {
8287
9426
  const node = this.getNode(target.nodeId);
8288
- if (_optionalChain([node, 'optionalAccess', _219 => _219.type]) !== "path") return { ok: false, message: "There is no such path." };
9427
+ if (_optionalChain([node, 'optionalAccess', _235 => _235.type]) !== "path") return { ok: false, message: "There is no such path." };
8289
9428
  const g = vectorStrokeWidthGeometry(node);
8290
9429
  if (!g || !(g.unit > 0)) return { ok: false, message: "The path has no visible stroke." };
8291
9430
  const num2 = (v2) => typeof v2 === "number" && Number.isFinite(v2) ? v2 : void 0;
@@ -8318,11 +9457,11 @@ var VectorEditorController = (_class5 = class {
8318
9457
  }
8319
9458
  }
8320
9459
  }
8321
- const subpath = _optionalChain([this, 'access', _220 => _220.widthEdit, 'optionalAccess', _221 => _221.nodeId]) === node.id ? this.widthEdit.subpath : _nullishCoalesce(_optionalChain([this, 'access', _222 => _222.widthPoints, 'access', _223 => _223.find, 'call', _224 => _224((r) => r.nodeId === node.id), 'optionalAccess', _225 => _225.subpath]), () => ( 0));
9460
+ const subpath = _optionalChain([this, 'access', _236 => _236.widthEdit, 'optionalAccess', _237 => _237.nodeId]) === node.id ? this.widthEdit.subpath : _nullishCoalesce(_optionalChain([this, 'access', _238 => _238.widthPoints, 'access', _239 => _239.find, 'call', _240 => _240((r) => r.nodeId === node.id), 'optionalAccess', _241 => _241.subpath]), () => ( 0));
8322
9461
  const edit = this.widthEdit;
8323
9462
  this.change("Width Point", () => this.replaceNode(node.id, withStyle(node, { strokeWidthProfile: points })));
8324
9463
  this.widthPoints = [{ nodeId: node.id, index, subpath }];
8325
- if (_optionalChain([edit, 'optionalAccess', _226 => _226.nodeId]) === node.id && (edit.index === existing || existing === null)) this.widthEdit = this.widthEditFor(node.id, subpath, index, null);
9464
+ if (_optionalChain([edit, 'optionalAccess', _242 => _242.nodeId]) === node.id && (edit.index === existing || existing === null)) this.widthEdit = this.widthEditFor(node.id, subpath, index, null);
8326
9465
  this.notify();
8327
9466
  return { ok: true };
8328
9467
  }
@@ -8356,7 +9495,7 @@ var VectorEditorController = (_class5 = class {
8356
9495
  /** The editor's view of point `index` (or of the stroke at `t` when index is null) of `nodeId`. */
8357
9496
  widthEditFor(nodeId, subpath, index, t) {
8358
9497
  const node = this.getNode(nodeId);
8359
- if (_optionalChain([node, 'optionalAccess', _227 => _227.type]) !== "path") return null;
9498
+ if (_optionalChain([node, 'optionalAccess', _243 => _243.type]) !== "path") return null;
8360
9499
  const g = vectorStrokeWidthGeometry(node);
8361
9500
  if (!g) return null;
8362
9501
  const profile = sanitizeWidthProfile(node.strokeWidthProfile);
@@ -8390,7 +9529,7 @@ var VectorEditorController = (_class5 = class {
8390
9529
  const refs = this.cornerTargets(options);
8391
9530
  if (!refs.length) return { ok: false, message: "Nothing is selected." };
8392
9531
  this.change("Corner Kind", () => {
8393
- this.doc = this.updateAnchors(this.doc, refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access', _228 => _228.corner, 'optionalAccess', _229 => _229.radius]), () => ( 0)), kind));
9532
+ this.doc = this.updateAnchors(this.doc, refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access', _244 => _244.corner, 'optionalAccess', _245 => _245.radius]), () => ( 0)), kind));
8394
9533
  });
8395
9534
  return { ok: true };
8396
9535
  }
@@ -8512,7 +9651,7 @@ var VectorEditorController = (_class5 = class {
8512
9651
  updateEffect(nodeId, effectId, patch, options = {}) {
8513
9652
  const merge = options.merge === true ? `effect:${nodeId}:${effectId}` : options.merge || void 0;
8514
9653
  const node = this.getNode(nodeId);
8515
- const current = _optionalChain([node, 'optionalAccess', _230 => _230.effects, 'optionalAccess', _231 => _231.find, 'call', _232 => _232((e) => e.id === effectId)]);
9654
+ const current = _optionalChain([node, 'optionalAccess', _246 => _246.effects, 'optionalAccess', _247 => _247.find, 'call', _248 => _248((e) => e.id === effectId)]);
8516
9655
  const label = current ? _nullishCoalesce(VECTOR_EFFECT_LABELS[current.type], () => ( "Effect")) : "Effect";
8517
9656
  return this.editEffects(
8518
9657
  nodeId,
@@ -8521,7 +9660,8 @@ var VectorEditorController = (_class5 = class {
8521
9660
  const i = list.findIndex((e2) => e2.id === effectId);
8522
9661
  if (i < 0) return `Node "${nodeId}" has no effect "${effectId}".`;
8523
9662
  const e = list[i];
8524
- const params = patch.params ? normalizeVectorEffectParams(e.type, patch.params, e.params) : e.params;
9663
+ const raw = patch.params && e.type === "envelope" && node ? this.envelopeParams(node, e, patch.params) : patch.params;
9664
+ const params = raw ? normalizeVectorEffectParams(e.type, raw, e.params) : e.params;
8525
9665
  const next = { ...e, params, ...patch.enabled !== void 0 ? { enabled: patch.enabled } : {} };
8526
9666
  if (next.enabled !== false) delete next.enabled;
8527
9667
  return list.map((x, j) => j === i ? next : x);
@@ -8645,10 +9785,10 @@ var VectorEditorController = (_class5 = class {
8645
9785
  return this.selection.filter((id) => {
8646
9786
  let covered = false;
8647
9787
  const loc = locateVectorNode(this.doc.nodes, id);
8648
- let parent = _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _233 => _233.parent]), () => ( null));
9788
+ let parent = _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _249 => _249.parent]), () => ( null));
8649
9789
  while (parent) {
8650
9790
  if (this.selection.includes(parent.id)) covered = true;
8651
- parent = _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _234 => _234(this.doc.nodes, parent.id), 'optionalAccess', _235 => _235.parent]), () => ( null));
9791
+ parent = _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _250 => _250(this.doc.nodes, parent.id), 'optionalAccess', _251 => _251.parent]), () => ( null));
8652
9792
  }
8653
9793
  return !covered;
8654
9794
  });
@@ -8661,6 +9801,318 @@ var VectorEditorController = (_class5 = class {
8661
9801
  if (!angle) return m;
8662
9802
  return multiplyMatrices(multiplyMatrices(rotateMatrix(-angle), m), rotateMatrix(angle));
8663
9803
  }
9804
+ /** The selection frame's corners in document space, clockwise from the top left. */
9805
+ frameCorners(frame2) {
9806
+ const rot = rotateMatrix(frame2.angle);
9807
+ return vectorBoxCorners(frame2).map((c) => frame2.angle ? applyMatrix(rot, c) : c);
9808
+ }
9809
+ /** `doc` with nodes `ids` sent through `f` (a map of document space), each in its own space (see `distortVectorNode`). */
9810
+ distorted(doc, ids, f, tolerance = VECTOR_DISTORT_TOLERANCE) {
9811
+ const visit = (list, parent) => {
9812
+ let changed = false;
9813
+ const out = list.map((n) => {
9814
+ let next = n;
9815
+ if (ids.has(n.id) && !n.locked) next = distortVectorNode(n, parent, f, tolerance);
9816
+ else if (n.type === "group") {
9817
+ const children = visit(n.children, multiplyMatrices(nodeMatrix(n), parent));
9818
+ if (children !== n.children) next = { ...n, children };
9819
+ }
9820
+ if (next !== n) changed = true;
9821
+ return next;
9822
+ });
9823
+ return changed ? out : list;
9824
+ };
9825
+ const nodes = visit(doc.nodes, IDENTITY_MATRIX);
9826
+ return nodes === doc.nodes ? doc : { ...doc, nodes };
9827
+ }
9828
+ /**
9829
+ * Free Distort mode of the selection box (`state.freeDistort`): dragging a corner distorts the
9830
+ * selection in perspective, each corner on its own (Shift+Alt+Mod: symmetric perspective, the
9831
+ * corner beside it moving the other way); dragging a side moves its two corners; Mod-dragging a
9832
+ * side skews along it (Alt: about the centre). Each drag is one undo step.
9833
+ */
9834
+ setFreeDistort(on) {
9835
+ if (this.freeDistort === on) return;
9836
+ this.freeDistort = on;
9837
+ this.notify();
9838
+ }
9839
+ /**
9840
+ * Distorts the selected (or given) nodes so the corners of their selection box (clockwise from
9841
+ * the top left, in the box's own rotation) land on `corners` (document space): a projective map,
9842
+ * so straight lines stay straight. Curves are followed within `tolerance` (document units).
9843
+ * One undo step.
9844
+ */
9845
+ distort(corners2, options = {}) {
9846
+ const ids = _nullishCoalesce(options.ids, () => ( this.selectedRoots()));
9847
+ const frame2 = this.frameOf(ids);
9848
+ if (!frame2) return { ok: false, message: "Nothing is selected." };
9849
+ if (!(frame2.width > 0 && frame2.height > 0)) return { ok: false, message: "The selection has no area to distort." };
9850
+ const from = this.frameCorners(frame2);
9851
+ const h = corners2.length === 4 ? vectorHomography(from, corners2) : null;
9852
+ if (!h || !vectorHomographyKeepsQuad(h, from)) return { ok: false, message: "The four corners must make a convex quadrilateral, clockwise from the top left." };
9853
+ this.change("Distort", () => {
9854
+ this.doc = this.distorted(this.doc, new Set(ids), (p) => _nullishCoalesce(applyVectorHomography(h, p), () => ( p)), options.tolerance);
9855
+ });
9856
+ return { ok: true };
9857
+ }
9858
+ /**
9859
+ * Skews the selected (or given) nodes along the selection box's own axes by `ax` degrees
9860
+ * horizontally (x' = x + tan(ax)·y: vertical lines lean right for positive angles) and `ay`
9861
+ * vertically, about `origin` (default: the box centre, document space). One undo step.
9862
+ */
9863
+ skew(ax, ay = 0, options = {}) {
9864
+ const frame2 = this.frameOf(_nullishCoalesce(options.ids, () => ( this.selectedRoots())));
9865
+ if (!frame2) return { ok: false, message: "Nothing is selected." };
9866
+ if (![ax, ay].every((v2) => Number.isFinite(v2) && Math.abs(v2) < 89.9)) return { ok: false, message: "Skew angles must be between \u221289.9\xB0 and 89.9\xB0." };
9867
+ const origin = applyMatrix(rotateMatrix(-frame2.angle), _nullishCoalesce(options.origin, () => ( this.frameCenter(frame2))));
9868
+ return this.transform(this.inFrame(frame2.angle, vectorSkewMatrix(ax, ay, origin)), { ids: options.ids, label: "Skew" });
9869
+ }
9870
+ /** A selection box handle dragged in Free Distort mode. */
9871
+ moveDistort(drag, p, input) {
9872
+ const angle = drag.frame.angle;
9873
+ const unrotate = (v2) => angle ? applyMatrix(rotateMatrix(-angle), v2) : v2;
9874
+ const q = unrotate(p);
9875
+ const q0 = unrotate(drag.start);
9876
+ const d = { x: q.x - q0.x, y: q.y - q0.y };
9877
+ const ids = new Set(this.selectedRoots());
9878
+ const from = this.frameCorners(drag.frame);
9879
+ const corner = drag.handle.length === 2;
9880
+ this.setGuides(null);
9881
+ if (!corner && input.mod) {
9882
+ const m = this.inFrame(angle, vectorShearForSide(drag.frame, drag.handle, d, !!input.alt));
9883
+ drag.op = "Skew";
9884
+ this.doc = this.transformed(drag.base, ids, m);
9885
+ this.interaction = { type: "distort", mode: "skew", corners: from.map((c) => applyMatrix(m, c)) };
9886
+ this.notify(true);
9887
+ return;
9888
+ }
9889
+ const mode = corner && input.mod && input.alt && input.shift ? "perspective" : "distort";
9890
+ const rot = rotateMatrix(angle);
9891
+ const quad = vectorDistortQuad(drag.frame, drag.handle, d, mode).map((c) => angle ? applyMatrix(rot, c) : c);
9892
+ const h = vectorHomography(from, quad);
9893
+ if (!h || !vectorHomographyKeepsQuad(h, from)) return;
9894
+ drag.op = mode === "perspective" ? "Perspective" : "Distort";
9895
+ this.doc = this.distorted(drag.base, ids, (pt2) => _nullishCoalesce(applyVectorHomography(h, pt2), () => ( pt2)));
9896
+ this.interaction = { type: "distort", mode, corners: quad };
9897
+ this.notify(true);
9898
+ }
9899
+ // -------------------------------------------------------------------------
9900
+ // Envelopes
9901
+ // -------------------------------------------------------------------------
9902
+ /** Selected (or given) roots that can carry an envelope. */
9903
+ envelopeTargets(ids) {
9904
+ return this.effectTargets(ids).filter((n) => !n.locked);
9905
+ }
9906
+ /** Envelope parameters for `node` after `patch`: a preset switched to a mesh becomes the mesh it stood for. */
9907
+ envelopeParams(node, current, patch) {
9908
+ if (patch.style !== "mesh" || patch.mesh !== void 0 || !current || current.params.style === "mesh") return patch;
9909
+ const frame2 = vectorEnvelopeFrame(node, current.id);
9910
+ if (!frame2) return patch;
9911
+ const rows = typeof patch.rows === "number" ? patch.rows : current.params.rows;
9912
+ const columns = typeof patch.columns === "number" ? patch.columns : current.params.columns;
9913
+ return { ...patch, mesh: resizeVectorMesh(frame2.mesh, columns, rows) };
9914
+ }
9915
+ /**
9916
+ * Gives the selected (or given) nodes an envelope distortion, or changes the one they have: a
9917
+ * warp preset (`style` with `bend`, `horizontal` and `vertical` in percent and `orientation`) or
9918
+ * a mesh (`style: 'mesh'` with `rows` and `columns`, and optionally its `mesh` points). The
9919
+ * envelope stays live (an `envelope` effect: edit it with the Envelope tool, Expand Appearance
9920
+ * bakes it). One undo step (with `merge`, consecutive changes fold into one, as a slider drag
9921
+ * should). Returns the envelope of each node.
9922
+ */
9923
+ envelope(params = {}, options = {}) {
9924
+ const targets = this.envelopeTargets(options.ids);
9925
+ if (!targets.length) return [];
9926
+ const out = [];
9927
+ const next = /* @__PURE__ */ new Map();
9928
+ const raw = params;
9929
+ for (const node of targets) {
9930
+ const list = _nullishCoalesce(node.effects, () => ( []));
9931
+ const current = _nullishCoalesce(list.find((e) => e.type === "envelope"), () => ( null));
9932
+ if (current) {
9933
+ const p = normalizeVectorEffectParams("envelope", this.envelopeParams(node, current, raw), current.params);
9934
+ const { enabled: _e, ...rest } = current;
9935
+ next.set(node.id, { ...node, effects: list.map((e) => e === current ? { ...rest, params: p } : e) });
9936
+ out.push({ nodeId: node.id, effectId: current.id });
9937
+ } else {
9938
+ let k = list.length + 1;
9939
+ while (list.some((e) => e.id === `fx${k}`)) k++;
9940
+ const effect = createVectorEffect("envelope", `fx${k}`, raw);
9941
+ next.set(node.id, { ...node, effects: [...list, effect] });
9942
+ out.push({ nodeId: node.id, effectId: effect.id });
9943
+ }
9944
+ }
9945
+ const made = out.some((o) => !_optionalChain([targets, 'access', _252 => _252.find, 'call', _253 => _253((n) => n.id === o.nodeId), 'optionalAccess', _254 => _254.effects, 'optionalAccess', _255 => _255.some, 'call', _256 => _256((e) => e.id === o.effectId)]));
9946
+ const merge = options.merge ? `envelope:${out.map((o) => o.nodeId).join(",")}` : void 0;
9947
+ this.change(made ? params.style === "mesh" ? "Make Envelope with Mesh" : "Make Envelope with Warp" : "Edit Envelope", () => this.setDoc(mapTree(this.doc.nodes, (n) => _nullishCoalesce(next.get(n.id), () => ( n)))), merge);
9948
+ return out;
9949
+ }
9950
+ /**
9951
+ * Make with Top Object: the topmost selected object's outline (a closed path) becomes the envelope
9952
+ * of the other selected objects (grouped when there are several; they must share a parent), as a
9953
+ * mesh of `columns × rows` patches whose border follows the outline. The top object is used up.
9954
+ * One undo step; returns the id of the enveloped node.
9955
+ */
9956
+ makeEnvelopeWithTopObject(options = {}) {
9957
+ const ids = _nullishCoalesce(options.ids, () => ( this.selectedRoots()));
9958
+ if (ids.length < 2) return { ok: false, message: "Select the objects and, on top of them, the shape to use as the envelope." };
9959
+ const order = /* @__PURE__ */ new Map();
9960
+ walkVectorNodes(this.doc.nodes, (n) => order.set(n.id, order.size));
9961
+ const sorted = ids.filter((id) => order.has(id)).sort((a, b) => order.get(a) - order.get(b));
9962
+ const topId = sorted[sorted.length - 1];
9963
+ const top = this.getNode(topId);
9964
+ const outline = _optionalChain([top, 'optionalAccess', _257 => _257.type]) === "path" ? top.subpaths.find((sp) => sp.closed && sp.anchors.length > 1) : void 0;
9965
+ if (!top || !outline) return { ok: false, message: "The top object must be a path with a closed outline." };
9966
+ const contents = sorted.slice(0, -1).map((id) => this.getNode(id));
9967
+ if (contents.some((n) => n.locked)) return { ok: false, message: "Locked objects cannot be enveloped." };
9968
+ const parents = contents.map((n) => _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _258 => _258(this.doc.nodes, n.id), 'optionalAccess', _259 => _259.parent, 'optionalAccess', _260 => _260.id]), () => ( null)));
9969
+ if (parents.some((p) => p !== parents[0])) return { ok: false, message: "The objects to envelope must be in the same group." };
9970
+ const target = contents.length === 1 ? contents[0] : { id: this.newId(), type: "group", name: "Envelope", children: contents.map((n) => n) };
9971
+ const parentToDoc = parents[0] ? this.worldOf(parents[0]) : IDENTITY_MATRIX;
9972
+ const targetToDoc = multiplyMatrices(nodeMatrix(target), parentToDoc);
9973
+ const toLocal = multiplyMatrices(this.worldOf(topId), invertMatrix(targetToDoc));
9974
+ const local = {
9975
+ closed: true,
9976
+ anchors: outline.anchors.map((a) => ({
9977
+ ...applyMatrix(toLocal, a),
9978
+ ...a.in ? { in: applyMatrix(toLocal, a.in) } : {},
9979
+ ...a.out ? { out: applyMatrix(toLocal, a.out) } : {}
9980
+ }))
9981
+ };
9982
+ const mesh = vectorMeshFromOutline(local, _nullishCoalesce(options.columns, () => ( 4)), _nullishCoalesce(options.rows, () => ( 4)));
9983
+ if (!mesh) return { ok: false, message: "The top object\u2019s outline is too small to use as an envelope." };
9984
+ const list = _nullishCoalesce(target.effects, () => ( []));
9985
+ let k = list.length + 1;
9986
+ while (list.some((e) => e.id === `fx${k}`)) k++;
9987
+ const effect = createVectorEffect("envelope", `fx${k}`, { style: "mesh", mesh });
9988
+ const enveloped = { ...target, effects: [...list, effect] };
9989
+ this.change("Make Envelope with Top Object", () => {
9990
+ let nodes = spliceTree(this.doc.nodes, topId, []);
9991
+ if (contents.length === 1) nodes = spliceTree(nodes, target.id, [enveloped]);
9992
+ else {
9993
+ const last = contents[contents.length - 1].id;
9994
+ for (const n of contents.slice(0, -1)) nodes = spliceTree(nodes, n.id, []);
9995
+ nodes = spliceTree(nodes, last, [enveloped]);
9996
+ }
9997
+ this.setDoc(nodes);
9998
+ this.selection = [target.id];
9999
+ this.anchors = [];
10000
+ this.editingId = null;
10001
+ });
10002
+ return { ok: true, nodeId: target.id };
10003
+ }
10004
+ /**
10005
+ * Release: the selected (or given) nodes lose their envelope, and its shape (the mesh's border)
10006
+ * comes back as a path above each of them. One undo step; returns the new paths' ids.
10007
+ */
10008
+ releaseEnvelope(options = {}) {
10009
+ const targets = this.envelopeTargets(options.ids).filter((n) => _optionalChain([n, 'access', _261 => _261.effects, 'optionalAccess', _262 => _262.some, 'call', _263 => _263((e) => e.type === "envelope")]));
10010
+ if (!targets.length) return [];
10011
+ const created = [];
10012
+ const replace = /* @__PURE__ */ new Map();
10013
+ for (const node of targets) {
10014
+ const effect = node.effects.find((e) => e.type === "envelope");
10015
+ const frame2 = vectorEnvelopeFrame(node, effect.id);
10016
+ const rest = node.effects.filter((e) => e !== effect);
10017
+ const { effects: _e, ...plain3 } = node;
10018
+ const kept = rest.length ? { ...plain3, effects: rest } : plain3;
10019
+ if (!frame2) {
10020
+ replace.set(node.id, [kept]);
10021
+ continue;
10022
+ }
10023
+ const id = this.newId();
10024
+ created.push(id);
10025
+ const shape = {
10026
+ id,
10027
+ type: "path",
10028
+ name: "Envelope",
10029
+ ...node.transform ? { transform: node.transform } : {},
10030
+ subpaths: [vectorMeshOutline(frame2.mesh)],
10031
+ fill: null,
10032
+ stroke: "#808080",
10033
+ strokeWidth: 1
10034
+ };
10035
+ replace.set(node.id, [kept, shape]);
10036
+ }
10037
+ this.change("Release Envelope", () => {
10038
+ let nodes = this.doc.nodes;
10039
+ for (const [id, list] of replace) nodes = spliceTree(nodes, id, list);
10040
+ this.setDoc(nodes);
10041
+ this.selection = [...targets.map((n) => n.id), ...created];
10042
+ this.anchors = [];
10043
+ });
10044
+ return created;
10045
+ }
10046
+ /** The selected node the Envelope tool edits, with its mesh (node space) and node → document matrix. */
10047
+ envelopeTarget() {
10048
+ const target = getVectorEnvelopeTarget(this.doc, this.selection);
10049
+ return target && !target.node.locked ? target : null;
10050
+ }
10051
+ /** The envelope mesh point under `screen` (handles first), or a spot inside the mesh. */
10052
+ hitEnvelope(screen, p) {
10053
+ const target = this.envelopeTarget();
10054
+ if (!target) return null;
10055
+ const { mesh } = target.frame;
10056
+ const pts = vectorMeshEditPoints(mesh);
10057
+ let best = null;
10058
+ let bestD = Infinity;
10059
+ for (const index of [...pts.handles.map((h) => h.index), ...pts.anchors]) {
10060
+ const s = this.documentToScreen(applyMatrix(target.world, mesh.points[index]));
10061
+ const d = Math.hypot(s.x - screen.x, s.y - screen.y);
10062
+ if (d <= this.hitRadius && d < bestD - 0.5) {
10063
+ best = index;
10064
+ bestD = d;
10065
+ }
10066
+ }
10067
+ if (best !== null) return { target, index: best, s: 0, t: 0 };
10068
+ const local = applyMatrix(invertMatrix(target.world), p);
10069
+ const at2 = vectorMeshParamAt(mesh, local);
10070
+ if (at2.distance > this.tolerance()) return null;
10071
+ return { target, index: null, s: at2.s, t: at2.t };
10072
+ }
10073
+ downEnvelope(screen, p, input) {
10074
+ const hit = this.hitEnvelope(screen, p);
10075
+ if (hit) {
10076
+ const { node: node2, frame: frame2 } = hit.target;
10077
+ this.drag = {
10078
+ kind: "envelope",
10079
+ nodeId: node2.id,
10080
+ effectId: frame2.effectId,
10081
+ base: frame2.mesh,
10082
+ baseDoc: this.doc,
10083
+ before: this.snapshot(),
10084
+ index: hit.index,
10085
+ s: hit.s,
10086
+ t: hit.t,
10087
+ start: this.toLocal(node2.id, p),
10088
+ moved: false
10089
+ };
10090
+ this.interaction = { type: "envelope", nodeId: node2.id, index: hit.index };
10091
+ this.notify();
10092
+ return;
10093
+ }
10094
+ const node = hitTestVectorNodes(this.doc.nodes, p, this.tolerance(), { entered: this.enteredGroups() });
10095
+ if (node) this.selection = input.shift ? this.selection.includes(node.id) ? this.selection.filter((id) => id !== node.id) : [...this.selection, node.id] : [node.id];
10096
+ else if (!input.shift) this.selection = [];
10097
+ this.anchors = [];
10098
+ this.notify();
10099
+ }
10100
+ moveEnvelope(drag, p) {
10101
+ const local = this.toLocal(drag.nodeId, p, drag.baseDoc);
10102
+ const d = { x: local.x - drag.start.x, y: local.y - drag.start.y };
10103
+ if (!drag.moved && Math.hypot(d.x, d.y) * this.viewport.zoom < 1) return;
10104
+ drag.moved = true;
10105
+ const mesh = drag.index !== null ? dragVectorMeshPoint(drag.base, drag.index, d) : pullVectorMesh(drag.base, drag.s, drag.t, d);
10106
+ const nodes = mapTree(drag.baseDoc.nodes, (n) => {
10107
+ if (n.id !== drag.nodeId) return n;
10108
+ const effects = (_nullishCoalesce(n.effects, () => ( []))).map(
10109
+ (e) => e.id === drag.effectId && e.type === "envelope" ? { ...e, params: { ...e.params, style: "mesh", mesh, columns: mesh.us.length - 1, rows: mesh.vs.length - 1 } } : e
10110
+ );
10111
+ return { ...n, effects };
10112
+ });
10113
+ this.doc = { ...drag.baseDoc, nodes };
10114
+ this.notify(true);
10115
+ }
8664
10116
  /** Applies a matrix to the selected (or given) nodes as one undo step. */
8665
10117
  transform(matrix, options = {}) {
8666
10118
  const ids = new Set(_nullishCoalesce(options.ids, () => ( this.selectedRoots())));
@@ -8831,8 +10283,8 @@ var VectorEditorController = (_class5 = class {
8831
10283
  if (!ids.length) return null;
8832
10284
  const locs = ids.map((id2) => locateVectorNode(this.doc.nodes, id2));
8833
10285
  if (locs.some((l) => !l)) return null;
8834
- const parent = _nullishCoalesce(_optionalChain([locs, 'access', _236 => _236[0], 'access', _237 => _237.parent, 'optionalAccess', _238 => _238.id]), () => ( null));
8835
- if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _239 => _239.parent, 'optionalAccess', _240 => _240.id]), () => ( null))) !== parent)) return null;
10286
+ const parent = _nullishCoalesce(_optionalChain([locs, 'access', _264 => _264[0], 'access', _265 => _265.parent, 'optionalAccess', _266 => _266.id]), () => ( null));
10287
+ if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _267 => _267.parent, 'optionalAccess', _268 => _268.id]), () => ( null))) !== parent)) return null;
8836
10288
  const id = this.newId();
8837
10289
  this.change("Group", () => {
8838
10290
  const set = new Set(ids);
@@ -8855,7 +10307,7 @@ var VectorEditorController = (_class5 = class {
8855
10307
  }
8856
10308
  /** Replaces selected groups with their children. */
8857
10309
  ungroup(options = {}) {
8858
- const groups = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _241 => _241.type]) === "group");
10310
+ const groups = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _269 => _269.type]) === "group");
8859
10311
  if (!groups.length) return { ok: false, message: "Select a group to ungroup." };
8860
10312
  const set = new Set(groups.map((g) => g.id));
8861
10313
  this.change("Ungroup", () => {
@@ -8955,7 +10407,7 @@ var VectorEditorController = (_class5 = class {
8955
10407
  this.change(label, () => this.replaceNode(lone.id, { ...lone, liveBoolean: op, children }));
8956
10408
  return lone.id;
8957
10409
  }
8958
- const parents = roots.map((id2) => _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _242 => _242(this.doc.nodes, id2), 'optionalAccess', _243 => _243.parent]), () => ( null)));
10410
+ const parents = roots.map((id2) => _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _270 => _270(this.doc.nodes, id2), 'optionalAccess', _271 => _271.parent]), () => ( null)));
8959
10411
  if (parents.every((g) => isVectorLiveBoolean(g))) {
8960
10412
  const set = new Set(roots);
8961
10413
  this.change(
@@ -8976,8 +10428,8 @@ var VectorEditorController = (_class5 = class {
8976
10428
  return parents[0].id;
8977
10429
  }
8978
10430
  if (nodes.length < 2) return null;
8979
- const parent = _nullishCoalesce(_optionalChain([parents, 'access', _244 => _244[0], 'optionalAccess', _245 => _245.id]), () => ( null));
8980
- if (parents.some((g) => (_nullishCoalesce(_optionalChain([g, 'optionalAccess', _246 => _246.id]), () => ( null))) !== parent)) return null;
10431
+ const parent = _nullishCoalesce(_optionalChain([parents, 'access', _272 => _272[0], 'optionalAccess', _273 => _273.id]), () => ( null));
10432
+ if (parents.some((g) => (_nullishCoalesce(_optionalChain([g, 'optionalAccess', _274 => _274.id]), () => ( null))) !== parent)) return null;
8981
10433
  const id = this.newId();
8982
10434
  this.change(label, () => {
8983
10435
  const set = new Set(roots);
@@ -9025,7 +10477,7 @@ var VectorEditorController = (_class5 = class {
9025
10477
  }
9026
10478
  /** Splits selected compound paths into one path per subpath. */
9027
10479
  breakApart(options = {}) {
9028
- const paths = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _247 => _247.type]) === "path" && n.subpaths.length > 1);
10480
+ const paths = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _275 => _275.type]) === "path" && n.subpaths.length > 1);
9029
10481
  if (!paths.length) return { ok: false, message: "Select a compound path to break apart." };
9030
10482
  const created = [];
9031
10483
  const set = new Set(paths.map((p) => p.id));
@@ -9093,7 +10545,7 @@ var VectorEditorController = (_class5 = class {
9093
10545
  const out = /* @__PURE__ */ new Map();
9094
10546
  for (const id of _nullishCoalesce(ids, () => ( this.selection))) {
9095
10547
  const node = this.getNode(id);
9096
- const group = isVectorBlendGroup(node) ? node : _optionalChain([locateVectorNode, 'call', _248 => _248(this.doc.nodes, id), 'optionalAccess', _249 => _249.parent]);
10548
+ const group = isVectorBlendGroup(node) ? node : _optionalChain([locateVectorNode, 'call', _276 => _276(this.doc.nodes, id), 'optionalAccess', _277 => _277.parent]);
9097
10549
  if (isVectorBlendGroup(group)) out.set(group.id, group);
9098
10550
  }
9099
10551
  return [...out.values()];
@@ -9111,8 +10563,8 @@ var VectorEditorController = (_class5 = class {
9111
10563
  });
9112
10564
  if (ids.length < 2) return null;
9113
10565
  const locs = ids.map((id2) => locateVectorNode(this.doc.nodes, id2));
9114
- const parent = _nullishCoalesce(_optionalChain([locs, 'access', _250 => _250[0], 'access', _251 => _251.parent, 'optionalAccess', _252 => _252.id]), () => ( null));
9115
- if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _253 => _253.parent, 'optionalAccess', _254 => _254.id]), () => ( null))) !== parent)) return null;
10566
+ const parent = _nullishCoalesce(_optionalChain([locs, 'access', _278 => _278[0], 'access', _279 => _279.parent, 'optionalAccess', _280 => _280.id]), () => ( null));
10567
+ if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _281 => _281.parent, 'optionalAccess', _282 => _282.id]), () => ( null))) !== parent)) return null;
9116
10568
  const order = input.keepOrder ? ids : ids.slice().sort((a, b) => locs[ids.indexOf(a)].index - locs[ids.indexOf(b)].index);
9117
10569
  const blend = blendOptionsOf({ ...this.blendDefaults, ...input });
9118
10570
  if (input.starts) {
@@ -9154,7 +10606,7 @@ var VectorEditorController = (_class5 = class {
9154
10606
  const node = this.getNode(nodeId);
9155
10607
  if (!isVectorBlendGroup(group)) return { ok: false, message: `"${blendId}" is not a blend.` };
9156
10608
  if (!node || node.blendStep || node.locked || node.id === blendId) return { ok: false, message: `"${nodeId}" cannot be a key.` };
9157
- const parentOf = (id) => _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _255 => _255(this.doc.nodes, id), 'optionalAccess', _256 => _256.parent, 'optionalAccess', _257 => _257.id]), () => ( null));
10609
+ const parentOf = (id) => _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _283 => _283(this.doc.nodes, id), 'optionalAccess', _284 => _284.parent, 'optionalAccess', _285 => _285.id]), () => ( null));
9158
10610
  if (parentOf(blendId) !== parentOf(nodeId)) return { ok: false, message: "The new key must sit beside the blend (same parent)." };
9159
10611
  const start = options.start;
9160
10612
  this.change("Blend", () => {
@@ -9224,7 +10676,7 @@ var VectorEditorController = (_class5 = class {
9224
10676
  replaceBlendSpine(options = {}) {
9225
10677
  const roots = _nullishCoalesce(options.ids, () => ( this.selectedRoots()));
9226
10678
  const groups = this.blendTargets(roots);
9227
- const paths = roots.map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _258 => _258.type]) === "path" && !n.blendStep && !isVectorBlendGroup(_optionalChain([locateVectorNode, 'call', _259 => _259(this.doc.nodes, n.id), 'optionalAccess', _260 => _260.parent])));
10679
+ const paths = roots.map((id) => this.getNode(id)).filter((n) => _optionalChain([n, 'optionalAccess', _286 => _286.type]) === "path" && !n.blendStep && !isVectorBlendGroup(_optionalChain([locateVectorNode, 'call', _287 => _287(this.doc.nodes, n.id), 'optionalAccess', _288 => _288.parent])));
9228
10680
  if (groups.length !== 1 || paths.length !== 1) return { ok: false, message: "Select one blend and one path to be its spine." };
9229
10681
  const group = groups[0];
9230
10682
  const path = paths[0];
@@ -9255,7 +10707,7 @@ var VectorEditorController = (_class5 = class {
9255
10707
  shapeBuilderMap(ids) {
9256
10708
  const roots = _nullishCoalesce(ids, () => ( this.selectedRoots()));
9257
10709
  const key = roots.join("\0");
9258
- if (_optionalChain([this, 'access', _261 => _261.builderCache, 'optionalAccess', _262 => _262.doc]) === this.doc && this.builderCache.key === key) return this.builderCache.map;
10710
+ if (_optionalChain([this, 'access', _289 => _289.builderCache, 'optionalAccess', _290 => _290.doc]) === this.doc && this.builderCache.key === key) return this.builderCache.map;
9259
10711
  const entries = roots.length ? vectorPathEntries(this.doc, roots, { expand: false }) : [];
9260
10712
  const map = entries.length ? vectorShapeBuilderMap(entries) : null;
9261
10713
  this.builderCache = { doc: this.doc, key, map };
@@ -9315,9 +10767,9 @@ var VectorEditorController = (_class5 = class {
9315
10767
  const list = [];
9316
10768
  const r = plan.replace.get(i);
9317
10769
  if (r === void 0) list.push(node);
9318
- else if (_optionalChain([r, 'optionalAccess', _263 => _263.kind]) === "fill") list.push({ ...node, fillRule: "nonzero", subpaths: bezierToSubpaths(toLocal(r.path)) });
9319
- else if (_optionalChain([r, 'optionalAccess', _264 => _264.kind]) === "outline") list.push({ ...node, subpaths: bezierToSubpaths(toLocal(r.path)) });
9320
- else if (_optionalChain([r, 'optionalAccess', _265 => _265.kind]) === "pieces") {
10770
+ else if (_optionalChain([r, 'optionalAccess', _291 => _291.kind]) === "fill") list.push({ ...node, fillRule: "nonzero", subpaths: bezierToSubpaths(toLocal(r.path)) });
10771
+ else if (_optionalChain([r, 'optionalAccess', _292 => _292.kind]) === "outline") list.push({ ...node, subpaths: bezierToSubpaths(toLocal(r.path)) });
10772
+ else if (_optionalChain([r, 'optionalAccess', _293 => _293.kind]) === "pieces") {
9321
10773
  r.paths.forEach(
9322
10774
  (path, k) => list.push({ ...node, id: k === 0 ? node.id : this.newId(), subpaths: bezierToSubpaths(toLocal(path)).map((sp) => ({ ...sp, closed: false })) })
9323
10775
  );
@@ -9351,7 +10803,7 @@ var VectorEditorController = (_class5 = class {
9351
10803
  }
9352
10804
  /** The paint bucket's map of the visible outlines, cached per document and gap. */
9353
10805
  fillMap(gap) {
9354
- if (_optionalChain([this, 'access', _266 => _266.fillCache, 'optionalAccess', _267 => _267.doc]) === this.doc && this.fillCache.gap === gap) return this.fillCache.map;
10806
+ if (_optionalChain([this, 'access', _294 => _294.fillCache, 'optionalAccess', _295 => _295.doc]) === this.doc && this.fillCache.gap === gap) return this.fillCache.map;
9355
10807
  const map = vectorFillMap(this.doc, gap);
9356
10808
  this.fillCache = { doc: this.doc, gap, map };
9357
10809
  return map;
@@ -9365,8 +10817,8 @@ var VectorEditorController = (_class5 = class {
9365
10817
  */
9366
10818
  fillRegion(point, options = {}) {
9367
10819
  if (!Number.isFinite(point.x) || !Number.isFinite(point.y)) return null;
9368
- const region = _optionalChain([this, 'access', _268 => _268.fillMap, 'call', _269 => _269(_nullishCoalesce(options.gap, () => ( this.editing.fillGap))), 'optionalAccess', _270 => _270.regionAt, 'call', _271 => _271([point.x, point.y])]);
9369
- if (!_optionalChain([region, 'optionalAccess', _272 => _272.length])) return null;
10820
+ const region = _optionalChain([this, 'access', _296 => _296.fillMap, 'call', _297 => _297(_nullishCoalesce(options.gap, () => ( this.editing.fillGap))), 'optionalAccess', _298 => _298.regionAt, 'call', _299 => _299([point.x, point.y])]);
10821
+ if (!_optionalChain([region, 'optionalAccess', _300 => _300.length])) return null;
9370
10822
  let below = null;
9371
10823
  const roots = new Set(this.selectedRoots());
9372
10824
  walkVectorNodes(this.doc.nodes, (n) => {
@@ -9392,7 +10844,7 @@ var VectorEditorController = (_class5 = class {
9392
10844
  /** Updates the Shape Builder / paint bucket highlight for the pointer at `p`; true when it changed. */
9393
10845
  hoverBuilder(p, alt) {
9394
10846
  if (this.tool === "paintBucket") {
9395
- const region = _nullishCoalesce(_optionalChain([this, 'access', _273 => _273.fillMap, 'call', _274 => _274(this.editing.fillGap), 'optionalAccess', _275 => _275.regionAt, 'call', _276 => _276([p.x, p.y])]), () => ( null));
10847
+ const region = _nullishCoalesce(_optionalChain([this, 'access', _301 => _301.fillMap, 'call', _302 => _302(this.editing.fillGap), 'optionalAccess', _303 => _303.regionAt, 'call', _304 => _304([p.x, p.y])]), () => ( null));
9396
10848
  const key2 = region ? _chunkVNYRI265cjs.bezierPathToSvg.call(void 0, region, { precision: 2 }) : null;
9397
10849
  if (key2 === this.builderHoverKey) return false;
9398
10850
  this.builderHoverKey = key2;
@@ -9500,7 +10952,7 @@ var VectorEditorController = (_class5 = class {
9500
10952
  /** `doc` with anchor `ref` moved to document point `to` by a Curvature-tool move. */
9501
10953
  curvatureMoved(doc, ref, to) {
9502
10954
  const node = findVectorNode(doc.nodes, ref.nodeId);
9503
- if (_optionalChain([node, 'optionalAccess', _277 => _277.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
10955
+ if (_optionalChain([node, 'optionalAccess', _305 => _305.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
9504
10956
  const q = this.toLocal(ref.nodeId, to, doc);
9505
10957
  const subpaths = node.subpaths.map((sp, i) => i === ref.subpath ? curvatureMoveAnchor(sp, ref.index, q) : sp);
9506
10958
  const nodes = mapTree(doc.nodes, (n) => n.id === ref.nodeId ? { ...node, subpaths } : n);
@@ -9509,7 +10961,7 @@ var VectorEditorController = (_class5 = class {
9509
10961
  /** `doc` with segment `ref` bent through document point `p` at parameter `t`. */
9510
10962
  bent(doc, ref, t, p) {
9511
10963
  const node = findVectorNode(doc.nodes, ref.nodeId);
9512
- if (_optionalChain([node, 'optionalAccess', _278 => _278.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
10964
+ if (_optionalChain([node, 'optionalAccess', _306 => _306.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
9513
10965
  const q = this.toLocal(ref.nodeId, p, doc);
9514
10966
  const subpaths = node.subpaths.map((sp, i) => i === ref.subpath ? bendSegment(sp, ref.segment, t, q) : sp);
9515
10967
  return { ...doc, nodes: mapTree(doc.nodes, (n) => n.id === ref.nodeId ? { ...node, subpaths } : n) };
@@ -9520,7 +10972,7 @@ var VectorEditorController = (_class5 = class {
9520
10972
  */
9521
10973
  bendSegment(ref, to, t = 0.5) {
9522
10974
  const node = this.getNode(ref.nodeId);
9523
- const sp = _optionalChain([node, 'optionalAccess', _279 => _279.type]) === "path" ? node.subpaths[ref.subpath] : void 0;
10975
+ const sp = _optionalChain([node, 'optionalAccess', _307 => _307.type]) === "path" ? node.subpaths[ref.subpath] : void 0;
9524
10976
  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." };
9525
10977
  if (node.locked) return { ok: false, message: "The path is locked." };
9526
10978
  this.change("Bend Segment", () => {
@@ -9555,7 +11007,7 @@ var VectorEditorController = (_class5 = class {
9555
11007
  /** Adds an anchor on the nearest segment of `nodeId` to document point `point` (shape unchanged). */
9556
11008
  insertAnchorAt(nodeId, point) {
9557
11009
  const node = this.getNode(nodeId);
9558
- if (_optionalChain([node, 'optionalAccess', _280 => _280.type]) !== "path") return null;
11010
+ if (_optionalChain([node, 'optionalAccess', _308 => _308.type]) !== "path") return null;
9559
11011
  const hit = nearestSegment(node, this.toLocal(nodeId, point));
9560
11012
  if (!hit) return null;
9561
11013
  const { subpath, index } = insertAnchor(node.subpaths[hit.subpath], hit.segment, hit.t);
@@ -9599,7 +11051,7 @@ var VectorEditorController = (_class5 = class {
9599
11051
  setClosed(closed, nodeId) {
9600
11052
  const targets = nodeId ? (() => {
9601
11053
  const n = this.getNode(nodeId);
9602
- return _optionalChain([n, 'optionalAccess', _281 => _281.type]) === "path" ? n.subpaths.map((_, s) => ({ nodeId, subpath: s })) : [];
11054
+ return _optionalChain([n, 'optionalAccess', _309 => _309.type]) === "path" ? n.subpaths.map((_, s) => ({ nodeId, subpath: s })) : [];
9603
11055
  })() : this.anchors.map((r) => ({ nodeId: r.nodeId, subpath: r.subpath }));
9604
11056
  if (!targets.length) return { ok: false, message: "Select a path or points." };
9605
11057
  this.change(closed ? "Close Path" : "Open Path", () => {
@@ -9620,7 +11072,7 @@ var VectorEditorController = (_class5 = class {
9620
11072
  this.setDoc(
9621
11073
  mapTree(
9622
11074
  this.doc.nodes,
9623
- (n) => n.type === "path" && set.has(n.id) ? { ...n, subpaths: n.subpaths.map(reverseSubpath), ..._optionalChain([n, 'access', _282 => _282.strokeWidthProfile, 'optionalAccess', _283 => _283.length]) ? { strokeWidthProfile: reverseWidthProfile(n.strokeWidthProfile) } : {} } : n
11075
+ (n) => n.type === "path" && set.has(n.id) ? { ...n, subpaths: n.subpaths.map(reverseSubpath), ..._optionalChain([n, 'access', _310 => _310.strokeWidthProfile, 'optionalAccess', _311 => _311.length]) ? { strokeWidthProfile: reverseWidthProfile(n.strokeWidthProfile) } : {} } : n
9624
11076
  )
9625
11077
  );
9626
11078
  this.anchors = [];
@@ -9758,7 +11210,7 @@ var VectorEditorController = (_class5 = class {
9758
11210
  */
9759
11211
  cutPathAt(nodeId, point) {
9760
11212
  const node = this.getNode(nodeId);
9761
- if (_optionalChain([node, 'optionalAccess', _284 => _284.type]) !== "path" || node.locked) return null;
11213
+ if (_optionalChain([node, 'optionalAccess', _312 => _312.type]) !== "path" || node.locked) return null;
9762
11214
  const local = this.toLocal(nodeId, point);
9763
11215
  const hit = nearestSegment(node, local);
9764
11216
  if (!hit) return null;
@@ -9808,8 +11260,8 @@ var VectorEditorController = (_class5 = class {
9808
11260
  if (n.visible === false || n.locked || parent && blocked.has(parent.id)) blocked.add(n.id);
9809
11261
  });
9810
11262
  const visible = (p) => !blocked.has(p.id);
9811
- if (_optionalChain([ids, 'optionalAccess', _285 => _285.length]) || this.selection.length) return this.pathTargets(_nullishCoalesce(ids, () => ( this.selection))).filter(visible);
9812
- const box = polylineBounds(points.map(toPoint2), pad);
11263
+ if (_optionalChain([ids, 'optionalAccess', _313 => _313.length]) || this.selection.length) return this.pathTargets(_nullishCoalesce(ids, () => ( this.selection))).filter(visible);
11264
+ const box = polylineBounds(points.map(toPoint3), pad);
9813
11265
  if (!box) return [];
9814
11266
  const out = [];
9815
11267
  walkVectorNodes(this.doc.nodes, (n) => {
@@ -9822,7 +11274,7 @@ var VectorEditorController = (_class5 = class {
9822
11274
  /** A stroke's points in node `id`'s own space. */
9823
11275
  localPoints(id, points) {
9824
11276
  const inv = invertMatrix(this.worldOf(id));
9825
- return points.map((p) => toPoint2(applyMatrix(inv, p)));
11277
+ return points.map((p) => toPoint3(applyMatrix(inv, p)));
9826
11278
  }
9827
11279
  /**
9828
11280
  * Knife: cuts closed paths along the polyline `points` (document space) wherever it crosses
@@ -9831,7 +11283,7 @@ var VectorEditorController = (_class5 = class {
9831
11283
  * when nothing was cut).
9832
11284
  */
9833
11285
  knife(points, options = {}) {
9834
- const pts = simplifyPolyline(points.map(toPoint2), 0.25 / this.viewport.zoom).map(([x, y]) => ({ x, y }));
11286
+ const pts = simplifyPolyline(points.map(toPoint3), 0.25 / this.viewport.zoom).map(([x, y]) => ({ x, y }));
9835
11287
  if (pts.length < 2) return [];
9836
11288
  const plan = [];
9837
11289
  for (const node of this.strokeTargets(pts, options.ids, 0)) {
@@ -9860,7 +11312,7 @@ var VectorEditorController = (_class5 = class {
9860
11312
  erase(points, options = {}) {
9861
11313
  const width = _nullishCoalesce(options.size, () => ( this.editing.eraserSize));
9862
11314
  if (!(width > 0) || !points.length) return [];
9863
- const pts = simplifyPolyline(points.map(toPoint2), Math.min(width * 0.05, 0.25 / this.viewport.zoom));
11315
+ const pts = simplifyPolyline(points.map(toPoint3), Math.min(width * 0.05, 0.25 / this.viewport.zoom));
9864
11316
  const region = eraserRegion(pts, width);
9865
11317
  if (!region.length) return [];
9866
11318
  const plan = [];
@@ -9894,7 +11346,7 @@ var VectorEditorController = (_class5 = class {
9894
11346
  finishPath() {
9895
11347
  if (!this.pen) return;
9896
11348
  const node = this.getNode(this.pen.nodeId);
9897
- const sp = _optionalChain([node, 'optionalAccess', _286 => _286.subpaths, 'access', _287 => _287[this.pen.subpath]]);
11349
+ const sp = _optionalChain([node, 'optionalAccess', _314 => _314.subpaths, 'access', _315 => _315[this.pen.subpath]]);
9898
11350
  const pen = this.pen;
9899
11351
  this.pen = null;
9900
11352
  this.pointer = null;
@@ -9938,7 +11390,7 @@ var VectorEditorController = (_class5 = class {
9938
11390
  if (trimmed.startsWith("{")) {
9939
11391
  try {
9940
11392
  const data = JSON.parse(trimmed);
9941
- if (_optionalChain([data, 'optionalAccess', _288 => _288.type]) === VECTOR_CLIPBOARD_TYPE && Array.isArray(data.nodes)) nodes = data.nodes;
11393
+ if (_optionalChain([data, 'optionalAccess', _316 => _316.type]) === VECTOR_CLIPBOARD_TYPE && Array.isArray(data.nodes)) nodes = data.nodes;
9942
11394
  } catch (e7) {
9943
11395
  nodes = null;
9944
11396
  }
@@ -9950,7 +11402,7 @@ var VectorEditorController = (_class5 = class {
9950
11402
  }
9951
11403
  }
9952
11404
  } else nodes = this.clipboard;
9953
- if (!_optionalChain([nodes, 'optionalAccess', _289 => _289.length])) return [];
11405
+ if (!_optionalChain([nodes, 'optionalAccess', _317 => _317.length])) return [];
9954
11406
  const offset = _nullishCoalesce(options.offset, () => ( (text && !text.trim().startsWith("{") ? { x: 0, y: 0 } : { x: 10, y: 10 })));
9955
11407
  const copies = nodes.map((n) => transformVectorNode(this.freshIds(n), translateMatrix(offset.x, offset.y)));
9956
11408
  this.change("Paste", () => {
@@ -10001,7 +11453,7 @@ var VectorEditorController = (_class5 = class {
10001
11453
  hitHandle(screen) {
10002
11454
  for (const ref of getVisibleHandles(this.view()).reverse()) {
10003
11455
  const a = getAnchorWorld(this.doc, ref);
10004
- const h = _optionalChain([a, 'optionalAccess', _290 => _290[ref.handle]]);
11456
+ const h = _optionalChain([a, 'optionalAccess', _318 => _318[ref.handle]]);
10005
11457
  if (!h) continue;
10006
11458
  const s = this.documentToScreen(h);
10007
11459
  if (Math.hypot(s.x - screen.x, s.y - screen.y) <= this.hitRadius) return ref;
@@ -10128,6 +11580,12 @@ var VectorEditorController = (_class5 = class {
10128
11580
  const path = this.hitPath(p);
10129
11581
  return path ? { nodeId: path.id } : null;
10130
11582
  }
11583
+ case "envelope": {
11584
+ const hit = this.hitEnvelope(screen, p);
11585
+ if (hit) return { nodeId: hit.target.node.id, envelope: { nodeId: hit.target.node.id, index: hit.index } };
11586
+ const node = hitTestVectorNodes(this.doc.nodes, p, this.tolerance(), { entered: this.enteredGroups() });
11587
+ return node ? { nodeId: node.id } : null;
11588
+ }
10131
11589
  default:
10132
11590
  return null;
10133
11591
  }
@@ -10140,7 +11598,7 @@ var VectorEditorController = (_class5 = class {
10140
11598
  const shown = this.hitWidthHandleIn(screen, this.widthView());
10141
11599
  if (shown) return shown;
10142
11600
  const spot = this.strokeSpotAt(this.screenToDocument(screen));
10143
- return spot && spot.nodeId !== _optionalChain([this, 'access', _291 => _291.hover, 'optionalAccess', _292 => _292.nodeId]) ? this.hitWidthHandleIn(screen, { ...this.widthView(), hover: { nodeId: spot.nodeId } }) : null;
11601
+ return spot && spot.nodeId !== _optionalChain([this, 'access', _319 => _319.hover, 'optionalAccess', _320 => _320.nodeId]) ? this.hitWidthHandleIn(screen, { ...this.widthView(), hover: { nodeId: spot.nodeId } }) : null;
10144
11602
  }
10145
11603
  hitWidthHandleIn(screen, view) {
10146
11604
  let best = null;
@@ -10195,9 +11653,9 @@ var VectorEditorController = (_class5 = class {
10195
11653
  downWidth(screen, p, input) {
10196
11654
  const hit = this.hitWidthHandle(screen);
10197
11655
  const spot = hit ? null : this.strokeSpotAt(p);
10198
- const nodeId = _nullishCoalesce(_optionalChain([hit, 'optionalAccess', _293 => _293.ref, 'access', _294 => _294.nodeId]), () => ( _optionalChain([spot, 'optionalAccess', _295 => _295.nodeId])));
11656
+ const nodeId = _nullishCoalesce(_optionalChain([hit, 'optionalAccess', _321 => _321.ref, 'access', _322 => _322.nodeId]), () => ( _optionalChain([spot, 'optionalAccess', _323 => _323.nodeId])));
10199
11657
  const node = nodeId ? this.getNode(nodeId) : void 0;
10200
- const g = _optionalChain([node, 'optionalAccess', _296 => _296.type]) === "path" ? vectorStrokeWidthGeometry(node) : null;
11658
+ const g = _optionalChain([node, 'optionalAccess', _324 => _324.type]) === "path" ? vectorStrokeWidthGeometry(node) : null;
10201
11659
  if (this.widthEdit) this.widthEdit = null;
10202
11660
  if (!node || node.type !== "path" || !g) {
10203
11661
  if (!input.shift) this.widthPoints = [];
@@ -10217,19 +11675,19 @@ var VectorEditorController = (_class5 = class {
10217
11675
  if (hit) {
10218
11676
  profile = sanitizeWidthProfile(node.strokeWidthProfile);
10219
11677
  ref = { nodeId: node.id, index: hit.ref.index, subpath: hit.ref.subpath };
10220
- t = _nullishCoalesce(_optionalChain([profile, 'access', _297 => _297[ref.index], 'optionalAccess', _298 => _298.t]), () => ( 0));
11678
+ t = _nullishCoalesce(_optionalChain([profile, 'access', _325 => _325[ref.index], 'optionalAccess', _326 => _326.t]), () => ( 0));
10221
11679
  subpath = hit.ref.subpath;
10222
11680
  if (hit.ref.part === "center") mode = input.alt && profile.length < VECTOR_WIDTH_PROFILE_MAX_POINTS ? "copy" : "move";
10223
11681
  else if (input.alt) side = hit.ref.part;
10224
- const same = this.widthPoints.length > 0 && this.widthPoints[0].nodeId === node.id;
10225
- const selected = same && this.widthPoints.some((r) => r.index === ref.index);
11682
+ const same2 = this.widthPoints.length > 0 && this.widthPoints[0].nodeId === node.id;
11683
+ const selected = same2 && this.widthPoints.some((r) => r.index === ref.index);
10226
11684
  if (input.shift && mode !== "copy") {
10227
11685
  if (selected) {
10228
11686
  this.widthPoints = this.widthPoints.filter((r) => r.index !== ref.index);
10229
11687
  this.notify();
10230
11688
  return;
10231
11689
  }
10232
- this.widthPoints = same ? [...this.widthPoints, ref] : [ref];
11690
+ this.widthPoints = same2 ? [...this.widthPoints, ref] : [ref];
10233
11691
  shift = true;
10234
11692
  } else if (mode === "copy" || !selected) this.widthPoints = [ref];
10235
11693
  if (mode !== "copy") group = this.widthPoints.filter((r) => r.index !== ref.index).map((r) => r.index);
@@ -10352,6 +11810,8 @@ var VectorEditorController = (_class5 = class {
10352
11810
  return this.downBlend(screen, p);
10353
11811
  case "gradient":
10354
11812
  return this.downGradient(screen, p, input);
11813
+ case "envelope":
11814
+ return this.downEnvelope(screen, p, input);
10355
11815
  case "scissors": {
10356
11816
  const seg = this.nearestOutline(p);
10357
11817
  if (seg) this.cutPathAt(seg.nodeId, seg.point);
@@ -10374,7 +11834,7 @@ var VectorEditorController = (_class5 = class {
10374
11834
  let anchor = null;
10375
11835
  if (node.type === "path" && node.subpaths[0]) {
10376
11836
  const refs = node.subpaths[0].anchors.map((_, index) => ({ nodeId: node.id, subpath: 0, index }));
10377
- anchor = _nullishCoalesce(_optionalChain([this, 'access', _299 => _299.hitAnchor, 'call', _300 => _300(screen, refs), 'optionalAccess', _301 => _301.index]), () => ( null));
11837
+ anchor = _nullishCoalesce(_optionalChain([this, 'access', _327 => _327.hitAnchor, 'call', _328 => _328(screen, refs), 'optionalAccess', _329 => _329.index]), () => ( null));
10378
11838
  }
10379
11839
  return { nodeId: node.id, anchor };
10380
11840
  }
@@ -10527,7 +11987,7 @@ var VectorEditorController = (_class5 = class {
10527
11987
  }
10528
11988
  downPen(screen, p, input) {
10529
11989
  const before = this.snapshot();
10530
- const sp = this.pen ? _optionalChain([this, 'access', _302 => _302.getNode, 'call', _303 => _303(this.pen.nodeId), 'optionalAccess', _304 => _304.subpaths, 'access', _305 => _305[this.pen.subpath]]) : void 0;
11990
+ const sp = this.pen ? _optionalChain([this, 'access', _330 => _330.getNode, 'call', _331 => _331(this.pen.nodeId), 'optionalAccess', _332 => _332.subpaths, 'access', _333 => _333[this.pen.subpath]]) : void 0;
10531
11991
  if (this.pen && sp) {
10532
11992
  const pen = this.pen;
10533
11993
  const first = { nodeId: pen.nodeId, subpath: pen.subpath, index: 0 };
@@ -10645,6 +12105,8 @@ var VectorEditorController = (_class5 = class {
10645
12105
  return;
10646
12106
  case "gradient":
10647
12107
  return this.moveGradient(drag, screen, p, input);
12108
+ case "envelope":
12109
+ return this.moveEnvelope(drag, p);
10648
12110
  case "move": {
10649
12111
  let dx = p.x - drag.start.x;
10650
12112
  let dy = p.y - drag.start.y;
@@ -10665,6 +12127,7 @@ var VectorEditorController = (_class5 = class {
10665
12127
  return;
10666
12128
  }
10667
12129
  case "scale": {
12130
+ if (this.freeDistort && drag.handle !== "rotate") return this.moveDistort(drag, p, input);
10668
12131
  const angle = drag.frame.angle;
10669
12132
  const q = angle ? applyMatrix(rotateMatrix(-angle), p) : p;
10670
12133
  let { sx, sy, origin } = scaleFor(drag.handle, drag.frame, q, input);
@@ -10791,7 +12254,7 @@ var VectorEditorController = (_class5 = class {
10791
12254
  }
10792
12255
  case "shape": {
10793
12256
  const node = this.getNode(drag.nodeId);
10794
- if (_optionalChain([node, 'optionalAccess', _306 => _306.type]) !== "path") return;
12257
+ if (_optionalChain([node, 'optionalAccess', _334 => _334.type]) !== "path") return;
10795
12258
  const leave = { at: drag.start, constrain: input.shift ? drag.tool === "line" ? "angle" : "square" : null, curves: false };
10796
12259
  let end = this.snapDrawn(p, leave, input, () => drag.targets ??= this.drawingTargets(null));
10797
12260
  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);
@@ -10865,14 +12328,14 @@ var VectorEditorController = (_class5 = class {
10865
12328
  for (const q of drag.lazy.push([p.x, p.y])) {
10866
12329
  if (Math.hypot(q[0] - last[0], q[1] - last[1]) * this.viewport.zoom < 1.5) continue;
10867
12330
  drag.points.push(q);
10868
- _optionalChain([drag, 'access', _307 => _307.pressures, 'optionalAccess', _308 => _308.push, 'call', _309 => _309(drag.pressure)]);
12331
+ _optionalChain([drag, 'access', _335 => _335.pressures, 'optionalAccess', _336 => _336.push, 'call', _337 => _337(drag.pressure)]);
10869
12332
  moved = true;
10870
12333
  }
10871
12334
  const string = drag.lazy.string();
10872
12335
  const node = this.getNode(drag.nodeId);
10873
- if (_optionalChain([node, 'optionalAccess', _310 => _310.type]) !== "path") return;
12336
+ if (_optionalChain([node, 'optionalAccess', _338 => _338.type]) !== "path") return;
10874
12337
  if (!moved) {
10875
- if (string && _optionalChain([this, 'access', _311 => _311.interaction, 'optionalAccess', _312 => _312.type]) === "draw") {
12338
+ if (string && _optionalChain([this, 'access', _339 => _339.interaction, 'optionalAccess', _340 => _340.type]) === "draw") {
10876
12339
  this.interaction = { ...this.interaction, string: [{ x: string[0][0], y: string[0][1] }, { x: string[1][0], y: string[1][1] }] };
10877
12340
  this.notify();
10878
12341
  }
@@ -10908,8 +12371,8 @@ var VectorEditorController = (_class5 = class {
10908
12371
  }
10909
12372
  this.setGuides(res);
10910
12373
  return {
10911
- dx: _optionalChain([res, 'optionalAccess', _313 => _313.x]) ? dx + res.dx : axes.x ? this.gridValue(origin.x + dx) - origin.x : dx,
10912
- dy: _optionalChain([res, 'optionalAccess', _314 => _314.y]) ? dy + res.dy : axes.y ? this.gridValue(origin.y + dy) - origin.y : dy
12374
+ dx: _optionalChain([res, 'optionalAccess', _341 => _341.x]) ? dx + res.dx : axes.x ? this.gridValue(origin.x + dx) - origin.x : dx,
12375
+ dy: _optionalChain([res, 'optionalAccess', _342 => _342.y]) ? dy + res.dy : axes.y ? this.gridValue(origin.y + dy) - origin.y : dy
10913
12376
  };
10914
12377
  }
10915
12378
  /** The anchor a point drag snaps by, where it started: the grabbed one, else the moving one nearest the press. */
@@ -10965,7 +12428,13 @@ var VectorEditorController = (_class5 = class {
10965
12428
  }
10966
12429
  return this.commit(drag.duplicated ? "Duplicate" : "Move", drag.before);
10967
12430
  case "scale":
10968
- return this.commit("Scale", drag.before);
12431
+ return this.commit(_nullishCoalesce(drag.op, () => ( "Scale")), drag.before);
12432
+ case "envelope":
12433
+ if (!drag.moved) {
12434
+ this.notify();
12435
+ return;
12436
+ }
12437
+ return this.commit("Edit Envelope", drag.before);
10969
12438
  case "rotate":
10970
12439
  return this.commit("Rotate", drag.before);
10971
12440
  case "anchors":
@@ -10988,7 +12457,7 @@ var VectorEditorController = (_class5 = class {
10988
12457
  if (drag.moved) return this.commit("Corner Radius", drag.before);
10989
12458
  if (drag.alt) {
10990
12459
  const kind = nextVectorCornerKind(drag.widget.kind);
10991
- this.doc = this.updateAnchors(drag.base, drag.refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access', _315 => _315.corner, 'optionalAccess', _316 => _316.radius]), () => ( 0)), kind));
12460
+ this.doc = this.updateAnchors(drag.base, drag.refs, (a) => setAnchorCorner(a, _nullishCoalesce(_optionalChain([a, 'access', _343 => _343.corner, 'optionalAccess', _344 => _344.radius]), () => ( 0)), kind));
10992
12461
  return this.commit("Corner Kind", drag.before);
10993
12462
  }
10994
12463
  const ref = drag.widget.ref;
@@ -11003,7 +12472,7 @@ var VectorEditorController = (_class5 = class {
11003
12472
  const several = drag.group.length > 0;
11004
12473
  if (drag.mode === "copy") this.widthPoints = [drag.ref];
11005
12474
  else if (drag.mode === "move" && several) {
11006
- this.widthPoints = [drag.source, ...drag.group].map((i) => ({ ...drag.ref, index: _nullishCoalesce(_optionalChain([drag, 'access', _317 => _317.renumber, 'optionalAccess', _318 => _318.get, 'call', _319 => _319(i)]), () => ( i)) }));
12475
+ this.widthPoints = [drag.source, ...drag.group].map((i) => ({ ...drag.ref, index: _nullishCoalesce(_optionalChain([drag, 'access', _345 => _345.renumber, 'optionalAccess', _346 => _346.get, 'call', _347 => _347(i)]), () => ( i)) }));
11007
12476
  } else if (!several) this.widthPoints = [drag.ref];
11008
12477
  const label = drag.mode === "copy" ? "Copy Width Point" : drag.mode === "move" ? several ? "Move Width Points" : "Move Width Point" : several ? "Width Points" : "Width Point";
11009
12478
  return this.commit(label, drag.before);
@@ -11047,14 +12516,14 @@ var VectorEditorController = (_class5 = class {
11047
12516
  }
11048
12517
  case "pencil": {
11049
12518
  const node = this.getNode(drag.nodeId);
11050
- if (_optionalChain([node, 'optionalAccess', _320 => _320.type]) !== "path" || drag.points.length < 2) {
12519
+ if (_optionalChain([node, 'optionalAccess', _348 => _348.type]) !== "path" || drag.points.length < 2) {
11051
12520
  this.doc = drag.before.doc;
11052
12521
  this.notify(true);
11053
12522
  return;
11054
12523
  }
11055
12524
  for (const q of drag.lazy.finish()) {
11056
12525
  drag.points.push(q);
11057
- _optionalChain([drag, 'access', _321 => _321.pressures, 'optionalAccess', _322 => _322.push, 'call', _323 => _323(drag.pressure)]);
12526
+ _optionalChain([drag, 'access', _349 => _349.pressures, 'optionalAccess', _350 => _350.push, 'call', _351 => _351(drag.pressure)]);
11058
12527
  }
11059
12528
  const shape = this.editing.recognizeShapes ? recognizeInkShape(drag.points, { minSize: 6 / this.viewport.zoom }) : null;
11060
12529
  if (shape) {
@@ -11129,7 +12598,7 @@ var VectorEditorController = (_class5 = class {
11129
12598
  this.convertAnchors(a.in || a.out ? "corner" : "smooth", [anchor]);
11130
12599
  return;
11131
12600
  }
11132
- const id = _nullishCoalesce(_optionalChain([this, 'access', _324 => _324.hover, 'optionalAccess', _325 => _325.segment, 'optionalAccess', _326 => _326.nodeId]), () => ( this.editingId));
12601
+ const id = _nullishCoalesce(_optionalChain([this, 'access', _352 => _352.hover, 'optionalAccess', _353 => _353.segment, 'optionalAccess', _354 => _354.nodeId]), () => ( this.editingId));
11133
12602
  if (id) {
11134
12603
  const node = this.getNode(id);
11135
12604
  const seg = node ? nearestSegment(node, this.toLocal(id, p)) : null;
@@ -11226,7 +12695,7 @@ var VectorEditorController = (_class5 = class {
11226
12695
  this.finishPath();
11227
12696
  return true;
11228
12697
  }
11229
- if (this.tool === "select" && this.selection.length === 1 && _optionalChain([this, 'access', _327 => _327.getNode, 'call', _328 => _328(this.selection[0]), 'optionalAccess', _329 => _329.type]) === "path") {
12698
+ if (this.tool === "select" && this.selection.length === 1 && _optionalChain([this, 'access', _355 => _355.getNode, 'call', _356 => _356(this.selection[0]), 'optionalAccess', _357 => _357.type]) === "path") {
11230
12699
  this.tool = "direct";
11231
12700
  this.editingId = this.selection[0];
11232
12701
  this.notify();
@@ -11370,7 +12839,7 @@ function renderNode(stored, defs, idPrefix) {
11370
12839
  strokeWidth: _nullishCoalesce(node.strokeWidth, () => ( 1)),
11371
12840
  ...node.strokeLinecap ? { strokeLinecap: node.strokeLinecap } : {},
11372
12841
  ...node.strokeLinejoin ? { strokeLinejoin: node.strokeLinejoin } : {},
11373
- ..._optionalChain([node, 'access', _330 => _330.strokeDasharray, 'optionalAccess', _331 => _331.length]) ? { strokeDasharray: node.strokeDasharray.join(" ") } : {},
12842
+ ..._optionalChain([node, 'access', _358 => _358.strokeDasharray, 'optionalAccess', _359 => _359.length]) ? { strokeDasharray: node.strokeDasharray.join(" ") } : {},
11374
12843
  fillRule: _nullishCoalesce(node.fillRule, () => ( "nonzero")),
11375
12844
  opacity: _nullishCoalesce(node.opacity, () => ( 1))
11376
12845
  };
@@ -11424,11 +12893,11 @@ function getVectorOverlayRenderData(state) {
11424
12893
  };
11425
12894
  for (const id of state.selection) outline(id, true);
11426
12895
  if (state.editingId) outline(state.editingId, true);
11427
- if (_optionalChain([state, 'access', _332 => _332.hover, 'optionalAccess', _333 => _333.nodeId]) && !state.interaction) outline(state.hover.nodeId, false);
12896
+ if (_optionalChain([state, 'access', _360 => _360.hover, 'optionalAccess', _361 => _361.nodeId]) && !state.interaction) outline(state.hover.nodeId, false);
11428
12897
  let selectionBox = null;
11429
- if (state.tool === "select" && state.selectionFrame && _optionalChain([state, 'access', _334 => _334.interaction, 'optionalAccess', _335 => _335.type]) !== "marquee") {
12898
+ if (state.tool === "select" && state.selectionFrame && _optionalChain([state, 'access', _362 => _362.interaction, 'optionalAccess', _363 => _363.type]) !== "marquee" && _optionalChain([state, 'access', _364 => _364.interaction, 'optionalAccess', _365 => _365.type]) !== "distort") {
11430
12899
  const g = getVectorSelectionBoxGeometry(state.selectionFrame, state.viewport);
11431
- selectionBox = { ...g.box, angle: g.angle, transform: g.transform, corners: g.corners, handles: g.handles };
12900
+ selectionBox = { ...g.box, angle: g.angle, transform: g.transform, corners: g.corners, handles: g.handles, freeDistort: state.freeDistort };
11432
12901
  }
11433
12902
  const selected = (r) => state.selectedAnchors.some((a) => a.nodeId === r.nodeId && a.subpath === r.subpath && a.index === r.index);
11434
12903
  const sameAnchor = (a, b) => !!a && a.nodeId === b.nodeId && a.subpath === b.subpath && a.index === b.index;
@@ -11436,9 +12905,9 @@ function getVectorOverlayRenderData(state) {
11436
12905
  const a = getAnchorWorld(doc, ref);
11437
12906
  const s = toScreen(state, a);
11438
12907
  const closes = !!state.pen && state.pen.nodeId === ref.nodeId && state.pen.subpath === ref.subpath && ref.index === 0;
11439
- return { ref, x: s.x, y: s.y, type: _nullishCoalesce(a.type, () => ( inferAnchorType(a))), selected: selected(ref), hovered: sameAnchor(_optionalChain([state, 'access', _336 => _336.hover, 'optionalAccess', _337 => _337.anchor]), ref), closes };
12908
+ return { ref, x: s.x, y: s.y, type: _nullishCoalesce(a.type, () => ( inferAnchorType(a))), selected: selected(ref), hovered: sameAnchor(_optionalChain([state, 'access', _366 => _366.hover, 'optionalAccess', _367 => _367.anchor]), ref), closes };
11440
12909
  });
11441
- if (state.tool === "pen" && !state.pen && _optionalChain([state, 'access', _338 => _338.hover, 'optionalAccess', _339 => _339.anchor])) {
12910
+ if (state.tool === "pen" && !state.pen && _optionalChain([state, 'access', _368 => _368.hover, 'optionalAccess', _369 => _369.anchor])) {
11442
12911
  const a = getAnchorWorld(doc, state.hover.anchor);
11443
12912
  if (a) {
11444
12913
  const s = toScreen(state, a);
@@ -11447,15 +12916,15 @@ function getVectorOverlayRenderData(state) {
11447
12916
  }
11448
12917
  const handles = getVisibleHandles(state).flatMap((ref) => {
11449
12918
  const a = getAnchorWorld(doc, ref);
11450
- const h = _optionalChain([a, 'optionalAccess', _340 => _340[ref.handle]]);
12919
+ const h = _optionalChain([a, 'optionalAccess', _370 => _370[ref.handle]]);
11451
12920
  if (!a || !h) return [];
11452
12921
  const s = toScreen(state, h);
11453
12922
  const sa = toScreen(state, a);
11454
- const hovered = !!_optionalChain([state, 'access', _341 => _341.hover, 'optionalAccess', _342 => _342.handle]) && sameAnchor(state.hover.handle, ref) && state.hover.handle.handle === ref.handle;
12923
+ const hovered = !!_optionalChain([state, 'access', _371 => _371.hover, 'optionalAccess', _372 => _372.handle]) && sameAnchor(state.hover.handle, ref) && state.hover.handle.handle === ref.handle;
11455
12924
  return [{ ref, x: s.x, y: s.y, anchorX: sa.x, anchorY: sa.y, hovered }];
11456
12925
  });
11457
12926
  let marquee = null;
11458
- if (_optionalChain([state, 'access', _343 => _343.interaction, 'optionalAccess', _344 => _344.type]) === "marquee") {
12927
+ if (_optionalChain([state, 'access', _373 => _373.interaction, 'optionalAccess', _374 => _374.type]) === "marquee") {
11459
12928
  const b = state.interaction.bounds;
11460
12929
  const tl = toScreen(state, b);
11461
12930
  marquee = { x: tl.x, y: tl.y, width: b.width * z, height: b.height * z };
@@ -11463,7 +12932,7 @@ function getVectorOverlayRenderData(state) {
11463
12932
  let penPreview = null;
11464
12933
  if (state.tool === "pen" && state.pen && state.pointer && !state.interaction) {
11465
12934
  const node = findVectorNode(doc.nodes, state.pen.nodeId);
11466
- const sp = _optionalChain([node, 'optionalAccess', _345 => _345.type]) === "path" ? node.subpaths[state.pen.subpath] : void 0;
12935
+ const sp = _optionalChain([node, 'optionalAccess', _375 => _375.type]) === "path" ? node.subpaths[state.pen.subpath] : void 0;
11467
12936
  const last = sp ? getAnchorWorld(doc, { nodeId: state.pen.nodeId, subpath: state.pen.subpath, index: sp.anchors.length - 1 }) : void 0;
11468
12937
  if (last) {
11469
12938
  const a = toScreen(state, last);
@@ -11476,9 +12945,9 @@ function getVectorOverlayRenderData(state) {
11476
12945
  const artboard = { x: origin.x, y: origin.y, width: doc.width * z, height: doc.height * z };
11477
12946
  let status = null;
11478
12947
  const it = state.interaction;
11479
- if (_optionalChain([it, 'optionalAccess', _346 => _346.type]) === "rotate") status = `${Math.round(it.angle)}\xB0`;
11480
- else if (_optionalChain([it, 'optionalAccess', _347 => _347.type]) === "move" || _optionalChain([it, 'optionalAccess', _348 => _348.type]) === "anchors") status = `\u0394 ${fmt4(it.dx)}, ${fmt4(it.dy)}`;
11481
- else if (_optionalChain([it, 'optionalAccess', _349 => _349.type]) === "scale" || _optionalChain([it, 'optionalAccess', _350 => _350.type]) === "draw") {
12948
+ if (_optionalChain([it, 'optionalAccess', _376 => _376.type]) === "rotate") status = `${Math.round(it.angle)}\xB0`;
12949
+ else if (_optionalChain([it, 'optionalAccess', _377 => _377.type]) === "move" || _optionalChain([it, 'optionalAccess', _378 => _378.type]) === "anchors") status = `\u0394 ${fmt4(it.dx)}, ${fmt4(it.dy)}`;
12950
+ else if (_optionalChain([it, 'optionalAccess', _379 => _379.type]) === "scale" || _optionalChain([it, 'optionalAccess', _380 => _380.type]) === "draw") {
11482
12951
  const b = it.type === "draw" ? findVectorNode(doc.nodes, it.nodeId) ? vectorNodeBounds(findVectorNode(doc.nodes, it.nodeId)) : null : state.selectionFrame;
11483
12952
  if (b) status = `W ${fmt4(b.width)} \xD7 H ${fmt4(b.height)}`;
11484
12953
  }
@@ -11495,24 +12964,24 @@ function getVectorOverlayRenderData(state) {
11495
12964
  }
11496
12965
  }
11497
12966
  let toolStroke = null;
11498
- if (_optionalChain([it, 'optionalAccess', _351 => _351.type]) === "stroke") {
12967
+ if (_optionalChain([it, 'optionalAccess', _381 => _381.type]) === "stroke") {
11499
12968
  const pts = it.points.map((q) => toScreen(state, q));
11500
12969
  const d = pts.map((q, i) => `${i ? "L" : "M"}${fmt4(q.x)} ${fmt4(q.y)}`).join("") + (pts.length === 1 ? `L${fmt4(pts[0].x)} ${fmt4(pts[0].y)}` : "");
11501
12970
  toolStroke = { tool: it.tool, d, width: fmt4(it.width * z) };
11502
12971
  }
11503
12972
  let pencilString = null;
11504
- if (_optionalChain([it, 'optionalAccess', _352 => _352.type]) === "draw" && it.string) {
12973
+ if (_optionalChain([it, 'optionalAccess', _382 => _382.type]) === "draw" && it.string) {
11505
12974
  const a = toScreen(state, it.string[0]);
11506
12975
  const b = toScreen(state, it.string[1]);
11507
12976
  pencilString = { x1: fmt4(a.x), y1: fmt4(a.y), x2: fmt4(b.x), y2: fmt4(b.y) };
11508
12977
  }
11509
- const dragged = _optionalChain([it, 'optionalAccess', _353 => _353.type]) === "corner" ? it.ref : null;
12978
+ const dragged = _optionalChain([it, 'optionalAccess', _383 => _383.type]) === "corner" ? it.ref : null;
11510
12979
  const cornerWidgets = getVectorCornerWidgets(state).map((w) => {
11511
12980
  const s = toScreen(state, w);
11512
- return { ref: w.ref, x: fmt4(s.x), y: fmt4(s.y), radius: w.radius, kind: w.kind, hovered: sameAnchor(_optionalChain([state, 'access', _354 => _354.hover, 'optionalAccess', _355 => _355.corner]), w.ref), active: !!dragged };
12981
+ return { ref: w.ref, x: fmt4(s.x), y: fmt4(s.y), radius: w.radius, kind: w.kind, hovered: sameAnchor(_optionalChain([state, 'access', _384 => _384.hover, 'optionalAccess', _385 => _385.corner]), w.ref), active: !!dragged };
11513
12982
  });
11514
- if (_optionalChain([it, 'optionalAccess', _356 => _356.type]) === "corner") status = `R ${fmt4(it.radius)}`;
11515
- const cutPoint = state.tool === "scissors" && _optionalChain([state, 'access', _357 => _357.hover, 'optionalAccess', _358 => _358.segment]) && !it ? (({ x, y }) => ({ x: fmt4(x), y: fmt4(y) }))(toScreen(state, state.hover.segment.point)) : null;
12983
+ if (_optionalChain([it, 'optionalAccess', _386 => _386.type]) === "corner") status = `R ${fmt4(it.radius)}`;
12984
+ const cutPoint = state.tool === "scissors" && _optionalChain([state, 'access', _387 => _387.hover, 'optionalAccess', _388 => _388.segment]) && !it ? (({ x, y }) => ({ x: fmt4(x), y: fmt4(y) }))(toScreen(state, state.hover.segment.point)) : null;
11516
12985
  const sc = (p) => {
11517
12986
  const q = toScreen(state, p);
11518
12987
  return { x: fmt4(q.x), y: fmt4(q.y) };
@@ -11520,13 +12989,13 @@ function getVectorOverlayRenderData(state) {
11520
12989
  const sameWidth = (a, b) => !!a && a.nodeId === b.nodeId && a.index === b.index;
11521
12990
  const widthPoints = getVectorWidthHandles(state).map((h) => {
11522
12991
  const c = sc(h);
11523
- const hw = _optionalChain([state, 'access', _359 => _359.hover, 'optionalAccess', _360 => _360.widthPoint]);
12992
+ const hw = _optionalChain([state, 'access', _389 => _389.hover, 'optionalAccess', _390 => _390.widthPoint]);
11524
12993
  const hovered = hw && sameWidth(hw, h.ref) && hw.subpath === h.ref.subpath ? hw.part : null;
11525
- 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', _361 => _361.type]) === "width" && sameWidth(it.ref, h.ref) };
12994
+ 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', _391 => _391.type]) === "width" && sameWidth(it.ref, h.ref) };
11526
12995
  });
11527
- const spot = state.tool === "width" && !it ? _optionalChain([state, 'access', _362 => _362.hover, 'optionalAccess', _363 => _363.strokeSpot]) : null;
12996
+ const spot = state.tool === "width" && !it ? _optionalChain([state, 'access', _392 => _392.hover, 'optionalAccess', _393 => _393.strokeSpot]) : null;
11528
12997
  const widthSpot = spot ? { ...sc(spot.point), left: sc(spot.left), right: sc(spot.right) } : null;
11529
- if (_optionalChain([it, 'optionalAccess', _364 => _364.type]) === "width") status = it.mode === "move" ? "Move width point" : it.mode === "copy" ? "Copy width point" : `W ${fmt4(it.width)}`;
12998
+ if (_optionalChain([it, 'optionalAccess', _394 => _394.type]) === "width") status = it.mode === "move" ? "Move width point" : it.mode === "copy" ? "Copy width point" : `W ${fmt4(it.width)}`;
11530
12999
  let builder = null;
11531
13000
  if (state.builder) {
11532
13001
  const v2 = state.viewport;
@@ -11542,7 +13011,7 @@ function getVectorOverlayRenderData(state) {
11542
13011
  lines: state.builder.lines.map((l) => svg(_chunkVNYRI265cjs.transformBezierPath.call(void 0, l, view))),
11543
13012
  trail
11544
13013
  };
11545
- if (state.builder.mode !== "fill" && _optionalChain([it, 'optionalAccess', _365 => _365.type]) === "builder") {
13014
+ if (state.builder.mode !== "fill" && _optionalChain([it, 'optionalAccess', _395 => _395.type]) === "builder") {
11546
13015
  const n = state.builder.faces.length;
11547
13016
  status = state.builder.mode === "erase" ? `Delete ${n} ${n === 1 ? "face" : "faces"}` : `Merge ${n} ${n === 1 ? "face" : "faces"}`;
11548
13017
  }
@@ -11553,18 +13022,72 @@ function getVectorOverlayRenderData(state) {
11553
13022
  if (state.tool === "gradient") {
11554
13023
  gradient = gradientOverlay(state);
11555
13024
  if (!gradient && !it) status = "Drag across a shape to set a gradient";
11556
- else if (_optionalChain([it, 'optionalAccess', _366 => _366.type]) === "gradient" && it.removing) status = "Release to delete the stop";
13025
+ else if (_optionalChain([it, 'optionalAccess', _396 => _396.type]) === "gradient" && it.removing) status = "Release to delete the stop";
11557
13026
  }
11558
- return { outlines, selectionBox, anchors, handles, marquee, penPreview, artboard, guides, status, toolStroke, pencilString, cutPoint, cornerWidgets, widthPoints, widthSpot, builder, blend, gradient };
13027
+ let distort = null;
13028
+ if (_optionalChain([it, 'optionalAccess', _397 => _397.type]) === "distort") {
13029
+ const corners2 = it.corners.map(sc);
13030
+ distort = { mode: it.mode, corners: corners2, d: corners2.map((c, i) => `${i ? "L" : "M"}${c.x} ${c.y}`).join("") + "Z" };
13031
+ status = it.mode === "skew" ? "Skew" : it.mode === "perspective" ? "Perspective" : "Distort";
13032
+ }
13033
+ const envelope = state.tool === "envelope" ? envelopeOverlay(state) : null;
13034
+ if (state.tool === "envelope" && !envelope && !it) status = "Select an object with an envelope to edit its mesh";
13035
+ return { outlines, selectionBox, distort, anchors, handles, marquee, penPreview, artboard, guides, status, toolStroke, pencilString, cutPoint, cornerWidgets, widthPoints, widthSpot, builder, blend, gradient, envelope };
13036
+ }
13037
+ function envelopeOverlay(state) {
13038
+ const target = getVectorEnvelopeTarget(state.document, state.selection);
13039
+ if (!target) return null;
13040
+ const v2 = state.viewport;
13041
+ const m = multiplyMatrices(target.world, [v2.zoom, 0, 0, v2.zoom, v2.x, v2.y]);
13042
+ const sc = (p) => ({ x: fmt4(m[0] * p.x + m[2] * p.y + m[4]), y: fmt4(m[1] * p.x + m[3] * p.y + m[5]) });
13043
+ const { mesh } = target.frame;
13044
+ const grid = vectorMeshGridCurves(mesh).map((c) => {
13045
+ const [a, b, cc, d] = c.map(sc);
13046
+ return `M${a.x} ${a.y}C${b.x} ${b.y} ${cc.x} ${cc.y} ${d.x} ${d.y}`;
13047
+ }).join("");
13048
+ const hover = _optionalChain([state, 'access', _398 => _398.hover, 'optionalAccess', _399 => _399.envelope, 'optionalAccess', _400 => _400.nodeId]) === target.node.id ? state.hover.envelope.index : void 0;
13049
+ const it = state.interaction;
13050
+ const active = _optionalChain([it, 'optionalAccess', _401 => _401.type]) === "envelope" && it.nodeId === target.node.id ? it.index : void 0;
13051
+ const pts = vectorMeshEditPoints(mesh);
13052
+ return {
13053
+ nodeId: target.node.id,
13054
+ grid,
13055
+ anchors: pts.anchors.map((index) => ({ index, ...sc(mesh.points[index]), hovered: !it && hover === index, active: active === index })),
13056
+ handles: pts.handles.map((h) => {
13057
+ const a = sc(mesh.points[h.anchor]);
13058
+ return { index: h.index, ...sc(mesh.points[h.index]), anchorX: a.x, anchorY: a.y, hovered: !it && hover === h.index, active: active === h.index };
13059
+ })
13060
+ };
13061
+ }
13062
+ var VECTOR_ENVELOPE_STYLE_OPTIONS = [
13063
+ ...VECTOR_WARP_STYLES.map((value) => ({ value, label: VECTOR_WARP_STYLE_LABELS[value] })),
13064
+ { value: "mesh", label: "Mesh" }
13065
+ ];
13066
+ function getVectorEnvelopePanel(state) {
13067
+ const nodes = state.selection.map((id) => findVectorNode(state.document.nodes, id)).filter((n) => !!n && !n.blendStep);
13068
+ if (!nodes.length) return null;
13069
+ const one = nodes.length === 1 ? nodes[0] : null;
13070
+ const first = _optionalChain([one, 'optionalAccess', _402 => _402.effects, 'optionalAccess', _403 => _403.find, 'call', _404 => _404((e) => e.type === "envelope")]);
13071
+ const order = /* @__PURE__ */ new Map();
13072
+ walkVectorNodes(state.document.nodes, (n) => order.set(n.id, order.size));
13073
+ const top = nodes.length > 1 ? nodes.slice().sort((a, b) => (_nullishCoalesce(order.get(a.id), () => ( 0))) - (_nullishCoalesce(order.get(b.id), () => ( 0))))[nodes.length - 1] : null;
13074
+ return {
13075
+ nodeId: _nullishCoalesce(_optionalChain([one, 'optionalAccess', _405 => _405.id]), () => ( null)),
13076
+ count: nodes.length,
13077
+ envelope: _optionalChain([first, 'optionalAccess', _406 => _406.type]) === "envelope" ? { effectId: first.id, enabled: first.enabled !== false, params: first.params } : null,
13078
+ canMake: nodes.some((n) => !n.locked),
13079
+ canMakeWithTopObject: _optionalChain([top, 'optionalAccess', _407 => _407.type]) === "path" && top.subpaths.some((sp) => sp.closed && sp.anchors.length > 1),
13080
+ canRelease: nodes.some((n) => !n.locked && !!_optionalChain([n, 'access', _408 => _408.effects, 'optionalAccess', _409 => _409.some, 'call', _410 => _410((e) => e.type === "envelope")]))
13081
+ };
11559
13082
  }
11560
13083
  function gradientOverlay(state) {
11561
13084
  const a = getVectorGradientAnnotator(state.document, state.selection, state.viewport, state.gradientEdit.target);
11562
13085
  if (!a) return null;
11563
- const hover = state.interaction ? null : _optionalChain([state, 'access', _367 => _367.hover, 'optionalAccess', _368 => _368.gradient]);
11564
- const handleHovered = (h) => _optionalChain([hover, 'optionalAccess', _369 => _369.kind]) === "handle" && hover.handle === h;
13086
+ const hover = state.interaction ? null : _optionalChain([state, 'access', _411 => _411.hover, 'optionalAccess', _412 => _412.gradient]);
13087
+ const handleHovered = (h) => _optionalChain([hover, 'optionalAccess', _413 => _413.kind]) === "handle" && hover.handle === h;
11565
13088
  const pt2 = (p) => ({ x: fmt4(p.x), y: fmt4(p.y) });
11566
13089
  const centred = isCentredVectorGradient(a.gradient.type);
11567
- const removing = _optionalChain([state, 'access', _370 => _370.interaction, 'optionalAccess', _371 => _371.type]) === "gradient" && !!state.interaction.removing;
13090
+ const removing = _optionalChain([state, 'access', _414 => _414.interaction, 'optionalAccess', _415 => _415.type]) === "gradient" && !!state.interaction.removing;
11568
13091
  return {
11569
13092
  nodeId: a.nodeId,
11570
13093
  type: a.gradient.type,
@@ -11580,9 +13103,9 @@ function gradientOverlay(state) {
11580
13103
  color: s.color,
11581
13104
  opacity: _nullishCoalesce(s.opacity, () => ( 1)),
11582
13105
  selected: state.gradientEdit.stop === s.index,
11583
- hovered: _optionalChain([hover, 'optionalAccess', _372 => _372.kind]) === "stop" && hover.index === s.index
13106
+ hovered: _optionalChain([hover, 'optionalAccess', _416 => _416.kind]) === "stop" && hover.index === s.index
11584
13107
  })),
11585
- midpoints: a.midpoints.map((m) => ({ index: m.index, ...pt2(m), hovered: _optionalChain([hover, 'optionalAccess', _373 => _373.kind]) === "midpoint" && hover.index === m.index })),
13108
+ midpoints: a.midpoints.map((m) => ({ index: m.index, ...pt2(m), hovered: _optionalChain([hover, 'optionalAccess', _417 => _417.kind]) === "midpoint" && hover.index === m.index })),
11586
13109
  extent: a.extent,
11587
13110
  removing
11588
13111
  };
@@ -11591,7 +13114,7 @@ function selectedBlends(state) {
11591
13114
  const out = /* @__PURE__ */ new Map();
11592
13115
  for (const id of state.selection) {
11593
13116
  const node = findVectorNode(state.document.nodes, id);
11594
- const group = isVectorBlendGroup(node) ? node : _optionalChain([locateVectorNode, 'call', _374 => _374(state.document.nodes, id), 'optionalAccess', _375 => _375.parent]);
13117
+ const group = isVectorBlendGroup(node) ? node : _optionalChain([locateVectorNode, 'call', _418 => _418(state.document.nodes, id), 'optionalAccess', _419 => _419.parent]);
11595
13118
  if (isVectorBlendGroup(group)) out.set(group.id, group);
11596
13119
  }
11597
13120
  return [...out.values()];
@@ -11623,11 +13146,11 @@ function blendOverlay(state) {
11623
13146
  const a = state.blendStart.anchor === null ? void 0 : getAnchorWorld(doc, { nodeId: from.id, subpath: 0, index: state.blendStart.anchor });
11624
13147
  start = { d: screenOutline(state, from, /* @__PURE__ */ new Set()), anchor: a ? sc(a, view) : null };
11625
13148
  }
11626
- const hovered = _optionalChain([state, 'access', _376 => _376.hover, 'optionalAccess', _377 => _377.nodeId]) ? findVectorNode(doc.nodes, state.hover.nodeId) : void 0;
11627
- if (_optionalChain([hovered, 'optionalAccess', _378 => _378.type]) === "path" && hovered.subpaths[0]) {
13149
+ const hovered = _optionalChain([state, 'access', _420 => _420.hover, 'optionalAccess', _421 => _421.nodeId]) ? findVectorNode(doc.nodes, state.hover.nodeId) : void 0;
13150
+ if (_optionalChain([hovered, 'optionalAccess', _422 => _422.type]) === "path" && hovered.subpaths[0]) {
11628
13151
  hovered.subpaths[0].anchors.forEach((_, index) => {
11629
13152
  const a = getAnchorWorld(doc, { nodeId: hovered.id, subpath: 0, index });
11630
- if (a) anchors.push({ ...sc(a, view), hovered: _optionalChain([state, 'access', _379 => _379.hover, 'optionalAccess', _380 => _380.anchor, 'optionalAccess', _381 => _381.index]) === index });
13153
+ if (a) anchors.push({ ...sc(a, view), hovered: _optionalChain([state, 'access', _423 => _423.hover, 'optionalAccess', _424 => _424.anchor, 'optionalAccess', _425 => _425.index]) === index });
11631
13154
  });
11632
13155
  }
11633
13156
  }
@@ -11638,17 +13161,17 @@ function getVectorBlendControls(state) {
11638
13161
  const doc = state.document;
11639
13162
  const roots = state.selection.filter((id) => {
11640
13163
  const node = findVectorNode(doc.nodes, id);
11641
- return !!node && !node.blendStep && !node.locked && !state.selection.includes(_nullishCoalesce(_optionalChain([locateVectorNode, 'call', _382 => _382(doc.nodes, id), 'optionalAccess', _383 => _383.parent, 'optionalAccess', _384 => _384.id]), () => ( "")));
13164
+ return !!node && !node.blendStep && !node.locked && !state.selection.includes(_nullishCoalesce(_optionalChain([locateVectorNode, 'call', _426 => _426(doc.nodes, id), 'optionalAccess', _427 => _427.parent, 'optionalAccess', _428 => _428.id]), () => ( "")));
11642
13165
  });
11643
- const parents = new Set(roots.map((id) => _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _385 => _385(doc.nodes, id), 'optionalAccess', _386 => _386.parent, 'optionalAccess', _387 => _387.id]), () => ( null))));
11644
- const paths = roots.filter((id) => _optionalChain([findVectorNode, 'call', _388 => _388(doc.nodes, id), 'optionalAccess', _389 => _389.type]) === "path" && !isVectorBlendGroup(_optionalChain([locateVectorNode, 'call', _390 => _390(doc.nodes, id), 'optionalAccess', _391 => _391.parent])));
13166
+ const parents = new Set(roots.map((id) => _nullishCoalesce(_optionalChain([locateVectorNode, 'call', _429 => _429(doc.nodes, id), 'optionalAccess', _430 => _430.parent, 'optionalAccess', _431 => _431.id]), () => ( null))));
13167
+ const paths = roots.filter((id) => _optionalChain([findVectorNode, 'call', _432 => _432(doc.nodes, id), 'optionalAccess', _433 => _433.type]) === "path" && !isVectorBlendGroup(_optionalChain([locateVectorNode, 'call', _434 => _434(doc.nodes, id), 'optionalAccess', _435 => _435.parent])));
11645
13168
  const first = blends[0];
11646
13169
  return {
11647
13170
  ids: blends.map((g) => g.id),
11648
13171
  options: resolveVectorBlendOptions(first ? first.blend : state.blendDefaults),
11649
13172
  canBlend: roots.length >= 2 && parents.size === 1,
11650
13173
  canReplaceSpine: blends.length === 1 && paths.length === 1,
11651
- hasSpine: !!_optionalChain([first, 'optionalAccess', _392 => _392.blend, 'optionalAccess', _393 => _393.spine])
13174
+ hasSpine: !!_optionalChain([first, 'optionalAccess', _436 => _436.blend, 'optionalAccess', _437 => _437.spine])
11652
13175
  };
11653
13176
  }
11654
13177
  function applyVectorBlendOptions(controller, patch) {
@@ -11701,7 +13224,7 @@ function isVectorTextTarget(target) {
11701
13224
  if (!el || typeof el !== "object") return false;
11702
13225
  const tag = (_nullishCoalesce(el.tagName, () => ( ""))).toUpperCase();
11703
13226
  if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
11704
- return !!el.isContentEditable || _optionalChain([el, 'access', _394 => _394.getAttribute, 'optionalCall', _395 => _395("contenteditable")]) === "true";
13227
+ return !!el.isContentEditable || _optionalChain([el, 'access', _438 => _438.getAttribute, 'optionalCall', _439 => _439("contenteditable")]) === "true";
11705
13228
  }
11706
13229
  function getVectorSelectionStyle(state) {
11707
13230
  const paths = [];
@@ -11709,23 +13232,23 @@ function getVectorSelectionStyle(state) {
11709
13232
  const node = findVectorNode(state.document.nodes, id);
11710
13233
  if (node) paths.push(...collect(node));
11711
13234
  }
11712
- const anchorMode = state.tool === "direct" && !!_optionalChain([state, 'access', _396 => _396.selectedAnchors, 'optionalAccess', _397 => _397.length]);
13235
+ const anchorMode = state.tool === "direct" && !!_optionalChain([state, 'access', _440 => _440.selectedAnchors, 'optionalAccess', _441 => _441.length]);
11713
13236
  if (anchorMode) {
11714
13237
  for (const r of state.selectedAnchors) {
11715
13238
  if (paths.some((p) => p.id === r.nodeId)) continue;
11716
13239
  const node = findVectorNode(state.document.nodes, r.nodeId);
11717
- if (_optionalChain([node, 'optionalAccess', _398 => _398.type]) === "path") paths.push(node);
13240
+ if (_optionalChain([node, 'optionalAccess', _442 => _442.type]) === "path") paths.push(node);
11718
13241
  }
11719
13242
  }
11720
13243
  if (!paths.length) return null;
11721
13244
  const first = paths[0];
11722
- const same = (get) => paths.every((p) => JSON.stringify(_nullishCoalesce(get(p), () => ( null))) === JSON.stringify(_nullishCoalesce(get(first), () => ( null))));
13245
+ const same2 = (get) => paths.every((p) => JSON.stringify(_nullishCoalesce(get(p), () => ( null))) === JSON.stringify(_nullishCoalesce(get(first), () => ( null))));
11723
13246
  const corners2 = [];
11724
13247
  for (const p of paths) {
11725
13248
  for (const c of vectorCorners(p.subpaths)) {
11726
13249
  if (anchorMode && !state.selectedAnchors.some((r) => r.nodeId === p.id && r.subpath === c.subpath && r.index === c.index)) continue;
11727
13250
  const corner = p.subpaths[c.subpath].anchors[c.index].corner;
11728
- corners2.push({ radius: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _399 => _399.radius]), () => ( 0)), kind: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _400 => _400.kind]), () => ( "round")) });
13251
+ corners2.push({ radius: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _443 => _443.radius]), () => ( 0)), kind: _nullishCoalesce(_optionalChain([corner, 'optionalAccess', _444 => _444.kind]), () => ( "round")) });
11729
13252
  }
11730
13253
  }
11731
13254
  const c0 = _nullishCoalesce(corners2[0], () => ( { radius: 0, kind: "round" }));
@@ -11747,17 +13270,17 @@ function getVectorSelectionStyle(state) {
11747
13270
  corners: corners2.length,
11748
13271
  hasOpenPath: paths.some((p) => p.subpaths.some((sp) => !sp.closed && sp.anchors.length > 1)),
11749
13272
  mixed: {
11750
- fill: !same((p) => p.fill),
11751
- stroke: !same((p) => p.stroke),
11752
- strokeWidth: !same((p) => _nullishCoalesce(p.strokeWidth, () => ( 1))),
11753
- opacity: !same((p) => _nullishCoalesce(p.opacity, () => ( 1))),
11754
- strokeAlign: !same((p) => _nullishCoalesce(p.strokeAlign, () => ( "center"))),
11755
- startArrow: !same((p) => _nullishCoalesce(p.startArrow, () => ( null))),
11756
- endArrow: !same((p) => _nullishCoalesce(p.endArrow, () => ( null))),
11757
- arrowAlign: !same((p) => _nullishCoalesce(p.arrowAlign, () => ( "extend"))),
11758
- startArrowScale: !same((p) => _nullishCoalesce(p.startArrowScale, () => ( 1))),
11759
- endArrowScale: !same((p) => _nullishCoalesce(p.endArrowScale, () => ( 1))),
11760
- widthProfile: !same(profileOf),
13273
+ fill: !same2((p) => p.fill),
13274
+ stroke: !same2((p) => p.stroke),
13275
+ strokeWidth: !same2((p) => _nullishCoalesce(p.strokeWidth, () => ( 1))),
13276
+ opacity: !same2((p) => _nullishCoalesce(p.opacity, () => ( 1))),
13277
+ strokeAlign: !same2((p) => _nullishCoalesce(p.strokeAlign, () => ( "center"))),
13278
+ startArrow: !same2((p) => _nullishCoalesce(p.startArrow, () => ( null))),
13279
+ endArrow: !same2((p) => _nullishCoalesce(p.endArrow, () => ( null))),
13280
+ arrowAlign: !same2((p) => _nullishCoalesce(p.arrowAlign, () => ( "extend"))),
13281
+ startArrowScale: !same2((p) => _nullishCoalesce(p.startArrowScale, () => ( 1))),
13282
+ endArrowScale: !same2((p) => _nullishCoalesce(p.endArrowScale, () => ( 1))),
13283
+ widthProfile: !same2(profileOf),
11761
13284
  cornerRadius: corners2.some((c) => c.radius !== c0.radius),
11762
13285
  cornerKind: corners2.some((c) => c.kind !== c0.kind)
11763
13286
  },
@@ -11805,7 +13328,7 @@ function getVectorGradientEditor(state) {
11805
13328
  const sel = stopIndex !== null && sorted[stopIndex] ? { ...sorted[stopIndex], index: stopIndex, last: stopIndex === sorted.length - 1 } : null;
11806
13329
  const preview = gradient ? `linear-gradient(to right, ${expandVectorGradientStops(gradient).map((s) => {
11807
13330
  const c = parseVectorColor(s.color);
11808
- const a = (_nullishCoalesce(_optionalChain([c, 'optionalAccess', _401 => _401[3]]), () => ( 1))) * (_nullishCoalesce(s.opacity, () => ( 1)));
13331
+ const a = (_nullishCoalesce(_optionalChain([c, 'optionalAccess', _445 => _445[3]]), () => ( 1))) * (_nullishCoalesce(s.opacity, () => ( 1)));
11809
13332
  const color = c ? `rgba(${Math.round(c[0] * 255)}, ${Math.round(c[1] * 255)}, ${Math.round(c[2] * 255)}, ${Math.round(a * 1e3) / 1e3})` : s.color;
11810
13333
  return `${color} ${Math.round(s.offset * 1e4) / 100}%`;
11811
13334
  }).join(", ")})` : null;
@@ -11816,11 +13339,11 @@ function getVectorGradientEditor(state) {
11816
13339
  stops,
11817
13340
  selected: sel,
11818
13341
  preview,
11819
- type: _nullishCoalesce(_optionalChain([gradient, 'optionalAccess', _402 => _402.type]), () => ( null)),
11820
- spread: _nullishCoalesce(_optionalChain([gradient, 'optionalAccess', _403 => _403.spread]), () => ( "pad")),
11821
- interpolation: _nullishCoalesce(_optionalChain([gradient, 'optionalAccess', _404 => _404.interpolation]), () => ( "srgb")),
11822
- smoothness: _nullishCoalesce(_optionalChain([gradient, 'optionalAccess', _405 => _405.smoothness]), () => ( 0)),
11823
- strokeMode: _nullishCoalesce(_optionalChain([gradient, 'optionalAccess', _406 => _406.strokeMode]), () => ( "within")),
13342
+ type: _nullishCoalesce(_optionalChain([gradient, 'optionalAccess', _446 => _446.type]), () => ( null)),
13343
+ spread: _nullishCoalesce(_optionalChain([gradient, 'optionalAccess', _447 => _447.spread]), () => ( "pad")),
13344
+ interpolation: _nullishCoalesce(_optionalChain([gradient, 'optionalAccess', _448 => _448.interpolation]), () => ( "srgb")),
13345
+ smoothness: _nullishCoalesce(_optionalChain([gradient, 'optionalAccess', _449 => _449.smoothness]), () => ( 0)),
13346
+ strokeMode: _nullishCoalesce(_optionalChain([gradient, 'optionalAccess', _450 => _450.strokeMode]), () => ( "within")),
11824
13347
  mixed: paths.some((p) => JSON.stringify(_nullishCoalesce(p[target], () => ( null))) !== JSON.stringify(_nullishCoalesce(paint, () => ( null))))
11825
13348
  };
11826
13349
  }
@@ -11851,22 +13374,23 @@ function getVectorEffectsPanel(state) {
11851
13374
  if (!nodes.length) return null;
11852
13375
  const one = nodes.length === 1 ? nodes[0] : null;
11853
13376
  return {
11854
- nodeId: _nullishCoalesce(_optionalChain([one, 'optionalAccess', _407 => _407.id]), () => ( null)),
13377
+ nodeId: _nullishCoalesce(_optionalChain([one, 'optionalAccess', _451 => _451.id]), () => ( null)),
11855
13378
  count: nodes.length,
11856
- effects: (_nullishCoalesce(_optionalChain([one, 'optionalAccess', _408 => _408.effects]), () => ( []))).map((e) => ({
13379
+ effects: (_nullishCoalesce(_optionalChain([one, 'optionalAccess', _452 => _452.effects]), () => ( []))).map((e) => ({
11857
13380
  id: e.id,
11858
13381
  type: e.type,
11859
13382
  label: _nullishCoalesce(VECTOR_EFFECT_LABELS[e.type], () => ( e.type)),
11860
13383
  enabled: e.enabled !== false,
11861
13384
  params: e.params,
11862
- specs: _nullishCoalesce(VECTOR_EFFECT_PARAM_SPECS[e.type], () => ( []))
13385
+ // The Envelope panel (`getVectorEnvelopePanel`) edits an envelope's warp and mesh.
13386
+ specs: e.type === "envelope" ? [] : _nullishCoalesce(VECTOR_EFFECT_PARAM_SPECS[e.type], () => ( []))
11863
13387
  })),
11864
13388
  expandable: nodes.some(hasVectorAppearance)
11865
13389
  };
11866
13390
  }
11867
13391
 
11868
13392
  // src/vector/commands.ts
11869
- var EFFECT_PARAMS_DESCRIPTION = "Effect parameters (missing ones keep their value or default). trim: start, end (percent), offset (degrees), mode simultaneous|individual. roundCorners: radius. puckerBloat: amount (\u2212100\u2026100). twist: angle, center {x, y} (offset from the middle). zigzag: size, ridges, smooth. wiggle: size, detail, smooth, speed, correlation, phase, seed, time (seconds). offset: amount, join miter|round|bevel, miterLimit, copies, copyOffset. merge: mode merge|add|subtract|intersect|exclude. repeater: copies (fractions fade the last), offset, position {x, y}, anchor {x, y} (offset from the middle), rotation, scale {x, y} (percent), startOpacity, endOpacity (percent), composite below|above.";
13393
+ var EFFECT_PARAMS_DESCRIPTION = "Effect parameters (missing ones keep their value or default). trim: start, end (percent), offset (degrees), mode simultaneous|individual. roundCorners: radius. puckerBloat: amount (\u2212100\u2026100). twist: angle, center {x, y} (offset from the middle). zigzag: size, ridges, smooth. wiggle: size, detail, smooth, speed, correlation, phase, seed, time (seconds). offset: amount, join miter|round|bevel, miterLimit, copies, copyOffset. merge: mode merge|add|subtract|intersect|exclude. repeater: copies (fractions fade the last), offset, position {x, y}, anchor {x, y} (offset from the middle), rotation, scale {x, y} (percent), startOpacity, endOpacity (percent), composite below|above. envelope: style (a warp preset: arc|arcLower|arcUpper|arch|bulge|shellLower|shellUpper|flag|wave|fish|rise|fisheye|inflate|squeeze|twist, or mesh), bend, horizontal, vertical (percent, \u2212100\u2026100), orientation horizontal|vertical, rows, columns, mesh { us, vs, points } (node space; prefer vector.envelope).";
11870
13394
  var fail = (message) => {
11871
13395
  throw new Error(message);
11872
13396
  };
@@ -11907,9 +13431,9 @@ var BLEND_PROPS = {
11907
13431
  linear: { type: "boolean", description: "Move anchors in straight lines instead of the rotation-aware morph." }
11908
13432
  };
11909
13433
  var checkBlendOptions = (params) => {
11910
- if (_optionalChain([params, 'optionalAccess', _409 => _409.spacing]) !== void 0 && !VECTOR_BLEND_SPACINGS.includes(params.spacing)) fail(`Unknown blend spacing "${params.spacing}".`);
11911
- if (_optionalChain([params, 'optionalAccess', _410 => _410.steps]) !== void 0 && !(Number.isFinite(params.steps) && params.steps >= 1)) fail("steps must be at least 1.");
11912
- if (_optionalChain([params, 'optionalAccess', _411 => _411.distance]) !== void 0 && !(Number.isFinite(params.distance) && params.distance > 0)) fail("distance must be positive.");
13434
+ if (_optionalChain([params, 'optionalAccess', _453 => _453.spacing]) !== void 0 && !VECTOR_BLEND_SPACINGS.includes(params.spacing)) fail(`Unknown blend spacing "${params.spacing}".`);
13435
+ if (_optionalChain([params, 'optionalAccess', _454 => _454.steps]) !== void 0 && !(Number.isFinite(params.steps) && params.steps >= 1)) fail("steps must be at least 1.");
13436
+ if (_optionalChain([params, 'optionalAccess', _455 => _455.distance]) !== void 0 && !(Number.isFinite(params.distance) && params.distance > 0)) fail("distance must be positive.");
11913
13437
  };
11914
13438
  var POINT = { type: "object", properties: { x: { type: "number" }, y: { type: "number" } }, required: ["x", "y"] };
11915
13439
  var GRADIENT_PROPS = {
@@ -11981,17 +13505,17 @@ function createVectorCommands(controller, options = {}) {
11981
13505
  const base = { group, ...options.scope ? { scope: options.scope } : {} };
11982
13506
  const hasSelection = () => controller.getState().selection.length ? true : "Nothing is selected.";
11983
13507
  const ids = (params) => {
11984
- const list2 = _nullishCoalesce(_optionalChain([params, 'optionalAccess', _412 => _412.ids]), () => ( controller.getState().selection));
13508
+ const list2 = _nullishCoalesce(_optionalChain([params, 'optionalAccess', _456 => _456.ids]), () => ( controller.getState().selection));
11985
13509
  for (const id of list2) if (!controller.getNode(id)) fail(`There is no node "${id}".`);
11986
13510
  if (!list2.length) fail("Nothing is selected; pass ids.");
11987
13511
  return list2;
11988
13512
  };
11989
- const enabledFor = (_, params) => _optionalChain([params, 'optionalAccess', _413 => _413.ids, 'optionalAccess', _414 => _414.length]) ? true : hasSelection();
13513
+ const enabledFor = (_, params) => _optionalChain([params, 'optionalAccess', _457 => _457.ids, 'optionalAccess', _458 => _458.length]) ? true : hasSelection();
11990
13514
  const anchorsOf = (refs) => {
11991
13515
  if (!refs) return [...controller.getState().selectedAnchors];
11992
13516
  for (const r of refs) {
11993
13517
  const node = controller.getNode(r.nodeId);
11994
- if (_optionalChain([node, 'optionalAccess', _415 => _415.type]) !== "path" || !_optionalChain([node, 'access', _416 => _416.subpaths, 'access', _417 => _417[r.subpath], 'optionalAccess', _418 => _418.anchors, 'access', _419 => _419[r.index]])) fail(`There is no anchor ${r.index} on subpath ${r.subpath} of "${r.nodeId}".`);
13518
+ if (_optionalChain([node, 'optionalAccess', _459 => _459.type]) !== "path" || !_optionalChain([node, 'access', _460 => _460.subpaths, 'access', _461 => _461[r.subpath], 'optionalAccess', _462 => _462.anchors, 'access', _463 => _463[r.index]])) fail(`There is no anchor ${r.index} on subpath ${r.subpath} of "${r.nodeId}".`);
11995
13519
  }
11996
13520
  return refs;
11997
13521
  };
@@ -12015,7 +13539,7 @@ function createVectorCommands(controller, options = {}) {
12015
13539
  ...n.type === "path" ? { fill: _nullishCoalesce(n.fill, () => ( null)), stroke: _nullishCoalesce(n.stroke, () => ( null)), strokeWidth: _nullishCoalesce(n.strokeWidth, () => ( 1)), d: vectorPathData(n, 2) } : { children: n.children.length },
12016
13540
  ...n.type === "group" && n.blend ? { blend: { ...resolveVectorBlendOptions(n.blend), spine: !!n.blend.spine, keys: vectorBlendKeys(n).map((k) => k.id) } } : {},
12017
13541
  ...n.blendStep ? { blendStep: true } : {},
12018
- ..._optionalChain([n, 'access', _420 => _420.effects, 'optionalAccess', _421 => _421.length]) ? { effects: n.effects } : {},
13542
+ ..._optionalChain([n, 'access', _464 => _464.effects, 'optionalAccess', _465 => _465.length]) ? { effects: n.effects } : {},
12019
13543
  ...n.type === "group" && n.liveBoolean ? { liveBoolean: n.liveBoolean } : {},
12020
13544
  ...n.booleanOperation ? { booleanOperation: n.booleanOperation } : {}
12021
13545
  });
@@ -12087,7 +13611,7 @@ function createVectorCommands(controller, options = {}) {
12087
13611
  run: (_ctx, params) => {
12088
13612
  const id = controller.addPath(params.d, { ...pickStyle(params), ...params.name ? { name: params.name } : {} });
12089
13613
  const node = controller.getNode(id);
12090
- if (_optionalChain([node, 'optionalAccess', _422 => _422.type]) === "path" && !node.subpaths.length) {
13614
+ if (_optionalChain([node, 'optionalAccess', _466 => _466.type]) === "path" && !node.subpaths.length) {
12091
13615
  controller.undo();
12092
13616
  fail("The path data has no points.");
12093
13617
  }
@@ -12126,7 +13650,7 @@ function createVectorCommands(controller, options = {}) {
12126
13650
  check(controller.setGradient(patch, { ids: ids(params), target: _nullishCoalesce(target, () => ( "fill")) }));
12127
13651
  const id = ids(params)[0];
12128
13652
  const node = id ? controller.getNode(id) : void 0;
12129
- const path = _optionalChain([node, 'optionalAccess', _423 => _423.type]) === "path" ? node : void 0;
13653
+ const path = _optionalChain([node, 'optionalAccess', _467 => _467.type]) === "path" ? node : void 0;
12130
13654
  return { ok: true, ...path ? { gradient: path[_nullishCoalesce(target, () => ( "fill"))] } : {} };
12131
13655
  }
12132
13656
  },
@@ -12139,10 +13663,10 @@ function createVectorCommands(controller, options = {}) {
12139
13663
  params: { type: "object", properties: { radius: { type: "number", minimum: 0 }, kind: { type: "string", enum: VECTOR_CORNER_KINDS }, ids: IDS, anchors: ANCHORS } },
12140
13664
  undoable: true,
12141
13665
  run: (_ctx, params) => {
12142
- const refs = _optionalChain([params, 'optionalAccess', _424 => _424.anchors]) ? anchorsOf(params.anchors) : void 0;
12143
- const target = { refs, ids: _optionalChain([params, 'optionalAccess', _425 => _425.ids]) ? ids(params) : void 0 };
12144
- if (_optionalChain([params, 'optionalAccess', _426 => _426.radius]) !== void 0) check(controller.setCornerRadius(params.radius, { ...target, kind: params.kind }));
12145
- else if (_optionalChain([params, 'optionalAccess', _427 => _427.kind])) check(controller.setCornerKind(params.kind, target));
13666
+ const refs = _optionalChain([params, 'optionalAccess', _468 => _468.anchors]) ? anchorsOf(params.anchors) : void 0;
13667
+ const target = { refs, ids: _optionalChain([params, 'optionalAccess', _469 => _469.ids]) ? ids(params) : void 0 };
13668
+ if (_optionalChain([params, 'optionalAccess', _470 => _470.radius]) !== void 0) check(controller.setCornerRadius(params.radius, { ...target, kind: params.kind }));
13669
+ else if (_optionalChain([params, 'optionalAccess', _471 => _471.kind])) check(controller.setCornerKind(params.kind, target));
12146
13670
  else fail("Pass `radius` and / or `kind`.");
12147
13671
  return { ok: true };
12148
13672
  }
@@ -12177,12 +13701,12 @@ function createVectorCommands(controller, options = {}) {
12177
13701
  undoable: true,
12178
13702
  run: (_ctx, params) => {
12179
13703
  const target = { ids: ids(params) };
12180
- if (_optionalChain([params, 'optionalAccess', _428 => _428.preset])) check(controller.setWidthProfile(params.preset, target));
12181
- else if (_optionalChain([params, 'optionalAccess', _429 => _429.points]) !== void 0) check(controller.setWidthProfile(_nullishCoalesce(params.points, () => ( null)), target));
12182
- else if (_optionalChain([params, 'optionalAccess', _430 => _430.taper]) || _optionalChain([params, 'optionalAccess', _431 => _431.wave])) check(controller.setWidthProfile({ taper: params.taper, wave: params.wave }, target));
13704
+ if (_optionalChain([params, 'optionalAccess', _472 => _472.preset])) check(controller.setWidthProfile(params.preset, target));
13705
+ else if (_optionalChain([params, 'optionalAccess', _473 => _473.points]) !== void 0) check(controller.setWidthProfile(_nullishCoalesce(params.points, () => ( null)), target));
13706
+ else if (_optionalChain([params, 'optionalAccess', _474 => _474.taper]) || _optionalChain([params, 'optionalAccess', _475 => _475.wave])) check(controller.setWidthProfile({ taper: params.taper, wave: params.wave }, target));
12183
13707
  else fail("Pass `preset`, `points`, `taper` or `wave`.");
12184
13708
  const node = controller.getNode(target.ids[0]);
12185
- return { ok: true, points: _optionalChain([node, 'optionalAccess', _432 => _432.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
13709
+ return { ok: true, points: _optionalChain([node, 'optionalAccess', _476 => _476.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
12186
13710
  }
12187
13711
  },
12188
13712
  {
@@ -12204,10 +13728,10 @@ function createVectorCommands(controller, options = {}) {
12204
13728
  },
12205
13729
  undoable: true,
12206
13730
  run: (_ctx, params) => {
12207
- if (!_optionalChain([params, 'optionalAccess', _433 => _433.id])) fail("Pass the path `id`.");
13731
+ if (!_optionalChain([params, 'optionalAccess', _477 => _477.id])) fail("Pass the path `id`.");
12208
13732
  check(controller.setWidthPoint({ nodeId: params.id, index: _nullishCoalesce(params.index, () => ( null)) }, { t: params.t, left: params.left, right: params.right }));
12209
13733
  const node = controller.getNode(params.id);
12210
- return { ok: true, points: _optionalChain([node, 'optionalAccess', _434 => _434.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
13734
+ return { ok: true, points: _optionalChain([node, 'optionalAccess', _478 => _478.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
12211
13735
  }
12212
13736
  },
12213
13737
  {
@@ -12220,11 +13744,119 @@ function createVectorCommands(controller, options = {}) {
12220
13744
  enabled: enabledFor,
12221
13745
  undoable: true,
12222
13746
  run: (_ctx, params) => {
12223
- const created = controller.outlineStroke({ ids: _optionalChain([params, 'optionalAccess', _435 => _435.ids]) ? ids(params) : void 0 });
13747
+ const created = controller.outlineStroke({ ids: _optionalChain([params, 'optionalAccess', _479 => _479.ids]) ? ids(params) : void 0 });
12224
13748
  if (!created.length) fail("No selected path has a stroke.");
12225
13749
  return { ids: created };
12226
13750
  }
12227
13751
  },
13752
+ {
13753
+ ...base,
13754
+ id: `${prefix}distort`,
13755
+ label: "Free Distort\u2026",
13756
+ keywords: ["distort", "perspective", "free distort", "corners", "projective", "keystone"],
13757
+ description: "Free Distort: moves the four corners of the selection box (clockwise from the top left, in the box\u2019s own rotation) to `corners` in document units, distorting the nodes in perspective (straight lines stay straight; curves are followed within `tolerance`). The corners must make a convex quadrilateral. One undo step.",
13758
+ params: {
13759
+ type: "object",
13760
+ properties: {
13761
+ ids: IDS,
13762
+ corners: { type: "array", items: POINT, minItems: 4, maxItems: 4, description: "New top-left, top-right, bottom-right and bottom-left corners." },
13763
+ tolerance: { type: "number", exclusiveMinimum: 0, description: "How closely curves follow the distortion (document units, default 0.05)." }
13764
+ },
13765
+ required: ["corners"]
13766
+ },
13767
+ enabled: enabledFor,
13768
+ undoable: true,
13769
+ run: (_ctx, params) => {
13770
+ check(controller.distort(params.corners, { ids: ids(params), tolerance: params.tolerance }));
13771
+ const frame2 = controller.getState().selectionFrame;
13772
+ return { ok: true, bounds: frame2 ? { x: frame2.x, y: frame2.y, width: frame2.width, height: frame2.height } : null };
13773
+ }
13774
+ },
13775
+ {
13776
+ ...base,
13777
+ id: `${prefix}skew`,
13778
+ label: "Skew\u2026",
13779
+ keywords: ["skew", "shear", "slant", "oblique"],
13780
+ description: "Skews nodes along the selection box\u2019s axes: `ax` degrees horizontally (vertical lines lean right for positive angles) and `ay` degrees vertically, about the box centre or `origin`. One undo step.",
13781
+ params: {
13782
+ type: "object",
13783
+ properties: {
13784
+ ids: IDS,
13785
+ ax: { type: "number", minimum: -89.9, maximum: 89.9 },
13786
+ ay: { type: "number", minimum: -89.9, maximum: 89.9 },
13787
+ origin: POINT
13788
+ }
13789
+ },
13790
+ enabled: enabledFor,
13791
+ undoable: true,
13792
+ run: (_ctx, params) => {
13793
+ check(controller.skew(_nullishCoalesce(params.ax, () => ( 0)), _nullishCoalesce(params.ay, () => ( 0)), { ids: ids(params), origin: params.origin }));
13794
+ return { ok: true };
13795
+ }
13796
+ },
13797
+ {
13798
+ ...base,
13799
+ id: `${prefix}envelope`,
13800
+ label: "Envelope Distort\u2026",
13801
+ keywords: ["envelope", "warp", "mesh", "arc", "arch", "bulge", "flag", "wave", "fish", "rise", "fisheye", "inflate", "squeeze", "twist", "shell", "bend", "distort"],
13802
+ description: "Envelope distortion that stays editable (a live `envelope` effect). Give `preset` (with `bend`, `horizontal`, `vertical` in percent, \u2212100\u2026100, and `orientation`) to warp, or `mesh` ({ rows, columns } and optionally `points`, the control grid row by row in the node\u2019s own space) for an editable mesh; a node that already has an envelope is changed. `topObject: true` uses the topmost selected closed path as the envelope of the others; `release: true` removes the envelope and gives back its shape as a path; `expand: true` bakes it (Expand Appearance). One undo step.",
13803
+ params: {
13804
+ type: "object",
13805
+ properties: {
13806
+ ids: IDS,
13807
+ preset: { type: "string", enum: VECTOR_WARP_STYLES },
13808
+ bend: { type: "number", minimum: -100, maximum: 100 },
13809
+ horizontal: { type: "number", minimum: -100, maximum: 100 },
13810
+ vertical: { type: "number", minimum: -100, maximum: 100 },
13811
+ orientation: { type: "string", enum: ["horizontal", "vertical"] },
13812
+ mesh: {
13813
+ type: "object",
13814
+ properties: {
13815
+ rows: { type: "integer", minimum: 1, maximum: 16 },
13816
+ columns: { type: "integer", minimum: 1, maximum: 16 },
13817
+ points: { type: "array", items: POINT, description: "(3\xB7columns + 1) \xD7 (3\xB7rows + 1) control points, row by row (node space)." }
13818
+ }
13819
+ },
13820
+ topObject: { type: "boolean" },
13821
+ release: { type: "boolean" },
13822
+ expand: { type: "boolean" }
13823
+ }
13824
+ },
13825
+ enabled: enabledFor,
13826
+ undoable: true,
13827
+ run: (_ctx, params) => {
13828
+ const target = ids(params);
13829
+ if (params.release) return { released: target, shapes: controller.releaseEnvelope({ ids: target }) };
13830
+ if (params.expand) return { expanded: controller.expandAppearance({ ids: target }) };
13831
+ if (params.topObject) {
13832
+ const r = controller.makeEnvelopeWithTopObject({ ids: target, rows: _optionalChain([params, 'access', _480 => _480.mesh, 'optionalAccess', _481 => _481.rows]), columns: _optionalChain([params, 'access', _482 => _482.mesh, 'optionalAccess', _483 => _483.columns]) });
13833
+ check(r);
13834
+ return { nodeId: r.nodeId };
13835
+ }
13836
+ if (params.preset !== void 0 && !VECTOR_WARP_STYLES.includes(params.preset)) fail(`Unknown warp preset "${params.preset}".`);
13837
+ const patch = {};
13838
+ if (params.preset) patch.style = params.preset;
13839
+ for (const k of ["bend", "horizontal", "vertical"]) if (params[k] !== void 0) patch[k] = params[k];
13840
+ if (params.orientation) patch.orientation = params.orientation;
13841
+ if (params.mesh) {
13842
+ if (params.preset) fail("Give either `preset` or `mesh`, not both.");
13843
+ patch.style = "mesh";
13844
+ const columns = _nullishCoalesce(params.mesh.columns, () => ( 2));
13845
+ const rows = _nullishCoalesce(params.mesh.rows, () => ( 2));
13846
+ patch.columns = columns;
13847
+ patch.rows = rows;
13848
+ if (params.mesh.points) {
13849
+ const even = (n) => Array.from({ length: n + 1 }, (_, i) => i / n);
13850
+ const mesh = { us: even(columns), vs: even(rows), points: params.mesh.points.map((p) => ({ x: p.x, y: p.y })) };
13851
+ if (!isValidVectorMesh(mesh)) fail(`A ${columns} \xD7 ${rows} mesh needs ${(3 * columns + 1) * (3 * rows + 1)} finite points.`);
13852
+ patch.mesh = mesh;
13853
+ }
13854
+ }
13855
+ const made = controller.envelope(patch, { ids: target });
13856
+ if (!made.length) fail("Nothing to envelope.");
13857
+ return { envelopes: made };
13858
+ }
13859
+ },
12228
13860
  {
12229
13861
  ...base,
12230
13862
  id: `${prefix}transform`,
@@ -12337,7 +13969,7 @@ function createVectorCommands(controller, options = {}) {
12337
13969
  run: (_ctx, params) => {
12338
13970
  if (params.params !== void 0 || params.enabled !== void 0) check(controller.updateEffect(params.nodeId, params.effectId, { params: params.params, enabled: params.enabled }));
12339
13971
  if (params.index !== void 0) check(controller.moveEffect(params.nodeId, params.effectId, params.index));
12340
- return { effects: _nullishCoalesce(_optionalChain([controller, 'access', _436 => _436.getNode, 'call', _437 => _437(params.nodeId), 'optionalAccess', _438 => _438.effects]), () => ( [])) };
13972
+ return { effects: _nullishCoalesce(_optionalChain([controller, 'access', _484 => _484.getNode, 'call', _485 => _485(params.nodeId), 'optionalAccess', _486 => _486.effects]), () => ( [])) };
12341
13973
  }
12342
13974
  },
12343
13975
  {
@@ -12401,7 +14033,7 @@ function createVectorCommands(controller, options = {}) {
12401
14033
  undoable: true,
12402
14034
  run: (_ctx, params) => {
12403
14035
  checkBlendOptions(params);
12404
- const r = controller.setBlendOptions(_nullishCoalesce(params, () => ( {})), { ids: _optionalChain([params, 'optionalAccess', _439 => _439.ids]) });
14036
+ const r = controller.setBlendOptions(_nullishCoalesce(params, () => ( {})), { ids: _optionalChain([params, 'optionalAccess', _487 => _487.ids]) });
12405
14037
  if (!r.ok) fail(r.message);
12406
14038
  return { ok: true };
12407
14039
  }
@@ -12415,7 +14047,7 @@ function createVectorCommands(controller, options = {}) {
12415
14047
  params: { type: "object", properties: { ids: IDS } },
12416
14048
  undoable: true,
12417
14049
  run: (_ctx, params) => {
12418
- const groups = controller.expandBlend({ ids: _optionalChain([params, 'optionalAccess', _440 => _440.ids]) });
14050
+ const groups = controller.expandBlend({ ids: _optionalChain([params, 'optionalAccess', _488 => _488.ids]) });
12419
14051
  if (!groups.length) fail("Select a blend to expand.");
12420
14052
  return { ids: groups };
12421
14053
  }
@@ -12429,7 +14061,7 @@ function createVectorCommands(controller, options = {}) {
12429
14061
  params: { type: "object", properties: { ids: IDS } },
12430
14062
  undoable: true,
12431
14063
  run: (_ctx, params) => {
12432
- const released = controller.releaseBlend({ ids: _optionalChain([params, 'optionalAccess', _441 => _441.ids]) });
14064
+ const released = controller.releaseBlend({ ids: _optionalChain([params, 'optionalAccess', _489 => _489.ids]) });
12433
14065
  if (!released.length) fail("Select a blend to release.");
12434
14066
  return { ids: released };
12435
14067
  }
@@ -12443,7 +14075,7 @@ function createVectorCommands(controller, options = {}) {
12443
14075
  params: { type: "object", properties: { ids: IDS } },
12444
14076
  undoable: true,
12445
14077
  run: (_ctx, params) => {
12446
- const r = controller.replaceBlendSpine({ ids: _optionalChain([params, 'optionalAccess', _442 => _442.ids]) });
14078
+ const r = controller.replaceBlendSpine({ ids: _optionalChain([params, 'optionalAccess', _490 => _490.ids]) });
12447
14079
  if (!r.ok) fail(r.message);
12448
14080
  return { ok: true };
12449
14081
  }
@@ -12557,7 +14189,7 @@ function createVectorCommands(controller, options = {}) {
12557
14189
  enabled: enabledFor,
12558
14190
  undoable: true,
12559
14191
  run: (_ctx, params) => {
12560
- const id = controller.group({ ids: ids(params), name: _optionalChain([params, 'optionalAccess', _443 => _443.name]) });
14192
+ const id = controller.group({ ids: ids(params), name: _optionalChain([params, 'optionalAccess', _491 => _491.name]) });
12561
14193
  if (!id) fail("Only nodes that share a parent can be grouped.");
12562
14194
  return { id };
12563
14195
  }
@@ -12585,7 +14217,7 @@ function createVectorCommands(controller, options = {}) {
12585
14217
  params: { type: "object", properties: { anchors: ANCHORS, keepShape: { type: "boolean" } } },
12586
14218
  undoable: true,
12587
14219
  run: (_ctx, params) => {
12588
- check(controller.deleteAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _444 => _444.anchors])), { keepShape: _optionalChain([params, 'optionalAccess', _445 => _445.keepShape]) }));
14220
+ check(controller.deleteAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _492 => _492.anchors])), { keepShape: _optionalChain([params, 'optionalAccess', _493 => _493.keepShape]) }));
12589
14221
  return { ok: true };
12590
14222
  }
12591
14223
  },
@@ -12640,7 +14272,7 @@ function createVectorCommands(controller, options = {}) {
12640
14272
  params: { type: "object", properties: { ids: IDS, tolerance: { type: "number", minimum: 0 } } },
12641
14273
  undoable: true,
12642
14274
  run: (_ctx, params) => {
12643
- check(controller.joinPaths({ ids: _optionalChain([params, 'optionalAccess', _446 => _446.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _447 => _447.tolerance]) }));
14275
+ check(controller.joinPaths({ ids: _optionalChain([params, 'optionalAccess', _494 => _494.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _495 => _495.tolerance]) }));
12644
14276
  return { selection: controller.getState().selection };
12645
14277
  }
12646
14278
  },
@@ -12654,7 +14286,7 @@ function createVectorCommands(controller, options = {}) {
12654
14286
  params: { type: "object", properties: { axis: { type: "string", enum: ["horizontal", "vertical", "both"] }, anchors: ANCHORS } },
12655
14287
  undoable: true,
12656
14288
  run: (_ctx, params) => {
12657
- check(controller.averageAnchors(_nullishCoalesce(_optionalChain([params, 'optionalAccess', _448 => _448.axis]), () => ( "both")), anchorsOf(_optionalChain([params, 'optionalAccess', _449 => _449.anchors]))));
14289
+ check(controller.averageAnchors(_nullishCoalesce(_optionalChain([params, 'optionalAccess', _496 => _496.axis]), () => ( "both")), anchorsOf(_optionalChain([params, 'optionalAccess', _497 => _497.anchors]))));
12658
14290
  return { ok: true };
12659
14291
  }
12660
14292
  },
@@ -12668,7 +14300,7 @@ function createVectorCommands(controller, options = {}) {
12668
14300
  enabled: enabledFor,
12669
14301
  undoable: true,
12670
14302
  run: (_ctx, params) => {
12671
- check(controller.removeRedundantPoints({ ids: _optionalChain([params, 'optionalAccess', _450 => _450.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _451 => _451.tolerance]) }));
14303
+ check(controller.removeRedundantPoints({ ids: _optionalChain([params, 'optionalAccess', _498 => _498.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _499 => _499.tolerance]) }));
12672
14304
  return { ok: true };
12673
14305
  }
12674
14306
  },
@@ -12681,7 +14313,7 @@ function createVectorCommands(controller, options = {}) {
12681
14313
  params: { type: "object", properties: { ids: IDS, amount: { type: "number", minimum: 0, maximum: 1 }, anchors: ANCHORS } },
12682
14314
  undoable: true,
12683
14315
  run: (_ctx, params) => {
12684
- check(controller.smoothPaths({ ids: _optionalChain([params, 'optionalAccess', _452 => _452.ids]) ? ids(params) : void 0, amount: _optionalChain([params, 'optionalAccess', _453 => _453.amount]), refs: _optionalChain([params, 'optionalAccess', _454 => _454.anchors]) }));
14316
+ check(controller.smoothPaths({ ids: _optionalChain([params, 'optionalAccess', _500 => _500.ids]) ? ids(params) : void 0, amount: _optionalChain([params, 'optionalAccess', _501 => _501.amount]), refs: _optionalChain([params, 'optionalAccess', _502 => _502.anchors]) }));
12685
14317
  return { ok: true };
12686
14318
  }
12687
14319
  },
@@ -12694,14 +14326,14 @@ function createVectorCommands(controller, options = {}) {
12694
14326
  params: { type: "object", properties: { nodeId: { type: "string" }, x: { type: "number" }, y: { type: "number" }, anchors: ANCHORS } },
12695
14327
  undoable: true,
12696
14328
  run: (_ctx, params) => {
12697
- if (_optionalChain([params, 'optionalAccess', _455 => _455.nodeId]) !== void 0) {
14329
+ if (_optionalChain([params, 'optionalAccess', _503 => _503.nodeId]) !== void 0) {
12698
14330
  if (!controller.getNode(params.nodeId)) fail(`There is no node "${params.nodeId}".`);
12699
14331
  if (params.x === void 0 || params.y === void 0) fail("Pass x and y with nodeId.");
12700
14332
  const created = controller.cutPathAt(params.nodeId, { x: params.x, y: params.y });
12701
14333
  if (!created) fail("Nothing to cut there (the end of an open path, or a locked path).");
12702
14334
  return { ids: created };
12703
14335
  }
12704
- check(controller.cutAtAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _456 => _456.anchors]))));
14336
+ check(controller.cutAtAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _504 => _504.anchors]))));
12705
14337
  return { ids: controller.getState().selection };
12706
14338
  }
12707
14339
  },
@@ -12752,7 +14384,7 @@ function createVectorCommands(controller, options = {}) {
12752
14384
  },
12753
14385
  run: (_ctx, params) => {
12754
14386
  const patch = {};
12755
- for (const key of ["keepShapeOnDelete", "curvatureMoves", "pencilSmoothing", "recognizeShapes", "eraserSize", "pencilPressure"]) if (_optionalChain([params, 'optionalAccess', _457 => _457[key]]) !== void 0) patch[key] = params[key];
14387
+ for (const key of ["keepShapeOnDelete", "curvatureMoves", "pencilSmoothing", "recognizeShapes", "eraserSize", "pencilPressure"]) if (_optionalChain([params, 'optionalAccess', _505 => _505[key]]) !== void 0) patch[key] = params[key];
12756
14388
  controller.setEditing(patch);
12757
14389
  return { editing: controller.getState().editing };
12758
14390
  }
@@ -12777,7 +14409,7 @@ function createVectorCommands(controller, options = {}) {
12777
14409
  keywords: ["download", "save", "markup"],
12778
14410
  description: "Returns the document as SVG markup.",
12779
14411
  params: { type: "object", properties: { precision: { type: "integer", minimum: 0, maximum: 8 } } },
12780
- run: (_ctx, params) => ({ svg: controller.toSvg({ precision: _optionalChain([params, 'optionalAccess', _458 => _458.precision]) }) })
14412
+ run: (_ctx, params) => ({ svg: controller.toSvg({ precision: _optionalChain([params, 'optionalAccess', _506 => _506.precision]) }) })
12781
14413
  },
12782
14414
  {
12783
14415
  ...base,
@@ -13136,5 +14768,54 @@ function createVectorCommands(controller, options = {}) {
13136
14768
 
13137
14769
 
13138
14770
 
13139
- exports.DEFAULT_VECTOR_BLEND_DISTANCE = DEFAULT_VECTOR_BLEND_DISTANCE; exports.DEFAULT_VECTOR_BLEND_STEPS = DEFAULT_VECTOR_BLEND_STEPS; 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_BLEND_MAX_SMOOTH_STEPS = VECTOR_BLEND_MAX_SMOOTH_STEPS; exports.VECTOR_BLEND_MAX_STEPS = VECTOR_BLEND_MAX_STEPS; exports.VECTOR_BLEND_SPACINGS = VECTOR_BLEND_SPACINGS; exports.VECTOR_BLEND_SPACING_LABELS = VECTOR_BLEND_SPACING_LABELS; exports.VECTOR_BUILDER_HATCH_GAP = VECTOR_BUILDER_HATCH_GAP; exports.VECTOR_CLIPBOARD_TYPE = VECTOR_CLIPBOARD_TYPE; exports.VECTOR_CONSTRUCTION_ANGLES = VECTOR_CONSTRUCTION_ANGLES; exports.VECTOR_CORNER_KINDS = VECTOR_CORNER_KINDS; exports.VECTOR_CORNER_KIND_LABELS = VECTOR_CORNER_KIND_LABELS; exports.VECTOR_CORNER_WIDGET_INSET = VECTOR_CORNER_WIDGET_INSET; exports.VECTOR_EDIT_TOGGLES = VECTOR_EDIT_TOGGLES; exports.VECTOR_EFFECT_DEFAULTS = VECTOR_EFFECT_DEFAULTS; exports.VECTOR_EFFECT_LABELS = VECTOR_EFFECT_LABELS; exports.VECTOR_EFFECT_MENU = VECTOR_EFFECT_MENU; exports.VECTOR_EFFECT_PARAM_SPECS = VECTOR_EFFECT_PARAM_SPECS; exports.VECTOR_EFFECT_TYPES = VECTOR_EFFECT_TYPES; exports.VECTOR_FILL_GAP = VECTOR_FILL_GAP; exports.VECTOR_GRADIENT_INTERPOLATIONS = VECTOR_GRADIENT_INTERPOLATIONS; exports.VECTOR_GRADIENT_INTERPOLATION_LABELS = VECTOR_GRADIENT_INTERPOLATION_LABELS; exports.VECTOR_GRADIENT_MAX_PERIODS = VECTOR_GRADIENT_MAX_PERIODS; exports.VECTOR_GRADIENT_MIDPOINT_GAP = VECTOR_GRADIENT_MIDPOINT_GAP; exports.VECTOR_GRADIENT_MIN_STOPS = VECTOR_GRADIENT_MIN_STOPS; exports.VECTOR_GRADIENT_OFF_BAR = VECTOR_GRADIENT_OFF_BAR; exports.VECTOR_GRADIENT_SPREADS = VECTOR_GRADIENT_SPREADS; exports.VECTOR_GRADIENT_SPREAD_LABELS = VECTOR_GRADIENT_SPREAD_LABELS; exports.VECTOR_GRADIENT_STOP_GAP = VECTOR_GRADIENT_STOP_GAP; exports.VECTOR_GRADIENT_TYPES = VECTOR_GRADIENT_TYPES; exports.VECTOR_GRADIENT_TYPE_LABELS = VECTOR_GRADIENT_TYPE_LABELS; exports.VECTOR_INK_MAX_CORNERS = VECTOR_INK_MAX_CORNERS; exports.VECTOR_MERGE_MODES = VECTOR_MERGE_MODES; 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_STROKE_GRADIENT_MODES = VECTOR_STROKE_GRADIENT_MODES; exports.VECTOR_STROKE_GRADIENT_MODE_LABELS = VECTOR_STROKE_GRADIENT_MODE_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.activeVectorEffects = activeVectorEffects; exports.addBuilderHit = addBuilderHit; exports.applyMatrix = applyMatrix; exports.applyMatrixLinear = applyMatrixLinear; exports.applyVectorBlendOptions = applyVectorBlendOptions; exports.applyVectorCornersAttribute = applyVectorCornersAttribute; exports.applyVectorEffects = applyVectorEffects; exports.applyVectorGradientPatch = applyVectorGradientPatch; exports.applyVectorGradientSpread = applyVectorGradientSpread; exports.arrowheadInset = arrowheadInset; exports.arrowheadPath = arrowheadPath; exports.arrowheadWeight = arrowheadWeight; exports.bendSegment = bendSegment; exports.bezierToSubpaths = bezierToSubpaths; exports.boundsFromPoints = boundsFromPoints; exports.boundsIntersect = boundsIntersect; exports.clearVectorLiveBooleanCache = clearVectorLiveBooleanCache; exports.cloneAnchor = cloneAnchor; exports.cloneSubpath = cloneSubpath; exports.cloneVectorDocument = cloneVectorDocument; exports.cloneVectorNode = cloneVectorNode; exports.collectPathNodes = collectPathNodes; exports.constrainToLeave = constrainToLeave; exports.convertAnchor = convertAnchor; exports.convertVectorGradient = convertVectorGradient; exports.cornerBisectorPoint = cornerBisectorPoint; exports.cornerRadiusChange = cornerRadiusChange; exports.cornerSetback = cornerSetback; exports.correspondMorphContours = correspondMorphContours; exports.createVectorCommands = createVectorCommands; exports.createVectorEffect = createVectorEffect; exports.createVectorMorph = createVectorMorph; exports.curvatureMoveAnchor = curvatureMoveAnchor; exports.cutSubpathAt = cutSubpathAt; exports.dashIntervals = dashIntervals; exports.decomposeRigid = decomposeRigid; exports.defaultVectorGradient = defaultVectorGradient; exports.effectPathLength = effectPathLength; exports.effectPathVertexCount = effectPathVertexCount; exports.effectiveStrokeAlign = effectiveStrokeAlign; exports.ellipseSubpath = ellipseSubpath; exports.eraseFromFill = eraseFromFill; exports.eraseFromOutline = eraseFromOutline; exports.eraserRegion = eraserRegion; exports.evaluateVectorPathKeyframes = evaluateVectorPathKeyframes; exports.expandVectorAppearance = expandVectorAppearance; exports.expandVectorAppearances = expandVectorAppearances; exports.expandVectorBlend = expandVectorBlend; exports.expandVectorCorners = expandVectorCorners; exports.expandVectorCornersOf = expandVectorCornersOf; exports.expandVectorGradientSpread = expandVectorGradientSpread; exports.expandVectorGradientStops = expandVectorGradientStops; exports.explicitVectorGradient = explicitVectorGradient; exports.findVectorNode = findVectorNode; exports.fitCornerRadius = fitCornerRadius; exports.foldVectorBooleanOperands = foldVectorBooleanOperands; exports.generateVectorBlendChildren = generateVectorBlendChildren; exports.generateWidthProfile = generateWidthProfile; exports.getAnchor = getAnchor; exports.getAnchorWorld = getAnchorWorld; exports.getEditablePathIds = getEditablePathIds; exports.getTransformHandlePositions = getTransformHandlePositions; exports.getVectorBlendControls = getVectorBlendControls; exports.getVectorCornerWidgets = getVectorCornerWidgets; exports.getVectorEffectsPanel = getVectorEffectsPanel; exports.getVectorEnteredGroups = getVectorEnteredGroups; exports.getVectorGradientAnnotator = getVectorGradientAnnotator; exports.getVectorGradientEditor = getVectorGradientEditor; 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.gradientMidpointRemap = gradientMidpointRemap; exports.hasExplicitGradientGeometry = hasExplicitGradientGeometry; exports.hasOwnVectorAppearance = hasOwnVectorAppearance; exports.hasPaint = hasPaint; exports.hasStrokeExtras = hasStrokeExtras; exports.hasVectorAppearance = hasVectorAppearance; exports.hasVectorCorners = hasVectorCorners; exports.hitTestVectorNode = hitTestVectorNode; exports.hitTestVectorNodes = hitTestVectorNodes; exports.hitTestVectorStroke = hitTestVectorStroke; exports.hitVectorGradientAnnotator = hitVectorGradientAnnotator; exports.inferAnchorType = inferAnchorType; exports.insertAnchor = insertAnchor; exports.insertVectorGradientStop = insertVectorGradientStop; exports.insertWidthPoint = insertWidthPoint; exports.interpolateMorphContours = interpolateMorphContours; exports.interpolateRigidMatrix = interpolateRigidMatrix; exports.interpolateVectorColor = interpolateVectorColor; exports.interpolateVectorPaint = interpolateVectorPaint; exports.interpolateVectorPaths = interpolateVectorPaths; exports.interpolateVectorStyle = interpolateVectorStyle; exports.interpolateWidthProfiles = interpolateWidthProfiles; exports.invertMatrix = invertMatrix; exports.isCentredVectorGradient = isCentredVectorGradient; exports.isClosedBezierShape = isClosedBezierShape; exports.isIdentityMatrix = isIdentityMatrix; exports.isUniformWidthProfile = isUniformWidthProfile; exports.isVectorBlendGroup = isVectorBlendGroup; exports.isVectorGradient = isVectorGradient; exports.isVectorLiveBoolean = isVectorLiveBoolean; exports.isVectorTextTarget = isVectorTextTarget; exports.joinSubpaths = joinSubpaths; exports.knifePath = knifePath; exports.lineSubpath = lineSubpath; exports.locateVectorNode = locateVectorNode; exports.matrixRotation = matrixRotation; exports.mergePaths = mergePaths; exports.mirrorWidthProfile = mirrorWidthProfile; exports.morphContourToSubpath = morphContourToSubpath; exports.morphPathsCross = morphPathsCross; exports.moveAnchorHandle = moveAnchorHandle; exports.moveVectorGradientHandle = moveVectorGradientHandle; exports.moveVectorGradientStop = moveVectorGradientStop; exports.multiplyMatrices = multiplyMatrices; exports.nearestSegment = nearestSegment; exports.nearestStrokePosition = nearestStrokePosition; exports.nextVectorCornerKind = nextVectorCornerKind; exports.nodeMatrix = nodeMatrix; exports.normalizeVectorEffectParams = normalizeVectorEffectParams; exports.offsetPaths = offsetPaths; exports.parseSvgTransform = parseSvgTransform; exports.parseVectorColor = parseVectorColor; exports.parseVectorSvg = parseVectorSvg; exports.pathsCenter = pathsCenter; exports.patternAttrs = patternAttrs; exports.periodicVectorGradientStops = periodicVectorGradientStops; exports.pinVectorGradient = pinVectorGradient; exports.planShapeBuilder = planShapeBuilder; exports.polygonSubpath = polygonSubpath; exports.polylineBounds = polylineBounds; exports.pressureWidthProfile = pressureWidthProfile; exports.puckerBloatPaths = puckerBloatPaths; exports.recognizeInkShape = recognizeInkShape; exports.rectSubpath = rectSubpath; exports.refineMorphContour = refineMorphContour; exports.refreshVectorBlends = refreshVectorBlends; exports.releaseVectorBlend = releaseVectorBlend; exports.removeAnchorKeepingShape = removeAnchorKeepingShape; exports.removeAnchors = removeAnchors; exports.removeAnchorsKeepingShape = removeAnchorsKeepingShape; exports.removeRedundantPoints = removeRedundantPoints; exports.removeVectorGradientStop = removeVectorGradientStop; exports.removeWidthPoints = removeWidthPoints; exports.repeatPaths = repeatPaths; exports.resampleGradientStops = resampleGradientStops; exports.resolveVectorBlendOptions = resolveVectorBlendOptions; exports.reverseMorphContour = reverseMorphContour; exports.reverseSubpath = reverseSubpath; exports.reverseVectorGradient = reverseVectorGradient; exports.reverseWidthProfile = reverseWidthProfile; exports.rotateMatrix = rotateMatrix; exports.roundCornerPaths = roundCornerPaths; exports.roundSubpaths = roundSubpaths; exports.samplePlainStops = samplePlainStops; exports.samplePolyline = samplePolyline; exports.sampleVectorGradient = sampleVectorGradient; exports.sampleVectorGradientAt = sampleVectorGradientAt; exports.sampleVectorPaintDefAt = sampleVectorPaintDefAt; exports.sanitizeVectorEffects = sanitizeVectorEffects; exports.sanitizeVectorGradient = sanitizeVectorGradient; exports.sanitizeWidthProfile = sanitizeWidthProfile; exports.scaleFor = scaleFor; exports.scaleMatrix = scaleMatrix; exports.setAnchorCorner = setAnchorCorner; exports.setSubpathCorners = setSubpathCorners; exports.setVectorGradientVector = setVectorGradientVector; exports.setWidthPoint = setWidthPoint; exports.simplifyPolyline = simplifyPolyline; exports.smoothSubpath = smoothSubpath; exports.sortedVectorGradientStops = sortedVectorGradientStops; exports.spanVectorGradientStops = spanVectorGradientStops; 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.subpathToMorphContour = subpathToMorphContour; exports.subpathsToBezier = subpathsToBezier; exports.taperWaveFactor = taperWaveFactor; exports.toVectorKeyInput = toVectorKeyInput; exports.toVectorModifiers = toVectorModifiers; exports.toVectorPointerInput = toVectorPointerInput; exports.transformVectorEffects = transformVectorEffects; exports.transformVectorGradient = transformVectorGradient; exports.transformVectorNode = transformVectorNode; exports.transformVectorPaint = transformVectorPaint; exports.translateAnchor = translateAnchor; exports.translateMatrix = translateMatrix; exports.trimIntervals = trimIntervals; exports.trimPaths = trimPaths; exports.trimPathsIndividually = trimPathsIndividually; exports.turnMorphContour = turnMorphContour; exports.twistPaths = twistPaths; exports.unionBounds = unionBounds; exports.variableStrokeOutline = variableStrokeOutline; exports.variableStrokeRings = variableStrokeRings; exports.vectorAppearanceNodes = vectorAppearanceNodes; exports.vectorAppearanceOutline = vectorAppearanceOutline; exports.vectorAppearanceShapes = vectorAppearanceShapes; exports.vectorBlendColorDistance = vectorBlendColorDistance; exports.vectorBlendKeyTargets = vectorBlendKeyTargets; exports.vectorBlendKeys = vectorBlendKeys; exports.vectorBlendRail = vectorBlendRail; exports.vectorBlendRailAt = vectorBlendRailAt; exports.vectorBlendSpine = vectorBlendSpine; exports.vectorBlendStepCount = vectorBlendStepCount; exports.vectorBoxMatrix = vectorBoxMatrix; exports.vectorBuilderErasedEdges = vectorBuilderErasedEdges; exports.vectorCornerAt = vectorCornerAt; exports.vectorCorners = vectorCorners; exports.vectorCornersAttribute = vectorCornersAttribute; exports.vectorDiamondPath = vectorDiamondPath; exports.vectorDocumentToSvg = vectorDocumentToSvg; exports.vectorEnteredGroups = vectorEnteredGroups; exports.vectorFillMap = vectorFillMap; exports.vectorGradientArea = vectorGradientArea; exports.vectorGradientAspect = vectorGradientAspect; exports.vectorGradientBarPosition = vectorGradientBarPosition; exports.vectorGradientFocalParam = vectorGradientFocalParam; exports.vectorGradientHandles = vectorGradientHandles; exports.vectorGradientMatrix = vectorGradientMatrix; exports.vectorGradientMidpointFromPosition = vectorGradientMidpointFromPosition; exports.vectorGradientMidpointPosition = vectorGradientMidpointPosition; exports.vectorGradientNeedsExpansion = vectorGradientNeedsExpansion; exports.vectorGradientParam = vectorGradientParam; exports.vectorGradientPoints = vectorGradientPoints; exports.vectorGradientRamp = vectorGradientRamp; exports.vectorGradientSvgDefs = vectorGradientSvgDefs; exports.vectorGradientTAt = vectorGradientTAt; exports.vectorGradientTargetPath = vectorGradientTargetPath; exports.vectorGradientUnitsMatrix = vectorGradientUnitsMatrix; exports.vectorInkShapeName = vectorInkShapeName; exports.vectorLiveBooleanSteps = vectorLiveBooleanSteps; exports.vectorNodeBounds = vectorNodeBounds; exports.vectorNodeRotation = vectorNodeRotation; exports.vectorNodeToBezier = vectorNodeToBezier; exports.vectorOperandOperation = vectorOperandOperation; exports.vectorPaintToHex = vectorPaintToHex; exports.vectorPaintToSvg = vectorPaintToSvg; exports.vectorParentMatrix = vectorParentMatrix; exports.vectorPathData = vectorPathData; exports.vectorPathEntries = vectorPathEntries; exports.vectorPathLocalBounds = vectorPathLocalBounds; exports.vectorPathWorldBezier = vectorPathWorldBezier; exports.vectorPathfinderShape = vectorPathfinderShape; exports.vectorRepeaterCopies = vectorRepeaterCopies; exports.vectorResizeCursor = vectorResizeCursor; exports.vectorResultStyle = vectorResultStyle; exports.vectorShapeBuilderHit = vectorShapeBuilderHit; exports.vectorShapeBuilderMap = vectorShapeBuilderMap; exports.vectorStrokeGradientDefs = vectorStrokeGradientDefs; 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; exports.wigglePaths = wigglePaths; exports.zigzagPaths = zigzagPaths;
14771
+
14772
+
14773
+
14774
+
14775
+
14776
+
14777
+
14778
+
14779
+
14780
+
14781
+
14782
+
14783
+
14784
+
14785
+
14786
+
14787
+
14788
+
14789
+
14790
+
14791
+
14792
+
14793
+
14794
+
14795
+
14796
+
14797
+
14798
+
14799
+
14800
+
14801
+
14802
+
14803
+
14804
+
14805
+
14806
+
14807
+
14808
+
14809
+
14810
+
14811
+
14812
+
14813
+
14814
+
14815
+
14816
+
14817
+
14818
+
14819
+
14820
+ exports.DEFAULT_VECTOR_BLEND_DISTANCE = DEFAULT_VECTOR_BLEND_DISTANCE; exports.DEFAULT_VECTOR_BLEND_STEPS = DEFAULT_VECTOR_BLEND_STEPS; 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_BLEND_MAX_SMOOTH_STEPS = VECTOR_BLEND_MAX_SMOOTH_STEPS; exports.VECTOR_BLEND_MAX_STEPS = VECTOR_BLEND_MAX_STEPS; exports.VECTOR_BLEND_SPACINGS = VECTOR_BLEND_SPACINGS; exports.VECTOR_BLEND_SPACING_LABELS = VECTOR_BLEND_SPACING_LABELS; exports.VECTOR_BUILDER_HATCH_GAP = VECTOR_BUILDER_HATCH_GAP; exports.VECTOR_CLIPBOARD_TYPE = VECTOR_CLIPBOARD_TYPE; exports.VECTOR_CONSTRUCTION_ANGLES = VECTOR_CONSTRUCTION_ANGLES; exports.VECTOR_CORNER_KINDS = VECTOR_CORNER_KINDS; exports.VECTOR_CORNER_KIND_LABELS = VECTOR_CORNER_KIND_LABELS; exports.VECTOR_CORNER_WIDGET_INSET = VECTOR_CORNER_WIDGET_INSET; exports.VECTOR_DISTORT_TOLERANCE = VECTOR_DISTORT_TOLERANCE; exports.VECTOR_EDIT_TOGGLES = VECTOR_EDIT_TOGGLES; exports.VECTOR_EFFECT_DEFAULTS = VECTOR_EFFECT_DEFAULTS; exports.VECTOR_EFFECT_LABELS = VECTOR_EFFECT_LABELS; exports.VECTOR_EFFECT_MENU = VECTOR_EFFECT_MENU; exports.VECTOR_EFFECT_PARAM_SPECS = VECTOR_EFFECT_PARAM_SPECS; exports.VECTOR_EFFECT_TYPES = VECTOR_EFFECT_TYPES; exports.VECTOR_ENVELOPE_STYLE_OPTIONS = VECTOR_ENVELOPE_STYLE_OPTIONS; exports.VECTOR_FILL_GAP = VECTOR_FILL_GAP; exports.VECTOR_GRADIENT_INTERPOLATIONS = VECTOR_GRADIENT_INTERPOLATIONS; exports.VECTOR_GRADIENT_INTERPOLATION_LABELS = VECTOR_GRADIENT_INTERPOLATION_LABELS; exports.VECTOR_GRADIENT_MAX_PERIODS = VECTOR_GRADIENT_MAX_PERIODS; exports.VECTOR_GRADIENT_MIDPOINT_GAP = VECTOR_GRADIENT_MIDPOINT_GAP; exports.VECTOR_GRADIENT_MIN_STOPS = VECTOR_GRADIENT_MIN_STOPS; exports.VECTOR_GRADIENT_OFF_BAR = VECTOR_GRADIENT_OFF_BAR; exports.VECTOR_GRADIENT_SPREADS = VECTOR_GRADIENT_SPREADS; exports.VECTOR_GRADIENT_SPREAD_LABELS = VECTOR_GRADIENT_SPREAD_LABELS; exports.VECTOR_GRADIENT_STOP_GAP = VECTOR_GRADIENT_STOP_GAP; exports.VECTOR_GRADIENT_TYPES = VECTOR_GRADIENT_TYPES; exports.VECTOR_GRADIENT_TYPE_LABELS = VECTOR_GRADIENT_TYPE_LABELS; exports.VECTOR_INK_MAX_CORNERS = VECTOR_INK_MAX_CORNERS; exports.VECTOR_MERGE_MODES = VECTOR_MERGE_MODES; 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_STROKE_GRADIENT_MODES = VECTOR_STROKE_GRADIENT_MODES; exports.VECTOR_STROKE_GRADIENT_MODE_LABELS = VECTOR_STROKE_GRADIENT_MODE_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_WARP_STYLES = VECTOR_WARP_STYLES; exports.VECTOR_WARP_STYLE_LABELS = VECTOR_WARP_STYLE_LABELS; 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.activeVectorEffects = activeVectorEffects; exports.addBuilderHit = addBuilderHit; exports.applyMatrix = applyMatrix; exports.applyMatrixLinear = applyMatrixLinear; exports.applyVectorBlendOptions = applyVectorBlendOptions; exports.applyVectorCornersAttribute = applyVectorCornersAttribute; exports.applyVectorEffects = applyVectorEffects; exports.applyVectorGradientPatch = applyVectorGradientPatch; exports.applyVectorGradientSpread = applyVectorGradientSpread; exports.applyVectorHomography = applyVectorHomography; exports.arrowheadInset = arrowheadInset; exports.arrowheadPath = arrowheadPath; exports.arrowheadWeight = arrowheadWeight; exports.bendSegment = bendSegment; exports.bezierToSubpaths = bezierToSubpaths; exports.boundsFromPoints = boundsFromPoints; exports.boundsIntersect = boundsIntersect; exports.clearVectorLiveBooleanCache = clearVectorLiveBooleanCache; exports.cloneAnchor = cloneAnchor; exports.cloneSubpath = cloneSubpath; exports.cloneVectorDocument = cloneVectorDocument; exports.cloneVectorNode = cloneVectorNode; exports.collectPathNodes = collectPathNodes; exports.constrainToLeave = constrainToLeave; exports.convertAnchor = convertAnchor; exports.convertVectorGradient = convertVectorGradient; exports.cornerBisectorPoint = cornerBisectorPoint; exports.cornerRadiusChange = cornerRadiusChange; exports.cornerSetback = cornerSetback; exports.correspondMorphContours = correspondMorphContours; exports.createVectorCommands = createVectorCommands; exports.createVectorEffect = createVectorEffect; exports.createVectorMorph = createVectorMorph; exports.curvatureMoveAnchor = curvatureMoveAnchor; exports.cutSubpathAt = cutSubpathAt; exports.dashIntervals = dashIntervals; exports.decomposeRigid = decomposeRigid; exports.defaultVectorGradient = defaultVectorGradient; exports.distortVectorNode = distortVectorNode; exports.dragVectorMeshPoint = dragVectorMeshPoint; exports.effectPathLength = effectPathLength; exports.effectPathVertexCount = effectPathVertexCount; exports.effectiveStrokeAlign = effectiveStrokeAlign; exports.ellipseSubpath = ellipseSubpath; exports.eraseFromFill = eraseFromFill; exports.eraseFromOutline = eraseFromOutline; exports.eraserRegion = eraserRegion; exports.evalVectorMesh = evalVectorMesh; exports.evaluateVectorPathKeyframes = evaluateVectorPathKeyframes; exports.expandVectorAppearance = expandVectorAppearance; exports.expandVectorAppearances = expandVectorAppearances; exports.expandVectorBlend = expandVectorBlend; exports.expandVectorCorners = expandVectorCorners; exports.expandVectorCornersOf = expandVectorCornersOf; exports.expandVectorGradientSpread = expandVectorGradientSpread; exports.expandVectorGradientStops = expandVectorGradientStops; exports.explicitVectorGradient = explicitVectorGradient; exports.findVectorNode = findVectorNode; exports.fitCornerRadius = fitCornerRadius; exports.fitVectorMesh = fitVectorMesh; exports.foldVectorBooleanOperands = foldVectorBooleanOperands; exports.generateVectorBlendChildren = generateVectorBlendChildren; exports.generateWidthProfile = generateWidthProfile; exports.getAnchor = getAnchor; exports.getAnchorWorld = getAnchorWorld; exports.getEditablePathIds = getEditablePathIds; exports.getTransformHandlePositions = getTransformHandlePositions; exports.getVectorBlendControls = getVectorBlendControls; exports.getVectorCornerWidgets = getVectorCornerWidgets; exports.getVectorEffectsPanel = getVectorEffectsPanel; exports.getVectorEnteredGroups = getVectorEnteredGroups; exports.getVectorEnvelopePanel = getVectorEnvelopePanel; exports.getVectorEnvelopeTarget = getVectorEnvelopeTarget; exports.getVectorGradientAnnotator = getVectorGradientAnnotator; exports.getVectorGradientEditor = getVectorGradientEditor; 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.gradientMidpointRemap = gradientMidpointRemap; exports.hasExplicitGradientGeometry = hasExplicitGradientGeometry; exports.hasOwnVectorAppearance = hasOwnVectorAppearance; exports.hasPaint = hasPaint; exports.hasStrokeExtras = hasStrokeExtras; exports.hasVectorAppearance = hasVectorAppearance; exports.hasVectorCorners = hasVectorCorners; exports.hitTestVectorNode = hitTestVectorNode; exports.hitTestVectorNodes = hitTestVectorNodes; exports.hitTestVectorStroke = hitTestVectorStroke; exports.hitVectorGradientAnnotator = hitVectorGradientAnnotator; exports.inferAnchorType = inferAnchorType; exports.insertAnchor = insertAnchor; exports.insertVectorGradientStop = insertVectorGradientStop; exports.insertWidthPoint = insertWidthPoint; exports.interpolateMorphContours = interpolateMorphContours; exports.interpolateRigidMatrix = interpolateRigidMatrix; exports.interpolateVectorColor = interpolateVectorColor; exports.interpolateVectorPaint = interpolateVectorPaint; exports.interpolateVectorPaths = interpolateVectorPaths; exports.interpolateVectorStyle = interpolateVectorStyle; exports.interpolateWidthProfiles = interpolateWidthProfiles; exports.invertMatrix = invertMatrix; exports.isCentredVectorGradient = isCentredVectorGradient; exports.isClosedBezierShape = isClosedBezierShape; exports.isIdentityMatrix = isIdentityMatrix; exports.isUniformWidthProfile = isUniformWidthProfile; exports.isValidVectorMesh = isValidVectorMesh; exports.isVectorBlendGroup = isVectorBlendGroup; exports.isVectorGradient = isVectorGradient; exports.isVectorLiveBoolean = isVectorLiveBoolean; exports.isVectorTextTarget = isVectorTextTarget; exports.joinSubpaths = joinSubpaths; exports.knifePath = knifePath; exports.lineSubpath = lineSubpath; exports.locateVectorNode = locateVectorNode; exports.mapBezierPath = mapBezierPath; exports.mapVectorGradient = mapVectorGradient; exports.mapVectorMeshPoints = mapVectorMeshPoints; exports.mapVectorPaint = mapVectorPaint; exports.mapVectorPoints = mapVectorPoints; exports.mapVectorSubpaths = mapVectorSubpaths; exports.matrixRotation = matrixRotation; exports.mergePaths = mergePaths; exports.mirrorWidthProfile = mirrorWidthProfile; exports.morphContourToSubpath = morphContourToSubpath; exports.morphPathsCross = morphPathsCross; exports.moveAnchorHandle = moveAnchorHandle; exports.moveVectorGradientHandle = moveVectorGradientHandle; exports.moveVectorGradientStop = moveVectorGradientStop; exports.multiplyMatrices = multiplyMatrices; exports.nearestSegment = nearestSegment; exports.nearestStrokePosition = nearestStrokePosition; exports.nextVectorCornerKind = nextVectorCornerKind; exports.nodeMatrix = nodeMatrix; exports.normalizeVectorEffectParams = normalizeVectorEffectParams; exports.offsetPaths = offsetPaths; exports.orderVectorQuad = orderVectorQuad; exports.parseSvgTransform = parseSvgTransform; exports.parseVectorColor = parseVectorColor; exports.parseVectorSvg = parseVectorSvg; exports.pathsCenter = pathsCenter; exports.patternAttrs = patternAttrs; exports.periodicVectorGradientStops = periodicVectorGradientStops; exports.pinVectorGradient = pinVectorGradient; exports.planShapeBuilder = planShapeBuilder; exports.polygonSubpath = polygonSubpath; exports.polylineBounds = polylineBounds; exports.pressureWidthProfile = pressureWidthProfile; exports.puckerBloatPaths = puckerBloatPaths; exports.pullVectorMesh = pullVectorMesh; exports.recognizeInkShape = recognizeInkShape; exports.rectSubpath = rectSubpath; exports.refineMorphContour = refineMorphContour; exports.refreshVectorBlends = refreshVectorBlends; exports.releaseVectorBlend = releaseVectorBlend; exports.removeAnchorKeepingShape = removeAnchorKeepingShape; exports.removeAnchors = removeAnchors; exports.removeAnchorsKeepingShape = removeAnchorsKeepingShape; exports.removeRedundantPoints = removeRedundantPoints; exports.removeVectorGradientStop = removeVectorGradientStop; exports.removeVectorMeshSplitU = removeVectorMeshSplitU; exports.removeVectorMeshSplitV = removeVectorMeshSplitV; exports.removeWidthPoints = removeWidthPoints; exports.repeatPaths = repeatPaths; exports.resampleGradientStops = resampleGradientStops; exports.resizeVectorMesh = resizeVectorMesh; exports.resolveVectorBlendOptions = resolveVectorBlendOptions; exports.reverseMorphContour = reverseMorphContour; exports.reverseSubpath = reverseSubpath; exports.reverseVectorGradient = reverseVectorGradient; exports.reverseWidthProfile = reverseWidthProfile; exports.rotateMatrix = rotateMatrix; exports.roundCornerPaths = roundCornerPaths; exports.roundSubpaths = roundSubpaths; exports.samplePlainStops = samplePlainStops; exports.samplePolyline = samplePolyline; exports.sampleVectorGradient = sampleVectorGradient; exports.sampleVectorGradientAt = sampleVectorGradientAt; exports.sampleVectorPaintDefAt = sampleVectorPaintDefAt; exports.sanitizeVectorEffects = sanitizeVectorEffects; exports.sanitizeVectorGradient = sanitizeVectorGradient; exports.sanitizeWidthProfile = sanitizeWidthProfile; exports.scaleFor = scaleFor; exports.scaleMatrix = scaleMatrix; exports.setAnchorCorner = setAnchorCorner; exports.setSubpathCorners = setSubpathCorners; exports.setVectorGradientVector = setVectorGradientVector; exports.setWidthPoint = setWidthPoint; exports.simplifyPolyline = simplifyPolyline; exports.smoothSubpath = smoothSubpath; exports.solve8 = solve8; exports.sortedVectorGradientStops = sortedVectorGradientStops; exports.spanVectorGradientStops = spanVectorGradientStops; exports.splitIntoFaces = splitIntoFaces; exports.splitSubpathAt = splitSubpathAt; exports.splitVectorMeshU = splitVectorMeshU; exports.splitVectorMeshV = splitVectorMeshV; exports.starSubpath = starSubpath; exports.strokePositionPoint = strokePositionPoint; exports.strokeWidthProfileOf = strokeWidthProfileOf; exports.subpathEnclosesArea = subpathEnclosesArea; exports.subpathPointAt = subpathPointAt; exports.subpathSegment = subpathSegment; exports.subpathSegmentCount = subpathSegmentCount; exports.subpathToMorphContour = subpathToMorphContour; exports.subpathsToBezier = subpathsToBezier; exports.taperWaveFactor = taperWaveFactor; exports.toVectorKeyInput = toVectorKeyInput; exports.toVectorModifiers = toVectorModifiers; exports.toVectorPointerInput = toVectorPointerInput; exports.transformVectorEffects = transformVectorEffects; exports.transformVectorGradient = transformVectorGradient; exports.transformVectorNode = transformVectorNode; exports.transformVectorPaint = transformVectorPaint; exports.translateAnchor = translateAnchor; exports.translateMatrix = translateMatrix; exports.trimIntervals = trimIntervals; exports.trimPaths = trimPaths; exports.trimPathsIndividually = trimPathsIndividually; exports.turnMorphContour = turnMorphContour; exports.twistPaths = twistPaths; exports.unionBounds = unionBounds; exports.variableStrokeOutline = variableStrokeOutline; exports.variableStrokeRings = variableStrokeRings; exports.vectorAppearanceNodes = vectorAppearanceNodes; exports.vectorAppearanceOutline = vectorAppearanceOutline; exports.vectorAppearanceShapes = vectorAppearanceShapes; exports.vectorBlendColorDistance = vectorBlendColorDistance; exports.vectorBlendKeyTargets = vectorBlendKeyTargets; exports.vectorBlendKeys = vectorBlendKeys; exports.vectorBlendRail = vectorBlendRail; exports.vectorBlendRailAt = vectorBlendRailAt; exports.vectorBlendSpine = vectorBlendSpine; exports.vectorBlendStepCount = vectorBlendStepCount; exports.vectorBoxCorners = vectorBoxCorners; exports.vectorBoxMatrix = vectorBoxMatrix; exports.vectorBuilderErasedEdges = vectorBuilderErasedEdges; exports.vectorCornerAt = vectorCornerAt; exports.vectorCorners = vectorCorners; exports.vectorCornersAttribute = vectorCornersAttribute; exports.vectorDiamondPath = vectorDiamondPath; exports.vectorDistortQuad = vectorDistortQuad; exports.vectorDocumentToSvg = vectorDocumentToSvg; exports.vectorEffectInputBounds = vectorEffectInputBounds; exports.vectorEffectInputPaths = vectorEffectInputPaths; exports.vectorEnteredGroups = vectorEnteredGroups; exports.vectorEnvelopeFrame = vectorEnvelopeFrame; exports.vectorEnvelopeMap = vectorEnvelopeMap; exports.vectorEnvelopeMesh = vectorEnvelopeMesh; exports.vectorFillMap = vectorFillMap; exports.vectorGradientArea = vectorGradientArea; exports.vectorGradientAspect = vectorGradientAspect; exports.vectorGradientBarPosition = vectorGradientBarPosition; exports.vectorGradientFocalParam = vectorGradientFocalParam; exports.vectorGradientHandles = vectorGradientHandles; exports.vectorGradientMatrix = vectorGradientMatrix; exports.vectorGradientMidpointFromPosition = vectorGradientMidpointFromPosition; exports.vectorGradientMidpointPosition = vectorGradientMidpointPosition; exports.vectorGradientNeedsExpansion = vectorGradientNeedsExpansion; exports.vectorGradientParam = vectorGradientParam; exports.vectorGradientPoints = vectorGradientPoints; exports.vectorGradientRamp = vectorGradientRamp; exports.vectorGradientSvgDefs = vectorGradientSvgDefs; exports.vectorGradientTAt = vectorGradientTAt; exports.vectorGradientTargetPath = vectorGradientTargetPath; exports.vectorGradientUnitsMatrix = vectorGradientUnitsMatrix; exports.vectorHomography = vectorHomography; exports.vectorHomographyKeepsQuad = vectorHomographyKeepsQuad; exports.vectorIdentityMesh = vectorIdentityMesh; exports.vectorInkShapeName = vectorInkShapeName; exports.vectorLiveBooleanSteps = vectorLiveBooleanSteps; exports.vectorMeshColumns = vectorMeshColumns; exports.vectorMeshControlBounds = vectorMeshControlBounds; exports.vectorMeshEditPoints = vectorMeshEditPoints; exports.vectorMeshFromOutline = vectorMeshFromOutline; exports.vectorMeshGridCurves = vectorMeshGridCurves; exports.vectorMeshOutline = vectorMeshOutline; exports.vectorMeshParamAt = vectorMeshParamAt; exports.vectorMeshRows = vectorMeshRows; exports.vectorNodeBounds = vectorNodeBounds; exports.vectorNodeEnvelope = vectorNodeEnvelope; exports.vectorNodeRotation = vectorNodeRotation; exports.vectorNodeToBezier = vectorNodeToBezier; exports.vectorOperandOperation = vectorOperandOperation; exports.vectorPaintToHex = vectorPaintToHex; exports.vectorPaintToSvg = vectorPaintToSvg; exports.vectorParentMatrix = vectorParentMatrix; exports.vectorPathData = vectorPathData; exports.vectorPathEntries = vectorPathEntries; exports.vectorPathLocalBounds = vectorPathLocalBounds; exports.vectorPathWorldBezier = vectorPathWorldBezier; exports.vectorPathfinderShape = vectorPathfinderShape; exports.vectorRepeaterCopies = vectorRepeaterCopies; exports.vectorResizeCursor = vectorResizeCursor; exports.vectorResultStyle = vectorResultStyle; exports.vectorShapeBuilderHit = vectorShapeBuilderHit; exports.vectorShapeBuilderMap = vectorShapeBuilderMap; exports.vectorShearForSide = vectorShearForSide; exports.vectorSkewMatrix = vectorSkewMatrix; exports.vectorStrokeGradientDefs = vectorStrokeGradientDefs; 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.vectorWarpPresetGrid = vectorWarpPresetGrid; exports.vectorWarpPresetMesh = vectorWarpPresetMesh; exports.vectorWorldMatrix = vectorWorldMatrix; exports.walkVectorNodes = walkVectorNodes; exports.widthProfileAt = widthProfileAt; exports.widthProfileFromAttribute = widthProfileFromAttribute; exports.widthProfileMaxScale = widthProfileMaxScale; exports.widthProfilePreset = widthProfilePreset; exports.widthProfilePresetId = widthProfilePresetId; exports.widthProfileToAttribute = widthProfileToAttribute; exports.wigglePaths = wigglePaths; exports.zigzagPaths = zigzagPaths;
13140
14821
  //# sourceMappingURL=index.cjs.map