@weasel-js/core 1.4.4 → 1.5.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 (48) hide show
  1. package/CHANGELOG.md +937 -2202
  2. package/README.md +118 -75
  3. package/dist/{autoPoseDescriptor-DF1SnnSx.d.ts → autoPoseDescriptor-CvjflWJK.d.ts} +29 -26
  4. package/dist/{chunk-2VXGHUVL.js → chunk-BDWAA634.js} +4 -22
  5. package/dist/chunk-BDWAA634.js.map +1 -0
  6. package/dist/{chunk-R3AWPTLZ.js → chunk-MG7OXCAI.js} +2760 -4491
  7. package/dist/chunk-MG7OXCAI.js.map +1 -0
  8. package/dist/{chunk-PRGBGMH3.js → chunk-MQI4PIX3.js} +3 -3
  9. package/dist/chunk-MQI4PIX3.js.map +1 -0
  10. package/dist/{chunk-WPM42WJP.js → chunk-UCPV7JXC.js} +201 -256
  11. package/dist/chunk-UCPV7JXC.js.map +1 -0
  12. package/dist/clipboard.d.ts +2 -3
  13. package/dist/clone.d.ts +3 -2
  14. package/dist/depSchema-nMqj_qTM.d.ts +3490 -0
  15. package/dist/{grid-0Pbn5B2C.d.ts → grid-BrIa38gG.d.ts} +7 -10
  16. package/dist/index.d.ts +1996 -1229
  17. package/dist/index.js +4 -5
  18. package/dist/insert.d.ts +4 -4
  19. package/dist/insert.js +1 -1
  20. package/dist/move.d.ts +5 -6
  21. package/dist/move.js +3 -6
  22. package/dist/move.js.map +1 -1
  23. package/dist/{options-DbYLImvq.d.ts → options-BDyCnrp8.d.ts} +3 -2
  24. package/dist/poseDescriptor-CGOgIgf8.d.ts +134 -0
  25. package/dist/renderer.d.ts +10 -4
  26. package/dist/renderer.js +4 -5
  27. package/dist/resize.d.ts +10 -12
  28. package/dist/resize.js +2 -2
  29. package/dist/routing.d.ts +1 -142
  30. package/dist/routing.js +1 -1
  31. package/dist/routing.js.map +1 -1
  32. package/dist/{types-ei3UMl9R.d.ts → types-DMyo7dnM.d.ts} +12 -41
  33. package/dist/{types-DEALFt5F.d.ts → types-DtjCJA5r.d.ts} +9 -3
  34. package/package.json +13 -10
  35. package/dist/DrawCommand-CD-ug3d9.d.ts +0 -332
  36. package/dist/builtins-BXFBXegF.d.ts +0 -840
  37. package/dist/chunk-2VXGHUVL.js.map +0 -1
  38. package/dist/chunk-BL65SHCX.js +0 -573
  39. package/dist/chunk-BL65SHCX.js.map +0 -1
  40. package/dist/chunk-PRGBGMH3.js.map +0 -1
  41. package/dist/chunk-R3AWPTLZ.js.map +0 -1
  42. package/dist/chunk-WPM42WJP.js.map +0 -1
  43. package/dist/geometry-6fCNhAux.d.ts +0 -114
  44. package/dist/path-JEV2c5If.d.ts +0 -48
  45. package/dist/registry-BY-wI9gm.d.ts +0 -4003
  46. package/dist/types-BHK2dkMu.d.ts +0 -172
  47. package/dist/types-bcc7jcUy.d.ts +0 -594
  48. package/dist/view-DSQgxBJB.d.ts +0 -63
@@ -1,5 +1,5 @@
1
- import { PATH_Z, PATH_Q, elevateQuadraticToCubic, cubicBounds, PATH_C, PATH_L, PATH_M, pointSegmentDist2, transformCoords, forEachSegment, pathCommandCoordCount, boxToBox } from '@weasel-js/geom';
2
- export { PATH_C, PATH_CMD_LENGTHS, PATH_L, PATH_M, PATH_Q, PATH_Z, pathCommandCoordCount } from '@weasel-js/geom';
1
+ import { forEachSegment, PATH_Z, PATH_Q, elevateQuadraticToCubic, cubicBounds, PATH_C, PATH_L, PATH_M, DEFAULT_FLATTEN_TOLERANCE, flattenQuadratic, flattenCubic, pointSegmentDist2, transformCoords, pathCommandCoordCount, boxToBox } from '@weasel-js/geom';
2
+ export { DEFAULT_FLATTEN_TOLERANCE, PATH_C, PATH_CMD_LENGTHS, PATH_L, PATH_M, PATH_Q, PATH_Z, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, pathCommandCoordCount } from '@weasel-js/geom';
3
3
 
4
4
  // src/core/units.ts
5
5
  function resolveUnit(v, unitSystem) {
@@ -43,6 +43,10 @@ var METRIC_MM = {
43
43
  base: "mm",
44
44
  units: { mm: 1, cm: 10, m: 1e3, km: 1e6 }
45
45
  };
46
+ var ANGLE_RADIANS = {
47
+ base: "rad",
48
+ units: { rad: 1, deg: Math.PI / 180, turn: Math.PI * 2 }
49
+ };
46
50
  var PIXELS = {
47
51
  base: "px",
48
52
  units: { px: 1 }
@@ -54,9 +58,7 @@ function boundsOfPath(path) {
54
58
  return { kind: "rect", x: 0, y: 0, width: 0, height: 0 };
55
59
  }
56
60
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
57
- let ci = 0;
58
61
  let seen = false;
59
- let px = 0, py = 0;
60
62
  const include = (x, y) => {
61
63
  if (x < minX) minX = x;
62
64
  if (x > maxX) maxX = x;
@@ -64,40 +66,34 @@ function boundsOfPath(path) {
64
66
  if (y > maxY) maxY = y;
65
67
  seen = true;
66
68
  };
67
- for (let i = 0; i < commands.length; i++) {
68
- const cmd = commands[i];
69
+ forEachSegment(commands, coords, (cmd, ci, px, py) => {
69
70
  switch (cmd) {
70
71
  case PATH_M:
71
72
  case PATH_L: {
72
- const x = coords[ci], y = coords[ci + 1];
73
- include(x, y);
74
- px = x;
75
- py = y;
76
- ci += 2;
73
+ include(coords[ci], coords[ci + 1]);
77
74
  break;
78
75
  }
79
76
  case PATH_C: {
80
- const x1 = coords[ci], y1 = coords[ci + 1];
81
- const x2 = coords[ci + 2], y2 = coords[ci + 3];
82
- const x3 = coords[ci + 4], y3 = coords[ci + 5];
83
- const [bMinX, bMinY, bMaxX, bMaxY] = cubicBounds(px, py, x1, y1, x2, y2, x3, y3);
77
+ const [bMinX, bMinY, bMaxX, bMaxY] = cubicBounds(
78
+ px,
79
+ py,
80
+ coords[ci],
81
+ coords[ci + 1],
82
+ coords[ci + 2],
83
+ coords[ci + 3],
84
+ coords[ci + 4],
85
+ coords[ci + 5]
86
+ );
84
87
  include(bMinX, bMinY);
85
88
  include(bMaxX, bMaxY);
86
- px = x3;
87
- py = y3;
88
- ci += 6;
89
89
  break;
90
90
  }
91
91
  case PATH_Q: {
92
- const qx1 = coords[ci], qy1 = coords[ci + 1];
93
92
  const qx2 = coords[ci + 2], qy2 = coords[ci + 3];
94
- const [c1x, c1y, c2x, c2y] = elevateQuadraticToCubic(px, py, qx1, qy1, qx2, qy2);
93
+ const [c1x, c1y, c2x, c2y] = elevateQuadraticToCubic(px, py, coords[ci], coords[ci + 1], qx2, qy2);
95
94
  const [bMinX, bMinY, bMaxX, bMaxY] = cubicBounds(px, py, c1x, c1y, c2x, c2y, qx2, qy2);
96
95
  include(bMinX, bMinY);
97
96
  include(bMaxX, bMaxY);
98
- px = qx2;
99
- py = qy2;
100
- ci += 4;
101
97
  break;
102
98
  }
103
99
  case PATH_Z:
@@ -105,133 +101,10 @@ function boundsOfPath(path) {
105
101
  default:
106
102
  throw new Error(`boundsOfPath: unknown command ${cmd}`);
107
103
  }
108
- }
104
+ });
109
105
  if (!seen) return { kind: "rect", x: 0, y: 0, width: 0, height: 0 };
110
106
  return { kind: "rect", x: minX, y: minY, width: maxX - minX, height: maxY - minY };
111
107
  }
112
-
113
- // src/features/paths/flatten.ts
114
- var DEFAULT_FLATTEN_TOLERANCE = 0.5;
115
- var MIN_FLATTEN_TOLERANCE = 1e-6;
116
- function usableTolerance(tolerance) {
117
- return tolerance > 0 ? tolerance : MIN_FLATTEN_TOLERANCE;
118
- }
119
- function finite6(a, b, c, d, e, f) {
120
- return Number.isFinite(a) && Number.isFinite(b) && Number.isFinite(c) && Number.isFinite(d) && Number.isFinite(e) && Number.isFinite(f);
121
- }
122
- function finite8(a, b, c, d, e, f, g, h) {
123
- return finite6(a, b, c, d, e, f) && Number.isFinite(g) && Number.isFinite(h);
124
- }
125
- function distPointToLine(px, py, ax, ay, bx, by) {
126
- const dx = bx - ax;
127
- const dy = by - ay;
128
- const len2 = dx * dx + dy * dy;
129
- if (len2 === 0) {
130
- const ex = px - ax;
131
- const ey = py - ay;
132
- return Math.sqrt(ex * ex + ey * ey);
133
- }
134
- const cross = (px - ax) * dy - (py - ay) * dx;
135
- return Math.abs(cross) / Math.sqrt(len2);
136
- }
137
- function flattenCubic(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out) {
138
- if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {
139
- out.push(x3, y3);
140
- return;
141
- }
142
- flattenCubicRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out);
143
- }
144
- function flattenCubicRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out) {
145
- const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);
146
- const d2 = distPointToLine(x2, y2, x0, y0, x3, y3);
147
- if (Math.max(d1, d2) <= tolerance) {
148
- out.push(x3, y3);
149
- return;
150
- }
151
- const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;
152
- const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;
153
- const x23 = (x2 + x3) * 0.5, y23 = (y2 + y3) * 0.5;
154
- const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;
155
- const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;
156
- const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;
157
- flattenCubicRec(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out);
158
- flattenCubicRec(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out);
159
- }
160
- function flattenQuadratic(x0, y0, x1, y1, x2, y2, tolerance, out) {
161
- if (!finite6(x0, y0, x1, y1, x2, y2)) {
162
- out.push(x2, y2);
163
- return;
164
- }
165
- flattenQuadraticRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out);
166
- }
167
- function flattenQuadraticRec(x0, y0, x1, y1, x2, y2, tolerance, out) {
168
- const d = distPointToLine(x1, y1, x0, y0, x2, y2);
169
- if (d <= tolerance) {
170
- out.push(x2, y2);
171
- return;
172
- }
173
- const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;
174
- const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;
175
- const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;
176
- flattenQuadraticRec(x0, y0, x01, y01, x012, y012, tolerance, out);
177
- flattenQuadraticRec(x012, y012, x12, y12, x2, y2, tolerance, out);
178
- }
179
- function flattenCubicWithArcLen(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, arcOut) {
180
- if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {
181
- out.push(x3, y3);
182
- arcOut.push(0);
183
- return 0;
184
- }
185
- return flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out, arcOut, 0);
186
- }
187
- function flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, arcOut, accum) {
188
- const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);
189
- const d2 = distPointToLine(x2, y2, x0, y0, x3, y3);
190
- if (Math.max(d1, d2) <= tolerance) {
191
- const lastX = out.length >= 2 ? out[out.length - 2] : x0;
192
- const lastY = out.length >= 2 ? out[out.length - 1] : y0;
193
- const seg = Math.hypot(x3 - lastX, y3 - lastY);
194
- accum += seg;
195
- out.push(x3, y3);
196
- arcOut.push(accum);
197
- return accum;
198
- }
199
- const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;
200
- const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;
201
- const x23 = (x2 + x3) * 0.5, y23 = (y2 + y3) * 0.5;
202
- const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;
203
- const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;
204
- const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;
205
- accum = flattenCubicArcRec(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out, arcOut, accum);
206
- accum = flattenCubicArcRec(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out, arcOut, accum);
207
- return accum;
208
- }
209
- function flattenQuadraticWithArcLen(x0, y0, x1, y1, x2, y2, tolerance, out, arcOut) {
210
- if (!finite6(x0, y0, x1, y1, x2, y2)) {
211
- out.push(x2, y2);
212
- arcOut.push(0);
213
- return 0;
214
- }
215
- return flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out, arcOut, 0);
216
- }
217
- function flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, tolerance, out, arcOut, accum) {
218
- const d = distPointToLine(x1, y1, x0, y0, x2, y2);
219
- if (d <= tolerance) {
220
- const lastX = out.length >= 2 ? out[out.length - 2] : x0;
221
- const lastY = out.length >= 2 ? out[out.length - 1] : y0;
222
- const seg = Math.hypot(x2 - lastX, y2 - lastY);
223
- accum += seg;
224
- out.push(x2, y2);
225
- arcOut.push(accum);
226
- return accum;
227
- }
228
- const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;
229
- const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;
230
- const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;
231
- accum = flattenQuadraticArcRec(x0, y0, x01, y01, x012, y012, tolerance, out, arcOut, accum);
232
- accum = flattenQuadraticArcRec(x012, y012, x12, y12, x2, y2, tolerance, out, arcOut, accum);
233
- return accum;
234
- }
235
108
  function pointInPath(path, x, y, opts = {}) {
236
109
  if (path.kind === "rect") {
237
110
  return x >= path.x && x <= path.x + path.width && y >= path.y && y <= path.y + path.height;
@@ -244,7 +117,6 @@ function pointInPolygonPath(path, x, y, tolerance) {
244
117
  let crossings = 0;
245
118
  let winding = 0;
246
119
  let subStartX = 0, subStartY = 0;
247
- let curX = 0, curY = 0;
248
120
  let subVerts = [];
249
121
  let subOpen = false;
250
122
  const flushSubpath = (closed) => {
@@ -263,57 +135,52 @@ function pointInPolygonPath(path, x, y, tolerance) {
263
135
  subVerts = [];
264
136
  subOpen = false;
265
137
  };
266
- let ci = 0;
267
- for (let i = 0; i < commands.length; i++) {
268
- const cmd = commands[i];
138
+ forEachSegment(commands, coords, (cmd, ci, curX, curY) => {
269
139
  switch (cmd) {
270
140
  case PATH_M: {
271
141
  if (subOpen) flushSubpath(false);
272
142
  subStartX = coords[ci];
273
143
  subStartY = coords[ci + 1];
274
- curX = subStartX;
275
- curY = subStartY;
276
- subVerts.push(curX, curY);
144
+ subVerts.push(subStartX, subStartY);
277
145
  subOpen = true;
278
- ci += 2;
279
146
  break;
280
147
  }
281
- case PATH_L: {
282
- curX = coords[ci];
283
- curY = coords[ci + 1];
284
- subVerts.push(curX, curY);
285
- ci += 2;
148
+ case PATH_L:
149
+ subVerts.push(coords[ci], coords[ci + 1]);
286
150
  break;
287
- }
288
- case PATH_C: {
289
- const x1 = coords[ci], y1 = coords[ci + 1];
290
- const x2 = coords[ci + 2], y2 = coords[ci + 3];
291
- const x3 = coords[ci + 4], y3 = coords[ci + 5];
292
- flattenCubic(curX, curY, x1, y1, x2, y2, x3, y3, tolerance, subVerts);
293
- curX = x3;
294
- curY = y3;
295
- ci += 6;
151
+ case PATH_C:
152
+ flattenCubic(
153
+ curX,
154
+ curY,
155
+ coords[ci],
156
+ coords[ci + 1],
157
+ coords[ci + 2],
158
+ coords[ci + 3],
159
+ coords[ci + 4],
160
+ coords[ci + 5],
161
+ tolerance,
162
+ subVerts
163
+ );
296
164
  break;
297
- }
298
- case PATH_Q: {
299
- const x1 = coords[ci], y1 = coords[ci + 1];
300
- const x2 = coords[ci + 2], y2 = coords[ci + 3];
301
- flattenQuadratic(curX, curY, x1, y1, x2, y2, tolerance, subVerts);
302
- curX = x2;
303
- curY = y2;
304
- ci += 4;
165
+ case PATH_Q:
166
+ flattenQuadratic(
167
+ curX,
168
+ curY,
169
+ coords[ci],
170
+ coords[ci + 1],
171
+ coords[ci + 2],
172
+ coords[ci + 3],
173
+ tolerance,
174
+ subVerts
175
+ );
305
176
  break;
306
- }
307
- case PATH_Z: {
177
+ case PATH_Z:
308
178
  flushSubpath(true);
309
- curX = subStartX;
310
- curY = subStartY;
311
179
  break;
312
- }
313
180
  default:
314
181
  throw new Error(`pointInPath: unknown command ${cmd}`);
315
182
  }
316
- }
183
+ });
317
184
  if (subOpen) flushSubpath(false);
318
185
  return fillRule === "evenodd" ? (crossings & 1) === 1 : winding !== 0;
319
186
  }
@@ -334,7 +201,6 @@ function polylineWithinThreshold(path, px, py, t2, tolerance) {
334
201
  const { commands, coords } = path;
335
202
  if (commands.length === 0) return false;
336
203
  let subStartX = 0, subStartY = 0;
337
- let curX = 0, curY = 0;
338
204
  let subVerts = [];
339
205
  let subOpen = false;
340
206
  const checkSegments = (closed) => {
@@ -346,62 +212,66 @@ function polylineWithinThreshold(path, px, py, t2, tolerance) {
346
212
  }
347
213
  return false;
348
214
  };
349
- let ci = 0;
350
- for (let i = 0; i < commands.length; i++) {
351
- const cmd = commands[i];
215
+ let hit = false;
216
+ forEachSegment(commands, coords, (cmd, ci, curX, curY) => {
352
217
  switch (cmd) {
353
218
  case PATH_M: {
354
219
  if (subOpen) {
355
- if (checkSegments(false)) return true;
220
+ if (checkSegments(false)) {
221
+ hit = true;
222
+ return false;
223
+ }
356
224
  subVerts = [];
357
225
  }
358
226
  subStartX = coords[ci];
359
227
  subStartY = coords[ci + 1];
360
- curX = subStartX;
361
- curY = subStartY;
362
- subVerts.push(curX, curY);
228
+ subVerts.push(subStartX, subStartY);
363
229
  subOpen = true;
364
- ci += 2;
365
230
  break;
366
231
  }
367
- case PATH_L: {
368
- curX = coords[ci];
369
- curY = coords[ci + 1];
370
- subVerts.push(curX, curY);
371
- ci += 2;
232
+ case PATH_L:
233
+ subVerts.push(coords[ci], coords[ci + 1]);
372
234
  break;
373
- }
374
- case PATH_C: {
375
- const x1 = coords[ci], y1 = coords[ci + 1];
376
- const x2 = coords[ci + 2], y2 = coords[ci + 3];
377
- const x3 = coords[ci + 4], y3 = coords[ci + 5];
378
- flattenCubic(curX, curY, x1, y1, x2, y2, x3, y3, tolerance, subVerts);
379
- curX = x3;
380
- curY = y3;
381
- ci += 6;
235
+ case PATH_C:
236
+ flattenCubic(
237
+ curX,
238
+ curY,
239
+ coords[ci],
240
+ coords[ci + 1],
241
+ coords[ci + 2],
242
+ coords[ci + 3],
243
+ coords[ci + 4],
244
+ coords[ci + 5],
245
+ tolerance,
246
+ subVerts
247
+ );
382
248
  break;
383
- }
384
- case PATH_Q: {
385
- const x1 = coords[ci], y1 = coords[ci + 1];
386
- const x2 = coords[ci + 2], y2 = coords[ci + 3];
387
- flattenQuadratic(curX, curY, x1, y1, x2, y2, tolerance, subVerts);
388
- curX = x2;
389
- curY = y2;
390
- ci += 4;
249
+ case PATH_Q:
250
+ flattenQuadratic(
251
+ curX,
252
+ curY,
253
+ coords[ci],
254
+ coords[ci + 1],
255
+ coords[ci + 2],
256
+ coords[ci + 3],
257
+ tolerance,
258
+ subVerts
259
+ );
391
260
  break;
392
- }
393
- case PATH_Z: {
394
- if (checkSegments(true)) return true;
261
+ case PATH_Z:
262
+ if (checkSegments(true)) {
263
+ hit = true;
264
+ return false;
265
+ }
395
266
  subVerts = [];
396
267
  subOpen = false;
397
- curX = subStartX;
398
- curY = subStartY;
399
268
  break;
400
- }
401
269
  default:
402
270
  throw new Error(`strokeHitTest: unknown command ${cmd}`);
403
271
  }
404
- }
272
+ return true;
273
+ });
274
+ if (hit) return true;
405
275
  if (subOpen && checkSegments(false)) return true;
406
276
  return false;
407
277
  }
@@ -609,7 +479,81 @@ function scalePolygon(path, src, dst) {
609
479
  return transformPath(path, m);
610
480
  }
611
481
 
612
- // src/interactions/actions/resize/geometry.ts
482
+ // src/core/geometry/unionBounds.ts
483
+ function unionBounds(poses) {
484
+ let minX = Infinity;
485
+ let minY = Infinity;
486
+ let maxX = -Infinity;
487
+ let maxY = -Infinity;
488
+ let any = false;
489
+ for (const p of poses) {
490
+ any = true;
491
+ if (p.x < minX) minX = p.x;
492
+ if (p.y < minY) minY = p.y;
493
+ const right = p.x + p.width;
494
+ const bottom = p.y + p.height;
495
+ if (right > maxX) maxX = right;
496
+ if (bottom > maxY) maxY = bottom;
497
+ }
498
+ if (!any) return null;
499
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
500
+ }
501
+ function axisAlignedBounds(b) {
502
+ const rotation = b.rotation;
503
+ if (!rotation) {
504
+ return { x: b.x, y: b.y, width: b.width, height: b.height };
505
+ }
506
+ const cos = Math.cos(rotation);
507
+ const sin = Math.sin(rotation);
508
+ const cx = b.x + b.width / 2;
509
+ const cy = b.y + b.height / 2;
510
+ let minX = Infinity;
511
+ let minY = Infinity;
512
+ let maxX = -Infinity;
513
+ let maxY = -Infinity;
514
+ const corners = [
515
+ [b.x, b.y],
516
+ [b.x + b.width, b.y],
517
+ [b.x + b.width, b.y + b.height],
518
+ [b.x, b.y + b.height]
519
+ ];
520
+ for (const [px, py] of corners) {
521
+ const dx = px - cx;
522
+ const dy = py - cy;
523
+ const rx = cx + dx * cos - dy * sin;
524
+ const ry = cy + dx * sin + dy * cos;
525
+ if (rx < minX) minX = rx;
526
+ if (rx > maxX) maxX = rx;
527
+ if (ry < minY) minY = ry;
528
+ if (ry > maxY) maxY = ry;
529
+ }
530
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
531
+ }
532
+ function unionAABB(parts) {
533
+ let minX = Infinity;
534
+ let minY = Infinity;
535
+ let maxX = -Infinity;
536
+ let maxY = -Infinity;
537
+ let any = false;
538
+ for (const part of parts) {
539
+ if (!part) continue;
540
+ const b = axisAlignedBounds(part);
541
+ any = true;
542
+ if (b.x < minX) minX = b.x;
543
+ if (b.y < minY) minY = b.y;
544
+ const right = b.x + b.width;
545
+ const bottom = b.y + b.height;
546
+ if (right > maxX) maxX = right;
547
+ if (bottom > maxY) maxY = bottom;
548
+ }
549
+ if (!any) return null;
550
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
551
+ }
552
+
553
+ // src/core/geometry/poseDescriptor.ts
554
+ function poseDescriptorForNode(descriptor, node) {
555
+ return descriptor.forNode?.(node) ?? descriptor;
556
+ }
613
557
  function aabbIntersectsRect(b, r) {
614
558
  return b.x < r.x + r.width && b.x + b.width > r.x && b.y < r.y + r.height && b.y + b.height > r.y;
615
559
  }
@@ -626,6 +570,7 @@ var RECT_POSE_DESCRIPTOR = {
626
570
  height: p.height * sy
627
571
  };
628
572
  },
573
+ fromBounds: (b) => ({ x: b.x, y: b.y, width: b.width, height: b.height }),
629
574
  translate: (p, dx, dy) => ({ ...p, x: p.x + dx, y: p.y + dy }),
630
575
  intersectsRect: (p, r) => aabbIntersectsRect(p, r),
631
576
  lerp: (a, b, t) => ({
@@ -634,7 +579,8 @@ var RECT_POSE_DESCRIPTOR = {
634
579
  y: a.y + (b.y - a.y) * t,
635
580
  width: a.width + (b.width - a.width) * t,
636
581
  height: a.height + (b.height - a.height) * t
637
- })
582
+ }),
583
+ withRotation: (p, rotation) => ({ ...p, rotation })
638
584
  };
639
585
  var ROTATED_POSE_DESCRIPTOR = {
640
586
  getBounds: RECT_POSE_DESCRIPTOR.getBounds,
@@ -642,7 +588,9 @@ var ROTATED_POSE_DESCRIPTOR = {
642
588
  translate: RECT_POSE_DESCRIPTOR.translate,
643
589
  intersectsRect: RECT_POSE_DESCRIPTOR.intersectsRect,
644
590
  lerp: RECT_POSE_DESCRIPTOR.lerp,
645
- getRotation: (p) => p.rotation
591
+ fromBounds: (b) => ({ x: b.x, y: b.y, width: b.width, height: b.height, rotation: 0 }),
592
+ getRotation: (p) => p.rotation,
593
+ withRotation: (p, rotation) => ({ ...p, rotation })
646
594
  };
647
595
  function remapRotatedLeaf(pose, src, dst) {
648
596
  const sx = src.width === 0 ? 1 : dst.width / src.width;
@@ -666,22 +614,24 @@ function remapRotatedLeaf(pose, src, dst) {
666
614
  rotation
667
615
  };
668
616
  }
617
+ function visualBoundsViaDescriptor(pose, geometry) {
618
+ const b = geometry.getBounds(pose);
619
+ const rotation = geometry.getRotation?.(pose) ?? b.rotation ?? 0;
620
+ return axisAlignedBounds({ x: b.x, y: b.y, width: b.width, height: b.height, rotation });
621
+ }
622
+ function translatePoseViaDescriptor(pose, dx, dy, geometry) {
623
+ if (geometry.translate) return geometry.translate(pose, dx, dy);
624
+ const src = geometry.getBounds(pose);
625
+ const dst = { x: src.x + dx, y: src.y + dy, width: src.width, height: src.height };
626
+ return geometry.remapBounds(pose, src, dst);
627
+ }
669
628
  var pathPoseDescriptor = {
670
629
  getBounds: (path) => boundsOfPath(path),
671
- remapBounds: (path, src, dst) => {
672
- const sx = src.width === 0 ? 0 : dst.width / src.width;
673
- const sy = src.height === 0 ? 0 : dst.height / src.height;
674
- if (path.kind === "rect") {
675
- return {
676
- kind: "rect",
677
- x: dst.x + (path.x - src.x) * sx,
678
- y: dst.y + (path.y - src.y) * sy,
679
- width: path.width * sx,
680
- height: path.height * sy
681
- };
682
- }
683
- return remapPolygon(path, src, dst, sx, sy);
684
- },
630
+ remapBounds: (path, src, dst) => transformPath(
631
+ path,
632
+ boxToBox(src.x, src.y, src.width, src.height, dst.x, dst.y, dst.width, dst.height)
633
+ ),
634
+ fromBounds: (b) => ({ kind: "rect", x: b.x, y: b.y, width: b.width, height: b.height }),
685
635
  translate: (path, dx, dy) => translatePath(path, dx, dy),
686
636
  // WHY: AABB pre-test is cheap; only fall through to per-corner pointInPath
687
637
  // when the rect is fully inside the AABB (silhouette test).
@@ -718,25 +668,20 @@ var pathPoseDescriptor = {
718
668
  // so the rotate cursor doesn't appear without a working interaction.
719
669
  supportsRotation: () => false
720
670
  };
721
- function remapPolygon(path, src, dst, sx, sy) {
722
- const next = new Float32Array(path.coords.length);
723
- const { commands, coords } = path;
724
- forEachSegment(commands, coords, (cmd, ci) => {
725
- for (let k = 0, len = pathCommandCoordCount(cmd); k < len; k += 2) {
726
- next[ci + k] = dst.x + (coords[ci + k] - src.x) * sx;
727
- next[ci + k + 1] = dst.y + (coords[ci + k + 1] - src.y) * sy;
728
- }
729
- });
730
- return { kind: "polygon", commands: path.commands, coords: next, fillRule: path.fillRule };
731
- }
732
671
 
733
672
  // src/interactions/actions/resize/autoPoseDescriptor.ts
734
673
  function isPathLike(p) {
735
674
  return !!p && typeof p === "object" && "kind" in p && (p.kind === "polygon" || p.kind === "rect");
736
675
  }
676
+ function isRectPose(p) {
677
+ if (!p || typeof p !== "object") return false;
678
+ const r = p;
679
+ return typeof r.x === "number" && typeof r.y === "number" && typeof r.width === "number" && typeof r.height === "number";
680
+ }
737
681
  var AUTO_POSE_DESCRIPTOR = {
738
682
  getBounds: (p) => isPathLike(p) ? pathPoseDescriptor.getBounds(p) : RECT_POSE_DESCRIPTOR.getBounds(p),
739
683
  remapBounds: (p, src, dst) => isPathLike(p) ? pathPoseDescriptor.remapBounds(p, src, dst) : RECT_POSE_DESCRIPTOR.remapBounds(p, src, dst),
684
+ fromBounds: (b, template) => isPathLike(template) ? pathPoseDescriptor.fromBounds(b, template) : RECT_POSE_DESCRIPTOR.fromBounds(b, template),
740
685
  translate: (p, dx, dy) => isPathLike(p) ? pathPoseDescriptor.translate(p, dx, dy) : RECT_POSE_DESCRIPTOR.translate(p, dx, dy),
741
686
  intersectsRect: (p, rect) => isPathLike(p) ? pathPoseDescriptor.intersectsRect(p, rect) : RECT_POSE_DESCRIPTOR.intersectsRect(p, rect),
742
687
  getRotation: (p) => {
@@ -748,7 +693,8 @@ var AUTO_POSE_DESCRIPTOR = {
748
693
  // Everything else flows through `wrapWithPoseRotation`'s x/y/w/h gate at
749
694
  // paint time, so report `true` and let the wrapper no-op for poses
750
695
  // missing AABB fields.
751
- supportsRotation: (p) => !isPathLike(p)
696
+ supportsRotation: (p) => !isPathLike(p),
697
+ withRotation: (p, rotation) => isPathLike(p) ? p : { ...p, rotation }
752
698
  };
753
699
 
754
700
  // src/interactions/gestures/shared/strategies/grid.ts
@@ -797,11 +743,10 @@ function pointToGridCell(point, spacing, unitSystem, origin = { x: 0, y: 0 }) {
797
743
  }
798
744
 
799
745
  // src/core/viewport/pxExtent.ts
800
- var MIN_SCALE = 1e-9;
801
746
  function pxExtent(px, scale) {
802
747
  return {
803
- x: px / Math.max(MIN_SCALE, Math.abs(scale.x)),
804
- y: px / Math.max(MIN_SCALE, Math.abs(scale.y))
748
+ x: px / Math.abs(scale.x),
749
+ y: px / Math.abs(scale.y)
805
750
  };
806
751
  }
807
752
  function scaleDelta(dx, dy, scale) {
@@ -858,6 +803,6 @@ function guideSnapStrategy(getGuides, options = {}) {
858
803
  };
859
804
  }
860
805
 
861
- export { AUTO_POSE_DESCRIPTOR, DEFAULT_FLATTEN_TOLERANCE, DEFAULT_GUIDE_TOLERANCE_PX, IMPERIAL_INCHES, METRIC_MM, PIXELS, PathBuilder, RECT_ORIGIN_PROJECTION, RECT_POSE_DESCRIPTOR, ROTATED_POSE_DESCRIPTOR, boundsOfPath, ellipsePath, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, formatUnit, gridSnapStrategy, guideSnapStrategy, isPathLike, linePath, pathPoseDescriptor, pointInPath, pointToGridCell, polygonFromPoints, polylineFromPoints, pxExtent, rectPath, regularPolygonPath, remapRotatedLeaf, resolveUnit, scaleDelta, scalePathToBounds, starPath, strokeHitTest, transformPath, translatePath, translatePolygonInPlace, withinPxBox, withinPxRadius };
862
- //# sourceMappingURL=chunk-WPM42WJP.js.map
863
- //# sourceMappingURL=chunk-WPM42WJP.js.map
806
+ export { ANGLE_RADIANS, AUTO_POSE_DESCRIPTOR, DEFAULT_GUIDE_TOLERANCE_PX, IMPERIAL_INCHES, METRIC_MM, PIXELS, PathBuilder, RECT_ORIGIN_PROJECTION, RECT_POSE_DESCRIPTOR, ROTATED_POSE_DESCRIPTOR, aabbIntersectsRect, axisAlignedBounds, boundsOfPath, ellipsePath, formatUnit, gridSnapStrategy, guideSnapStrategy, isPathLike, isRectPose, linePath, pathPoseDescriptor, pointInPath, pointToGridCell, polygonFromPoints, polylineFromPoints, poseDescriptorForNode, pxExtent, rectPath, regularPolygonPath, remapRotatedLeaf, resolveUnit, scaleDelta, scalePathToBounds, starPath, strokeHitTest, transformPath, translatePath, translatePolygonInPlace, translatePoseViaDescriptor, unionAABB, unionBounds, visualBoundsViaDescriptor, withinPxBox, withinPxRadius };
807
+ //# sourceMappingURL=chunk-UCPV7JXC.js.map
808
+ //# sourceMappingURL=chunk-UCPV7JXC.js.map