@myoc/element 0.19.518 → 0.19.520

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 (67) hide show
  1. package/dist/dev/index.js +1768 -987
  2. package/dist/dev/index.js.map +4 -4
  3. package/dist/prod/index.js +15 -15
  4. package/dist/types/common/src/colors.d.ts +1 -1
  5. package/dist/types/common/src/constants.d.ts +8 -5
  6. package/dist/types/common/src/utils.d.ts +0 -42
  7. package/dist/types/element/src/bounds.d.ts +18 -1
  8. package/dist/types/element/src/comparisons.d.ts +1 -0
  9. package/dist/types/element/src/image.d.ts +5 -0
  10. package/dist/types/element/src/newElement.d.ts +2 -0
  11. package/dist/types/element/src/types.d.ts +8 -0
  12. package/dist/types/element/src/visualdebug.d.ts +1 -2
  13. package/dist/types/excalidraw/actions/actionBoundText.d.ts +6 -2
  14. package/dist/types/excalidraw/actions/actionCanvas.d.ts +33 -11
  15. package/dist/types/excalidraw/actions/actionClipboard.d.ts +6 -2
  16. package/dist/types/excalidraw/actions/actionCropEditor.d.ts +3 -1
  17. package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +9 -3
  18. package/dist/types/excalidraw/actions/actionDeselect.d.ts +3 -1
  19. package/dist/types/excalidraw/actions/actionElementLink.d.ts +3 -1
  20. package/dist/types/excalidraw/actions/actionElementLock.d.ts +6 -2
  21. package/dist/types/excalidraw/actions/actionEmbeddable.d.ts +3 -1
  22. package/dist/types/excalidraw/actions/actionExport.d.ts +6 -2
  23. package/dist/types/excalidraw/actions/actionFrame.d.ts +14 -4
  24. package/dist/types/excalidraw/actions/actionGroup.d.ts +6 -2
  25. package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +5 -1
  26. package/dist/types/excalidraw/actions/actionLink.d.ts +3 -1
  27. package/dist/types/excalidraw/actions/actionMenu.d.ts +3 -1
  28. package/dist/types/excalidraw/actions/actionProperties.d.ts +18 -5
  29. package/dist/types/excalidraw/actions/actionSelectAll.d.ts +3 -1
  30. package/dist/types/excalidraw/actions/actionStyles.d.ts +3 -1
  31. package/dist/types/excalidraw/actions/actionToggleArrowBinding.d.ts +3 -1
  32. package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +3 -1
  33. package/dist/types/excalidraw/actions/actionToggleMidpointSnapping.d.ts +3 -1
  34. package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +3 -1
  35. package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +3 -1
  36. package/dist/types/excalidraw/actions/actionToggleStats.d.ts +3 -1
  37. package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +5 -3
  38. package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +3 -1
  39. package/dist/types/excalidraw/actions/index.d.ts +1 -1
  40. package/dist/types/excalidraw/actions/types.d.ts +1 -1
  41. package/dist/types/excalidraw/appState.d.ts +2 -1
  42. package/dist/types/excalidraw/components/App.d.ts +13 -28
  43. package/dist/types/excalidraw/components/ColorPicker/colorPickerUtils.d.ts +1 -1
  44. package/dist/types/excalidraw/components/ConvertElementTypePopup.d.ts +1 -1
  45. package/dist/types/excalidraw/components/EyeDropper.d.ts +1 -1
  46. package/dist/types/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.d.ts +1 -1
  47. package/dist/types/excalidraw/components/SearchMenu.d.ts +1 -1
  48. package/dist/types/excalidraw/components/Sidebar/Sidebar.d.ts +1 -1
  49. package/dist/types/excalidraw/components/canvases/StaticCanvas.d.ts +2 -1
  50. package/dist/types/excalidraw/components/icons.d.ts +2 -0
  51. package/dist/types/excalidraw/components/main-menu/DefaultItems.d.ts +7 -4
  52. package/dist/types/excalidraw/data/blob.d.ts +3 -1
  53. package/dist/types/excalidraw/data/json.d.ts +3 -1
  54. package/dist/types/excalidraw/renderer/animation.d.ts +1 -0
  55. package/dist/types/excalidraw/scene/Renderer.d.ts +2 -0
  56. package/dist/types/excalidraw/scene/index.d.ts +1 -1
  57. package/dist/types/excalidraw/scene/types.d.ts +1 -0
  58. package/dist/types/excalidraw/scroll.d.ts +46 -0
  59. package/dist/types/excalidraw/types.d.ts +24 -3
  60. package/dist/types/laser-pointer/src/index.d.ts +2 -0
  61. package/dist/types/laser-pointer/src/math.d.ts +16 -0
  62. package/dist/types/laser-pointer/src/simplify.d.ts +2 -0
  63. package/dist/types/laser-pointer/src/state.d.ts +35 -0
  64. package/dist/types/utils/src/index.d.ts +1 -2
  65. package/package.json +5 -4
  66. package/dist/types/utils/src/bbox.d.ts +0 -9
  67. package/dist/types/utils/src/withinBounds.d.ts +0 -19
package/dist/dev/index.js CHANGED
@@ -1832,9 +1832,9 @@ init_define_import_meta_env();
1832
1832
  function rotatePoints(points, center, degrees) {
1833
1833
  if (points && points.length) {
1834
1834
  const [cx, cy] = center;
1835
- const angle = Math.PI / 180 * degrees;
1836
- const cos = Math.cos(angle);
1837
- const sin = Math.sin(angle);
1835
+ const angle2 = Math.PI / 180 * degrees;
1836
+ const cos = Math.cos(angle2);
1837
+ const sin = Math.sin(angle2);
1838
1838
  for (const p of points) {
1839
1839
  const [x, y] = p;
1840
1840
  p[0] = (x - cx) * cos - (y - cy) * sin + cx;
@@ -1851,21 +1851,21 @@ function areSamePoints(p1, p2) {
1851
1851
  return p1[0] === p2[0] && p1[1] === p2[1];
1852
1852
  }
1853
1853
  function hachureLines(polygons, hachureGap, hachureAngle, hachureStepOffset = 1) {
1854
- const angle = hachureAngle;
1854
+ const angle2 = hachureAngle;
1855
1855
  const gap = Math.max(hachureGap, 0.1);
1856
1856
  const polygonList = polygons[0] && polygons[0][0] && typeof polygons[0][0] === "number" ? [polygons] : polygons;
1857
1857
  const rotationCenter = [0, 0];
1858
- if (angle) {
1858
+ if (angle2) {
1859
1859
  for (const polygon3 of polygonList) {
1860
- rotatePoints(polygon3, rotationCenter, angle);
1860
+ rotatePoints(polygon3, rotationCenter, angle2);
1861
1861
  }
1862
1862
  }
1863
1863
  const lines = straightHachureLines(polygonList, gap, hachureStepOffset);
1864
- if (angle) {
1864
+ if (angle2) {
1865
1865
  for (const polygon3 of polygonList) {
1866
- rotatePoints(polygon3, rotationCenter, -angle);
1866
+ rotatePoints(polygon3, rotationCenter, -angle2);
1867
1867
  }
1868
- rotateLines(lines, rotationCenter, -angle);
1868
+ rotateLines(lines, rotationCenter, -angle2);
1869
1869
  }
1870
1870
  return lines;
1871
1871
  }
@@ -1976,7 +1976,7 @@ function straightHachureLines(polygons, gap, hachureStepOffset) {
1976
1976
  // ../../node_modules/roughjs/bin/fillers/scan-line-hachure.js
1977
1977
  function polygonHachureLines(polygonList, o) {
1978
1978
  var _a;
1979
- const angle = o.hachureAngle + 90;
1979
+ const angle2 = o.hachureAngle + 90;
1980
1980
  let gap = o.hachureGap;
1981
1981
  if (gap < 0) {
1982
1982
  gap = o.strokeWidth * 4;
@@ -1988,7 +1988,7 @@ function polygonHachureLines(polygonList, o) {
1988
1988
  skipOffset = gap;
1989
1989
  }
1990
1990
  }
1991
- return hachureLines(polygonList, gap, angle, skipOffset || 1);
1991
+ return hachureLines(polygonList, gap, angle2, skipOffset || 1);
1992
1992
  }
1993
1993
 
1994
1994
  // ../../node_modules/roughjs/bin/fillers/hachure-filler.js
@@ -2526,7 +2526,7 @@ function normalize(segments) {
2526
2526
  case "A": {
2527
2527
  const r1 = Math.abs(data[0]);
2528
2528
  const r2 = Math.abs(data[1]);
2529
- const angle = data[2];
2529
+ const angle2 = data[2];
2530
2530
  const largeArcFlag = data[3];
2531
2531
  const sweepFlag = data[4];
2532
2532
  const x = data[5];
@@ -2537,7 +2537,7 @@ function normalize(segments) {
2537
2537
  cy = y;
2538
2538
  } else {
2539
2539
  if (cx !== x || cy !== y) {
2540
- const curves = arcToCubicCurves(cx, cy, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
2540
+ const curves = arcToCubicCurves(cx, cy, x, y, r1, r2, angle2, largeArcFlag, sweepFlag);
2541
2541
  curves.forEach(function(curve4) {
2542
2542
  out.push({ key: "C", data: curve4 });
2543
2543
  });
@@ -2565,8 +2565,8 @@ function rotate(x, y, angleRad) {
2565
2565
  const Y = x * Math.sin(angleRad) + y * Math.cos(angleRad);
2566
2566
  return [X, Y];
2567
2567
  }
2568
- function arcToCubicCurves(x1, y1, x2, y2, r1, r2, angle, largeArcFlag, sweepFlag, recursive) {
2569
- const angleRad = degToRad(angle);
2568
+ function arcToCubicCurves(x1, y1, x2, y2, r1, r2, angle2, largeArcFlag, sweepFlag, recursive) {
2569
+ const angleRad = degToRad(angle2);
2570
2570
  let params = [];
2571
2571
  let f1 = 0, f2 = 0, cx = 0, cy = 0;
2572
2572
  if (recursive) {
@@ -2623,7 +2623,7 @@ function arcToCubicCurves(x1, y1, x2, y2, r1, r2, angle, largeArcFlag, sweepFlag
2623
2623
  }
2624
2624
  x2 = cx + r1 * Math.cos(f2);
2625
2625
  y2 = cy + r2 * Math.sin(f2);
2626
- params = arcToCubicCurves(x2, y2, x2old, y2old, r1, r2, angle, 0, sweepFlag, [f2, f2old, cx, cy]);
2626
+ params = arcToCubicCurves(x2, y2, x2old, y2old, r1, r2, angle2, 0, sweepFlag, [f2, f2old, cx, cy]);
2627
2627
  }
2628
2628
  df = f2 - f1;
2629
2629
  const c1 = Math.cos(f1);
@@ -2829,8 +2829,8 @@ function patternFillArc(x, y, width, height, start2, stop2, o) {
2829
2829
  }
2830
2830
  const increment = (stp - strt) / o.curveStepCount;
2831
2831
  const points = [];
2832
- for (let angle = strt; angle <= stp; angle = angle + increment) {
2833
- points.push([cx + rx * Math.cos(angle), cy + ry * Math.sin(angle)]);
2832
+ for (let angle2 = strt; angle2 <= stp; angle2 = angle2 + increment) {
2833
+ points.push([cx + rx * Math.cos(angle2), cy + ry * Math.sin(angle2)]);
2834
2834
  }
2835
2835
  points.push([cx + rx * Math.cos(stp), cy + ry * Math.sin(stp)]);
2836
2836
  points.push([cx, cy]);
@@ -3016,10 +3016,10 @@ function _computeEllipsePoints(increment, cx, cy, rx, ry, offset, overlap, o) {
3016
3016
  cx + rx * Math.cos(-increment),
3017
3017
  cy + ry * Math.sin(-increment)
3018
3018
  ]);
3019
- for (let angle = 0; angle <= Math.PI * 2; angle = angle + increment) {
3019
+ for (let angle2 = 0; angle2 <= Math.PI * 2; angle2 = angle2 + increment) {
3020
3020
  const p = [
3021
- cx + rx * Math.cos(angle),
3022
- cy + ry * Math.sin(angle)
3021
+ cx + rx * Math.cos(angle2),
3022
+ cy + ry * Math.sin(angle2)
3023
3023
  ];
3024
3024
  corePoints.push(p);
3025
3025
  allPoints.push(p);
@@ -3039,10 +3039,10 @@ function _computeEllipsePoints(increment, cx, cy, rx, ry, offset, overlap, o) {
3039
3039
  _offsetOpt(offset, o) + cy + 0.9 * ry * Math.sin(radOffset - increment)
3040
3040
  ]);
3041
3041
  const endAngle = Math.PI * 2 + radOffset - 0.01;
3042
- for (let angle = radOffset; angle < endAngle; angle = angle + increment) {
3042
+ for (let angle2 = radOffset; angle2 < endAngle; angle2 = angle2 + increment) {
3043
3043
  const p = [
3044
- _offsetOpt(offset, o) + cx + rx * Math.cos(angle),
3045
- _offsetOpt(offset, o) + cy + ry * Math.sin(angle)
3044
+ _offsetOpt(offset, o) + cx + rx * Math.cos(angle2),
3045
+ _offsetOpt(offset, o) + cy + ry * Math.sin(angle2)
3046
3046
  ];
3047
3047
  corePoints.push(p);
3048
3048
  allPoints.push(p);
@@ -3069,10 +3069,10 @@ function _arc(increment, cx, cy, rx, ry, strt, stp, offset, o) {
3069
3069
  _offsetOpt(offset, o) + cx + 0.9 * rx * Math.cos(radOffset - increment),
3070
3070
  _offsetOpt(offset, o) + cy + 0.9 * ry * Math.sin(radOffset - increment)
3071
3071
  ]);
3072
- for (let angle = radOffset; angle <= stp; angle = angle + increment) {
3072
+ for (let angle2 = radOffset; angle2 <= stp; angle2 = angle2 + increment) {
3073
3073
  points.push([
3074
- _offsetOpt(offset, o) + cx + rx * Math.cos(angle),
3075
- _offsetOpt(offset, o) + cy + ry * Math.sin(angle)
3074
+ _offsetOpt(offset, o) + cx + rx * Math.cos(angle2),
3075
+ _offsetOpt(offset, o) + cy + ry * Math.sin(angle2)
3076
3076
  ]);
3077
3077
  }
3078
3078
  points.push([
@@ -3869,11 +3869,11 @@ import {
3869
3869
  } from "@excalidraw/common";
3870
3870
  import {
3871
3871
  degreesToRadians,
3872
- lineSegment as lineSegment7,
3872
+ lineSegment as lineSegment6,
3873
3873
  pointDistance as pointDistance7,
3874
- pointFrom as pointFrom14,
3874
+ pointFrom as pointFrom13,
3875
3875
  pointFromArray as pointFromArray3,
3876
- pointRotateRads as pointRotateRads13
3876
+ pointRotateRads as pointRotateRads12
3877
3877
  } from "@excalidraw/math";
3878
3878
 
3879
3879
  // ../utils/src/shape.ts
@@ -3898,24 +3898,24 @@ import {
3898
3898
  } from "@excalidraw/math";
3899
3899
  import { getElementAbsoluteCoords } from "@excalidraw/element";
3900
3900
  var getPolygonShape = (element) => {
3901
- const { angle, width, height, x, y } = element;
3901
+ const { angle: angle2, width, height, x, y } = element;
3902
3902
  const cx = x + width / 2;
3903
3903
  const cy = y + height / 2;
3904
3904
  const center = pointFrom(cx, cy);
3905
3905
  let data;
3906
3906
  if (element.type === "diamond") {
3907
3907
  data = polygon2(
3908
- pointRotateRads(pointFrom(cx, y), center, angle),
3909
- pointRotateRads(pointFrom(x + width, cy), center, angle),
3910
- pointRotateRads(pointFrom(cx, y + height), center, angle),
3911
- pointRotateRads(pointFrom(x, cy), center, angle)
3908
+ pointRotateRads(pointFrom(cx, y), center, angle2),
3909
+ pointRotateRads(pointFrom(x + width, cy), center, angle2),
3910
+ pointRotateRads(pointFrom(cx, y + height), center, angle2),
3911
+ pointRotateRads(pointFrom(x, cy), center, angle2)
3912
3912
  );
3913
3913
  } else {
3914
3914
  data = polygon2(
3915
- pointRotateRads(pointFrom(x, y), center, angle),
3916
- pointRotateRads(pointFrom(x + width, y), center, angle),
3917
- pointRotateRads(pointFrom(x + width, y + height), center, angle),
3918
- pointRotateRads(pointFrom(x, y + height), center, angle)
3915
+ pointRotateRads(pointFrom(x, y), center, angle2),
3916
+ pointRotateRads(pointFrom(x + width, y), center, angle2),
3917
+ pointRotateRads(pointFrom(x + width, y + height), center, angle2),
3918
+ pointRotateRads(pointFrom(x, y + height), center, angle2)
3919
3919
  );
3920
3920
  }
3921
3921
  return {
@@ -3924,12 +3924,12 @@ var getPolygonShape = (element) => {
3924
3924
  };
3925
3925
  };
3926
3926
  var getEllipseShape = (element) => {
3927
- const { width, height, angle, x, y } = element;
3927
+ const { width, height, angle: angle2, x, y } = element;
3928
3928
  return {
3929
3929
  type: "ellipse",
3930
3930
  data: {
3931
3931
  center: pointFrom(x + width / 2, y + height / 2),
3932
- angle,
3932
+ angle: angle2,
3933
3933
  halfWidth: width / 2,
3934
3934
  halfHeight: height / 2
3935
3935
  }
@@ -4213,11 +4213,367 @@ function ae(e, t = {}) {
4213
4213
  return ce(me(e, t), t);
4214
4214
  }
4215
4215
 
4216
+ // ../laser-pointer/src/index.ts
4217
+ init_define_import_meta_env();
4218
+
4219
+ // ../laser-pointer/src/state.ts
4220
+ init_define_import_meta_env();
4221
+
4222
+ // ../laser-pointer/src/math.ts
4223
+ init_define_import_meta_env();
4224
+ function add([ax, ay, ar], [bx, by, br]) {
4225
+ return [ax + bx, ay + by, ar + br];
4226
+ }
4227
+ function sub([ax, ay, ar], [bx, by, br]) {
4228
+ return [ax - bx, ay - by, ar - br];
4229
+ }
4230
+ function smul([x, y, r], s) {
4231
+ return [x * s, y * s, r * s];
4232
+ }
4233
+ function norm([x, y, r]) {
4234
+ return [x / Math.sqrt(x ** 2 + y ** 2), y / Math.sqrt(x ** 2 + y ** 2), r];
4235
+ }
4236
+ function rot([x, y, r], rad) {
4237
+ return [
4238
+ Math.cos(rad) * x - Math.sin(rad) * y,
4239
+ Math.sin(rad) * x + Math.cos(rad) * y,
4240
+ r
4241
+ ];
4242
+ }
4243
+ function plerp(a2, b2, t) {
4244
+ return add(a2, smul(sub(b2, a2), t));
4245
+ }
4246
+ function angle(p, p1, p2) {
4247
+ return Math.atan2(p2[1] - p[1], p2[0] - p[0]) - Math.atan2(p1[1] - p[1], p1[0] - p[0]);
4248
+ }
4249
+ function normAngle(a2) {
4250
+ return Math.atan2(Math.sin(a2), Math.cos(a2));
4251
+ }
4252
+ function mag([x, y]) {
4253
+ return Math.sqrt(x ** 2 + y ** 2);
4254
+ }
4255
+ function dist([ax, ay], [bx, by]) {
4256
+ return Math.sqrt((bx - ax) ** 2 + (by - ay) ** 2);
4257
+ }
4258
+ function runLength(ps) {
4259
+ if (ps.length < 2) {
4260
+ return 0;
4261
+ }
4262
+ let len = 0;
4263
+ for (let i = 1; i <= ps.length - 1; i++) {
4264
+ len += dist(ps[i - 1], ps[i]);
4265
+ }
4266
+ len += dist(ps[ps.length - 2], ps[ps.length - 1]);
4267
+ return len;
4268
+ }
4269
+ var clamp = (v, min, max) => Math.max(min, Math.min(max, v));
4270
+ function distancePointToSegment(p3, p1, p2) {
4271
+ const sMag = dist(p1, p2);
4272
+ if (sMag === 0) {
4273
+ return dist(p3, p1);
4274
+ }
4275
+ const u = clamp(
4276
+ ((p3[0] - p1[0]) * (p2[0] - p1[0]) + (p3[1] - p1[1]) * (p2[1] - p1[1])) / sMag ** 2,
4277
+ 0,
4278
+ 1
4279
+ );
4280
+ const pi = [
4281
+ p1[0] + u * (p2[0] - p1[0]),
4282
+ p1[1] + u * (p2[1] - p1[1]),
4283
+ p3[2]
4284
+ ];
4285
+ return dist(pi, p3);
4286
+ }
4287
+
4288
+ // ../laser-pointer/src/simplify.ts
4289
+ init_define_import_meta_env();
4290
+ function douglasPeucker(points, epsilon) {
4291
+ if (epsilon === 0) {
4292
+ return points;
4293
+ }
4294
+ if (points.length <= 2) {
4295
+ return points;
4296
+ }
4297
+ const first = points[0];
4298
+ const last = points[points.length - 1];
4299
+ const [maxDistance, maxIndex] = points.reduce(
4300
+ ([maxDistance2, maxIndex2], point, index) => {
4301
+ const distance3 = distancePointToSegment(point, first, last);
4302
+ return distance3 > maxDistance2 ? [distance3, index] : [maxDistance2, maxIndex2];
4303
+ },
4304
+ [0, -1]
4305
+ );
4306
+ if (maxDistance >= epsilon) {
4307
+ const maxIndexPoint = points[maxIndex];
4308
+ return [
4309
+ ...douglasPeucker(
4310
+ [first, ...points.slice(1, maxIndex), maxIndexPoint],
4311
+ epsilon
4312
+ ).slice(0, -1),
4313
+ maxIndexPoint,
4314
+ ...douglasPeucker(
4315
+ [maxIndexPoint, ...points.slice(maxIndex, -1), last],
4316
+ epsilon
4317
+ ).slice(1)
4318
+ ];
4319
+ }
4320
+ return [first, last];
4321
+ }
4322
+
4323
+ // ../laser-pointer/src/state.ts
4324
+ var LaserPointer = class _LaserPointer {
4325
+ static defaults = {
4326
+ size: 2,
4327
+ streamline: 0.45,
4328
+ simplify: 0.1,
4329
+ simplifyPhase: "output",
4330
+ keepHead: false,
4331
+ sizeMapping: () => 1
4332
+ };
4333
+ static constants = {
4334
+ cornerDetectionMaxAngle: 75,
4335
+ cornerDetectionVariance: (s) => s > 35 ? 0.5 : 1,
4336
+ maxTailLength: 50
4337
+ };
4338
+ options;
4339
+ constructor(options) {
4340
+ this.options = Object.assign({}, _LaserPointer.defaults, options);
4341
+ }
4342
+ originalPoints = [];
4343
+ stablePoints = [];
4344
+ tailPoints = [];
4345
+ isFresh = true;
4346
+ get lastPoint() {
4347
+ return this.tailPoints[this.tailPoints.length - 1] ?? this.stablePoints[this.stablePoints.length - 1];
4348
+ }
4349
+ addPoint(point) {
4350
+ const lastPoint = this.originalPoints[this.originalPoints.length - 1];
4351
+ if (lastPoint && lastPoint[0] === point[0] && lastPoint[1] === point[1]) {
4352
+ return;
4353
+ }
4354
+ this.originalPoints.push(point);
4355
+ if (this.isFresh) {
4356
+ this.isFresh = false;
4357
+ this.stablePoints.push(point);
4358
+ return;
4359
+ }
4360
+ if (this.options.streamline > 0) {
4361
+ point = plerp(this.lastPoint, point, 1 - this.options.streamline);
4362
+ }
4363
+ this.tailPoints.push(point);
4364
+ if (runLength(this.tailPoints) > _LaserPointer.constants.maxTailLength) {
4365
+ this.stabilizeTail();
4366
+ }
4367
+ }
4368
+ close() {
4369
+ this.stabilizeTail();
4370
+ }
4371
+ stabilizeTail() {
4372
+ if (this.options.simplify > 0 && this.options.simplifyPhase === "tail") {
4373
+ throw new Error("Not implemented yet");
4374
+ } else {
4375
+ this.stablePoints.push(...this.tailPoints);
4376
+ this.tailPoints = [];
4377
+ }
4378
+ }
4379
+ getSize(sizeOverride, pressure, index, totalLength, runningLength) {
4380
+ return (sizeOverride ?? this.options.size) * this.options.sizeMapping({
4381
+ pressure,
4382
+ runningLength,
4383
+ currentIndex: index,
4384
+ totalLength
4385
+ });
4386
+ }
4387
+ getStrokeOutline(sizeOverride) {
4388
+ if (this.isFresh) {
4389
+ return [];
4390
+ }
4391
+ let points = [...this.stablePoints, ...this.tailPoints];
4392
+ if (this.options.simplify > 0 && this.options.simplifyPhase === "input") {
4393
+ points = douglasPeucker(points, this.options.simplify);
4394
+ }
4395
+ const len = points.length;
4396
+ if (len === 0) {
4397
+ return [];
4398
+ }
4399
+ if (len === 1) {
4400
+ const c = points[0];
4401
+ const size = this.getSize(sizeOverride, c[2], 0, len, 0);
4402
+ if (size < 0.5) {
4403
+ return [];
4404
+ }
4405
+ const ps = [];
4406
+ for (let theta = 0; theta <= Math.PI * 2; theta += Math.PI / 16) {
4407
+ ps.push(add(c, smul(rot([1, 0, 0], theta), size)));
4408
+ }
4409
+ ps.push(
4410
+ add(
4411
+ c,
4412
+ smul(
4413
+ [1, 0, 0],
4414
+ this.getSize(sizeOverride, c[2], 0, len, 0)
4415
+ )
4416
+ )
4417
+ );
4418
+ return ps;
4419
+ }
4420
+ if (len === 2) {
4421
+ const c = points[0];
4422
+ const n = points[1];
4423
+ const cSize = this.getSize(sizeOverride, c[2], 0, len, 0);
4424
+ const nSize = this.getSize(sizeOverride, n[2], 0, len, 0);
4425
+ if (cSize < 0.5 || nSize < 0.5) {
4426
+ return [];
4427
+ }
4428
+ const ps = [];
4429
+ const pAngle = angle(c, [c[0], c[1] - 100, c[2]], n);
4430
+ for (let theta = pAngle; theta <= Math.PI + pAngle; theta += Math.PI / 16) {
4431
+ ps.push(add(c, smul(rot([1, 0, 0], theta), cSize)));
4432
+ }
4433
+ for (let theta = Math.PI + pAngle; theta <= Math.PI * 2 + pAngle; theta += Math.PI / 16) {
4434
+ ps.push(add(n, smul(rot([1, 0, 0], theta), nSize)));
4435
+ }
4436
+ ps.push(ps[0]);
4437
+ return ps;
4438
+ }
4439
+ const forwardPoints = [];
4440
+ const backwardPoints = [];
4441
+ let speed = 0;
4442
+ let prevSpeed = 0;
4443
+ let visibleStartIndex = 0;
4444
+ let runningLength = 0;
4445
+ for (let i = 1; i < len - 1; i++) {
4446
+ const p = points[i - 1];
4447
+ const c = points[i];
4448
+ const n = points[i + 1];
4449
+ const pressure = c[2];
4450
+ const d = dist(p, c);
4451
+ runningLength += d;
4452
+ speed = prevSpeed + (d - prevSpeed) * 0.2;
4453
+ const cSize = this.getSize(sizeOverride, pressure, i, len, runningLength);
4454
+ if (cSize === 0) {
4455
+ visibleStartIndex = i + 1;
4456
+ continue;
4457
+ }
4458
+ const dirPC = norm(sub(p, c));
4459
+ const dirNC = norm(sub(n, c));
4460
+ const p1dirPC = rot(dirPC, Math.PI / 2);
4461
+ const p2dirPC = rot(dirPC, -Math.PI / 2);
4462
+ const p1dirNC = rot(dirNC, Math.PI / 2);
4463
+ const p2dirNC = rot(dirNC, -Math.PI / 2);
4464
+ const p1PC = add(c, smul(p1dirPC, cSize));
4465
+ const p2PC = add(c, smul(p2dirPC, cSize));
4466
+ const p1NC = add(c, smul(p1dirNC, cSize));
4467
+ const p2NC = add(c, smul(p2dirNC, cSize));
4468
+ const ftdir = add(p1dirPC, p2dirNC);
4469
+ const btdir = add(p2dirPC, p1dirNC);
4470
+ const paPC = add(
4471
+ c,
4472
+ smul(mag(ftdir) === 0 ? dirPC : norm(ftdir), cSize)
4473
+ );
4474
+ const paNC = add(
4475
+ c,
4476
+ smul(mag(btdir) === 0 ? dirNC : norm(btdir), cSize)
4477
+ );
4478
+ const cAngle = normAngle(angle(c, p, n));
4479
+ const D_ANGLE = _LaserPointer.constants.cornerDetectionMaxAngle / 180 * Math.PI * _LaserPointer.constants.cornerDetectionVariance(speed);
4480
+ if (Math.abs(cAngle) < D_ANGLE) {
4481
+ const tAngle = Math.abs(normAngle(Math.PI - cAngle));
4482
+ if (tAngle === 0) {
4483
+ continue;
4484
+ }
4485
+ if (cAngle < 0) {
4486
+ backwardPoints.push(p2PC, paNC);
4487
+ for (let theta = 0; theta <= tAngle; theta += tAngle / 4) {
4488
+ forwardPoints.push(add(c, rot(smul(p1dirPC, cSize), theta)));
4489
+ }
4490
+ for (let theta = tAngle; theta >= 0; theta -= tAngle / 4) {
4491
+ backwardPoints.push(add(c, rot(smul(p1dirPC, cSize), theta)));
4492
+ }
4493
+ backwardPoints.push(paNC, p1NC);
4494
+ } else {
4495
+ forwardPoints.push(p1PC, paPC);
4496
+ for (let theta = 0; theta <= tAngle; theta += tAngle / 4) {
4497
+ backwardPoints.push(
4498
+ add(c, rot(smul(p1dirPC, -cSize), -theta))
4499
+ );
4500
+ }
4501
+ for (let theta = tAngle; theta >= 0; theta -= tAngle / 4) {
4502
+ forwardPoints.push(
4503
+ add(c, rot(smul(p1dirPC, -cSize), -theta))
4504
+ );
4505
+ }
4506
+ forwardPoints.push(paPC, p2NC);
4507
+ }
4508
+ } else {
4509
+ forwardPoints.push(paPC);
4510
+ backwardPoints.push(paNC);
4511
+ }
4512
+ prevSpeed = speed;
4513
+ }
4514
+ if (visibleStartIndex >= len - 2) {
4515
+ if (this.options.keepHead) {
4516
+ const c = points[len - 1];
4517
+ const ps = [];
4518
+ for (let theta = 0; theta <= Math.PI * 2; theta += Math.PI / 16) {
4519
+ ps.push(
4520
+ add(
4521
+ c,
4522
+ smul(rot([1, 0, 0], theta), this.options.size)
4523
+ )
4524
+ );
4525
+ }
4526
+ ps.push(add(c, smul([1, 0, 0], this.options.size)));
4527
+ return ps;
4528
+ }
4529
+ return [];
4530
+ }
4531
+ const first = points[visibleStartIndex];
4532
+ const second = points[visibleStartIndex + 1];
4533
+ const penultimate = points[len - 2];
4534
+ const ultimate = points[len - 1];
4535
+ const dirFS = norm(sub(second, first));
4536
+ const dirPU = norm(sub(penultimate, ultimate));
4537
+ const ppdirFS = rot(dirFS, -Math.PI / 2);
4538
+ const ppdirPU = rot(dirPU, Math.PI / 2);
4539
+ const startCapSize = this.getSize(sizeOverride, first[2], 0, len, 0);
4540
+ const startCap = [];
4541
+ const endCapSize = this.options.keepHead ? this.options.size : this.getSize(sizeOverride, penultimate[2], len - 2, len, runningLength);
4542
+ const endCap = [];
4543
+ if (startCapSize > 0.1) {
4544
+ for (let theta = 0; theta <= Math.PI; theta += Math.PI / 16) {
4545
+ startCap.unshift(
4546
+ add(first, rot(smul(ppdirFS, startCapSize), -theta))
4547
+ );
4548
+ }
4549
+ startCap.unshift(add(first, smul(ppdirFS, -startCapSize)));
4550
+ } else {
4551
+ startCap.push(first);
4552
+ }
4553
+ for (let theta = 0; theta <= Math.PI * 3; theta += Math.PI / 16) {
4554
+ endCap.push(add(ultimate, rot(smul(ppdirPU, -endCapSize), -theta)));
4555
+ }
4556
+ const strokeOutline = [
4557
+ ...startCap,
4558
+ ...forwardPoints,
4559
+ ...endCap.reverse(),
4560
+ ...backwardPoints.reverse()
4561
+ ];
4562
+ if (startCap.length > 0) {
4563
+ strokeOutline.push(startCap[0]);
4564
+ }
4565
+ if (this.options.simplify > 0 && this.options.simplifyPhase === "output") {
4566
+ return douglasPeucker(strokeOutline, this.options.simplify);
4567
+ }
4568
+ return strokeOutline;
4569
+ }
4570
+ };
4571
+
4216
4572
  // src/shape.ts
4217
4573
  import {
4218
- pointFrom as pointFrom13,
4574
+ pointFrom as pointFrom12,
4219
4575
  pointDistance as pointDistance6,
4220
- pointRotateRads as pointRotateRads12
4576
+ pointRotateRads as pointRotateRads11
4221
4577
  } from "@excalidraw/math";
4222
4578
  import {
4223
4579
  ROUGHNESS,
@@ -4226,16 +4582,17 @@ import {
4226
4582
  assertNever as assertNever2,
4227
4583
  COLOR_PALETTE,
4228
4584
  LINE_POLYGON_POINT_MERGE_DISTANCE,
4229
- applyDarkModeFilter as applyDarkModeFilter2
4585
+ applyDarkModeFilter as applyDarkModeFilter2,
4586
+ DEFAULT_STROKE_STREAMLINE
4230
4587
  } from "@excalidraw/common";
4231
4588
 
4232
4589
  // src/renderElement.ts
4233
4590
  init_define_import_meta_env();
4234
4591
  import {
4235
4592
  isRightAngleRads,
4236
- lineSegment as lineSegment6,
4237
- pointFrom as pointFrom12,
4238
- pointRotateRads as pointRotateRads11
4593
+ lineSegment as lineSegment5,
4594
+ pointFrom as pointFrom11,
4595
+ pointRotateRads as pointRotateRads10
4239
4596
  } from "@excalidraw/math";
4240
4597
  import {
4241
4598
  BOUND_TEXT_PADDING as BOUND_TEXT_PADDING3,
@@ -4243,7 +4600,7 @@ import {
4243
4600
  ELEMENT_READY_TO_ERASE_OPACITY,
4244
4601
  FRAME_STYLE,
4245
4602
  DARK_THEME_FILTER,
4246
- MIME_TYPES,
4603
+ MIME_TYPES as MIME_TYPES2,
4247
4604
  THEME,
4248
4605
  distance as distance2,
4249
4606
  getFontString as getFontString3,
@@ -4266,7 +4623,7 @@ import {
4266
4623
  vectorAdd as vectorAdd2,
4267
4624
  vectorScale as vectorScale2,
4268
4625
  pointFromVector as pointFromVector2,
4269
- clamp,
4626
+ clamp as clamp2,
4270
4627
  isCloseTo
4271
4628
  } from "@excalidraw/math";
4272
4629
  var MINIMAL_CROP_SIZE = 10;
@@ -4300,7 +4657,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4300
4657
  let changeInHeight = pointerY - element.y;
4301
4658
  let changeInWidth = pointerX - element.x;
4302
4659
  if (transformHandle.includes("n")) {
4303
- nextHeight = clamp(
4660
+ nextHeight = clamp2(
4304
4661
  element.height - changeInHeight,
4305
4662
  MINIMAL_CROP_SIZE,
4306
4663
  isFlippedByY ? uncroppedHeight - croppedTop : element.height + croppedTop
@@ -4308,7 +4665,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4308
4665
  }
4309
4666
  if (transformHandle.includes("s")) {
4310
4667
  changeInHeight = pointerY - element.y - element.height;
4311
- nextHeight = clamp(
4668
+ nextHeight = clamp2(
4312
4669
  element.height + changeInHeight,
4313
4670
  MINIMAL_CROP_SIZE,
4314
4671
  isFlippedByY ? element.height + croppedTop : uncroppedHeight - croppedTop
@@ -4316,14 +4673,14 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4316
4673
  }
4317
4674
  if (transformHandle.includes("e")) {
4318
4675
  changeInWidth = pointerX - element.x - element.width;
4319
- nextWidth = clamp(
4676
+ nextWidth = clamp2(
4320
4677
  element.width + changeInWidth,
4321
4678
  MINIMAL_CROP_SIZE,
4322
4679
  isFlippedByX ? element.width + croppedLeft : uncroppedWidth - croppedLeft
4323
4680
  );
4324
4681
  }
4325
4682
  if (transformHandle.includes("w")) {
4326
- nextWidth = clamp(
4683
+ nextWidth = clamp2(
4327
4684
  element.width - changeInWidth,
4328
4685
  MINIMAL_CROP_SIZE,
4329
4686
  isFlippedByX ? uncroppedWidth - croppedLeft : element.width + croppedLeft
@@ -4363,7 +4720,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4363
4720
  const distanceToLeft = croppedLeft + element.width / 2;
4364
4721
  const distanceToRight = uncroppedWidth - croppedLeft - element.width / 2;
4365
4722
  const MAX_WIDTH = Math.min(distanceToLeft, distanceToRight) * 2;
4366
- nextWidth = clamp(
4723
+ nextWidth = clamp2(
4367
4724
  nextHeight * widthAspectRatio,
4368
4725
  MINIMAL_CROP_SIZE,
4369
4726
  MAX_WIDTH
@@ -4381,7 +4738,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4381
4738
  const distanceToLeft = croppedLeft + element.width / 2;
4382
4739
  const distanceToRight = uncroppedWidth - croppedLeft - element.width / 2;
4383
4740
  const MAX_WIDTH = Math.min(distanceToLeft, distanceToRight) * 2;
4384
- nextWidth = clamp(
4741
+ nextWidth = clamp2(
4385
4742
  nextHeight * widthAspectRatio,
4386
4743
  MINIMAL_CROP_SIZE,
4387
4744
  MAX_WIDTH
@@ -4399,7 +4756,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4399
4756
  const distanceToTop = croppedTop + element.height / 2;
4400
4757
  const distanceToBottom = uncroppedHeight - croppedTop - element.height / 2;
4401
4758
  const MAX_HEIGHT = Math.min(distanceToTop, distanceToBottom) * 2;
4402
- nextHeight = clamp(
4759
+ nextHeight = clamp2(
4403
4760
  nextWidth / widthAspectRatio,
4404
4761
  MINIMAL_CROP_SIZE,
4405
4762
  MAX_HEIGHT
@@ -4417,7 +4774,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4417
4774
  const distanceToTop = croppedTop + element.height / 2;
4418
4775
  const distanceToBottom = uncroppedHeight - croppedTop - element.height / 2;
4419
4776
  const MAX_HEIGHT = Math.min(distanceToTop, distanceToBottom) * 2;
4420
- nextHeight = clamp(
4777
+ nextHeight = clamp2(
4421
4778
  nextWidth / widthAspectRatio,
4422
4779
  MINIMAL_CROP_SIZE,
4423
4780
  MAX_HEIGHT
@@ -4434,7 +4791,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4434
4791
  if (widthAspectRatio) {
4435
4792
  if (changeInWidth > -changeInHeight) {
4436
4793
  const MAX_HEIGHT = isFlippedByY ? uncroppedHeight - croppedTop : croppedTop + element.height;
4437
- nextHeight = clamp(
4794
+ nextHeight = clamp2(
4438
4795
  nextWidth / widthAspectRatio,
4439
4796
  MINIMAL_CROP_SIZE,
4440
4797
  MAX_HEIGHT
@@ -4442,7 +4799,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4442
4799
  nextWidth = nextHeight * widthAspectRatio;
4443
4800
  } else {
4444
4801
  const MAX_WIDTH = isFlippedByX ? croppedLeft + element.width : uncroppedWidth - croppedLeft;
4445
- nextWidth = clamp(
4802
+ nextWidth = clamp2(
4446
4803
  nextHeight * widthAspectRatio,
4447
4804
  MINIMAL_CROP_SIZE,
4448
4805
  MAX_WIDTH
@@ -4457,7 +4814,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4457
4814
  if (widthAspectRatio) {
4458
4815
  if (changeInWidth < changeInHeight) {
4459
4816
  const MAX_HEIGHT = isFlippedByY ? uncroppedHeight - croppedTop : croppedTop + element.height;
4460
- nextHeight = clamp(
4817
+ nextHeight = clamp2(
4461
4818
  nextWidth / widthAspectRatio,
4462
4819
  MINIMAL_CROP_SIZE,
4463
4820
  MAX_HEIGHT
@@ -4465,7 +4822,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4465
4822
  nextWidth = nextHeight * widthAspectRatio;
4466
4823
  } else {
4467
4824
  const MAX_WIDTH = isFlippedByX ? uncroppedWidth - croppedLeft : croppedLeft + element.width;
4468
- nextWidth = clamp(
4825
+ nextWidth = clamp2(
4469
4826
  nextHeight * widthAspectRatio,
4470
4827
  MINIMAL_CROP_SIZE,
4471
4828
  MAX_WIDTH
@@ -4480,7 +4837,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4480
4837
  if (widthAspectRatio) {
4481
4838
  if (changeInWidth > changeInHeight) {
4482
4839
  const MAX_HEIGHT = isFlippedByY ? croppedTop + element.height : uncroppedHeight - croppedTop;
4483
- nextHeight = clamp(
4840
+ nextHeight = clamp2(
4484
4841
  nextWidth / widthAspectRatio,
4485
4842
  MINIMAL_CROP_SIZE,
4486
4843
  MAX_HEIGHT
@@ -4488,7 +4845,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4488
4845
  nextWidth = nextHeight * widthAspectRatio;
4489
4846
  } else {
4490
4847
  const MAX_WIDTH = isFlippedByX ? croppedLeft + element.width : uncroppedWidth - croppedLeft;
4491
- nextWidth = clamp(
4848
+ nextWidth = clamp2(
4492
4849
  nextHeight * widthAspectRatio,
4493
4850
  MINIMAL_CROP_SIZE,
4494
4851
  MAX_WIDTH
@@ -4503,7 +4860,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4503
4860
  if (widthAspectRatio) {
4504
4861
  if (-changeInWidth > changeInHeight) {
4505
4862
  const MAX_HEIGHT = isFlippedByY ? croppedTop + element.height : uncroppedHeight - croppedTop;
4506
- nextHeight = clamp(
4863
+ nextHeight = clamp2(
4507
4864
  nextWidth / widthAspectRatio,
4508
4865
  MINIMAL_CROP_SIZE,
4509
4866
  MAX_HEIGHT
@@ -4511,7 +4868,7 @@ var cropElement = (element, elementsMap, transformHandle, naturalWidth, naturalH
4511
4868
  nextWidth = nextHeight * widthAspectRatio;
4512
4869
  } else {
4513
4870
  const MAX_WIDTH = isFlippedByX ? uncroppedWidth - croppedLeft : croppedLeft + element.width;
4514
- nextWidth = clamp(
4871
+ nextWidth = clamp2(
4515
4872
  nextHeight * widthAspectRatio,
4516
4873
  MINIMAL_CROP_SIZE,
4517
4874
  MAX_WIDTH
@@ -4579,17 +4936,17 @@ var recomputeOrigin = (stateAtCropStart, transformHandle, width, height, shouldM
4579
4936
  newTopLeft[1] = startCenter[1] - newBoundsHeight / 2;
4580
4937
  }
4581
4938
  }
4582
- const angle = stateAtCropStart.angle;
4583
- const rotatedTopLeft = pointRotateRads2(newTopLeft, startCenter, angle);
4939
+ const angle2 = stateAtCropStart.angle;
4940
+ const rotatedTopLeft = pointRotateRads2(newTopLeft, startCenter, angle2);
4584
4941
  const newCenter = [
4585
4942
  newTopLeft[0] + Math.abs(newBoundsWidth) / 2,
4586
4943
  newTopLeft[1] + Math.abs(newBoundsHeight) / 2
4587
4944
  ];
4588
- const rotatedNewCenter = pointRotateRads2(newCenter, startCenter, angle);
4945
+ const rotatedNewCenter = pointRotateRads2(newCenter, startCenter, angle2);
4589
4946
  newTopLeft = pointRotateRads2(
4590
4947
  rotatedTopLeft,
4591
4948
  rotatedNewCenter,
4592
- -angle
4949
+ -angle2
4593
4950
  );
4594
4951
  const newOrigin = [...newTopLeft];
4595
4952
  newOrigin[0] += stateAtCropStart.x - newBoundsX1;
@@ -4716,11 +5073,11 @@ var getFlipAdjustedCropPosition = (element, natural = false) => {
4716
5073
  init_define_import_meta_env();
4717
5074
  import {
4718
5075
  pointCenter as pointCenter2,
4719
- pointFrom as pointFrom11,
4720
- pointRotateRads as pointRotateRads10,
5076
+ pointFrom as pointFrom10,
5077
+ pointRotateRads as pointRotateRads9,
4721
5078
  pointsEqual as pointsEqual6,
4722
5079
  pointDistance as pointDistance5,
4723
- vectorFromPoint as vectorFromPoint9,
5080
+ vectorFromPoint as vectorFromPoint8,
4724
5081
  curveLength,
4725
5082
  curvePointAtLength
4726
5083
  } from "@excalidraw/math";
@@ -4744,7 +5101,7 @@ import {
4744
5101
  } from "@excalidraw/common";
4745
5102
  import {
4746
5103
  PRECISION as PRECISION2,
4747
- clamp as clamp3,
5104
+ clamp as clamp4,
4748
5105
  lineSegment as lineSegment4,
4749
5106
  pointDistance as pointDistance4,
4750
5107
  pointDistanceSq,
@@ -6290,8 +6647,8 @@ var computeBoundTextPosition = (container, boundTextElement, elementsMap) => {
6290
6647
  } else {
6291
6648
  x = containerCoords.x + (maxContainerWidth / 2 - boundTextElement.width / 2);
6292
6649
  }
6293
- const angle = container.angle ?? 0;
6294
- if (angle !== 0) {
6650
+ const angle2 = container.angle ?? 0;
6651
+ if (angle2 !== 0) {
6295
6652
  const contentCenter = pointFrom4(
6296
6653
  containerCoords.x + maxContainerWidth / 2,
6297
6654
  containerCoords.y + maxContainerHeight / 2
@@ -6300,7 +6657,7 @@ var computeBoundTextPosition = (container, boundTextElement, elementsMap) => {
6300
6657
  x + boundTextElement.width / 2,
6301
6658
  y + boundTextElement.height / 2
6302
6659
  );
6303
- const [rx, ry] = pointRotateRads4(textCenter, contentCenter, angle);
6660
+ const [rx, ry] = pointRotateRads4(textCenter, contentCenter, angle2);
6304
6661
  return {
6305
6662
  x: rx - boundTextElement.width / 2,
6306
6663
  y: ry - boundTextElement.height / 2
@@ -6557,6 +6914,7 @@ var hasBackground = (type) => type === "rectangle" || type === "iframe" || type
6557
6914
  var hasStrokeColor = (type) => type === "rectangle" || type === "ellipse" || type === "diamond" || type === "freedraw" || type === "arrow" || type === "line" || type === "text" || type === "embeddable";
6558
6915
  var hasStrokeWidth = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "freedraw" || type === "arrow" || type === "line";
6559
6916
  var hasStrokeStyle = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "arrow" || type === "line";
6917
+ var hasFreedrawMode = (type) => type === "freedraw";
6560
6918
  var canChangeRoundness = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "line" || type === "diamond" || type === "image";
6561
6919
  var toolIsArrow = (type) => type === "arrow";
6562
6920
  var canHaveArrowheads = (type) => type === "arrow";
@@ -6625,8 +6983,8 @@ var hitElementItself = ({
6625
6983
  cachedHit = result;
6626
6984
  return result;
6627
6985
  };
6628
- var isPointInRotatedBounds = (point, bounds, angle, tolerance = 0) => {
6629
- const adjustedPoint = angle === 0 ? point : pointRotateRads6(point, getCenterForBounds(bounds), -angle);
6986
+ var isPointInRotatedBounds = (point, bounds, angle2, tolerance = 0) => {
6987
+ const adjustedPoint = angle2 === 0 ? point : pointRotateRads6(point, getCenterForBounds(bounds), -angle2);
6630
6988
  return isPointWithinBounds(
6631
6989
  pointFrom5(bounds[0] - tolerance, bounds[1] - tolerance),
6632
6990
  adjustedPoint,
@@ -6802,7 +7160,7 @@ var intersectElementWithLineSegment = (element, elementsMap, line2, offset = 0,
6802
7160
  );
6803
7161
  }
6804
7162
  };
6805
- var curveIntersections = (curves, segment, intersections, center, angle, onlyFirst = false) => {
7163
+ var curveIntersections = (curves, segment, intersections, center, angle2, onlyFirst = false) => {
6806
7164
  for (const c of curves) {
6807
7165
  const b1 = getCubicBezierCurveBound(c[0], c[1], c[2], c[3]);
6808
7166
  const b2 = [
@@ -6817,7 +7175,7 @@ var curveIntersections = (curves, segment, intersections, center, angle, onlyFir
6817
7175
  const hits = curveIntersectLineSegment(c, segment);
6818
7176
  if (hits.length > 0) {
6819
7177
  for (const j of hits) {
6820
- intersections.push(pointRotateRads6(j, center, angle));
7178
+ intersections.push(pointRotateRads6(j, center, angle2));
6821
7179
  }
6822
7180
  if (onlyFirst) {
6823
7181
  return intersections;
@@ -6826,11 +7184,11 @@ var curveIntersections = (curves, segment, intersections, center, angle, onlyFir
6826
7184
  }
6827
7185
  return intersections;
6828
7186
  };
6829
- var lineIntersections = (lines, segment, intersections, center, angle, onlyFirst = false) => {
7187
+ var lineIntersections = (lines, segment, intersections, center, angle2, onlyFirst = false) => {
6830
7188
  for (const l2 of lines) {
6831
7189
  const intersection = lineSegmentIntersectionPoints2(l2, segment);
6832
7190
  if (intersection) {
6833
- intersections.push(pointRotateRads6(intersection, center, angle));
7191
+ intersections.push(pointRotateRads6(intersection, center, angle2));
6834
7192
  if (onlyFirst) {
6835
7193
  return intersections;
6836
7194
  }
@@ -6976,7 +7334,7 @@ var isPointInElement = (point, element, elementsMap) => {
6976
7334
  };
6977
7335
  var isBindableElementInsideOtherBindable = (innerElement, outerElement, elementsMap) => {
6978
7336
  const getCornerPoints = (element, offset2) => {
6979
- const { x, y, width, height, angle } = element;
7337
+ const { x, y, width, height, angle: angle2 } = element;
6980
7338
  const center = elementCenterPoint(element, elementsMap);
6981
7339
  if (element.type === "diamond") {
6982
7340
  const [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY] = getDiamondPoints(element);
@@ -6990,7 +7348,7 @@ var isBindableElementInsideOtherBindable = (innerElement, outerElement, elements
6990
7348
  pointFrom5(x + leftX - offset2, y + leftY)
6991
7349
  // left
6992
7350
  ];
6993
- return corners2.map((corner) => pointRotateRads6(corner, center, angle));
7351
+ return corners2.map((corner) => pointRotateRads6(corner, center, angle2));
6994
7352
  }
6995
7353
  if (element.type === "ellipse") {
6996
7354
  const cx = x + width / 2;
@@ -7007,7 +7365,7 @@ var isBindableElementInsideOtherBindable = (innerElement, outerElement, elements
7007
7365
  pointFrom5(cx - rx - offset2, cy)
7008
7366
  // left
7009
7367
  ];
7010
- return corners2.map((corner) => pointRotateRads6(corner, center, angle));
7368
+ return corners2.map((corner) => pointRotateRads6(corner, center, angle2));
7011
7369
  }
7012
7370
  const corners = [
7013
7371
  pointFrom5(x - offset2, y - offset2),
@@ -7019,7 +7377,7 @@ var isBindableElementInsideOtherBindable = (innerElement, outerElement, elements
7019
7377
  pointFrom5(x - offset2, y + height + offset2)
7020
7378
  // bottom-left
7021
7379
  ];
7022
- return corners.map((corner) => pointRotateRads6(corner, center, angle));
7380
+ return corners.map((corner) => pointRotateRads6(corner, center, angle2));
7023
7381
  };
7024
7382
  const offset = -1 * Math.max(innerElement.width, innerElement.height) / 20;
7025
7383
  const innerCorners = getCornerPoints(innerElement, offset);
@@ -7245,7 +7603,7 @@ import {
7245
7603
  // src/elbowArrow.ts
7246
7604
  init_define_import_meta_env();
7247
7605
  import {
7248
- clamp as clamp2,
7606
+ clamp as clamp3,
7249
7607
  pointDistance as pointDistance3,
7250
7608
  pointFrom as pointFrom7,
7251
7609
  pointScaleFromOrigin as pointScaleFromOrigin2,
@@ -8589,12 +8947,12 @@ var normalizeArrowElementUpdate = (global2, nextFixedSegments, startIsSpecial, e
8589
8947
  );
8590
8948
  }
8591
8949
  points = points.map(
8592
- ([x, y]) => pointFrom7(clamp2(x, -1e6, 1e6), clamp2(y, -1e6, 1e6))
8950
+ ([x, y]) => pointFrom7(clamp3(x, -1e6, 1e6), clamp3(y, -1e6, 1e6))
8593
8951
  );
8594
8952
  return {
8595
8953
  points,
8596
- x: clamp2(offsetX, -1e6, 1e6),
8597
- y: clamp2(offsetY, -1e6, 1e6),
8954
+ x: clamp3(offsetX, -1e6, 1e6),
8955
+ y: clamp3(offsetY, -1e6, 1e6),
8598
8956
  fixedSegments: (nextFixedSegments?.length ?? 0) > 0 ? nextFixedSegments : null,
8599
8957
  ...getSizeFromPoints(points),
8600
8958
  startIsSpecial,
@@ -8806,7 +9164,7 @@ var getBindingGap = (bindTarget, opts) => {
8806
9164
  var maxBindingDistance_simple = (zoom) => {
8807
9165
  const BASE_BINDING_DISTANCE = Math.max(BASE_BINDING_GAP, 15);
8808
9166
  const zoomValue = zoom?.value && zoom.value < 1 ? zoom.value : 1;
8809
- return clamp3(
9167
+ return clamp4(
8810
9168
  // reducing zoom impact so that the diff between binding distance and
8811
9169
  // binding gap is kept to minimum when possible
8812
9170
  BASE_BINDING_DISTANCE / (zoomValue * 1.5),
@@ -9118,10 +9476,12 @@ var getBindingStrategyForDraggingBindingElementEndpoints_simple = (arrow, draggi
9118
9476
  const endDragged = draggingPoints.has(endIdx);
9119
9477
  let start2 = { mode: void 0 };
9120
9478
  let end = { mode: void 0 };
9121
- invariant7(
9122
- arrow.points.length > 1,
9123
- "Do not attempt to bind linear elements with a single point"
9124
- );
9479
+ if (arrow.points.length < 2) {
9480
+ console.error(
9481
+ "Attempting to bind a linear element with less than 2 points"
9482
+ );
9483
+ return { start: { mode: void 0 }, end: { mode: void 0 } };
9484
+ }
9125
9485
  if (!startDragged && !endDragged) {
9126
9486
  return { start: start2, end };
9127
9487
  }
@@ -9282,10 +9642,12 @@ var getBindingStrategyForDraggingBindingElementEndpoints_complex = (arrow, dragg
9282
9642
  const endDragged = draggingPoints.has(endIdx);
9283
9643
  let start2 = { mode: void 0 };
9284
9644
  let end = { mode: void 0 };
9285
- invariant7(
9286
- arrow.points.length > 1,
9287
- "Do not attempt to bind linear elements with a single point"
9288
- );
9645
+ if (arrow.points.length < 2) {
9646
+ console.error(
9647
+ "Attempting to bind a linear element with less than 2 points"
9648
+ );
9649
+ return { start: { mode: void 0 }, end: { mode: void 0 } };
9650
+ }
9289
9651
  if (!startDragged && !endDragged) {
9290
9652
  return { start: start2, end };
9291
9653
  }
@@ -9770,12 +10132,12 @@ var avoidRectangularCorner = (arrowElement, bindTarget, elementsMap, p) => {
9770
10132
  return p;
9771
10133
  };
9772
10134
  var snapToMid = (bindTarget, elementsMap, p, tolerance = 0.05, arrowElement) => {
9773
- const { x, y, width, height, angle } = bindTarget;
10135
+ const { x, y, width, height, angle: angle2 } = bindTarget;
9774
10136
  const center = elementCenterPoint(bindTarget, elementsMap, -0.1, -0.1);
9775
- const nonRotated = pointRotateRads8(p, center, -angle);
10137
+ const nonRotated = pointRotateRads8(p, center, -angle2);
9776
10138
  const bindingGap = arrowElement ? getBindingGap(bindTarget, arrowElement) : 0;
9777
- const verticalThreshold = clamp3(tolerance * height, 5, 80);
9778
- const horizontalThreshold = clamp3(tolerance * width, 5, 80);
10139
+ const verticalThreshold = clamp4(tolerance * height, 5, 80);
10140
+ const horizontalThreshold = clamp4(tolerance * width, 5, 80);
9779
10141
  if (pointDistance4(center, nonRotated) < bindingGap) {
9780
10142
  return void 0;
9781
10143
  }
@@ -9783,25 +10145,25 @@ var snapToMid = (bindTarget, elementsMap, p, tolerance = 0.05, arrowElement) =>
9783
10145
  return pointRotateRads8(
9784
10146
  pointFrom8(x - bindingGap, center[1]),
9785
10147
  center,
9786
- angle
10148
+ angle2
9787
10149
  );
9788
10150
  } else if (nonRotated[1] <= y + height / 2 && nonRotated[0] > center[0] - horizontalThreshold && nonRotated[0] < center[0] + horizontalThreshold) {
9789
10151
  return pointRotateRads8(
9790
10152
  pointFrom8(center[0], y - bindingGap),
9791
10153
  center,
9792
- angle
10154
+ angle2
9793
10155
  );
9794
10156
  } else if (nonRotated[0] >= x + width / 2 && nonRotated[1] > center[1] - verticalThreshold && nonRotated[1] < center[1] + verticalThreshold) {
9795
10157
  return pointRotateRads8(
9796
10158
  pointFrom8(x + width + bindingGap, center[1]),
9797
10159
  center,
9798
- angle
10160
+ angle2
9799
10161
  );
9800
10162
  } else if (nonRotated[1] >= y + height / 2 && nonRotated[0] > center[0] - horizontalThreshold && nonRotated[0] < center[0] + horizontalThreshold) {
9801
10163
  return pointRotateRads8(
9802
10164
  pointFrom8(center[0], y + height + bindingGap),
9803
10165
  center,
9804
- angle
10166
+ angle2
9805
10167
  );
9806
10168
  } else if (bindTarget.type === "diamond") {
9807
10169
  const distance3 = bindingGap;
@@ -9822,16 +10184,16 @@ var snapToMid = (bindTarget, elementsMap, p, tolerance = 0.05, arrowElement) =>
9822
10184
  y + 3 * height / 4 + distance3
9823
10185
  );
9824
10186
  if (pointDistance4(topLeft, nonRotated) < Math.max(horizontalThreshold, verticalThreshold)) {
9825
- return pointRotateRads8(topLeft, center, angle);
10187
+ return pointRotateRads8(topLeft, center, angle2);
9826
10188
  }
9827
10189
  if (pointDistance4(topRight, nonRotated) < Math.max(horizontalThreshold, verticalThreshold)) {
9828
- return pointRotateRads8(topRight, center, angle);
10190
+ return pointRotateRads8(topRight, center, angle2);
9829
10191
  }
9830
10192
  if (pointDistance4(bottomLeft, nonRotated) < Math.max(horizontalThreshold, verticalThreshold)) {
9831
- return pointRotateRads8(bottomLeft, center, angle);
10193
+ return pointRotateRads8(bottomLeft, center, angle2);
9832
10194
  }
9833
10195
  if (pointDistance4(bottomRight, nonRotated) < Math.max(horizontalThreshold, verticalThreshold)) {
9834
- return pointRotateRads8(bottomRight, center, angle);
10196
+ return pointRotateRads8(bottomRight, center, angle2);
9835
10197
  }
9836
10198
  }
9837
10199
  return void 0;
@@ -10338,10 +10700,10 @@ var normalizeFixedPoint = (fixedPoint) => {
10338
10700
  if (!isFixedPoint(fixedPoint)) {
10339
10701
  return [0.5001, 0.5001];
10340
10702
  }
10341
- const EPSILON2 = 1e-4;
10342
- if (Math.abs(fixedPoint[0] - 0.5) < EPSILON2 || Math.abs(fixedPoint[1] - 0.5) < EPSILON2) {
10703
+ const EPSILON = 1e-4;
10704
+ if (Math.abs(fixedPoint[0] - 0.5) < EPSILON || Math.abs(fixedPoint[1] - 0.5) < EPSILON) {
10343
10705
  return fixedPoint.map(
10344
- (ratio) => Math.abs(ratio - 0.5) < EPSILON2 ? 0.5001 : ratio
10706
+ (ratio) => Math.abs(ratio - 0.5) < EPSILON ? 0.5001 : ratio
10345
10707
  );
10346
10708
  }
10347
10709
  return fixedPoint;
@@ -10401,11 +10763,11 @@ var getShapeSideAdaptive = (fixedPoint, shapeType) => {
10401
10763
  const [x, y] = fixedPoint;
10402
10764
  const centerX = x - 0.5;
10403
10765
  const centerY = y - 0.5;
10404
- let angle = Math.atan2(centerY, centerX);
10405
- if (angle < 0) {
10406
- angle += 2 * Math.PI;
10766
+ let angle2 = Math.atan2(centerY, centerX);
10767
+ if (angle2 < 0) {
10768
+ angle2 += 2 * Math.PI;
10407
10769
  }
10408
- const degrees = angle * 180 / Math.PI;
10770
+ const degrees = angle2 * 180 / Math.PI;
10409
10771
  const config = SHAPE_CONFIGS[shapeType];
10410
10772
  const boundaries = getSectorBoundaries(config);
10411
10773
  for (const boundary of boundaries) {
@@ -10560,33 +10922,33 @@ var getBindingSideMidPoint = (binding, elementsMap) => {
10560
10922
  break;
10561
10923
  }
10562
10924
  case "top-right": {
10563
- const angle = -Math.PI / 4;
10564
- const ellipseX = radiusX * Math.cos(angle);
10565
- const ellipseY = radiusY * Math.sin(angle);
10925
+ const angle2 = -Math.PI / 4;
10926
+ const ellipseX = radiusX * Math.cos(angle2);
10927
+ const ellipseY = radiusY * Math.sin(angle2);
10566
10928
  x = ellipseCenterX + ellipseX + OFFSET * 0.707;
10567
10929
  y = ellipseCenterY + ellipseY - OFFSET * 0.707;
10568
10930
  break;
10569
10931
  }
10570
10932
  case "bottom-right": {
10571
- const angle = Math.PI / 4;
10572
- const ellipseX = radiusX * Math.cos(angle);
10573
- const ellipseY = radiusY * Math.sin(angle);
10933
+ const angle2 = Math.PI / 4;
10934
+ const ellipseX = radiusX * Math.cos(angle2);
10935
+ const ellipseY = radiusY * Math.sin(angle2);
10574
10936
  x = ellipseCenterX + ellipseX + OFFSET * 0.707;
10575
10937
  y = ellipseCenterY + ellipseY + OFFSET * 0.707;
10576
10938
  break;
10577
10939
  }
10578
10940
  case "bottom-left": {
10579
- const angle = 3 * Math.PI / 4;
10580
- const ellipseX = radiusX * Math.cos(angle);
10581
- const ellipseY = radiusY * Math.sin(angle);
10941
+ const angle2 = 3 * Math.PI / 4;
10942
+ const ellipseX = radiusX * Math.cos(angle2);
10943
+ const ellipseY = radiusY * Math.sin(angle2);
10582
10944
  x = ellipseCenterX + ellipseX - OFFSET * 0.707;
10583
10945
  y = ellipseCenterY + ellipseY + OFFSET * 0.707;
10584
10946
  break;
10585
10947
  }
10586
10948
  case "top-left": {
10587
- const angle = -3 * Math.PI / 4;
10588
- const ellipseX = radiusX * Math.cos(angle);
10589
- const ellipseY = radiusY * Math.sin(angle);
10949
+ const angle2 = -3 * Math.PI / 4;
10950
+ const ellipseX = radiusX * Math.cos(angle2);
10951
+ const ellipseY = radiusY * Math.sin(angle2);
10590
10952
  x = ellipseCenterX + ellipseX - OFFSET * 0.707;
10591
10953
  y = ellipseCenterY + ellipseY - OFFSET * 0.707;
10592
10954
  break;
@@ -10700,6 +11062,7 @@ var getMidPoint = (p1, p2) => {
10700
11062
  // src/zindex.ts
10701
11063
  init_define_import_meta_env();
10702
11064
  import { arrayToMap as arrayToMap6, findIndex, findLastIndex } from "@excalidraw/common";
11065
+ import { isFiniteNumber } from "@excalidraw/math";
10703
11066
 
10704
11067
  // src/groups.ts
10705
11068
  init_define_import_meta_env();
@@ -10707,52 +11070,15 @@ init_define_import_meta_env();
10707
11070
  // src/selection.ts
10708
11071
  init_define_import_meta_env();
10709
11072
  import { arrayToMap as arrayToMap5, isShallowEqual } from "@excalidraw/common";
10710
- import {
10711
- lineSegment as lineSegment5,
10712
- pointFrom as pointFrom10,
10713
- pointRotateRads as pointRotateRads9
10714
- } from "@excalidraw/math";
10715
11073
 
10716
11074
  // src/frame.ts
10717
11075
  init_define_import_meta_env();
10718
11076
  import { arrayToMap as arrayToMap4 } from "@excalidraw/common";
10719
- import { isPointWithinBounds as isPointWithinBounds2, pointFrom as pointFrom9 } from "@excalidraw/math";
10720
-
10721
- // ../utils/src/bbox.ts
10722
- init_define_import_meta_env();
10723
11077
  import {
10724
- vectorCross as vectorCross3,
10725
- vectorFromPoint as vectorFromPoint8
11078
+ isPointWithinBounds as isPointWithinBounds2,
11079
+ pointFrom as pointFrom9,
11080
+ segmentsIntersectAt as segmentsIntersectAt2
10726
11081
  } from "@excalidraw/math";
10727
- function getBBox(line2) {
10728
- return [
10729
- Math.min(line2[0][0], line2[1][0]),
10730
- Math.min(line2[0][1], line2[1][1]),
10731
- Math.max(line2[0][0], line2[1][0]),
10732
- Math.max(line2[0][1], line2[1][1])
10733
- ];
10734
- }
10735
- function doBBoxesIntersect(a2, b2) {
10736
- return a2[0] <= b2[2] && a2[2] >= b2[0] && a2[1] <= b2[3] && a2[3] >= b2[1];
10737
- }
10738
- var EPSILON = 1e-6;
10739
- function isPointOnLine(l2, p) {
10740
- const p1 = vectorFromPoint8(l2[1], l2[0]);
10741
- const p2 = vectorFromPoint8(p, l2[0]);
10742
- const r = vectorCross3(p1, p2);
10743
- return Math.abs(r) < EPSILON;
10744
- }
10745
- function isPointRightOfLine(l2, p) {
10746
- const p1 = vectorFromPoint8(l2[1], l2[0]);
10747
- const p2 = vectorFromPoint8(p, l2[0]);
10748
- return vectorCross3(p1, p2) < 0;
10749
- }
10750
- function isLineSegmentTouchingOrCrossingLine(a2, b2) {
10751
- return isPointOnLine(a2, b2[0]) || isPointOnLine(a2, b2[1]) || (isPointRightOfLine(a2, b2[0]) ? !isPointRightOfLine(a2, b2[1]) : isPointRightOfLine(a2, b2[1]));
10752
- }
10753
- function doLineSegmentsIntersect(a2, b2) {
10754
- return doBBoxesIntersect(getBBox(a2), getBBox(b2)) && isLineSegmentTouchingOrCrossingLine(a2, b2) && isLineSegmentTouchingOrCrossingLine(b2, a2);
10755
- }
10756
11082
 
10757
11083
  // src/fractionalIndex.ts
10758
11084
  init_define_import_meta_env();
@@ -11025,7 +11351,7 @@ function isElementIntersectingFrame(element, frame, elementsMap) {
11025
11351
  const elementLineSegments = getElementLineSegments(element, elementsMap);
11026
11352
  const intersecting = frameLineSegments.some(
11027
11353
  (frameLineSegment) => elementLineSegments.some(
11028
- (elementLineSegment) => doLineSegmentsIntersect(frameLineSegment, elementLineSegment)
11354
+ (elementLineSegment) => segmentsIntersectAt2(frameLineSegment, elementLineSegment)
11029
11355
  )
11030
11356
  );
11031
11357
  return intersecting;
@@ -11313,9 +11639,6 @@ var addElementsToFrame = (allElements, elementsToAdd, frame) => {
11313
11639
  if (isFrameLikeElement(element) || element.frameId && otherFrames.has(element.frameId)) {
11314
11640
  continue;
11315
11641
  }
11316
- if (element.frameId && element.frameId !== frame.id) {
11317
- continue;
11318
- }
11319
11642
  finalElementsToAdd.add(element);
11320
11643
  const boundTextElement = getBoundTextElement(element, elementsMap);
11321
11644
  if (boundTextElement && !finalElementsToAdd.has(boundTextElement)) {
@@ -11598,283 +11921,100 @@ var getElementsWithinSelection = (elements, selection, elementsMap, excludeEleme
11598
11921
  selectionX2,
11599
11922
  selectionY2
11600
11923
  ];
11601
- const selectionEdges = [
11602
- lineSegment5(
11603
- pointFrom10(selectionX1, selectionY1),
11604
- pointFrom10(selectionX2, selectionY1)
11605
- ),
11606
- lineSegment5(
11607
- pointFrom10(selectionX2, selectionY1),
11608
- pointFrom10(selectionX2, selectionY2)
11609
- ),
11610
- lineSegment5(
11611
- pointFrom10(selectionX2, selectionY2),
11612
- pointFrom10(selectionX1, selectionY2)
11613
- ),
11614
- lineSegment5(
11615
- pointFrom10(selectionX1, selectionY2),
11616
- pointFrom10(selectionX1, selectionY1)
11617
- )
11618
- ];
11619
- const framesInSelection = excludeElementsInFrames ? /* @__PURE__ */ new Set() : null;
11620
- const groups = {};
11621
- const elementsInSelection = /* @__PURE__ */ new Set();
11622
- for (const element of elements) {
11623
- if (shouldIgnoreElementFromSelection(element)) {
11924
+ return elementsOverlappingBBox({
11925
+ elements,
11926
+ bounds: selectionBounds,
11927
+ elementsMap,
11928
+ type: boxSelectionMode,
11929
+ shouldIgnoreElementFromSelection,
11930
+ excludeElementsInFrames
11931
+ });
11932
+ };
11933
+ var getVisibleAndNonSelectedElements = (elements, selectedElements, appState, elementsMap) => {
11934
+ const selectedElementsSet = new Set(
11935
+ selectedElements.map((element) => element.id)
11936
+ );
11937
+ return elements.filter((element) => {
11938
+ const isVisible = isElementInViewport(
11939
+ element,
11940
+ appState.width,
11941
+ appState.height,
11942
+ appState,
11943
+ elementsMap
11944
+ );
11945
+ return !selectedElementsSet.has(element.id) && isVisible;
11946
+ });
11947
+ };
11948
+ var isSomeElementSelected = function() {
11949
+ let lastElements = null;
11950
+ let lastSelectedElementIds = null;
11951
+ let isSelected = null;
11952
+ const ret = (elements, appState) => {
11953
+ if (isSelected != null && elements === lastElements && appState.selectedElementIds === lastSelectedElementIds) {
11954
+ return isSelected;
11955
+ }
11956
+ isSelected = elements.some(
11957
+ (element) => appState.selectedElementIds[element.id]
11958
+ );
11959
+ lastElements = elements;
11960
+ lastSelectedElementIds = appState.selectedElementIds;
11961
+ return isSelected;
11962
+ };
11963
+ ret.clearCache = () => {
11964
+ lastElements = null;
11965
+ lastSelectedElementIds = null;
11966
+ isSelected = null;
11967
+ };
11968
+ return ret;
11969
+ }();
11970
+ var getSelectedElements = (elements, appState, opts) => {
11971
+ const addedElements = /* @__PURE__ */ new Set();
11972
+ const selectedElements = [];
11973
+ for (const element of elements.values()) {
11974
+ if (appState.selectedElementIds[element.id]) {
11975
+ selectedElements.push(element);
11976
+ addedElements.add(element.id);
11624
11977
  continue;
11625
11978
  }
11626
- const groupId = element.groupIds.at(-1);
11627
- if (groupId) {
11628
- if (!groups[groupId]) {
11629
- groups[groupId] = [];
11979
+ if (opts?.includeBoundTextElement && isBoundToContainer(element) && appState.selectedElementIds[element?.containerId]) {
11980
+ selectedElements.push(element);
11981
+ addedElements.add(element.id);
11982
+ continue;
11983
+ }
11984
+ }
11985
+ if (opts?.includeElementsInFrames) {
11986
+ const elementsToInclude = [];
11987
+ selectedElements.forEach((element) => {
11988
+ if (isFrameLikeElement(element)) {
11989
+ getFrameChildren(elements, element.id).forEach(
11990
+ (e) => !addedElements.has(e.id) && elementsToInclude.push(e)
11991
+ );
11630
11992
  }
11631
- groups[groupId].push(element);
11632
- }
11633
- const strokeWidth = element.strokeWidth;
11634
- let labelAABB = null;
11635
- let elementAABB = getElementBounds(element, elementsMap);
11636
- elementAABB = [
11637
- elementAABB[0] - strokeWidth / 2,
11638
- elementAABB[1] - strokeWidth / 2,
11639
- elementAABB[2] + strokeWidth / 2,
11640
- elementAABB[3] + strokeWidth / 2
11641
- ];
11642
- const boundTextElement = isArrowElement(element) && getBoundTextElement(element, elementsMap);
11643
- if (boundTextElement) {
11644
- const { x, y } = LinearElementEditor.getBoundTextElementPosition(
11645
- element,
11646
- boundTextElement,
11647
- elementsMap
11648
- );
11649
- labelAABB = [
11650
- x,
11651
- y,
11652
- x + boundTextElement.width,
11653
- y + boundTextElement.height
11654
- ];
11655
- }
11656
- const associatedFrame = getContainingFrame(element, elementsMap);
11657
- if (associatedFrame && elementOverlapsWithFrame(element, associatedFrame, elementsMap)) {
11658
- const frameAABB = getElementBounds(associatedFrame, elementsMap);
11659
- elementAABB = [
11660
- Math.max(elementAABB[0], frameAABB[0]),
11661
- Math.max(elementAABB[1], frameAABB[1]),
11662
- Math.min(elementAABB[2], frameAABB[2]),
11663
- Math.min(elementAABB[3], frameAABB[3])
11664
- ];
11665
- labelAABB = labelAABB ? [
11666
- Math.max(labelAABB[0], frameAABB[0]),
11667
- Math.max(labelAABB[1], frameAABB[1]),
11668
- Math.min(labelAABB[2], frameAABB[2]),
11669
- Math.min(labelAABB[3], frameAABB[3])
11670
- ] : null;
11671
- }
11672
- const commonAABB2 = labelAABB ? [
11673
- Math.min(labelAABB[0], elementAABB[0]),
11674
- Math.min(labelAABB[1], elementAABB[1]),
11675
- Math.max(labelAABB[2], elementAABB[2]),
11676
- Math.max(labelAABB[3], elementAABB[3])
11677
- ] : elementAABB;
11678
- if (boundsContainBounds(selectionBounds, commonAABB2)) {
11679
- if (framesInSelection && isFrameLikeElement(element)) {
11680
- framesInSelection.add(element.id);
11681
- }
11682
- elementsInSelection.add(element);
11683
- continue;
11684
- }
11685
- if (boxSelectionMode === "overlap" && labelAABB && doBoundsIntersect(selectionBounds, labelAABB)) {
11686
- elementsInSelection.add(element);
11687
- continue;
11688
- }
11689
- if (boxSelectionMode === "overlap" && doBoundsIntersect(selectionBounds, elementAABB)) {
11690
- let hasIntersection = false;
11691
- if (isLinearElement(element) || isFreeDrawElement(element)) {
11692
- const center = elementCenterPoint(element, elementsMap);
11693
- hasIntersection = element.points.some((point) => {
11694
- const rotatedPoint = pointRotateRads9(
11695
- pointFrom10(element.x + point[0], element.y + point[1]),
11696
- center,
11697
- element.angle
11698
- );
11699
- return pointInsideBounds(rotatedPoint, selectionBounds);
11700
- });
11701
- } else {
11702
- const nonRotatedElementBounds = getElementBounds(
11703
- element,
11704
- elementsMap,
11705
- true
11706
- );
11707
- const center = elementCenterPoint(element, elementsMap);
11708
- hasIntersection = [
11709
- pointRotateRads9(
11710
- pointFrom10(
11711
- (nonRotatedElementBounds[0] + nonRotatedElementBounds[2]) / 2,
11712
- nonRotatedElementBounds[1]
11713
- ),
11714
- center,
11715
- element.angle
11716
- ),
11717
- pointRotateRads9(
11718
- pointFrom10(
11719
- nonRotatedElementBounds[2],
11720
- (nonRotatedElementBounds[1] + nonRotatedElementBounds[3]) / 2
11721
- ),
11722
- center,
11723
- element.angle
11724
- ),
11725
- pointRotateRads9(
11726
- pointFrom10(
11727
- (nonRotatedElementBounds[0] + nonRotatedElementBounds[2]) / 2,
11728
- nonRotatedElementBounds[3]
11729
- ),
11730
- center,
11731
- element.angle
11732
- ),
11733
- pointRotateRads9(
11734
- pointFrom10(
11735
- nonRotatedElementBounds[0],
11736
- (nonRotatedElementBounds[1] + nonRotatedElementBounds[3]) / 2
11737
- ),
11738
- center,
11739
- element.angle
11740
- )
11741
- ].some((point) => {
11742
- return pointInsideBounds(
11743
- pointRotateRads9(point, center, element.angle),
11744
- selectionBounds
11745
- );
11746
- });
11747
- }
11748
- if (!hasIntersection) {
11749
- hasIntersection = selectionEdges.some(
11750
- (selectionEdge) => intersectElementWithLineSegment(
11751
- element,
11752
- elementsMap,
11753
- selectionEdge,
11754
- strokeWidth / 2,
11755
- true
11756
- // Stop at first hit for better performance
11757
- ).length > 0
11758
- );
11759
- }
11760
- if (hasIntersection) {
11761
- if (framesInSelection && isFrameLikeElement(element)) {
11762
- framesInSelection.add(element.id);
11763
- }
11764
- elementsInSelection.add(element);
11765
- continue;
11766
- }
11767
- }
11768
- }
11769
- if (framesInSelection) {
11770
- elementsInSelection.forEach((element) => {
11771
- if (element.frameId && framesInSelection.has(element.frameId)) {
11772
- elementsInSelection.delete(element);
11773
- }
11774
- });
11775
- }
11776
- if (boxSelectionMode === "overlap") {
11777
- Array.from(elementsInSelection).forEach((element) => {
11778
- const groupId = element.groupIds.at(-1);
11779
- const group = groupId ? groups[groupId] : null;
11780
- group?.forEach((groupElement) => elementsInSelection.add(groupElement));
11781
- });
11782
- } else if (boxSelectionMode === "contain") {
11783
- elementsInSelection.forEach((element) => {
11784
- const groupId = element.groupIds.at(-1);
11785
- const group = groupId ? groups[groupId] : null;
11786
- if (group && !group.every((groupElement) => elementsInSelection.has(groupElement))) {
11787
- elementsInSelection.delete(element);
11788
- }
11789
- });
11790
- }
11791
- return elements.filter((element) => elementsInSelection.has(element));
11792
- };
11793
- var getVisibleAndNonSelectedElements = (elements, selectedElements, appState, elementsMap) => {
11794
- const selectedElementsSet = new Set(
11795
- selectedElements.map((element) => element.id)
11796
- );
11797
- return elements.filter((element) => {
11798
- const isVisible = isElementInViewport(
11799
- element,
11800
- appState.width,
11801
- appState.height,
11802
- appState,
11803
- elementsMap
11804
- );
11805
- return !selectedElementsSet.has(element.id) && isVisible;
11806
- });
11807
- };
11808
- var isSomeElementSelected = function() {
11809
- let lastElements = null;
11810
- let lastSelectedElementIds = null;
11811
- let isSelected = null;
11812
- const ret = (elements, appState) => {
11813
- if (isSelected != null && elements === lastElements && appState.selectedElementIds === lastSelectedElementIds) {
11814
- return isSelected;
11815
- }
11816
- isSelected = elements.some(
11817
- (element) => appState.selectedElementIds[element.id]
11818
- );
11819
- lastElements = elements;
11820
- lastSelectedElementIds = appState.selectedElementIds;
11821
- return isSelected;
11822
- };
11823
- ret.clearCache = () => {
11824
- lastElements = null;
11825
- lastSelectedElementIds = null;
11826
- isSelected = null;
11827
- };
11828
- return ret;
11829
- }();
11830
- var getSelectedElements = (elements, appState, opts) => {
11831
- const addedElements = /* @__PURE__ */ new Set();
11832
- const selectedElements = [];
11833
- for (const element of elements.values()) {
11834
- if (appState.selectedElementIds[element.id]) {
11835
- selectedElements.push(element);
11836
- addedElements.add(element.id);
11837
- continue;
11838
- }
11839
- if (opts?.includeBoundTextElement && isBoundToContainer(element) && appState.selectedElementIds[element?.containerId]) {
11840
- selectedElements.push(element);
11841
- addedElements.add(element.id);
11842
- continue;
11843
- }
11844
- }
11845
- if (opts?.includeElementsInFrames) {
11846
- const elementsToInclude = [];
11847
- selectedElements.forEach((element) => {
11848
- if (isFrameLikeElement(element)) {
11849
- getFrameChildren(elements, element.id).forEach(
11850
- (e) => !addedElements.has(e.id) && elementsToInclude.push(e)
11851
- );
11852
- }
11853
- elementsToInclude.push(element);
11854
- });
11855
- return elementsToInclude;
11856
- }
11857
- return selectedElements;
11858
- };
11859
- var getTargetElements = (elements, appState) => appState.editingTextElement ? [appState.editingTextElement] : appState.newElement ? [appState.newElement] : getSelectedElements(elements, appState, {
11860
- includeBoundTextElement: true
11861
- });
11862
- var makeNextSelectedElementIds = (nextSelectedElementIds, prevState) => {
11863
- if (isShallowEqual(prevState.selectedElementIds, nextSelectedElementIds)) {
11864
- return prevState.selectedElementIds;
11865
- }
11866
- return nextSelectedElementIds;
11867
- };
11868
- var _getLinearElementEditor = (targetElements, allElements) => {
11869
- const linears = targetElements.filter(isLinearElement);
11870
- if (linears.length === 1) {
11871
- const linear = linears[0];
11872
- const boundElements = linear.boundElements?.map((def) => def.id) ?? [];
11873
- const onlySingleLinearSelected = targetElements.every(
11874
- (el) => el.id === linear.id || boundElements.includes(el.id)
11875
- );
11876
- if (onlySingleLinearSelected) {
11877
- return new LinearElementEditor(linear, arrayToMap5(allElements));
11993
+ elementsToInclude.push(element);
11994
+ });
11995
+ return elementsToInclude;
11996
+ }
11997
+ return selectedElements;
11998
+ };
11999
+ var getTargetElements = (elements, appState) => appState.editingTextElement ? [appState.editingTextElement] : appState.newElement ? [appState.newElement] : getSelectedElements(elements, appState, {
12000
+ includeBoundTextElement: true
12001
+ });
12002
+ var makeNextSelectedElementIds = (nextSelectedElementIds, prevState) => {
12003
+ if (isShallowEqual(prevState.selectedElementIds, nextSelectedElementIds)) {
12004
+ return prevState.selectedElementIds;
12005
+ }
12006
+ return nextSelectedElementIds;
12007
+ };
12008
+ var _getLinearElementEditor = (targetElements, allElements) => {
12009
+ const linears = targetElements.filter(isLinearElement);
12010
+ if (linears.length === 1) {
12011
+ const linear = linears[0];
12012
+ const boundElements = linear.boundElements?.map((def) => def.id) ?? [];
12013
+ const onlySingleLinearSelected = targetElements.every(
12014
+ (el) => el.id === linear.id || boundElements.includes(el.id)
12015
+ );
12016
+ if (onlySingleLinearSelected) {
12017
+ return new LinearElementEditor(linear, arrayToMap5(allElements));
11878
12018
  }
11879
12019
  }
11880
12020
  return null;
@@ -12357,7 +12497,34 @@ var getTargetElementsMap = (elements, indices) => {
12357
12497
  return acc;
12358
12498
  }, /* @__PURE__ */ new Map());
12359
12499
  };
12500
+ var hasSameElementIds = (prevElements, nextElements) => {
12501
+ if (prevElements.length !== nextElements.length) {
12502
+ console.error(
12503
+ "z-index reordering failed: resulting array have different lengths"
12504
+ );
12505
+ return false;
12506
+ }
12507
+ const prevElementIdCounts = /* @__PURE__ */ new Map();
12508
+ for (const element of prevElements) {
12509
+ prevElementIdCounts.set(
12510
+ element.id,
12511
+ (prevElementIdCounts.get(element.id) || 0) + 1
12512
+ );
12513
+ }
12514
+ for (const element of nextElements) {
12515
+ const count = prevElementIdCounts.get(element.id);
12516
+ if (!count) {
12517
+ console.error(
12518
+ "z-index reordering failed: element id mismatch / duplicate ids"
12519
+ );
12520
+ return false;
12521
+ }
12522
+ prevElementIdCounts.set(element.id, count - 1);
12523
+ }
12524
+ return true;
12525
+ };
12360
12526
  var shiftElementsByOne = (elements, appState, direction, scene) => {
12527
+ const originalElements = elements;
12361
12528
  const indicesToMove = getIndicesToMove(elements, appState);
12362
12529
  const targetElementsMap = getTargetElementsMap(elements, indicesToMove);
12363
12530
  let groupedIndices = toContiguousGroups(indicesToMove);
@@ -12402,11 +12569,17 @@ var shiftElementsByOne = (elements, appState, direction, scene) => {
12402
12569
  ...trailingElements
12403
12570
  ];
12404
12571
  });
12572
+ if (!hasSameElementIds(originalElements, elements)) {
12573
+ return originalElements;
12574
+ }
12405
12575
  syncMovedIndices(elements, targetElementsMap);
12406
12576
  return elements;
12407
12577
  };
12408
12578
  var shiftElementsToEnd = (elements, appState, direction, containingFrame, elementsToBeMoved) => {
12409
12579
  const indicesToMove = getIndicesToMove(elements, appState, elementsToBeMoved);
12580
+ if (indicesToMove.length === 0) {
12581
+ return elements;
12582
+ }
12410
12583
  const targetElementsMap = getTargetElementsMap(elements, indicesToMove);
12411
12584
  const displacedElements = [];
12412
12585
  let leadingIndex;
@@ -12453,6 +12626,12 @@ var shiftElementsToEnd = (elements, appState, direction, containingFrame, elemen
12453
12626
  if (leadingIndex === -1) {
12454
12627
  leadingIndex = 0;
12455
12628
  }
12629
+ const isValidIndex = (index) => {
12630
+ return isFiniteNumber(index) && index >= 0;
12631
+ };
12632
+ if (!isValidIndex(leadingIndex) || !isValidIndex(trailingIndex) || leadingIndex > trailingIndex || indicesToMove.some((index) => index < leadingIndex || index > trailingIndex)) {
12633
+ return elements;
12634
+ }
12456
12635
  for (let index = leadingIndex; index < trailingIndex + 1; index++) {
12457
12636
  if (!indicesToMove.includes(index)) {
12458
12637
  displacedElements.push(elements[index]);
@@ -12472,6 +12651,9 @@ var shiftElementsToEnd = (elements, appState, direction, containingFrame, elemen
12472
12651
  ...targetElements,
12473
12652
  ...trailingElements
12474
12653
  ];
12654
+ if (!hasSameElementIds(elements, nextElements)) {
12655
+ return elements;
12656
+ }
12475
12657
  syncMovedIndices(nextElements, targetElementsMap);
12476
12658
  return nextElements;
12477
12659
  };
@@ -12513,7 +12695,7 @@ function shiftElementsAccountingForFrames(allElements, appState, direction, shif
12513
12695
  );
12514
12696
  for (const [frameId, children] of frameChildrenSets) {
12515
12697
  nextElements = shiftFunction(
12516
- allElements,
12698
+ nextElements,
12517
12699
  appState,
12518
12700
  direction,
12519
12701
  frameId,
@@ -12559,7 +12741,7 @@ var getNormalizedPoints = ({
12559
12741
  const offsetY = points[0][1];
12560
12742
  return {
12561
12743
  points: points.map((p) => {
12562
- return pointFrom11(p[0] - offsetX, p[1] - offsetY);
12744
+ return pointFrom10(p[0] - offsetX, p[1] - offsetY);
12563
12745
  }),
12564
12746
  offsetX,
12565
12747
  offsetY
@@ -12588,7 +12770,7 @@ var LinearElementEditor = class _LinearElementEditor {
12588
12770
  pointerDownState;
12589
12771
  constructor(element, elementsMap, isEditing = false) {
12590
12772
  this.elementId = element.id;
12591
- if (!pointsEqual6(element.points[0], pointFrom11(0, 0))) {
12773
+ if (!pointsEqual6(element.points[0], pointFrom10(0, 0))) {
12592
12774
  console.error("Linear element is not normalized", Error().stack);
12593
12775
  mutateElement(
12594
12776
  element,
@@ -12687,11 +12869,11 @@ var LinearElementEditor = class _LinearElementEditor {
12687
12869
  element,
12688
12870
  elementsMap,
12689
12871
  pivotPoint,
12690
- pointFrom11(scenePointerX, scenePointerY),
12872
+ pointFrom10(scenePointerX, scenePointerY),
12691
12873
  event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),
12692
12874
  customLineAngle
12693
12875
  );
12694
- const target = pointFrom11(
12876
+ const target = pointFrom10(
12695
12877
  width + pivotPoint[0],
12696
12878
  height + pivotPoint[1]
12697
12879
  );
@@ -12768,7 +12950,7 @@ var LinearElementEditor = class _LinearElementEditor {
12768
12950
  ...linearElementEditor.initialState,
12769
12951
  altFocusPoint: !linearElementEditor.initialState.altFocusPoint && startBindingElement && updates?.suggestedBinding?.element.id !== startBindingElement.id ? projectFixedPointOntoDiagonal(
12770
12952
  element,
12771
- pointFrom11(element.x, element.y),
12953
+ pointFrom10(element.x, element.y),
12772
12954
  startBindingElement,
12773
12955
  "start",
12774
12956
  elementsMap,
@@ -12830,11 +13012,11 @@ var LinearElementEditor = class _LinearElementEditor {
12830
13012
  element,
12831
13013
  elementsMap,
12832
13014
  pivotPoint,
12833
- pointFrom11(scenePointerX, scenePointerY),
13015
+ pointFrom10(scenePointerX, scenePointerY),
12834
13016
  event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),
12835
13017
  customLineAngle
12836
13018
  );
12837
- const target = pointFrom11(
13019
+ const target = pointFrom10(
12838
13020
  width + pivotPoint[0],
12839
13021
  height + pivotPoint[1]
12840
13022
  );
@@ -12928,7 +13110,7 @@ var LinearElementEditor = class _LinearElementEditor {
12928
13110
  altFocusPoint: !linearElementEditor.initialState.altFocusPoint && // We only set it once per arrow drag
12929
13111
  isBindingElement(element) && altFocusPointBindableElement ? projectFixedPointOntoDiagonal(
12930
13112
  element,
12931
- pointFrom11(element.x, element.y),
13113
+ pointFrom10(element.x, element.y),
12932
13114
  altFocusPointBindableElement,
12933
13115
  "start",
12934
13116
  elementsMap,
@@ -13072,11 +13254,11 @@ var LinearElementEditor = class _LinearElementEditor {
13072
13254
  const existingSegmentMidpointHitCoords = linearElementEditor.segmentMidPointHoveredCoords;
13073
13255
  if (existingSegmentMidpointHitCoords) {
13074
13256
  const distance3 = pointDistance5(
13075
- pointFrom11(
13257
+ pointFrom10(
13076
13258
  existingSegmentMidpointHitCoords[0],
13077
13259
  existingSegmentMidpointHitCoords[1]
13078
13260
  ),
13079
- pointFrom11(scenePointer.x, scenePointer.y)
13261
+ pointFrom10(scenePointer.x, scenePointer.y)
13080
13262
  );
13081
13263
  if (distance3 <= threshold) {
13082
13264
  return existingSegmentMidpointHitCoords;
@@ -13092,7 +13274,7 @@ var LinearElementEditor = class _LinearElementEditor {
13092
13274
  if (midPoints[index] !== null) {
13093
13275
  const distance3 = pointDistance5(
13094
13276
  midPoints[index],
13095
- pointFrom11(scenePointer.x, scenePointer.y)
13277
+ pointFrom10(scenePointer.x, scenePointer.y)
13096
13278
  );
13097
13279
  if (distance3 <= threshold) {
13098
13280
  return midPoints[index];
@@ -13134,7 +13316,7 @@ var LinearElementEditor = class _LinearElementEditor {
13134
13316
  "Invalid segment index while calculating elbow arrow mid point"
13135
13317
  );
13136
13318
  const p = pointCenter2(element.points[index - 1], element.points[index]);
13137
- return pointFrom11(element.x + p[0], element.y + p[1]);
13319
+ return pointFrom10(element.x + p[0], element.y + p[1]);
13138
13320
  }
13139
13321
  const [lines, curves] = deconstructLinearOrFreeDrawElement(
13140
13322
  element,
@@ -13202,7 +13384,7 @@ var LinearElementEditor = class _LinearElementEditor {
13202
13384
  appState,
13203
13385
  elementsMap
13204
13386
  );
13205
- const point = pointFrom11(scenePointer.x, scenePointer.y);
13387
+ const point = pointFrom10(scenePointer.x, scenePointer.y);
13206
13388
  let segmentMidpointIndex = null;
13207
13389
  if (segmentMidpoint) {
13208
13390
  segmentMidpointIndex = _LinearElementEditor.getSegmentMidPointIndex(
@@ -13261,12 +13443,12 @@ var LinearElementEditor = class _LinearElementEditor {
13261
13443
  const [x1, y1, x2, y2] = getElementAbsoluteCoords2(element, elementsMap);
13262
13444
  const cx = (x1 + x2) / 2;
13263
13445
  const cy = (y1 + y2) / 2;
13264
- const targetPoint = clickedPointIndex > -1 && pointRotateRads10(
13265
- pointFrom11(
13446
+ const targetPoint = clickedPointIndex > -1 && pointRotateRads9(
13447
+ pointFrom10(
13266
13448
  element.x + element.points[clickedPointIndex][0],
13267
13449
  element.y + element.points[clickedPointIndex][1]
13268
13450
  ),
13269
- pointFrom11(cx, cy),
13451
+ pointFrom10(cx, cy),
13270
13452
  element.angle
13271
13453
  );
13272
13454
  const nextSelectedPointsIndices = clickedPointIndex > -1 || event.shiftKey ? event.shiftKey || linearElementEditor.selectedPointsIndices?.includes(clickedPointIndex) ? normalizeSelectedPoints([
@@ -13333,10 +13515,10 @@ var LinearElementEditor = class _LinearElementEditor {
13333
13515
  element,
13334
13516
  elementsMap,
13335
13517
  anchor,
13336
- pointFrom11(scenePointerX, scenePointerY),
13518
+ pointFrom10(scenePointerX, scenePointerY),
13337
13519
  event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize()
13338
13520
  );
13339
- newPoint = pointFrom11(width + anchor[0], height + anchor[1]);
13521
+ newPoint = pointFrom10(width + anchor[0], height + anchor[1]);
13340
13522
  } else {
13341
13523
  newPoint = _LinearElementEditor.createPointAt(
13342
13524
  element,
@@ -13373,9 +13555,9 @@ var LinearElementEditor = class _LinearElementEditor {
13373
13555
  const cx = (x1 + x2) / 2;
13374
13556
  const cy = (y1 + y2) / 2;
13375
13557
  const { x, y } = element;
13376
- return pointRotateRads10(
13377
- pointFrom11(x + p[0], y + p[1]),
13378
- pointFrom11(cx, cy),
13558
+ return pointRotateRads9(
13559
+ pointFrom10(x + p[0], y + p[1]),
13560
+ pointFrom10(cx, cy),
13379
13561
  element.angle
13380
13562
  );
13381
13563
  }
@@ -13386,9 +13568,9 @@ var LinearElementEditor = class _LinearElementEditor {
13386
13568
  const cy = (y1 + y2) / 2;
13387
13569
  return element.points.map((p) => {
13388
13570
  const { x, y } = element;
13389
- return pointRotateRads10(
13390
- pointFrom11(x + p[0], y + p[1]),
13391
- pointFrom11(cx, cy),
13571
+ return pointRotateRads9(
13572
+ pointFrom10(x + p[0], y + p[1]),
13573
+ pointFrom10(cx, cy),
13392
13574
  element.angle
13393
13575
  );
13394
13576
  });
@@ -13396,18 +13578,18 @@ var LinearElementEditor = class _LinearElementEditor {
13396
13578
  static getPointAtIndexGlobalCoordinates(element, indexMaybeFromEnd, elementsMap) {
13397
13579
  const index = indexMaybeFromEnd < 0 ? element.points.length + indexMaybeFromEnd : indexMaybeFromEnd;
13398
13580
  const [, , , , cx, cy] = getElementAbsoluteCoords2(element, elementsMap);
13399
- const center = pointFrom11(cx, cy);
13581
+ const center = pointFrom10(cx, cy);
13400
13582
  const p = element.points[index];
13401
13583
  const { x, y } = element;
13402
- return p ? pointRotateRads10(
13403
- pointFrom11(x + p[0], y + p[1]),
13584
+ return p ? pointRotateRads9(
13585
+ pointFrom10(x + p[0], y + p[1]),
13404
13586
  center,
13405
13587
  element.angle
13406
- ) : pointRotateRads10(pointFrom11(x, y), center, element.angle);
13588
+ ) : pointRotateRads9(pointFrom10(x, y), center, element.angle);
13407
13589
  }
13408
13590
  static pointFromAbsoluteCoords(element, absoluteCoords, elementsMap) {
13409
13591
  if (isElbowArrow(element)) {
13410
- return pointFrom11(
13592
+ return pointFrom10(
13411
13593
  absoluteCoords[0] - element.x,
13412
13594
  absoluteCoords[1] - element.y
13413
13595
  );
@@ -13415,12 +13597,12 @@ var LinearElementEditor = class _LinearElementEditor {
13415
13597
  const [x1, y1, x2, y2] = getElementAbsoluteCoords2(element, elementsMap);
13416
13598
  const cx = (x1 + x2) / 2;
13417
13599
  const cy = (y1 + y2) / 2;
13418
- const [x, y] = pointRotateRads10(
13419
- pointFrom11(absoluteCoords[0], absoluteCoords[1]),
13420
- pointFrom11(cx, cy),
13600
+ const [x, y] = pointRotateRads9(
13601
+ pointFrom10(absoluteCoords[0], absoluteCoords[1]),
13602
+ pointFrom10(cx, cy),
13421
13603
  -element.angle
13422
13604
  );
13423
- return pointFrom11(x - element.x, y - element.y);
13605
+ return pointFrom10(x - element.x, y - element.y);
13424
13606
  }
13425
13607
  static getPointIndexUnderCursor(element, elementsMap, zoom, x, y) {
13426
13608
  const pointHandles = _LinearElementEditor.getPointsGlobalCoordinates(
@@ -13430,7 +13612,7 @@ var LinearElementEditor = class _LinearElementEditor {
13430
13612
  let idx = pointHandles.length;
13431
13613
  while (--idx > -1) {
13432
13614
  const p = pointHandles[idx];
13433
- if (pointDistance5(pointFrom11(x, y), pointFrom11(p[0], p[1])) * zoom.value < // +1px to account for outline stroke
13615
+ if (pointDistance5(pointFrom10(x, y), pointFrom10(p[0], p[1])) * zoom.value < // +1px to account for outline stroke
13434
13616
  _LinearElementEditor.POINT_HANDLE_SIZE + 1) {
13435
13617
  return idx;
13436
13618
  }
@@ -13442,12 +13624,12 @@ var LinearElementEditor = class _LinearElementEditor {
13442
13624
  const [x1, y1, x2, y2] = getElementAbsoluteCoords2(element, elementsMap);
13443
13625
  const cx = (x1 + x2) / 2;
13444
13626
  const cy = (y1 + y2) / 2;
13445
- const [rotatedX, rotatedY] = pointRotateRads10(
13446
- pointFrom11(pointerOnGrid[0], pointerOnGrid[1]),
13447
- pointFrom11(cx, cy),
13627
+ const [rotatedX, rotatedY] = pointRotateRads9(
13628
+ pointFrom10(pointerOnGrid[0], pointerOnGrid[1]),
13629
+ pointFrom10(cx, cy),
13448
13630
  -element.angle
13449
13631
  );
13450
- return pointFrom11(rotatedX - element.x, rotatedY - element.y);
13632
+ return pointFrom10(rotatedX - element.x, rotatedY - element.y);
13451
13633
  }
13452
13634
  /**
13453
13635
  * Normalizes line points so that the start point is at [0,0]. This is
@@ -13496,7 +13678,7 @@ var LinearElementEditor = class _LinearElementEditor {
13496
13678
  pointAddedToEnd = true;
13497
13679
  }
13498
13680
  acc.push(
13499
- nextPoint ? pointFrom11((p[0] + nextPoint[0]) / 2, (p[1] + nextPoint[1]) / 2) : pointFrom11(p[0], p[1])
13681
+ nextPoint ? pointFrom10((p[0] + nextPoint[0]) / 2, (p[1] + nextPoint[1]) / 2) : pointFrom10(p[0], p[1])
13500
13682
  );
13501
13683
  nextSelectedIndices.push(indexCursor + 1);
13502
13684
  ++indexCursor;
@@ -13512,7 +13694,7 @@ var LinearElementEditor = class _LinearElementEditor {
13512
13694
  /* @__PURE__ */ new Map([
13513
13695
  [
13514
13696
  element.points.length - 1,
13515
- { point: pointFrom11(lastPoint[0] + 30, lastPoint[1] + 30) }
13697
+ { point: pointFrom10(lastPoint[0] + 30, lastPoint[1] + 30) }
13516
13698
  ]
13517
13699
  ])
13518
13700
  );
@@ -13532,7 +13714,7 @@ var LinearElementEditor = class _LinearElementEditor {
13532
13714
  });
13533
13715
  const isPolygon = isLineElement(element) && element.polygon;
13534
13716
  if (isPolygon && (isUncommittedPoint || pointIndices.includes(0) || pointIndices.includes(element.points.length - 1))) {
13535
- nextPoints[0] = pointFrom11(
13717
+ nextPoints[0] = pointFrom10(
13536
13718
  nextPoints[nextPoints.length - 1][0],
13537
13719
  nextPoints[nextPoints.length - 1][1]
13538
13720
  );
@@ -13553,7 +13735,7 @@ var LinearElementEditor = class _LinearElementEditor {
13553
13735
  static addPoints(element, scene, addedPoints) {
13554
13736
  const nextPoints = [...element.points, ...addedPoints];
13555
13737
  if (isLineElement(element) && element.polygon) {
13556
- nextPoints[0] = pointFrom11(
13738
+ nextPoints[0] = pointFrom10(
13557
13739
  nextPoints[nextPoints.length - 1][0],
13558
13740
  nextPoints[nextPoints.length - 1][1]
13559
13741
  );
@@ -13578,7 +13760,7 @@ var LinearElementEditor = class _LinearElementEditor {
13578
13760
  const lastPointUpdate = pointUpdates.get(points.length - 1);
13579
13761
  if (firstPointUpdate) {
13580
13762
  pointUpdates.set(points.length - 1, {
13581
- point: pointFrom11(
13763
+ point: pointFrom10(
13582
13764
  firstPointUpdate.point[0],
13583
13765
  firstPointUpdate.point[1]
13584
13766
  ),
@@ -13586,12 +13768,12 @@ var LinearElementEditor = class _LinearElementEditor {
13586
13768
  });
13587
13769
  } else if (lastPointUpdate) {
13588
13770
  pointUpdates.set(0, {
13589
- point: pointFrom11(lastPointUpdate.point[0], lastPointUpdate.point[1]),
13771
+ point: pointFrom10(lastPointUpdate.point[0], lastPointUpdate.point[1]),
13590
13772
  isDragging: lastPointUpdate.isDragging
13591
13773
  });
13592
13774
  }
13593
13775
  }
13594
- const updatedOriginPoint = pointUpdates.get(0)?.point ?? pointFrom11(0, 0);
13776
+ const updatedOriginPoint = pointUpdates.get(0)?.point ?? pointFrom10(0, 0);
13595
13777
  const [offsetX, offsetY] = updatedOriginPoint;
13596
13778
  const nextPoints = isElbowArrow(element) ? [
13597
13779
  pointUpdates.get(0)?.point ?? points[0],
@@ -13601,7 +13783,7 @@ var LinearElementEditor = class _LinearElementEditor {
13601
13783
  if (otherUpdates?.moveMidPointsWithElement && idx !== 0 && idx !== points.length - 1 && !pointUpdates.has(idx)) {
13602
13784
  return current;
13603
13785
  }
13604
- return pointFrom11(
13786
+ return pointFrom10(
13605
13787
  current[0] - offsetX,
13606
13788
  current[1] - offsetY
13607
13789
  );
@@ -13636,11 +13818,11 @@ var LinearElementEditor = class _LinearElementEditor {
13636
13818
  return false;
13637
13819
  }
13638
13820
  const origin = linearElementEditor.initialState.origin;
13639
- const dist = pointDistance5(
13821
+ const dist2 = pointDistance5(
13640
13822
  origin,
13641
- pointFrom11(pointerCoords.x, pointerCoords.y)
13823
+ pointFrom10(pointerCoords.x, pointerCoords.y)
13642
13824
  );
13643
- if (!appState.selectedLinearElement?.isEditing && dist < DRAGGING_THRESHOLD / appState.zoom.value) {
13825
+ if (!appState.selectedLinearElement?.isEditing && dist2 < DRAGGING_THRESHOLD / appState.zoom.value) {
13644
13826
  return false;
13645
13827
  }
13646
13828
  return true;
@@ -13708,9 +13890,9 @@ var LinearElementEditor = class _LinearElementEditor {
13708
13890
  const prevCenterY = (prevCoords[1] + prevCoords[3]) / 2;
13709
13891
  const dX = prevCenterX - nextCenterX;
13710
13892
  const dY = prevCenterY - nextCenterY;
13711
- const rotatedOffset = pointRotateRads10(
13712
- pointFrom11(offsetX, offsetY),
13713
- pointFrom11(dX, dY),
13893
+ const rotatedOffset = pointRotateRads9(
13894
+ pointFrom10(offsetX, offsetY),
13895
+ pointFrom10(dX, dY),
13714
13896
  element.angle
13715
13897
  );
13716
13898
  scene.mutateElement(element, {
@@ -13745,9 +13927,9 @@ var LinearElementEditor = class _LinearElementEditor {
13745
13927
  gridY,
13746
13928
  customLineAngle
13747
13929
  );
13748
- return pointRotateRads10(
13749
- pointFrom11(width, height),
13750
- pointFrom11(0, 0),
13930
+ return pointRotateRads9(
13931
+ pointFrom10(width, height),
13932
+ pointFrom10(0, 0),
13751
13933
  -element.angle
13752
13934
  );
13753
13935
  }
@@ -13793,34 +13975,34 @@ var LinearElementEditor = class _LinearElementEditor {
13793
13975
  );
13794
13976
  const boundTextX2 = boundTextX1 + boundTextElement.width;
13795
13977
  const boundTextY2 = boundTextY1 + boundTextElement.height;
13796
- const centerPoint = pointFrom11(cx, cy);
13797
- const topLeftRotatedPoint = pointRotateRads10(
13798
- pointFrom11(x1, y1),
13978
+ const centerPoint = pointFrom10(cx, cy);
13979
+ const topLeftRotatedPoint = pointRotateRads9(
13980
+ pointFrom10(x1, y1),
13799
13981
  centerPoint,
13800
13982
  element.angle
13801
13983
  );
13802
- const topRightRotatedPoint = pointRotateRads10(
13803
- pointFrom11(x2, y1),
13984
+ const topRightRotatedPoint = pointRotateRads9(
13985
+ pointFrom10(x2, y1),
13804
13986
  centerPoint,
13805
13987
  element.angle
13806
13988
  );
13807
- const counterRotateBoundTextTopLeft = pointRotateRads10(
13808
- pointFrom11(boundTextX1, boundTextY1),
13989
+ const counterRotateBoundTextTopLeft = pointRotateRads9(
13990
+ pointFrom10(boundTextX1, boundTextY1),
13809
13991
  centerPoint,
13810
13992
  -element.angle
13811
13993
  );
13812
- const counterRotateBoundTextTopRight = pointRotateRads10(
13813
- pointFrom11(boundTextX2, boundTextY1),
13994
+ const counterRotateBoundTextTopRight = pointRotateRads9(
13995
+ pointFrom10(boundTextX2, boundTextY1),
13814
13996
  centerPoint,
13815
13997
  -element.angle
13816
13998
  );
13817
- const counterRotateBoundTextBottomLeft = pointRotateRads10(
13818
- pointFrom11(boundTextX1, boundTextY2),
13999
+ const counterRotateBoundTextBottomLeft = pointRotateRads9(
14000
+ pointFrom10(boundTextX1, boundTextY2),
13819
14001
  centerPoint,
13820
14002
  -element.angle
13821
14003
  );
13822
- const counterRotateBoundTextBottomRight = pointRotateRads10(
13823
- pointFrom11(boundTextX2, boundTextY2),
14004
+ const counterRotateBoundTextBottomRight = pointRotateRads9(
14005
+ pointFrom10(boundTextX2, boundTextY2),
13824
14006
  centerPoint,
13825
14007
  -element.angle
13826
14008
  );
@@ -13898,7 +14080,7 @@ var LinearElementEditor = class _LinearElementEditor {
13898
14080
  if (index && index > 0 && index < element.points.length) {
13899
14081
  const isHorizontal = headingIsHorizontal(
13900
14082
  vectorToHeading(
13901
- vectorFromPoint9(element.points[index], element.points[index - 1])
14083
+ vectorFromPoint8(element.points[index], element.points[index - 1])
13902
14084
  )
13903
14085
  );
13904
14086
  const fixedSegments = (element.fixedSegments ?? []).reduce(
@@ -13910,11 +14092,11 @@ var LinearElementEditor = class _LinearElementEditor {
13910
14092
  );
13911
14093
  fixedSegments[index] = {
13912
14094
  index,
13913
- start: pointFrom11(
14095
+ start: pointFrom10(
13914
14096
  !isHorizontal ? x - element.x : element.points[index - 1][0],
13915
14097
  isHorizontal ? y - element.y : element.points[index - 1][1]
13916
14098
  ),
13917
- end: pointFrom11(
14099
+ end: pointFrom10(
13918
14100
  !isHorizontal ? x - element.x : element.points[index][0],
13919
14101
  isHorizontal ? y - element.y : element.points[index][1]
13920
14102
  )
@@ -13926,7 +14108,7 @@ var LinearElementEditor = class _LinearElementEditor {
13926
14108
  scene.mutateElement(element, {
13927
14109
  fixedSegments: nextFixedSegments
13928
14110
  });
13929
- const point = pointFrom11(
14111
+ const point = pointFrom10(
13930
14112
  element.x + (element.fixedSegments[offset].start[0] + element.fixedSegments[offset].end[0]) / 2,
13931
14113
  element.y + (element.fixedSegments[offset].start[1] + element.fixedSegments[offset].end[1]) / 2
13932
14114
  );
@@ -13967,7 +14149,7 @@ var pointDraggingUpdates = (selectedPointsIndices, deltaX, deltaY, scenePointerX
13967
14149
  return [
13968
14150
  pointIndex,
13969
14151
  {
13970
- point: pointFrom11(point[0] + deltaX, point[1] + deltaY),
14152
+ point: pointFrom10(point[0] + deltaX, point[1] + deltaY),
13971
14153
  isDragging: true
13972
14154
  }
13973
14155
  ];
@@ -14006,7 +14188,7 @@ var pointDraggingUpdates = (selectedPointsIndices, deltaX, deltaY, scenePointerX
14006
14188
  midPoint: app.state.isMidpointSnappingEnabled ? snapToMid(
14007
14189
  suggestedBindingElement,
14008
14190
  elementsMap,
14009
- pointFrom11(
14191
+ pointFrom10(
14010
14192
  scenePointerX - linearElementEditor.pointerOffset.x,
14011
14193
  scenePointerY - linearElementEditor.pointerOffset.y
14012
14194
  )
@@ -14086,7 +14268,7 @@ var pointDraggingUpdates = (selectedPointsIndices, deltaX, deltaY, scenePointerX
14086
14268
  updates.suggestedBinding = start2.element ? {
14087
14269
  element: start2.element,
14088
14270
  midPoint: getSnapOutlineMidPoint(
14089
- pointFrom11(
14271
+ pointFrom10(
14090
14272
  scenePointerX - linearElementEditor.pointerOffset.x,
14091
14273
  scenePointerY - linearElementEditor.pointerOffset.y
14092
14274
  ),
@@ -14117,7 +14299,7 @@ var pointDraggingUpdates = (selectedPointsIndices, deltaX, deltaY, scenePointerX
14117
14299
  updates.suggestedBinding = end.element ? {
14118
14300
  element: end.element,
14119
14301
  midPoint: getSnapOutlineMidPoint(
14120
- pointFrom11(
14302
+ pointFrom10(
14121
14303
  scenePointerX - linearElementEditor.pointerOffset.x,
14122
14304
  scenePointerY - linearElementEditor.pointerOffset.y
14123
14305
  ),
@@ -14130,11 +14312,11 @@ var pointDraggingUpdates = (selectedPointsIndices, deltaX, deltaY, scenePointerX
14130
14312
  } else if (endIsDragged) {
14131
14313
  updates.suggestedBinding = app.state.suggestedBinding;
14132
14314
  }
14133
- const offsetStartLocalPoint = startIsDragged ? pointFrom11(
14315
+ const offsetStartLocalPoint = startIsDragged ? pointFrom10(
14134
14316
  element.points[0][0] + deltaX,
14135
14317
  element.points[0][1] + deltaY
14136
14318
  ) : element.points[0];
14137
- const offsetEndLocalPoint = endIsDragged ? pointFrom11(
14319
+ const offsetEndLocalPoint = endIsDragged ? pointFrom10(
14138
14320
  element.points[element.points.length - 1][0] + deltaX,
14139
14321
  element.points[element.points.length - 1][1] + deltaY
14140
14322
  ) : element.points[element.points.length - 1];
@@ -14203,11 +14385,338 @@ var pointDraggingUpdates = (selectedPointsIndices, deltaX, deltaY, scenePointerX
14203
14385
  };
14204
14386
  var determineCustomLinearAngle = (pivotPoint, draggedPoint) => Math.atan2(draggedPoint[1] - pivotPoint[1], draggedPoint[0] - pivotPoint[0]);
14205
14387
 
14206
- // src/renderElement.ts
14207
- var isPendingImageElement = (element, renderConfig) => isInitializedImageElement(element) && !renderConfig.imageCache.has(element.fileId);
14208
- var getCanvasPadding = (element) => {
14209
- switch (element.type) {
14210
- case "freedraw":
14388
+ // src/image.ts
14389
+ init_define_import_meta_env();
14390
+ import { MIME_TYPES, SVG_NS } from "@excalidraw/common";
14391
+
14392
+ // ../../node_modules/thumbhash/thumbhash.js
14393
+ init_define_import_meta_env();
14394
+ function rgbaToThumbHash(w, h, rgba) {
14395
+ if (w > 100 || h > 100)
14396
+ throw new Error(`${w}x${h} doesn't fit in 100x100`);
14397
+ let { PI, round, max, cos, abs } = Math;
14398
+ let avg_r = 0, avg_g = 0, avg_b = 0, avg_a = 0;
14399
+ for (let i = 0, j = 0; i < w * h; i++, j += 4) {
14400
+ let alpha = rgba[j + 3] / 255;
14401
+ avg_r += alpha / 255 * rgba[j];
14402
+ avg_g += alpha / 255 * rgba[j + 1];
14403
+ avg_b += alpha / 255 * rgba[j + 2];
14404
+ avg_a += alpha;
14405
+ }
14406
+ if (avg_a) {
14407
+ avg_r /= avg_a;
14408
+ avg_g /= avg_a;
14409
+ avg_b /= avg_a;
14410
+ }
14411
+ let hasAlpha = avg_a < w * h;
14412
+ let l_limit = hasAlpha ? 5 : 7;
14413
+ let lx = max(1, round(l_limit * w / max(w, h)));
14414
+ let ly = max(1, round(l_limit * h / max(w, h)));
14415
+ let l2 = [];
14416
+ let p = [];
14417
+ let q = [];
14418
+ let a2 = [];
14419
+ for (let i = 0, j = 0; i < w * h; i++, j += 4) {
14420
+ let alpha = rgba[j + 3] / 255;
14421
+ let r = avg_r * (1 - alpha) + alpha / 255 * rgba[j];
14422
+ let g = avg_g * (1 - alpha) + alpha / 255 * rgba[j + 1];
14423
+ let b2 = avg_b * (1 - alpha) + alpha / 255 * rgba[j + 2];
14424
+ l2[i] = (r + g + b2) / 3;
14425
+ p[i] = (r + g) / 2 - b2;
14426
+ q[i] = r - g;
14427
+ a2[i] = alpha;
14428
+ }
14429
+ let encodeChannel = (channel, nx, ny) => {
14430
+ let dc = 0, ac = [], scale = 0, fx = [];
14431
+ for (let cy = 0; cy < ny; cy++) {
14432
+ for (let cx = 0; cx * ny < nx * (ny - cy); cx++) {
14433
+ let f = 0;
14434
+ for (let x = 0; x < w; x++)
14435
+ fx[x] = cos(PI / w * cx * (x + 0.5));
14436
+ for (let y = 0; y < h; y++)
14437
+ for (let x = 0, fy = cos(PI / h * cy * (y + 0.5)); x < w; x++)
14438
+ f += channel[x + y * w] * fx[x] * fy;
14439
+ f /= w * h;
14440
+ if (cx || cy) {
14441
+ ac.push(f);
14442
+ scale = max(scale, abs(f));
14443
+ } else {
14444
+ dc = f;
14445
+ }
14446
+ }
14447
+ }
14448
+ if (scale)
14449
+ for (let i = 0; i < ac.length; i++)
14450
+ ac[i] = 0.5 + 0.5 / scale * ac[i];
14451
+ return [dc, ac, scale];
14452
+ };
14453
+ let [l_dc, l_ac, l_scale] = encodeChannel(l2, max(3, lx), max(3, ly));
14454
+ let [p_dc, p_ac, p_scale] = encodeChannel(p, 3, 3);
14455
+ let [q_dc, q_ac, q_scale] = encodeChannel(q, 3, 3);
14456
+ let [a_dc, a_ac, a_scale] = hasAlpha ? encodeChannel(a2, 5, 5) : [];
14457
+ let isLandscape = w > h;
14458
+ let header24 = round(63 * l_dc) | round(31.5 + 31.5 * p_dc) << 6 | round(31.5 + 31.5 * q_dc) << 12 | round(31 * l_scale) << 18 | hasAlpha << 23;
14459
+ let header16 = (isLandscape ? ly : lx) | round(63 * p_scale) << 3 | round(63 * q_scale) << 9 | isLandscape << 15;
14460
+ let hash = [header24 & 255, header24 >> 8 & 255, header24 >> 16, header16 & 255, header16 >> 8];
14461
+ let ac_start = hasAlpha ? 6 : 5;
14462
+ let ac_index = 0;
14463
+ if (hasAlpha)
14464
+ hash.push(round(15 * a_dc) | round(15 * a_scale) << 4);
14465
+ for (let ac of hasAlpha ? [l_ac, p_ac, q_ac, a_ac] : [l_ac, p_ac, q_ac])
14466
+ for (let f of ac)
14467
+ hash[ac_start + (ac_index >> 1)] |= round(15 * f) << ((ac_index++ & 1) << 2);
14468
+ return new Uint8Array(hash);
14469
+ }
14470
+ function thumbHashToRGBA(hash) {
14471
+ let { PI, min, max, cos, round } = Math;
14472
+ let header24 = hash[0] | hash[1] << 8 | hash[2] << 16;
14473
+ let header16 = hash[3] | hash[4] << 8;
14474
+ let l_dc = (header24 & 63) / 63;
14475
+ let p_dc = (header24 >> 6 & 63) / 31.5 - 1;
14476
+ let q_dc = (header24 >> 12 & 63) / 31.5 - 1;
14477
+ let l_scale = (header24 >> 18 & 31) / 31;
14478
+ let hasAlpha = header24 >> 23;
14479
+ let p_scale = (header16 >> 3 & 63) / 63;
14480
+ let q_scale = (header16 >> 9 & 63) / 63;
14481
+ let isLandscape = header16 >> 15;
14482
+ let lx = max(3, isLandscape ? hasAlpha ? 5 : 7 : header16 & 7);
14483
+ let ly = max(3, isLandscape ? header16 & 7 : hasAlpha ? 5 : 7);
14484
+ let a_dc = hasAlpha ? (hash[5] & 15) / 15 : 1;
14485
+ let a_scale = (hash[5] >> 4) / 15;
14486
+ let ac_start = hasAlpha ? 6 : 5;
14487
+ let ac_index = 0;
14488
+ let decodeChannel = (nx, ny, scale) => {
14489
+ let ac = [];
14490
+ for (let cy = 0; cy < ny; cy++)
14491
+ for (let cx = cy ? 0 : 1; cx * ny < nx * (ny - cy); cx++)
14492
+ ac.push(((hash[ac_start + (ac_index >> 1)] >> ((ac_index++ & 1) << 2) & 15) / 7.5 - 1) * scale);
14493
+ return ac;
14494
+ };
14495
+ let l_ac = decodeChannel(lx, ly, l_scale);
14496
+ let p_ac = decodeChannel(3, 3, p_scale * 1.25);
14497
+ let q_ac = decodeChannel(3, 3, q_scale * 1.25);
14498
+ let a_ac = hasAlpha && decodeChannel(5, 5, a_scale);
14499
+ let ratio = thumbHashToApproximateAspectRatio(hash);
14500
+ let w = round(ratio > 1 ? 32 : 32 * ratio);
14501
+ let h = round(ratio > 1 ? 32 / ratio : 32);
14502
+ let rgba = new Uint8Array(w * h * 4), fx = [], fy = [];
14503
+ for (let y = 0, i = 0; y < h; y++) {
14504
+ for (let x = 0; x < w; x++, i += 4) {
14505
+ let l2 = l_dc, p = p_dc, q = q_dc, a2 = a_dc;
14506
+ for (let cx = 0, n = max(lx, hasAlpha ? 5 : 3); cx < n; cx++)
14507
+ fx[cx] = cos(PI / w * (x + 0.5) * cx);
14508
+ for (let cy = 0, n = max(ly, hasAlpha ? 5 : 3); cy < n; cy++)
14509
+ fy[cy] = cos(PI / h * (y + 0.5) * cy);
14510
+ for (let cy = 0, j = 0; cy < ly; cy++)
14511
+ for (let cx = cy ? 0 : 1, fy2 = fy[cy] * 2; cx * ly < lx * (ly - cy); cx++, j++)
14512
+ l2 += l_ac[j] * fx[cx] * fy2;
14513
+ for (let cy = 0, j = 0; cy < 3; cy++) {
14514
+ for (let cx = cy ? 0 : 1, fy2 = fy[cy] * 2; cx < 3 - cy; cx++, j++) {
14515
+ let f = fx[cx] * fy2;
14516
+ p += p_ac[j] * f;
14517
+ q += q_ac[j] * f;
14518
+ }
14519
+ }
14520
+ if (hasAlpha)
14521
+ for (let cy = 0, j = 0; cy < 5; cy++)
14522
+ for (let cx = cy ? 0 : 1, fy2 = fy[cy] * 2; cx < 5 - cy; cx++, j++)
14523
+ a2 += a_ac[j] * fx[cx] * fy2;
14524
+ let b2 = l2 - 2 / 3 * p;
14525
+ let r = (3 * l2 - b2 + q) / 2;
14526
+ let g = r - q;
14527
+ rgba[i] = max(0, 255 * min(1, r));
14528
+ rgba[i + 1] = max(0, 255 * min(1, g));
14529
+ rgba[i + 2] = max(0, 255 * min(1, b2));
14530
+ rgba[i + 3] = max(0, 255 * min(1, a2));
14531
+ }
14532
+ }
14533
+ return { w, h, rgba };
14534
+ }
14535
+ function thumbHashToApproximateAspectRatio(hash) {
14536
+ let header = hash[3];
14537
+ let hasAlpha = hash[2] & 128;
14538
+ let isLandscape = hash[4] & 128;
14539
+ let lx = isLandscape ? hasAlpha ? 5 : 7 : header & 7;
14540
+ let ly = isLandscape ? header & 7 : hasAlpha ? 5 : 7;
14541
+ return lx / ly;
14542
+ }
14543
+
14544
+ // src/image.ts
14545
+ var THUMB_HASH_MAX_DIMENSION = 100;
14546
+ var thumbHashCanvasCache = /* @__PURE__ */ new Map();
14547
+ var invalidThumbHashes = /* @__PURE__ */ new Set();
14548
+ var bytesToBase64 = (bytes) => {
14549
+ let binary = "";
14550
+ for (const byte of bytes) {
14551
+ binary += String.fromCharCode(byte);
14552
+ }
14553
+ return btoa(binary);
14554
+ };
14555
+ var base64ToBytes = (base64) => {
14556
+ const binary = atob(base64);
14557
+ const bytes = new Uint8Array(binary.length);
14558
+ for (let index = 0; index < binary.length; index++) {
14559
+ bytes[index] = binary.charCodeAt(index);
14560
+ }
14561
+ return bytes;
14562
+ };
14563
+ var generateThumbHash = (image) => {
14564
+ const naturalWidth = image.naturalWidth || image.width;
14565
+ const naturalHeight = image.naturalHeight || image.height;
14566
+ if (!naturalWidth || !naturalHeight) {
14567
+ return null;
14568
+ }
14569
+ const scale = Math.min(
14570
+ 1,
14571
+ THUMB_HASH_MAX_DIMENSION / Math.max(naturalWidth, naturalHeight)
14572
+ );
14573
+ const width = Math.max(1, Math.round(naturalWidth * scale));
14574
+ const height = Math.max(1, Math.round(naturalHeight * scale));
14575
+ const canvas = document.createElement("canvas");
14576
+ canvas.width = width;
14577
+ canvas.height = height;
14578
+ const context = canvas.getContext("2d");
14579
+ if (!context) {
14580
+ return null;
14581
+ }
14582
+ context.drawImage(image, 0, 0, width, height);
14583
+ const imageData = context.getImageData(0, 0, width, height);
14584
+ return bytesToBase64(rgbaToThumbHash(width, height, imageData.data));
14585
+ };
14586
+ var getThumbHashPlaceholder = (thumbHash) => {
14587
+ if (invalidThumbHashes.has(thumbHash)) {
14588
+ return null;
14589
+ }
14590
+ const cached = thumbHashCanvasCache.get(thumbHash);
14591
+ if (cached) {
14592
+ return cached;
14593
+ }
14594
+ try {
14595
+ const { w, h, rgba } = thumbHashToRGBA(base64ToBytes(thumbHash));
14596
+ const canvas = document.createElement("canvas");
14597
+ canvas.width = w;
14598
+ canvas.height = h;
14599
+ const context = canvas.getContext("2d");
14600
+ if (!context) {
14601
+ return null;
14602
+ }
14603
+ const imageData = context.createImageData(w, h);
14604
+ imageData.data.set(rgba);
14605
+ context.putImageData(imageData, 0, 0);
14606
+ thumbHashCanvasCache.set(thumbHash, canvas);
14607
+ return canvas;
14608
+ } catch (error) {
14609
+ invalidThumbHashes.add(thumbHash);
14610
+ console.warn("Invalid ThumbHash", error);
14611
+ return null;
14612
+ }
14613
+ };
14614
+ var loadHTMLImageElement = (dataURL) => {
14615
+ return new Promise((resolve, reject) => {
14616
+ const image = new Image();
14617
+ image.onload = () => {
14618
+ resolve(image);
14619
+ };
14620
+ image.onerror = (error) => {
14621
+ reject(error);
14622
+ };
14623
+ image.src = dataURL;
14624
+ });
14625
+ };
14626
+ var updateImageCache = async ({
14627
+ fileIds,
14628
+ files,
14629
+ imageCache
14630
+ }) => {
14631
+ const updatedFiles = /* @__PURE__ */ new Map();
14632
+ const erroredFiles = /* @__PURE__ */ new Map();
14633
+ await Promise.all(
14634
+ fileIds.reduce((promises, fileId) => {
14635
+ const fileData = files[fileId];
14636
+ if (fileData && !updatedFiles.has(fileId)) {
14637
+ updatedFiles.set(fileId, true);
14638
+ return promises.concat(
14639
+ (async () => {
14640
+ try {
14641
+ if (fileData.mimeType === MIME_TYPES.binary) {
14642
+ throw new Error("Only images can be added to ImageCache");
14643
+ }
14644
+ const imagePromise = loadHTMLImageElement(fileData.dataURL);
14645
+ const data = {
14646
+ image: imagePromise,
14647
+ mimeType: fileData.mimeType
14648
+ };
14649
+ imageCache.set(fileId, data);
14650
+ const image = await imagePromise;
14651
+ imageCache.set(fileId, { ...data, image });
14652
+ } catch (error) {
14653
+ erroredFiles.set(fileId, true);
14654
+ }
14655
+ })()
14656
+ );
14657
+ }
14658
+ return promises;
14659
+ }, [])
14660
+ );
14661
+ return {
14662
+ imageCache,
14663
+ /** includes errored files because they cache was updated nonetheless */
14664
+ updatedFiles,
14665
+ /** files that failed when creating HTMLImageElement */
14666
+ erroredFiles
14667
+ };
14668
+ };
14669
+ var getInitializedImageElements = (elements) => elements.filter(
14670
+ (element) => isInitializedImageElement(element)
14671
+ );
14672
+ var isHTMLSVGElement = (node) => {
14673
+ return node?.nodeName.toLowerCase() === "svg";
14674
+ };
14675
+ var normalizeSVG = (SVGString) => {
14676
+ const doc = new DOMParser().parseFromString(SVGString, MIME_TYPES.svg);
14677
+ const svg = doc.querySelector("svg");
14678
+ const errorNode = doc.querySelector("parsererror");
14679
+ if (errorNode || !isHTMLSVGElement(svg)) {
14680
+ throw new Error("Invalid SVG");
14681
+ } else {
14682
+ if (!svg.hasAttribute("xmlns")) {
14683
+ svg.setAttribute("xmlns", SVG_NS);
14684
+ }
14685
+ let width = svg.getAttribute("width");
14686
+ let height = svg.getAttribute("height");
14687
+ if (width?.includes("%") || width === "auto") {
14688
+ width = null;
14689
+ }
14690
+ if (height?.includes("%") || height === "auto") {
14691
+ height = null;
14692
+ }
14693
+ const viewBox = svg.getAttribute("viewBox");
14694
+ if (!width || !height) {
14695
+ width = width || "50";
14696
+ height = height || "50";
14697
+ if (viewBox) {
14698
+ const match = viewBox.match(
14699
+ /\d+ +\d+ +(\d+(?:\.\d+)?) +(\d+(?:\.\d+)?)/
14700
+ );
14701
+ if (match) {
14702
+ [, width, height] = match;
14703
+ }
14704
+ }
14705
+ svg.setAttribute("width", width);
14706
+ svg.setAttribute("height", height);
14707
+ }
14708
+ if (!viewBox) {
14709
+ svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
14710
+ }
14711
+ return svg.outerHTML;
14712
+ }
14713
+ };
14714
+
14715
+ // src/renderElement.ts
14716
+ var isPendingImageElement = (element, renderConfig) => isInitializedImageElement(element) && !renderConfig.imageCache.has(element.fileId);
14717
+ var getCanvasPadding = (element) => {
14718
+ switch (element.type) {
14719
+ case "freedraw":
14211
14720
  return element.strokeWidth * 12;
14212
14721
  case "text":
14213
14722
  return element.fontSize / 2;
@@ -14332,14 +14841,27 @@ var generateElementCanvas = (element, elementsMap, zoom, renderConfig, appState)
14332
14841
  };
14333
14842
  var DEFAULT_LINK_SIZE = 14;
14334
14843
  var IMAGE_PLACEHOLDER_IMG = typeof document !== "undefined" ? document.createElement("img") : { src: "" };
14335
- IMAGE_PLACEHOLDER_IMG.src = `data:${MIME_TYPES.svg},${encodeURIComponent(
14844
+ IMAGE_PLACEHOLDER_IMG.src = `data:${MIME_TYPES2.svg},${encodeURIComponent(
14336
14845
  `<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="image" class="svg-inline--fa fa-image fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#888" d="M464 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48zM112 120c-30.928 0-56 25.072-56 56s25.072 56 56 56 56-25.072 56-56-25.072-56-56-56zM64 384h384V272l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L208 320l-55.515-55.515c-4.686-4.686-12.284-4.686-16.971 0L64 336v48z"></path></svg>`
14337
14846
  )}`;
14338
14847
  var IMAGE_ERROR_PLACEHOLDER_IMG = typeof document !== "undefined" ? document.createElement("img") : { src: "" };
14339
- IMAGE_ERROR_PLACEHOLDER_IMG.src = `data:${MIME_TYPES.svg},${encodeURIComponent(
14848
+ IMAGE_ERROR_PLACEHOLDER_IMG.src = `data:${MIME_TYPES2.svg},${encodeURIComponent(
14340
14849
  `<svg viewBox="0 0 668 668" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"><path d="M464 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48ZM112 120c-30.928 0-56 25.072-56 56s25.072 56 56 56 56-25.072 56-56-25.072-56-56-56ZM64 384h384V272l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L208 320l-55.515-55.515c-4.686-4.686-12.284-4.686-16.971 0L64 336v48Z" style="fill:#888;fill-rule:nonzero" transform="matrix(.81709 0 0 .81709 124.825 145.825)"/><path d="M256 8C119.034 8 8 119.033 8 256c0 136.967 111.034 248 248 248s248-111.034 248-248S392.967 8 256 8Zm130.108 117.892c65.448 65.448 70 165.481 20.677 235.637L150.47 105.216c70.204-49.356 170.226-44.735 235.638 20.676ZM125.892 386.108c-65.448-65.448-70-165.481-20.677-235.637L361.53 406.784c-70.203 49.356-170.226 44.736-235.638-20.676Z" style="fill:#888;fill-rule:nonzero" transform="matrix(.30366 0 0 .30366 506.822 60.065)"/></svg>`
14341
14850
  )}`;
14342
14851
  var drawImagePlaceholder = (element, context, theme) => {
14852
+ if (element.status !== "error" && element.thumbHash) {
14853
+ const thumbHashPlaceholder = getThumbHashPlaceholder(element.thumbHash);
14854
+ if (thumbHashPlaceholder) {
14855
+ context.drawImage(
14856
+ thumbHashPlaceholder,
14857
+ 0,
14858
+ 0,
14859
+ element.width,
14860
+ element.height
14861
+ );
14862
+ return;
14863
+ }
14864
+ }
14343
14865
  context.fillStyle = theme === THEME.DARK ? "#2E2E2E" : "#E7E7E7";
14344
14866
  context.fillRect(0, 0, element.width, element.height);
14345
14867
  const imageMinWidthOrHeight = Math.min(element.width, element.height);
@@ -14383,7 +14905,10 @@ var drawElementOnCanvas = (element, rc, context, renderConfig) => {
14383
14905
  const shapes = ShapeCache.generateElementShape(element, renderConfig);
14384
14906
  for (const shape of shapes) {
14385
14907
  if (typeof shape === "string") {
14386
- context.fillStyle = renderConfig.theme === THEME.DARK ? applyDarkModeFilter(element.strokeColor) : element.strokeColor;
14908
+ context.fillStyle = applyDarkModeFilter(
14909
+ element.strokeColor,
14910
+ renderConfig.theme === THEME.DARK
14911
+ );
14387
14912
  context.fill(new Path2D(shape));
14388
14913
  } else {
14389
14914
  rc.draw(shape);
@@ -14408,13 +14933,42 @@ var drawElementOnCanvas = (element, rc, context, renderConfig) => {
14408
14933
  );
14409
14934
  context.clip();
14410
14935
  }
14936
+ const transitionDuration = renderConfig.imageTransitionDuration ?? 0;
14937
+ if (!renderConfig.isExporting && cacheEntry?.transitionStart !== void 0) {
14938
+ if (transitionDuration > 0) {
14939
+ const transitionProgress = Math.min(
14940
+ 1,
14941
+ (performance.now() - cacheEntry.transitionStart) / transitionDuration
14942
+ );
14943
+ if (transitionProgress < 1) {
14944
+ if (cacheEntry.placeholderImage) {
14945
+ context.drawImage(
14946
+ cacheEntry.placeholderImage,
14947
+ 0,
14948
+ 0,
14949
+ element.width,
14950
+ element.height
14951
+ );
14952
+ } else {
14953
+ drawImagePlaceholder(element, context, renderConfig.theme);
14954
+ }
14955
+ context.globalAlpha *= transitionProgress;
14956
+ } else {
14957
+ delete cacheEntry.placeholderImage;
14958
+ delete cacheEntry.transitionStart;
14959
+ }
14960
+ } else {
14961
+ delete cacheEntry.placeholderImage;
14962
+ delete cacheEntry.transitionStart;
14963
+ }
14964
+ }
14411
14965
  const { x, y, width, height } = element.crop ? element.crop : {
14412
14966
  x: 0,
14413
14967
  y: 0,
14414
14968
  width: img.naturalWidth,
14415
14969
  height: img.naturalHeight
14416
14970
  };
14417
- const shouldInvertImage = renderConfig.theme === THEME.DARK && cacheEntry?.mimeType === MIME_TYPES.svg;
14971
+ const shouldInvertImage = renderConfig.theme === THEME.DARK && cacheEntry?.mimeType === MIME_TYPES2.svg;
14418
14972
  if (shouldInvertImage && isSafari) {
14419
14973
  const devicePixelRatio = window.devicePixelRatio || 1;
14420
14974
  const tempCanvas = document.createElement("canvas");
@@ -14491,7 +15045,10 @@ var drawElementOnCanvas = (element, rc, context, renderConfig) => {
14491
15045
  context.canvas.setAttribute("dir", rtl ? "rtl" : "ltr");
14492
15046
  context.save();
14493
15047
  context.font = getFontString3(element);
14494
- context.fillStyle = renderConfig.theme === THEME.DARK ? applyDarkModeFilter(element.strokeColor) : element.strokeColor;
15048
+ context.fillStyle = applyDarkModeFilter(
15049
+ element.strokeColor,
15050
+ renderConfig.theme === THEME.DARK
15051
+ );
14495
15052
  context.textAlign = element.textAlign;
14496
15053
  const lines = element.text.replace(/\r\n?/g, "\n").split("\n");
14497
15054
  const horizontalOffset = element.textAlign === "center" ? element.width / 2 : element.textAlign === "right" ? element.width : 0;
@@ -14531,8 +15088,9 @@ var generateElementWithCanvas = (element, elementsMap, renderConfig, appState) =
14531
15088
  const boundTextElement = getBoundTextElement(element, elementsMap);
14532
15089
  const boundTextElementVersion = boundTextElement?.version || null;
14533
15090
  const imageCrop = isImageElement(element) ? element.crop : null;
15091
+ const hasActiveImageTransition = isInitializedImageElement(element) && renderConfig.imageCache.get(element.fileId)?.transitionStart !== void 0;
14534
15092
  const containingFrameOpacity = getContainingFrame(element, elementsMap)?.opacity || 100;
14535
- if (!prevElementWithCanvas || shouldRegenerateBecauseZoom || prevElementWithCanvas.theme !== appState.theme || prevElementWithCanvas.boundTextElementVersion !== boundTextElementVersion || prevElementWithCanvas.imageCrop !== imageCrop || prevElementWithCanvas.containingFrameOpacity !== containingFrameOpacity || // since we rotate the canvas when copying from cached canvas, we don't
15093
+ if (!prevElementWithCanvas || shouldRegenerateBecauseZoom || prevElementWithCanvas.theme !== appState.theme || prevElementWithCanvas.boundTextElementVersion !== boundTextElementVersion || prevElementWithCanvas.imageCrop !== imageCrop || hasActiveImageTransition || prevElementWithCanvas.containingFrameOpacity !== containingFrameOpacity || // since we rotate the canvas when copying from cached canvas, we don't
14536
15094
  // regenerate the cached canvas. But we need to in case of labels which are
14537
15095
  // cached alongside the arrow, and we want the labels to remain unrotated
14538
15096
  // with respect to the arrow.
@@ -14639,7 +15197,10 @@ var renderElement = (element, elementsMap, allElementsMap, rc, context, renderCo
14639
15197
  );
14640
15198
  context.fillStyle = "rgba(0, 0, 200, 0.04)";
14641
15199
  context.lineWidth = FRAME_STYLE.strokeWidth / appState.zoom.value;
14642
- context.strokeStyle = appState.theme === THEME.DARK ? applyDarkModeFilter(FRAME_STYLE.strokeColor) : FRAME_STYLE.strokeColor;
15200
+ context.strokeStyle = applyDarkModeFilter(
15201
+ FRAME_STYLE.strokeColor,
15202
+ appState.theme === THEME.DARK
15203
+ );
14643
15204
  if (isMagicFrameElement(element)) {
14644
15205
  context.strokeStyle = appState.theme === THEME.LIGHT ? "#7affd7" : applyDarkModeFilter("#1d8264");
14645
15206
  }
@@ -14705,8 +15266,10 @@ var renderElement = (element, elementsMap, allElementsMap, rc, context, renderCo
14705
15266
  case "embeddable": {
14706
15267
  if (renderConfig.isExporting) {
14707
15268
  const [x1, y1, x2, y2] = getElementAbsoluteCoords2(element, elementsMap);
14708
- const cx = (x1 + x2) / 2 + appState.scrollX;
14709
- const cy = (y1 + y2) / 2 + appState.scrollY;
15269
+ const centerX = (x1 + x2) / 2;
15270
+ const centerY = (y1 + y2) / 2;
15271
+ const cx = centerX + appState.scrollX;
15272
+ const cy = centerY + appState.scrollY;
14710
15273
  let shiftX = (x2 - x1) / 2 - (element.x - x1);
14711
15274
  let shiftY = (y2 - y1) / 2 - (element.y - y1);
14712
15275
  if (isTextElement(element)) {
@@ -14725,46 +15288,33 @@ var renderElement = (element, elementsMap, allElementsMap, rc, context, renderCo
14725
15288
  context.translate(cx, cy);
14726
15289
  const boundTextElement = getBoundTextElement(element, elementsMap);
14727
15290
  if (isArrowElement(element) && boundTextElement) {
14728
- const tempCanvas = document.createElement("canvas");
14729
- const tempCanvasContext = tempCanvas.getContext("2d");
14730
- const maxDim = Math.max(distance2(x1, x2), distance2(y1, y2));
14731
- const padding = getCanvasPadding(element);
14732
- tempCanvas.width = maxDim * appState.exportScale + padding * 10 * appState.exportScale;
14733
- tempCanvas.height = maxDim * appState.exportScale + padding * 10 * appState.exportScale;
14734
- tempCanvasContext.translate(
14735
- tempCanvas.width / 2,
14736
- tempCanvas.height / 2
14737
- );
14738
- tempCanvasContext.scale(appState.exportScale, appState.exportScale);
14739
15291
  shiftX = element.width / 2 - (element.x - x1);
14740
15292
  shiftY = element.height / 2 - (element.y - y1);
14741
- tempCanvasContext.rotate(element.angle);
14742
- const tempRc = rough_default.canvas(tempCanvas);
14743
- tempCanvasContext.translate(-shiftX, -shiftY);
14744
- drawElementOnCanvas(element, tempRc, tempCanvasContext, renderConfig);
14745
- tempCanvasContext.translate(shiftX, shiftY);
14746
- tempCanvasContext.rotate(-element.angle);
15293
+ context.save();
15294
+ context.rotate(element.angle);
15295
+ context.translate(-shiftX, -shiftY);
15296
+ drawElementOnCanvas(element, rc, context, renderConfig);
15297
+ context.restore();
14747
15298
  const [, , , , boundTextCx, boundTextCy] = getElementAbsoluteCoords2(
14748
15299
  boundTextElement,
14749
15300
  elementsMap
14750
15301
  );
14751
- const boundTextShiftX = (x1 + x2) / 2 - boundTextCx;
14752
- const boundTextShiftY = (y1 + y2) / 2 - boundTextCy;
14753
- tempCanvasContext.translate(-boundTextShiftX, -boundTextShiftY);
14754
- tempCanvasContext.clearRect(
14755
- -boundTextElement.width / 2,
14756
- -boundTextElement.height / 2,
14757
- boundTextElement.width,
14758
- boundTextElement.height
14759
- );
14760
- context.scale(1 / appState.exportScale, 1 / appState.exportScale);
14761
- context.drawImage(
14762
- tempCanvas,
14763
- -tempCanvas.width / 2,
14764
- -tempCanvas.height / 2,
14765
- tempCanvas.width,
14766
- tempCanvas.height
14767
- );
15302
+ const holeX = boundTextCx - centerX - boundTextElement.width / 2 - BOUND_TEXT_PADDING3;
15303
+ const holeY = boundTextCy - centerY - boundTextElement.height / 2 - BOUND_TEXT_PADDING3;
15304
+ const holeWidth = boundTextElement.width + BOUND_TEXT_PADDING3 * 2;
15305
+ const holeHeight = boundTextElement.height + BOUND_TEXT_PADDING3 * 2;
15306
+ const isTransparentHole = "viewBackgroundColor" in appState && (appState.viewBackgroundColor === "transparent" || !appState.viewBackgroundColor);
15307
+ if (!isTransparentHole) {
15308
+ context.save();
15309
+ context.fillStyle = applyDarkModeFilter(
15310
+ renderConfig.canvasBackgroundColor,
15311
+ renderConfig.theme === THEME.DARK
15312
+ );
15313
+ context.fillRect(holeX, holeY, holeWidth, holeHeight);
15314
+ context.restore();
15315
+ } else {
15316
+ context.clearRect(holeX, holeY, holeWidth, holeHeight);
15317
+ }
14768
15318
  } else {
14769
15319
  context.rotate(element.angle);
14770
15320
  if (element.type === "image") {
@@ -14842,7 +15392,7 @@ function getFreedrawOutlineAsSegments(element, points, elementsMap) {
14842
15392
  },
14843
15393
  elementsMap
14844
15394
  );
14845
- const center = pointFrom12(
15395
+ const center = pointFrom11(
14846
15396
  (bounds[0] + bounds[2]) / 2,
14847
15397
  (bounds[1] + bounds[3]) / 2
14848
15398
  );
@@ -14850,10 +15400,10 @@ function getFreedrawOutlineAsSegments(element, points, elementsMap) {
14850
15400
  return points.slice(2).reduce(
14851
15401
  (acc, curr) => {
14852
15402
  acc.push(
14853
- lineSegment6(
15403
+ lineSegment5(
14854
15404
  acc[acc.length - 1][1],
14855
- pointRotateRads11(
14856
- pointFrom12(curr[0] + element.x, curr[1] + element.y),
15405
+ pointRotateRads10(
15406
+ pointFrom11(curr[0] + element.x, curr[1] + element.y),
14857
15407
  center,
14858
15408
  element.angle
14859
15409
  )
@@ -14862,17 +15412,17 @@ function getFreedrawOutlineAsSegments(element, points, elementsMap) {
14862
15412
  return acc;
14863
15413
  },
14864
15414
  [
14865
- lineSegment6(
14866
- pointRotateRads11(
14867
- pointFrom12(
15415
+ lineSegment5(
15416
+ pointRotateRads10(
15417
+ pointFrom11(
14868
15418
  points[0][0] + element.x,
14869
15419
  points[0][1] + element.y
14870
15420
  ),
14871
15421
  center,
14872
15422
  element.angle
14873
15423
  ),
14874
- pointRotateRads11(
14875
- pointFrom12(
15424
+ pointRotateRads10(
15425
+ pointFrom11(
14876
15426
  points[1][0] + element.x,
14877
15427
  points[1][1] + element.y
14878
15428
  ),
@@ -14967,7 +15517,7 @@ var generateRoughOptions = (element, continuousPath = false, isDarkMode = false)
14967
15517
  fillWeight: element.strokeWidth / 2,
14968
15518
  hachureGap: element.strokeWidth * 4,
14969
15519
  roughness: adjustRoughness(element),
14970
- stroke: isDarkMode ? applyDarkModeFilter2(element.strokeColor) : element.strokeColor,
15520
+ stroke: applyDarkModeFilter2(element.strokeColor, isDarkMode),
14971
15521
  preserveVertices: continuousPath || element.roughness < ROUGHNESS.cartoonist
14972
15522
  };
14973
15523
  switch (element.type) {
@@ -14977,7 +15527,7 @@ var generateRoughOptions = (element, continuousPath = false, isDarkMode = false)
14977
15527
  case "diamond":
14978
15528
  case "ellipse": {
14979
15529
  options.fillStyle = element.fillStyle;
14980
- options.fill = isTransparent3(element.backgroundColor) ? void 0 : isDarkMode ? applyDarkModeFilter2(element.backgroundColor) : element.backgroundColor;
15530
+ options.fill = isTransparent3(element.backgroundColor) ? void 0 : applyDarkModeFilter2(element.backgroundColor, isDarkMode);
14981
15531
  if (element.type === "ellipse") {
14982
15532
  options.curveFitting = 1;
14983
15533
  }
@@ -14987,7 +15537,7 @@ var generateRoughOptions = (element, continuousPath = false, isDarkMode = false)
14987
15537
  case "freedraw": {
14988
15538
  if (isPathALoop(element.points)) {
14989
15539
  options.fillStyle = element.fillStyle;
14990
- options.fill = element.backgroundColor === "transparent" ? void 0 : isDarkMode ? applyDarkModeFilter2(element.backgroundColor) : element.backgroundColor;
15540
+ options.fill = element.backgroundColor === "transparent" ? void 0 : applyDarkModeFilter2(element.backgroundColor, isDarkMode);
14991
15541
  }
14992
15542
  return options;
14993
15543
  }
@@ -15062,8 +15612,11 @@ var getArrowheadShapes = (element, shape, position, arrowhead, generator, option
15062
15612
  if (arrowhead === null) {
15063
15613
  return [];
15064
15614
  }
15065
- const strokeColor = isDarkMode ? applyDarkModeFilter2(element.strokeColor) : element.strokeColor;
15066
- const backgroundFillColor = isDarkMode ? applyDarkModeFilter2(canvasBackgroundColor) : canvasBackgroundColor;
15615
+ const strokeColor = applyDarkModeFilter2(element.strokeColor, isDarkMode);
15616
+ const backgroundFillColor = applyDarkModeFilter2(
15617
+ canvasBackgroundColor,
15618
+ isDarkMode
15619
+ );
15067
15620
  const cardinalityOneOrManyOffset = -0.25;
15068
15621
  const cardinalityZeroCircleScale = 0.8;
15069
15622
  switch (arrowhead) {
@@ -15248,26 +15801,26 @@ var generateLinearCollisionShape = (element, elementsMap) => {
15248
15801
  switch (element.type) {
15249
15802
  case "line":
15250
15803
  case "arrow": {
15251
- const points = element.points.length ? element.points : [pointFrom13(0, 0)];
15804
+ const points = element.points.length ? element.points : [pointFrom12(0, 0)];
15252
15805
  if (isElbowArrow(element)) {
15253
15806
  return generator.path(generateElbowArrowShape(points, 16), options).sets[0].ops;
15254
15807
  } else if (!element.roundness) {
15255
15808
  return points.map((point, idx) => {
15256
- const p = pointRotateRads12(
15257
- pointFrom13(element.x + point[0], element.y + point[1]),
15809
+ const p = pointRotateRads11(
15810
+ pointFrom12(element.x + point[0], element.y + point[1]),
15258
15811
  center,
15259
15812
  element.angle
15260
15813
  );
15261
15814
  return {
15262
15815
  op: idx === 0 ? "move" : "lineTo",
15263
- data: pointFrom13(p[0] - element.x, p[1] - element.y)
15816
+ data: pointFrom12(p[0] - element.x, p[1] - element.y)
15264
15817
  };
15265
15818
  });
15266
15819
  }
15267
15820
  return generator.curve(points, options).sets[0].ops.slice(0, element.points.length).map((op, i) => {
15268
15821
  if (i === 0) {
15269
- const p = pointRotateRads12(
15270
- pointFrom13(
15822
+ const p = pointRotateRads11(
15823
+ pointFrom12(
15271
15824
  element.x + op.data[0],
15272
15825
  element.y + op.data[1]
15273
15826
  ),
@@ -15276,30 +15829,30 @@ var generateLinearCollisionShape = (element, elementsMap) => {
15276
15829
  );
15277
15830
  return {
15278
15831
  op: "move",
15279
- data: pointFrom13(p[0] - element.x, p[1] - element.y)
15832
+ data: pointFrom12(p[0] - element.x, p[1] - element.y)
15280
15833
  };
15281
15834
  }
15282
15835
  return {
15283
15836
  op: "bcurveTo",
15284
15837
  data: [
15285
- pointRotateRads12(
15286
- pointFrom13(
15838
+ pointRotateRads11(
15839
+ pointFrom12(
15287
15840
  element.x + op.data[0],
15288
15841
  element.y + op.data[1]
15289
15842
  ),
15290
15843
  center,
15291
15844
  element.angle
15292
15845
  ),
15293
- pointRotateRads12(
15294
- pointFrom13(
15846
+ pointRotateRads11(
15847
+ pointFrom12(
15295
15848
  element.x + op.data[2],
15296
15849
  element.y + op.data[3]
15297
15850
  ),
15298
15851
  center,
15299
15852
  element.angle
15300
15853
  ),
15301
- pointRotateRads12(
15302
- pointFrom13(
15854
+ pointRotateRads11(
15855
+ pointFrom12(
15303
15856
  element.x + op.data[4],
15304
15857
  element.y + op.data[5]
15305
15858
  ),
@@ -15307,7 +15860,7 @@ var generateLinearCollisionShape = (element, elementsMap) => {
15307
15860
  element.angle
15308
15861
  )
15309
15862
  ].map(
15310
- (p) => pointFrom13(p[0] - element.x, p[1] - element.y)
15863
+ (p) => pointFrom12(p[0] - element.x, p[1] - element.y)
15311
15864
  ).flat()
15312
15865
  };
15313
15866
  });
@@ -15322,8 +15875,8 @@ var generateLinearCollisionShape = (element, elementsMap) => {
15322
15875
  );
15323
15876
  return generator.curve(simplifiedPoints, options).sets[0].ops.slice(0, element.points.length).map((op, i) => {
15324
15877
  if (i === 0) {
15325
- const p = pointRotateRads12(
15326
- pointFrom13(
15878
+ const p = pointRotateRads11(
15879
+ pointFrom12(
15327
15880
  element.x + op.data[0],
15328
15881
  element.y + op.data[1]
15329
15882
  ),
@@ -15332,30 +15885,30 @@ var generateLinearCollisionShape = (element, elementsMap) => {
15332
15885
  );
15333
15886
  return {
15334
15887
  op: "move",
15335
- data: pointFrom13(p[0] - element.x, p[1] - element.y)
15888
+ data: pointFrom12(p[0] - element.x, p[1] - element.y)
15336
15889
  };
15337
15890
  }
15338
15891
  return {
15339
15892
  op: "bcurveTo",
15340
15893
  data: [
15341
- pointRotateRads12(
15342
- pointFrom13(
15894
+ pointRotateRads11(
15895
+ pointFrom12(
15343
15896
  element.x + op.data[0],
15344
15897
  element.y + op.data[1]
15345
15898
  ),
15346
15899
  center,
15347
15900
  element.angle
15348
15901
  ),
15349
- pointRotateRads12(
15350
- pointFrom13(
15902
+ pointRotateRads11(
15903
+ pointFrom12(
15351
15904
  element.x + op.data[2],
15352
15905
  element.y + op.data[3]
15353
15906
  ),
15354
15907
  center,
15355
15908
  element.angle
15356
15909
  ),
15357
- pointRotateRads12(
15358
- pointFrom13(
15910
+ pointRotateRads11(
15911
+ pointFrom12(
15359
15912
  element.x + op.data[4],
15360
15913
  element.y + op.data[5]
15361
15914
  ),
@@ -15363,7 +15916,7 @@ var generateLinearCollisionShape = (element, elementsMap) => {
15363
15916
  element.angle
15364
15917
  )
15365
15918
  ].map(
15366
- (p) => pointFrom13(p[0] - element.x, p[1] - element.y)
15919
+ (p) => pointFrom12(p[0] - element.x, p[1] - element.y)
15367
15920
  ).flat()
15368
15921
  };
15369
15922
  });
@@ -15464,7 +16017,7 @@ var _generateElementShape = (element, generator, {
15464
16017
  case "arrow": {
15465
16018
  let shape;
15466
16019
  const options = generateRoughOptions(element, false, isDarkMode);
15467
- const points = element.points.length ? element.points : [pointFrom13(0, 0)];
16020
+ const points = element.points.length ? element.points : [pointFrom12(0, 0)];
15468
16021
  if (isElbowArrow(element)) {
15469
16022
  if (!points.every(
15470
16023
  (point) => Math.abs(point[0]) <= 1e6 && Math.abs(point[1]) <= 1e6
@@ -15628,14 +16181,14 @@ var getElementShape = (element, elementsMap) => {
15628
16181
  return shouldTestInside(element) ? getClosedCurveShape(
15629
16182
  element,
15630
16183
  roughShape,
15631
- pointFrom13(element.x, element.y),
16184
+ pointFrom12(element.x, element.y),
15632
16185
  element.angle,
15633
- pointFrom13(cx, cy)
16186
+ pointFrom12(cx, cy)
15634
16187
  ) : getCurveShape(
15635
16188
  roughShape,
15636
- pointFrom13(element.x, element.y),
16189
+ pointFrom12(element.x, element.y),
15637
16190
  element.angle,
15638
- pointFrom13(cx, cy)
16191
+ pointFrom12(cx, cy)
15639
16192
  );
15640
16193
  }
15641
16194
  case "ellipse":
@@ -15644,7 +16197,7 @@ var getElementShape = (element, elementsMap) => {
15644
16197
  const [, , , , cx, cy] = getElementAbsoluteCoords2(element, elementsMap);
15645
16198
  return getFreedrawShape(
15646
16199
  element,
15647
- pointFrom13(cx, cy),
16200
+ pointFrom12(cx, cy),
15648
16201
  shouldTestInside(element)
15649
16202
  );
15650
16203
  }
@@ -15663,9 +16216,9 @@ var toggleLinePolygonState = (element, nextPolygonState) => {
15663
16216
  firstPoint[1] - lastPoint[1]
15664
16217
  );
15665
16218
  if (distance3 > LINE_POLYGON_POINT_MERGE_DISTANCE || updatedPoints.length < 4) {
15666
- updatedPoints.push(pointFrom13(firstPoint[0], firstPoint[1]));
16219
+ updatedPoints.push(pointFrom12(firstPoint[0], firstPoint[1]));
15667
16220
  } else {
15668
- updatedPoints[updatedPoints.length - 1] = pointFrom13(
16221
+ updatedPoints[updatedPoints.length - 1] = pointFrom12(
15669
16222
  firstPoint[0],
15670
16223
  firstPoint[1]
15671
16224
  );
@@ -15682,19 +16235,46 @@ var getFreeDrawSvgPath = (element) => {
15682
16235
  getFreedrawOutlinePoints(element)
15683
16236
  );
15684
16237
  };
15685
- var getFreedrawOutlinePoints = (element) => {
15686
- const inputPoints = element.simulatePressure ? element.points : element.points.length ? element.points.map(([x, y], i) => [x, y, element.pressures[i]]) : [[0, 0, 0.5]];
16238
+ var VARIABLE_WIDTH_FREEDRAW = {
16239
+ /** Stroke size relative to `strokeWidth` for pressure-sensitive strokes. */
16240
+ SIZE_FACTOR: 4.25,
16241
+ THINNING: 0.6,
16242
+ SMOOTHING: 0.5
16243
+ };
16244
+ var CONSTANT_WIDTH_FREEDRAW = {
16245
+ /** Stroke size relative to `strokeWidth` for uniform (laser) strokes. */
16246
+ SIZE_FACTOR: 1.4
16247
+ };
16248
+ var getFreedrawStreamline = (element) => element.strokeOptions?.streamline ?? DEFAULT_STROKE_STREAMLINE;
16249
+ var getVariableWidthFreedrawOutline = (element) => {
16250
+ const inputPoints = element.simulatePressure ? element.points : element.points.length ? element.points.map(
16251
+ ([x, y], i) => [x, y, element.pressures[i]]
16252
+ ) : [[0, 0, 0.5]];
15687
16253
  return ae(inputPoints, {
15688
16254
  simulatePressure: element.simulatePressure,
15689
- size: element.strokeWidth * 4.25,
15690
- thinning: 0.6,
15691
- smoothing: 0.5,
15692
- streamline: 0.5,
16255
+ size: element.strokeWidth * VARIABLE_WIDTH_FREEDRAW.SIZE_FACTOR,
16256
+ thinning: VARIABLE_WIDTH_FREEDRAW.THINNING,
16257
+ smoothing: VARIABLE_WIDTH_FREEDRAW.SMOOTHING,
16258
+ streamline: getFreedrawStreamline(element),
15693
16259
  easing: (t) => Math.sin(t * Math.PI / 2),
15694
16260
  // https://easings.net/#easeOutSine
15695
16261
  last: true
15696
16262
  });
15697
16263
  };
16264
+ var createLaserPointer = (element) => new LaserPointer({
16265
+ size: element.strokeWidth * CONSTANT_WIDTH_FREEDRAW.SIZE_FACTOR,
16266
+ streamline: getFreedrawStreamline(element),
16267
+ simplify: 0,
16268
+ sizeMapping: (details) => Math.max(0.1, details.pressure)
16269
+ });
16270
+ var getConstantWidthFreedrawOutline = (element) => {
16271
+ const laserPointer = createLaserPointer(element);
16272
+ element.points.map(([x, y]) => laserPointer.addPoint([x, y, 1]));
16273
+ return laserPointer.getStrokeOutline().map(([x, y]) => [x, y]);
16274
+ };
16275
+ var getFreedrawOutlinePoints = (element) => {
16276
+ return element.strokeOptions?.variability === "constant" ? getConstantWidthFreedrawOutline(element) : getVariableWidthFreedrawOutline(element);
16277
+ };
15698
16278
  var med = (A2, B2) => {
15699
16279
  return [(A2[0] + B2[0]) / 2, (A2[1] + B2[1]) / 2];
15700
16280
  };
@@ -15758,9 +16338,9 @@ var ElementBounds = class _ElementBounds {
15758
16338
  if (isFreeDrawElement(element)) {
15759
16339
  const [minX, minY, maxX, maxY] = getBoundsFromPoints(
15760
16340
  element.points.map(
15761
- ([x, y]) => pointRotateRads13(
15762
- pointFrom14(x, y),
15763
- pointFrom14(cx - element.x, cy - element.y),
16341
+ ([x, y]) => pointRotateRads12(
16342
+ pointFrom13(x, y),
16343
+ pointFrom13(cx - element.x, cy - element.y),
15764
16344
  element.angle
15765
16345
  )
15766
16346
  )
@@ -15774,24 +16354,24 @@ var ElementBounds = class _ElementBounds {
15774
16354
  } else if (isLinearElement(element)) {
15775
16355
  bounds = getLinearElementRotatedBounds(element, cx, cy, elementsMap);
15776
16356
  } else if (element.type === "diamond") {
15777
- const [x11, y11] = pointRotateRads13(
15778
- pointFrom14(cx, y1),
15779
- pointFrom14(cx, cy),
16357
+ const [x11, y11] = pointRotateRads12(
16358
+ pointFrom13(cx, y1),
16359
+ pointFrom13(cx, cy),
15780
16360
  element.angle
15781
16361
  );
15782
- const [x12, y12] = pointRotateRads13(
15783
- pointFrom14(cx, y2),
15784
- pointFrom14(cx, cy),
16362
+ const [x12, y12] = pointRotateRads12(
16363
+ pointFrom13(cx, y2),
16364
+ pointFrom13(cx, cy),
15785
16365
  element.angle
15786
16366
  );
15787
- const [x22, y22] = pointRotateRads13(
15788
- pointFrom14(x1, cy),
15789
- pointFrom14(cx, cy),
16367
+ const [x22, y22] = pointRotateRads12(
16368
+ pointFrom13(x1, cy),
16369
+ pointFrom13(cx, cy),
15790
16370
  element.angle
15791
16371
  );
15792
- const [x21, y21] = pointRotateRads13(
15793
- pointFrom14(x2, cy),
15794
- pointFrom14(cx, cy),
16372
+ const [x21, y21] = pointRotateRads12(
16373
+ pointFrom13(x2, cy),
16374
+ pointFrom13(cx, cy),
15795
16375
  element.angle
15796
16376
  );
15797
16377
  const minX = Math.min(x11, x12, x22, x21);
@@ -15808,24 +16388,24 @@ var ElementBounds = class _ElementBounds {
15808
16388
  const hh = Math.hypot(h * cos, w * sin);
15809
16389
  bounds = [cx - ww, cy - hh, cx + ww, cy + hh];
15810
16390
  } else {
15811
- const [x11, y11] = pointRotateRads13(
15812
- pointFrom14(x1, y1),
15813
- pointFrom14(cx, cy),
16391
+ const [x11, y11] = pointRotateRads12(
16392
+ pointFrom13(x1, y1),
16393
+ pointFrom13(cx, cy),
15814
16394
  element.angle
15815
16395
  );
15816
- const [x12, y12] = pointRotateRads13(
15817
- pointFrom14(x1, y2),
15818
- pointFrom14(cx, cy),
16396
+ const [x12, y12] = pointRotateRads12(
16397
+ pointFrom13(x1, y2),
16398
+ pointFrom13(cx, cy),
15819
16399
  element.angle
15820
16400
  );
15821
- const [x22, y22] = pointRotateRads13(
15822
- pointFrom14(x2, y2),
15823
- pointFrom14(cx, cy),
16401
+ const [x22, y22] = pointRotateRads12(
16402
+ pointFrom13(x2, y2),
16403
+ pointFrom13(cx, cy),
15824
16404
  element.angle
15825
16405
  );
15826
- const [x21, y21] = pointRotateRads13(
15827
- pointFrom14(x2, y1),
15828
- pointFrom14(cx, cy),
16406
+ const [x21, y21] = pointRotateRads12(
16407
+ pointFrom13(x2, y1),
16408
+ pointFrom13(cx, cy),
15829
16409
  element.angle
15830
16410
  );
15831
16411
  const minX = Math.min(x11, x12, x22, x21);
@@ -15879,7 +16459,7 @@ var getElementLineSegments = (element, elementsMap) => {
15879
16459
  element,
15880
16460
  elementsMap
15881
16461
  );
15882
- const center = pointFrom14(cx, cy);
16462
+ const center = pointFrom13(cx, cy);
15883
16463
  if (shape.type === "polycurve") {
15884
16464
  const curves = shape.data;
15885
16465
  const pointsOnCurves = curves.map(
@@ -15891,9 +16471,9 @@ var getElementLineSegments = (element, elementsMap) => {
15891
16471
  let i = 0;
15892
16472
  while (i < points.length - 1) {
15893
16473
  segments.push(
15894
- lineSegment7(
15895
- pointFrom14(points[i][0], points[i][1]),
15896
- pointFrom14(points[i + 1][0], points[i + 1][1])
16474
+ lineSegment6(
16475
+ pointFrom13(points[i][0], points[i][1]),
16476
+ pointFrom13(points[i + 1][0], points[i + 1][1])
15897
16477
  )
15898
16478
  );
15899
16479
  i++;
@@ -15904,9 +16484,9 @@ var getElementLineSegments = (element, elementsMap) => {
15904
16484
  let i = 0;
15905
16485
  while (i < points.length - 1) {
15906
16486
  segments.push(
15907
- lineSegment7(
15908
- pointFrom14(points[i][0], points[i][1]),
15909
- pointFrom14(points[i + 1][0], points[i + 1][1])
16487
+ lineSegment6(
16488
+ pointFrom13(points[i][0], points[i][1]),
16489
+ pointFrom13(points[i + 1][0], points[i + 1][1])
15910
16490
  )
15911
16491
  );
15912
16492
  i++;
@@ -15930,10 +16510,10 @@ var getElementLineSegments = (element, elementsMap) => {
15930
16510
  const container = getContainerElement(element, elementsMap);
15931
16511
  if (container && isLinearElement(container)) {
15932
16512
  const segments2 = [
15933
- lineSegment7(pointFrom14(x1, y1), pointFrom14(x2, y1)),
15934
- lineSegment7(pointFrom14(x2, y1), pointFrom14(x2, y2)),
15935
- lineSegment7(pointFrom14(x2, y2), pointFrom14(x1, y2)),
15936
- lineSegment7(pointFrom14(x1, y2), pointFrom14(x1, y1))
16513
+ lineSegment6(pointFrom13(x1, y1), pointFrom13(x2, y1)),
16514
+ lineSegment6(pointFrom13(x2, y1), pointFrom13(x2, y2)),
16515
+ lineSegment6(pointFrom13(x2, y2), pointFrom13(x1, y2)),
16516
+ lineSegment6(pointFrom13(x1, y2), pointFrom13(x1, y1))
15937
16517
  ];
15938
16518
  return segments2;
15939
16519
  }
@@ -15941,7 +16521,7 @@ var getElementLineSegments = (element, elementsMap) => {
15941
16521
  const points = shape.data;
15942
16522
  const segments = [];
15943
16523
  for (let i = 0; i < points.length - 1; i++) {
15944
- segments.push(lineSegment7(points[i], points[i + 1]));
16524
+ segments.push(lineSegment6(points[i], points[i + 1]));
15945
16525
  }
15946
16526
  return segments;
15947
16527
  } else if (shape.type === "ellipse") {
@@ -15956,45 +16536,45 @@ var getElementLineSegments = (element, elementsMap) => {
15956
16536
  [cx, y2],
15957
16537
  [x1, cy],
15958
16538
  [x2, cy]
15959
- ].map((point) => pointRotateRads13(point, center, element.angle));
16539
+ ].map((point) => pointRotateRads12(point, center, element.angle));
15960
16540
  return [
15961
- lineSegment7(nw, ne),
15962
- lineSegment7(sw, se2),
15963
- lineSegment7(nw, sw),
15964
- lineSegment7(ne, se2),
15965
- lineSegment7(nw, e),
15966
- lineSegment7(sw, e),
15967
- lineSegment7(ne, w),
15968
- lineSegment7(se2, w)
16541
+ lineSegment6(nw, ne),
16542
+ lineSegment6(sw, se2),
16543
+ lineSegment6(nw, sw),
16544
+ lineSegment6(ne, se2),
16545
+ lineSegment6(nw, e),
16546
+ lineSegment6(sw, e),
16547
+ lineSegment6(ne, w),
16548
+ lineSegment6(se2, w)
15969
16549
  ];
15970
16550
  };
15971
16551
  var _isRectanguloidElement = (element) => {
15972
16552
  return element != null && (element.type === "rectangle" || element.type === "image" || element.type === "iframe" || element.type === "embeddable" || element.type === "frame" || element.type === "magicframe" || element.type === "text" && !element.containerId);
15973
16553
  };
15974
- var getRotatedSides = (sides, center, angle) => {
16554
+ var getRotatedSides = (sides, center, angle2) => {
15975
16555
  return sides.map((side) => {
15976
- return lineSegment7(
15977
- pointRotateRads13(side[0], center, angle),
15978
- pointRotateRads13(side[1], center, angle)
16556
+ return lineSegment6(
16557
+ pointRotateRads12(side[0], center, angle2),
16558
+ pointRotateRads12(side[1], center, angle2)
15979
16559
  );
15980
16560
  });
15981
16561
  };
15982
- var getSegmentsOnCurve = (curve4, center, angle) => {
16562
+ var getSegmentsOnCurve = (curve4, center, angle2) => {
15983
16563
  const points = pointsOnBezierCurves(curve4, 10);
15984
16564
  let i = 0;
15985
16565
  const segments = [];
15986
16566
  while (i < points.length - 1) {
15987
16567
  segments.push(
15988
- lineSegment7(
15989
- pointRotateRads13(
15990
- pointFrom14(points[i][0], points[i][1]),
16568
+ lineSegment6(
16569
+ pointRotateRads12(
16570
+ pointFrom13(points[i][0], points[i][1]),
15991
16571
  center,
15992
- angle
16572
+ angle2
15993
16573
  ),
15994
- pointRotateRads13(
15995
- pointFrom14(points[i + 1][0], points[i + 1][1]),
16574
+ pointRotateRads12(
16575
+ pointFrom13(points[i + 1][0], points[i + 1][1]),
15996
16576
  center,
15997
- angle
16577
+ angle2
15998
16578
  )
15999
16579
  )
16000
16580
  );
@@ -16003,7 +16583,7 @@ var getSegmentsOnCurve = (curve4, center, angle) => {
16003
16583
  return segments;
16004
16584
  };
16005
16585
  var getSegmentsOnEllipse = (ellipse4) => {
16006
- const center = pointFrom14(
16586
+ const center = pointFrom13(
16007
16587
  ellipse4.x + ellipse4.width / 2,
16008
16588
  ellipse4.y + ellipse4.height / 2
16009
16589
  );
@@ -16017,12 +16597,12 @@ var getSegmentsOnEllipse = (ellipse4) => {
16017
16597
  const t = i * deltaT;
16018
16598
  const x = center[0] + a2 * Math.cos(t);
16019
16599
  const y = center[1] + b2 * Math.sin(t);
16020
- points.push(pointRotateRads13(pointFrom14(x, y), center, ellipse4.angle));
16600
+ points.push(pointRotateRads12(pointFrom13(x, y), center, ellipse4.angle));
16021
16601
  }
16022
16602
  for (let i = 0; i < points.length - 1; i++) {
16023
- segments.push(lineSegment7(points[i], points[i + 1]));
16603
+ segments.push(lineSegment6(points[i], points[i + 1]));
16024
16604
  }
16025
- segments.push(lineSegment7(points[points.length - 1], points[0]));
16605
+ segments.push(lineSegment6(points[points.length - 1], points[0]));
16026
16606
  return segments;
16027
16607
  };
16028
16608
  var getRectangleBoxAbsoluteCoords = (boxSceneCoords) => {
@@ -16100,7 +16680,7 @@ var getCubicBezierCurveBound = (p0, p1, p2, p3) => {
16100
16680
  return [minX, minY, maxX, maxY];
16101
16681
  };
16102
16682
  var getMinMaxXYFromCurvePathOps = (ops, transformXY) => {
16103
- let currentP = pointFrom14(0, 0);
16683
+ let currentP = pointFrom13(0, 0);
16104
16684
  const { minX, minY, maxX, maxY } = ops.reduce(
16105
16685
  (limits, { op, data }) => {
16106
16686
  if (op === "move") {
@@ -16108,9 +16688,9 @@ var getMinMaxXYFromCurvePathOps = (ops, transformXY) => {
16108
16688
  invariant10(p != null, "Op data is not a point");
16109
16689
  currentP = p;
16110
16690
  } else if (op === "bcurveTo") {
16111
- const _p1 = pointFrom14(data[0], data[1]);
16112
- const _p2 = pointFrom14(data[2], data[3]);
16113
- const _p3 = pointFrom14(data[4], data[5]);
16691
+ const _p1 = pointFrom13(data[0], data[1]);
16692
+ const _p2 = pointFrom13(data[2], data[3]);
16693
+ const _p3 = pointFrom13(data[4], data[5]);
16114
16694
  const p1 = transformXY ? transformXY(_p1) : _p1;
16115
16695
  const p2 = transformXY ? transformXY(_p2) : _p2;
16116
16696
  const p3 = transformXY ? transformXY(_p3) : _p3;
@@ -16201,17 +16781,17 @@ var getArrowheadPoints = (element, shape, position, arrowhead, offsetMultiplier
16201
16781
  const index = position === "start" ? 1 : ops.length - 1;
16202
16782
  const data = ops[index].data;
16203
16783
  invariant10(data.length === 6, "Op data length is not 6");
16204
- const p3 = pointFrom14(data[4], data[5]);
16205
- const p2 = pointFrom14(data[2], data[3]);
16206
- const p1 = pointFrom14(data[0], data[1]);
16784
+ const p3 = pointFrom13(data[4], data[5]);
16785
+ const p2 = pointFrom13(data[2], data[3]);
16786
+ const p1 = pointFrom13(data[0], data[1]);
16207
16787
  const prevOp = ops[index - 1];
16208
- let p0 = pointFrom14(0, 0);
16788
+ let p0 = pointFrom13(0, 0);
16209
16789
  if (prevOp.op === "move") {
16210
16790
  const p = pointFromArray3(prevOp.data);
16211
16791
  invariant10(p != null, "Op data is not a point");
16212
16792
  p0 = p;
16213
16793
  } else if (prevOp.op === "bcurveTo") {
16214
- p0 = pointFrom14(prevOp.data[4], prevOp.data[5]);
16794
+ p0 = pointFrom13(prevOp.data[4], prevOp.data[5]);
16215
16795
  }
16216
16796
  const equation = (t, idx) => Math.pow(1 - t, 3) * p3[idx] + 3 * t * Math.pow(1 - t, 2) * p2[idx] + 3 * Math.pow(t, 2) * (1 - t) * p1[idx] + p0[idx] * Math.pow(t, 3);
16217
16797
  const [x2, y2] = position === "start" ? p0 : p3;
@@ -16236,45 +16816,45 @@ var getArrowheadPoints = (element, shape, position, arrowhead, offsetMultiplier
16236
16816
  const diameter = Math.hypot(ys - ty, xs - tx) + element.strokeWidth - 2;
16237
16817
  return [tx, ty, diameter];
16238
16818
  }
16239
- const angle = getArrowheadAngle(arrowhead);
16819
+ const angle2 = getArrowheadAngle(arrowhead);
16240
16820
  if (arrowhead === "cardinality_many" || arrowhead === "cardinality_one_or_many") {
16241
- const [x32, y32] = pointRotateRads13(
16242
- pointFrom14(tx, ty),
16243
- pointFrom14(xs, ys),
16244
- degreesToRadians(-angle)
16821
+ const [x32, y32] = pointRotateRads12(
16822
+ pointFrom13(tx, ty),
16823
+ pointFrom13(xs, ys),
16824
+ degreesToRadians(-angle2)
16245
16825
  );
16246
- const [x42, y42] = pointRotateRads13(
16247
- pointFrom14(tx, ty),
16248
- pointFrom14(xs, ys),
16249
- degreesToRadians(angle)
16826
+ const [x42, y42] = pointRotateRads12(
16827
+ pointFrom13(tx, ty),
16828
+ pointFrom13(xs, ys),
16829
+ degreesToRadians(angle2)
16250
16830
  );
16251
16831
  return [xs, ys, x32, y32, x42, y42];
16252
16832
  }
16253
- const [x3, y3] = pointRotateRads13(
16254
- pointFrom14(xs, ys),
16255
- pointFrom14(tx, ty),
16256
- -angle * Math.PI / 180
16833
+ const [x3, y3] = pointRotateRads12(
16834
+ pointFrom13(xs, ys),
16835
+ pointFrom13(tx, ty),
16836
+ -angle2 * Math.PI / 180
16257
16837
  );
16258
- const [x4, y4] = pointRotateRads13(
16259
- pointFrom14(xs, ys),
16260
- pointFrom14(tx, ty),
16261
- degreesToRadians(angle)
16838
+ const [x4, y4] = pointRotateRads12(
16839
+ pointFrom13(xs, ys),
16840
+ pointFrom13(tx, ty),
16841
+ degreesToRadians(angle2)
16262
16842
  );
16263
16843
  if (arrowhead === "diamond" || arrowhead === "diamond_outline") {
16264
16844
  let ox;
16265
16845
  let oy;
16266
16846
  if (position === "start") {
16267
16847
  const [px, py] = element.points.length > 1 ? element.points[1] : [0, 0];
16268
- [ox, oy] = pointRotateRads13(
16269
- pointFrom14(tx + minSize * 2, ty),
16270
- pointFrom14(tx, ty),
16848
+ [ox, oy] = pointRotateRads12(
16849
+ pointFrom13(tx + minSize * 2, ty),
16850
+ pointFrom13(tx, ty),
16271
16851
  Math.atan2(py - ty, px - tx)
16272
16852
  );
16273
16853
  } else {
16274
16854
  const [px, py] = element.points.length > 1 ? element.points[element.points.length - 2] : [0, 0];
16275
- [ox, oy] = pointRotateRads13(
16276
- pointFrom14(tx - minSize * 2, ty),
16277
- pointFrom14(tx, ty),
16855
+ [ox, oy] = pointRotateRads12(
16856
+ pointFrom13(tx - minSize * 2, ty),
16857
+ pointFrom13(tx, ty),
16278
16858
  Math.atan2(ty - py, tx - px)
16279
16859
  );
16280
16860
  }
@@ -16303,9 +16883,9 @@ var getLinearElementRotatedBounds = (element, cx, cy, elementsMap) => {
16303
16883
  const boundTextElement = getBoundTextElement(element, elementsMap);
16304
16884
  if (element.points.length < 2) {
16305
16885
  const [pointX, pointY] = element.points[0];
16306
- const [x, y] = pointRotateRads13(
16307
- pointFrom14(element.x + pointX, element.y + pointY),
16308
- pointFrom14(cx, cy),
16886
+ const [x, y] = pointRotateRads12(
16887
+ pointFrom13(element.x + pointX, element.y + pointY),
16888
+ pointFrom13(cx, cy),
16309
16889
  element.angle
16310
16890
  );
16311
16891
  let coords2 = [x, y, x, y];
@@ -16328,9 +16908,9 @@ var getLinearElementRotatedBounds = (element, cx, cy, elementsMap) => {
16328
16908
  const cachedShape = ShapeCache.get(element, null)?.[0];
16329
16909
  const shape = cachedShape ?? generateLinearElementShape(element);
16330
16910
  const ops = getCurvePathOps(shape);
16331
- const transformXY = ([x, y]) => pointRotateRads13(
16332
- pointFrom14(element.x + x, element.y + y),
16333
- pointFrom14(cx, cy),
16911
+ const transformXY = ([x, y]) => pointRotateRads12(
16912
+ pointFrom13(element.x + x, element.y + y),
16913
+ pointFrom13(cx, cy),
16334
16914
  element.angle
16335
16915
  );
16336
16916
  const res = getMinMaxXYFromCurvePathOps(ops, transformXY);
@@ -16441,8 +17021,8 @@ var getClosestElementBounds = (elements, from) => {
16441
17021
  elements.forEach((element) => {
16442
17022
  const [x1, y1, x2, y2] = getElementBounds(element, elementsMap);
16443
17023
  const distance3 = pointDistance7(
16444
- pointFrom14((x1 + x2) / 2, (y1 + y2) / 2),
16445
- pointFrom14(from.x, from.y)
17024
+ pointFrom13((x1 + x2) / 2, (y1 + y2) / 2),
17025
+ pointFrom13(from.x, from.y)
16446
17026
  );
16447
17027
  if (distance3 < minDistance) {
16448
17028
  minDistance = distance3;
@@ -16478,7 +17058,7 @@ var getVisibleSceneBounds = ({
16478
17058
  -scrollY + height / zoom.value
16479
17059
  ];
16480
17060
  };
16481
- var getCenterForBounds = (bounds) => pointFrom14(
17061
+ var getCenterForBounds = (bounds) => pointFrom13(
16482
17062
  bounds[0] + (bounds[2] - bounds[0]) / 2,
16483
17063
  bounds[1] + (bounds[3] - bounds[1]) / 2
16484
17064
  );
@@ -16492,23 +17072,23 @@ var aabbForElement = (element, elementsMap, offset) => {
16492
17072
  midY: element.y + element.height / 2
16493
17073
  };
16494
17074
  const center = elementCenterPoint(element, elementsMap);
16495
- const [topLeftX, topLeftY] = pointRotateRads13(
16496
- pointFrom14(bbox.minX, bbox.minY),
17075
+ const [topLeftX, topLeftY] = pointRotateRads12(
17076
+ pointFrom13(bbox.minX, bbox.minY),
16497
17077
  center,
16498
17078
  element.angle
16499
17079
  );
16500
- const [topRightX, topRightY] = pointRotateRads13(
16501
- pointFrom14(bbox.maxX, bbox.minY),
17080
+ const [topRightX, topRightY] = pointRotateRads12(
17081
+ pointFrom13(bbox.maxX, bbox.minY),
16502
17082
  center,
16503
17083
  element.angle
16504
17084
  );
16505
- const [bottomRightX, bottomRightY] = pointRotateRads13(
16506
- pointFrom14(bbox.maxX, bbox.maxY),
17085
+ const [bottomRightX, bottomRightY] = pointRotateRads12(
17086
+ pointFrom13(bbox.maxX, bbox.maxY),
16507
17087
  center,
16508
17088
  element.angle
16509
17089
  );
16510
- const [bottomLeftX, bottomLeftY] = pointRotateRads13(
16511
- pointFrom14(bbox.minX, bbox.maxY),
17090
+ const [bottomLeftX, bottomLeftY] = pointRotateRads12(
17091
+ pointFrom13(bbox.minX, bbox.maxY),
16512
17092
  center,
16513
17093
  element.angle
16514
17094
  );
@@ -16527,32 +17107,237 @@ var aabbForElement = (element, elementsMap, offset) => {
16527
17107
  bounds[3] + downOffset
16528
17108
  ];
16529
17109
  }
16530
- return bounds;
16531
- };
16532
- var pointInsideBounds = (p, bounds) => p[0] > bounds[0] && p[0] < bounds[2] && p[1] > bounds[1] && p[1] < bounds[3];
16533
- var pointInsideBoundsInclusive = (p, bounds) => p[0] >= bounds[0] && p[0] <= bounds[2] && p[1] >= bounds[1] && p[1] <= bounds[3];
16534
- var doBoundsIntersect = (bounds1, bounds2) => {
16535
- if (bounds1 == null || bounds2 == null) {
16536
- return false;
17110
+ return bounds;
17111
+ };
17112
+ var pointInsideBounds = (p, bounds) => p[0] > bounds[0] && p[0] < bounds[2] && p[1] > bounds[1] && p[1] < bounds[3];
17113
+ var pointInsideBoundsInclusive = (p, bounds) => p[0] >= bounds[0] && p[0] <= bounds[2] && p[1] >= bounds[1] && p[1] <= bounds[3];
17114
+ var doBoundsIntersect = (bounds1, bounds2) => {
17115
+ if (bounds1 == null || bounds2 == null) {
17116
+ return false;
17117
+ }
17118
+ const [minX1, minY1, maxX1, maxY1] = bounds1;
17119
+ const [minX2, minY2, maxX2, maxY2] = bounds2;
17120
+ return minX1 < maxX2 && maxX1 > minX2 && minY1 < maxY2 && maxY1 > minY2;
17121
+ };
17122
+ var boundsContainBounds = (outerBounds, innerBounds) => [
17123
+ pointFrom13(innerBounds[0], innerBounds[1]),
17124
+ pointFrom13(innerBounds[0], innerBounds[3]),
17125
+ pointFrom13(innerBounds[2], innerBounds[1]),
17126
+ pointFrom13(innerBounds[2], innerBounds[3])
17127
+ ].every((point) => pointInsideBoundsInclusive(point, outerBounds));
17128
+ var elementsOverlappingBBox = ({
17129
+ elements,
17130
+ elementsMap,
17131
+ bounds,
17132
+ type,
17133
+ excludeElementsInFrames,
17134
+ shouldIgnoreElementFromSelection: shouldIgnoreElementFromSelection2
17135
+ }) => {
17136
+ if (!elementsMap) {
17137
+ elementsMap = arrayToMap7(elements);
17138
+ }
17139
+ const selectionBounds = isExcalidrawElement(bounds) ? getElementBounds(bounds, elementsMap) : bounds;
17140
+ const [selectionX1, selectionY1, selectionX2, selectionY2] = selectionBounds;
17141
+ const selectionEdges = [
17142
+ lineSegment6(
17143
+ pointFrom13(selectionX1, selectionY1),
17144
+ pointFrom13(selectionX2, selectionY1)
17145
+ ),
17146
+ lineSegment6(
17147
+ pointFrom13(selectionX2, selectionY1),
17148
+ pointFrom13(selectionX2, selectionY2)
17149
+ ),
17150
+ lineSegment6(
17151
+ pointFrom13(selectionX2, selectionY2),
17152
+ pointFrom13(selectionX1, selectionY2)
17153
+ ),
17154
+ lineSegment6(
17155
+ pointFrom13(selectionX1, selectionY2),
17156
+ pointFrom13(selectionX1, selectionY1)
17157
+ )
17158
+ ];
17159
+ const framesInSelection = excludeElementsInFrames ? /* @__PURE__ */ new Set() : null;
17160
+ const groups = {};
17161
+ const elementsInSelection = /* @__PURE__ */ new Set();
17162
+ for (const element of elements) {
17163
+ if (shouldIgnoreElementFromSelection2?.(element)) {
17164
+ continue;
17165
+ }
17166
+ const groupId = element.groupIds.at(-1);
17167
+ if (groupId) {
17168
+ if (!groups[groupId]) {
17169
+ groups[groupId] = [];
17170
+ }
17171
+ groups[groupId].push(element);
17172
+ }
17173
+ const strokeWidth = element.strokeWidth;
17174
+ let labelAABB = null;
17175
+ let elementAABB = getElementBounds(element, elementsMap);
17176
+ elementAABB = [
17177
+ elementAABB[0] - strokeWidth / 2,
17178
+ elementAABB[1] - strokeWidth / 2,
17179
+ elementAABB[2] + strokeWidth / 2,
17180
+ elementAABB[3] + strokeWidth / 2
17181
+ ];
17182
+ const boundTextElement = isArrowElement(element) && getBoundTextElement(element, elementsMap);
17183
+ if (boundTextElement) {
17184
+ const { x, y } = LinearElementEditor.getBoundTextElementPosition(
17185
+ element,
17186
+ boundTextElement,
17187
+ elementsMap
17188
+ );
17189
+ labelAABB = [
17190
+ x,
17191
+ y,
17192
+ x + boundTextElement.width,
17193
+ y + boundTextElement.height
17194
+ ];
17195
+ }
17196
+ const associatedFrame = getContainingFrame(element, elementsMap);
17197
+ if (associatedFrame && elementOverlapsWithFrame(element, associatedFrame, elementsMap)) {
17198
+ const frameAABB = getElementBounds(associatedFrame, elementsMap);
17199
+ elementAABB = [
17200
+ Math.max(elementAABB[0], frameAABB[0]),
17201
+ Math.max(elementAABB[1], frameAABB[1]),
17202
+ Math.min(elementAABB[2], frameAABB[2]),
17203
+ Math.min(elementAABB[3], frameAABB[3])
17204
+ ];
17205
+ labelAABB = labelAABB ? [
17206
+ Math.max(labelAABB[0], frameAABB[0]),
17207
+ Math.max(labelAABB[1], frameAABB[1]),
17208
+ Math.min(labelAABB[2], frameAABB[2]),
17209
+ Math.min(labelAABB[3], frameAABB[3])
17210
+ ] : null;
17211
+ }
17212
+ const commonAABB2 = labelAABB ? [
17213
+ Math.min(labelAABB[0], elementAABB[0]),
17214
+ Math.min(labelAABB[1], elementAABB[1]),
17215
+ Math.max(labelAABB[2], elementAABB[2]),
17216
+ Math.max(labelAABB[3], elementAABB[3])
17217
+ ] : elementAABB;
17218
+ if (boundsContainBounds(selectionBounds, commonAABB2)) {
17219
+ if (framesInSelection && isFrameLikeElement(element)) {
17220
+ framesInSelection.add(element.id);
17221
+ }
17222
+ elementsInSelection.add(element);
17223
+ continue;
17224
+ }
17225
+ if (type === "overlap" && labelAABB && doBoundsIntersect(selectionBounds, labelAABB)) {
17226
+ elementsInSelection.add(element);
17227
+ continue;
17228
+ }
17229
+ if (type === "overlap" && doBoundsIntersect(selectionBounds, elementAABB)) {
17230
+ let hasIntersection = false;
17231
+ if (isLinearElement(element) || isFreeDrawElement(element)) {
17232
+ const center = elementCenterPoint(element, elementsMap);
17233
+ hasIntersection = element.points.some((point) => {
17234
+ const rotatedPoint = pointRotateRads12(
17235
+ pointFrom13(element.x + point[0], element.y + point[1]),
17236
+ center,
17237
+ element.angle
17238
+ );
17239
+ return pointInsideBounds(rotatedPoint, selectionBounds);
17240
+ });
17241
+ } else {
17242
+ const nonRotatedElementBounds = getElementBounds(
17243
+ element,
17244
+ elementsMap,
17245
+ true
17246
+ );
17247
+ const center = elementCenterPoint(element, elementsMap);
17248
+ hasIntersection = [
17249
+ pointRotateRads12(
17250
+ pointFrom13(
17251
+ (nonRotatedElementBounds[0] + nonRotatedElementBounds[2]) / 2,
17252
+ nonRotatedElementBounds[1]
17253
+ ),
17254
+ center,
17255
+ element.angle
17256
+ ),
17257
+ pointRotateRads12(
17258
+ pointFrom13(
17259
+ nonRotatedElementBounds[2],
17260
+ (nonRotatedElementBounds[1] + nonRotatedElementBounds[3]) / 2
17261
+ ),
17262
+ center,
17263
+ element.angle
17264
+ ),
17265
+ pointRotateRads12(
17266
+ pointFrom13(
17267
+ (nonRotatedElementBounds[0] + nonRotatedElementBounds[2]) / 2,
17268
+ nonRotatedElementBounds[3]
17269
+ ),
17270
+ center,
17271
+ element.angle
17272
+ ),
17273
+ pointRotateRads12(
17274
+ pointFrom13(
17275
+ nonRotatedElementBounds[0],
17276
+ (nonRotatedElementBounds[1] + nonRotatedElementBounds[3]) / 2
17277
+ ),
17278
+ center,
17279
+ element.angle
17280
+ )
17281
+ ].some((point) => {
17282
+ return pointInsideBounds(
17283
+ pointRotateRads12(point, center, element.angle),
17284
+ selectionBounds
17285
+ );
17286
+ });
17287
+ }
17288
+ if (!hasIntersection) {
17289
+ hasIntersection = selectionEdges.some(
17290
+ (selectionEdge) => intersectElementWithLineSegment(
17291
+ element,
17292
+ elementsMap,
17293
+ selectionEdge,
17294
+ strokeWidth / 2,
17295
+ true
17296
+ // Stop at first hit for better performance
17297
+ ).length > 0
17298
+ );
17299
+ }
17300
+ if (hasIntersection) {
17301
+ if (framesInSelection && isFrameLikeElement(element)) {
17302
+ framesInSelection.add(element.id);
17303
+ }
17304
+ elementsInSelection.add(element);
17305
+ continue;
17306
+ }
17307
+ }
17308
+ }
17309
+ if (framesInSelection) {
17310
+ elementsInSelection.forEach((element) => {
17311
+ if (element.frameId && framesInSelection.has(element.frameId)) {
17312
+ elementsInSelection.delete(element);
17313
+ }
17314
+ });
16537
17315
  }
16538
- const [minX1, minY1, maxX1, maxY1] = bounds1;
16539
- const [minX2, minY2, maxX2, maxY2] = bounds2;
16540
- return minX1 < maxX2 && maxX1 > minX2 && minY1 < maxY2 && maxY1 > minY2;
17316
+ if (type === "overlap") {
17317
+ Array.from(elementsInSelection).forEach((element) => {
17318
+ const groupId = element.groupIds.at(-1);
17319
+ const group = groupId ? groups[groupId] : null;
17320
+ group?.forEach((groupElement) => elementsInSelection.add(groupElement));
17321
+ });
17322
+ } else if (type === "contain") {
17323
+ elementsInSelection.forEach((element) => {
17324
+ const groupId = element.groupIds.at(-1);
17325
+ const group = groupId ? groups[groupId] : null;
17326
+ if (group && !group.every((groupElement) => elementsInSelection.has(groupElement))) {
17327
+ elementsInSelection.delete(element);
17328
+ }
17329
+ });
17330
+ }
17331
+ return elements.filter((element) => elementsInSelection.has(element));
16541
17332
  };
16542
- var boundsContainBounds = (outerBounds, innerBounds) => [
16543
- pointFrom14(innerBounds[0], innerBounds[1]),
16544
- pointFrom14(innerBounds[0], innerBounds[3]),
16545
- pointFrom14(innerBounds[2], innerBounds[1]),
16546
- pointFrom14(innerBounds[2], innerBounds[3])
16547
- ].every((point) => pointInsideBoundsInclusive(point, outerBounds));
16548
17333
  var elementCenterPoint = (element, elementsMap, xOffset = 0, yOffset = 0) => {
16549
17334
  if (isLinearElement(element) || isFreeDrawElement(element)) {
16550
17335
  const [x1, y1, x2, y2] = getElementAbsoluteCoords2(element, elementsMap);
16551
- const [x3, y3] = pointFrom14((x1 + x2) / 2, (y1 + y2) / 2);
16552
- return pointFrom14(x3 + xOffset, y3 + yOffset);
17336
+ const [x3, y3] = pointFrom13((x1 + x2) / 2, (y1 + y2) / 2);
17337
+ return pointFrom13(x3 + xOffset, y3 + yOffset);
16553
17338
  }
16554
17339
  const [x, y] = getCenterForBounds(getElementBounds(element, elementsMap));
16555
- return pointFrom14(x + xOffset, y + yOffset);
17340
+ return pointFrom13(x + xOffset, y + yOffset);
16556
17341
  };
16557
17342
 
16558
17343
  // src/sizeHelpers.ts
@@ -16623,18 +17408,18 @@ var getPerfectElementSize = (elementType, width, height) => {
16623
17408
  var getLockedLinearCursorAlignSize = (originX, originY, x, y, customAngle) => {
16624
17409
  let width = x - originX;
16625
17410
  let height = y - originY;
16626
- const angle = Math.atan2(height, width);
16627
- let lockedAngle = Math.round(angle / SHIFT_LOCKING_ANGLE) * SHIFT_LOCKING_ANGLE;
17411
+ const angle2 = Math.atan2(height, width);
17412
+ let lockedAngle = Math.round(angle2 / SHIFT_LOCKING_ANGLE) * SHIFT_LOCKING_ANGLE;
16628
17413
  if (customAngle) {
16629
17414
  const lower = Math.floor(customAngle / SHIFT_LOCKING_ANGLE) * SHIFT_LOCKING_ANGLE;
16630
17415
  if (radiansBetweenAngles(
16631
- angle,
17416
+ angle2,
16632
17417
  lower,
16633
17418
  lower + SHIFT_LOCKING_ANGLE
16634
17419
  )) {
16635
- if (radiansDifference(angle, customAngle) < SHIFT_LOCKING_ANGLE / 6) {
17420
+ if (radiansDifference(angle2, customAngle) < SHIFT_LOCKING_ANGLE / 6) {
16636
17421
  lockedAngle = customAngle;
16637
- } else if (normalizeRadians(angle) > normalizeRadians(customAngle)) {
17422
+ } else if (normalizeRadians(angle2) > normalizeRadians(customAngle)) {
16638
17423
  lockedAngle = lower + SHIFT_LOCKING_ANGLE;
16639
17424
  } else {
16640
17425
  lockedAngle = lower;
@@ -16849,7 +17634,7 @@ var compareScores = (a2, b2) => {
16849
17634
  return 0;
16850
17635
  };
16851
17636
  var compareBlocks = (a2, b2) => b2.packedW * b2.packedH - a2.packedW * a2.packedH || Math.max(b2.packedW, b2.packedH) - Math.max(a2.packedW, a2.packedH) || b2.packedH - a2.packedH || b2.packedW - a2.packedW;
16852
- var clamp4 = (value, min, max) => Math.min(Math.max(value, min), max);
17637
+ var clamp5 = (value, min, max) => Math.min(Math.max(value, min), max);
16853
17638
  var intersects = (a2, b2) => a2.x < b2.x + b2.w && a2.x + a2.w > b2.x && a2.y < b2.y + b2.h && a2.y + a2.h > b2.y;
16854
17639
  var contains = (outer, inner) => inner.x >= outer.x && inner.y >= outer.y && inner.x + inner.w <= outer.x + outer.w && inner.y + inner.h <= outer.y + outer.h;
16855
17640
  var getLayoutBounds = (blocks) => {
@@ -16961,8 +17746,8 @@ var getCandidatePositions = (freeRect, block, heuristic, targetCenter) => {
16961
17746
  ];
16962
17747
  if (heuristic === "center-distance") {
16963
17748
  positions.push({
16964
- x: clamp4(targetCenter.x - block.actualW / 2, freeRect.x, maxX),
16965
- y: clamp4(targetCenter.y - block.actualH / 2, freeRect.y, maxY)
17749
+ x: clamp5(targetCenter.x - block.actualW / 2, freeRect.x, maxX),
17750
+ y: clamp5(targetCenter.y - block.actualH / 2, freeRect.y, maxY)
16966
17751
  });
16967
17752
  }
16968
17753
  return positions.filter(
@@ -20213,6 +20998,7 @@ import {
20213
20998
  DEFAULT_FONT_SIZE as DEFAULT_FONT_SIZE3,
20214
20999
  DEFAULT_TEXT_ALIGN,
20215
21000
  DEFAULT_VERTICAL_ALIGN,
21001
+ DEFAULT_STROKE_STREAMLINE as DEFAULT_STROKE_STREAMLINE2,
20216
21002
  VERTICAL_ALIGN as VERTICAL_ALIGN2,
20217
21003
  randomInteger as randomInteger5,
20218
21004
  randomId as randomId3,
@@ -20232,7 +21018,7 @@ var _newElementBase = (type, {
20232
21018
  opacity = DEFAULT_ELEMENT_PROPS.opacity,
20233
21019
  width = 0,
20234
21020
  height = 0,
20235
- angle = 0,
21021
+ angle: angle2 = 0,
20236
21022
  groupIds = [],
20237
21023
  frameId = null,
20238
21024
  index = null,
@@ -20259,7 +21045,7 @@ var _newElementBase = (type, {
20259
21045
  y,
20260
21046
  width,
20261
21047
  height,
20262
- angle,
21048
+ angle: angle2,
20263
21049
  strokeColor,
20264
21050
  backgroundColor,
20265
21051
  fillStyle,
@@ -20416,9 +21202,9 @@ var getAdjustedDimensions = (element, elementsMap, nextText) => {
20416
21202
  y: Number.isFinite(y) ? y : element.y
20417
21203
  };
20418
21204
  };
20419
- var adjustXYWithRotation = (sides, x, y, angle, deltaX1, deltaY1, deltaX2, deltaY2) => {
20420
- const cos = Math.cos(angle);
20421
- const sin = Math.sin(angle);
21205
+ var adjustXYWithRotation = (sides, x, y, angle2, deltaX1, deltaY1, deltaX2, deltaY2) => {
21206
+ const cos = Math.cos(angle2);
21207
+ const sin = Math.sin(angle2);
20422
21208
  if (sides.e && sides.w) {
20423
21209
  x += deltaX1 + deltaX2;
20424
21210
  } else if (sides.e) {
@@ -20466,7 +21252,11 @@ var newFreeDrawElement = (opts) => {
20466
21252
  ..._newElementBase(opts.type, opts),
20467
21253
  points: opts.points || [],
20468
21254
  pressures: opts.pressures || [],
20469
- simulatePressure: opts.simulatePressure
21255
+ simulatePressure: opts.simulatePressure,
21256
+ strokeOptions: opts.strokeOptions ?? {
21257
+ variability: "variable",
21258
+ streamline: DEFAULT_STROKE_STREAMLINE2
21259
+ }
20470
21260
  };
20471
21261
  };
20472
21262
  var newLinearElement = (opts) => {
@@ -20521,6 +21311,7 @@ var newImageElement = (opts) => {
20521
21311
  status: opts.status ?? "pending",
20522
21312
  fileId: opts.fileId ?? null,
20523
21313
  fileName: opts.fileName ?? null,
21314
+ thumbHash: opts.thumbHash ?? null,
20524
21315
  scale: opts.scale ?? [1, 1],
20525
21316
  crop: opts.crop ?? null
20526
21317
  };
@@ -20936,7 +21727,7 @@ var embeddableURLValidator = (url, validateEmbeddable) => {
20936
21727
  // src/flowchart.ts
20937
21728
  init_define_import_meta_env();
20938
21729
  import { KEYS as KEYS2, invariant as invariant11, toBrandedType as toBrandedType2 } from "@excalidraw/common";
20939
- import { pointFrom as pointFrom15 } from "@excalidraw/math";
21730
+ import { pointFrom as pointFrom14 } from "@excalidraw/math";
20940
21731
  var VERTICAL_OFFSET = 100;
20941
21732
  var HORIZONTAL_OFFSET = 100;
20942
21733
  var getLinkDirectionFromKey = (key) => {
@@ -21216,7 +22007,7 @@ var createBindingArrow = (startBindingElement, endBindingElement, direction, app
21216
22007
  strokeWidth: startBindingElement.strokeWidth,
21217
22008
  opacity: startBindingElement.opacity,
21218
22009
  roughness: startBindingElement.roughness,
21219
- points: [pointFrom15(0, 0), pointFrom15(endX, endY)],
22010
+ points: [pointFrom14(0, 0), pointFrom14(endX, endY)],
21220
22011
  elbowed: true
21221
22012
  });
21222
22013
  const elementsMap = scene.getNonDeletedElementsMap();
@@ -21404,7 +22195,7 @@ var isNodeInFlowchart = (element, elementsMap) => {
21404
22195
 
21405
22196
  // src/arrows/focus.ts
21406
22197
  init_define_import_meta_env();
21407
- import { pointDistance as pointDistance8, pointFrom as pointFrom16 } from "@excalidraw/math";
22198
+ import { pointDistance as pointDistance8, pointFrom as pointFrom15 } from "@excalidraw/math";
21408
22199
  import { invariant as invariant12 } from "@excalidraw/common";
21409
22200
  var isFocusPointVisible = (focusPoint, arrow, bindableElement, elementsMap, appState, startOrEnd, ignoreOverlap = false) => {
21410
22201
  if (isElbowArrow(arrow) || !isBindingEnabled(appState) || arrow.points.length !== 2) {
@@ -21516,7 +22307,7 @@ var handleFocusPointDrag = (linearElementEditor, elementsMap, pointerCoords, sce
21516
22307
  const isStartBinding = linearElementEditor.draggedFocusPointBinding === "start";
21517
22308
  const binding = isStartBinding ? arrow.startBinding : arrow.endBinding;
21518
22309
  const { x: offsetX, y: offsetY } = linearElementEditor.pointerOffset;
21519
- const point = pointFrom16(
22310
+ const point = pointFrom15(
21520
22311
  pointerCoords.x - offsetX,
21521
22312
  pointerCoords.y - offsetY
21522
22313
  );
@@ -21599,7 +22390,7 @@ var handleFocusPointDrag = (linearElementEditor, elementsMap, pointerCoords, sce
21599
22390
  }
21600
22391
  };
21601
22392
  var handleFocusPointPointerDown = (arrow, pointerDownState, elementsMap, appState) => {
21602
- const pointerPos = pointFrom16(
22393
+ const pointerPos = pointFrom15(
21603
22394
  pointerDownState.origin.x,
21604
22395
  pointerDownState.origin.y
21605
22396
  );
@@ -21702,7 +22493,7 @@ var handleFocusPointPointerUp = (linearElementEditor, scene) => {
21702
22493
  };
21703
22494
  var handleFocusPointHover = (arrow, scenePointerX, scenePointerY, scene, appState) => {
21704
22495
  const elementsMap = scene.getNonDeletedElementsMap();
21705
- const pointerPos = pointFrom16(scenePointerX, scenePointerY);
22496
+ const pointerPos = pointFrom15(scenePointerX, scenePointerY);
21706
22497
  const hitThreshold = FOCUS_POINT_SIZE * 1.5 / appState.zoom.value;
21707
22498
  if (arrow.startBinding?.elementId) {
21708
22499
  const bindableElement = elementsMap.get(arrow.startBinding.elementId);
@@ -21747,110 +22538,6 @@ var handleFocusPointHover = (arrow, scenePointerX, scenePointerY, scene, appStat
21747
22538
  return null;
21748
22539
  };
21749
22540
 
21750
- // src/image.ts
21751
- init_define_import_meta_env();
21752
- import { MIME_TYPES as MIME_TYPES2, SVG_NS } from "@excalidraw/common";
21753
- var loadHTMLImageElement = (dataURL) => {
21754
- return new Promise((resolve, reject) => {
21755
- const image = new Image();
21756
- image.onload = () => {
21757
- resolve(image);
21758
- };
21759
- image.onerror = (error) => {
21760
- reject(error);
21761
- };
21762
- image.src = dataURL;
21763
- });
21764
- };
21765
- var updateImageCache = async ({
21766
- fileIds,
21767
- files,
21768
- imageCache
21769
- }) => {
21770
- const updatedFiles = /* @__PURE__ */ new Map();
21771
- const erroredFiles = /* @__PURE__ */ new Map();
21772
- await Promise.all(
21773
- fileIds.reduce((promises, fileId) => {
21774
- const fileData = files[fileId];
21775
- if (fileData && !updatedFiles.has(fileId)) {
21776
- updatedFiles.set(fileId, true);
21777
- return promises.concat(
21778
- (async () => {
21779
- try {
21780
- if (fileData.mimeType === MIME_TYPES2.binary) {
21781
- throw new Error("Only images can be added to ImageCache");
21782
- }
21783
- const imagePromise = loadHTMLImageElement(fileData.dataURL);
21784
- const data = {
21785
- image: imagePromise,
21786
- mimeType: fileData.mimeType
21787
- };
21788
- imageCache.set(fileId, data);
21789
- const image = await imagePromise;
21790
- imageCache.set(fileId, { ...data, image });
21791
- } catch (error) {
21792
- erroredFiles.set(fileId, true);
21793
- }
21794
- })()
21795
- );
21796
- }
21797
- return promises;
21798
- }, [])
21799
- );
21800
- return {
21801
- imageCache,
21802
- /** includes errored files because they cache was updated nonetheless */
21803
- updatedFiles,
21804
- /** files that failed when creating HTMLImageElement */
21805
- erroredFiles
21806
- };
21807
- };
21808
- var getInitializedImageElements = (elements) => elements.filter(
21809
- (element) => isInitializedImageElement(element)
21810
- );
21811
- var isHTMLSVGElement = (node) => {
21812
- return node?.nodeName.toLowerCase() === "svg";
21813
- };
21814
- var normalizeSVG = (SVGString) => {
21815
- const doc = new DOMParser().parseFromString(SVGString, MIME_TYPES2.svg);
21816
- const svg = doc.querySelector("svg");
21817
- const errorNode = doc.querySelector("parsererror");
21818
- if (errorNode || !isHTMLSVGElement(svg)) {
21819
- throw new Error("Invalid SVG");
21820
- } else {
21821
- if (!svg.hasAttribute("xmlns")) {
21822
- svg.setAttribute("xmlns", SVG_NS);
21823
- }
21824
- let width = svg.getAttribute("width");
21825
- let height = svg.getAttribute("height");
21826
- if (width?.includes("%") || width === "auto") {
21827
- width = null;
21828
- }
21829
- if (height?.includes("%") || height === "auto") {
21830
- height = null;
21831
- }
21832
- const viewBox = svg.getAttribute("viewBox");
21833
- if (!width || !height) {
21834
- width = width || "50";
21835
- height = height || "50";
21836
- if (viewBox) {
21837
- const match = viewBox.match(
21838
- /\d+ +\d+ +(\d+(?:\.\d+)?) +(\d+(?:\.\d+)?)/
21839
- );
21840
- if (match) {
21841
- [, width, height] = match;
21842
- }
21843
- }
21844
- svg.setAttribute("width", width);
21845
- svg.setAttribute("height", height);
21846
- }
21847
- if (!viewBox) {
21848
- svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
21849
- }
21850
- return svg.outerHTML;
21851
- }
21852
- };
21853
-
21854
22541
  // src/normalise.ts
21855
22542
  init_define_import_meta_env();
21856
22543
  var getGroupCenter = (boundingBox) => ({
@@ -22008,8 +22695,8 @@ init_define_import_meta_env();
22008
22695
  import {
22009
22696
  pointCenter as pointCenter3,
22010
22697
  normalizeRadians as normalizeRadians2,
22011
- pointFrom as pointFrom17,
22012
- pointRotateRads as pointRotateRads14
22698
+ pointFrom as pointFrom16,
22699
+ pointRotateRads as pointRotateRads13
22013
22700
  } from "@excalidraw/math";
22014
22701
  import {
22015
22702
  MIN_FONT_SIZE,
@@ -22121,20 +22808,20 @@ var rotateSingleElement = (element, scene, pointerX, pointerY, shouldRotateWithD
22121
22808
  );
22122
22809
  const cx = (x1 + x2) / 2;
22123
22810
  const cy = (y1 + y2) / 2;
22124
- let angle;
22811
+ let angle2;
22125
22812
  if (isFrameLikeElement(element)) {
22126
- angle = 0;
22813
+ angle2 = 0;
22127
22814
  } else {
22128
- angle = 5 * Math.PI / 2 + Math.atan2(pointerY - cy, pointerX - cx);
22815
+ angle2 = 5 * Math.PI / 2 + Math.atan2(pointerY - cy, pointerX - cx);
22129
22816
  if (shouldRotateWithDiscreteAngle2) {
22130
- angle = angle + SHIFT_LOCKING_ANGLE2 / 2;
22131
- angle = angle - angle % SHIFT_LOCKING_ANGLE2;
22817
+ angle2 = angle2 + SHIFT_LOCKING_ANGLE2 / 2;
22818
+ angle2 = angle2 - angle2 % SHIFT_LOCKING_ANGLE2;
22132
22819
  }
22133
- angle = normalizeRadians2(angle);
22820
+ angle2 = normalizeRadians2(angle2);
22134
22821
  }
22135
22822
  const boundTextElementId = getBoundTextElementId(element);
22136
22823
  let update = {
22137
- angle
22824
+ angle: angle2
22138
22825
  };
22139
22826
  if (isBindingElement(element)) {
22140
22827
  update = {
@@ -22157,7 +22844,7 @@ var rotateSingleElement = (element, scene, pointerX, pointerY, shouldRotateWithD
22157
22844
  scene.getNonDeletedElementsMap()
22158
22845
  );
22159
22846
  scene.mutateElement(textElement, {
22160
- angle,
22847
+ angle: angle2,
22161
22848
  x,
22162
22849
  y
22163
22850
  });
@@ -22197,7 +22884,7 @@ var resizeSingleTextElement = (origElement, element, scene, transformHandleType,
22197
22884
  return;
22198
22885
  }
22199
22886
  if (transformHandleType.includes("n") || transformHandleType.includes("s")) {
22200
- const previousOrigin = pointFrom17(origElement.x, origElement.y);
22887
+ const previousOrigin = pointFrom16(origElement.x, origElement.y);
22201
22888
  const newOrigin = getResizedOrigin(
22202
22889
  previousOrigin,
22203
22890
  origElement.width,
@@ -22238,7 +22925,7 @@ var resizeSingleTextElement = (origElement, element, scene, transformHandleType,
22238
22925
  element.lineHeight
22239
22926
  );
22240
22927
  const newHeight = metrics2.height;
22241
- const previousOrigin = pointFrom17(origElement.x, origElement.y);
22928
+ const previousOrigin = pointFrom16(origElement.x, origElement.y);
22242
22929
  const newOrigin = getResizedOrigin(
22243
22930
  previousOrigin,
22244
22931
  origElement.width,
@@ -22275,9 +22962,9 @@ var rotateMultipleElements = (originalElements, elements, scene, pointerX, point
22275
22962
  const cx = (x1 + x2) / 2;
22276
22963
  const cy = (y1 + y2) / 2;
22277
22964
  const origAngle = originalElements.get(element.id)?.angle ?? element.angle;
22278
- const [rotatedCX, rotatedCY] = pointRotateRads14(
22279
- pointFrom17(cx, cy),
22280
- pointFrom17(centerX, centerY),
22965
+ const [rotatedCX, rotatedCY] = pointRotateRads13(
22966
+ pointFrom16(cx, cy),
22967
+ pointFrom16(centerX, centerY),
22281
22968
  centerAngle + origAngle - element.angle
22282
22969
  );
22283
22970
  const updates = isElbowArrow(element) ? {
@@ -22325,45 +23012,45 @@ var getResizeOffsetXY = (transformHandleType, selectedElements, elementsMap, x,
22325
23012
  const [x1, y1, x2, y2] = selectedElements.length === 1 ? getElementAbsoluteCoords2(selectedElements[0], elementsMap) : getCommonBounds(selectedElements);
22326
23013
  const cx = (x1 + x2) / 2;
22327
23014
  const cy = (y1 + y2) / 2;
22328
- const angle = selectedElements.length === 1 ? selectedElements[0].angle : 0;
22329
- [x, y] = pointRotateRads14(
22330
- pointFrom17(x, y),
22331
- pointFrom17(cx, cy),
22332
- -angle
23015
+ const angle2 = selectedElements.length === 1 ? selectedElements[0].angle : 0;
23016
+ [x, y] = pointRotateRads13(
23017
+ pointFrom16(x, y),
23018
+ pointFrom16(cx, cy),
23019
+ -angle2
22333
23020
  );
22334
23021
  switch (transformHandleType) {
22335
23022
  case "n":
22336
- return pointRotateRads14(
22337
- pointFrom17(x - (x1 + x2) / 2, y - y1),
22338
- pointFrom17(0, 0),
22339
- angle
23023
+ return pointRotateRads13(
23024
+ pointFrom16(x - (x1 + x2) / 2, y - y1),
23025
+ pointFrom16(0, 0),
23026
+ angle2
22340
23027
  );
22341
23028
  case "s":
22342
- return pointRotateRads14(
22343
- pointFrom17(x - (x1 + x2) / 2, y - y2),
22344
- pointFrom17(0, 0),
22345
- angle
23029
+ return pointRotateRads13(
23030
+ pointFrom16(x - (x1 + x2) / 2, y - y2),
23031
+ pointFrom16(0, 0),
23032
+ angle2
22346
23033
  );
22347
23034
  case "w":
22348
- return pointRotateRads14(
22349
- pointFrom17(x - x1, y - (y1 + y2) / 2),
22350
- pointFrom17(0, 0),
22351
- angle
23035
+ return pointRotateRads13(
23036
+ pointFrom16(x - x1, y - (y1 + y2) / 2),
23037
+ pointFrom16(0, 0),
23038
+ angle2
22352
23039
  );
22353
23040
  case "e":
22354
- return pointRotateRads14(
22355
- pointFrom17(x - x2, y - (y1 + y2) / 2),
22356
- pointFrom17(0, 0),
22357
- angle
23041
+ return pointRotateRads13(
23042
+ pointFrom16(x - x2, y - (y1 + y2) / 2),
23043
+ pointFrom16(0, 0),
23044
+ angle2
22358
23045
  );
22359
23046
  case "nw":
22360
- return pointRotateRads14(pointFrom17(x - x1, y - y1), pointFrom17(0, 0), angle);
23047
+ return pointRotateRads13(pointFrom16(x - x1, y - y1), pointFrom16(0, 0), angle2);
22361
23048
  case "ne":
22362
- return pointRotateRads14(pointFrom17(x - x2, y - y1), pointFrom17(0, 0), angle);
23049
+ return pointRotateRads13(pointFrom16(x - x2, y - y1), pointFrom16(0, 0), angle2);
22363
23050
  case "sw":
22364
- return pointRotateRads14(pointFrom17(x - x1, y - y2), pointFrom17(0, 0), angle);
23051
+ return pointRotateRads13(pointFrom16(x - x1, y - y2), pointFrom16(0, 0), angle2);
22365
23052
  case "se":
22366
- return pointRotateRads14(pointFrom17(x - x2, y - y2), pointFrom17(0, 0), angle);
23053
+ return pointRotateRads13(pointFrom16(x - x2, y - y2), pointFrom16(0, 0), angle2);
22367
23054
  default:
22368
23055
  return [0, 0];
22369
23056
  }
@@ -22407,7 +23094,7 @@ var getResizeAnchor = (handleDirection, shouldMaintainAspectRatio, shouldResizeF
22407
23094
  }
22408
23095
  return "top-right";
22409
23096
  };
22410
- var getResizedOrigin = (prevOrigin, prevWidth, prevHeight, newWidth, newHeight, angle, handleDirection, shouldMaintainAspectRatio, shouldResizeFromCenter) => {
23097
+ var getResizedOrigin = (prevOrigin, prevWidth, prevHeight, newWidth, newHeight, angle2, handleDirection, shouldMaintainAspectRatio, shouldResizeFromCenter) => {
22411
23098
  const anchor = getResizeAnchor(
22412
23099
  handleDirection,
22413
23100
  shouldMaintainAspectRatio,
@@ -22417,23 +23104,23 @@ var getResizedOrigin = (prevOrigin, prevWidth, prevHeight, newWidth, newHeight,
22417
23104
  switch (anchor) {
22418
23105
  case "top-left":
22419
23106
  return {
22420
- x: x + (prevWidth - newWidth) / 2 + (newWidth - prevWidth) / 2 * Math.cos(angle) + (prevHeight - newHeight) / 2 * Math.sin(angle),
22421
- y: y + (prevHeight - newHeight) / 2 + (newWidth - prevWidth) / 2 * Math.sin(angle) + (newHeight - prevHeight) / 2 * Math.cos(angle)
23107
+ x: x + (prevWidth - newWidth) / 2 + (newWidth - prevWidth) / 2 * Math.cos(angle2) + (prevHeight - newHeight) / 2 * Math.sin(angle2),
23108
+ y: y + (prevHeight - newHeight) / 2 + (newWidth - prevWidth) / 2 * Math.sin(angle2) + (newHeight - prevHeight) / 2 * Math.cos(angle2)
22422
23109
  };
22423
23110
  case "top-right":
22424
23111
  return {
22425
- x: x + (prevWidth - newWidth) / 2 * (Math.cos(angle) + 1) + (prevHeight - newHeight) / 2 * Math.sin(angle),
22426
- y: y + (prevHeight - newHeight) / 2 + (prevWidth - newWidth) / 2 * Math.sin(angle) + (newHeight - prevHeight) / 2 * Math.cos(angle)
23112
+ x: x + (prevWidth - newWidth) / 2 * (Math.cos(angle2) + 1) + (prevHeight - newHeight) / 2 * Math.sin(angle2),
23113
+ y: y + (prevHeight - newHeight) / 2 + (prevWidth - newWidth) / 2 * Math.sin(angle2) + (newHeight - prevHeight) / 2 * Math.cos(angle2)
22427
23114
  };
22428
23115
  case "bottom-left":
22429
23116
  return {
22430
- x: x + (prevWidth - newWidth) / 2 * (1 - Math.cos(angle)) + (newHeight - prevHeight) / 2 * Math.sin(angle),
22431
- y: y + (prevHeight - newHeight) / 2 * (Math.cos(angle) + 1) + (newWidth - prevWidth) / 2 * Math.sin(angle)
23117
+ x: x + (prevWidth - newWidth) / 2 * (1 - Math.cos(angle2)) + (newHeight - prevHeight) / 2 * Math.sin(angle2),
23118
+ y: y + (prevHeight - newHeight) / 2 * (Math.cos(angle2) + 1) + (newWidth - prevWidth) / 2 * Math.sin(angle2)
22432
23119
  };
22433
23120
  case "bottom-right":
22434
23121
  return {
22435
- x: x + (prevWidth - newWidth) / 2 * (Math.cos(angle) + 1) + (newHeight - prevHeight) / 2 * Math.sin(angle),
22436
- y: y + (prevHeight - newHeight) / 2 * (Math.cos(angle) + 1) + (prevWidth - newWidth) / 2 * Math.sin(angle)
23122
+ x: x + (prevWidth - newWidth) / 2 * (Math.cos(angle2) + 1) + (newHeight - prevHeight) / 2 * Math.sin(angle2),
23123
+ y: y + (prevHeight - newHeight) / 2 * (Math.cos(angle2) + 1) + (prevWidth - newWidth) / 2 * Math.sin(angle2)
22437
23124
  };
22438
23125
  case "center":
22439
23126
  return {
@@ -22442,23 +23129,23 @@ var getResizedOrigin = (prevOrigin, prevWidth, prevHeight, newWidth, newHeight,
22442
23129
  };
22443
23130
  case "east-side":
22444
23131
  return {
22445
- x: x + (prevWidth - newWidth) / 2 * (Math.cos(angle) + 1),
22446
- y: y + (prevWidth - newWidth) / 2 * Math.sin(angle) + (prevHeight - newHeight) / 2
23132
+ x: x + (prevWidth - newWidth) / 2 * (Math.cos(angle2) + 1),
23133
+ y: y + (prevWidth - newWidth) / 2 * Math.sin(angle2) + (prevHeight - newHeight) / 2
22447
23134
  };
22448
23135
  case "west-side":
22449
23136
  return {
22450
- x: x + (prevWidth - newWidth) / 2 * (1 - Math.cos(angle)),
22451
- y: y + (newWidth - prevWidth) / 2 * Math.sin(angle) + (prevHeight - newHeight) / 2
23137
+ x: x + (prevWidth - newWidth) / 2 * (1 - Math.cos(angle2)),
23138
+ y: y + (newWidth - prevWidth) / 2 * Math.sin(angle2) + (prevHeight - newHeight) / 2
22452
23139
  };
22453
23140
  case "north-side":
22454
23141
  return {
22455
- x: x + (prevWidth - newWidth) / 2 + (prevHeight - newHeight) / 2 * Math.sin(angle),
22456
- y: y + (newHeight - prevHeight) / 2 * (Math.cos(angle) - 1)
23142
+ x: x + (prevWidth - newWidth) / 2 + (prevHeight - newHeight) / 2 * Math.sin(angle2),
23143
+ y: y + (newHeight - prevHeight) / 2 * (Math.cos(angle2) - 1)
22457
23144
  };
22458
23145
  case "south-side":
22459
23146
  return {
22460
- x: x + (prevWidth - newWidth) / 2 + (newHeight - prevHeight) / 2 * Math.sin(angle),
22461
- y: y + (prevHeight - newHeight) / 2 * (Math.cos(angle) + 1)
23147
+ x: x + (prevWidth - newWidth) / 2 + (newHeight - prevHeight) / 2 * Math.sin(angle2),
23148
+ y: y + (prevHeight - newHeight) / 2 * (Math.cos(angle2) + 1)
22462
23149
  };
22463
23150
  }
22464
23151
  };
@@ -22526,10 +23213,10 @@ var resizeSingleElement = (nextWidth, nextHeight, latestElement, origElement, or
22526
23213
  nextHeight,
22527
23214
  true
22528
23215
  );
22529
- let previousOrigin = pointFrom17(origElement.x, origElement.y);
23216
+ let previousOrigin = pointFrom16(origElement.x, origElement.y);
22530
23217
  if (isLinearElement(origElement)) {
22531
23218
  const [x1, y1] = getElementBounds(origElement, originalElementsMap);
22532
- previousOrigin = pointFrom17(x1, y1);
23219
+ previousOrigin = pointFrom16(x1, y1);
22533
23220
  }
22534
23221
  const newOrigin = getResizedOrigin(
22535
23222
  previousOrigin,
@@ -22552,7 +23239,7 @@ var resizeSingleElement = (nextWidth, nextHeight, latestElement, origElement, or
22552
23239
  newOrigin.x += scaledX;
22553
23240
  newOrigin.y += scaledY;
22554
23241
  rescaledPoints.points = rescaledPoints.points.map(
22555
- (p) => pointFrom17(p[0] - scaledX, p[1] - scaledY)
23242
+ (p) => pointFrom16(p[0] - scaledX, p[1] - scaledY)
22556
23243
  );
22557
23244
  }
22558
23245
  if (nextWidth < 0) {
@@ -22628,11 +23315,11 @@ var getNextSingleWidthAndHeightFromPointer = (latestElement, origElement, handle
22628
23315
  origElement.height,
22629
23316
  true
22630
23317
  );
22631
- const startTopLeft = pointFrom17(x1, y1);
22632
- const startBottomRight = pointFrom17(x2, y2);
23318
+ const startTopLeft = pointFrom16(x1, y1);
23319
+ const startBottomRight = pointFrom16(x2, y2);
22633
23320
  const startCenter = pointCenter3(startTopLeft, startBottomRight);
22634
- const rotatedPointer = pointRotateRads14(
22635
- pointFrom17(pointerX, pointerY),
23321
+ const rotatedPointer = pointRotateRads13(
23322
+ pointFrom16(pointerX, pointerY),
22636
23323
  startCenter,
22637
23324
  -origElement.angle
22638
23325
  );
@@ -22880,7 +23567,7 @@ var resizeMultipleElements = (selectedElements, elementsMap, handleDirection, sc
22880
23567
  }
22881
23568
  const width2 = orig.width * scaleX;
22882
23569
  const height2 = orig.height * scaleY;
22883
- const angle = normalizeRadians2(
23570
+ const angle2 = normalizeRadians2(
22884
23571
  orig.angle * flipFactorX * flipFactorY
22885
23572
  );
22886
23573
  const isLinearOrFreeDraw = isLinearElement(orig) || isFreeDrawElement(orig);
@@ -22901,7 +23588,7 @@ var resizeMultipleElements = (selectedElements, elementsMap, handleDirection, sc
22901
23588
  y,
22902
23589
  width: width2,
22903
23590
  height: height2,
22904
- angle,
23591
+ angle: angle2,
22905
23592
  ...rescaledPoints
22906
23593
  };
22907
23594
  if (isElbowArrow(orig)) {
@@ -22969,7 +23656,7 @@ var resizeMultipleElements = (selectedElements, elementsMap, handleDirection, sc
22969
23656
  element,
22970
23657
  update: { boundTextFontSize, ...update }
22971
23658
  } of elementsAndUpdates) {
22972
- const { angle } = update;
23659
+ const { angle: angle2 } = update;
22973
23660
  scene.mutateElement(element, update);
22974
23661
  updateBoundElements(element, scene, {
22975
23662
  simultaneouslyUpdated: elementsToUpdate
@@ -22990,7 +23677,7 @@ var resizeMultipleElements = (selectedElements, elementsMap, handleDirection, sc
22990
23677
  if (boundTextElement && boundTextFontSize) {
22991
23678
  scene.mutateElement(boundTextElement, {
22992
23679
  fontSize: boundTextFontSize,
22993
- angle: isLinearElement(element) ? void 0 : angle
23680
+ angle: isLinearElement(element) ? void 0 : angle2
22994
23681
  });
22995
23682
  handleBindTextResize(element, scene, handleDirection, true);
22996
23683
  }
@@ -23002,9 +23689,9 @@ var resizeMultipleElements = (selectedElements, elementsMap, handleDirection, sc
23002
23689
  // src/resizeTest.ts
23003
23690
  init_define_import_meta_env();
23004
23691
  import {
23005
- pointFrom as pointFrom19,
23692
+ pointFrom as pointFrom18,
23006
23693
  pointOnLineSegment,
23007
- pointRotateRads as pointRotateRads16
23694
+ pointRotateRads as pointRotateRads15
23008
23695
  } from "@excalidraw/math";
23009
23696
  import {
23010
23697
  SIDE_RESIZING_THRESHOLD
@@ -23015,7 +23702,7 @@ init_define_import_meta_env();
23015
23702
  import {
23016
23703
  DEFAULT_TRANSFORM_HANDLE_SPACING
23017
23704
  } from "@excalidraw/common";
23018
- import { pointFrom as pointFrom18, pointRotateRads as pointRotateRads15 } from "@excalidraw/math";
23705
+ import { pointFrom as pointFrom17, pointRotateRads as pointRotateRads14 } from "@excalidraw/math";
23019
23706
  var transformHandleSizes = {
23020
23707
  mouse: 8,
23021
23708
  pen: 16,
@@ -23055,11 +23742,11 @@ var OMIT_SIDES_FOR_LINE_BACKSLASH = {
23055
23742
  n: true,
23056
23743
  w: true
23057
23744
  };
23058
- var generateTransformHandle = (x, y, width, height, cx, cy, angle) => {
23059
- const [xx, yy] = pointRotateRads15(
23060
- pointFrom18(x + width / 2, y + height / 2),
23061
- pointFrom18(cx, cy),
23062
- angle
23745
+ var generateTransformHandle = (x, y, width, height, cx, cy, angle2) => {
23746
+ const [xx, yy] = pointRotateRads14(
23747
+ pointFrom17(x + width / 2, y + height / 2),
23748
+ pointFrom17(cx, cy),
23749
+ angle2
23063
23750
  );
23064
23751
  return [xx - width / 2, yy - height / 2, width, height];
23065
23752
  };
@@ -23075,7 +23762,7 @@ var getOmitSidesForEditorInterface = (editorInterface) => {
23075
23762
  }
23076
23763
  return {};
23077
23764
  };
23078
- var getTransformHandlesFromCoords = ([x1, y1, x2, y2, cx, cy], angle, zoom, pointerType, omitSides = {}, margin = 4, spacing = DEFAULT_TRANSFORM_HANDLE_SPACING) => {
23765
+ var getTransformHandlesFromCoords = ([x1, y1, x2, y2, cx, cy], angle2, zoom, pointerType, omitSides = {}, margin = 4, spacing = DEFAULT_TRANSFORM_HANDLE_SPACING) => {
23079
23766
  const size = transformHandleSizes[pointerType];
23080
23767
  const handleWidth = size / zoom.value;
23081
23768
  const handleHeight = size / zoom.value;
@@ -23093,7 +23780,7 @@ var getTransformHandlesFromCoords = ([x1, y1, x2, y2, cx, cy], angle, zoom, poin
23093
23780
  handleHeight,
23094
23781
  cx,
23095
23782
  cy,
23096
- angle
23783
+ angle2
23097
23784
  ),
23098
23785
  ne: omitSides.ne ? void 0 : generateTransformHandle(
23099
23786
  x2 + dashedLineMargin - centeringOffset,
@@ -23102,7 +23789,7 @@ var getTransformHandlesFromCoords = ([x1, y1, x2, y2, cx, cy], angle, zoom, poin
23102
23789
  handleHeight,
23103
23790
  cx,
23104
23791
  cy,
23105
- angle
23792
+ angle2
23106
23793
  ),
23107
23794
  sw: omitSides.sw ? void 0 : generateTransformHandle(
23108
23795
  x1 - dashedLineMargin - handleMarginX + centeringOffset,
@@ -23111,7 +23798,7 @@ var getTransformHandlesFromCoords = ([x1, y1, x2, y2, cx, cy], angle, zoom, poin
23111
23798
  handleHeight,
23112
23799
  cx,
23113
23800
  cy,
23114
- angle
23801
+ angle2
23115
23802
  ),
23116
23803
  se: omitSides.se ? void 0 : generateTransformHandle(
23117
23804
  x2 + dashedLineMargin - centeringOffset,
@@ -23120,7 +23807,7 @@ var getTransformHandlesFromCoords = ([x1, y1, x2, y2, cx, cy], angle, zoom, poin
23120
23807
  handleHeight,
23121
23808
  cx,
23122
23809
  cy,
23123
- angle
23810
+ angle2
23124
23811
  ),
23125
23812
  rotation: omitSides.rotation ? void 0 : generateTransformHandle(
23126
23813
  x1 + width / 2 - handleWidth / 2,
@@ -23129,7 +23816,7 @@ var getTransformHandlesFromCoords = ([x1, y1, x2, y2, cx, cy], angle, zoom, poin
23129
23816
  handleHeight,
23130
23817
  cx,
23131
23818
  cy,
23132
- angle
23819
+ angle2
23133
23820
  )
23134
23821
  };
23135
23822
  const minimumSizeForEightHandles = 5 * transformHandleSizes.mouse / zoom.value;
@@ -23142,7 +23829,7 @@ var getTransformHandlesFromCoords = ([x1, y1, x2, y2, cx, cy], angle, zoom, poin
23142
23829
  handleHeight,
23143
23830
  cx,
23144
23831
  cy,
23145
- angle
23832
+ angle2
23146
23833
  );
23147
23834
  }
23148
23835
  if (!omitSides.s) {
@@ -23153,7 +23840,7 @@ var getTransformHandlesFromCoords = ([x1, y1, x2, y2, cx, cy], angle, zoom, poin
23153
23840
  handleHeight,
23154
23841
  cx,
23155
23842
  cy,
23156
- angle
23843
+ angle2
23157
23844
  );
23158
23845
  }
23159
23846
  }
@@ -23166,7 +23853,7 @@ var getTransformHandlesFromCoords = ([x1, y1, x2, y2, cx, cy], angle, zoom, poin
23166
23853
  handleHeight,
23167
23854
  cx,
23168
23855
  cy,
23169
- angle
23856
+ angle2
23170
23857
  );
23171
23858
  }
23172
23859
  if (!omitSides.e) {
@@ -23177,7 +23864,7 @@ var getTransformHandlesFromCoords = ([x1, y1, x2, y2, cx, cy], angle, zoom, poin
23177
23864
  handleHeight,
23178
23865
  cx,
23179
23866
  cy,
23180
- angle
23867
+ angle2
23181
23868
  );
23182
23869
  }
23183
23870
  }
@@ -23272,14 +23959,14 @@ var resizeTest = (element, elementsMap, appState, x, y, zoom, pointerType, edito
23272
23959
  const SPACING = isImageElement(element) ? 0 : SIDE_RESIZING_THRESHOLD / zoom.value;
23273
23960
  const ZOOMED_SIDE_RESIZING_THRESHOLD = SIDE_RESIZING_THRESHOLD / zoom.value;
23274
23961
  const sides = getSelectionBorders(
23275
- pointFrom19(x1 - SPACING, y1 - SPACING),
23276
- pointFrom19(x2 + SPACING, y2 + SPACING),
23277
- pointFrom19(cx, cy),
23962
+ pointFrom18(x1 - SPACING, y1 - SPACING),
23963
+ pointFrom18(x2 + SPACING, y2 + SPACING),
23964
+ pointFrom18(cx, cy),
23278
23965
  element.angle
23279
23966
  );
23280
23967
  for (const [dir, side] of Object.entries(sides)) {
23281
23968
  if (pointOnLineSegment(
23282
- pointFrom19(x, y),
23969
+ pointFrom18(x, y),
23283
23970
  side,
23284
23971
  ZOOMED_SIDE_RESIZING_THRESHOLD
23285
23972
  )) {
@@ -23328,14 +24015,14 @@ var getTransformHandleTypeFromCoords = ([x1, y1, x2, y2], scenePointerX, scenePo
23328
24015
  const cy = (y1 + y2) / 2;
23329
24016
  const SPACING = SIDE_RESIZING_THRESHOLD / zoom.value;
23330
24017
  const sides = getSelectionBorders(
23331
- pointFrom19(x1 - SPACING, y1 - SPACING),
23332
- pointFrom19(x2 + SPACING, y2 + SPACING),
23333
- pointFrom19(cx, cy),
24018
+ pointFrom18(x1 - SPACING, y1 - SPACING),
24019
+ pointFrom18(x2 + SPACING, y2 + SPACING),
24020
+ pointFrom18(cx, cy),
23334
24021
  0
23335
24022
  );
23336
24023
  for (const [dir, side] of Object.entries(sides)) {
23337
24024
  if (pointOnLineSegment(
23338
- pointFrom19(scenePointerX, scenePointerY),
24025
+ pointFrom18(scenePointerX, scenePointerY),
23339
24026
  side,
23340
24027
  SPACING
23341
24028
  )) {
@@ -23346,10 +24033,10 @@ var getTransformHandleTypeFromCoords = ([x1, y1, x2, y2], scenePointerX, scenePo
23346
24033
  return false;
23347
24034
  };
23348
24035
  var RESIZE_CURSORS = ["ns", "nesw", "ew", "nwse"];
23349
- var rotateResizeCursor = (cursor, angle) => {
24036
+ var rotateResizeCursor = (cursor, angle2) => {
23350
24037
  const index = RESIZE_CURSORS.indexOf(cursor);
23351
24038
  if (index >= 0) {
23352
- const a2 = Math.round(angle / (Math.PI / 4));
24039
+ const a2 = Math.round(angle2 / (Math.PI / 4));
23353
24040
  cursor = RESIZE_CURSORS[(index + a2) % RESIZE_CURSORS.length];
23354
24041
  }
23355
24042
  return cursor;
@@ -23391,11 +24078,11 @@ var getCursorForResizingElement = (resizingElement) => {
23391
24078
  }
23392
24079
  return cursor ? `${cursor}-resize` : "";
23393
24080
  };
23394
- var getSelectionBorders = ([x1, y1], [x2, y2], center, angle) => {
23395
- const topLeft = pointRotateRads16(pointFrom19(x1, y1), center, angle);
23396
- const topRight = pointRotateRads16(pointFrom19(x2, y1), center, angle);
23397
- const bottomLeft = pointRotateRads16(pointFrom19(x1, y2), center, angle);
23398
- const bottomRight = pointRotateRads16(pointFrom19(x2, y2), center, angle);
24081
+ var getSelectionBorders = ([x1, y1], [x2, y2], center, angle2) => {
24082
+ const topLeft = pointRotateRads15(pointFrom18(x1, y1), center, angle2);
24083
+ const topRight = pointRotateRads15(pointFrom18(x2, y1), center, angle2);
24084
+ const bottomLeft = pointRotateRads15(pointFrom18(x1, y2), center, angle2);
24085
+ const bottomRight = pointRotateRads15(pointFrom18(x2, y2), center, angle2);
23399
24086
  return {
23400
24087
  n: [topLeft, topRight],
23401
24088
  e: [topRight, bottomRight],
@@ -24634,6 +25321,96 @@ var SloppinessCartoonistIcon = createIcon(
24634
25321
  ),
24635
25322
  modifiedTablerIconProps
24636
25323
  );
25324
+ var strokeVariabilityConstantIcon = createIcon(
25325
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { children: [
25326
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
25327
+ "path",
25328
+ {
25329
+ d: "M4 12 C 5 8, 6 8, 8 12",
25330
+ fill: "none",
25331
+ strokeWidth: "1",
25332
+ strokeLinecap: "round",
25333
+ strokeLinejoin: "round"
25334
+ }
25335
+ ),
25336
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
25337
+ "path",
25338
+ {
25339
+ d: "M8 12 C 9 16, 10 16, 12 12",
25340
+ fill: "none",
25341
+ strokeWidth: "1",
25342
+ strokeLinecap: "round",
25343
+ strokeLinejoin: "round"
25344
+ }
25345
+ ),
25346
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
25347
+ "path",
25348
+ {
25349
+ d: "M12 12 C 14 8, 15 8, 16 12",
25350
+ fill: "none",
25351
+ strokeWidth: "1",
25352
+ strokeLinecap: "round",
25353
+ strokeLinejoin: "round"
25354
+ }
25355
+ ),
25356
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
25357
+ "path",
25358
+ {
25359
+ d: "M16 12 C 17 16, 18 16, 19 12",
25360
+ fill: "none",
25361
+ strokeWidth: "1",
25362
+ strokeLinecap: "round",
25363
+ strokeLinejoin: "round"
25364
+ }
25365
+ )
25366
+ ] }),
25367
+ tablerIconProps
25368
+ );
25369
+ var strokeVariabilityVariableIcon = createIcon(
25370
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { children: [
25371
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
25372
+ "path",
25373
+ {
25374
+ d: "M4 12 C 5 8, 6 8, 8 12",
25375
+ fill: "none",
25376
+ strokeWidth: "1.5",
25377
+ strokeLinecap: "round",
25378
+ strokeLinejoin: "round"
25379
+ }
25380
+ ),
25381
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
25382
+ "path",
25383
+ {
25384
+ d: "M8 12 C 9 16, 10 16, 12 12",
25385
+ fill: "none",
25386
+ strokeWidth: "2",
25387
+ strokeLinecap: "round",
25388
+ strokeLinejoin: "round"
25389
+ }
25390
+ ),
25391
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
25392
+ "path",
25393
+ {
25394
+ d: "M12 12 C 14 8, 15 8, 16 12",
25395
+ fill: "none",
25396
+ strokeWidth: "2.75",
25397
+ strokeLinecap: "round",
25398
+ strokeLinejoin: "round"
25399
+ }
25400
+ ),
25401
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
25402
+ "path",
25403
+ {
25404
+ d: "M16 12 C 17 16, 18 16, 19 12",
25405
+ fill: "none",
25406
+ strokeWidth: "3.25",
25407
+ strokeLinecap: "round",
25408
+ strokeLinejoin: "round"
25409
+ }
25410
+ )
25411
+ ] }),
25412
+ tablerIconProps
25413
+ );
24637
25414
  var EdgeSharpIcon = createIcon(
24638
25415
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { strokeWidth: "1.5", children: [
24639
25416
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3.33334 9.99998V6.66665C3.33334 6.04326 3.33403 4.9332 3.33539 3.33646C4.95233 3.33436 6.06276 3.33331 6.66668 3.33331H10" }),
@@ -25999,7 +26776,7 @@ var showSelectedShapeActions = (appState, elements) => Boolean(
25999
26776
 
26000
26777
  // src/transform.ts
26001
26778
  init_define_import_meta_env();
26002
- import { pointFrom as pointFrom20 } from "@excalidraw/math";
26779
+ import { pointFrom as pointFrom19 } from "@excalidraw/math";
26003
26780
  import {
26004
26781
  DEFAULT_FONT_FAMILY as DEFAULT_FONT_FAMILY3,
26005
26782
  DEFAULT_FONT_SIZE as DEFAULT_FONT_SIZE4,
@@ -26281,7 +27058,7 @@ var convertToExcalidrawElements = (elementsSkeleton, opts) => {
26281
27058
  excalidrawElement = newLinearElement({
26282
27059
  width,
26283
27060
  height,
26284
- points: [pointFrom20(0, 0), pointFrom20(width, height)],
27061
+ points: [pointFrom19(0, 0), pointFrom19(width, height)],
26285
27062
  ...element
26286
27063
  });
26287
27064
  break;
@@ -26293,7 +27070,7 @@ var convertToExcalidrawElements = (elementsSkeleton, opts) => {
26293
27070
  width,
26294
27071
  height,
26295
27072
  endArrowhead: "arrow",
26296
- points: [pointFrom20(0, 0), pointFrom20(width, height)],
27073
+ points: [pointFrom19(0, 0), pointFrom19(width, height)],
26297
27074
  ...element,
26298
27075
  type: "arrow"
26299
27076
  });
@@ -26673,6 +27450,7 @@ export {
26673
27450
  elementWithCanvasCache,
26674
27451
  elementsAreInFrameBounds,
26675
27452
  elementsAreInSameGroup,
27453
+ elementsOverlappingBBox,
26676
27454
  embeddableURLValidator,
26677
27455
  excludeElementsInFramesFromSelection,
26678
27456
  filterElementsEligibleAsFrameChildren,
@@ -26683,6 +27461,7 @@ export {
26683
27461
  frameAndChildrenSelectedTogether,
26684
27462
  generateLinearCollisionShape,
26685
27463
  generateRoughOptions,
27464
+ generateThumbHash,
26686
27465
  getActiveTextElement,
26687
27466
  getAllHoveredElementAtPoint,
26688
27467
  getApproxMinLineHeight,
@@ -26787,6 +27566,7 @@ export {
26787
27566
  getTextFromElements,
26788
27567
  getTextHeight,
26789
27568
  getTextWidth,
27569
+ getThumbHashPlaceholder,
26790
27570
  getToolbarTools,
26791
27571
  getTransformHandleTypeFromCoords,
26792
27572
  getTransformHandles,
@@ -26808,6 +27588,7 @@ export {
26808
27588
  hasBackground,
26809
27589
  hasBoundTextElement,
26810
27590
  hasBoundingBox,
27591
+ hasFreedrawMode,
26811
27592
  hasStrokeColor,
26812
27593
  hasStrokeStyle,
26813
27594
  hasStrokeWidth,