@pixerate/editor 0.130.0 → 0.133.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/animation-editor/index.cjs +55 -55
  2. package/dist/animation-editor/index.d.cts +4 -4
  3. package/dist/animation-editor/index.d.ts +4 -4
  4. package/dist/animation-editor/index.js +2 -2
  5. package/dist/{bezier-CigmusV_.d.ts → bezier-BAGdL89w.d.ts} +1 -1
  6. package/dist/{bezier-CdoGygwG.d.cts → bezier-DL2wPsFf.d.cts} +1 -1
  7. package/dist/canvas/index.d.cts +7 -7
  8. package/dist/canvas/index.d.ts +7 -7
  9. package/dist/{chunk-MZXQTKUM.cjs → chunk-24ATT2PE.cjs} +10 -6
  10. package/dist/chunk-24ATT2PE.cjs.map +1 -0
  11. package/dist/{chunk-AHUYMDYW.js → chunk-2HC4DRF4.js} +10 -6
  12. package/dist/chunk-2HC4DRF4.js.map +1 -0
  13. package/dist/{chunk-2PXRKMOH.cjs → chunk-2QKUD3E2.cjs} +36 -36
  14. package/dist/{chunk-2PXRKMOH.cjs.map → chunk-2QKUD3E2.cjs.map} +1 -1
  15. package/dist/{chunk-PMHPXCJC.cjs → chunk-65GNHOD4.cjs} +268 -199
  16. package/dist/chunk-65GNHOD4.cjs.map +1 -0
  17. package/dist/{chunk-YRZ6NVE3.js → chunk-6CTZAGZ2.js} +235 -4
  18. package/dist/chunk-6CTZAGZ2.js.map +1 -0
  19. package/dist/{chunk-ERYGCA72.js → chunk-AOCFL7L7.js} +88 -19
  20. package/dist/chunk-AOCFL7L7.js.map +1 -0
  21. package/dist/{chunk-LXGOYRPE.cjs → chunk-F7GGEAO2.cjs} +322 -75
  22. package/dist/chunk-F7GGEAO2.cjs.map +1 -0
  23. package/dist/{chunk-PRYMC442.js → chunk-FOBB6AIO.js} +257 -10
  24. package/dist/chunk-FOBB6AIO.js.map +1 -0
  25. package/dist/{chunk-W6M7C7R3.cjs → chunk-NVTHUPJ6.cjs} +236 -5
  26. package/dist/chunk-NVTHUPJ6.cjs.map +1 -0
  27. package/dist/{chunk-L5OTIYOO.js → chunk-VGZSIXX3.js} +2 -2
  28. package/dist/effects/index.d.cts +4 -4
  29. package/dist/effects/index.d.ts +4 -4
  30. package/dist/{export-CejjC2iI.d.cts → export-BICOEM9d.d.cts} +33 -11
  31. package/dist/{export-5WDKJqTy.d.cts → export-CeFplzAW.d.cts} +1 -1
  32. package/dist/{export-B4r8b9Ft.d.ts → export-XnuX8FZ2.d.ts} +33 -11
  33. package/dist/{export-CU_ARP3A.d.ts → export-zB4HITwP.d.ts} +1 -1
  34. package/dist/{helpers-CzZu51eI.d.cts → helpers-BuKdqUlM.d.cts} +56 -1
  35. package/dist/{helpers-X_rycLNJ.d.ts → helpers-cssRNUzH.d.ts} +56 -1
  36. package/dist/image-editor/index.cjs +1064 -903
  37. package/dist/image-editor/index.cjs.map +1 -1
  38. package/dist/image-editor/index.d.cts +32 -13
  39. package/dist/image-editor/index.d.ts +32 -13
  40. package/dist/image-editor/index.js +180 -19
  41. package/dist/image-editor/index.js.map +1 -1
  42. package/dist/index.cjs +11 -4
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/index.js +11 -4
  45. package/dist/index.js.map +1 -1
  46. package/dist/{opentype-DlRMYcCW.d.cts → opentype-C3iyIFRx.d.cts} +1 -1
  47. package/dist/{opentype-CrHAsKh3.d.ts → opentype-DG5Lkwul.d.ts} +1 -1
  48. package/dist/paint/index.cjs +8 -2
  49. package/dist/paint/index.cjs.map +1 -1
  50. package/dist/paint/index.d.cts +14 -3
  51. package/dist/paint/index.d.ts +14 -3
  52. package/dist/paint/index.js +7 -1
  53. package/dist/paint-editor/index.cjs +78 -78
  54. package/dist/paint-editor/index.d.cts +7 -7
  55. package/dist/paint-editor/index.d.ts +7 -7
  56. package/dist/paint-editor/index.js +3 -3
  57. package/dist/{pathfinder-CKfKOVP4.d.cts → pathfinder-8vXik95z.d.cts} +1 -1
  58. package/dist/{pathfinder-Dlss70hL.d.ts → pathfinder-DKLt4UDG.d.ts} +1 -1
  59. package/dist/{pool-DDOo0xJH.d.ts → pool-C69pkWRz.d.ts} +1 -1
  60. package/dist/{pool-DKic69LD.d.cts → pool-VAWcYUbs.d.cts} +1 -1
  61. package/dist/{rand-pQQ2sJTk.d.ts → rand-BaqEOs1Y.d.ts} +17 -4
  62. package/dist/{rand-DTXAssW1.d.cts → rand-DdpFzCo6.d.cts} +17 -4
  63. package/dist/raster/index.cjs +2 -2
  64. package/dist/raster/index.d.cts +4 -4
  65. package/dist/raster/index.d.ts +4 -4
  66. package/dist/raster/index.js +1 -1
  67. package/dist/{svg-BRaii3pI.d.cts → svg-BThlZmja.d.cts} +2 -2
  68. package/dist/{svg-BYVZeVo0.d.ts → svg-CEYpvsgH.d.ts} +2 -2
  69. package/dist/{tools-CtheDLDr.d.cts → tools-CRnZJXXr.d.cts} +1 -1
  70. package/dist/{tools-D8bZ-7YG.d.ts → tools-CVGqEpO8.d.ts} +1 -1
  71. package/dist/vector/index.cjs +1493 -1032
  72. package/dist/vector/index.cjs.map +1 -1
  73. package/dist/vector/index.d.cts +155 -12
  74. package/dist/vector/index.d.ts +155 -12
  75. package/dist/vector/index.js +469 -8
  76. package/dist/vector/index.js.map +1 -1
  77. package/dist/video-editor/index.d.cts +4 -4
  78. package/dist/video-editor/index.d.ts +4 -4
  79. package/dist/{warp-BFoYxy_s.d.cts → warp-ChcFDdlT.d.cts} +1 -1
  80. package/dist/{warp-CZVC8pB5.d.ts → warp-mKylbLiF.d.ts} +1 -1
  81. package/package.json +2 -2
  82. package/skills/pixerate-image-editor/SKILL.md +7 -3
  83. package/skills/pixerate-image-editor/references/color-management.md +1 -1
  84. package/skills/pixerate-image-editor/references/photoshop-files.md +2 -2
  85. package/skills/pixerate-image-editor/references/retouching.md +12 -3
  86. package/skills/pixerate-vector/SKILL.md +17 -0
  87. package/skills/pixerate-vector/references/commands.md +19 -0
  88. package/dist/chunk-AHUYMDYW.js.map +0 -1
  89. package/dist/chunk-ERYGCA72.js.map +0 -1
  90. package/dist/chunk-LXGOYRPE.cjs.map +0 -1
  91. package/dist/chunk-MZXQTKUM.cjs.map +0 -1
  92. package/dist/chunk-PMHPXCJC.cjs.map +0 -1
  93. package/dist/chunk-PRYMC442.js.map +0 -1
  94. package/dist/chunk-W6M7C7R3.cjs.map +0 -1
  95. package/dist/chunk-YRZ6NVE3.js.map +0 -1
  96. /package/dist/{chunk-L5OTIYOO.js.map → chunk-VGZSIXX3.js.map} +0 -0
@@ -12,6 +12,7 @@ import {
12
12
  applyHomography,
13
13
  homographyFromPoints,
14
14
  homographyKeepsQuad,
15
+ invertHomography,
15
16
  orderQuad,
16
17
  solve8
17
18
  } from "../chunk-GX332W2C.js";
@@ -42,7 +43,7 @@ import {
42
43
  reverseMorphContour,
43
44
  subpathToMorphContour,
44
45
  turnMorphContour
45
- } from "../chunk-L5OTIYOO.js";
46
+ } from "../chunk-VGZSIXX3.js";
46
47
  import {
47
48
  DEFAULT_VECTOR_FONT,
48
49
  IDENTITY_MATRIX,
@@ -74,12 +75,16 @@ import {
74
75
  VECTOR_GRADIENT_TYPES,
75
76
  VECTOR_HORIZONTAL_RESIZING,
76
77
  VECTOR_HORIZONTAL_RESIZING_LABELS,
78
+ VECTOR_LENS_LABELS,
79
+ VECTOR_LENS_SPECS,
80
+ VECTOR_LENS_TYPES,
77
81
  VECTOR_MASK_TYPES,
78
82
  VECTOR_MERGE_MODES,
79
83
  VECTOR_MESH_MAX,
80
84
  VECTOR_PARAGRAPH_STYLE_KEYS,
81
85
  VECTOR_PATHFINDER_OPERATIONS,
82
86
  VECTOR_PATH_TEXT_BASELINES,
87
+ VECTOR_PERSPECTIVE_PLANES,
83
88
  VECTOR_PRESSURE_NOMINAL,
84
89
  VECTOR_SPATIAL_MIN,
85
90
  VECTOR_STROKE_GRADIENT_MODES,
@@ -198,6 +203,7 @@ import {
198
203
  isVectorFrame,
199
204
  isVectorFreeformGradient,
200
205
  isVectorGradient,
206
+ isVectorLens,
201
207
  isVectorLiveBoolean,
202
208
  isVectorMaskActive,
203
209
  isVectorMaskGroup,
@@ -212,6 +218,7 @@ import {
212
218
  mapBezierPath,
213
219
  mapVectorGradient,
214
220
  mapVectorPaint,
221
+ mapVectorPaintColors,
215
222
  mapVectorPoints,
216
223
  mapVectorShadedPaint,
217
224
  mapVectorSubpaths,
@@ -265,6 +272,7 @@ import {
265
272
  replaceVectorText,
266
273
  rerouteVectorConnectors,
267
274
  resizeWarpMesh,
275
+ resolveVectorLenses,
268
276
  resolveVectorSymbols,
269
277
  reverseSubpath,
270
278
  reverseVectorGradient,
@@ -284,6 +292,7 @@ import {
284
292
  sanitizeVectorFilters,
285
293
  sanitizeVectorFrame,
286
294
  sanitizeVectorGradient,
295
+ sanitizeVectorLens,
287
296
  sanitizeVectorMask,
288
297
  sanitizeVectorResizing,
289
298
  sanitizeVectorShadedPaint,
@@ -309,6 +318,7 @@ import {
309
318
  splitWarpMeshU,
310
319
  splitWarpMeshV,
311
320
  starSubpath,
321
+ stripVectorLensViews,
312
322
  stripVectorSymbolArt,
313
323
  strokePositionPoint,
314
324
  strokeWidthProfileOf,
@@ -387,6 +397,8 @@ import {
387
397
  vectorGradientUnitsMatrix,
388
398
  vectorInstanceDrawn,
389
399
  vectorInstanceGroup,
400
+ vectorLensColorMap,
401
+ vectorLensDrawn,
390
402
  vectorLiveBooleanSteps,
391
403
  vectorMaskContains,
392
404
  vectorMaskContentBounds,
@@ -483,7 +495,7 @@ import {
483
495
  withVectorStrokes,
484
496
  withVectorTargetPaint,
485
497
  zigzagPaths
486
- } from "../chunk-PRYMC442.js";
498
+ } from "../chunk-FOBB6AIO.js";
487
499
  import {
488
500
  bezierPathBounds,
489
501
  bezierPathToSvg,
@@ -824,6 +836,131 @@ function releaseVectorBlend(group, newId) {
824
836
  return [...keys, group.transform ? transformVectorNode(path, m) : path];
825
837
  }
826
838
 
839
+ // src/vector/perspective.ts
840
+ function vectorPerspectivePlanes(p) {
841
+ return p.vanishingPoints.length <= 1 ? ["floor", "side", "front"] : ["floor", "left", "right"];
842
+ }
843
+ function sanitizeVectorPerspective(value) {
844
+ if (!value || typeof value !== "object") return null;
845
+ const r = value;
846
+ const isPt = (v) => !!v && typeof v === "object" && Number.isFinite(v.x) && Number.isFinite(v.y);
847
+ if (!Array.isArray(r.vanishingPoints) || r.vanishingPoints.length < 1 || r.vanishingPoints.length > 3 || !r.vanishingPoints.every(isPt) || !isPt(r.origin)) return null;
848
+ const origin = { x: r.origin.x, y: r.origin.y };
849
+ const vps = r.vanishingPoints.map((v) => ({ x: v.x, y: v.y }));
850
+ if (vps.some((v) => Math.hypot(v.x - origin.x, v.y - origin.y) < 1e-6)) return null;
851
+ const out = { vanishingPoints: vps, origin };
852
+ if (typeof r.gridSize === "number" && r.gridSize > 0 && Number.isFinite(r.gridSize)) out.gridSize = Math.min(1e3, r.gridSize);
853
+ if (typeof r.extent === "number" && Number.isFinite(r.extent)) out.extent = Math.min(100, Math.max(1, Math.round(r.extent)));
854
+ if (r.visible === false) out.visible = false;
855
+ return out;
856
+ }
857
+ function towards(o, vp, want) {
858
+ const d = Math.hypot(vp.x - o.x, vp.y - o.y);
859
+ let a = 1 / d;
860
+ if (want === "right" ? vp.x - o.x < 0 : vp.y - o.y > 0) a = -a;
861
+ return [a * vp.x, a * vp.y, a];
862
+ }
863
+ function vectorPerspectivePlaneMap(p, plane) {
864
+ if (!vectorPerspectivePlanes(p).includes(plane)) return null;
865
+ const o = p.origin;
866
+ const [v1, v2, v3] = p.vanishingPoints;
867
+ const right = [1, 0, 0];
868
+ const up = v3 ? towards(o, v3, "up") : [0, -1, 0];
869
+ let x;
870
+ let y;
871
+ if (p.vanishingPoints.length <= 1) {
872
+ if (plane === "floor") [x, y] = [right, towards(o, v1, "up")];
873
+ else if (plane === "side") [x, y] = [towards(o, v1, "right"), up];
874
+ else [x, y] = [right, up];
875
+ } else if (plane === "floor") [x, y] = [towards(o, v2, "right"), towards(o, v1, "up")];
876
+ else if (plane === "left") [x, y] = [towards(o, v1, "right"), up];
877
+ else [x, y] = [towards(o, v2, "right"), up];
878
+ return [x[0], y[0], o.x, x[1], y[1], o.y, x[2], y[2], 1];
879
+ }
880
+ function vectorPerspectiveFlatToPlane(p, plane) {
881
+ const h = vectorPerspectivePlaneMap(p, plane);
882
+ if (!h) return null;
883
+ const o = p.origin;
884
+ return (q) => {
885
+ const u = q.x - o.x;
886
+ const v = o.y - q.y;
887
+ const w = h[6] * u + h[7] * v + h[8];
888
+ if (!(w > 1e-6)) return null;
889
+ return applyHomography(h, { x: u, y: v });
890
+ };
891
+ }
892
+ function vectorPerspectivePlaneToFlat(p, plane) {
893
+ const h = vectorPerspectivePlaneMap(p, plane);
894
+ const inv = h ? invertHomography(h) : null;
895
+ if (!inv) return null;
896
+ const o = p.origin;
897
+ return (q) => {
898
+ const f = applyHomography(inv, q);
899
+ if (!f) return null;
900
+ const w = h[6] * f.x + h[7] * f.y + h[8];
901
+ if (!(w > 1e-6)) return null;
902
+ return { x: o.x + f.x, y: o.y - f.y };
903
+ };
904
+ }
905
+ function vectorPerspectiveMapPath(p, plane, path) {
906
+ const f = vectorPerspectiveFlatToPlane(p, plane);
907
+ if (!f) return null;
908
+ let behind = false;
909
+ const out = mapBezierPath(
910
+ path,
911
+ (q) => {
912
+ const r = f(q);
913
+ if (!r) {
914
+ behind = true;
915
+ return q;
916
+ }
917
+ return r;
918
+ },
919
+ 0.1
920
+ );
921
+ return behind ? null : out;
922
+ }
923
+ function vectorPerspectiveGridLines(p, plane) {
924
+ const h = vectorPerspectivePlaneMap(p, plane);
925
+ if (!h) return [];
926
+ const g = p.gridSize ?? 20;
927
+ const n2 = p.extent ?? 12;
928
+ const max = n2 * g;
929
+ const lo = (axis) => axis === "y" && plane !== "floor" ? 0 : -max;
930
+ const w = (u, v) => h[6] * u + h[7] * v + h[8];
931
+ const at = (u, v) => applyHomography(h, { x: u, y: v });
932
+ const segment = (u0, v0, u1, v1) => {
933
+ const wa = w(u0, v0);
934
+ const wb = w(u1, v1);
935
+ const min = 0.05;
936
+ if (wa < min && wb < min) return null;
937
+ let t0 = 0;
938
+ let t1 = 1;
939
+ if (wa < min) t0 = (min - wa) / (wb - wa);
940
+ if (wb < min) t1 = (min - wa) / (wb - wa);
941
+ const a = at(u0 + (u1 - u0) * t0, v0 + (v1 - v0) * t0);
942
+ const b = at(u0 + (u1 - u0) * t1, v0 + (v1 - v0) * t1);
943
+ return a && b ? { a, b } : null;
944
+ };
945
+ const out = [];
946
+ for (let k = lo("x") / g; k <= n2; k++) {
947
+ const s = segment(k * g, lo("y"), k * g, max);
948
+ if (s) out.push(s);
949
+ }
950
+ for (let k = lo("y") / g; k <= n2; k++) {
951
+ const s = segment(lo("x"), k * g, max, k * g);
952
+ if (s) out.push(s);
953
+ }
954
+ return out;
955
+ }
956
+ function vectorPerspectivePreset(points, width, height) {
957
+ const horizon = height * 0.35;
958
+ const origin = { x: width / 2, y: height * 0.8 };
959
+ const vps = points === 1 ? [{ x: width / 2, y: horizon }] : [{ x: -width * 0.3, y: horizon }, { x: width * 1.3, y: horizon }];
960
+ if (points === 3) vps.push({ x: width / 2, y: height * 3 });
961
+ return { vanishingPoints: vps, origin, gridSize: Math.max(4, Math.round(Math.min(width, height) / 20)), extent: 12 };
962
+ }
963
+
827
964
  // src/vector/constraints/lm.ts
828
965
  var MAX_ROWS = 800;
829
966
  var maxAbs = (v) => v.reduce((m, a) => Number.isFinite(a) ? Math.max(m, Math.abs(a)) : Infinity, 0);
@@ -2296,12 +2433,20 @@ function collapsedNode(node, box, prefix) {
2296
2433
  byPrefix.set(prefix, out);
2297
2434
  return out;
2298
2435
  }
2436
+ var lensResolved = /* @__PURE__ */ new WeakMap();
2437
+ function resolvedLensNodes(doc) {
2438
+ const hit = lensResolved.get(doc.nodes);
2439
+ if (hit) return hit;
2440
+ const nodes = resolveVectorLenses(doc).nodes;
2441
+ lensResolved.set(doc.nodes, nodes);
2442
+ return nodes;
2443
+ }
2299
2444
  function getVectorSceneRenderData(state, options = {}) {
2300
2445
  const defs = [];
2301
2446
  const filters = [];
2302
2447
  const prefix = options.idPrefix ?? "ve-";
2303
2448
  const v = state.viewport;
2304
- const all = state.document.nodes;
2449
+ const all = resolvedLensNodes(state.document);
2305
2450
  const stats = { nodes: all.length, culled: 0, collapsed: 0 };
2306
2451
  let nodes;
2307
2452
  const size = options.viewportSize;
@@ -2396,6 +2541,21 @@ function shadingOverlay(state) {
2396
2541
  }
2397
2542
  return out;
2398
2543
  }
2544
+ function perspectiveOverlay(state) {
2545
+ const grid = state.document.perspective;
2546
+ if (!grid || grid.visible === false) return null;
2547
+ const r = (n2) => Math.round(n2 * 10) / 10;
2548
+ const planes = vectorPerspectivePlanes(grid).map((plane) => ({
2549
+ plane,
2550
+ active: state.perspectivePlane === plane,
2551
+ d: vectorPerspectiveGridLines(grid, plane).map(({ a, b }) => {
2552
+ const p = toScreen(state, a);
2553
+ const q = toScreen(state, b);
2554
+ return `M${r(p.x)} ${r(p.y)}L${r(q.x)} ${r(q.y)}`;
2555
+ }).join("")
2556
+ }));
2557
+ return { planes, vanishingPoints: grid.vanishingPoints.map((v) => toScreen(state, v)), origin: toScreen(state, grid.origin) };
2558
+ }
2399
2559
  function symmetryOverlay(state) {
2400
2560
  const ids = /* @__PURE__ */ new Set([...state.selection, ...state.symmetryTarget ? [state.symmetryTarget] : []]);
2401
2561
  const out = [];
@@ -2709,6 +2869,7 @@ function getVectorOverlayRenderData(state) {
2709
2869
  connectorSites: connectorSiteOverlay(state),
2710
2870
  shading: shadingOverlay(state),
2711
2871
  symmetry: symmetryOverlay(state),
2872
+ perspective: perspectiveOverlay(state),
2712
2873
  trackingPoints: (state.trackingPoints ?? []).map((p) => toScreen(state, p)),
2713
2874
  typedEntry: state.typedEntry ? { text: state.typedEntry, ...state.pointer ? toScreen(state, state.pointer) : { x: 0, y: 0 } } : null
2714
2875
  };
@@ -3517,6 +3678,7 @@ ${offset}
3517
3678
  var pdfString = (s) => `(${s.replace(/[\\()]/g, (c) => `\\${c}`).replace(/[^\x20-\x7e]/g, "?")})`;
3518
3679
  function vectorDocumentToPdf(doc, options = {}) {
3519
3680
  const notes = /* @__PURE__ */ new Set();
3681
+ doc = resolveVectorLenses(doc);
3520
3682
  const scale = options.scale ?? 1;
3521
3683
  const compress = options.compress !== false;
3522
3684
  const frames = options.pages === "artboards" ? vectorArtboards(doc) : [];
@@ -3730,8 +3892,9 @@ function nodeGroup(node, notes) {
3730
3892
  const m = nodeMatrix(node);
3731
3893
  let items = [];
3732
3894
  const live = (node.effects ?? []).some((e) => e.enabled !== false && (e.type === "wiggle" || e.type === "envelope" || e.type === "contour" || e.type === "blockShadow" || e.type === "extrude" || e.type === "bevel"));
3733
- if (node.type === "text" || node.type === "instance" || live || isVectorMaskGroup(node) || isVectorFrame(node) || isVectorSymmetryGroup(node)) {
3895
+ if (node.type === "text" || node.type === "instance" || live || isVectorMaskGroup(node) || isVectorFrame(node) || isVectorSymmetryGroup(node) || isVectorLens(node)) {
3734
3896
  if (live) notes.push(`${label(node)}: wiggle, envelope, contour, block shadow, extrude and bevel effects have no Lottie equivalent (exported as drawn).`);
3897
+ if (isVectorLens(node)) notes.push(`${label(node)}: a lens exports as drawn (what it shows now, clipped by its outline).`);
3735
3898
  if (isVectorMaskGroup(node) && node.mask?.type !== "clip") notes.push(`${label(node)}: opacity masks are not exported (the contents are drawn whole).`);
3736
3899
  const drawn = isVectorFrame(node) ? vectorFrameDrawn(node) : node;
3737
3900
  const shapes = isVectorMaskGroup(drawn) && drawn.mask?.type === "clip" ? vectorAppearanceShapes({ ...drawn, transform: void 0 }) : null;
@@ -3785,6 +3948,7 @@ function vectorDocumentToLottie(doc, options = {}) {
3785
3948
  const fps = options.fps ?? 30;
3786
3949
  const op = Math.max(1, Math.round(options.frames ?? 1));
3787
3950
  const shapes = [];
3951
+ if (!options.nodes) doc = resolveVectorLenses(doc);
3788
3952
  for (const n2 of [...options.nodes ?? doc.nodes].reverse()) {
3789
3953
  const g = nodeGroup(n2, notes);
3790
3954
  if (g) shapes.push(g);
@@ -6966,6 +7130,7 @@ var VectorEditorController = class _VectorEditorController {
6966
7130
  typedEntry: this.typed,
6967
7131
  shadingPoint: this.getShadingSelection(),
6968
7132
  symmetryTarget: this.symmetryTarget && this.doc.nodes.some((n2) => n2.id === this.symmetryTarget) ? this.symmetryTarget : null,
7133
+ perspectivePlane: this.perspectivePlane && this.doc.perspective && vectorPerspectivePlanes(this.doc.perspective).includes(this.perspectivePlane) ? this.perspectivePlane : null,
6969
7134
  canUndo: h.canUndo,
6970
7135
  canRedo: h.canRedo,
6971
7136
  undoLabel: h.undoName,
@@ -6982,7 +7147,7 @@ var VectorEditorController = class _VectorEditorController {
6982
7147
  out = { ...out, symbols: out.symbols.map((s) => s.id === edit.symbolId ? { ...s, nodes: out.nodes } : s) };
6983
7148
  }
6984
7149
  out = resolveVectorSymbols(out);
6985
- return rerouteVectorConnectors(this.solved(out));
7150
+ return resolveVectorLenses(rerouteVectorConnectors(this.solved(out)));
6986
7151
  }
6987
7152
  /**
6988
7153
  * `doc` with its constraints solved (geometry edited since the last solve moving least) and
@@ -7476,7 +7641,7 @@ var VectorEditorController = class _VectorEditorController {
7476
7641
  return vectorDocumentToSvg(this.storedDocument(), options);
7477
7642
  }
7478
7643
  toJSON() {
7479
- return cloneVectorDocument(stripVectorSymbolArt(this.storedDocument()));
7644
+ return cloneVectorDocument(stripVectorLensViews(stripVectorSymbolArt(this.storedDocument())));
7480
7645
  }
7481
7646
  /** Adds a node (ids are kept unless taken). Returns its id. */
7482
7647
  addNode(node, options = {}) {
@@ -9493,6 +9658,109 @@ var VectorEditorController = class _VectorEditorController {
9493
9658
  this.notify();
9494
9659
  }
9495
9660
  // -----------------------------------------------------------------------------------------
9661
+ // Perspective drawing
9662
+ perspectivePlane = null;
9663
+ /** The document's perspective grid, or null. */
9664
+ getPerspective() {
9665
+ return this.doc.perspective ?? null;
9666
+ }
9667
+ /**
9668
+ * Sets the document's perspective grid (CorelDRAW's Perspective Drawing): 1 to 3 vanishing
9669
+ * points, the origin where its planes meet, the cell size and extent, and whether it shows;
9670
+ * `null` removes it. One undo step.
9671
+ */
9672
+ setPerspective(grid) {
9673
+ let next = null;
9674
+ if (grid) {
9675
+ next = sanitizeVectorPerspective(grid);
9676
+ if (!next) return { ok: false, message: "A perspective grid needs 1 to 3 vanishing points { x, y } away from an origin { x, y }." };
9677
+ }
9678
+ this.change(next ? "Perspective Grid" : "Remove Perspective Grid", () => {
9679
+ const { perspective: _p, ...rest } = this.doc;
9680
+ this.doc = next ? { ...rest, perspective: next } : rest;
9681
+ });
9682
+ if (!next) this.perspectivePlane = null;
9683
+ return { ok: true, perspective: next };
9684
+ }
9685
+ /**
9686
+ * Draws new rectangles, ellipses, polygons and stars on a plane of the perspective grid (their
9687
+ * drag box is taken on the plane, so they recede with it), or flat again with `null`.
9688
+ */
9689
+ setPerspectivePlane(plane) {
9690
+ if (plane !== null) {
9691
+ const grid = this.doc.perspective;
9692
+ if (!grid) return { ok: false, message: "There is no perspective grid: set one with vector.setPerspective first." };
9693
+ const planes = vectorPerspectivePlanes(grid);
9694
+ if (!planes.includes(plane)) return { ok: false, message: `This grid's planes are ${planes.join(", ")}.` };
9695
+ }
9696
+ this.perspectivePlane = plane;
9697
+ this.notify();
9698
+ return { ok: true };
9699
+ }
9700
+ /**
9701
+ * Lays objects onto a plane of the perspective grid: each is read flat, relative to the grid's
9702
+ * origin (right and up), and projected onto the plane, so art near the origin keeps its size and
9703
+ * art further along recedes. Paths and groups are mapped in document space (their transforms
9704
+ * baked in); text and instances must be converted to outlines first. One undo step. Returns
9705
+ * the ids changed.
9706
+ */
9707
+ attachToPerspective(plane, options = {}) {
9708
+ const grid = this.doc.perspective;
9709
+ if (!grid) return { ok: false, message: "There is no perspective grid: set one with vector.setPerspective first." };
9710
+ const planes = vectorPerspectivePlanes(grid);
9711
+ if (!planes.includes(plane)) return { ok: false, message: `This grid's planes are ${planes.join(", ")}.` };
9712
+ const ids = [...new Set(options.ids ?? this.selectedRoots())];
9713
+ if (!ids.length) return { ok: false, message: "Select objects to put on the plane first." };
9714
+ const next = /* @__PURE__ */ new Map();
9715
+ const project = (n2, m) => {
9716
+ const own = n2.transform ? multiplyMatrices(m, n2.transform) : m;
9717
+ if (n2.type === "text" || n2.type === "instance") return `"${n2.id}" is ${n2.type === "text" ? "text" : "a symbol instance"}: convert it to outlines first (vector.createOutlines${n2.type === "instance" ? " after vector.detachInstance" : ""}).`;
9718
+ if (n2.type === "group") {
9719
+ const children = [];
9720
+ for (const c of n2.children) {
9721
+ const r = project(c, own);
9722
+ if (typeof r === "string") return r;
9723
+ children.push(r);
9724
+ }
9725
+ const { transform: _t2, ...rest2 } = n2;
9726
+ return { ...rest2, children };
9727
+ }
9728
+ const flat = transformBezierPath(subpathsToBezier(n2.subpaths), own);
9729
+ const mapped = vectorPerspectiveMapPath(grid, plane, flat);
9730
+ if (!mapped) return `"${n2.id}" reaches beyond the plane's horizon: move it nearer the origin, or the vanishing points further out.`;
9731
+ const { transform: _t, ...rest } = n2;
9732
+ return { ...rest, subpaths: bezierToSubpaths(mapped) };
9733
+ };
9734
+ for (const id of ids) {
9735
+ const loc = locateVectorNode(this.doc.nodes, id);
9736
+ if (!loc) return { ok: false, message: `There is no node "${id}".` };
9737
+ const node = loc.list[loc.index];
9738
+ if (node.locked) return { ok: false, message: `"${id}" is locked; unlock it first.` };
9739
+ const parentM = this.parentMatrixOf(id);
9740
+ const r = project(node, parentM);
9741
+ if (typeof r === "string") return { ok: false, message: r };
9742
+ const inv = invertMatrix(parentM);
9743
+ next.set(id, isIdentityMatrix(inv) ? r : transformVectorNode(r, inv));
9744
+ }
9745
+ this.change(`Attach to ${plane[0].toUpperCase()}${plane.slice(1)} Plane`, () => {
9746
+ this.setDoc(mapTree(this.doc.nodes, (n2) => next.get(n2.id) ?? n2));
9747
+ });
9748
+ return { ok: true, ids };
9749
+ }
9750
+ /** A shape's subpaths drawn on the active perspective plane from its flat drag box, or null to keep it flat. */
9751
+ perspectiveShape(kind, start, end) {
9752
+ const grid = this.doc.perspective;
9753
+ const plane = this.perspectivePlane;
9754
+ if (!grid || !plane || kind === "line" || !vectorPerspectivePlanes(grid).includes(plane)) return null;
9755
+ const toFlat = vectorPerspectivePlaneToFlat(grid, plane);
9756
+ const a = toFlat?.(start);
9757
+ const b = toFlat?.(end);
9758
+ if (!a || !b) return null;
9759
+ const flat = this.createShapeNode({ kind, ...boundsFromPoints(a, b) });
9760
+ const mapped = vectorPerspectiveMapPath(grid, plane, subpathsToBezier(flat.subpaths));
9761
+ return mapped ? bezierToSubpaths(mapped) : null;
9762
+ }
9763
+ // -----------------------------------------------------------------------------------------
9496
9764
  // PDF
9497
9765
  /**
9498
9766
  * The document as a vector PDF (see `vectorDocumentToPdf`): one page of the artboard, or a page
@@ -10134,6 +10402,51 @@ var VectorEditorController = class _VectorEditorController {
10134
10402
  * (`{ nodeId, side? }`) or unglue it (`null`, the end staying where it is), and `route`,
10135
10403
  * `radius`, `gap` set how they run. Plain open paths given by id become connectors. One undo step.
10136
10404
  */
10405
+ /**
10406
+ * Makes closed paths lenses (CorelDRAW's Lens) or changes their lens: `lens` is merged over the
10407
+ * current settings (a different `type` starts from that type's defaults), and `null` makes
10408
+ * them plain paths again. One undo step. Returns each path's id and resulting lens.
10409
+ */
10410
+ setLens(lens, options = {}) {
10411
+ const ids = options.ids ?? this.selection;
10412
+ if (!ids.length) return { ok: false, message: "Select a closed path to make a lens first." };
10413
+ if (lens && lens.type !== void 0 && !VECTOR_LENS_TYPES.includes(lens.type)) return { ok: false, message: `Unknown lens "${lens.type}": use ${VECTOR_LENS_TYPES.join(", ")}.` };
10414
+ if (lens?.color !== void 0 && lens.color !== null && !parseVectorColor(lens.color)) return { ok: false, message: `"${lens.color}" is not a colour: use a CSS colour such as #ff0000.` };
10415
+ const next = /* @__PURE__ */ new Map();
10416
+ for (const id of ids) {
10417
+ const n2 = this.getNode(id);
10418
+ if (!n2) return { ok: false, message: `There is no node "${id}".` };
10419
+ if (n2.locked) return { ok: false, message: `"${id}" is locked; unlock it first.` };
10420
+ if (lens === null) {
10421
+ if (n2.type === "path" && n2.lens) next.set(id, null);
10422
+ continue;
10423
+ }
10424
+ if (n2.type !== "path" || !n2.subpaths.some((sp) => sp.closed) || isVectorConnector(n2)) return { ok: false, message: `"${id}" is not a closed path: only closed paths can be lenses.` };
10425
+ const type = lens.type ?? n2.lens?.type;
10426
+ if (!type) return { ok: false, message: `"${id}" is not a lens yet: pass a type (${VECTOR_LENS_TYPES.join(", ")}).` };
10427
+ const spec = VECTOR_LENS_SPECS[type];
10428
+ 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}).` };
10429
+ const base = n2.lens && n2.lens.type === type ? n2.lens : { type };
10430
+ next.set(id, sanitizeVectorLens({ ...base, ...lens, type }));
10431
+ }
10432
+ if (!next.size) return { ok: true, lenses: [] };
10433
+ this.change(
10434
+ lens === null ? "Remove Lens" : "Lens",
10435
+ () => {
10436
+ this.setDoc(
10437
+ mapTree(this.doc.nodes, (n2) => {
10438
+ if (!next.has(n2.id) || n2.type !== "path") return n2;
10439
+ const l = next.get(n2.id);
10440
+ if (l) return { ...n2, lens: l };
10441
+ const { lens: _l, lensView: _v, ...rest } = n2;
10442
+ return rest;
10443
+ })
10444
+ );
10445
+ },
10446
+ options.merge
10447
+ );
10448
+ return { ok: true, lenses: [...next].map(([id, l]) => ({ id, lens: l })) };
10449
+ }
10137
10450
  setConnector(patch, options = {}) {
10138
10451
  const ids = options.ids ?? this.selection;
10139
10452
  if (!ids.length) return { ok: false, message: "Select a connector first." };
@@ -12239,7 +12552,9 @@ var VectorEditorController = class _VectorEditorController {
12239
12552
  const y2 = drag.start.y + h;
12240
12553
  bounds = boundsFromPoints(start, { x: x2, y: y2 });
12241
12554
  }
12242
- const shaped = this.createShapeNode({ kind: drag.tool === "frame" ? "rect" : drag.tool, ...bounds });
12555
+ const kind = drag.tool === "frame" ? "rect" : drag.tool;
12556
+ const onPlane = drag.tool !== "frame" ? this.perspectiveShape(kind, start, { x: bounds.x === start.x ? bounds.x + bounds.width : bounds.x, y: bounds.y === start.y ? bounds.y + bounds.height : bounds.y }) : null;
12557
+ const shaped = onPlane ? { subpaths: onPlane } : this.createShapeNode({ kind, ...bounds });
12243
12558
  this.replaceNode(drag.nodeId, { ...node, subpaths: shaped.subpaths });
12244
12559
  this.interaction = { type: "draw", tool: drag.tool, nodeId: drag.nodeId, bounds };
12245
12560
  this.notify(true);
@@ -14091,7 +14406,8 @@ function createVectorCommands(controller, options = {}) {
14091
14406
  ...isVectorFrame(n2) ? { frameRect: n2.frame } : {},
14092
14407
  ...n2.resizing ? { resizing: n2.resizing } : {},
14093
14408
  ...n2.type === "path" && n2.connector ? { connector: n2.connector } : {},
14094
- ...n2.type === "group" && n2.symmetry ? { symmetry: n2.symmetry } : {}
14409
+ ...n2.type === "group" && n2.symmetry ? { symmetry: n2.symmetry } : {},
14410
+ ...n2.type === "path" && n2.lens ? { lens: n2.lens } : {}
14095
14411
  });
14096
14412
  if (n2.type === "group") visit(n2.children, depth + 1);
14097
14413
  }
@@ -15055,6 +15371,130 @@ function createVectorCommands(controller, options = {}) {
15055
15371
  }
15056
15372
  }
15057
15373
  ];
15374
+ const LENS_AMOUNTS = VECTOR_LENS_TYPES.map((t) => `${t} ${VECTOR_LENS_SPECS[t].min}\u2026${VECTOR_LENS_SPECS[t].max} ${VECTOR_LENS_SPECS[t].unit} (default ${VECTOR_LENS_SPECS[t].amount})`).join("; ");
15375
+ const lensCommands = () => [
15376
+ {
15377
+ ...base,
15378
+ id: `${prefix}setLens`,
15379
+ label: "Lens\u2026",
15380
+ keywords: ["lens", "magnify", "fisheye", "fish eye", "invert", "brighten", "grayscale", "heat map", "wireframe", "transparency", "tint", "loupe"],
15381
+ description: "Makes closed paths (`ids`, default the selection) lenses, or changes their lens: inside its outline, what is drawn below shows changed (magnify, fisheye, brighten, invert, tintedGrayscale, colorAdd, colorLimit, heatMap, wireframe, or the lens's own fill see-through for transparency). The lens follows every edit below it; its bounds stay its own shape. Pass type to make or switch a lens (missing values take that type's defaults); omit it to change amount or color of existing lenses. One undo step. Returns { lenses: [{ id, lens }] }.",
15382
+ params: {
15383
+ type: "object",
15384
+ properties: {
15385
+ ids: { ...IDS, description: "Closed paths to make or change (default: the selection)." },
15386
+ type: { type: "string", enum: [...VECTOR_LENS_TYPES], description: "What the lens does. Required for a path that is not a lens yet." },
15387
+ amount: { type: "number", description: `Strength, by type: ${LENS_AMOUNTS}.` },
15388
+ color: { type: ["string", "null"], description: "CSS colour for tintedGrayscale, colorAdd, colorLimit and wireframe (default per type; ignored by the others)." }
15389
+ },
15390
+ additionalProperties: false
15391
+ },
15392
+ undoable: true,
15393
+ enabled: enabledFor,
15394
+ run: (_ctx, params) => {
15395
+ const { ids: list2, ...patch } = params ?? {};
15396
+ if (!Object.keys(patch).length) fail("Pass at least one of type, amount, color.");
15397
+ const r = controller.setLens(patch, list2 ? { ids: list2 } : {});
15398
+ check(r);
15399
+ return { lenses: r.lenses ?? [] };
15400
+ }
15401
+ },
15402
+ {
15403
+ ...base,
15404
+ id: `${prefix}removeLens`,
15405
+ label: "Remove Lens",
15406
+ keywords: ["lens", "remove", "plain"],
15407
+ description: "Makes lenses (`ids`, default the selection) plain paths again; ids that are not lenses are skipped. One undo step. Returns { ids } of the paths that stopped being lenses.",
15408
+ params: { type: "object", properties: { ids: { ...IDS, description: "Lens ids (default: the selection)." } }, additionalProperties: false },
15409
+ undoable: true,
15410
+ enabled: enabledFor,
15411
+ run: (_ctx, params) => {
15412
+ const r = controller.setLens(null, params?.ids ? { ids: params.ids } : {});
15413
+ check(r);
15414
+ return { ids: (r.lenses ?? []).map((l) => l.id) };
15415
+ }
15416
+ }
15417
+ ];
15418
+ const PLANE = { type: "string", enum: [...VECTOR_PERSPECTIVE_PLANES], description: "A plane of the grid: floor, left and right (2 or 3 vanishing points), or floor, side and front (1 point)." };
15419
+ const perspectiveResult = () => {
15420
+ const grid = controller.getPerspective();
15421
+ return { perspective: grid, planes: grid ? vectorPerspectivePlanes(grid) : [], drawingOn: controller.getState().perspectivePlane };
15422
+ };
15423
+ const perspectiveCommands = () => [
15424
+ {
15425
+ ...base,
15426
+ id: `${prefix}getPerspective`,
15427
+ label: "Perspective Grid",
15428
+ keywords: ["perspective", "grid", "vanishing point", "horizon"],
15429
+ description: "Reads the document's perspective grid: { perspective: { vanishingPoints, origin, gridSize, extent, visible } or null, planes (the planes it has), drawingOn (the plane new shapes are drawn on, or null) }.",
15430
+ params: { type: "object", properties: {}, additionalProperties: false },
15431
+ run: () => perspectiveResult()
15432
+ },
15433
+ {
15434
+ ...base,
15435
+ id: `${prefix}setPerspective`,
15436
+ label: "Perspective Grid\u2026",
15437
+ keywords: ["perspective", "grid", "vanishing point", "one point", "two point", "three point", "horizon", "drawing in perspective"],
15438
+ description: "Sets the document's perspective grid (CorelDRAW's Perspective Drawing): 1 vanishing point (planes floor, side, front), 2 (floor, left, right; walls recede to the first and second) or 3 (the third is where the walls' verticals meet). Put the vanishing points on the horizon line and the origin below it, where the planes meet. One undo step. Returns the grid as vector.getPerspective does.",
15439
+ params: {
15440
+ type: "object",
15441
+ properties: {
15442
+ vanishingPoints: { type: "array", minItems: 1, maxItems: 3, items: { ...POINT, description: "A vanishing point (document units)." }, description: "1 to 3 vanishing points, document units." },
15443
+ origin: { ...POINT, description: "Where the planes meet (document units), not on a vanishing point." },
15444
+ gridSize: { type: "number", exclusiveMinimum: 0, description: "Grid cell size at the origin, document units (default 20)." },
15445
+ extent: { type: "integer", minimum: 1, maximum: 100, description: "Cells drawn out from the origin along each axis (default 12)." },
15446
+ visible: { type: "boolean", description: "Show the grid on the canvas (default true)." }
15447
+ },
15448
+ required: ["vanishingPoints", "origin"],
15449
+ additionalProperties: false
15450
+ },
15451
+ undoable: true,
15452
+ run: (_ctx, params) => {
15453
+ check(controller.setPerspective(params));
15454
+ return perspectiveResult();
15455
+ }
15456
+ },
15457
+ {
15458
+ ...base,
15459
+ id: `${prefix}removePerspective`,
15460
+ label: "Remove Perspective Grid",
15461
+ keywords: ["perspective", "grid", "remove"],
15462
+ description: "Removes the perspective grid (art already on its planes stays as drawn). One undo step. Returns { perspective: null }.",
15463
+ params: { type: "object", properties: {}, additionalProperties: false },
15464
+ undoable: true,
15465
+ run: () => {
15466
+ check(controller.setPerspective(null));
15467
+ return { perspective: null };
15468
+ }
15469
+ },
15470
+ {
15471
+ ...base,
15472
+ id: `${prefix}setPerspectivePlane`,
15473
+ label: "Draw on Perspective Plane",
15474
+ keywords: ["perspective", "plane", "draw", "floor", "wall"],
15475
+ description: "Makes the Rectangle, Ellipse, Polygon and Star tools draw on a plane of the grid (their drag box is taken on the plane, so shapes recede with it), or flat again with plane null. Not an undo step. Returns the grid as vector.getPerspective does.",
15476
+ params: { type: "object", properties: { plane: { ...PLANE, type: ["string", "null"], enum: [...VECTOR_PERSPECTIVE_PLANES, null], description: `${PLANE.description} null draws flat.` } }, required: ["plane"], additionalProperties: false },
15477
+ run: (_ctx, params) => {
15478
+ check(controller.setPerspectivePlane(params.plane));
15479
+ return perspectiveResult();
15480
+ }
15481
+ },
15482
+ {
15483
+ ...base,
15484
+ id: `${prefix}attachToPerspective`,
15485
+ label: "Attach to Perspective",
15486
+ keywords: ["perspective", "attach", "plane", "project", "wall", "floor", "sign"],
15487
+ description: "Lays objects (`ids`, default the selection) onto a plane of the grid: each is read flat relative to the grid origin (right and up) and projected, so art near the origin keeps its size and further art recedes. Draw or place the flat art beside the origin first. Text and instances must be outlines (vector.createOutlines). One undo step. Returns { ids }.",
15488
+ params: { type: "object", properties: { ids: { ...IDS, description: "Objects to project (default: the selection)." }, plane: PLANE }, required: ["plane"], additionalProperties: false },
15489
+ undoable: true,
15490
+ enabled: enabledFor,
15491
+ run: (_ctx, params) => {
15492
+ const r = controller.attachToPerspective(params.plane, params.ids ? { ids: params.ids } : {});
15493
+ check(r);
15494
+ return { ids: r.ids ?? [] };
15495
+ }
15496
+ }
15497
+ ];
15058
15498
  const pdfCommands = () => [
15059
15499
  {
15060
15500
  ...base,
@@ -15891,6 +16331,8 @@ function createVectorCommands(controller, options = {}) {
15891
16331
  ...lottieCommands(),
15892
16332
  ...pdfCommands(),
15893
16333
  ...symmetryCommands(),
16334
+ ...perspectiveCommands(),
16335
+ ...lensCommands(),
15894
16336
  {
15895
16337
  ...base,
15896
16338
  id: `${prefix}setCorners`,
@@ -16922,6 +17364,9 @@ export {
16922
17364
  VECTOR_HORIZONTAL_RESIZING,
16923
17365
  VECTOR_HORIZONTAL_RESIZING_LABELS,
16924
17366
  VECTOR_INK_MAX_CORNERS,
17367
+ VECTOR_LENS_LABELS,
17368
+ VECTOR_LENS_SPECS,
17369
+ VECTOR_LENS_TYPES,
16925
17370
  VECTOR_MASK_TYPES,
16926
17371
  VECTOR_MASK_TYPE_LABELS,
16927
17372
  VECTOR_MASK_TYPE_OPTIONS,
@@ -16937,6 +17382,7 @@ export {
16937
17382
  VECTOR_PATH_ACTIONS,
16938
17383
  VECTOR_PATH_TEXT_BASELINES,
16939
17384
  VECTOR_PENCIL_STRING_PX,
17385
+ VECTOR_PERSPECTIVE_PLANES,
16940
17386
  VECTOR_PRESSURE_NOMINAL,
16941
17387
  VECTOR_ROTATE_HANDLE_OFFSET,
16942
17388
  VECTOR_SPATIAL_MIN,
@@ -17128,6 +17574,7 @@ export {
17128
17574
  isVectorFrame,
17129
17575
  isVectorFreeformGradient,
17130
17576
  isVectorGradient,
17577
+ isVectorLens,
17131
17578
  isVectorLiveBoolean,
17132
17579
  isVectorMaskActive,
17133
17580
  isVectorMaskGroup,
@@ -17147,6 +17594,7 @@ export {
17147
17594
  mapVectorGradient,
17148
17595
  mapWarpMeshPoints as mapVectorMeshPoints,
17149
17596
  mapVectorPaint,
17597
+ mapVectorPaintColors,
17150
17598
  mapVectorPoints,
17151
17599
  mapVectorShadedPaint,
17152
17600
  mapVectorSubpaths,
@@ -17217,6 +17665,7 @@ export {
17217
17665
  resampleGradientStops,
17218
17666
  resizeWarpMesh as resizeVectorMesh,
17219
17667
  resolveVectorBlendOptions,
17668
+ resolveVectorLenses,
17220
17669
  resolveVectorSymbols,
17221
17670
  reverseMorphContour,
17222
17671
  reverseSubpath,
@@ -17238,7 +17687,9 @@ export {
17238
17687
  sanitizeVectorFilters,
17239
17688
  sanitizeVectorFrame,
17240
17689
  sanitizeVectorGradient,
17690
+ sanitizeVectorLens,
17241
17691
  sanitizeVectorMask,
17692
+ sanitizeVectorPerspective,
17242
17693
  sanitizeVectorResizing,
17243
17694
  sanitizeVectorShadedPaint,
17244
17695
  sanitizeVectorStrokeSettings,
@@ -17267,6 +17718,7 @@ export {
17267
17718
  splitWarpMeshU as splitVectorMeshU,
17268
17719
  splitWarpMeshV as splitVectorMeshV,
17269
17720
  starSubpath,
17721
+ stripVectorLensViews,
17270
17722
  stripVectorSymbolArt,
17271
17723
  strokePositionPoint,
17272
17724
  strokeWidthProfileOf,
@@ -17383,6 +17835,8 @@ export {
17383
17835
  vectorInkShapeName,
17384
17836
  vectorInstanceDrawn,
17385
17837
  vectorInstanceGroup,
17838
+ vectorLensColorMap,
17839
+ vectorLensDrawn,
17386
17840
  vectorLiveBooleanSteps,
17387
17841
  vectorMaskContains,
17388
17842
  vectorMaskContentBounds,
@@ -17432,6 +17886,13 @@ export {
17432
17886
  vectorPathTextPositions,
17433
17887
  vectorPathWorldBezier,
17434
17888
  vectorPathfinderShape,
17889
+ vectorPerspectiveFlatToPlane,
17890
+ vectorPerspectiveGridLines,
17891
+ vectorPerspectiveMapPath,
17892
+ vectorPerspectivePlaneMap,
17893
+ vectorPerspectivePlaneToFlat,
17894
+ vectorPerspectivePlanes,
17895
+ vectorPerspectivePreset,
17435
17896
  vectorPolarAngles,
17436
17897
  vectorPolarIncrementOf,
17437
17898
  vectorRepeaterCopies,