@pixerate/editor 0.203.0 → 0.205.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.
@@ -9470,24 +9470,42 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
9470
9470
  * placed by position.
9471
9471
  */
9472
9472
  reorderNode(id, index) {
9473
+ return this.moveNode(id, { index });
9474
+ }
9475
+ /**
9476
+ * Moves a node into group `parentId` (null: the top level; left out: where it is) at `index`
9477
+ * among its new siblings (bottom to top, 0 the bottom; left out: the top), as dragging it in a
9478
+ * layers panel does. It stays where it is on the canvas. Clipping groups and blends keep their
9479
+ * children: their mask and keys are placed by position.
9480
+ */
9481
+ moveNode(id, options = {}) {
9473
9482
  const node = this.getNode(id);
9474
- if (!node) return { ok: false, message: `No node "${id}".` };
9475
- let parent = null;
9476
- _chunkBRKVNXDZcjs.walkVectorNodes.call(void 0, this.doc.nodes, (n2, p) => {
9477
- if (n2.id === id) parent = p;
9478
- });
9479
- const group = parent;
9480
- if (group && (_chunkBRKVNXDZcjs.isVectorMaskGroup.call(void 0, group) || isVectorBlendGroup(group))) {
9481
- return { ok: false, message: "The order inside a clipping group or blend is fixed." };
9482
- }
9483
- const siblings = group ? group.children : this.doc.nodes;
9484
- const from = siblings.findIndex((n2) => n2.id === id);
9485
- const to = Math.max(0, Math.min(siblings.length - 1, Math.round(index)));
9486
- if (from === to) return { ok: true };
9483
+ const at = node && _chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id);
9484
+ if (!node || !at) return { ok: false, message: `No node "${id}".` };
9485
+ const fixed = (g) => !!g && (_chunkBRKVNXDZcjs.isVectorMaskGroup.call(void 0, g) || isVectorBlendGroup(g));
9486
+ if (fixed(at.parent)) return { ok: false, message: "The order inside a clipping group or blend is fixed." };
9487
+ const parentId = options.parentId === void 0 ? _nullishCoalesce(_optionalChain([at, 'access', _390 => _390.parent, 'optionalAccess', _391 => _391.id]), () => ( null)) : options.parentId;
9488
+ const target = parentId === null ? null : this.getNode(parentId);
9489
+ if (parentId !== null) {
9490
+ if (_optionalChain([target, 'optionalAccess', _392 => _392.type]) !== "group") return { ok: false, message: `"${parentId}" is not a group.` };
9491
+ if (parentId === id || _chunkBRKVNXDZcjs.findVectorNode.call(void 0, [node], parentId)) return { ok: false, message: "A layer cannot go inside itself." };
9492
+ if (fixed(target)) return { ok: false, message: "The order inside a clipping group or blend is fixed." };
9493
+ }
9494
+ const groupId = _nullishCoalesce(_optionalChain([target, 'optionalAccess', _393 => _393.id]), () => ( null));
9495
+ const without = mapTree(this.doc.nodes, (n2) => n2.id === id ? null : n2);
9496
+ const inGroup = groupId === null ? null : _chunkBRKVNXDZcjs.findVectorNode.call(void 0, without, groupId);
9497
+ const siblings = _optionalChain([inGroup, 'optionalAccess', _394 => _394.type]) === "group" ? inGroup.children : without;
9498
+ const to = Math.max(0, Math.min(siblings.length, Math.round(_nullishCoalesce(options.index, () => ( siblings.length)))));
9499
+ if (groupId === (_nullishCoalesce(_optionalChain([at, 'access', _395 => _395.parent, 'optionalAccess', _396 => _396.id]), () => ( null))) && to === at.index) return { ok: true };
9500
+ const from = _nullishCoalesce(_chunkBRKVNXDZcjs.vectorParentMatrix.call(void 0, this.doc.nodes, id), () => ( _chunkBRKVNXDZcjs.IDENTITY_MATRIX));
9501
+ const into = groupId === null ? _chunkBRKVNXDZcjs.IDENTITY_MATRIX : _nullishCoalesce(_chunkBRKVNXDZcjs.vectorWorldMatrix.call(void 0, this.doc.nodes, groupId), () => ( _chunkBRKVNXDZcjs.IDENTITY_MATRIX));
9502
+ const m = _chunkBRKVNXDZcjs.multiplyMatrices.call(void 0, from, _chunkBRKVNXDZcjs.invertMatrix.call(void 0, into));
9487
9503
  const next = [...siblings];
9488
- next.splice(from, 1);
9489
- next.splice(to, 0, node);
9490
- this.change("Move Layer", () => group ? this.replaceNode(group.id, { ...group, children: next }) : this.setDoc(next));
9504
+ next.splice(to, 0, _chunkBRKVNXDZcjs.isIdentityMatrix.call(void 0, m) ? node : _chunkBRKVNXDZcjs.transformVectorNode.call(void 0, node, m));
9505
+ this.change(
9506
+ "Move Layer",
9507
+ () => this.setDoc(groupId === null ? next : mapTree(without, (n2) => n2.id === groupId && n2.type === "group" ? { ...n2, children: next } : n2))
9508
+ );
9491
9509
  return { ok: true };
9492
9510
  }
9493
9511
  /**
@@ -9543,7 +9561,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
9543
9561
  this.change(label2, () => this.replaceNode(lone.id, { ...lone, liveBoolean: op, children }));
9544
9562
  return lone.id;
9545
9563
  }
9546
- const parents = roots.map((id2) => _nullishCoalesce(_optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id2), 'optionalAccess', _390 => _390.parent]), () => ( null)));
9564
+ const parents = roots.map((id2) => _nullishCoalesce(_optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id2), 'optionalAccess', _397 => _397.parent]), () => ( null)));
9547
9565
  if (parents.every((g) => _chunkBRKVNXDZcjs.isVectorLiveBoolean.call(void 0, g))) {
9548
9566
  const set = new Set(roots);
9549
9567
  this.change(
@@ -9564,8 +9582,8 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
9564
9582
  return parents[0].id;
9565
9583
  }
9566
9584
  if (nodes.length < 2) return null;
9567
- const parent = _nullishCoalesce(_optionalChain([parents, 'access', _391 => _391[0], 'optionalAccess', _392 => _392.id]), () => ( null));
9568
- if (parents.some((g) => (_nullishCoalesce(_optionalChain([g, 'optionalAccess', _393 => _393.id]), () => ( null))) !== parent)) return null;
9585
+ const parent = _nullishCoalesce(_optionalChain([parents, 'access', _398 => _398[0], 'optionalAccess', _399 => _399.id]), () => ( null));
9586
+ if (parents.some((g) => (_nullishCoalesce(_optionalChain([g, 'optionalAccess', _400 => _400.id]), () => ( null))) !== parent)) return null;
9569
9587
  const id = this.newId();
9570
9588
  this.change(label2, () => {
9571
9589
  const set = new Set(roots);
@@ -9613,7 +9631,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
9613
9631
  }
9614
9632
  /** Splits selected compound paths into one path per subpath. */
9615
9633
  breakApart(options = {}) {
9616
- const paths = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n2) => _optionalChain([n2, 'optionalAccess', _394 => _394.type]) === "path" && n2.subpaths.length > 1);
9634
+ const paths = (_nullishCoalesce(options.ids, () => ( this.selection))).map((id) => this.getNode(id)).filter((n2) => _optionalChain([n2, 'optionalAccess', _401 => _401.type]) === "path" && n2.subpaths.length > 1);
9617
9635
  if (!paths.length) return { ok: false, message: "Select a compound path to break apart." };
9618
9636
  const created = [];
9619
9637
  const set = new Set(paths.map((p) => p.id));
@@ -9681,7 +9699,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
9681
9699
  const out = /* @__PURE__ */ new Map();
9682
9700
  for (const id of _nullishCoalesce(ids, () => ( this.selection))) {
9683
9701
  const node = this.getNode(id);
9684
- const group = isVectorBlendGroup(node) ? node : _optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id), 'optionalAccess', _395 => _395.parent]);
9702
+ const group = isVectorBlendGroup(node) ? node : _optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id), 'optionalAccess', _402 => _402.parent]);
9685
9703
  if (isVectorBlendGroup(group)) out.set(group.id, group);
9686
9704
  }
9687
9705
  return [...out.values()];
@@ -9699,8 +9717,8 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
9699
9717
  });
9700
9718
  if (ids.length < 2) return null;
9701
9719
  const locs = ids.map((id2) => _chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id2));
9702
- const parent = _nullishCoalesce(_optionalChain([locs, 'access', _396 => _396[0], 'access', _397 => _397.parent, 'optionalAccess', _398 => _398.id]), () => ( null));
9703
- if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _399 => _399.parent, 'optionalAccess', _400 => _400.id]), () => ( null))) !== parent)) return null;
9720
+ const parent = _nullishCoalesce(_optionalChain([locs, 'access', _403 => _403[0], 'access', _404 => _404.parent, 'optionalAccess', _405 => _405.id]), () => ( null));
9721
+ if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _406 => _406.parent, 'optionalAccess', _407 => _407.id]), () => ( null))) !== parent)) return null;
9704
9722
  const order = input.keepOrder ? ids : ids.slice().sort((a, b) => locs[ids.indexOf(a)].index - locs[ids.indexOf(b)].index);
9705
9723
  const blend = blendOptionsOf({ ...this.blendDefaults, ...input });
9706
9724
  if (input.starts) {
@@ -9748,8 +9766,8 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
9748
9766
  if (n2.blendStep) return { ok: false, message: `"${id2}" is a blend step; select its blend instead.` };
9749
9767
  }
9750
9768
  const locs = ids.map((id2) => _chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id2));
9751
- const parent = _nullishCoalesce(_optionalChain([locs, 'access', _401 => _401[0], 'access', _402 => _402.parent, 'optionalAccess', _403 => _403.id]), () => ( null));
9752
- if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _404 => _404.parent, 'optionalAccess', _405 => _405.id]), () => ( null))) !== parent)) return { ok: false, message: "The objects must share a parent (group them, or pick objects at one level)." };
9769
+ const parent = _nullishCoalesce(_optionalChain([locs, 'access', _408 => _408[0], 'access', _409 => _409.parent, 'optionalAccess', _410 => _410.id]), () => ( null));
9770
+ if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _411 => _411.parent, 'optionalAccess', _412 => _412.id]), () => ( null))) !== parent)) return { ok: false, message: "The objects must share a parent (group them, or pick objects at one level)." };
9753
9771
  const order = ids.slice().sort((a, b) => locs[ids.indexOf(a)].index - locs[ids.indexOf(b)].index);
9754
9772
  const maskId = _nullishCoalesce(options.maskId, () => ( order[order.length - 1]));
9755
9773
  if (!order.includes(maskId)) return { ok: false, message: `The mask "${maskId}" must be one of the objects (${order.map((id2) => `"${id2}"`).join(", ")}).` };
@@ -9814,8 +9832,8 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
9814
9832
  if (n2.locked) return { ok: false, message: `"${id2}" is locked; unlock it first.` };
9815
9833
  }
9816
9834
  const locs = ids.map((id2) => _chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id2));
9817
- const parent = _nullishCoalesce(_optionalChain([locs, 'access', _406 => _406[0], 'optionalAccess', _407 => _407.parent]), () => ( null));
9818
- if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _408 => _408.parent, 'optionalAccess', _409 => _409.id]), () => ( null))) !== (_nullishCoalesce(_optionalChain([parent, 'optionalAccess', _410 => _410.id]), () => ( null))))) return { ok: false, message: "The objects must share a parent (pick objects at one level)." };
9835
+ const parent = _nullishCoalesce(_optionalChain([locs, 'access', _413 => _413[0], 'optionalAccess', _414 => _414.parent]), () => ( null));
9836
+ if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _415 => _415.parent, 'optionalAccess', _416 => _416.id]), () => ( null))) !== (_nullishCoalesce(_optionalChain([parent, 'optionalAccess', _417 => _417.id]), () => ( null))))) return { ok: false, message: "The objects must share a parent (pick objects at one level)." };
9819
9837
  const b = _chunkBRKVNXDZcjs.unionBounds.call(void 0, ids.map((id2) => _chunkBRKVNXDZcjs.vectorNodeBounds.call(void 0, this.getNode(id2))));
9820
9838
  const center = _nullishCoalesce(input.center, () => ( (b ? { x: b.x + b.width / 2, y: b.y + b.height / 2 } : { x: this.doc.width / 2, y: this.doc.height / 2 })));
9821
9839
  const id = this.newId();
@@ -9852,7 +9870,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
9852
9870
  const n2 = this.getNode(id);
9853
9871
  if (_chunkBRKVNXDZcjs.isVectorSymmetryGroup.call(void 0, n2)) out.set(n2.id, n2);
9854
9872
  else if (!ids) {
9855
- const p = _optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id), 'optionalAccess', _411 => _411.parent]);
9873
+ const p = _optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id), 'optionalAccess', _418 => _418.parent]);
9856
9874
  if (_chunkBRKVNXDZcjs.isVectorSymmetryGroup.call(void 0, p)) out.set(p.id, p);
9857
9875
  }
9858
9876
  }
@@ -10021,8 +10039,8 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10021
10039
  const plane = this.perspectivePlane;
10022
10040
  if (!grid || !plane || kind === "line" || !vectorPerspectivePlanes(grid).includes(plane)) return null;
10023
10041
  const toFlat = vectorPerspectivePlaneToFlat(grid, plane);
10024
- const a = _optionalChain([toFlat, 'optionalCall', _412 => _412(start)]);
10025
- const b = _optionalChain([toFlat, 'optionalCall', _413 => _413(end)]);
10042
+ const a = _optionalChain([toFlat, 'optionalCall', _419 => _419(start)]);
10043
+ const b = _optionalChain([toFlat, 'optionalCall', _420 => _420(end)]);
10026
10044
  if (!a || !b) return null;
10027
10045
  const flat = this.createShapeNode({ kind, ..._chunkBRKVNXDZcjs.boundsFromPoints.call(void 0, a, b) });
10028
10046
  const mapped = vectorPerspectiveMapPath(grid, plane, _chunkBRKVNXDZcjs.subpathsToBezier.call(void 0, flat.subpaths));
@@ -10207,7 +10225,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10207
10225
  getShadingSelection() {
10208
10226
  const sel = this.shadingSel;
10209
10227
  const node = sel ? this.getNode(sel.nodeId) : void 0;
10210
- if (!sel || _optionalChain([node, 'optionalAccess', _414 => _414.type]) !== "path" || !_chunkBRKVNXDZcjs.isVectorShadedPaint.call(void 0, node.fill) || sel.index >= node.fill.points.length) return null;
10228
+ if (!sel || _optionalChain([node, 'optionalAccess', _421 => _421.type]) !== "path" || !_chunkBRKVNXDZcjs.isVectorShadedPaint.call(void 0, node.fill) || sel.index >= node.fill.points.length) return null;
10211
10229
  return { ...sel, kind: node.fill.type };
10212
10230
  }
10213
10231
  /** The path `id` (or a message why it cannot take a mesh or freeform fill). */
@@ -10273,17 +10291,17 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10273
10291
  const b = _chunkBRKVNXDZcjs.vectorPathLocalBounds.call(void 0, t);
10274
10292
  if (!b) return { ok: false, message: `"${id}" has no area to fill.` };
10275
10293
  let f;
10276
- if (_optionalChain([input, 'access', _415 => _415.points, 'optionalAccess', _416 => _416.length])) {
10294
+ if (_optionalChain([input, 'access', _422 => _422.points, 'optionalAccess', _423 => _423.length])) {
10277
10295
  f = _chunkBRKVNXDZcjs.sanitizeVectorShadedPaint.call(void 0, { type: "freeform", points: input.points.map((q) => ({ ...q, ...this.toLocal(id, q) })), ...input.lines ? { lines: input.lines } : {} });
10278
10296
  if (!f) return { ok: false, message: "Each point needs x, y (numbers) and a colour." };
10279
- if (input.lines && (_nullishCoalesce(_optionalChain([f, 'access', _417 => _417.lines, 'optionalAccess', _418 => _418.length]), () => ( 0))) !== input.lines.length) return { ok: false, message: `Each line needs two or more point indices from 0 to ${input.points.length - 1}, none twice in a row.` };
10297
+ if (input.lines && (_nullishCoalesce(_optionalChain([f, 'access', _424 => _424.lines, 'optionalAccess', _425 => _425.length]), () => ( 0))) !== input.lines.length) return { ok: false, message: `Each line needs two or more point indices from 0 to ${input.points.length - 1}, none twice in a row.` };
10280
10298
  } else {
10281
10299
  const bad = (_nullishCoalesce(input.colors, () => ( []))).find((c) => !_chunkBRKVNXDZcjs.parseVectorColor.call(void 0, c));
10282
10300
  if (bad !== void 0) return { ok: false, message: `"${bad}" is not a colour.` };
10283
10301
  const outline = _chunkBRKVNXDZcjs.subpathsToBezier.call(void 0, t.subpaths);
10284
10302
  const inside = (q) => _chunkGF2RBSDMcjs.pointInBezierPath.call(void 0, outline, [q.x, q.y], _nullishCoalesce(t.fillRule, () => ( "nonzero")));
10285
10303
  const base = typeof t.fill === "string" && _chunkBRKVNXDZcjs.parseVectorColor.call(void 0, t.fill) ? t.fill : "#000000";
10286
- f = _chunkBRKVNXDZcjs.autoVectorFreeformGradient.call(void 0, b, _optionalChain([input, 'access', _419 => _419.colors, 'optionalAccess', _420 => _420.length]) ? input.colors : [base, "#ffffff"], inside);
10304
+ f = _chunkBRKVNXDZcjs.autoVectorFreeformGradient.call(void 0, b, _optionalChain([input, 'access', _426 => _426.colors, 'optionalAccess', _427 => _427.length]) ? input.colors : [base, "#ffffff"], inside);
10287
10305
  }
10288
10306
  fills.set(id, f);
10289
10307
  }
@@ -10293,7 +10311,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10293
10311
  /** The mesh or freeform fill of path `id` with its points in document units, or null. */
10294
10312
  getShading(id) {
10295
10313
  const n2 = this.getNode(id);
10296
- if (_optionalChain([n2, 'optionalAccess', _421 => _421.type]) !== "path" || !_chunkBRKVNXDZcjs.isVectorShadedPaint.call(void 0, n2.fill)) return null;
10314
+ if (_optionalChain([n2, 'optionalAccess', _428 => _428.type]) !== "path" || !_chunkBRKVNXDZcjs.isVectorShadedPaint.call(void 0, n2.fill)) return null;
10297
10315
  const world = this.worldOf(id);
10298
10316
  return _chunkBRKVNXDZcjs.mapVectorShadedPaint.call(void 0, n2.fill, (q) => _chunkBRKVNXDZcjs.applyMatrix.call(void 0, world, q));
10299
10317
  }
@@ -10400,7 +10418,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10400
10418
  if (typeof t === "string") return { ok: false, message: t };
10401
10419
  if (!_chunkBRKVNXDZcjs.isVectorFreeformGradient.call(void 0, t.fill)) return { ok: false, message: `"${id}" has no freeform gradient fill (add one with vector.setFreeformGradient).` };
10402
10420
  const f = _chunkBRKVNXDZcjs.sanitizeVectorShadedPaint.call(void 0, { ...t.fill, lines });
10403
- if ((_nullishCoalesce(_optionalChain([f, 'access', _422 => _422.lines, 'optionalAccess', _423 => _423.length]), () => ( 0))) !== lines.length) return { ok: false, message: `Each line needs two or more point indices from 0 to ${t.fill.points.length - 1}, none twice in a row.` };
10421
+ if ((_nullishCoalesce(_optionalChain([f, 'access', _429 => _429.lines, 'optionalAccess', _430 => _430.length]), () => ( 0))) !== lines.length) return { ok: false, message: `Each line needs two or more point indices from 0 to ${t.fill.points.length - 1}, none twice in a row.` };
10404
10422
  const { lines: _l, ...rest } = t.fill;
10405
10423
  this.setFills("Freeform Lines", /* @__PURE__ */ new Map([[id, lines.length ? { ...rest, lines: f.lines } : rest]]));
10406
10424
  return { ok: true };
@@ -10420,7 +10438,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10420
10438
  penAngles() {
10421
10439
  if (!this.snap.polarRelative || !this.pen) return {};
10422
10440
  const node = this.getNode(this.pen.nodeId);
10423
- const sp = _optionalChain([node, 'optionalAccess', _424 => _424.subpaths, 'access', _425 => _425[this.pen.subpath]]);
10441
+ const sp = _optionalChain([node, 'optionalAccess', _431 => _431.subpaths, 'access', _432 => _432[this.pen.subpath]]);
10424
10442
  if (!sp || sp.anchors.length < 2) return {};
10425
10443
  const n2 = sp.anchors.length;
10426
10444
  const a = getAnchorWorld(this.doc, { nodeId: this.pen.nodeId, subpath: this.pen.subpath, index: n2 - 2 });
@@ -10538,7 +10556,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10538
10556
  const pen = this.pen;
10539
10557
  const node = pen ? this.getNode(pen.nodeId) : void 0;
10540
10558
  const sp = pen && node ? node.subpaths[pen.subpath] : void 0;
10541
- if (!pen || !node || !_optionalChain([sp, 'optionalAccess', _426 => _426.anchors, 'access', _427 => _427.length])) return { ok: false, message: "Start a path with the pen first: typed entry places its next point." };
10559
+ if (!pen || !node || !_optionalChain([sp, 'optionalAccess', _433 => _433.anchors, 'access', _434 => _434.length])) return { ok: false, message: "Start a path with the pen first: typed entry places its next point." };
10542
10560
  const last = getAnchorWorld(this.doc, { nodeId: pen.nodeId, subpath: pen.subpath, index: sp.anchors.length - 1 });
10543
10561
  const num2 = "(-?(?:\\d+\\.?\\d*|\\.\\d+))";
10544
10562
  const t = text.replace(/\s+/g, "");
@@ -10547,7 +10565,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10547
10565
  if (m = t.match(new RegExp(`^@${num2},${num2}$`))) target = { x: last.x + parseFloat(m[1]), y: last.y + parseFloat(m[2]) };
10548
10566
  else if (m = t.match(new RegExp(`^${num2},${num2}$`))) target = { x: parseFloat(m[1]), y: parseFloat(m[2]) };
10549
10567
  else if (m = t.match(new RegExp(`^${num2}<${num2}$`))) {
10550
- const base = this.snap.polarRelative ? (_nullishCoalesce(_nullishCoalesce(_optionalChain([this, 'access', _428 => _428.penAngles, 'call', _429 => _429(), 'access', _430 => _430.angles, 'optionalAccess', _431 => _431[0]]), () => ( this.snap.angles[0])), () => ( 0))) - (_nullishCoalesce(this.snap.angles[0], () => ( 0))) : 0;
10568
+ const base = this.snap.polarRelative ? (_nullishCoalesce(_nullishCoalesce(_optionalChain([this, 'access', _435 => _435.penAngles, 'call', _436 => _436(), 'access', _437 => _437.angles, 'optionalAccess', _438 => _438[0]]), () => ( this.snap.angles[0])), () => ( 0))) - (_nullishCoalesce(this.snap.angles[0], () => ( 0))) : 0;
10551
10569
  const dir = vectorAngleDirection(parseFloat(m[2]) + base);
10552
10570
  const len2 = parseFloat(m[1]);
10553
10571
  target = { x: last.x + dir.x * len2, y: last.y + dir.y * len2 };
@@ -10575,7 +10593,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10575
10593
  */
10576
10594
  addPathByDimensions(input) {
10577
10595
  if (!input.start || !Number.isFinite(input.start.x) || !Number.isFinite(input.start.y)) return { ok: false, message: "start must be { x, y } in document units." };
10578
- if (!_optionalChain([input, 'access', _432 => _432.steps, 'optionalAccess', _433 => _433.length])) return { ok: false, message: "Give at least one step." };
10596
+ if (!_optionalChain([input, 'access', _439 => _439.steps, 'optionalAccess', _440 => _440.length])) return { ok: false, message: "Give at least one step." };
10579
10597
  const pts = [{ x: input.start.x, y: input.start.y }];
10580
10598
  for (const [i, step] of input.steps.entries()) {
10581
10599
  const at = pts[pts.length - 1];
@@ -10609,7 +10627,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10609
10627
  downConnector(p) {
10610
10628
  const before = this.snapshot();
10611
10629
  const target = _chunkBRKVNXDZcjs.vectorConnectorTargetAt.call(void 0, this.doc.nodes, p, this.connectorRadius());
10612
- const at = _nullishCoalesce(_optionalChain([target, 'optionalAccess', _434 => _434.site]), () => ( p));
10630
+ const at = _nullishCoalesce(_optionalChain([target, 'optionalAccess', _441 => _441.site]), () => ( p));
10613
10631
  const node = {
10614
10632
  id: this.newId(),
10615
10633
  type: "path",
@@ -10711,7 +10729,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10711
10729
  const ids = _nullishCoalesce(options.ids, () => ( this.selection));
10712
10730
  if (!ids.length) return { ok: false, message: "Select a closed path to make a lens first." };
10713
10731
  if (lens && lens.type !== void 0 && !_chunkBRKVNXDZcjs.VECTOR_LENS_TYPES.includes(lens.type)) return { ok: false, message: `Unknown lens "${lens.type}": use ${_chunkBRKVNXDZcjs.VECTOR_LENS_TYPES.join(", ")}.` };
10714
- if (_optionalChain([lens, 'optionalAccess', _435 => _435.color]) !== void 0 && lens.color !== null && !_chunkBRKVNXDZcjs.parseVectorColor.call(void 0, lens.color)) return { ok: false, message: `"${lens.color}" is not a colour: use a CSS colour such as #ff0000.` };
10732
+ if (_optionalChain([lens, 'optionalAccess', _442 => _442.color]) !== void 0 && lens.color !== null && !_chunkBRKVNXDZcjs.parseVectorColor.call(void 0, lens.color)) return { ok: false, message: `"${lens.color}" is not a colour: use a CSS colour such as #ff0000.` };
10715
10733
  const next = /* @__PURE__ */ new Map();
10716
10734
  for (const id of ids) {
10717
10735
  const n2 = this.getNode(id);
@@ -10722,7 +10740,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10722
10740
  continue;
10723
10741
  }
10724
10742
  if (n2.type !== "path" || !n2.subpaths.some((sp) => sp.closed) || _chunkBRKVNXDZcjs.isVectorConnector.call(void 0, n2)) return { ok: false, message: `"${id}" is not a closed path: only closed paths can be lenses.` };
10725
- const type = _nullishCoalesce(lens.type, () => ( _optionalChain([n2, 'access', _436 => _436.lens, 'optionalAccess', _437 => _437.type])));
10743
+ const type = _nullishCoalesce(lens.type, () => ( _optionalChain([n2, 'access', _443 => _443.lens, 'optionalAccess', _444 => _444.type])));
10726
10744
  if (!type) return { ok: false, message: `"${id}" is not a lens yet: pass a type (${_chunkBRKVNXDZcjs.VECTOR_LENS_TYPES.join(", ")}).` };
10727
10745
  const spec = _chunkBRKVNXDZcjs.VECTOR_LENS_SPECS[type];
10728
10746
  if (lens.amount !== void 0 && !(Number.isFinite(lens.amount) && lens.amount >= spec.min && lens.amount <= spec.max)) return { ok: false, message: `amount for a ${type} lens must be from ${spec.min} to ${spec.max} (${spec.unit}).` };
@@ -10799,8 +10817,8 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10799
10817
  const r = _chunkBRKVNXDZcjs.routeVectorConnector.call(void 0, this.doc.nodes, n2.id);
10800
10818
  const world = _nullishCoalesce(_chunkBRKVNXDZcjs.vectorWorldMatrix.call(void 0, this.doc.nodes, n2.id), () => ( _chunkBRKVNXDZcjs.IDENTITY_MATRIX));
10801
10819
  const sp = n2.subpaths[0];
10802
- const first = _optionalChain([sp, 'optionalAccess', _438 => _438.anchors, 'access', _439 => _439[0]]);
10803
- const last = _optionalChain([sp, 'optionalAccess', _440 => _440.anchors, 'access', _441 => _441[sp.anchors.length - 1]]);
10820
+ const first = _optionalChain([sp, 'optionalAccess', _445 => _445.anchors, 'access', _446 => _446[0]]);
10821
+ const last = _optionalChain([sp, 'optionalAccess', _447 => _447.anchors, 'access', _448 => _448[sp.anchors.length - 1]]);
10804
10822
  const end = (e, side, a) => {
10805
10823
  const at = a ? _chunkBRKVNXDZcjs.applyMatrix.call(void 0, world, a) : null;
10806
10824
  return { ...e ? { nodeId: e.nodeId, side: _nullishCoalesce(e.side, () => ( "auto")), resolvedSide: side } : {}, ...at ? { x: at.x, y: at.y } : {} };
@@ -10810,8 +10828,8 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10810
10828
  ...n2.name ? { name: n2.name } : {},
10811
10829
  route: _nullishCoalesce(n2.connector.route, () => ( "straight")),
10812
10830
  ...n2.connector.radius ? { radius: n2.connector.radius } : {},
10813
- start: end(n2.connector.start, _nullishCoalesce(_optionalChain([r, 'optionalAccess', _442 => _442.startSide]), () => ( null)), first),
10814
- end: end(n2.connector.end, _nullishCoalesce(_optionalChain([r, 'optionalAccess', _443 => _443.endSide]), () => ( null)), last)
10831
+ start: end(n2.connector.start, _nullishCoalesce(_optionalChain([r, 'optionalAccess', _449 => _449.startSide]), () => ( null)), first),
10832
+ end: end(n2.connector.end, _nullishCoalesce(_optionalChain([r, 'optionalAccess', _450 => _450.endSide]), () => ( null)), last)
10815
10833
  });
10816
10834
  });
10817
10835
  return out;
@@ -10878,9 +10896,9 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10878
10896
  nextPageRect(master) {
10879
10897
  const frames = this.doc.nodes.filter(_chunkBRKVNXDZcjs.isVectorFrame);
10880
10898
  const pages = _chunkBRKVNXDZcjs.vectorPages.call(void 0, this.doc);
10881
- const like = _nullishCoalesce(_optionalChain([pages, 'access', _444 => _444[pages.length - 1], 'optionalAccess', _445 => _445.frame]), () => ( _optionalChain([frames, 'access', _446 => _446[frames.length - 1], 'optionalAccess', _447 => _447.frame])));
10882
- const width = _nullishCoalesce(_optionalChain([like, 'optionalAccess', _448 => _448.width]), () => ( this.doc.width));
10883
- const height = _nullishCoalesce(_optionalChain([like, 'optionalAccess', _449 => _449.height]), () => ( this.doc.height));
10899
+ const like = _nullishCoalesce(_optionalChain([pages, 'access', _451 => _451[pages.length - 1], 'optionalAccess', _452 => _452.frame]), () => ( _optionalChain([frames, 'access', _453 => _453[frames.length - 1], 'optionalAccess', _454 => _454.frame])));
10900
+ const width = _nullishCoalesce(_optionalChain([like, 'optionalAccess', _455 => _455.width]), () => ( this.doc.width));
10901
+ const height = _nullishCoalesce(_optionalChain([like, 'optionalAccess', _456 => _456.height]), () => ( this.doc.height));
10884
10902
  if (!frames.length) return { x: 0, y: 0, width, height };
10885
10903
  const gap = Math.max(20, Math.round(width * 0.1));
10886
10904
  if (master) {
@@ -10905,7 +10923,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
10905
10923
  const first = !this.doc.nodes.some(_chunkBRKVNXDZcjs.isVectorFrame);
10906
10924
  const rect = this.nextPageRect(false);
10907
10925
  const id = this.newId();
10908
- const masterId = input.masterId === void 0 ? _nullishCoalesce(_optionalChain([pages, 'access', _450 => _450[pages.length - 1], 'optionalAccess', _451 => _451.frame, 'access', _452 => _452.masterId]), () => ( null)) : input.masterId;
10926
+ const masterId = input.masterId === void 0 ? _nullishCoalesce(_optionalChain([pages, 'access', _457 => _457[pages.length - 1], 'optionalAccess', _458 => _458.frame, 'access', _459 => _459.masterId]), () => ( null)) : input.masterId;
10909
10927
  const adopted = first ? this.doc.nodes.filter((n2) => !n2.locked && n2.visible !== false && !n2.blendStep) : [];
10910
10928
  const page = {
10911
10929
  id,
@@ -11018,7 +11036,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11018
11036
  }
11019
11037
  const locs = ids.map((id2) => _chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id2));
11020
11038
  const parent = _nullishCoalesce(locs[0].parent, () => ( null));
11021
- if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _453 => _453.parent, 'optionalAccess', _454 => _454.id]), () => ( null))) !== (_nullishCoalesce(_optionalChain([parent, 'optionalAccess', _455 => _455.id]), () => ( null))))) return { ok: false, message: "The objects must share a parent (pick objects at one level)." };
11039
+ if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _460 => _460.parent, 'optionalAccess', _461 => _461.id]), () => ( null))) !== (_nullishCoalesce(_optionalChain([parent, 'optionalAccess', _462 => _462.id]), () => ( null))))) return { ok: false, message: "The objects must share a parent (pick objects at one level)." };
11022
11040
  const b = _chunkBRKVNXDZcjs.unionBounds.call(void 0, ids.map((id2) => _chunkBRKVNXDZcjs.vectorNodeBounds.call(void 0, this.getNode(id2))));
11023
11041
  if (!b) return { ok: false, message: "The objects have no extent to frame." };
11024
11042
  const id = this.newId();
@@ -11058,7 +11076,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11058
11076
  const n2 = this.getNode(id);
11059
11077
  if (_chunkBRKVNXDZcjs.isVectorFrame.call(void 0, n2)) out.set(n2.id, n2);
11060
11078
  else if (!ids) {
11061
- const parent = _optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id), 'optionalAccess', _456 => _456.parent]);
11079
+ const parent = _optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id), 'optionalAccess', _463 => _463.parent]);
11062
11080
  if (_chunkBRKVNXDZcjs.isVectorFrame.call(void 0, parent)) out.set(parent.id, parent);
11063
11081
  }
11064
11082
  }
@@ -11127,7 +11145,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11127
11145
  if (!ids.length) return { ok: false, message: "Select objects inside a frame first." };
11128
11146
  for (const id of ids) {
11129
11147
  if (!this.getNode(id)) return { ok: false, message: `There is no node "${id}".` };
11130
- if (!_chunkBRKVNXDZcjs.isVectorFrame.call(void 0, _optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id), 'optionalAccess', _457 => _457.parent]))) return { ok: false, message: `"${id}" is not directly inside a frame: resizing constraints only apply to a frame's children.` };
11148
+ if (!_chunkBRKVNXDZcjs.isVectorFrame.call(void 0, _optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id), 'optionalAccess', _464 => _464.parent]))) return { ok: false, message: `"${id}" is not directly inside a frame: resizing constraints only apply to a frame's children.` };
11131
11149
  }
11132
11150
  const set = new Set(ids);
11133
11151
  this.change("Constraints", () => {
@@ -11148,7 +11166,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11148
11166
  artboard: parent === null,
11149
11167
  frame: n2.frame,
11150
11168
  bounds: _chunkBRKVNXDZcjs.vectorNodeBounds.call(void 0, n2, _nullishCoalesce(_chunkBRKVNXDZcjs.vectorParentMatrix.call(void 0, this.doc.nodes, n2.id), () => ( _chunkBRKVNXDZcjs.IDENTITY_MATRIX))),
11151
- children: n2.children.map((c) => ({ id: c.id, type: c.type, ...c.name ? { name: c.name } : {}, horizontal: _nullishCoalesce(_optionalChain([c, 'access', _458 => _458.resizing, 'optionalAccess', _459 => _459.horizontal]), () => ( "left")), vertical: _nullishCoalesce(_optionalChain([c, 'access', _460 => _460.resizing, 'optionalAccess', _461 => _461.vertical]), () => ( "top")) }))
11169
+ children: n2.children.map((c) => ({ id: c.id, type: c.type, ...c.name ? { name: c.name } : {}, horizontal: _nullishCoalesce(_optionalChain([c, 'access', _465 => _465.resizing, 'optionalAccess', _466 => _466.horizontal]), () => ( "left")), vertical: _nullishCoalesce(_optionalChain([c, 'access', _467 => _467.resizing, 'optionalAccess', _468 => _468.vertical]), () => ( "top")) }))
11152
11170
  });
11153
11171
  }
11154
11172
  if (n2.type === "group") visit(n2.children, n2.id);
@@ -11169,7 +11187,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11169
11187
  const n2 = this.getNode(id);
11170
11188
  if (_chunkBRKVNXDZcjs.isVectorMaskGroup.call(void 0, n2)) out.set(n2.id, n2);
11171
11189
  else {
11172
- const parent = _optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id), 'optionalAccess', _462 => _462.parent]);
11190
+ const parent = _optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id), 'optionalAccess', _469 => _469.parent]);
11173
11191
  if (_chunkBRKVNXDZcjs.isVectorMaskGroup.call(void 0, parent)) out.set(parent.id, parent);
11174
11192
  }
11175
11193
  }
@@ -11191,7 +11209,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11191
11209
  const children = [...contents, mask];
11192
11210
  released.push(...children.map((c) => c.id));
11193
11211
  const { mask: _m, ...rest } = g;
11194
- const keep = !!(_optionalChain([g, 'access', _463 => _463.filters, 'optionalAccess', _464 => _464.length]) || g.blendMode && g.blendMode !== "normal" || _optionalChain([g, 'access', _465 => _465.effects, 'optionalAccess', _466 => _466.length]));
11212
+ const keep = !!(_optionalChain([g, 'access', _470 => _470.filters, 'optionalAccess', _471 => _471.length]) || g.blendMode && g.blendMode !== "normal" || _optionalChain([g, 'access', _472 => _472.effects, 'optionalAccess', _473 => _473.length]));
11195
11213
  if (keep) {
11196
11214
  this.replaceNode(g.id, { ...rest, children });
11197
11215
  continue;
@@ -11275,7 +11293,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11275
11293
  const node = this.getNode(nodeId);
11276
11294
  if (!isVectorBlendGroup(group)) return { ok: false, message: `"${blendId}" is not a blend.` };
11277
11295
  if (!node || node.blendStep || node.locked || node.id === blendId) return { ok: false, message: `"${nodeId}" cannot be a key.` };
11278
- const parentOf = (id) => _nullishCoalesce(_optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id), 'optionalAccess', _467 => _467.parent, 'optionalAccess', _468 => _468.id]), () => ( null));
11296
+ const parentOf = (id) => _nullishCoalesce(_optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id), 'optionalAccess', _474 => _474.parent, 'optionalAccess', _475 => _475.id]), () => ( null));
11279
11297
  if (parentOf(blendId) !== parentOf(nodeId)) return { ok: false, message: "The new key must sit beside the blend (same parent)." };
11280
11298
  const start = options.start;
11281
11299
  this.change("Blend", () => {
@@ -11345,7 +11363,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11345
11363
  replaceBlendSpine(options = {}) {
11346
11364
  const roots = _nullishCoalesce(options.ids, () => ( this.selectedRoots()));
11347
11365
  const groups = this.blendTargets(roots);
11348
- const paths = roots.map((id) => this.getNode(id)).filter((n2) => _optionalChain([n2, 'optionalAccess', _469 => _469.type]) === "path" && !n2.blendStep && !isVectorBlendGroup(_optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, n2.id), 'optionalAccess', _470 => _470.parent])));
11366
+ const paths = roots.map((id) => this.getNode(id)).filter((n2) => _optionalChain([n2, 'optionalAccess', _476 => _476.type]) === "path" && !n2.blendStep && !isVectorBlendGroup(_optionalChain([_chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, n2.id), 'optionalAccess', _477 => _477.parent])));
11349
11367
  if (groups.length !== 1 || paths.length !== 1) return { ok: false, message: "Select one blend and one path to be its spine." };
11350
11368
  const group = groups[0];
11351
11369
  const path = paths[0];
@@ -11376,7 +11394,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11376
11394
  shapeBuilderMap(ids) {
11377
11395
  const roots = _nullishCoalesce(ids, () => ( this.selectedRoots()));
11378
11396
  const key = roots.join("\0");
11379
- if (_optionalChain([this, 'access', _471 => _471.builderCache, 'optionalAccess', _472 => _472.doc]) === this.doc && this.builderCache.key === key) return this.builderCache.map;
11397
+ if (_optionalChain([this, 'access', _478 => _478.builderCache, 'optionalAccess', _479 => _479.doc]) === this.doc && this.builderCache.key === key) return this.builderCache.map;
11380
11398
  const entries = roots.length ? vectorPathEntries(this.doc, roots, { expand: false }) : [];
11381
11399
  const map = entries.length ? vectorShapeBuilderMap(entries) : null;
11382
11400
  this.builderCache = { doc: this.doc, key, map };
@@ -11436,9 +11454,9 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11436
11454
  const list = [];
11437
11455
  const r = plan.replace.get(i);
11438
11456
  if (r === void 0) list.push(node);
11439
- else if (_optionalChain([r, 'optionalAccess', _473 => _473.kind]) === "fill") list.push({ ...node, fillRule: "nonzero", subpaths: _chunkBRKVNXDZcjs.bezierToSubpaths.call(void 0, toLocal(r.path)) });
11440
- else if (_optionalChain([r, 'optionalAccess', _474 => _474.kind]) === "outline") list.push({ ...node, subpaths: _chunkBRKVNXDZcjs.bezierToSubpaths.call(void 0, toLocal(r.path)) });
11441
- else if (_optionalChain([r, 'optionalAccess', _475 => _475.kind]) === "pieces") {
11457
+ else if (_optionalChain([r, 'optionalAccess', _480 => _480.kind]) === "fill") list.push({ ...node, fillRule: "nonzero", subpaths: _chunkBRKVNXDZcjs.bezierToSubpaths.call(void 0, toLocal(r.path)) });
11458
+ else if (_optionalChain([r, 'optionalAccess', _481 => _481.kind]) === "outline") list.push({ ...node, subpaths: _chunkBRKVNXDZcjs.bezierToSubpaths.call(void 0, toLocal(r.path)) });
11459
+ else if (_optionalChain([r, 'optionalAccess', _482 => _482.kind]) === "pieces") {
11442
11460
  r.paths.forEach(
11443
11461
  (path, k) => list.push({ ...node, id: k === 0 ? node.id : this.newId(), subpaths: _chunkBRKVNXDZcjs.bezierToSubpaths.call(void 0, toLocal(path)).map((sp) => ({ ...sp, closed: false })) })
11444
11462
  );
@@ -11472,7 +11490,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11472
11490
  }
11473
11491
  /** The paint bucket's map of the visible outlines, cached per document and gap. */
11474
11492
  fillMap(gap) {
11475
- if (_optionalChain([this, 'access', _476 => _476.fillCache, 'optionalAccess', _477 => _477.doc]) === this.doc && this.fillCache.gap === gap) return this.fillCache.map;
11493
+ if (_optionalChain([this, 'access', _483 => _483.fillCache, 'optionalAccess', _484 => _484.doc]) === this.doc && this.fillCache.gap === gap) return this.fillCache.map;
11476
11494
  const map = vectorFillMap(this.doc, gap);
11477
11495
  this.fillCache = { doc: this.doc, gap, map };
11478
11496
  return map;
@@ -11486,8 +11504,8 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11486
11504
  */
11487
11505
  fillRegion(point, options = {}) {
11488
11506
  if (!Number.isFinite(point.x) || !Number.isFinite(point.y)) return null;
11489
- const region = _optionalChain([this, 'access', _478 => _478.fillMap, 'call', _479 => _479(_nullishCoalesce(options.gap, () => ( this.editing.fillGap))), 'optionalAccess', _480 => _480.regionAt, 'call', _481 => _481([point.x, point.y])]);
11490
- if (!_optionalChain([region, 'optionalAccess', _482 => _482.length])) return null;
11507
+ const region = _optionalChain([this, 'access', _485 => _485.fillMap, 'call', _486 => _486(_nullishCoalesce(options.gap, () => ( this.editing.fillGap))), 'optionalAccess', _487 => _487.regionAt, 'call', _488 => _488([point.x, point.y])]);
11508
+ if (!_optionalChain([region, 'optionalAccess', _489 => _489.length])) return null;
11491
11509
  let below = null;
11492
11510
  const roots = new Set(this.selectedRoots());
11493
11511
  _chunkBRKVNXDZcjs.walkVectorNodes.call(void 0, this.doc.nodes, (n2) => {
@@ -11513,7 +11531,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11513
11531
  /** Updates the Shape Builder / paint bucket highlight for the pointer at `p`; true when it changed. */
11514
11532
  hoverBuilder(p, alt) {
11515
11533
  if (this.tool === "paintBucket") {
11516
- const region = _nullishCoalesce(_optionalChain([this, 'access', _483 => _483.fillMap, 'call', _484 => _484(this.editing.fillGap), 'optionalAccess', _485 => _485.regionAt, 'call', _486 => _486([p.x, p.y])]), () => ( null));
11534
+ const region = _nullishCoalesce(_optionalChain([this, 'access', _490 => _490.fillMap, 'call', _491 => _491(this.editing.fillGap), 'optionalAccess', _492 => _492.regionAt, 'call', _493 => _493([p.x, p.y])]), () => ( null));
11517
11535
  const key2 = region ? _chunkGF2RBSDMcjs.bezierPathToSvg.call(void 0, region, { precision: 2 }) : null;
11518
11536
  if (key2 === this.builderHoverKey) return false;
11519
11537
  this.builderHoverKey = key2;
@@ -11621,7 +11639,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11621
11639
  /** `doc` with anchor `ref` moved to document point `to` by a Curvature-tool move. */
11622
11640
  curvatureMoved(doc, ref, to) {
11623
11641
  const node = _chunkBRKVNXDZcjs.findVectorNode.call(void 0, doc.nodes, ref.nodeId);
11624
- if (_optionalChain([node, 'optionalAccess', _487 => _487.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
11642
+ if (_optionalChain([node, 'optionalAccess', _494 => _494.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
11625
11643
  const q = this.toLocal(ref.nodeId, to, doc);
11626
11644
  const subpaths = node.subpaths.map((sp, i) => i === ref.subpath ? curvatureMoveAnchor(sp, ref.index, q) : sp);
11627
11645
  const nodes = mapTree(doc.nodes, (n2) => n2.id === ref.nodeId ? { ...node, subpaths } : n2);
@@ -11630,7 +11648,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11630
11648
  /** `doc` with segment `ref` bent through document point `p` at parameter `t`. */
11631
11649
  bent(doc, ref, t, p) {
11632
11650
  const node = _chunkBRKVNXDZcjs.findVectorNode.call(void 0, doc.nodes, ref.nodeId);
11633
- if (_optionalChain([node, 'optionalAccess', _488 => _488.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
11651
+ if (_optionalChain([node, 'optionalAccess', _495 => _495.type]) !== "path" || node.locked || !node.subpaths[ref.subpath]) return doc;
11634
11652
  const q = this.toLocal(ref.nodeId, p, doc);
11635
11653
  const subpaths = node.subpaths.map((sp, i) => i === ref.subpath ? bendSegment(sp, ref.segment, t, q) : sp);
11636
11654
  return { ...doc, nodes: mapTree(doc.nodes, (n2) => n2.id === ref.nodeId ? { ...node, subpaths } : n2) };
@@ -11641,7 +11659,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11641
11659
  */
11642
11660
  bendSegment(ref, to, t = 0.5) {
11643
11661
  const node = this.getNode(ref.nodeId);
11644
- const sp = _optionalChain([node, 'optionalAccess', _489 => _489.type]) === "path" ? node.subpaths[ref.subpath] : void 0;
11662
+ const sp = _optionalChain([node, 'optionalAccess', _496 => _496.type]) === "path" ? node.subpaths[ref.subpath] : void 0;
11645
11663
  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." };
11646
11664
  if (node.locked) return { ok: false, message: "The path is locked." };
11647
11665
  this.change("Bend Segment", () => {
@@ -11676,7 +11694,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11676
11694
  /** Adds an anchor on the nearest segment of `nodeId` to document point `point` (shape unchanged). */
11677
11695
  insertAnchorAt(nodeId, point) {
11678
11696
  const node = this.getNode(nodeId);
11679
- if (_optionalChain([node, 'optionalAccess', _490 => _490.type]) !== "path") return null;
11697
+ if (_optionalChain([node, 'optionalAccess', _497 => _497.type]) !== "path") return null;
11680
11698
  const hit = _chunkBRKVNXDZcjs.nearestSegment.call(void 0, node, this.toLocal(nodeId, point));
11681
11699
  if (!hit) return null;
11682
11700
  const { subpath, index } = _chunkBRKVNXDZcjs.insertAnchor.call(void 0, node.subpaths[hit.subpath], hit.segment, hit.t);
@@ -11720,7 +11738,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11720
11738
  setClosed(closed, nodeId) {
11721
11739
  const targets = nodeId ? (() => {
11722
11740
  const n2 = this.getNode(nodeId);
11723
- return _optionalChain([n2, 'optionalAccess', _491 => _491.type]) === "path" ? n2.subpaths.map((_, s) => ({ nodeId, subpath: s })) : [];
11741
+ return _optionalChain([n2, 'optionalAccess', _498 => _498.type]) === "path" ? n2.subpaths.map((_, s) => ({ nodeId, subpath: s })) : [];
11724
11742
  })() : this.anchors.map((r) => ({ nodeId: r.nodeId, subpath: r.subpath }));
11725
11743
  if (!targets.length) return { ok: false, message: "Select a path or points." };
11726
11744
  this.change(closed ? "Close Path" : "Open Path", () => {
@@ -11741,7 +11759,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11741
11759
  this.setDoc(
11742
11760
  mapTree(
11743
11761
  this.doc.nodes,
11744
- (n2) => n2.type === "path" && set.has(n2.id) ? { ...n2, subpaths: n2.subpaths.map(_chunkBRKVNXDZcjs.reverseSubpath), ..._optionalChain([n2, 'access', _492 => _492.strokeWidthProfile, 'optionalAccess', _493 => _493.length]) ? { strokeWidthProfile: _chunkBRKVNXDZcjs.reverseWidthProfile.call(void 0, n2.strokeWidthProfile) } : {} } : n2
11762
+ (n2) => n2.type === "path" && set.has(n2.id) ? { ...n2, subpaths: n2.subpaths.map(_chunkBRKVNXDZcjs.reverseSubpath), ..._optionalChain([n2, 'access', _499 => _499.strokeWidthProfile, 'optionalAccess', _500 => _500.length]) ? { strokeWidthProfile: _chunkBRKVNXDZcjs.reverseWidthProfile.call(void 0, n2.strokeWidthProfile) } : {} } : n2
11745
11763
  )
11746
11764
  );
11747
11765
  this.anchors = [];
@@ -11879,7 +11897,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11879
11897
  */
11880
11898
  cutPathAt(nodeId, point) {
11881
11899
  const node = this.getNode(nodeId);
11882
- if (_optionalChain([node, 'optionalAccess', _494 => _494.type]) !== "path" || node.locked) return null;
11900
+ if (_optionalChain([node, 'optionalAccess', _501 => _501.type]) !== "path" || node.locked) return null;
11883
11901
  const local = this.toLocal(nodeId, point);
11884
11902
  const hit = _chunkBRKVNXDZcjs.nearestSegment.call(void 0, node, local);
11885
11903
  if (!hit) return null;
@@ -11929,7 +11947,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11929
11947
  if (n2.visible === false || n2.locked || parent && blocked.has(parent.id)) blocked.add(n2.id);
11930
11948
  });
11931
11949
  const visible = (p) => !blocked.has(p.id);
11932
- if (_optionalChain([ids, 'optionalAccess', _495 => _495.length]) || this.selection.length) return this.pathTargets(_nullishCoalesce(ids, () => ( this.selection))).filter(visible);
11950
+ if (_optionalChain([ids, 'optionalAccess', _502 => _502.length]) || this.selection.length) return this.pathTargets(_nullishCoalesce(ids, () => ( this.selection))).filter(visible);
11933
11951
  const box = _chunkBRKVNXDZcjs.polylineBounds.call(void 0, points.map(toPoint2), pad);
11934
11952
  if (!box) return [];
11935
11953
  const out = [];
@@ -11991,7 +12009,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
11991
12009
  */
11992
12010
  distortBrush(mode, points, options = {}) {
11993
12011
  if (!VECTOR_DISTORT_BRUSH_MODES.includes(mode)) return { ok: false, message: `Unknown brush "${mode}": use ${VECTOR_DISTORT_BRUSH_MODES.join(", ")}.` };
11994
- if (!points.length || points.some((q) => !Number.isFinite(_optionalChain([q, 'optionalAccess', _496 => _496.x])) || !Number.isFinite(_optionalChain([q, 'optionalAccess', _497 => _497.y])))) return { ok: false, message: "points must be one or more { x, y } numbers." };
12012
+ if (!points.length || points.some((q) => !Number.isFinite(_optionalChain([q, 'optionalAccess', _503 => _503.x])) || !Number.isFinite(_optionalChain([q, 'optionalAccess', _504 => _504.y])))) return { ok: false, message: "points must be one or more { x, y } numbers." };
11995
12013
  if (mode === "smudge" && points.length < 2) return { ok: false, message: "Smudge needs two or more points: the stroke pushes the outlines along it." };
11996
12014
  const radius = _nullishCoalesce(options.radius, () => ( this.editing.distortSize));
11997
12015
  const strength = _nullishCoalesce(options.strength, () => ( this.editing.distortStrength));
@@ -12090,7 +12108,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
12090
12108
  finishPath() {
12091
12109
  if (!this.pen) return;
12092
12110
  const node = this.getNode(this.pen.nodeId);
12093
- const sp = _optionalChain([node, 'optionalAccess', _498 => _498.subpaths, 'access', _499 => _499[this.pen.subpath]]);
12111
+ const sp = _optionalChain([node, 'optionalAccess', _505 => _505.subpaths, 'access', _506 => _506[this.pen.subpath]]);
12094
12112
  const pen = this.pen;
12095
12113
  this.pen = null;
12096
12114
  this.pointer = null;
@@ -12134,7 +12152,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
12134
12152
  if (trimmed.startsWith("{")) {
12135
12153
  try {
12136
12154
  const data = JSON.parse(trimmed);
12137
- if (_optionalChain([data, 'optionalAccess', _500 => _500.type]) === VECTOR_CLIPBOARD_TYPE && Array.isArray(data.nodes)) nodes = data.nodes;
12155
+ if (_optionalChain([data, 'optionalAccess', _507 => _507.type]) === VECTOR_CLIPBOARD_TYPE && Array.isArray(data.nodes)) nodes = data.nodes;
12138
12156
  } catch (e8) {
12139
12157
  nodes = null;
12140
12158
  }
@@ -12146,7 +12164,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
12146
12164
  }
12147
12165
  }
12148
12166
  } else nodes = this.clipboard;
12149
- if (!_optionalChain([nodes, 'optionalAccess', _501 => _501.length])) return [];
12167
+ if (!_optionalChain([nodes, 'optionalAccess', _508 => _508.length])) return [];
12150
12168
  const offset = _nullishCoalesce(options.offset, () => ( (text && !text.trim().startsWith("{") ? { x: 0, y: 0 } : { x: 10, y: 10 })));
12151
12169
  const copies = nodes.map((n2) => _chunkBRKVNXDZcjs.transformVectorNode.call(void 0, this.freshIds(n2), _chunkBRKVNXDZcjs.translateMatrix.call(void 0, offset.x, offset.y)));
12152
12170
  this.change("Paste", () => {
@@ -12197,7 +12215,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
12197
12215
  hitHandle(screen) {
12198
12216
  for (const ref of getVisibleHandles(this.view()).reverse()) {
12199
12217
  const a = getAnchorWorld(this.doc, ref);
12200
- const h = _optionalChain([a, 'optionalAccess', _502 => _502[ref.handle]]);
12218
+ const h = _optionalChain([a, 'optionalAccess', _509 => _509[ref.handle]]);
12201
12219
  if (!h) continue;
12202
12220
  const s = this.documentToScreen(h);
12203
12221
  if (Math.hypot(s.x - screen.x, s.y - screen.y) <= this.hitRadius) return ref;
@@ -12350,7 +12368,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
12350
12368
  const shown = this.hitWidthHandleIn(screen, this.widthView());
12351
12369
  if (shown) return shown;
12352
12370
  const spot = this.strokeSpotAt(this.screenToDocument(screen));
12353
- return spot && spot.nodeId !== _optionalChain([this, 'access', _503 => _503.hover, 'optionalAccess', _504 => _504.nodeId]) ? this.hitWidthHandleIn(screen, { ...this.widthView(), hover: { nodeId: spot.nodeId } }) : null;
12371
+ return spot && spot.nodeId !== _optionalChain([this, 'access', _510 => _510.hover, 'optionalAccess', _511 => _511.nodeId]) ? this.hitWidthHandleIn(screen, { ...this.widthView(), hover: { nodeId: spot.nodeId } }) : null;
12354
12372
  }
12355
12373
  hitWidthHandleIn(screen, view) {
12356
12374
  let best = null;
@@ -12405,9 +12423,9 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
12405
12423
  downWidth(screen, p, input) {
12406
12424
  const hit = this.hitWidthHandle(screen);
12407
12425
  const spot = hit ? null : this.strokeSpotAt(p);
12408
- const nodeId = _nullishCoalesce(_optionalChain([hit, 'optionalAccess', _505 => _505.ref, 'access', _506 => _506.nodeId]), () => ( _optionalChain([spot, 'optionalAccess', _507 => _507.nodeId])));
12426
+ const nodeId = _nullishCoalesce(_optionalChain([hit, 'optionalAccess', _512 => _512.ref, 'access', _513 => _513.nodeId]), () => ( _optionalChain([spot, 'optionalAccess', _514 => _514.nodeId])));
12409
12427
  const node = nodeId ? this.getNode(nodeId) : void 0;
12410
- const g = _optionalChain([node, 'optionalAccess', _508 => _508.type]) === "path" ? vectorStrokeWidthGeometry(node) : null;
12428
+ const g = _optionalChain([node, 'optionalAccess', _515 => _515.type]) === "path" ? vectorStrokeWidthGeometry(node) : null;
12411
12429
  if (this.widthEdit) this.widthEdit = null;
12412
12430
  if (!node || node.type !== "path" || !g) {
12413
12431
  if (!input.shift) this.widthPoints = [];
@@ -12427,7 +12445,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
12427
12445
  if (hit) {
12428
12446
  profile = _chunkBRKVNXDZcjs.sanitizeWidthProfile.call(void 0, node.strokeWidthProfile);
12429
12447
  ref = { nodeId: node.id, index: hit.ref.index, subpath: hit.ref.subpath };
12430
- t = _nullishCoalesce(_optionalChain([profile, 'access', _509 => _509[ref.index], 'optionalAccess', _510 => _510.t]), () => ( 0));
12448
+ t = _nullishCoalesce(_optionalChain([profile, 'access', _516 => _516[ref.index], 'optionalAccess', _517 => _517.t]), () => ( 0));
12431
12449
  subpath = hit.ref.subpath;
12432
12450
  if (hit.ref.part === "center") mode = input.alt && profile.length < _chunkBRKVNXDZcjs.VECTOR_WIDTH_PROFILE_MAX_POINTS ? "copy" : "move";
12433
12451
  else if (input.alt) side = hit.ref.part;
@@ -12594,7 +12612,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
12594
12612
  let anchor = null;
12595
12613
  if (node.type === "path" && node.subpaths[0]) {
12596
12614
  const refs = node.subpaths[0].anchors.map((_, index) => ({ nodeId: node.id, subpath: 0, index }));
12597
- anchor = _nullishCoalesce(_optionalChain([this, 'access', _511 => _511.hitAnchor, 'call', _512 => _512(screen, refs), 'optionalAccess', _513 => _513.index]), () => ( null));
12615
+ anchor = _nullishCoalesce(_optionalChain([this, 'access', _518 => _518.hitAnchor, 'call', _519 => _519(screen, refs), 'optionalAccess', _520 => _520.index]), () => ( null));
12598
12616
  }
12599
12617
  return { nodeId: node.id, anchor };
12600
12618
  }
@@ -12747,7 +12765,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
12747
12765
  }
12748
12766
  downPen(screen, p, input) {
12749
12767
  const before = this.snapshot();
12750
- const sp = this.pen ? _optionalChain([this, 'access', _514 => _514.getNode, 'call', _515 => _515(this.pen.nodeId), 'optionalAccess', _516 => _516.subpaths, 'access', _517 => _517[this.pen.subpath]]) : void 0;
12768
+ const sp = this.pen ? _optionalChain([this, 'access', _521 => _521.getNode, 'call', _522 => _522(this.pen.nodeId), 'optionalAccess', _523 => _523.subpaths, 'access', _524 => _524[this.pen.subpath]]) : void 0;
12751
12769
  if (this.pen && sp) {
12752
12770
  const pen = this.pen;
12753
12771
  const first = { nodeId: pen.nodeId, subpath: pen.subpath, index: 0 };
@@ -12872,7 +12890,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
12872
12890
  return;
12873
12891
  case "textSelect": {
12874
12892
  const node = this.getNode(drag.nodeId);
12875
- if (_optionalChain([node, 'optionalAccess', _518 => _518.type]) === "text" && this.textEdit) {
12893
+ if (_optionalChain([node, 'optionalAccess', _525 => _525.type]) === "text" && this.textEdit) {
12876
12894
  this.textEdit = { ...this.textEdit, focus: _chunkBRKVNXDZcjs.vectorTextIndexAt.call(void 0, node, this.toLocal(node.id, p)) };
12877
12895
  this.notify();
12878
12896
  }
@@ -13048,15 +13066,15 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13048
13066
  if (!_chunkBRKVNXDZcjs.isVectorConnector.call(void 0, node)) return;
13049
13067
  const target = _chunkBRKVNXDZcjs.vectorConnectorTargetAt.call(void 0, this.doc.nodes, p, this.connectorRadius(), drag.nodeId);
13050
13068
  const startGlue = node.connector.start;
13051
- const end = target && target.nodeId !== _optionalChain([startGlue, 'optionalAccess', _519 => _519.nodeId]) ? { nodeId: target.nodeId, ...target.side && target.side !== "auto" ? { side: target.side } : {} } : null;
13052
- const first = _nullishCoalesce(_optionalChain([node, 'access', _520 => _520.subpaths, 'access', _521 => _521[0], 'optionalAccess', _522 => _522.anchors, 'access', _523 => _523[0]]), () => ( drag.start));
13069
+ const end = target && target.nodeId !== _optionalChain([startGlue, 'optionalAccess', _526 => _526.nodeId]) ? { nodeId: target.nodeId, ...target.side && target.side !== "auto" ? { side: target.side } : {} } : null;
13070
+ const first = _nullishCoalesce(_optionalChain([node, 'access', _527 => _527.subpaths, 'access', _528 => _528[0], 'optionalAccess', _529 => _529.anchors, 'access', _530 => _530[0]]), () => ( drag.start));
13053
13071
  this.replaceNode(drag.nodeId, { ...node, connector: { ...node.connector, end }, subpaths: [{ closed: false, anchors: [{ x: first.x, y: first.y }, { x: p.x, y: p.y }] }] });
13054
13072
  this.notify(true);
13055
13073
  return;
13056
13074
  }
13057
13075
  case "shape": {
13058
13076
  const node = this.getNode(drag.nodeId);
13059
- if (_optionalChain([node, 'optionalAccess', _524 => _524.type]) !== "path") return;
13077
+ if (_optionalChain([node, 'optionalAccess', _531 => _531.type]) !== "path") return;
13060
13078
  const leave = { at: drag.start, constrain: input.shift ? drag.tool === "line" ? "angle" : "square" : null, curves: false };
13061
13079
  let end = this.snapDrawn(p, leave, input, () => drag.targets ??= this.drawingTargets(null));
13062
13080
  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);
@@ -13132,14 +13150,14 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13132
13150
  for (const q of drag.lazy.push([p.x, p.y])) {
13133
13151
  if (Math.hypot(q[0] - last[0], q[1] - last[1]) * this.viewport.zoom < 1.5) continue;
13134
13152
  drag.points.push(q);
13135
- _optionalChain([drag, 'access', _525 => _525.pressures, 'optionalAccess', _526 => _526.push, 'call', _527 => _527(drag.pressure)]);
13153
+ _optionalChain([drag, 'access', _532 => _532.pressures, 'optionalAccess', _533 => _533.push, 'call', _534 => _534(drag.pressure)]);
13136
13154
  moved = true;
13137
13155
  }
13138
13156
  const string = drag.lazy.string();
13139
13157
  const node = this.getNode(drag.nodeId);
13140
- if (_optionalChain([node, 'optionalAccess', _528 => _528.type]) !== "path") return;
13158
+ if (_optionalChain([node, 'optionalAccess', _535 => _535.type]) !== "path") return;
13141
13159
  if (!moved) {
13142
- if (string && _optionalChain([this, 'access', _529 => _529.interaction, 'optionalAccess', _530 => _530.type]) === "draw") {
13160
+ if (string && _optionalChain([this, 'access', _536 => _536.interaction, 'optionalAccess', _537 => _537.type]) === "draw") {
13143
13161
  this.interaction = { ...this.interaction, string: [{ x: string[0][0], y: string[0][1] }, { x: string[1][0], y: string[1][1] }] };
13144
13162
  this.notify();
13145
13163
  }
@@ -13175,8 +13193,8 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13175
13193
  }
13176
13194
  this.setGuides(res);
13177
13195
  return {
13178
- dx: _optionalChain([res, 'optionalAccess', _531 => _531.x]) ? dx + res.dx : axes.x ? this.gridValue(origin.x + dx) - origin.x : dx,
13179
- dy: _optionalChain([res, 'optionalAccess', _532 => _532.y]) ? dy + res.dy : axes.y ? this.gridValue(origin.y + dy) - origin.y : dy
13196
+ dx: _optionalChain([res, 'optionalAccess', _538 => _538.x]) ? dx + res.dx : axes.x ? this.gridValue(origin.x + dx) - origin.x : dx,
13197
+ dy: _optionalChain([res, 'optionalAccess', _539 => _539.y]) ? dy + res.dy : axes.y ? this.gridValue(origin.y + dy) - origin.y : dy
13180
13198
  };
13181
13199
  }
13182
13200
  /** The anchor a point drag snaps by, where it started: the grabbed one, else the moving one nearest the press. */
@@ -13266,7 +13284,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13266
13284
  if (drag.moved) return this.commit("Corner Radius", drag.before);
13267
13285
  if (drag.alt) {
13268
13286
  const kind = _chunkBRKVNXDZcjs.nextVectorCornerKind.call(void 0, drag.widget.kind);
13269
- this.doc = this.updateAnchors(drag.base, drag.refs, (a) => _chunkBRKVNXDZcjs.setAnchorCorner.call(void 0, a, _nullishCoalesce(_optionalChain([a, 'access', _533 => _533.corner, 'optionalAccess', _534 => _534.radius]), () => ( 0)), kind));
13287
+ this.doc = this.updateAnchors(drag.base, drag.refs, (a) => _chunkBRKVNXDZcjs.setAnchorCorner.call(void 0, a, _nullishCoalesce(_optionalChain([a, 'access', _540 => _540.corner, 'optionalAccess', _541 => _541.radius]), () => ( 0)), kind));
13270
13288
  return this.commit("Corner Kind", drag.before);
13271
13289
  }
13272
13290
  const ref = drag.widget.ref;
@@ -13281,7 +13299,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13281
13299
  const several = drag.group.length > 0;
13282
13300
  if (drag.mode === "copy") this.widthPoints = [drag.ref];
13283
13301
  else if (drag.mode === "move" && several) {
13284
- this.widthPoints = [drag.source, ...drag.group].map((i) => ({ ...drag.ref, index: _nullishCoalesce(_optionalChain([drag, 'access', _535 => _535.renumber, 'optionalAccess', _536 => _536.get, 'call', _537 => _537(i)]), () => ( i)) }));
13302
+ this.widthPoints = [drag.source, ...drag.group].map((i) => ({ ...drag.ref, index: _nullishCoalesce(_optionalChain([drag, 'access', _542 => _542.renumber, 'optionalAccess', _543 => _543.get, 'call', _544 => _544(i)]), () => ( i)) }));
13285
13303
  } else if (!several) this.widthPoints = [drag.ref];
13286
13304
  const label2 = drag.mode === "copy" ? "Copy Width Point" : drag.mode === "move" ? several ? "Move Width Points" : "Move Width Point" : several ? "Width Points" : "Width Point";
13287
13305
  return this.commit(label2, drag.before);
@@ -13359,14 +13377,14 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13359
13377
  }
13360
13378
  case "pencil": {
13361
13379
  const node = this.getNode(drag.nodeId);
13362
- if (_optionalChain([node, 'optionalAccess', _538 => _538.type]) !== "path" || drag.points.length < 2) {
13380
+ if (_optionalChain([node, 'optionalAccess', _545 => _545.type]) !== "path" || drag.points.length < 2) {
13363
13381
  this.doc = drag.before.doc;
13364
13382
  this.notify(true);
13365
13383
  return;
13366
13384
  }
13367
13385
  for (const q of drag.lazy.finish()) {
13368
13386
  drag.points.push(q);
13369
- _optionalChain([drag, 'access', _539 => _539.pressures, 'optionalAccess', _540 => _540.push, 'call', _541 => _541(drag.pressure)]);
13387
+ _optionalChain([drag, 'access', _546 => _546.pressures, 'optionalAccess', _547 => _547.push, 'call', _548 => _548(drag.pressure)]);
13370
13388
  }
13371
13389
  const shape = this.editing.recognizeShapes ? recognizeInkShape(drag.points, { minSize: 6 / this.viewport.zoom }) : null;
13372
13390
  if (shape) {
@@ -13440,7 +13458,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13440
13458
  if (text) {
13441
13459
  if (this.tool === "select") this.setTool("type");
13442
13460
  const index = _chunkBRKVNXDZcjs.vectorTextIndexAt.call(void 0, text, this.toLocal(text.id, p));
13443
- if (_optionalChain([this, 'access', _542 => _542.textEdit, 'optionalAccess', _543 => _543.nodeId]) === text.id) {
13461
+ if (_optionalChain([this, 'access', _549 => _549.textEdit, 'optionalAccess', _550 => _550.nodeId]) === text.id) {
13444
13462
  const [a, b] = wordAt(text.text, index);
13445
13463
  this.textEdit = { ...this.textEdit, anchor: a, focus: b };
13446
13464
  this.notify();
@@ -13465,7 +13483,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13465
13483
  this.convertAnchors(a.in || a.out ? "corner" : "smooth", [anchor]);
13466
13484
  return;
13467
13485
  }
13468
- const id = _nullishCoalesce(_optionalChain([this, 'access', _544 => _544.hover, 'optionalAccess', _545 => _545.segment, 'optionalAccess', _546 => _546.nodeId]), () => ( this.editingId));
13486
+ const id = _nullishCoalesce(_optionalChain([this, 'access', _551 => _551.hover, 'optionalAccess', _552 => _552.segment, 'optionalAccess', _553 => _553.nodeId]), () => ( this.editingId));
13469
13487
  if (id) {
13470
13488
  const node = this.getNode(id);
13471
13489
  const seg = node ? _chunkBRKVNXDZcjs.nearestSegment.call(void 0, node, this.toLocal(id, p)) : null;
@@ -13572,7 +13590,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13572
13590
  return { ok: false, message: e instanceof Error ? e.message : String(e) };
13573
13591
  }
13574
13592
  if (next === node) return { ok: true };
13575
- const pending = _optionalChain([this, 'access', _547 => _547.textEdit, 'optionalAccess', _548 => _548.nodeId]) === id ? this.textEdit.before : null;
13593
+ const pending = _optionalChain([this, 'access', _554 => _554.textEdit, 'optionalAccess', _555 => _555.nodeId]) === id ? this.textEdit.before : null;
13576
13594
  const before = _nullishCoalesce(pending, () => ( this.snapshot()));
13577
13595
  if (pending && this.textEdit) this.textEdit.before = null;
13578
13596
  this.replaceNode(id, next);
@@ -13684,10 +13702,10 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13684
13702
  frame = _chunkBRKVNXDZcjs.sanitizeVectorTextFrame.call(void 0, { kind: "point", x: _nullishCoalesce(patch.x, () => ( layout.origin.x + at.x)), y: _nullishCoalesce(patch.y, () => ( layout.origin.y + at.y)) });
13685
13703
  } else if (kind === "point") {
13686
13704
  const first = layout.lines[0];
13687
- const x = _nullishCoalesce(patch.x, () => ( (cur.kind === "point" ? cur.x : _nullishCoalesce(_optionalChain([first, 'optionalAccess', _549 => _549.x]), () => ( box.x)))));
13688
- const y = _nullishCoalesce(patch.y, () => ( (cur.kind === "point" ? cur.y : _nullishCoalesce(_optionalChain([first, 'optionalAccess', _550 => _550.baseline]), () => ( box.y)))));
13705
+ const x = _nullishCoalesce(patch.x, () => ( (cur.kind === "point" ? cur.x : _nullishCoalesce(_optionalChain([first, 'optionalAccess', _556 => _556.x]), () => ( box.x)))));
13706
+ const y = _nullishCoalesce(patch.y, () => ( (cur.kind === "point" ? cur.y : _nullishCoalesce(_optionalChain([first, 'optionalAccess', _557 => _557.baseline]), () => ( box.y)))));
13689
13707
  frame = _chunkBRKVNXDZcjs.sanitizeVectorTextFrame.call(void 0, { kind: "point", x, y });
13690
- if (cur.kind !== "point" && first && _optionalChain([n2, 'access', _551 => _551.paragraph, 'optionalAccess', _552 => _552.align]) && n2.paragraph.align !== "left") frame = _chunkBRKVNXDZcjs.sanitizeVectorTextFrame.call(void 0, { kind: "point", x: box.x, y });
13708
+ if (cur.kind !== "point" && first && _optionalChain([n2, 'access', _558 => _558.paragraph, 'optionalAccess', _559 => _559.align]) && n2.paragraph.align !== "left") frame = _chunkBRKVNXDZcjs.sanitizeVectorTextFrame.call(void 0, { kind: "point", x: box.x, y });
13691
13709
  } else if (kind === "area") {
13692
13710
  const base = cur.kind === "area" ? cur : { x: box.x, y: box.y, width: Math.max(box.width, n2.font.fontSize), height: Math.max(box.height, n2.font.fontSize * 1.2) };
13693
13711
  frame = _chunkBRKVNXDZcjs.sanitizeVectorTextFrame.call(void 0, { kind: "area", x: _nullishCoalesce(patch.x, () => ( base.x)), y: _nullishCoalesce(patch.y, () => ( base.y)), width: _nullishCoalesce(patch.width, () => ( base.width)), height: _nullishCoalesce(patch.height, () => ( base.height)) });
@@ -13774,15 +13792,15 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13774
13792
  ...t.locked ? { locked: true } : {},
13775
13793
  ...t.opacity !== void 0 ? { opacity: t.opacity } : {},
13776
13794
  ...t.blendMode ? { blendMode: t.blendMode } : {},
13777
- ..._optionalChain([t, 'access', _553 => _553.filters, 'optionalAccess', _554 => _554.length]) ? { filters: t.filters } : {},
13778
- ..._optionalChain([t, 'access', _555 => _555.effects, 'optionalAccess', _556 => _556.length]) ? { effects: t.effects } : {},
13795
+ ..._optionalChain([t, 'access', _560 => _560.filters, 'optionalAccess', _561 => _561.length]) ? { filters: t.filters } : {},
13796
+ ..._optionalChain([t, 'access', _562 => _562.effects, 'optionalAccess', _563 => _563.length]) ? { effects: t.effects } : {},
13779
13797
  ...t.booleanOperation ? { booleanOperation: t.booleanOperation } : {}
13780
13798
  };
13781
13799
  const pathOf = (fill, path, id) => {
13782
13800
  const { transform: _t, visible: _v, locked: _l, opacity: _o, blendMode: _b, filters: _f, effects: _e, booleanOperation: _bo, name: _n, ...style } = _chunkBRKVNXDZcjs.vectorTextPaintSource.call(void 0, t, fill, _chunkBRKVNXDZcjs.bezierToSubpaths.call(void 0, path));
13783
13801
  return { ...style, id };
13784
13802
  };
13785
- if (parts.length <= 1) replaced.set(t.id, { ...pathOf(_optionalChain([parts, 'access', _557 => _557[0], 'optionalAccess', _558 => _558.fill]), _nullishCoalesce(_optionalChain([parts, 'access', _559 => _559[0], 'optionalAccess', _560 => _560.path]), () => ( [])), t.id), ...keep });
13803
+ if (parts.length <= 1) replaced.set(t.id, { ...pathOf(_optionalChain([parts, 'access', _564 => _564[0], 'optionalAccess', _565 => _565.fill]), _nullishCoalesce(_optionalChain([parts, 'access', _566 => _566[0], 'optionalAccess', _567 => _567.path]), () => ( [])), t.id), ...keep });
13786
13804
  else replaced.set(t.id, { id: t.id, type: "group", ...keep, children: parts.map((p) => ({ ...pathOf(p.fill, p.path, this.newId()), name: "Outlines" })) });
13787
13805
  }
13788
13806
  if (this.textEdit && replaced.has(this.textEdit.nodeId)) this.endTextEdit();
@@ -13792,7 +13810,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13792
13810
  /** The layout of text node `id` (lines, glyphs, bounds, overflow), or null. */
13793
13811
  getTextLayout(id) {
13794
13812
  const node = this.getNode(id);
13795
- return _optionalChain([node, 'optionalAccess', _561 => _561.type]) === "text" ? _chunkBRKVNXDZcjs.layoutVectorText.call(void 0, node) : null;
13813
+ return _optionalChain([node, 'optionalAccess', _568 => _568.type]) === "text" ? _chunkBRKVNXDZcjs.layoutVectorText.call(void 0, node) : null;
13796
13814
  }
13797
13815
  // --- Editing on the canvas ------------------------------------------------
13798
13816
  /**
@@ -13802,12 +13820,12 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13802
13820
  editText(id, options = {}) {
13803
13821
  const node = this.textNode(id);
13804
13822
  if (typeof node === "string") return { ok: false, message: node };
13805
- if (_optionalChain([this, 'access', _562 => _562.textEdit, 'optionalAccess', _563 => _563.nodeId]) !== id) this.endTextEdit();
13823
+ if (_optionalChain([this, 'access', _569 => _569.textEdit, 'optionalAccess', _570 => _570.nodeId]) !== id) this.endTextEdit();
13806
13824
  const n2 = node.text.length;
13807
13825
  const clamp = (v, d) => Math.max(0, Math.min(n2, _nullishCoalesce(v, () => ( d))));
13808
13826
  const focus = clamp(_nullishCoalesce(options.focus, () => ( options.index)), n2);
13809
13827
  const anchor = clamp(options.anchor, focus);
13810
- this.textEdit = { nodeId: id, anchor, focus, before: _optionalChain([this, 'access', _564 => _564.textEdit, 'optionalAccess', _565 => _565.nodeId]) === id ? this.textEdit.before : null, key: _optionalChain([this, 'access', _566 => _566.textEdit, 'optionalAccess', _567 => _567.nodeId]) === id ? this.textEdit.key : `text-edit:${id}:${++this.textEditCount}`, created: _optionalChain([this, 'access', _568 => _568.textEdit, 'optionalAccess', _569 => _569.nodeId]) === id ? this.textEdit.created : false };
13828
+ this.textEdit = { nodeId: id, anchor, focus, before: _optionalChain([this, 'access', _571 => _571.textEdit, 'optionalAccess', _572 => _572.nodeId]) === id ? this.textEdit.before : null, key: _optionalChain([this, 'access', _573 => _573.textEdit, 'optionalAccess', _574 => _574.nodeId]) === id ? this.textEdit.key : `text-edit:${id}:${++this.textEditCount}`, created: _optionalChain([this, 'access', _575 => _575.textEdit, 'optionalAccess', _576 => _576.nodeId]) === id ? this.textEdit.created : false };
13811
13829
  this.selection = [id];
13812
13830
  this.anchors = [];
13813
13831
  this.notify();
@@ -13817,7 +13835,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13817
13835
  selectText(anchor, focus = anchor) {
13818
13836
  const t = this.textEdit;
13819
13837
  const node = t ? this.getNode(t.nodeId) : null;
13820
- if (!t || _optionalChain([node, 'optionalAccess', _570 => _570.type]) !== "text") return;
13838
+ if (!t || _optionalChain([node, 'optionalAccess', _577 => _577.type]) !== "text") return;
13821
13839
  const n2 = node.text.length;
13822
13840
  this.textEdit = { ...t, anchor: Math.max(0, Math.min(n2, anchor)), focus: Math.max(0, Math.min(n2, focus)) };
13823
13841
  this.notify();
@@ -13832,7 +13850,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13832
13850
  this.textEdit = null;
13833
13851
  this.history.endGesture();
13834
13852
  const node = this.getNode(t.nodeId);
13835
- if (_optionalChain([node, 'optionalAccess', _571 => _571.type]) === "text" && !node.text) {
13853
+ if (_optionalChain([node, 'optionalAccess', _578 => _578.type]) === "text" && !node.text) {
13836
13854
  if (t.before) {
13837
13855
  this.doc = t.before.doc;
13838
13856
  this.selection = t.before.selection.filter((id) => this.getNode(id));
@@ -13867,7 +13885,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13867
13885
  textDelete(forward, word = false) {
13868
13886
  const t = this.textEdit;
13869
13887
  const node = t ? this.getNode(t.nodeId) : null;
13870
- if (!t || _optionalChain([node, 'optionalAccess', _572 => _572.type]) !== "text") return;
13888
+ if (!t || _optionalChain([node, 'optionalAccess', _579 => _579.type]) !== "text") return;
13871
13889
  let a = Math.min(t.anchor, t.focus);
13872
13890
  let b = Math.max(t.anchor, t.focus);
13873
13891
  if (a === b) {
@@ -13884,7 +13902,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13884
13902
  textKey(input) {
13885
13903
  const t = this.textEdit;
13886
13904
  const node = this.getNode(t.nodeId);
13887
- if (_optionalChain([node, 'optionalAccess', _573 => _573.type]) !== "text") {
13905
+ if (_optionalChain([node, 'optionalAccess', _580 => _580.type]) !== "text") {
13888
13906
  this.textEdit = null;
13889
13907
  return false;
13890
13908
  }
@@ -13969,7 +13987,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
13969
13987
  getSelectedText() {
13970
13988
  const t = this.textEdit;
13971
13989
  const node = t ? this.getNode(t.nodeId) : null;
13972
- if (!t || _optionalChain([node, 'optionalAccess', _574 => _574.type]) !== "text") return null;
13990
+ if (!t || _optionalChain([node, 'optionalAccess', _581 => _581.type]) !== "text") return null;
13973
13991
  return node.text.slice(Math.min(t.anchor, t.focus), Math.max(t.anchor, t.focus));
13974
13992
  }
13975
13993
  /** Cut while editing text: returns the selected characters and deletes them (null when not editing). */
@@ -14039,7 +14057,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
14039
14057
  const text = this.hitText(p);
14040
14058
  if (text) {
14041
14059
  const index = _chunkBRKVNXDZcjs.vectorTextIndexAt.call(void 0, text, this.toLocal(text.id, p));
14042
- if (_optionalChain([this, 'access', _575 => _575.textEdit, 'optionalAccess', _576 => _576.nodeId]) === text.id) {
14060
+ if (_optionalChain([this, 'access', _582 => _582.textEdit, 'optionalAccess', _583 => _583.nodeId]) === text.id) {
14043
14061
  this.textEdit = { ...this.textEdit, focus: index, anchor: input.shift ? this.textEdit.anchor : index };
14044
14062
  this.notify();
14045
14063
  } else this.editText(text.id, { index });
@@ -14056,7 +14074,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
14056
14074
  }
14057
14075
  if (this.tool === "typePath") {
14058
14076
  const path = this.hitPath(p);
14059
- if (!path || _optionalChain([path, 'access', _577 => _577.subpaths, 'access', _578 => _578[0], 'optionalAccess', _579 => _579.anchors, 'access', _580 => _580.length]) < 2 || hiddenOrLocked(this.doc.nodes, path.id)) return;
14077
+ if (!path || _optionalChain([path, 'access', _584 => _584.subpaths, 'access', _585 => _585[0], 'optionalAccess', _586 => _586.anchors, 'access', _587 => _587.length]) < 2 || hiddenOrLocked(this.doc.nodes, path.id)) return;
14060
14078
  let node;
14061
14079
  try {
14062
14080
  node = this.createTextNode({ text: "", path: path.subpaths[0] });
@@ -14084,16 +14102,16 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
14084
14102
  storedDocument() {
14085
14103
  const edit = this.symbolEdit;
14086
14104
  if (!edit) return this.doc;
14087
- const symbols = (_nullishCoalesce(edit.host.symbols, () => ( []))).map((s) => s.id === edit.symbolId ? { ...s, nodes: this.doc.nodes } : _nullishCoalesce(_optionalChain([this, 'access', _581 => _581.doc, 'access', _582 => _582.symbols, 'optionalAccess', _583 => _583.find, 'call', _584 => _584((x) => x.id === s.id)]), () => ( s)));
14105
+ const symbols = (_nullishCoalesce(edit.host.symbols, () => ( []))).map((s) => s.id === edit.symbolId ? { ...s, nodes: this.doc.nodes } : _nullishCoalesce(_optionalChain([this, 'access', _588 => _588.doc, 'access', _589 => _589.symbols, 'optionalAccess', _590 => _590.find, 'call', _591 => _591((x) => x.id === s.id)]), () => ( s)));
14088
14106
  return _chunkBRKVNXDZcjs.resolveVectorSymbols.call(void 0, { ...edit.host, symbols });
14089
14107
  }
14090
14108
  symbolEditState() {
14091
14109
  const edit = this.symbolEdit;
14092
14110
  if (!edit) return null;
14093
14111
  const host = this.storedDocument();
14094
- const sym = _optionalChain([host, 'access', _585 => _585.symbols, 'optionalAccess', _586 => _586.find, 'call', _587 => _587((s) => s.id === edit.symbolId)]);
14112
+ const sym = _optionalChain([host, 'access', _592 => _592.symbols, 'optionalAccess', _593 => _593.find, 'call', _594 => _594((s) => s.id === edit.symbolId)]);
14095
14113
  const hostTransform = edit.origin ? [1 / edit.scale, 0, 0, 1 / edit.scale, -edit.origin.x / edit.scale + 0, -edit.origin.y / edit.scale + 0] : null;
14096
- return { symbolId: edit.symbolId, name: _nullishCoalesce(_optionalChain([sym, 'optionalAccess', _588 => _588.name]), () => ( edit.symbolId)), instanceId: edit.instanceId, host, hostTransform };
14114
+ return { symbolId: edit.symbolId, name: _nullishCoalesce(_optionalChain([sym, 'optionalAccess', _595 => _595.name]), () => ( edit.symbolId)), instanceId: edit.instanceId, host, hostTransform };
14097
14115
  }
14098
14116
  /** The document's symbols (the stored ones, also while one is being edited). */
14099
14117
  getSymbols() {
@@ -14129,8 +14147,8 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
14129
14147
  if (!ids.length) return { ok: false, message: "Select the objects to make a symbol from." };
14130
14148
  const locs = ids.map((id) => _chunkBRKVNXDZcjs.locateVectorNode.call(void 0, this.doc.nodes, id));
14131
14149
  if (locs.some((l) => !l)) return { ok: false, message: `There is no node "${ids[locs.findIndex((l) => !l)]}".` };
14132
- const parent = _nullishCoalesce(_optionalChain([locs, 'access', _589 => _589[0], 'access', _590 => _590.parent, 'optionalAccess', _591 => _591.id]), () => ( null));
14133
- if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _592 => _592.parent, 'optionalAccess', _593 => _593.id]), () => ( null))) !== parent)) return { ok: false, message: "The objects must share a parent (the same group) to make one symbol." };
14150
+ const parent = _nullishCoalesce(_optionalChain([locs, 'access', _596 => _596[0], 'access', _597 => _597.parent, 'optionalAccess', _598 => _598.id]), () => ( null));
14151
+ if (locs.some((l) => (_nullishCoalesce(_optionalChain([l, 'access', _599 => _599.parent, 'optionalAccess', _600 => _600.id]), () => ( null))) !== parent)) return { ok: false, message: "The objects must share a parent (the same group) to make one symbol." };
14134
14152
  if (ids.some((id) => hiddenOrLocked(this.doc.nodes, id))) return { ok: false, message: "Unlock and show the objects first." };
14135
14153
  const parentMatrix = parent ? this.worldOf(parent) : _chunkBRKVNXDZcjs.IDENTITY_MATRIX;
14136
14154
  const box = _chunkBRKVNXDZcjs.unionBounds.call(void 0, ids.map((id) => _chunkBRKVNXDZcjs.vectorNodeBounds.call(void 0, this.getNode(id), _chunkBRKVNXDZcjs.IDENTITY_MATRIX)));
@@ -14140,7 +14158,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
14140
14158
  const cy = box.y + box.height / 2;
14141
14159
  const symbolId = this.newSymbolId();
14142
14160
  const instanceId = this.newId();
14143
- const name = _optionalChain([options, 'access', _594 => _594.name, 'optionalAccess', _595 => _595.trim, 'call', _596 => _596()]) || `Symbol ${this.getSymbols().length + 1}`;
14161
+ const name = _optionalChain([options, 'access', _601 => _601.name, 'optionalAccess', _602 => _602.trim, 'call', _603 => _603()]) || `Symbol ${this.getSymbols().length + 1}`;
14144
14162
  const set = new Set(ids);
14145
14163
  this.change("Make Symbol", () => {
14146
14164
  const replace = (list) => {
@@ -14221,7 +14239,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
14221
14239
  mapTree(this.doc.nodes, (n2) => {
14222
14240
  if (!set.has(n2.id) || n2.type !== "instance") return n2;
14223
14241
  const { art: _a, ...rest } = n2;
14224
- const hidden = _optionalChain([n2, 'access', _597 => _597.overrides, 'optionalAccess', _598 => _598.hidden]);
14242
+ const hidden = _optionalChain([n2, 'access', _604 => _604.overrides, 'optionalAccess', _605 => _605.hidden]);
14225
14243
  const overrides = n2.overrides ? { ...n2.overrides } : null;
14226
14244
  if (overrides && hidden) delete overrides.hidden;
14227
14245
  return { ...rest, symbolId, ...overrides && Object.keys(overrides).length ? { overrides } : { overrides: void 0 } };
@@ -14252,7 +14270,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
14252
14270
  else o[key] = patch[key];
14253
14271
  }
14254
14272
  if (patch.hidden !== void 0) {
14255
- if (_optionalChain([patch, 'access', _599 => _599.hidden, 'optionalAccess', _600 => _600.length])) {
14273
+ if (_optionalChain([patch, 'access', _606 => _606.hidden, 'optionalAccess', _607 => _607.length])) {
14256
14274
  const known = /* @__PURE__ */ new Set();
14257
14275
  _chunkBRKVNXDZcjs.walkVectorNodes.call(void 0, _nullishCoalesce(t.art, () => ( [])), (a) => known.add(a.id));
14258
14276
  const unknown = patch.hidden.filter((id) => !known.has(id));
@@ -14305,9 +14323,9 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
14305
14323
  */
14306
14324
  editSymbol(id) {
14307
14325
  const node = this.getNode(id);
14308
- const symbolId = _optionalChain([node, 'optionalAccess', _601 => _601.type]) === "instance" ? node.symbolId : id;
14326
+ const symbolId = _optionalChain([node, 'optionalAccess', _608 => _608.type]) === "instance" ? node.symbolId : id;
14309
14327
  const host = this.storedDocument();
14310
- const sym = _optionalChain([host, 'access', _602 => _602.symbols, 'optionalAccess', _603 => _603.find, 'call', _604 => _604((s) => s.id === symbolId)]);
14328
+ const sym = _optionalChain([host, 'access', _609 => _609.symbols, 'optionalAccess', _610 => _610.find, 'call', _611 => _611((s) => s.id === symbolId)]);
14311
14329
  if (!sym) return { ok: false, message: node ? `"${id}" is a ${node.type}, not a symbol instance.` : `There is no symbol or instance "${id}".` };
14312
14330
  if (this.symbolEdit) this.exitSymbolEdit();
14313
14331
  this.endTextEdit();
@@ -14315,7 +14333,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
14315
14333
  const fresh = this.storedDocument();
14316
14334
  let origin = null;
14317
14335
  let scale = 1;
14318
- const world = _optionalChain([node, 'optionalAccess', _605 => _605.type]) === "instance" ? _chunkBRKVNXDZcjs.vectorWorldMatrix.call(void 0, fresh.nodes, node.id) : null;
14336
+ const world = _optionalChain([node, 'optionalAccess', _612 => _612.type]) === "instance" ? _chunkBRKVNXDZcjs.vectorWorldMatrix.call(void 0, fresh.nodes, node.id) : null;
14319
14337
  if (world) {
14320
14338
  const det = Math.abs(world[0] * world[3] - world[1] * world[2]);
14321
14339
  if (det > 1e-12) {
@@ -14389,7 +14407,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
14389
14407
  if (anchor === void 0) {
14390
14408
  if (r.subpath === void 0 || r.index === void 0) throw new VectorConstraintError(`refs[${i}]: give an anchor (subpath and index, or its id), or circle: true.`);
14391
14409
  const sp = node.subpaths[r.subpath];
14392
- if (!_optionalChain([sp, 'optionalAccess', _606 => _606.anchors, 'access', _607 => _607[r.index]])) throw new VectorConstraintError(`refs[${i}]: "${r.nodeId}" has no anchor ${r.index} on subpath ${r.subpath}.`);
14410
+ if (!_optionalChain([sp, 'optionalAccess', _613 => _613.anchors, 'access', _614 => _614[r.index]])) throw new VectorConstraintError(`refs[${i}]: "${r.nodeId}" has no anchor ${r.index} on subpath ${r.subpath}.`);
14393
14411
  const withIds = withVectorAnchorIds(node);
14394
14412
  nodes.set(node.id, withIds);
14395
14413
  anchor = withIds.subpaths[r.subpath].anchors[r.index].id;
@@ -14604,7 +14622,7 @@ var VectorEditorController = (_class7 = class _VectorEditorController {
14604
14622
  this.finishPath();
14605
14623
  return true;
14606
14624
  }
14607
- if (this.tool === "select" && this.selection.length === 1 && _optionalChain([this, 'access', _608 => _608.getNode, 'call', _609 => _609(this.selection[0]), 'optionalAccess', _610 => _610.type]) === "path") {
14625
+ if (this.tool === "select" && this.selection.length === 1 && _optionalChain([this, 'access', _615 => _615.getNode, 'call', _616 => _616(this.selection[0]), 'optionalAccess', _617 => _617.type]) === "path") {
14608
14626
  this.tool = "direct";
14609
14627
  this.editingId = this.selection[0];
14610
14628
  this.notify();
@@ -14848,7 +14866,7 @@ var PLANS = {
14848
14866
  },
14849
14867
  setTextStyle: (p, controller) => {
14850
14868
  const node = controller.getNode(p.id);
14851
- if (_optionalChain([node, 'optionalAccess', _611 => _611.type]) !== "text") return null;
14869
+ if (_optionalChain([node, 'optionalAccess', _618 => _618.type]) !== "text") return null;
14852
14870
  const rect = createVectorPlaybackLocator(controller)({ kind: VECTOR_PLAYBACK_KIND, id: p.id });
14853
14871
  if (!rect) return null;
14854
14872
  const length = Math.max(1, node.text.length);
@@ -14862,7 +14880,7 @@ var PLANS = {
14862
14880
  },
14863
14881
  setMeshPoint: (p, controller) => {
14864
14882
  const shading = controller.getShading(p.id);
14865
- const point = _optionalChain([shading, 'optionalAccess', _612 => _612.points, 'access', _613 => _613[p.index]]);
14883
+ const point = _optionalChain([shading, 'optionalAccess', _619 => _619.points, 'access', _620 => _620[p.index]]);
14866
14884
  if (!point) return null;
14867
14885
  return num(p.x) && num(p.y) ? dragOut(point, { x: p.x, y: p.y }) : click(point);
14868
14886
  }
@@ -14878,7 +14896,7 @@ function withVectorPlayback(controller, prefix, commands) {
14878
14896
  return commands.map((spec) => {
14879
14897
  if (!spec.id.startsWith(prefix)) return spec;
14880
14898
  const name = spec.id.slice(prefix.length);
14881
- const props = _nullishCoalesce(_optionalChain([spec, 'access', _614 => _614.params, 'optionalAccess', _615 => _615.properties]), () => ( {}));
14899
+ const props = _nullishCoalesce(_optionalChain([spec, 'access', _621 => _621.params, 'optionalAccess', _622 => _622.properties]), () => ( {}));
14882
14900
  const planner = _nullishCoalesce(PLANS[name], () => ( (/Image$/.test(name) && "x" in props && "width" in props ? placeImage : void 0)));
14883
14901
  const surface = _nullishCoalesce(_nullishCoalesce(spec.playbackSurface, () => ( spec.scope)), () => ( "vector"));
14884
14902
  if (!planner || spec.plan) return { ...spec, playbackSurface: surface };
@@ -14933,9 +14951,9 @@ var BLEND_PROPS = {
14933
14951
  linear: { type: "boolean", description: "Move anchors in straight lines instead of the rotation-aware morph." }
14934
14952
  };
14935
14953
  var checkBlendOptions = (params) => {
14936
- if (_optionalChain([params, 'optionalAccess', _616 => _616.spacing]) !== void 0 && !_chunkBRKVNXDZcjs.VECTOR_BLEND_SPACINGS.includes(params.spacing)) fail(`Unknown blend spacing "${params.spacing}".`);
14937
- if (_optionalChain([params, 'optionalAccess', _617 => _617.steps]) !== void 0 && !(Number.isFinite(params.steps) && params.steps >= 1)) fail("steps must be at least 1.");
14938
- if (_optionalChain([params, 'optionalAccess', _618 => _618.distance]) !== void 0 && !(Number.isFinite(params.distance) && params.distance > 0)) fail("distance must be positive.");
14954
+ if (_optionalChain([params, 'optionalAccess', _623 => _623.spacing]) !== void 0 && !_chunkBRKVNXDZcjs.VECTOR_BLEND_SPACINGS.includes(params.spacing)) fail(`Unknown blend spacing "${params.spacing}".`);
14955
+ if (_optionalChain([params, 'optionalAccess', _624 => _624.steps]) !== void 0 && !(Number.isFinite(params.steps) && params.steps >= 1)) fail("steps must be at least 1.");
14956
+ if (_optionalChain([params, 'optionalAccess', _625 => _625.distance]) !== void 0 && !(Number.isFinite(params.distance) && params.distance > 0)) fail("distance must be positive.");
14939
14957
  };
14940
14958
  var POINT = { type: "object", properties: { x: { type: "number" }, y: { type: "number" } }, required: ["x", "y"] };
14941
14959
  var GRADIENT_PROPS = {
@@ -15038,22 +15056,22 @@ function createVectorCommands(controller, options = {}) {
15038
15056
  const base = { group, ...options.scope ? { scope: options.scope } : {} };
15039
15057
  const parentOf = (parentId) => {
15040
15058
  if (parentId === void 0) return {};
15041
- if (_optionalChain([controller, 'access', _619 => _619.getNode, 'call', _620 => _620(parentId), 'optionalAccess', _621 => _621.type]) !== "group") fail(`"${parentId}" is not a group to add into.`);
15059
+ if (_optionalChain([controller, 'access', _626 => _626.getNode, 'call', _627 => _627(parentId), 'optionalAccess', _628 => _628.type]) !== "group") fail(`"${parentId}" is not a group to add into.`);
15042
15060
  return { parentId };
15043
15061
  };
15044
15062
  const hasSelection = () => controller.getState().selection.length ? true : "Nothing is selected.";
15045
15063
  const ids = (params) => {
15046
- const list2 = _nullishCoalesce(_optionalChain([params, 'optionalAccess', _622 => _622.ids]), () => ( controller.getState().selection));
15064
+ const list2 = _nullishCoalesce(_optionalChain([params, 'optionalAccess', _629 => _629.ids]), () => ( controller.getState().selection));
15047
15065
  for (const id of list2) if (!controller.getNode(id)) fail(`There is no node "${id}".`);
15048
15066
  if (!list2.length) fail("Nothing is selected; pass ids.");
15049
15067
  return list2;
15050
15068
  };
15051
- const enabledFor = (_, params) => _optionalChain([params, 'optionalAccess', _623 => _623.ids, 'optionalAccess', _624 => _624.length]) ? true : hasSelection();
15069
+ const enabledFor = (_, params) => _optionalChain([params, 'optionalAccess', _630 => _630.ids, 'optionalAccess', _631 => _631.length]) ? true : hasSelection();
15052
15070
  const anchorsOf = (refs) => {
15053
15071
  if (!refs) return [...controller.getState().selectedAnchors];
15054
15072
  for (const r of refs) {
15055
15073
  const node = controller.getNode(r.nodeId);
15056
- if (_optionalChain([node, 'optionalAccess', _625 => _625.type]) !== "path" || !_optionalChain([node, 'access', _626 => _626.subpaths, 'access', _627 => _627[r.subpath], 'optionalAccess', _628 => _628.anchors, 'access', _629 => _629[r.index]])) fail(`There is no anchor ${r.index} on subpath ${r.subpath} of "${r.nodeId}".`);
15074
+ if (_optionalChain([node, 'optionalAccess', _632 => _632.type]) !== "path" || !_optionalChain([node, 'access', _633 => _633.subpaths, 'access', _634 => _634[r.subpath], 'optionalAccess', _635 => _635.anchors, 'access', _636 => _636[r.index]])) fail(`There is no anchor ${r.index} on subpath ${r.subpath} of "${r.nodeId}".`);
15057
15075
  }
15058
15076
  return refs;
15059
15077
  };
@@ -15077,13 +15095,13 @@ function createVectorCommands(controller, options = {}) {
15077
15095
  ...n2.type === "path" ? { fill: _nullishCoalesce(n2.fill, () => ( null)), stroke: _nullishCoalesce(n2.stroke, () => ( null)), strokeWidth: _nullishCoalesce(n2.strokeWidth, () => ( 1)), d: _chunkBRKVNXDZcjs.vectorPathData.call(void 0, n2, 2) } : n2.type === "text" ? { fill: _nullishCoalesce(n2.fill, () => ( null)), stroke: _nullishCoalesce(n2.stroke, () => ( null)), strokeWidth: _nullishCoalesce(n2.strokeWidth, () => ( 1)), text: n2.text, frame: n2.frame.kind } : n2.type === "instance" ? { symbolId: n2.symbolId, ...n2.transform ? { transform: [...n2.transform] } : {}, ...n2.overrides ? { overrides: n2.overrides } : {} } : { children: n2.children.length },
15078
15096
  ...n2.type === "group" && n2.blend ? { blend: { ...resolveVectorBlendOptions(n2.blend), spine: !!n2.blend.spine, keys: vectorBlendKeys(n2).map((k) => k.id) } } : {},
15079
15097
  ...n2.blendStep ? { blendStep: true } : {},
15080
- ..._optionalChain([n2, 'access', _630 => _630.effects, 'optionalAccess', _631 => _631.length]) ? { effects: n2.effects } : {},
15098
+ ..._optionalChain([n2, 'access', _637 => _637.effects, 'optionalAccess', _638 => _638.length]) ? { effects: n2.effects } : {},
15081
15099
  ...n2.type === "group" && n2.liveBoolean ? { liveBoolean: n2.liveBoolean } : {},
15082
15100
  ...n2.booleanOperation ? { booleanOperation: n2.booleanOperation } : {},
15083
15101
  ...(n2.type === "path" || n2.type === "text") && Array.isArray(n2.fills) ? { fills: n2.fills } : {},
15084
15102
  ...(n2.type === "path" || n2.type === "text") && Array.isArray(n2.strokes) ? { strokes: n2.strokes } : {},
15085
15103
  ...n2.blendMode && n2.blendMode !== "normal" ? { blendMode: n2.blendMode } : {},
15086
- ..._optionalChain([n2, 'access', _632 => _632.filters, 'optionalAccess', _633 => _633.length]) ? { filters: n2.filters } : {},
15104
+ ..._optionalChain([n2, 'access', _639 => _639.filters, 'optionalAccess', _640 => _640.length]) ? { filters: n2.filters } : {},
15087
15105
  ..._chunkBRKVNXDZcjs.isVectorMaskGroup.call(void 0, n2) ? { mask: _chunkBRKVNXDZcjs.vectorMaskSummary.call(void 0, n2) } : {},
15088
15106
  ..._chunkBRKVNXDZcjs.isVectorFrame.call(void 0, n2) ? { frameRect: n2.frame } : {},
15089
15107
  ...n2.resizing ? { resizing: n2.resizing } : {},
@@ -15159,7 +15177,7 @@ function createVectorCommands(controller, options = {}) {
15159
15177
  enabled: enabledFor,
15160
15178
  run: (_ctx, params) => {
15161
15179
  const targets = ids(params);
15162
- check2(controller.addPaintLayer(kind, layerPatchOf(_nullishCoalesce(params, () => ( {})), keys), { ids: targets, index: _optionalChain([params, 'optionalAccess', _634 => _634.index]) }));
15180
+ check2(controller.addPaintLayer(kind, layerPatchOf(_nullishCoalesce(params, () => ( {})), keys), { ids: targets, index: _optionalChain([params, 'optionalAccess', _641 => _641.index]) }));
15163
15181
  return { nodes: pathsUnder(targets).map((id) => stackResult(id, kind)) };
15164
15182
  }
15165
15183
  },
@@ -15232,17 +15250,17 @@ function createVectorCommands(controller, options = {}) {
15232
15250
  const allowed = _chunkBRKVNXDZcjs.vectorFilterParamKeys.call(void 0, type);
15233
15251
  for (const key of Object.keys(_nullishCoalesce(params, () => ( {})))) if (!allowed.includes(key)) fail(`${type} has no parameter "${key}"; it takes ${allowed.join(", ")}.`);
15234
15252
  };
15235
- const filtersResult = (id) => ({ id, filters: _nullishCoalesce(_optionalChain([controller, 'access', _635 => _635.getNode, 'call', _636 => _636(id), 'optionalAccess', _637 => _637.filters]), () => ( [])) });
15253
+ const filtersResult = (id) => ({ id, filters: _nullishCoalesce(_optionalChain([controller, 'access', _642 => _642.getNode, 'call', _643 => _643(id), 'optionalAccess', _644 => _644.filters]), () => ( [])) });
15236
15254
  const filterOf = (nodeId, filterId) => {
15237
15255
  const node = _nullishCoalesce(controller.getNode(nodeId), () => ( fail(`There is no node "${nodeId}".`)));
15238
- return _nullishCoalesce(_optionalChain([node, 'access', _638 => _638.filters, 'optionalAccess', _639 => _639.find, 'call', _640 => _640((f) => f.id === filterId)]), () => ( fail(`Node "${nodeId}" has no filter "${filterId}"; it has ${(_nullishCoalesce(node.filters, () => ( []))).map((f) => `"${f.id}" (${f.type})`).join(", ") || "none"}.`)));
15256
+ return _nullishCoalesce(_optionalChain([node, 'access', _645 => _645.filters, 'optionalAccess', _646 => _646.find, 'call', _647 => _647((f) => f.id === filterId)]), () => ( fail(`Node "${nodeId}" has no filter "${filterId}"; it has ${(_nullishCoalesce(node.filters, () => ( []))).map((f) => `"${f.id}" (${f.type})`).join(", ") || "none"}.`)));
15239
15257
  };
15240
15258
  const maskResult = (id) => ({ id, mask: _nullishCoalesce(_chunkBRKVNXDZcjs.vectorMaskSummary.call(void 0, controller.getNode(id)), () => ( fail(`"${id}" is not a mask group.`))) });
15241
15259
  const maskInputs = (params) => {
15242
15260
  const list2 = [...new Set(ids(params))];
15243
15261
  if (list2.length < 2) fail(`Masking needs at least two objects (the mask and what it masks); got ${list2.length}. Pass ids, or select more.`);
15244
15262
  for (const id of list2) if (controller.getNode(id).locked) fail(`"${id}" is locked; ask the user to unlock it, or leave it out of ids.`);
15245
- if (_optionalChain([params, 'optionalAccess', _641 => _641.maskId]) !== void 0 && !list2.includes(params.maskId)) fail(`maskId "${params.maskId}" must be one of ids (${list2.map((id) => `"${id}"`).join(", ")}).`);
15263
+ if (_optionalChain([params, 'optionalAccess', _648 => _648.maskId]) !== void 0 && !list2.includes(params.maskId)) fail(`maskId "${params.maskId}" must be one of ids (${list2.map((id) => `"${id}"`).join(", ")}).`);
15246
15264
  return list2;
15247
15265
  };
15248
15266
  const maskTargets = (params) => {
@@ -15269,7 +15287,7 @@ function createVectorCommands(controller, options = {}) {
15269
15287
  enabled: enabledFor,
15270
15288
  run: (_ctx, params) => {
15271
15289
  const list2 = maskInputs(params);
15272
- const r = controller.makeMask("clip", { ids: list2, ..._optionalChain([params, 'optionalAccess', _642 => _642.maskId]) ? { maskId: params.maskId } : {}, invert: _optionalChain([params, 'optionalAccess', _643 => _643.invert]) });
15290
+ const r = controller.makeMask("clip", { ids: list2, ..._optionalChain([params, 'optionalAccess', _649 => _649.maskId]) ? { maskId: params.maskId } : {}, invert: _optionalChain([params, 'optionalAccess', _650 => _650.invert]) });
15273
15291
  if (!r.ok) fail(r.message);
15274
15292
  return maskResult(r.id);
15275
15293
  }
@@ -15289,7 +15307,7 @@ function createVectorCommands(controller, options = {}) {
15289
15307
  enabled: enabledFor,
15290
15308
  run: (_ctx, params) => {
15291
15309
  const list2 = maskInputs(params);
15292
- const r = controller.makeMask(_nullishCoalesce(_optionalChain([params, 'optionalAccess', _644 => _644.type]), () => ( "luminance")), { ids: list2, ..._optionalChain([params, 'optionalAccess', _645 => _645.maskId]) ? { maskId: params.maskId } : {}, invert: _optionalChain([params, 'optionalAccess', _646 => _646.invert]) });
15310
+ const r = controller.makeMask(_nullishCoalesce(_optionalChain([params, 'optionalAccess', _651 => _651.type]), () => ( "luminance")), { ids: list2, ..._optionalChain([params, 'optionalAccess', _652 => _652.maskId]) ? { maskId: params.maskId } : {}, invert: _optionalChain([params, 'optionalAccess', _653 => _653.invert]) });
15293
15311
  if (!r.ok) fail(r.message);
15294
15312
  return maskResult(r.id);
15295
15313
  }
@@ -15313,9 +15331,9 @@ function createVectorCommands(controller, options = {}) {
15313
15331
  undoable: true,
15314
15332
  enabled: enabledFor,
15315
15333
  run: (_ctx, params) => {
15316
- if (_optionalChain([params, 'optionalAccess', _647 => _647.type]) === void 0 && _optionalChain([params, 'optionalAccess', _648 => _648.invert]) === void 0 && _optionalChain([params, 'optionalAccess', _649 => _649.enabled]) === void 0) fail("Pass at least one of type, invert, enabled.");
15334
+ if (_optionalChain([params, 'optionalAccess', _654 => _654.type]) === void 0 && _optionalChain([params, 'optionalAccess', _655 => _655.invert]) === void 0 && _optionalChain([params, 'optionalAccess', _656 => _656.enabled]) === void 0) fail("Pass at least one of type, invert, enabled.");
15317
15335
  const groups = maskTargets(params);
15318
- const patch = { ..._optionalChain([params, 'optionalAccess', _650 => _650.type]) ? { type: params.type } : {}, ..._optionalChain([params, 'optionalAccess', _651 => _651.invert]) !== void 0 ? { invert: params.invert } : {}, ..._optionalChain([params, 'optionalAccess', _652 => _652.enabled]) !== void 0 ? { enabled: params.enabled } : {} };
15336
+ const patch = { ..._optionalChain([params, 'optionalAccess', _657 => _657.type]) ? { type: params.type } : {}, ..._optionalChain([params, 'optionalAccess', _658 => _658.invert]) !== void 0 ? { invert: params.invert } : {}, ..._optionalChain([params, 'optionalAccess', _659 => _659.enabled]) !== void 0 ? { enabled: params.enabled } : {} };
15319
15337
  check2(controller.setMaskOptions(patch, { ids: groups }));
15320
15338
  return { groups: groups.map(maskResult) };
15321
15339
  }
@@ -15366,7 +15384,7 @@ function createVectorCommands(controller, options = {}) {
15366
15384
  run: (_ctx, params) => {
15367
15385
  const targets = ids(params);
15368
15386
  check2(controller.setBlendMode(params.blendMode, { ids: targets }));
15369
- return { nodes: targets.map((id) => ({ id, blendMode: _nullishCoalesce(_optionalChain([controller, 'access', _653 => _653.getNode, 'call', _654 => _654(id), 'optionalAccess', _655 => _655.blendMode]), () => ( "normal")) })) };
15387
+ return { nodes: targets.map((id) => ({ id, blendMode: _nullishCoalesce(_optionalChain([controller, 'access', _660 => _660.getNode, 'call', _661 => _661(id), 'optionalAccess', _662 => _662.blendMode]), () => ( "normal")) })) };
15370
15388
  }
15371
15389
  },
15372
15390
  {
@@ -15800,7 +15818,7 @@ function createVectorCommands(controller, options = {}) {
15800
15818
  keywords: ["symbol", "symbols", "library", "component", "reuse", "instance"],
15801
15819
  description: "Lists the document's symbols: id, name, the art's nodes (ids, types, names; use them for hidden overrides), its bounds in symbol space (around the registration point at 0, 0) and the ids of its instances. Also says which symbol is being edited in isolation, if any.",
15802
15820
  params: { type: "object", properties: {}, additionalProperties: false },
15803
- run: () => ({ symbols: controller.getSymbols().map((x) => symbolSummary(x.id)), editing: _nullishCoalesce(_optionalChain([controller, 'access', _656 => _656.getState, 'call', _657 => _657(), 'access', _658 => _658.symbolEdit, 'optionalAccess', _659 => _659.symbolId]), () => ( null)) })
15821
+ run: () => ({ symbols: controller.getSymbols().map((x) => symbolSummary(x.id)), editing: _nullishCoalesce(_optionalChain([controller, 'access', _663 => _663.getState, 'call', _664 => _664(), 'access', _665 => _665.symbolEdit, 'optionalAccess', _666 => _666.symbolId]), () => ( null)) })
15804
15822
  },
15805
15823
  {
15806
15824
  ...base,
@@ -15813,7 +15831,7 @@ function createVectorCommands(controller, options = {}) {
15813
15831
  undoable: true,
15814
15832
  enabled: enabledFor,
15815
15833
  run: (_ctx, params) => {
15816
- const r = controller.makeSymbol({ ids: ids(params), ..._optionalChain([params, 'optionalAccess', _660 => _660.name]) ? { name: params.name } : {} });
15834
+ const r = controller.makeSymbol({ ids: ids(params), ..._optionalChain([params, 'optionalAccess', _667 => _667.name]) ? { name: params.name } : {} });
15817
15835
  check2(r);
15818
15836
  return { symbolId: r.symbolId, instanceId: r.instanceId, symbol: symbolSummary(r.symbolId) };
15819
15837
  }
@@ -15870,10 +15888,10 @@ function createVectorCommands(controller, options = {}) {
15870
15888
  enabled: enabledFor,
15871
15889
  run: (_ctx, params) => {
15872
15890
  const patch = {
15873
- ..._optionalChain([params, 'optionalAccess', _661 => _661.scaleStrokes]) !== void 0 ? { scaleStrokes: params.scaleStrokes } : {},
15874
- ..._optionalChain([params, 'optionalAccess', _662 => _662.fill]) !== void 0 ? { fill: params.fill === null ? null : checkPaint(params.fill, "fill") } : {},
15875
- ..._optionalChain([params, 'optionalAccess', _663 => _663.stroke]) !== void 0 ? { stroke: params.stroke === null ? null : checkPaint(params.stroke, "stroke") } : {},
15876
- ..._optionalChain([params, 'optionalAccess', _664 => _664.hidden]) !== void 0 ? { hidden: params.hidden } : {}
15891
+ ..._optionalChain([params, 'optionalAccess', _668 => _668.scaleStrokes]) !== void 0 ? { scaleStrokes: params.scaleStrokes } : {},
15892
+ ..._optionalChain([params, 'optionalAccess', _669 => _669.fill]) !== void 0 ? { fill: params.fill === null ? null : checkPaint(params.fill, "fill") } : {},
15893
+ ..._optionalChain([params, 'optionalAccess', _670 => _670.stroke]) !== void 0 ? { stroke: params.stroke === null ? null : checkPaint(params.stroke, "stroke") } : {},
15894
+ ..._optionalChain([params, 'optionalAccess', _671 => _671.hidden]) !== void 0 ? { hidden: params.hidden } : {}
15877
15895
  };
15878
15896
  if (!Object.keys(patch).length) fail("Pass at least one of scaleStrokes, fill, stroke, hidden.");
15879
15897
  const targetIds = ids(params);
@@ -15958,7 +15976,7 @@ function createVectorCommands(controller, options = {}) {
15958
15976
  params: { type: "object", properties: {}, additionalProperties: false },
15959
15977
  enabled: () => controller.getState().symbolEdit ? true : "No symbol is being edited.",
15960
15978
  run: () => {
15961
- const id = _nullishCoalesce(_optionalChain([controller, 'access', _665 => _665.getState, 'call', _666 => _666(), 'access', _667 => _667.symbolEdit, 'optionalAccess', _668 => _668.symbolId]), () => ( null));
15979
+ const id = _nullishCoalesce(_optionalChain([controller, 'access', _672 => _672.getState, 'call', _673 => _673(), 'access', _674 => _674.symbolEdit, 'optionalAccess', _675 => _675.symbolId]), () => ( null));
15962
15980
  controller.exitSymbolEdit();
15963
15981
  return { symbolId: id };
15964
15982
  }
@@ -16007,7 +16025,7 @@ function createVectorCommands(controller, options = {}) {
16007
16025
  };
16008
16026
  const symmetryResult = (id) => {
16009
16027
  const n2 = controller.getNode(id);
16010
- return _optionalChain([n2, 'optionalAccess', _669 => _669.type]) === "group" && n2.symmetry ? { id, symmetry: n2.symmetry, children: n2.children.map((c) => c.id) } : fail(`"${id}" is not a symmetry group.`);
16028
+ return _optionalChain([n2, 'optionalAccess', _676 => _676.type]) === "group" && n2.symmetry ? { id, symmetry: n2.symmetry, children: n2.children.map((c) => c.id) } : fail(`"${id}" is not a symmetry group.`);
16011
16029
  };
16012
16030
  const symmetryCommands = () => [
16013
16031
  {
@@ -16037,8 +16055,8 @@ function createVectorCommands(controller, options = {}) {
16037
16055
  const { ids: list2, ...patch } = _nullishCoalesce(params, () => ( {}));
16038
16056
  if (!Object.keys(patch).length) fail("Pass at least one of mode, center, rotation, copies, mirror.");
16039
16057
  check2(controller.setSymmetry(patch, list2 ? { ids: list2 } : {}));
16040
- const ids2 = _nullishCoalesce(list2, () => ( controller.getState().selection.filter((id) => _optionalChain([controller, 'access', _670 => _670.getNode, 'call', _671 => _671(id), 'optionalAccess', _672 => _672.type]) === "group")));
16041
- return { groups: ids2.filter((id) => _optionalChain([controller, 'access', _673 => _673.getNode, 'call', _674 => _674(id), 'optionalAccess', _675 => _675.symmetry])).map(symmetryResult) };
16058
+ const ids2 = _nullishCoalesce(list2, () => ( controller.getState().selection.filter((id) => _optionalChain([controller, 'access', _677 => _677.getNode, 'call', _678 => _678(id), 'optionalAccess', _679 => _679.type]) === "group")));
16059
+ return { groups: ids2.filter((id) => _optionalChain([controller, 'access', _680 => _680.getNode, 'call', _681 => _681(id), 'optionalAccess', _682 => _682.symmetry])).map(symmetryResult) };
16042
16060
  }
16043
16061
  },
16044
16062
  {
@@ -16051,7 +16069,7 @@ function createVectorCommands(controller, options = {}) {
16051
16069
  undoable: true,
16052
16070
  enabled: enabledFor,
16053
16071
  run: (_ctx, params) => {
16054
- const r = controller.releaseSymmetry({ ..._optionalChain([params, 'optionalAccess', _676 => _676.ids]) ? { ids: params.ids } : {}, ..._optionalChain([params, 'optionalAccess', _677 => _677.expand]) ? { expand: true } : {} });
16072
+ const r = controller.releaseSymmetry({ ..._optionalChain([params, 'optionalAccess', _683 => _683.ids]) ? { ids: params.ids } : {}, ..._optionalChain([params, 'optionalAccess', _684 => _684.expand]) ? { expand: true } : {} });
16055
16073
  check2(r);
16056
16074
  return { ids: _nullishCoalesce(r.ids, () => ( [])) };
16057
16075
  }
@@ -16119,7 +16137,7 @@ function createVectorCommands(controller, options = {}) {
16119
16137
  undoable: true,
16120
16138
  enabled: enabledFor,
16121
16139
  run: (_ctx, params) => {
16122
- const r = controller.setLens(null, _optionalChain([params, 'optionalAccess', _678 => _678.ids]) ? { ids: params.ids } : {});
16140
+ const r = controller.setLens(null, _optionalChain([params, 'optionalAccess', _685 => _685.ids]) ? { ids: params.ids } : {});
16123
16141
  check2(r);
16124
16142
  return { ids: (_nullishCoalesce(r.lenses, () => ( []))).map((l) => l.id) };
16125
16143
  }
@@ -16300,7 +16318,7 @@ function createVectorCommands(controller, options = {}) {
16300
16318
  const paths = [];
16301
16319
  for (const id of targets) {
16302
16320
  const n2 = controller.getNode(id);
16303
- if (_optionalChain([n2, 'optionalAccess', _679 => _679.type]) === "path") paths.push(stackResult(id, "stroke"));
16321
+ if (_optionalChain([n2, 'optionalAccess', _686 => _686.type]) === "path") paths.push(stackResult(id, "stroke"));
16304
16322
  }
16305
16323
  return { paths };
16306
16324
  }
@@ -16380,7 +16398,7 @@ function createVectorCommands(controller, options = {}) {
16380
16398
  additionalProperties: false
16381
16399
  },
16382
16400
  run: (_ctx, params) => {
16383
- if (_optionalChain([params, 'optionalAccess', _680 => _680.ids])) {
16401
+ if (_optionalChain([params, 'optionalAccess', _687 => _687.ids])) {
16384
16402
  for (const id of params.ids) if (!controller.getNode(id)) fail(`There is no node "${id}".`);
16385
16403
  }
16386
16404
  return controller.toLottie(_nullishCoalesce(params, () => ( {})));
@@ -16743,7 +16761,7 @@ function createVectorCommands(controller, options = {}) {
16743
16761
  run: (_ctx, params) => {
16744
16762
  const { polarIncrement, additionalAngles, ...rest } = _nullishCoalesce(params, () => ( {}));
16745
16763
  if (!Object.keys(_nullishCoalesce(params, () => ( {}))).length) fail("Pass at least one option.");
16746
- if (_optionalChain([rest, 'access', _681 => _681.angles, 'optionalAccess', _682 => _682.some, 'call', _683 => _683((a) => !Number.isFinite(a))])) fail("angles must be numbers (degrees).");
16764
+ if (_optionalChain([rest, 'access', _688 => _688.angles, 'optionalAccess', _689 => _689.some, 'call', _690 => _690((a) => !Number.isFinite(a))])) fail("angles must be numbers (degrees).");
16747
16765
  if (additionalAngles && polarIncrement === void 0) fail("additionalAngles go with polarIncrement.");
16748
16766
  const angles = _nullishCoalesce(rest.angles, () => ( (polarIncrement !== void 0 ? vectorPolarAngles(polarIncrement, additionalAngles) : void 0)));
16749
16767
  controller.setSnap({ ...rest, ...angles ? { angles } : {} });
@@ -17097,8 +17115,8 @@ function createVectorCommands(controller, options = {}) {
17097
17115
  enabled: enabledFor,
17098
17116
  run: (_ctx, params) => {
17099
17117
  const list2 = ids(params);
17100
- check2(controller.setResizing({ ..._optionalChain([params, 'optionalAccess', _684 => _684.horizontal]) ? { horizontal: params.horizontal } : {}, ..._optionalChain([params, 'optionalAccess', _685 => _685.vertical]) ? { vertical: params.vertical } : {} }, { ids: list2 }));
17101
- return { nodes: list2.map((id) => ({ id, horizontal: _nullishCoalesce(_optionalChain([controller, 'access', _686 => _686.getNode, 'call', _687 => _687(id), 'optionalAccess', _688 => _688.resizing, 'optionalAccess', _689 => _689.horizontal]), () => ( "left")), vertical: _nullishCoalesce(_optionalChain([controller, 'access', _690 => _690.getNode, 'call', _691 => _691(id), 'optionalAccess', _692 => _692.resizing, 'optionalAccess', _693 => _693.vertical]), () => ( "top")) })) };
17118
+ check2(controller.setResizing({ ..._optionalChain([params, 'optionalAccess', _691 => _691.horizontal]) ? { horizontal: params.horizontal } : {}, ..._optionalChain([params, 'optionalAccess', _692 => _692.vertical]) ? { vertical: params.vertical } : {} }, { ids: list2 }));
17119
+ return { nodes: list2.map((id) => ({ id, horizontal: _nullishCoalesce(_optionalChain([controller, 'access', _693 => _693.getNode, 'call', _694 => _694(id), 'optionalAccess', _695 => _695.resizing, 'optionalAccess', _696 => _696.horizontal]), () => ( "left")), vertical: _nullishCoalesce(_optionalChain([controller, 'access', _697 => _697.getNode, 'call', _698 => _698(id), 'optionalAccess', _699 => _699.resizing, 'optionalAccess', _700 => _700.vertical]), () => ( "top")) })) };
17102
17120
  }
17103
17121
  },
17104
17122
  {
@@ -17284,7 +17302,7 @@ function createVectorCommands(controller, options = {}) {
17284
17302
  run: (_ctx, params) => {
17285
17303
  const id = controller.addPath(params.d, { ...pickStyle(params), ...params.name ? { name: params.name } : {} }, parentOf(params.parentId));
17286
17304
  const node = controller.getNode(id);
17287
- if (_optionalChain([node, 'optionalAccess', _694 => _694.type]) === "path" && !node.subpaths.length) {
17305
+ if (_optionalChain([node, 'optionalAccess', _701 => _701.type]) === "path" && !node.subpaths.length) {
17288
17306
  controller.undo();
17289
17307
  fail("The path data has no points.");
17290
17308
  }
@@ -17323,7 +17341,7 @@ function createVectorCommands(controller, options = {}) {
17323
17341
  check2(controller.setGradient(patch, { ids: ids(params), target: _nullishCoalesce(target, () => ( "fill")) }));
17324
17342
  const id = ids(params)[0];
17325
17343
  const node = id ? controller.getNode(id) : void 0;
17326
- const path = _optionalChain([node, 'optionalAccess', _695 => _695.type]) === "path" ? node : void 0;
17344
+ const path = _optionalChain([node, 'optionalAccess', _702 => _702.type]) === "path" ? node : void 0;
17327
17345
  return { ok: true, ...path ? { gradient: path[_nullishCoalesce(target, () => ( "fill"))] } : {} };
17328
17346
  }
17329
17347
  },
@@ -17363,12 +17381,12 @@ function createVectorCommands(controller, options = {}) {
17363
17381
  },
17364
17382
  undoable: true,
17365
17383
  run: (_ctx, params) => {
17366
- const refs = _optionalChain([params, 'optionalAccess', _696 => _696.anchors]) ? anchorsOf(params.anchors) : void 0;
17367
- const target = { refs, ids: _optionalChain([params, 'optionalAccess', _697 => _697.ids]) ? ids(params) : void 0 };
17368
- if (_optionalChain([params, 'optionalAccess', _698 => _698.radius]) !== void 0) check2(controller.setCornerRadius(params.radius, { ...target, kind: params.kind, ...params.smoothing !== void 0 ? { smoothing: params.smoothing } : {} }));
17369
- else if (_optionalChain([params, 'optionalAccess', _699 => _699.kind])) check2(controller.setCornerKind(params.kind, target));
17370
- if (_optionalChain([params, 'optionalAccess', _700 => _700.radius]) === void 0 && _optionalChain([params, 'optionalAccess', _701 => _701.smoothing]) !== void 0) check2(controller.setCornerSmoothing(params.smoothing, target));
17371
- if (_optionalChain([params, 'optionalAccess', _702 => _702.radius]) === void 0 && !_optionalChain([params, 'optionalAccess', _703 => _703.kind]) && _optionalChain([params, 'optionalAccess', _704 => _704.smoothing]) === void 0) fail("Pass `radius`, `kind` and / or `smoothing`.");
17384
+ const refs = _optionalChain([params, 'optionalAccess', _703 => _703.anchors]) ? anchorsOf(params.anchors) : void 0;
17385
+ const target = { refs, ids: _optionalChain([params, 'optionalAccess', _704 => _704.ids]) ? ids(params) : void 0 };
17386
+ if (_optionalChain([params, 'optionalAccess', _705 => _705.radius]) !== void 0) check2(controller.setCornerRadius(params.radius, { ...target, kind: params.kind, ...params.smoothing !== void 0 ? { smoothing: params.smoothing } : {} }));
17387
+ else if (_optionalChain([params, 'optionalAccess', _706 => _706.kind])) check2(controller.setCornerKind(params.kind, target));
17388
+ if (_optionalChain([params, 'optionalAccess', _707 => _707.radius]) === void 0 && _optionalChain([params, 'optionalAccess', _708 => _708.smoothing]) !== void 0) check2(controller.setCornerSmoothing(params.smoothing, target));
17389
+ if (_optionalChain([params, 'optionalAccess', _709 => _709.radius]) === void 0 && !_optionalChain([params, 'optionalAccess', _710 => _710.kind]) && _optionalChain([params, 'optionalAccess', _711 => _711.smoothing]) === void 0) fail("Pass `radius`, `kind` and / or `smoothing`.");
17372
17390
  return { ok: true };
17373
17391
  }
17374
17392
  },
@@ -17402,12 +17420,12 @@ function createVectorCommands(controller, options = {}) {
17402
17420
  undoable: true,
17403
17421
  run: (_ctx, params) => {
17404
17422
  const target = { ids: ids(params) };
17405
- if (_optionalChain([params, 'optionalAccess', _705 => _705.preset])) check2(controller.setWidthProfile(params.preset, target));
17406
- else if (_optionalChain([params, 'optionalAccess', _706 => _706.points]) !== void 0) check2(controller.setWidthProfile(_nullishCoalesce(params.points, () => ( null)), target));
17407
- else if (_optionalChain([params, 'optionalAccess', _707 => _707.taper]) || _optionalChain([params, 'optionalAccess', _708 => _708.wave])) check2(controller.setWidthProfile({ taper: params.taper, wave: params.wave }, target));
17423
+ if (_optionalChain([params, 'optionalAccess', _712 => _712.preset])) check2(controller.setWidthProfile(params.preset, target));
17424
+ else if (_optionalChain([params, 'optionalAccess', _713 => _713.points]) !== void 0) check2(controller.setWidthProfile(_nullishCoalesce(params.points, () => ( null)), target));
17425
+ else if (_optionalChain([params, 'optionalAccess', _714 => _714.taper]) || _optionalChain([params, 'optionalAccess', _715 => _715.wave])) check2(controller.setWidthProfile({ taper: params.taper, wave: params.wave }, target));
17408
17426
  else fail("Pass `preset`, `points`, `taper` or `wave`.");
17409
17427
  const node = controller.getNode(target.ids[0]);
17410
- return { ok: true, points: _optionalChain([node, 'optionalAccess', _709 => _709.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
17428
+ return { ok: true, points: _optionalChain([node, 'optionalAccess', _716 => _716.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
17411
17429
  }
17412
17430
  },
17413
17431
  {
@@ -17429,10 +17447,10 @@ function createVectorCommands(controller, options = {}) {
17429
17447
  },
17430
17448
  undoable: true,
17431
17449
  run: (_ctx, params) => {
17432
- if (!_optionalChain([params, 'optionalAccess', _710 => _710.id])) fail("Pass the path `id`.");
17450
+ if (!_optionalChain([params, 'optionalAccess', _717 => _717.id])) fail("Pass the path `id`.");
17433
17451
  check2(controller.setWidthPoint({ nodeId: params.id, index: _nullishCoalesce(params.index, () => ( null)) }, { t: params.t, left: params.left, right: params.right }));
17434
17452
  const node = controller.getNode(params.id);
17435
- return { ok: true, points: _optionalChain([node, 'optionalAccess', _711 => _711.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
17453
+ return { ok: true, points: _optionalChain([node, 'optionalAccess', _718 => _718.type]) === "path" ? _nullishCoalesce(node.strokeWidthProfile, () => ( [])) : [] };
17436
17454
  }
17437
17455
  },
17438
17456
  {
@@ -17445,7 +17463,7 @@ function createVectorCommands(controller, options = {}) {
17445
17463
  enabled: enabledFor,
17446
17464
  undoable: true,
17447
17465
  run: (_ctx, params) => {
17448
- const created = controller.outlineStroke({ ids: _optionalChain([params, 'optionalAccess', _712 => _712.ids]) ? ids(params) : void 0 });
17466
+ const created = controller.outlineStroke({ ids: _optionalChain([params, 'optionalAccess', _719 => _719.ids]) ? ids(params) : void 0 });
17449
17467
  if (!created.length) fail("No selected path has a stroke.");
17450
17468
  return { ids: created };
17451
17469
  }
@@ -17530,7 +17548,7 @@ function createVectorCommands(controller, options = {}) {
17530
17548
  if (params.release) return { released: target, shapes: controller.releaseEnvelope({ ids: target }) };
17531
17549
  if (params.expand) return { expanded: controller.expandAppearance({ ids: target }) };
17532
17550
  if (params.topObject) {
17533
- const r = controller.makeEnvelopeWithTopObject({ ids: target, rows: _optionalChain([params, 'access', _713 => _713.mesh, 'optionalAccess', _714 => _714.rows]), columns: _optionalChain([params, 'access', _715 => _715.mesh, 'optionalAccess', _716 => _716.columns]) });
17551
+ const r = controller.makeEnvelopeWithTopObject({ ids: target, rows: _optionalChain([params, 'access', _720 => _720.mesh, 'optionalAccess', _721 => _721.rows]), columns: _optionalChain([params, 'access', _722 => _722.mesh, 'optionalAccess', _723 => _723.columns]) });
17534
17552
  check2(r);
17535
17553
  return { nodeId: r.nodeId };
17536
17554
  }
@@ -17670,7 +17688,7 @@ function createVectorCommands(controller, options = {}) {
17670
17688
  run: (_ctx, params) => {
17671
17689
  if (params.params !== void 0 || params.enabled !== void 0) check2(controller.updateEffect(params.nodeId, params.effectId, { params: params.params, enabled: params.enabled }));
17672
17690
  if (params.index !== void 0) check2(controller.moveEffect(params.nodeId, params.effectId, params.index));
17673
- return { effects: _nullishCoalesce(_optionalChain([controller, 'access', _717 => _717.getNode, 'call', _718 => _718(params.nodeId), 'optionalAccess', _719 => _719.effects]), () => ( [])) };
17691
+ return { effects: _nullishCoalesce(_optionalChain([controller, 'access', _724 => _724.getNode, 'call', _725 => _725(params.nodeId), 'optionalAccess', _726 => _726.effects]), () => ( [])) };
17674
17692
  }
17675
17693
  },
17676
17694
  {
@@ -17734,7 +17752,7 @@ function createVectorCommands(controller, options = {}) {
17734
17752
  undoable: true,
17735
17753
  run: (_ctx, params) => {
17736
17754
  checkBlendOptions(params);
17737
- const r = controller.setBlendOptions(_nullishCoalesce(params, () => ( {})), { ids: _optionalChain([params, 'optionalAccess', _720 => _720.ids]) });
17755
+ const r = controller.setBlendOptions(_nullishCoalesce(params, () => ( {})), { ids: _optionalChain([params, 'optionalAccess', _727 => _727.ids]) });
17738
17756
  if (!r.ok) fail(r.message);
17739
17757
  return { ok: true };
17740
17758
  }
@@ -17748,7 +17766,7 @@ function createVectorCommands(controller, options = {}) {
17748
17766
  params: { type: "object", properties: { ids: IDS } },
17749
17767
  undoable: true,
17750
17768
  run: (_ctx, params) => {
17751
- const groups = controller.expandBlend({ ids: _optionalChain([params, 'optionalAccess', _721 => _721.ids]) });
17769
+ const groups = controller.expandBlend({ ids: _optionalChain([params, 'optionalAccess', _728 => _728.ids]) });
17752
17770
  if (!groups.length) fail("Select a blend to expand.");
17753
17771
  return { ids: groups };
17754
17772
  }
@@ -17762,7 +17780,7 @@ function createVectorCommands(controller, options = {}) {
17762
17780
  params: { type: "object", properties: { ids: IDS } },
17763
17781
  undoable: true,
17764
17782
  run: (_ctx, params) => {
17765
- const released = controller.releaseBlend({ ids: _optionalChain([params, 'optionalAccess', _722 => _722.ids]) });
17783
+ const released = controller.releaseBlend({ ids: _optionalChain([params, 'optionalAccess', _729 => _729.ids]) });
17766
17784
  if (!released.length) fail("Select a blend to release.");
17767
17785
  return { ids: released };
17768
17786
  }
@@ -17776,7 +17794,7 @@ function createVectorCommands(controller, options = {}) {
17776
17794
  params: { type: "object", properties: { ids: IDS } },
17777
17795
  undoable: true,
17778
17796
  run: (_ctx, params) => {
17779
- const r = controller.replaceBlendSpine({ ids: _optionalChain([params, 'optionalAccess', _723 => _723.ids]) });
17797
+ const r = controller.replaceBlendSpine({ ids: _optionalChain([params, 'optionalAccess', _730 => _730.ids]) });
17780
17798
  if (!r.ok) fail(r.message);
17781
17799
  return { ok: true };
17782
17800
  }
@@ -17880,6 +17898,27 @@ function createVectorCommands(controller, options = {}) {
17880
17898
  return { ok: true };
17881
17899
  }
17882
17900
  },
17901
+ {
17902
+ ...base,
17903
+ id: `${prefix}moveLayer`,
17904
+ label: "Move Layer\u2026",
17905
+ keywords: ["reorder", "layer", "order", "into group", "out of group", "reparent", "nest", "z-index"],
17906
+ description: "Moves one node to a position among its siblings (0 the bottom; default the top), as dragging it in the layers panel does. With `parentId` it moves into that group, or with null to the top level; it stays where it is on the canvas.",
17907
+ params: {
17908
+ type: "object",
17909
+ properties: {
17910
+ id: { type: "string", description: "The node to move." },
17911
+ index: { type: "integer", minimum: 0, description: "Position among its new siblings, bottom to top (default: the top)." },
17912
+ parentId: { type: ["string", "null"], description: "The group to move into, or null for the top level (default: its current parent)." }
17913
+ },
17914
+ required: ["id"]
17915
+ },
17916
+ undoable: true,
17917
+ run: (_ctx, params) => {
17918
+ check2(controller.moveNode(params.id, { index: params.index, parentId: params.parentId }));
17919
+ return { ok: true };
17920
+ }
17921
+ },
17883
17922
  {
17884
17923
  ...base,
17885
17924
  id: `${prefix}group`,
@@ -17890,7 +17929,7 @@ function createVectorCommands(controller, options = {}) {
17890
17929
  enabled: enabledFor,
17891
17930
  undoable: true,
17892
17931
  run: (_ctx, params) => {
17893
- const id = controller.group({ ids: ids(params), name: _optionalChain([params, 'optionalAccess', _724 => _724.name]) });
17932
+ const id = controller.group({ ids: ids(params), name: _optionalChain([params, 'optionalAccess', _731 => _731.name]) });
17894
17933
  if (!id) fail("Only nodes that share a parent can be grouped.");
17895
17934
  return { id };
17896
17935
  }
@@ -17918,7 +17957,7 @@ function createVectorCommands(controller, options = {}) {
17918
17957
  params: { type: "object", properties: { anchors: ANCHORS, keepShape: { type: "boolean" } } },
17919
17958
  undoable: true,
17920
17959
  run: (_ctx, params) => {
17921
- check2(controller.deleteAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _725 => _725.anchors])), { keepShape: _optionalChain([params, 'optionalAccess', _726 => _726.keepShape]) }));
17960
+ check2(controller.deleteAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _732 => _732.anchors])), { keepShape: _optionalChain([params, 'optionalAccess', _733 => _733.keepShape]) }));
17922
17961
  return { ok: true };
17923
17962
  }
17924
17963
  },
@@ -17973,7 +18012,7 @@ function createVectorCommands(controller, options = {}) {
17973
18012
  params: { type: "object", properties: { ids: IDS, tolerance: { type: "number", minimum: 0 } } },
17974
18013
  undoable: true,
17975
18014
  run: (_ctx, params) => {
17976
- check2(controller.joinPaths({ ids: _optionalChain([params, 'optionalAccess', _727 => _727.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _728 => _728.tolerance]) }));
18015
+ check2(controller.joinPaths({ ids: _optionalChain([params, 'optionalAccess', _734 => _734.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _735 => _735.tolerance]) }));
17977
18016
  return { selection: controller.getState().selection };
17978
18017
  }
17979
18018
  },
@@ -17987,7 +18026,7 @@ function createVectorCommands(controller, options = {}) {
17987
18026
  params: { type: "object", properties: { axis: { type: "string", enum: ["horizontal", "vertical", "both"] }, anchors: ANCHORS } },
17988
18027
  undoable: true,
17989
18028
  run: (_ctx, params) => {
17990
- check2(controller.averageAnchors(_nullishCoalesce(_optionalChain([params, 'optionalAccess', _729 => _729.axis]), () => ( "both")), anchorsOf(_optionalChain([params, 'optionalAccess', _730 => _730.anchors]))));
18029
+ check2(controller.averageAnchors(_nullishCoalesce(_optionalChain([params, 'optionalAccess', _736 => _736.axis]), () => ( "both")), anchorsOf(_optionalChain([params, 'optionalAccess', _737 => _737.anchors]))));
17991
18030
  return { ok: true };
17992
18031
  }
17993
18032
  },
@@ -18001,7 +18040,7 @@ function createVectorCommands(controller, options = {}) {
18001
18040
  enabled: enabledFor,
18002
18041
  undoable: true,
18003
18042
  run: (_ctx, params) => {
18004
- check2(controller.removeRedundantPoints({ ids: _optionalChain([params, 'optionalAccess', _731 => _731.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _732 => _732.tolerance]) }));
18043
+ check2(controller.removeRedundantPoints({ ids: _optionalChain([params, 'optionalAccess', _738 => _738.ids]) ? ids(params) : void 0, tolerance: _optionalChain([params, 'optionalAccess', _739 => _739.tolerance]) }));
18005
18044
  return { ok: true };
18006
18045
  }
18007
18046
  },
@@ -18014,7 +18053,7 @@ function createVectorCommands(controller, options = {}) {
18014
18053
  params: { type: "object", properties: { ids: IDS, amount: { type: "number", minimum: 0, maximum: 1 }, anchors: ANCHORS } },
18015
18054
  undoable: true,
18016
18055
  run: (_ctx, params) => {
18017
- check2(controller.smoothPaths({ ids: _optionalChain([params, 'optionalAccess', _733 => _733.ids]) ? ids(params) : void 0, amount: _optionalChain([params, 'optionalAccess', _734 => _734.amount]), refs: _optionalChain([params, 'optionalAccess', _735 => _735.anchors]) }));
18056
+ check2(controller.smoothPaths({ ids: _optionalChain([params, 'optionalAccess', _740 => _740.ids]) ? ids(params) : void 0, amount: _optionalChain([params, 'optionalAccess', _741 => _741.amount]), refs: _optionalChain([params, 'optionalAccess', _742 => _742.anchors]) }));
18018
18057
  return { ok: true };
18019
18058
  }
18020
18059
  },
@@ -18027,14 +18066,14 @@ function createVectorCommands(controller, options = {}) {
18027
18066
  params: { type: "object", properties: { nodeId: { type: "string" }, x: { type: "number" }, y: { type: "number" }, anchors: ANCHORS } },
18028
18067
  undoable: true,
18029
18068
  run: (_ctx, params) => {
18030
- if (_optionalChain([params, 'optionalAccess', _736 => _736.nodeId]) !== void 0) {
18069
+ if (_optionalChain([params, 'optionalAccess', _743 => _743.nodeId]) !== void 0) {
18031
18070
  if (!controller.getNode(params.nodeId)) fail(`There is no node "${params.nodeId}".`);
18032
18071
  if (params.x === void 0 || params.y === void 0) fail("Pass x and y with nodeId.");
18033
18072
  const created = controller.cutPathAt(params.nodeId, { x: params.x, y: params.y });
18034
18073
  if (!created) fail("Nothing to cut there (the end of an open path, or a locked path).");
18035
18074
  return { ids: created };
18036
18075
  }
18037
- check2(controller.cutAtAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _737 => _737.anchors]))));
18076
+ check2(controller.cutAtAnchors(anchorsOf(_optionalChain([params, 'optionalAccess', _744 => _744.anchors]))));
18038
18077
  return { ids: controller.getState().selection };
18039
18078
  }
18040
18079
  },
@@ -18089,7 +18128,7 @@ function createVectorCommands(controller, options = {}) {
18089
18128
  },
18090
18129
  run: (_ctx, params) => {
18091
18130
  const patch = {};
18092
- for (const key of ["keepShapeOnDelete", "curvatureMoves", "pencilSmoothing", "recognizeShapes", "eraserSize", "pencilPressure", "distortMode", "distortSize", "distortStrength"]) if (_optionalChain([params, 'optionalAccess', _738 => _738[key]]) !== void 0) patch[key] = params[key];
18131
+ for (const key of ["keepShapeOnDelete", "curvatureMoves", "pencilSmoothing", "recognizeShapes", "eraserSize", "pencilPressure", "distortMode", "distortSize", "distortStrength"]) if (_optionalChain([params, 'optionalAccess', _745 => _745[key]]) !== void 0) patch[key] = params[key];
18093
18132
  controller.setEditing(patch);
18094
18133
  return { editing: controller.getState().editing };
18095
18134
  }
@@ -18114,7 +18153,7 @@ function createVectorCommands(controller, options = {}) {
18114
18153
  keywords: ["download", "save", "markup"],
18115
18154
  description: "Returns the document as SVG markup.",
18116
18155
  params: { type: "object", properties: { precision: { type: "integer", minimum: 0, maximum: 8 } } },
18117
- run: (_ctx, params) => ({ svg: controller.toSvg({ precision: _optionalChain([params, 'optionalAccess', _739 => _739.precision]) }) })
18156
+ run: (_ctx, params) => ({ svg: controller.toSvg({ precision: _optionalChain([params, 'optionalAccess', _746 => _746.precision]) }) })
18118
18157
  },
18119
18158
  {
18120
18159
  ...base,
@@ -18254,7 +18293,7 @@ function regenerateVectorArt(controller, input, options) {
18254
18293
  const { signal, ...args } = input;
18255
18294
  return once(controller, input.idempotencyKey, args, async () => {
18256
18295
  const node = controller.getNode(input.id);
18257
- const prov = _optionalChain([node, 'optionalAccess', _740 => _740.type]) === "group" ? node.generation : void 0;
18296
+ const prov = _optionalChain([node, 'optionalAccess', _747 => _747.type]) === "group" ? node.generation : void 0;
18258
18297
  if (!node || node.type !== "group" || !prov) return { ok: false, message: `"${input.id}" is not generated art (generate some with generate_vector_art).` };
18259
18298
  if (node.locked) return { ok: false, message: `"${input.id}" is locked; unlock it first.` };
18260
18299
  const models = listModels(options);
@@ -18373,7 +18412,7 @@ function getVectorTextPanel(state) {
18373
18412
  }
18374
18413
  const typing = state.tool === "type" || state.tool === "typePath";
18375
18414
  const one = state.selection.length === 1 ? _chunkBRKVNXDZcjs.findVectorNode.call(void 0, state.document.nodes, state.selection[0]) : void 0;
18376
- const pathId = _optionalChain([one, 'optionalAccess', _741 => _741.type]) === "path" ? one.id : null;
18415
+ const pathId = _optionalChain([one, 'optionalAccess', _748 => _748.type]) === "path" ? one.id : null;
18377
18416
  if (!nodes.length && !typing && !state.textEdit) return null;
18378
18417
  const styles = [];
18379
18418
  let target = "defaults";
@@ -18396,7 +18435,7 @@ function getVectorTextPanel(state) {
18396
18435
  return values.every((v) => v === values[0]) ? _nullishCoalesce(values[0], () => ( null)) : null;
18397
18436
  };
18398
18437
  const font = Object.fromEntries(FIELDS.map((k) => [k, same(k)]));
18399
- const alignSource = target === "defaults" ? [_nullishCoalesce(state.textDefaults.align, () => ( "left"))] : (target === "range" ? [edited] : nodes).map((n2) => _nullishCoalesce(_optionalChain([n2, 'access', _742 => _742.paragraph, 'optionalAccess', _743 => _743.align]), () => ( "left")));
18438
+ const alignSource = target === "defaults" ? [_nullishCoalesce(state.textDefaults.align, () => ( "left"))] : (target === "range" ? [edited] : nodes).map((n2) => _nullishCoalesce(_optionalChain([n2, 'access', _749 => _749.paragraph, 'optionalAccess', _750 => _750.align]), () => ( "left")));
18400
18439
  const align = alignSource.every((a) => a === alignSource[0]) ? alignSource[0] : null;
18401
18440
  const ids = target === "range" ? [edited.id] : nodes.map((n2) => n2.id);
18402
18441
  const frameNode = target === "range" ? edited : nodes.length === 1 ? nodes[0] : void 0;
@@ -18404,7 +18443,7 @@ function getVectorTextPanel(state) {
18404
18443
  const orientations = edits.map((n2) => _nullishCoalesce(n2.orientation, () => ( "horizontal")));
18405
18444
  const orientation = orientations.length && orientations.every((o) => o === orientations[0]) ? orientations[0] : null;
18406
18445
  const canOrient = edits.length > 0 && edits.every((n2) => n2.frame.kind !== "path");
18407
- return { target, ids, font, align, frame: _nullishCoalesce(_optionalChain([frameNode, 'optionalAccess', _744 => _744.frame, 'access', _745 => _745.kind]), () => ( null)), orientation, canOrient, families: _chunkBRKVNXDZcjs.vectorTextFamilies.call(void 0, ), outlines: _chunkBRKVNXDZcjs.vectorTextHasOutlines.call(void 0, ), pathId };
18446
+ return { target, ids, font, align, frame: _nullishCoalesce(_optionalChain([frameNode, 'optionalAccess', _751 => _751.frame, 'access', _752 => _752.kind]), () => ( null)), orientation, canOrient, families: _chunkBRKVNXDZcjs.vectorTextFamilies.call(void 0, ), outlines: _chunkBRKVNXDZcjs.vectorTextHasOutlines.call(void 0, ), pathId };
18408
18447
  }
18409
18448
  function applyVectorTextStyle(controller, patch, options = {}) {
18410
18449
  const state = controller.getState();
@@ -18439,7 +18478,7 @@ function applyVectorTextOrientation(controller, orientation) {
18439
18478
  // src/vector/symbolsPanel.ts
18440
18479
  var fmt3 = (n2) => Math.round(n2 * 100) / 100;
18441
18480
  function getVectorSymbolsPanel(state, options = {}) {
18442
- const host = _nullishCoalesce(_optionalChain([state, 'access', _746 => _746.symbolEdit, 'optionalAccess', _747 => _747.host]), () => ( state.document));
18481
+ const host = _nullishCoalesce(_optionalChain([state, 'access', _753 => _753.symbolEdit, 'optionalAccess', _754 => _754.host]), () => ( state.document));
18443
18482
  const counts = /* @__PURE__ */ new Map();
18444
18483
  const count = (list) => {
18445
18484
  for (const n2 of list) {
@@ -18460,15 +18499,15 @@ function getVectorSymbolsPanel(state, options = {}) {
18460
18499
  instances: _nullishCoalesce(counts.get(s.id), () => ( 0)),
18461
18500
  viewBox: `${fmt3(b.x - pad)} ${fmt3(b.y - pad)} ${fmt3(b.width + 2 * pad)} ${fmt3(b.height + 2 * pad)}`,
18462
18501
  scene,
18463
- editing: _optionalChain([state, 'access', _748 => _748.symbolEdit, 'optionalAccess', _749 => _749.symbolId]) === s.id
18502
+ editing: _optionalChain([state, 'access', _755 => _755.symbolEdit, 'optionalAccess', _756 => _756.symbolId]) === s.id
18464
18503
  };
18465
18504
  });
18466
18505
  const one = state.selection.length === 1 ? _chunkBRKVNXDZcjs.findVectorNode.call(void 0, state.document.nodes, state.selection[0]) : void 0;
18467
- const inst = _optionalChain([one, 'optionalAccess', _750 => _750.type]) === "instance" ? one : null;
18506
+ const inst = _optionalChain([one, 'optionalAccess', _757 => _757.type]) === "instance" ? one : null;
18468
18507
  return {
18469
18508
  symbols,
18470
18509
  canMake: state.selection.length > 0 && !(state.selection.length === 1 && inst),
18471
- instance: inst ? { id: inst.id, symbolId: inst.symbolId, scaleStrokes: inst.scaleStrokes !== false, fill: _nullishCoalesce(_optionalChain([inst, 'access', _751 => _751.overrides, 'optionalAccess', _752 => _752.fill]), () => ( null)), stroke: _nullishCoalesce(_optionalChain([inst, 'access', _753 => _753.overrides, 'optionalAccess', _754 => _754.stroke]), () => ( null)), hidden: _nullishCoalesce(_optionalChain([inst, 'access', _755 => _755.overrides, 'optionalAccess', _756 => _756.hidden, 'optionalAccess', _757 => _757.length]), () => ( 0)) } : null,
18510
+ instance: inst ? { id: inst.id, symbolId: inst.symbolId, scaleStrokes: inst.scaleStrokes !== false, fill: _nullishCoalesce(_optionalChain([inst, 'access', _758 => _758.overrides, 'optionalAccess', _759 => _759.fill]), () => ( null)), stroke: _nullishCoalesce(_optionalChain([inst, 'access', _760 => _760.overrides, 'optionalAccess', _761 => _761.stroke]), () => ( null)), hidden: _nullishCoalesce(_optionalChain([inst, 'access', _762 => _762.overrides, 'optionalAccess', _763 => _763.hidden, 'optionalAccess', _764 => _764.length]), () => ( 0)) } : null,
18472
18511
  editing: state.symbolEdit ? { symbolId: state.symbolEdit.symbolId, name: state.symbolEdit.name } : null
18473
18512
  };
18474
18513
  }
@@ -18503,7 +18542,7 @@ function createVectorEffectsToolProvider(controller, options = {}) {
18503
18542
  };
18504
18543
  const result = (id, removed) => {
18505
18544
  const g = controller.getNode(id);
18506
- const effects = _optionalChain([g, 'optionalAccess', _758 => _758.providerEffect]) ? [info(g)] : [];
18545
+ const effects = _optionalChain([g, 'optionalAccess', _765 => _765.providerEffect]) ? [info(g)] : [];
18507
18546
  return { target: id, effect: _nullishCoalesce(removed, () => ( effects[0])), effects };
18508
18547
  };
18509
18548
  return _chunkA3A5TI6Rcjs.createEffectToolProvider.call(void 0, {
@@ -18612,7 +18651,7 @@ function vectorLayerKind(node) {
18612
18651
  return "group";
18613
18652
  }
18614
18653
  function vectorLayerName(node) {
18615
- const name = _optionalChain([node, 'access', _759 => _759.name, 'optionalAccess', _760 => _760.trim, 'call', _761 => _761()]);
18654
+ const name = _optionalChain([node, 'access', _766 => _766.name, 'optionalAccess', _767 => _767.trim, 'call', _768 => _768()]);
18616
18655
  if (name) return name;
18617
18656
  if (node.type === "text") {
18618
18657
  const text = node.text.replace(/\s+/g, " ").trim();