@excalidraw/element 0.18.0-f0063e113 → 0.18.0-f2600fe

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/dev/index.js +1098 -634
  2. package/dist/dev/index.js.map +4 -4
  3. package/dist/prod/index.js +14 -14
  4. package/dist/types/common/src/constants.d.ts +19 -15
  5. package/dist/types/common/src/editorInterface.d.ts +34 -0
  6. package/dist/types/common/src/index.d.ts +1 -0
  7. package/dist/types/common/src/utils.d.ts +2 -1
  8. package/dist/types/element/src/Scene.d.ts +6 -2
  9. package/dist/types/element/src/align.d.ts +2 -1
  10. package/dist/types/element/src/bounds.d.ts +1 -1
  11. package/dist/types/element/src/delta.d.ts +16 -4
  12. package/dist/types/element/src/distribute.d.ts +2 -1
  13. package/dist/types/element/src/groups.d.ts +1 -0
  14. package/dist/types/element/src/index.d.ts +1 -0
  15. package/dist/types/element/src/linearElementEditor.d.ts +2 -1
  16. package/dist/types/element/src/positionElementsOnGrid.d.ts +2 -0
  17. package/dist/types/element/src/renderElement.d.ts +4 -1
  18. package/dist/types/element/src/resizeTest.d.ts +5 -4
  19. package/dist/types/element/src/store.d.ts +8 -2
  20. package/dist/types/element/src/textElement.d.ts +1 -1
  21. package/dist/types/element/src/transformHandles.d.ts +5 -4
  22. package/dist/types/excalidraw/actions/actionAddToLibrary.d.ts +21 -12
  23. package/dist/types/excalidraw/actions/actionBoundText.d.ts +14 -8
  24. package/dist/types/excalidraw/actions/actionCanvas.d.ts +94 -54
  25. package/dist/types/excalidraw/actions/actionClipboard.d.ts +45 -26
  26. package/dist/types/excalidraw/actions/actionCropEditor.d.ts +7 -4
  27. package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +25 -16
  28. package/dist/types/excalidraw/actions/actionDuplicateSelection.d.ts +1 -1
  29. package/dist/types/excalidraw/actions/actionElementLink.d.ts +7 -4
  30. package/dist/types/excalidraw/actions/actionElementLock.d.ts +14 -8
  31. package/dist/types/excalidraw/actions/actionEmbeddable.d.ts +7 -4
  32. package/dist/types/excalidraw/actions/actionExport.d.ts +63 -36
  33. package/dist/types/excalidraw/actions/actionFinalize.d.ts +16 -9
  34. package/dist/types/excalidraw/actions/actionFrame.d.ts +28 -16
  35. package/dist/types/excalidraw/actions/actionGroup.d.ts +14 -8
  36. package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +41 -7
  37. package/dist/types/excalidraw/actions/actionLink.d.ts +5 -2
  38. package/dist/types/excalidraw/actions/actionMenu.d.ts +7 -372
  39. package/dist/types/excalidraw/actions/actionNavigate.d.ts +14 -8
  40. package/dist/types/excalidraw/actions/actionProperties.d.ts +122 -68
  41. package/dist/types/excalidraw/actions/actionSelectAll.d.ts +7 -4
  42. package/dist/types/excalidraw/actions/actionStyles.d.ts +7 -4
  43. package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +7 -4
  44. package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +7 -4
  45. package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +7 -4
  46. package/dist/types/excalidraw/actions/actionToggleStats.d.ts +7 -4
  47. package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +7 -4
  48. package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +8 -5
  49. package/dist/types/excalidraw/actions/index.d.ts +2 -2
  50. package/dist/types/excalidraw/actions/types.d.ts +1 -1
  51. package/dist/types/excalidraw/appState.d.ts +5 -1
  52. package/dist/types/excalidraw/clipboard.d.ts +64 -1
  53. package/dist/types/excalidraw/components/Actions.d.ts +20 -7
  54. package/dist/types/excalidraw/components/App.d.ts +29 -23
  55. package/dist/types/excalidraw/components/ColorPicker/Picker.d.ts +2 -0
  56. package/dist/types/excalidraw/components/ColorPicker/PickerColorList.d.ts +2 -1
  57. package/dist/types/excalidraw/components/ColorPicker/ShadeList.d.ts +2 -1
  58. package/dist/types/excalidraw/components/CommandPalette/CommandPalette.d.ts +1 -0
  59. package/dist/types/excalidraw/components/Ellipsify.d.ts +4 -0
  60. package/dist/types/excalidraw/components/ExcalidrawLogo.d.ts +1 -1
  61. package/dist/types/excalidraw/components/FilledButton.d.ts +1 -1
  62. package/dist/types/excalidraw/components/FontPicker/FontPicker.d.ts +2 -1
  63. package/dist/types/excalidraw/components/FontPicker/FontPickerTrigger.d.ts +3 -1
  64. package/dist/types/excalidraw/components/HintViewer.d.ts +4 -3
  65. package/dist/types/excalidraw/components/InlineIcon.d.ts +3 -1
  66. package/dist/types/excalidraw/components/LayerUI.d.ts +2 -1
  67. package/dist/types/excalidraw/components/LibraryMenuSection.d.ts +1 -1
  68. package/dist/types/excalidraw/components/MobileMenu.d.ts +3 -5
  69. package/dist/types/excalidraw/components/MobileToolBar.d.ts +11 -0
  70. package/dist/types/excalidraw/components/Popover.d.ts +2 -1
  71. package/dist/types/excalidraw/components/PropertiesPopover.d.ts +1 -0
  72. package/dist/types/excalidraw/components/TTDDialog/TTDDialogTrigger.d.ts +1 -2
  73. package/dist/types/excalidraw/components/TextField.d.ts +1 -0
  74. package/dist/types/excalidraw/components/ToolPopover.d.ts +25 -0
  75. package/dist/types/excalidraw/components/canvases/InteractiveCanvas.d.ts +3 -2
  76. package/dist/types/excalidraw/components/dropdownMenu/DropdownMenu.d.ts +4 -2
  77. package/dist/types/excalidraw/components/dropdownMenu/DropdownMenuContent.d.ts +2 -1
  78. package/dist/types/excalidraw/components/icons.d.ts +10 -0
  79. package/dist/types/excalidraw/components/live-collaboration/LiveCollaborationTrigger.d.ts +13 -1
  80. package/dist/types/excalidraw/components/main-menu/MainMenu.d.ts +0 -3
  81. package/dist/types/excalidraw/components/shapes.d.ts +129 -1
  82. package/dist/types/excalidraw/data/blob.d.ts +3 -7
  83. package/dist/types/excalidraw/data/reconcile.d.ts +1 -0
  84. package/dist/types/excalidraw/data/restore.d.ts +6 -1
  85. package/dist/types/excalidraw/data/types.d.ts +4 -1
  86. package/dist/types/excalidraw/hooks/useLibraryItemSvg.d.ts +1 -1
  87. package/dist/types/excalidraw/hooks/useOutsideClick.d.ts +3 -1
  88. package/dist/types/excalidraw/hooks/useTextEditorFocus.d.ts +14 -0
  89. package/dist/types/excalidraw/index.d.ts +4 -4
  90. package/dist/types/excalidraw/renderer/interactiveScene.d.ts +1 -1
  91. package/dist/types/excalidraw/renderer/staticScene.d.ts +4 -1
  92. package/dist/types/excalidraw/scene/types.d.ts +3 -3
  93. package/dist/types/excalidraw/shortcut.d.ts +1 -0
  94. package/dist/types/excalidraw/types.d.ts +23 -19
  95. package/dist/types/math/src/segment.d.ts +1 -0
  96. package/package.json +7 -3
package/dist/dev/index.js CHANGED
@@ -2261,17 +2261,17 @@ var rough_default = {
2261
2261
  // src/bounds.ts
2262
2262
  import {
2263
2263
  arrayToMap as arrayToMap6,
2264
- invariant as invariant7,
2264
+ invariant as invariant8,
2265
2265
  rescalePoints,
2266
2266
  sizeOf
2267
2267
  } from "@excalidraw/common";
2268
2268
  import {
2269
2269
  degreesToRadians,
2270
- lineSegment as lineSegment5,
2270
+ lineSegment as lineSegment6,
2271
2271
  pointDistance as pointDistance7,
2272
- pointFrom as pointFrom12,
2272
+ pointFrom as pointFrom14,
2273
2273
  pointFromArray as pointFromArray3,
2274
- pointRotateRads as pointRotateRads10
2274
+ pointRotateRads as pointRotateRads12
2275
2275
  } from "@excalidraw/math";
2276
2276
 
2277
2277
  // ../utils/src/shape.ts
@@ -2448,9 +2448,9 @@ var getClosedCurveShape = (element, roughShape, startingPoint = pointFrom(0, 0),
2448
2448
  // src/shape.ts
2449
2449
  init_define_import_meta_env();
2450
2450
  import {
2451
- pointFrom as pointFrom11,
2451
+ pointFrom as pointFrom13,
2452
2452
  pointDistance as pointDistance6,
2453
- pointRotateRads as pointRotateRads9
2453
+ pointRotateRads as pointRotateRads11
2454
2454
  } from "@excalidraw/math";
2455
2455
  import {
2456
2456
  ROUGHNESS,
@@ -2627,7 +2627,12 @@ function ae(e, t = {}) {
2627
2627
  }
2628
2628
 
2629
2629
  // src/renderElement.ts
2630
- import { isRightAngleRads } from "@excalidraw/math";
2630
+ import {
2631
+ isRightAngleRads,
2632
+ lineSegment as lineSegment5,
2633
+ pointFrom as pointFrom12,
2634
+ pointRotateRads as pointRotateRads10
2635
+ } from "@excalidraw/math";
2631
2636
  import {
2632
2637
  BOUND_TEXT_PADDING as BOUND_TEXT_PADDING3,
2633
2638
  DEFAULT_REDUCED_GLOBAL_ALPHA,
@@ -2638,7 +2643,8 @@ import {
2638
2643
  distance as distance2,
2639
2644
  getFontString as getFontString3,
2640
2645
  isRTL,
2641
- getVerticalOffset
2646
+ getVerticalOffset,
2647
+ invariant as invariant7
2642
2648
  } from "@excalidraw/common";
2643
2649
 
2644
2650
  // src/cropElement.ts
@@ -3103,8 +3109,8 @@ var getFlipAdjustedCropPosition = (element, natural = false) => {
3103
3109
  init_define_import_meta_env();
3104
3110
  import {
3105
3111
  pointCenter as pointCenter2,
3106
- pointFrom as pointFrom8,
3107
- pointRotateRads as pointRotateRads7,
3112
+ pointFrom as pointFrom9,
3113
+ pointRotateRads as pointRotateRads8,
3108
3114
  pointsEqual as pointsEqual6,
3109
3115
  pointDistance as pointDistance5,
3110
3116
  vectorFromPoint as vectorFromPoint7,
@@ -3138,8 +3144,8 @@ import {
3138
3144
  } from "@excalidraw/common";
3139
3145
  import {
3140
3146
  lineSegment as lineSegment4,
3141
- pointFrom as pointFrom7,
3142
- pointRotateRads as pointRotateRads6,
3147
+ pointFrom as pointFrom8,
3148
+ pointRotateRads as pointRotateRads7,
3143
3149
  vectorFromPoint as vectorFromPoint6,
3144
3150
  pointDistanceSq,
3145
3151
  clamp as clamp3,
@@ -3161,9 +3167,9 @@ import {
3161
3167
  isPointWithinBounds,
3162
3168
  lineSegment as lineSegment3,
3163
3169
  lineSegmentIntersectionPoints,
3164
- pointFrom as pointFrom4,
3170
+ pointFrom as pointFrom5,
3165
3171
  pointFromVector as pointFromVector3,
3166
- pointRotateRads as pointRotateRads4,
3172
+ pointRotateRads as pointRotateRads5,
3167
3173
  pointsEqual as pointsEqual2,
3168
3174
  vectorFromPoint as vectorFromPoint3,
3169
3175
  vectorNormalize as vectorNormalize2,
@@ -3711,6 +3717,7 @@ import {
3711
3717
  isProdEnv,
3712
3718
  invariant as invariant2
3713
3719
  } from "@excalidraw/common";
3720
+ import { pointFrom as pointFrom4, pointRotateRads as pointRotateRads3 } from "@excalidraw/math";
3714
3721
 
3715
3722
  // src/containerCache.ts
3716
3723
  init_define_import_meta_env();
@@ -4390,6 +4397,22 @@ var computeBoundTextPosition = (container, boundTextElement, elementsMap) => {
4390
4397
  } else {
4391
4398
  x = containerCoords.x + (maxContainerWidth / 2 - boundTextElement.width / 2);
4392
4399
  }
4400
+ const angle = container.angle ?? 0;
4401
+ if (angle !== 0) {
4402
+ const contentCenter = pointFrom4(
4403
+ containerCoords.x + maxContainerWidth / 2,
4404
+ containerCoords.y + maxContainerHeight / 2
4405
+ );
4406
+ const textCenter = pointFrom4(
4407
+ x + boundTextElement.width / 2,
4408
+ y + boundTextElement.height / 2
4409
+ );
4410
+ const [rx, ry] = pointRotateRads3(textCenter, contentCenter, angle);
4411
+ return {
4412
+ x: rx - boundTextElement.width / 2,
4413
+ y: ry - boundTextElement.height / 2
4414
+ };
4415
+ }
4393
4416
  return { x, y };
4394
4417
  };
4395
4418
  var getBoundTextElementId = (container) => {
@@ -4573,7 +4596,7 @@ init_define_import_meta_env();
4573
4596
  import {
4574
4597
  curvePointDistance,
4575
4598
  distanceToLineSegment,
4576
- pointRotateRads as pointRotateRads3
4599
+ pointRotateRads as pointRotateRads4
4577
4600
  } from "@excalidraw/math";
4578
4601
  import { ellipse as ellipse2, ellipseDistanceFromPoint } from "@excalidraw/math/ellipse";
4579
4602
  var distanceToElement = (element, elementsMap, p) => {
@@ -4599,7 +4622,7 @@ var distanceToElement = (element, elementsMap, p) => {
4599
4622
  };
4600
4623
  var distanceToRectanguloidElement = (element, elementsMap, p) => {
4601
4624
  const center = elementCenterPoint(element, elementsMap);
4602
- const rotatedPoint = pointRotateRads3(p, center, -element.angle);
4625
+ const rotatedPoint = pointRotateRads4(p, center, -element.angle);
4603
4626
  const [sides, corners] = deconstructRectanguloidElement(element);
4604
4627
  return Math.min(
4605
4628
  ...sides.map((s) => distanceToLineSegment(rotatedPoint, s)),
@@ -4608,7 +4631,7 @@ var distanceToRectanguloidElement = (element, elementsMap, p) => {
4608
4631
  };
4609
4632
  var distanceToDiamondElement = (element, elementsMap, p) => {
4610
4633
  const center = elementCenterPoint(element, elementsMap);
4611
- const rotatedPoint = pointRotateRads3(p, center, -element.angle);
4634
+ const rotatedPoint = pointRotateRads4(p, center, -element.angle);
4612
4635
  const [sides, curves] = deconstructDiamondElement(element);
4613
4636
  return Math.min(
4614
4637
  ...sides.map((s) => distanceToLineSegment(rotatedPoint, s)),
@@ -4619,7 +4642,7 @@ var distanceToEllipseElement = (element, elementsMap, p) => {
4619
4642
  const center = elementCenterPoint(element, elementsMap);
4620
4643
  return ellipseDistanceFromPoint(
4621
4644
  // Instead of rotating the ellipse, rotate the point to the inverse angle
4622
- pointRotateRads3(p, center, -element.angle),
4645
+ pointRotateRads4(p, center, -element.angle),
4623
4646
  ellipse2(center, element.width / 2, element.height / 2)
4624
4647
  );
4625
4648
  };
@@ -4653,22 +4676,22 @@ var hitElementItself = ({
4653
4676
  frameNameBound = null
4654
4677
  }) => {
4655
4678
  const hitFrameName = frameNameBound ? isPointWithinBounds(
4656
- pointFrom4(frameNameBound.x - threshold, frameNameBound.y - threshold),
4679
+ pointFrom5(frameNameBound.x - threshold, frameNameBound.y - threshold),
4657
4680
  point,
4658
- pointFrom4(
4681
+ pointFrom5(
4659
4682
  frameNameBound.x + frameNameBound.width + threshold,
4660
4683
  frameNameBound.y + frameNameBound.height + threshold
4661
4684
  )
4662
4685
  ) : false;
4663
4686
  const bounds = getElementBounds(element, elementsMap, true);
4664
4687
  const hitBounds = isPointWithinBounds(
4665
- pointFrom4(bounds[0] - threshold, bounds[1] - threshold),
4666
- pointRotateRads4(
4688
+ pointFrom5(bounds[0] - threshold, bounds[1] - threshold),
4689
+ pointRotateRads5(
4667
4690
  point,
4668
4691
  getCenterForBounds(bounds),
4669
4692
  -element.angle
4670
4693
  ),
4671
- pointFrom4(bounds[2] + threshold, bounds[3] + threshold)
4694
+ pointFrom5(bounds[2] + threshold, bounds[3] + threshold)
4672
4695
  );
4673
4696
  if (!hitBounds && !hitFrameName) {
4674
4697
  return false;
@@ -4686,7 +4709,7 @@ var hitElementBoundingBox = (point, element, elementsMap, tolerance = 0) => {
4686
4709
  y1 -= tolerance;
4687
4710
  x2 += tolerance;
4688
4711
  y2 += tolerance;
4689
- return isPointWithinBounds(pointFrom4(x1, y1), point, pointFrom4(x2, y2));
4712
+ return isPointWithinBounds(pointFrom5(x1, y1), point, pointFrom5(x2, y2));
4690
4713
  };
4691
4714
  var hitElementBoundingBoxOnly = (hitArgs, elementsMap) => !hitElementItself(hitArgs) && // bound text is considered part of the element (even if it's outside the bounding box)
4692
4715
  !hitElementBoundText(hitArgs.point, hitArgs.element, elementsMap) && hitElementBoundingBox(hitArgs.point, hitArgs.element, elementsMap);
@@ -4770,7 +4793,7 @@ var curveIntersections = (curves, segment, intersections, center, angle, onlyFir
4770
4793
  const hits = curveIntersectLineSegment(c, segment);
4771
4794
  if (hits.length > 0) {
4772
4795
  for (const j of hits) {
4773
- intersections.push(pointRotateRads4(j, center, angle));
4796
+ intersections.push(pointRotateRads5(j, center, angle));
4774
4797
  }
4775
4798
  if (onlyFirst) {
4776
4799
  return intersections;
@@ -4783,7 +4806,7 @@ var lineIntersections = (lines, segment, intersections, center, angle, onlyFirst
4783
4806
  for (const l2 of lines) {
4784
4807
  const intersection = lineSegmentIntersectionPoints(l2, segment);
4785
4808
  if (intersection) {
4786
- intersections.push(pointRotateRads4(intersection, center, angle));
4809
+ intersections.push(pointRotateRads5(intersection, center, angle));
4787
4810
  if (onlyFirst) {
4788
4811
  return intersections;
4789
4812
  }
@@ -4826,12 +4849,12 @@ var intersectLinearOrFreeDrawWithLineSegment = (element, segment, onlyFirst = fa
4826
4849
  };
4827
4850
  var intersectRectanguloidWithLineSegment = (element, elementsMap, segment, offset = 0, onlyFirst = false) => {
4828
4851
  const center = elementCenterPoint(element, elementsMap);
4829
- const rotatedA = pointRotateRads4(
4852
+ const rotatedA = pointRotateRads5(
4830
4853
  segment[0],
4831
4854
  center,
4832
4855
  -element.angle
4833
4856
  );
4834
- const rotatedB = pointRotateRads4(
4857
+ const rotatedB = pointRotateRads5(
4835
4858
  segment[1],
4836
4859
  center,
4837
4860
  -element.angle
@@ -4862,8 +4885,8 @@ var intersectRectanguloidWithLineSegment = (element, elementsMap, segment, offse
4862
4885
  };
4863
4886
  var intersectDiamondWithLineSegment = (element, elementsMap, l2, offset = 0, onlyFirst = false) => {
4864
4887
  const center = elementCenterPoint(element, elementsMap);
4865
- const rotatedA = pointRotateRads4(l2[0], center, -element.angle);
4866
- const rotatedB = pointRotateRads4(l2[1], center, -element.angle);
4888
+ const rotatedA = pointRotateRads5(l2[0], center, -element.angle);
4889
+ const rotatedB = pointRotateRads5(l2[1], center, -element.angle);
4867
4890
  const rotatedIntersector = lineSegment3(rotatedA, rotatedB);
4868
4891
  const [sides, corners] = deconstructDiamondElement(element, offset);
4869
4892
  const intersections = [];
@@ -4890,12 +4913,12 @@ var intersectDiamondWithLineSegment = (element, elementsMap, l2, offset = 0, onl
4890
4913
  };
4891
4914
  var intersectEllipseWithLineSegment = (element, elementsMap, l2, offset = 0) => {
4892
4915
  const center = elementCenterPoint(element, elementsMap);
4893
- const rotatedA = pointRotateRads4(l2[0], center, -element.angle);
4894
- const rotatedB = pointRotateRads4(l2[1], center, -element.angle);
4916
+ const rotatedA = pointRotateRads5(l2[0], center, -element.angle);
4917
+ const rotatedB = pointRotateRads5(l2[1], center, -element.angle);
4895
4918
  return ellipseSegmentInterceptPoints(
4896
4919
  ellipse3(center, element.width / 2 + offset, element.height / 2 + offset),
4897
4920
  lineSegment3(rotatedA, rotatedB)
4898
- ).map((p) => pointRotateRads4(p, center, element.angle));
4921
+ ).map((p) => pointRotateRads5(p, center, element.angle));
4899
4922
  };
4900
4923
  var isPointOnElementOutline = (point, element, elementsMap, tolerance = 1) => distanceToElement(element, elementsMap, point) <= tolerance;
4901
4924
  var isPointInElement = (point, element, elementsMap) => {
@@ -4903,10 +4926,10 @@ var isPointInElement = (point, element, elementsMap) => {
4903
4926
  return false;
4904
4927
  }
4905
4928
  const [x1, y1, x2, y2] = getElementBounds(element, elementsMap);
4906
- if (!isPointWithinBounds(pointFrom4(x1, y1), point, pointFrom4(x2, y2))) {
4929
+ if (!isPointWithinBounds(pointFrom5(x1, y1), point, pointFrom5(x2, y2))) {
4907
4930
  return false;
4908
4931
  }
4909
- const center = pointFrom4((x1 + x2) / 2, (y1 + y2) / 2);
4932
+ const center = pointFrom5((x1 + x2) / 2, (y1 + y2) / 2);
4910
4933
  const otherPoint = pointFromVector3(
4911
4934
  vectorScale3(
4912
4935
  vectorNormalize2(vectorFromPoint3(point, center, 0.1)),
@@ -4927,9 +4950,9 @@ var isPointInElement = (point, element, elementsMap) => {
4927
4950
  init_define_import_meta_env();
4928
4951
  import { invariant as invariant3, isDevEnv as isDevEnv2, isTestEnv as isTestEnv3 } from "@excalidraw/common";
4929
4952
  import {
4930
- pointFrom as pointFrom5,
4953
+ pointFrom as pointFrom6,
4931
4954
  pointFromVector as pointFromVector4,
4932
- pointRotateRads as pointRotateRads5,
4955
+ pointRotateRads as pointRotateRads6,
4933
4956
  pointScaleFromOrigin,
4934
4957
  pointsEqual as pointsEqual3,
4935
4958
  triangleIncludesPoint,
@@ -4975,8 +4998,8 @@ var headingForPointFromDiamondElement = (element, aabb, point) => {
4975
4998
  const top = pointFromVector4(
4976
4999
  vectorScale4(
4977
5000
  vectorFromPoint4(
4978
- pointRotateRads5(
4979
- pointFrom5(element.x + element.width / 2, element.y),
5001
+ pointRotateRads6(
5002
+ pointFrom6(element.x + element.width / 2, element.y),
4980
5003
  midPoint,
4981
5004
  element.angle
4982
5005
  ),
@@ -4989,8 +5012,8 @@ var headingForPointFromDiamondElement = (element, aabb, point) => {
4989
5012
  const right = pointFromVector4(
4990
5013
  vectorScale4(
4991
5014
  vectorFromPoint4(
4992
- pointRotateRads5(
4993
- pointFrom5(
5015
+ pointRotateRads6(
5016
+ pointFrom6(
4994
5017
  element.x + element.width,
4995
5018
  element.y + element.height / 2
4996
5019
  ),
@@ -5006,8 +5029,8 @@ var headingForPointFromDiamondElement = (element, aabb, point) => {
5006
5029
  const bottom = pointFromVector4(
5007
5030
  vectorScale4(
5008
5031
  vectorFromPoint4(
5009
- pointRotateRads5(
5010
- pointFrom5(
5032
+ pointRotateRads6(
5033
+ pointFrom6(
5011
5034
  element.x + element.width / 2,
5012
5035
  element.y + element.height
5013
5036
  ),
@@ -5023,8 +5046,8 @@ var headingForPointFromDiamondElement = (element, aabb, point) => {
5023
5046
  const left = pointFromVector4(
5024
5047
  vectorScale4(
5025
5048
  vectorFromPoint4(
5026
- pointRotateRads5(
5027
- pointFrom5(element.x, element.y + element.height / 2),
5049
+ pointRotateRads6(
5050
+ pointFrom6(element.x, element.y + element.height / 2),
5028
5051
  midPoint,
5029
5052
  element.angle
5030
5053
  ),
@@ -5090,22 +5113,22 @@ var headingForPointFromElement = (element, aabb, p) => {
5090
5113
  return headingForPointFromDiamondElement(element, aabb, p);
5091
5114
  }
5092
5115
  const topLeft = pointScaleFromOrigin(
5093
- pointFrom5(aabb[0], aabb[1]),
5116
+ pointFrom6(aabb[0], aabb[1]),
5094
5117
  midPoint,
5095
5118
  SEARCH_CONE_MULTIPLIER
5096
5119
  );
5097
5120
  const topRight = pointScaleFromOrigin(
5098
- pointFrom5(aabb[2], aabb[1]),
5121
+ pointFrom6(aabb[2], aabb[1]),
5099
5122
  midPoint,
5100
5123
  SEARCH_CONE_MULTIPLIER
5101
5124
  );
5102
5125
  const bottomLeft = pointScaleFromOrigin(
5103
- pointFrom5(aabb[0], aabb[3]),
5126
+ pointFrom6(aabb[0], aabb[3]),
5104
5127
  midPoint,
5105
5128
  SEARCH_CONE_MULTIPLIER
5106
5129
  );
5107
5130
  const bottomRight = pointScaleFromOrigin(
5108
- pointFrom5(aabb[2], aabb[3]),
5131
+ pointFrom6(aabb[2], aabb[3]),
5109
5132
  midPoint,
5110
5133
  SEARCH_CONE_MULTIPLIER
5111
5134
  );
@@ -5138,7 +5161,7 @@ init_define_import_meta_env();
5138
5161
  import {
5139
5162
  clamp as clamp2,
5140
5163
  pointDistance as pointDistance3,
5141
- pointFrom as pointFrom6,
5164
+ pointFrom as pointFrom7,
5142
5165
  pointScaleFromOrigin as pointScaleFromOrigin2,
5143
5166
  pointsEqual as pointsEqual4,
5144
5167
  pointTranslate,
@@ -5162,7 +5185,7 @@ var handleSegmentRenormalization = (arrow, elementsMap) => {
5162
5185
  const nextFixedSegments = arrow.fixedSegments ? arrow.fixedSegments.slice() : null;
5163
5186
  if (nextFixedSegments) {
5164
5187
  const _nextPoints = [];
5165
- arrow.points.map((p) => pointFrom6(arrow.x + p[0], arrow.y + p[1])).forEach((p, i, points) => {
5188
+ arrow.points.map((p) => pointFrom7(arrow.x + p[0], arrow.y + p[1])).forEach((p, i, points) => {
5166
5189
  if (i < 2) {
5167
5190
  return _nextPoints.push(p);
5168
5191
  }
@@ -5180,7 +5203,7 @@ var handleSegmentRenormalization = (arrow, elementsMap) => {
5180
5203
  ) ?? -1;
5181
5204
  const segmentIdx = nextFixedSegments?.findIndex((segment) => segment.index === i) ?? -1;
5182
5205
  if (segmentIdx !== -1) {
5183
- nextFixedSegments[segmentIdx].start = pointFrom6(
5206
+ nextFixedSegments[segmentIdx].start = pointFrom7(
5184
5207
  points[i - 2][0] - arrow.x,
5185
5208
  points[i - 2][1] - arrow.y
5186
5209
  );
@@ -5222,7 +5245,7 @@ var handleSegmentRenormalization = (arrow, elementsMap) => {
5222
5245
  });
5223
5246
  const isHorizontal = headingForPointIsHorizontal(p, points[i - 1]);
5224
5247
  return nextPoints.push(
5225
- pointFrom6(
5248
+ pointFrom7(
5226
5249
  !isHorizontal ? points[i - 2][0] : p[0],
5227
5250
  isHorizontal ? points[i - 2][1] : p[1]
5228
5251
  )
@@ -5243,7 +5266,7 @@ var handleSegmentRenormalization = (arrow, elementsMap) => {
5243
5266
  arrow,
5244
5267
  elementsMap,
5245
5268
  nextPoints.map(
5246
- (p) => pointFrom6(p[0] - arrow.x, p[1] - arrow.y)
5269
+ (p) => pointFrom7(p[0] - arrow.x, p[1] - arrow.y)
5247
5270
  )
5248
5271
  )
5249
5272
  ) ?? []
@@ -5312,8 +5335,8 @@ var handleSegmentRelease = (arrow, fixedSegments, elementsMap) => {
5312
5335
  },
5313
5336
  elementsMap,
5314
5337
  [
5315
- pointFrom6(0, 0),
5316
- pointFrom6(
5338
+ pointFrom7(0, 0),
5339
+ pointFrom7(
5317
5340
  arrow.x + (nextSegment?.start[0] ?? arrow.points[arrow.points.length - 1][0]) - x,
5318
5341
  arrow.y + (nextSegment?.start[1] ?? arrow.points[arrow.points.length - 1][1]) - y
5319
5342
  )
@@ -5338,11 +5361,16 @@ var handleSegmentRelease = (arrow, fixedSegments, elementsMap) => {
5338
5361
  null,
5339
5362
  null
5340
5363
  );
5364
+ if (!restoredPoints || restoredPoints.length < 2) {
5365
+ throw new Error(
5366
+ "Property 'points' is required in the update returned by normalizeArrowElementUpdate()"
5367
+ );
5368
+ }
5341
5369
  const nextPoints = [];
5342
5370
  if (prevSegment) {
5343
5371
  for (let i = 0; i < prevSegment.index; i++) {
5344
5372
  nextPoints.push(
5345
- pointFrom6(
5373
+ pointFrom7(
5346
5374
  arrow.x + arrow.points[i][0],
5347
5375
  arrow.y + arrow.points[i][1]
5348
5376
  )
@@ -5351,7 +5379,7 @@ var handleSegmentRelease = (arrow, fixedSegments, elementsMap) => {
5351
5379
  }
5352
5380
  restoredPoints.forEach((p) => {
5353
5381
  nextPoints.push(
5354
- pointFrom6(
5382
+ pointFrom7(
5355
5383
  arrow.x + (prevSegment ? prevSegment.end[0] : 0) + p[0],
5356
5384
  arrow.y + (prevSegment ? prevSegment.end[1] : 0) + p[1]
5357
5385
  )
@@ -5360,7 +5388,7 @@ var handleSegmentRelease = (arrow, fixedSegments, elementsMap) => {
5360
5388
  if (nextSegment) {
5361
5389
  for (let i = nextSegment.index; i < arrow.points.length; i++) {
5362
5390
  nextPoints.push(
5363
- pointFrom6(
5391
+ pointFrom7(
5364
5392
  arrow.x + arrow.points[i][0],
5365
5393
  arrow.y + arrow.points[i][1]
5366
5394
  )
@@ -5431,7 +5459,7 @@ var handleSegmentMove = (arrow, fixedSegments, startHeading, endHeading, hovered
5431
5459
  const startIsHorizontal = headingIsHorizontal(startHeading);
5432
5460
  const startIsPositive = startIsHorizontal ? compareHeading(startHeading, HEADING_RIGHT) : compareHeading(startHeading, HEADING_DOWN);
5433
5461
  const padding = startIsPositive ? segmentIsTooShort ? segmentLength / 2 : BASE_PADDING : segmentIsTooShort ? -segmentLength / 2 : -BASE_PADDING;
5434
- fixedSegments[activelyModifiedSegmentIdx].start = pointFrom6(
5462
+ fixedSegments[activelyModifiedSegmentIdx].start = pointFrom7(
5435
5463
  fixedSegments[activelyModifiedSegmentIdx].start[0] + (startIsHorizontal ? padding : 0),
5436
5464
  fixedSegments[activelyModifiedSegmentIdx].start[1] + (!startIsHorizontal ? padding : 0)
5437
5465
  );
@@ -5440,24 +5468,24 @@ var handleSegmentMove = (arrow, fixedSegments, startHeading, endHeading, hovered
5440
5468
  const endIsHorizontal = headingIsHorizontal(endHeading);
5441
5469
  const endIsPositive = endIsHorizontal ? compareHeading(endHeading, HEADING_RIGHT) : compareHeading(endHeading, HEADING_DOWN);
5442
5470
  const padding = endIsPositive ? segmentIsTooShort ? segmentLength / 2 : BASE_PADDING : segmentIsTooShort ? -segmentLength / 2 : -BASE_PADDING;
5443
- fixedSegments[activelyModifiedSegmentIdx].end = pointFrom6(
5471
+ fixedSegments[activelyModifiedSegmentIdx].end = pointFrom7(
5444
5472
  fixedSegments[activelyModifiedSegmentIdx].end[0] + (endIsHorizontal ? padding : 0),
5445
5473
  fixedSegments[activelyModifiedSegmentIdx].end[1] + (!endIsHorizontal ? padding : 0)
5446
5474
  );
5447
5475
  }
5448
5476
  const nextFixedSegments = fixedSegments.map((segment) => ({
5449
5477
  ...segment,
5450
- start: pointFrom6(
5478
+ start: pointFrom7(
5451
5479
  arrow.x + segment.start[0],
5452
5480
  arrow.y + segment.start[1]
5453
5481
  ),
5454
- end: pointFrom6(
5482
+ end: pointFrom7(
5455
5483
  arrow.x + segment.end[0],
5456
5484
  arrow.y + segment.end[1]
5457
5485
  )
5458
5486
  }));
5459
5487
  const newPoints = arrow.points.map(
5460
- (p, i) => pointFrom6(arrow.x + p[0], arrow.y + p[1])
5488
+ (p, i) => pointFrom7(arrow.x + p[0], arrow.y + p[1])
5461
5489
  );
5462
5490
  const startIdx = nextFixedSegments[activelyModifiedSegmentIdx].index - 1;
5463
5491
  const endIdx = nextFixedSegments[activelyModifiedSegmentIdx].index;
@@ -5503,14 +5531,14 @@ var handleSegmentMove = (arrow, fixedSegments, startHeading, endHeading, hovered
5503
5531
  if (firstSegmentIdx === -1 && startIdx === 0) {
5504
5532
  const startIsHorizontal = hoveredStartElement ? headingIsHorizontal(startHeading) : headingForPointIsHorizontal(newPoints[1], newPoints[0]);
5505
5533
  newPoints.unshift(
5506
- pointFrom6(
5534
+ pointFrom7(
5507
5535
  startIsHorizontal ? start[0] : arrow.x + arrow.points[0][0],
5508
5536
  !startIsHorizontal ? start[1] : arrow.y + arrow.points[0][1]
5509
5537
  )
5510
5538
  );
5511
5539
  if (hoveredStartElement) {
5512
5540
  newPoints.unshift(
5513
- pointFrom6(
5541
+ pointFrom7(
5514
5542
  arrow.x + arrow.points[0][0],
5515
5543
  arrow.y + arrow.points[0][1]
5516
5544
  )
@@ -5523,14 +5551,14 @@ var handleSegmentMove = (arrow, fixedSegments, startHeading, endHeading, hovered
5523
5551
  if (lastSegmentIdx === -1 && endIdx === arrow.points.length - 1) {
5524
5552
  const endIsHorizontal = headingIsHorizontal(endHeading);
5525
5553
  newPoints.push(
5526
- pointFrom6(
5554
+ pointFrom7(
5527
5555
  endIsHorizontal ? end[0] : arrow.x + arrow.points[arrow.points.length - 1][0],
5528
5556
  !endIsHorizontal ? end[1] : arrow.y + arrow.points[arrow.points.length - 1][1]
5529
5557
  )
5530
5558
  );
5531
5559
  if (hoveredEndElement) {
5532
5560
  newPoints.push(
5533
- pointFrom6(
5561
+ pointFrom7(
5534
5562
  arrow.x + arrow.points[arrow.points.length - 1][0],
5535
5563
  arrow.y + arrow.points[arrow.points.length - 1][1]
5536
5564
  )
@@ -5541,11 +5569,11 @@ var handleSegmentMove = (arrow, fixedSegments, startHeading, endHeading, hovered
5541
5569
  newPoints,
5542
5570
  nextFixedSegments.map((segment) => ({
5543
5571
  ...segment,
5544
- start: pointFrom6(
5572
+ start: pointFrom7(
5545
5573
  segment.start[0] - arrow.x,
5546
5574
  segment.start[1] - arrow.y
5547
5575
  ),
5548
- end: pointFrom6(
5576
+ end: pointFrom7(
5549
5577
  segment.end[0] - arrow.x,
5550
5578
  segment.end[1] - arrow.y
5551
5579
  )
@@ -5560,18 +5588,18 @@ var handleEndpointDrag = (arrow, updatedPoints, fixedSegments, startHeading, end
5560
5588
  let startIsSpecial = arrow.startIsSpecial ?? null;
5561
5589
  let endIsSpecial = arrow.endIsSpecial ?? null;
5562
5590
  const globalUpdatedPoints = updatedPoints.map(
5563
- (p, i) => i === 0 ? pointFrom6(arrow.x + p[0], arrow.y + p[1]) : i === updatedPoints.length - 1 ? pointFrom6(arrow.x + p[0], arrow.y + p[1]) : pointFrom6(
5591
+ (p, i) => i === 0 ? pointFrom7(arrow.x + p[0], arrow.y + p[1]) : i === updatedPoints.length - 1 ? pointFrom7(arrow.x + p[0], arrow.y + p[1]) : pointFrom7(
5564
5592
  arrow.x + arrow.points[i][0],
5565
5593
  arrow.y + arrow.points[i][1]
5566
5594
  )
5567
5595
  );
5568
5596
  const nextFixedSegments = fixedSegments.map((segment) => ({
5569
5597
  ...segment,
5570
- start: pointFrom6(
5598
+ start: pointFrom7(
5571
5599
  arrow.x + (segment.start[0] - updatedPoints[0][0]),
5572
5600
  arrow.y + (segment.start[1] - updatedPoints[0][1])
5573
5601
  ),
5574
- end: pointFrom6(
5602
+ end: pointFrom7(
5575
5603
  arrow.x + (segment.end[0] - updatedPoints[0][0]),
5576
5604
  arrow.y + (segment.end[1] - updatedPoints[0][1])
5577
5605
  )
@@ -5583,8 +5611,13 @@ var handleEndpointDrag = (arrow, updatedPoints, fixedSegments, startHeading, end
5583
5611
  newPoints.push(globalUpdatedPoints[newPoints.length + offset]);
5584
5612
  }
5585
5613
  {
5586
- const secondPoint = globalUpdatedPoints[startIsSpecial ? 2 : 1];
5587
- const thirdPoint = globalUpdatedPoints[startIsSpecial ? 3 : 2];
5614
+ const secondPoint = globalUpdatedPoints.at(startIsSpecial ? 2 : 1);
5615
+ const thirdPoint = globalUpdatedPoints.at(startIsSpecial ? 3 : 2);
5616
+ if (!secondPoint || !thirdPoint) {
5617
+ throw new Error(
5618
+ `Second and third points must exist when handling endpoint drag (${startIsSpecial})`
5619
+ );
5620
+ }
5588
5621
  const startIsHorizontal = headingIsHorizontal(startHeading);
5589
5622
  const secondIsHorizontal = headingIsHorizontal(
5590
5623
  vectorToHeading(vectorFromPoint5(secondPoint, thirdPoint))
@@ -5592,13 +5625,13 @@ var handleEndpointDrag = (arrow, updatedPoints, fixedSegments, startHeading, end
5592
5625
  if (hoveredStartElement && startIsHorizontal === secondIsHorizontal) {
5593
5626
  const positive = startIsHorizontal ? compareHeading(startHeading, HEADING_RIGHT) : compareHeading(startHeading, HEADING_DOWN);
5594
5627
  newPoints.unshift(
5595
- pointFrom6(
5628
+ pointFrom7(
5596
5629
  !secondIsHorizontal ? thirdPoint[0] : startGlobalPoint[0] + (positive ? BASE_PADDING : -BASE_PADDING),
5597
5630
  secondIsHorizontal ? thirdPoint[1] : startGlobalPoint[1] + (positive ? BASE_PADDING : -BASE_PADDING)
5598
5631
  )
5599
5632
  );
5600
5633
  newPoints.unshift(
5601
- pointFrom6(
5634
+ pointFrom7(
5602
5635
  startIsHorizontal ? startGlobalPoint[0] + (positive ? BASE_PADDING : -BASE_PADDING) : startGlobalPoint[0],
5603
5636
  !startIsHorizontal ? startGlobalPoint[1] + (positive ? BASE_PADDING : -BASE_PADDING) : startGlobalPoint[1]
5604
5637
  )
@@ -5613,7 +5646,7 @@ var handleEndpointDrag = (arrow, updatedPoints, fixedSegments, startHeading, end
5613
5646
  }
5614
5647
  } else {
5615
5648
  newPoints.unshift(
5616
- pointFrom6(
5649
+ pointFrom7(
5617
5650
  !secondIsHorizontal ? secondPoint[0] : startGlobalPoint[0],
5618
5651
  secondIsHorizontal ? secondPoint[1] : startGlobalPoint[1]
5619
5652
  )
@@ -5630,8 +5663,17 @@ var handleEndpointDrag = (arrow, updatedPoints, fixedSegments, startHeading, end
5630
5663
  newPoints.unshift(startGlobalPoint);
5631
5664
  }
5632
5665
  {
5633
- const secondToLastPoint = globalUpdatedPoints[globalUpdatedPoints.length - (endIsSpecial ? 3 : 2)];
5634
- const thirdToLastPoint = globalUpdatedPoints[globalUpdatedPoints.length - (endIsSpecial ? 4 : 3)];
5666
+ const secondToLastPoint = globalUpdatedPoints.at(
5667
+ globalUpdatedPoints.length - (endIsSpecial ? 3 : 2)
5668
+ );
5669
+ const thirdToLastPoint = globalUpdatedPoints.at(
5670
+ globalUpdatedPoints.length - (endIsSpecial ? 4 : 3)
5671
+ );
5672
+ if (!secondToLastPoint || !thirdToLastPoint) {
5673
+ throw new Error(
5674
+ `Second and third to last points must exist when handling endpoint drag (${endIsSpecial})`
5675
+ );
5676
+ }
5635
5677
  const endIsHorizontal = headingIsHorizontal(endHeading);
5636
5678
  const secondIsHorizontal = headingForPointIsHorizontal(
5637
5679
  thirdToLastPoint,
@@ -5640,13 +5682,13 @@ var handleEndpointDrag = (arrow, updatedPoints, fixedSegments, startHeading, end
5640
5682
  if (hoveredEndElement && endIsHorizontal === secondIsHorizontal) {
5641
5683
  const positive = endIsHorizontal ? compareHeading(endHeading, HEADING_RIGHT) : compareHeading(endHeading, HEADING_DOWN);
5642
5684
  newPoints.push(
5643
- pointFrom6(
5685
+ pointFrom7(
5644
5686
  !secondIsHorizontal ? thirdToLastPoint[0] : endGlobalPoint[0] + (positive ? BASE_PADDING : -BASE_PADDING),
5645
5687
  secondIsHorizontal ? thirdToLastPoint[1] : endGlobalPoint[1] + (positive ? BASE_PADDING : -BASE_PADDING)
5646
5688
  )
5647
5689
  );
5648
5690
  newPoints.push(
5649
- pointFrom6(
5691
+ pointFrom7(
5650
5692
  endIsHorizontal ? endGlobalPoint[0] + (positive ? BASE_PADDING : -BASE_PADDING) : endGlobalPoint[0],
5651
5693
  !endIsHorizontal ? endGlobalPoint[1] + (positive ? BASE_PADDING : -BASE_PADDING) : endGlobalPoint[1]
5652
5694
  )
@@ -5656,7 +5698,7 @@ var handleEndpointDrag = (arrow, updatedPoints, fixedSegments, startHeading, end
5656
5698
  }
5657
5699
  } else {
5658
5700
  newPoints.push(
5659
- pointFrom6(
5701
+ pointFrom7(
5660
5702
  !secondIsHorizontal ? secondToLastPoint[0] : endGlobalPoint[0],
5661
5703
  secondIsHorizontal ? secondToLastPoint[1] : endGlobalPoint[1]
5662
5704
  )
@@ -5675,11 +5717,11 @@ var handleEndpointDrag = (arrow, updatedPoints, fixedSegments, startHeading, end
5675
5717
  end: newPoints[index]
5676
5718
  })).map((segment) => ({
5677
5719
  ...segment,
5678
- start: pointFrom6(
5720
+ start: pointFrom7(
5679
5721
  segment.start[0] - startGlobalPoint[0],
5680
5722
  segment.start[1] - startGlobalPoint[1]
5681
5723
  ),
5682
- end: pointFrom6(
5724
+ end: pointFrom7(
5683
5725
  segment.end[0] - startGlobalPoint[0],
5684
5726
  segment.end[1] - startGlobalPoint[1]
5685
5727
  )
@@ -5741,7 +5783,7 @@ var updateElbowArrowPoints = (arrow, elementsMap, updates, options) => {
5741
5783
  if (startBinding && !startElement && areUpdatedPointsValid || endBinding && !endElement && areUpdatedPointsValid || elementsMap.size === 0 && areUpdatedPointsValid || Object.keys(restOfTheUpdates).length === 0 && (startElement?.id !== startBinding?.elementId || endElement?.id !== endBinding?.elementId)) {
5742
5784
  return normalizeArrowElementUpdate(
5743
5785
  updatedPoints.map(
5744
- (p) => pointFrom6(arrow.x + p[0], arrow.y + p[1])
5786
+ (p) => pointFrom7(arrow.x + p[0], arrow.y + p[1])
5745
5787
  ),
5746
5788
  arrow.fixedSegments,
5747
5789
  arrow.startIsSpecial,
@@ -5773,7 +5815,7 @@ var updateElbowArrowPoints = (arrow, elementsMap, updates, options) => {
5773
5815
  if (elementsMap.size === 0 && areUpdatedPointsValid) {
5774
5816
  return normalizeArrowElementUpdate(
5775
5817
  updatedPoints.map(
5776
- (p) => pointFrom6(arrow.x + p[0], arrow.y + p[1])
5818
+ (p) => pointFrom7(arrow.x + p[0], arrow.y + p[1])
5777
5819
  ),
5778
5820
  arrow.fixedSegments,
5779
5821
  arrow.startIsSpecial,
@@ -5786,7 +5828,7 @@ var updateElbowArrowPoints = (arrow, elementsMap, updates, options) => {
5786
5828
  if (updates.startBinding === arrow.startBinding && updates.endBinding === arrow.endBinding && (updates.points ?? []).every(
5787
5829
  (p, i) => pointsEqual4(
5788
5830
  p,
5789
- arrow.points[i] ?? pointFrom6(Infinity, Infinity)
5831
+ arrow.points[i] ?? pointFrom7(Infinity, Infinity)
5790
5832
  )
5791
5833
  ) && areUpdatedPointsValid) {
5792
5834
  return {};
@@ -6280,13 +6322,13 @@ var calculateGrid = (aabbs, start, startHeading, end, endHeading, common) => {
6280
6322
  var getDonglePosition = (bounds, heading, p) => {
6281
6323
  switch (heading) {
6282
6324
  case HEADING_UP:
6283
- return pointFrom6(p[0], bounds[1]);
6325
+ return pointFrom7(p[0], bounds[1]);
6284
6326
  case HEADING_RIGHT:
6285
- return pointFrom6(bounds[2], p[1]);
6327
+ return pointFrom7(bounds[2], p[1]);
6286
6328
  case HEADING_DOWN:
6287
- return pointFrom6(p[0], bounds[3]);
6329
+ return pointFrom7(p[0], bounds[3]);
6288
6330
  }
6289
- return pointFrom6(bounds[0], p[1]);
6331
+ return pointFrom7(bounds[0], p[1]);
6290
6332
  };
6291
6333
  var estimateSegmentCount = (start, end, startHeading, endHeading) => {
6292
6334
  if (endHeading === HEADING_RIGHT) {
@@ -6454,7 +6496,7 @@ var normalizeArrowElementUpdate = (global2, nextFixedSegments, startIsSpecial, e
6454
6496
  );
6455
6497
  }
6456
6498
  points = points.map(
6457
- ([x, y]) => pointFrom6(clamp2(x, -1e6, 1e6), clamp2(y, -1e6, 1e6))
6499
+ ([x, y]) => pointFrom7(clamp2(x, -1e6, 1e6), clamp2(y, -1e6, 1e6))
6458
6500
  );
6459
6501
  return {
6460
6502
  points,
@@ -7192,7 +7234,7 @@ var bindPointToSnapToElementOutline = (arrow, bindableElement, startOrEnd, eleme
7192
7234
  }
7193
7235
  const aabb = aabbForElement(bindableElement, elementsMap);
7194
7236
  const localP = arrow.points[startOrEnd === "start" ? 0 : arrow.points.length - 1];
7195
- const globalP = pointFrom7(
7237
+ const globalP = pointFrom8(
7196
7238
  arrow.x + localP[0],
7197
7239
  arrow.y + localP[1]
7198
7240
  );
@@ -7200,8 +7242,8 @@ var bindPointToSnapToElementOutline = (arrow, bindableElement, startOrEnd, eleme
7200
7242
  const elbowed = isElbowArrow(arrow);
7201
7243
  const center = getCenterForBounds(aabb);
7202
7244
  const adjacentPointIdx = startOrEnd === "start" ? 1 : arrow.points.length - 2;
7203
- const adjacentPoint = pointRotateRads6(
7204
- pointFrom7(
7245
+ const adjacentPoint = pointRotateRads7(
7246
+ pointFrom8(
7205
7247
  arrow.x + arrow.points[adjacentPointIdx][0],
7206
7248
  arrow.y + arrow.points[adjacentPointIdx][1]
7207
7249
  ),
@@ -7214,7 +7256,7 @@ var bindPointToSnapToElementOutline = (arrow, bindableElement, startOrEnd, eleme
7214
7256
  headingForPointFromElement(bindableElement, aabb, globalP)
7215
7257
  );
7216
7258
  const snapPoint = snapToMid(bindableElement, elementsMap, edgePoint);
7217
- const otherPoint = pointFrom7(
7259
+ const otherPoint = pointFrom8(
7218
7260
  isHorizontal ? center[0] : snapPoint[0],
7219
7261
  !isHorizontal ? center[1] : snapPoint[1]
7220
7262
  );
@@ -7234,6 +7276,28 @@ var bindPointToSnapToElementOutline = (arrow, bindableElement, startOrEnd, eleme
7234
7276
  intersector,
7235
7277
  FIXED_BINDING_DISTANCE
7236
7278
  ).sort(pointDistanceSq)[0];
7279
+ if (!intersection) {
7280
+ const anotherPoint = pointFrom8(
7281
+ !isHorizontal ? center[0] : snapPoint[0],
7282
+ isHorizontal ? center[1] : snapPoint[1]
7283
+ );
7284
+ const anotherIntersector = lineSegment4(
7285
+ anotherPoint,
7286
+ pointFromVector5(
7287
+ vectorScale6(
7288
+ vectorNormalize3(vectorFromPoint6(snapPoint, anotherPoint)),
7289
+ Math.max(bindableElement.width, bindableElement.height) * 2
7290
+ ),
7291
+ anotherPoint
7292
+ )
7293
+ );
7294
+ intersection = intersectElementWithLineSegment(
7295
+ bindableElement,
7296
+ elementsMap,
7297
+ anotherIntersector,
7298
+ FIXED_BINDING_DISTANCE
7299
+ ).sort(pointDistanceSq)[0];
7300
+ }
7237
7301
  } else {
7238
7302
  intersection = intersectElementWithLineSegment(
7239
7303
  bindableElement,
@@ -7261,24 +7325,24 @@ var bindPointToSnapToElementOutline = (arrow, bindableElement, startOrEnd, eleme
7261
7325
  };
7262
7326
  var avoidRectangularCorner = (element, elementsMap, p) => {
7263
7327
  const center = elementCenterPoint(element, elementsMap);
7264
- const nonRotatedPoint = pointRotateRads6(p, center, -element.angle);
7328
+ const nonRotatedPoint = pointRotateRads7(p, center, -element.angle);
7265
7329
  if (nonRotatedPoint[0] < element.x && nonRotatedPoint[1] < element.y) {
7266
7330
  if (nonRotatedPoint[1] - element.y > -FIXED_BINDING_DISTANCE) {
7267
- return pointRotateRads6(
7268
- pointFrom7(element.x - FIXED_BINDING_DISTANCE, element.y),
7331
+ return pointRotateRads7(
7332
+ pointFrom8(element.x - FIXED_BINDING_DISTANCE, element.y),
7269
7333
  center,
7270
7334
  element.angle
7271
7335
  );
7272
7336
  }
7273
- return pointRotateRads6(
7274
- pointFrom7(element.x, element.y - FIXED_BINDING_DISTANCE),
7337
+ return pointRotateRads7(
7338
+ pointFrom8(element.x, element.y - FIXED_BINDING_DISTANCE),
7275
7339
  center,
7276
7340
  element.angle
7277
7341
  );
7278
7342
  } else if (nonRotatedPoint[0] < element.x && nonRotatedPoint[1] > element.y + element.height) {
7279
7343
  if (nonRotatedPoint[0] - element.x > -FIXED_BINDING_DISTANCE) {
7280
- return pointRotateRads6(
7281
- pointFrom7(
7344
+ return pointRotateRads7(
7345
+ pointFrom8(
7282
7346
  element.x,
7283
7347
  element.y + element.height + FIXED_BINDING_DISTANCE
7284
7348
  ),
@@ -7286,15 +7350,15 @@ var avoidRectangularCorner = (element, elementsMap, p) => {
7286
7350
  element.angle
7287
7351
  );
7288
7352
  }
7289
- return pointRotateRads6(
7290
- pointFrom7(element.x - FIXED_BINDING_DISTANCE, element.y + element.height),
7353
+ return pointRotateRads7(
7354
+ pointFrom8(element.x - FIXED_BINDING_DISTANCE, element.y + element.height),
7291
7355
  center,
7292
7356
  element.angle
7293
7357
  );
7294
7358
  } else if (nonRotatedPoint[0] > element.x + element.width && nonRotatedPoint[1] > element.y + element.height) {
7295
7359
  if (nonRotatedPoint[0] - element.x < element.width + FIXED_BINDING_DISTANCE) {
7296
- return pointRotateRads6(
7297
- pointFrom7(
7360
+ return pointRotateRads7(
7361
+ pointFrom8(
7298
7362
  element.x + element.width,
7299
7363
  element.y + element.height + FIXED_BINDING_DISTANCE
7300
7364
  ),
@@ -7302,8 +7366,8 @@ var avoidRectangularCorner = (element, elementsMap, p) => {
7302
7366
  element.angle
7303
7367
  );
7304
7368
  }
7305
- return pointRotateRads6(
7306
- pointFrom7(
7369
+ return pointRotateRads7(
7370
+ pointFrom8(
7307
7371
  element.x + element.width + FIXED_BINDING_DISTANCE,
7308
7372
  element.y + element.height
7309
7373
  ),
@@ -7312,8 +7376,8 @@ var avoidRectangularCorner = (element, elementsMap, p) => {
7312
7376
  );
7313
7377
  } else if (nonRotatedPoint[0] > element.x + element.width && nonRotatedPoint[1] < element.y) {
7314
7378
  if (nonRotatedPoint[0] - element.x < element.width + FIXED_BINDING_DISTANCE) {
7315
- return pointRotateRads6(
7316
- pointFrom7(
7379
+ return pointRotateRads7(
7380
+ pointFrom8(
7317
7381
  element.x + element.width,
7318
7382
  element.y - FIXED_BINDING_DISTANCE
7319
7383
  ),
@@ -7321,8 +7385,8 @@ var avoidRectangularCorner = (element, elementsMap, p) => {
7321
7385
  element.angle
7322
7386
  );
7323
7387
  }
7324
- return pointRotateRads6(
7325
- pointFrom7(element.x + element.width + FIXED_BINDING_DISTANCE, element.y),
7388
+ return pointRotateRads7(
7389
+ pointFrom8(element.x + element.width + FIXED_BINDING_DISTANCE, element.y),
7326
7390
  center,
7327
7391
  element.angle
7328
7392
  );
@@ -7332,62 +7396,62 @@ var avoidRectangularCorner = (element, elementsMap, p) => {
7332
7396
  var snapToMid = (element, elementsMap, p, tolerance = 0.05) => {
7333
7397
  const { x, y, width, height, angle } = element;
7334
7398
  const center = elementCenterPoint(element, elementsMap, -0.1, -0.1);
7335
- const nonRotated = pointRotateRads6(p, center, -angle);
7399
+ const nonRotated = pointRotateRads7(p, center, -angle);
7336
7400
  const verticalThreshold = clamp3(tolerance * height, 5, 80);
7337
7401
  const horizontalThreshold = clamp3(tolerance * width, 5, 80);
7338
7402
  if (nonRotated[0] <= x + width / 2 && nonRotated[1] > center[1] - verticalThreshold && nonRotated[1] < center[1] + verticalThreshold) {
7339
- return pointRotateRads6(
7340
- pointFrom7(x - FIXED_BINDING_DISTANCE, center[1]),
7403
+ return pointRotateRads7(
7404
+ pointFrom8(x - FIXED_BINDING_DISTANCE, center[1]),
7341
7405
  center,
7342
7406
  angle
7343
7407
  );
7344
7408
  } else if (nonRotated[1] <= y + height / 2 && nonRotated[0] > center[0] - horizontalThreshold && nonRotated[0] < center[0] + horizontalThreshold) {
7345
- return pointRotateRads6(
7346
- pointFrom7(center[0], y - FIXED_BINDING_DISTANCE),
7409
+ return pointRotateRads7(
7410
+ pointFrom8(center[0], y - FIXED_BINDING_DISTANCE),
7347
7411
  center,
7348
7412
  angle
7349
7413
  );
7350
7414
  } else if (nonRotated[0] >= x + width / 2 && nonRotated[1] > center[1] - verticalThreshold && nonRotated[1] < center[1] + verticalThreshold) {
7351
- return pointRotateRads6(
7352
- pointFrom7(x + width + FIXED_BINDING_DISTANCE, center[1]),
7415
+ return pointRotateRads7(
7416
+ pointFrom8(x + width + FIXED_BINDING_DISTANCE, center[1]),
7353
7417
  center,
7354
7418
  angle
7355
7419
  );
7356
7420
  } else if (nonRotated[1] >= y + height / 2 && nonRotated[0] > center[0] - horizontalThreshold && nonRotated[0] < center[0] + horizontalThreshold) {
7357
- return pointRotateRads6(
7358
- pointFrom7(center[0], y + height + FIXED_BINDING_DISTANCE),
7421
+ return pointRotateRads7(
7422
+ pointFrom8(center[0], y + height + FIXED_BINDING_DISTANCE),
7359
7423
  center,
7360
7424
  angle
7361
7425
  );
7362
7426
  } else if (element.type === "diamond") {
7363
7427
  const distance3 = FIXED_BINDING_DISTANCE;
7364
- const topLeft = pointFrom7(
7428
+ const topLeft = pointFrom8(
7365
7429
  x + width / 4 - distance3,
7366
7430
  y + height / 4 - distance3
7367
7431
  );
7368
- const topRight = pointFrom7(
7432
+ const topRight = pointFrom8(
7369
7433
  x + 3 * width / 4 + distance3,
7370
7434
  y + height / 4 - distance3
7371
7435
  );
7372
- const bottomLeft = pointFrom7(
7436
+ const bottomLeft = pointFrom8(
7373
7437
  x + width / 4 - distance3,
7374
7438
  y + 3 * height / 4 + distance3
7375
7439
  );
7376
- const bottomRight = pointFrom7(
7440
+ const bottomRight = pointFrom8(
7377
7441
  x + 3 * width / 4 + distance3,
7378
7442
  y + 3 * height / 4 + distance3
7379
7443
  );
7380
7444
  if (pointDistance4(topLeft, nonRotated) < Math.max(horizontalThreshold, verticalThreshold)) {
7381
- return pointRotateRads6(topLeft, center, angle);
7445
+ return pointRotateRads7(topLeft, center, angle);
7382
7446
  }
7383
7447
  if (pointDistance4(topRight, nonRotated) < Math.max(horizontalThreshold, verticalThreshold)) {
7384
- return pointRotateRads6(topRight, center, angle);
7448
+ return pointRotateRads7(topRight, center, angle);
7385
7449
  }
7386
7450
  if (pointDistance4(bottomLeft, nonRotated) < Math.max(horizontalThreshold, verticalThreshold)) {
7387
- return pointRotateRads6(bottomLeft, center, angle);
7451
+ return pointRotateRads7(bottomLeft, center, angle);
7388
7452
  }
7389
7453
  if (pointDistance4(bottomRight, nonRotated) < Math.max(horizontalThreshold, verticalThreshold)) {
7390
- return pointRotateRads6(bottomRight, center, angle);
7454
+ return pointRotateRads7(bottomRight, center, angle);
7391
7455
  }
7392
7456
  }
7393
7457
  return p;
@@ -7407,11 +7471,11 @@ var updateBoundPoint = (linearElement, startOrEnd, binding, bindableElement, ele
7407
7471
  elementsMap
7408
7472
  ).fixedPoint;
7409
7473
  const globalMidPoint = elementCenterPoint(bindableElement, elementsMap);
7410
- const global2 = pointFrom7(
7474
+ const global2 = pointFrom8(
7411
7475
  bindableElement.x + fixedPoint[0] * bindableElement.width,
7412
7476
  bindableElement.y + fixedPoint[1] * bindableElement.height
7413
7477
  );
7414
- const rotatedGlobal = pointRotateRads6(
7478
+ const rotatedGlobal = pointRotateRads7(
7415
7479
  global2,
7416
7480
  globalMidPoint,
7417
7481
  bindableElement.angle
@@ -7501,11 +7565,11 @@ var calculateFixedPointForElbowArrowBinding = (linearElement, hoveredElement, st
7501
7565
  startOrEnd,
7502
7566
  elementsMap
7503
7567
  );
7504
- const globalMidPoint = pointFrom7(
7568
+ const globalMidPoint = pointFrom8(
7505
7569
  bounds[0] + (bounds[2] - bounds[0]) / 2,
7506
7570
  bounds[1] + (bounds[3] - bounds[1]) / 2
7507
7571
  );
7508
- const nonRotatedSnappedGlobalPoint = pointRotateRads6(
7572
+ const nonRotatedSnappedGlobalPoint = pointRotateRads7(
7509
7573
  snappedPoint,
7510
7574
  globalMidPoint,
7511
7575
  -hoveredElement.angle
@@ -7638,7 +7702,7 @@ var newBoundElements = (boundElements, idsToRemove, elementsToAdd = []) => {
7638
7702
  return nextBoundElements;
7639
7703
  };
7640
7704
  var bindingBorderTest = (element, { x, y }, elementsMap, zoom, fullShape) => {
7641
- const p = pointFrom7(x, y);
7705
+ const p = pointFrom8(x, y);
7642
7706
  const threshold = maxBindingGap(element, element.width, element.height, zoom);
7643
7707
  const shouldTestInside2 = (
7644
7708
  // disable fullshape snapping for frame elements so we
@@ -7680,8 +7744,8 @@ var determineFocusDistance = (element, elementsMap, a2, b2) => {
7680
7744
  if (pointsEqual5(a2, b2)) {
7681
7745
  return 0;
7682
7746
  }
7683
- const rotatedA = pointRotateRads6(a2, center, -element.angle);
7684
- const rotatedB = pointRotateRads6(b2, center, -element.angle);
7747
+ const rotatedA = pointRotateRads7(a2, center, -element.angle);
7748
+ const rotatedB = pointRotateRads7(b2, center, -element.angle);
7685
7749
  const sign = Math.sign(
7686
7750
  vectorCross3(
7687
7751
  vectorFromPoint6(rotatedB, a2),
@@ -7700,70 +7764,70 @@ var determineFocusDistance = (element, elementsMap, a2, b2) => {
7700
7764
  );
7701
7765
  const axes = element.type === "diamond" ? [
7702
7766
  lineSegment4(
7703
- pointFrom7(element.x + element.width / 2, element.y),
7704
- pointFrom7(
7767
+ pointFrom8(element.x + element.width / 2, element.y),
7768
+ pointFrom8(
7705
7769
  element.x + element.width / 2,
7706
7770
  element.y + element.height
7707
7771
  )
7708
7772
  ),
7709
7773
  lineSegment4(
7710
- pointFrom7(element.x, element.y + element.height / 2),
7711
- pointFrom7(
7774
+ pointFrom8(element.x, element.y + element.height / 2),
7775
+ pointFrom8(
7712
7776
  element.x + element.width,
7713
7777
  element.y + element.height / 2
7714
7778
  )
7715
7779
  )
7716
7780
  ] : [
7717
7781
  lineSegment4(
7718
- pointFrom7(element.x, element.y),
7719
- pointFrom7(
7782
+ pointFrom8(element.x, element.y),
7783
+ pointFrom8(
7720
7784
  element.x + element.width,
7721
7785
  element.y + element.height
7722
7786
  )
7723
7787
  ),
7724
7788
  lineSegment4(
7725
- pointFrom7(element.x + element.width, element.y),
7726
- pointFrom7(element.x, element.y + element.height)
7789
+ pointFrom8(element.x + element.width, element.y),
7790
+ pointFrom8(element.x, element.y + element.height)
7727
7791
  )
7728
7792
  ];
7729
7793
  const interceptees = element.type === "diamond" ? [
7730
7794
  lineSegment4(
7731
- pointFrom7(
7795
+ pointFrom8(
7732
7796
  element.x + element.width / 2,
7733
7797
  element.y - element.height
7734
7798
  ),
7735
- pointFrom7(
7799
+ pointFrom8(
7736
7800
  element.x + element.width / 2,
7737
7801
  element.y + element.height * 2
7738
7802
  )
7739
7803
  ),
7740
7804
  lineSegment4(
7741
- pointFrom7(
7805
+ pointFrom8(
7742
7806
  element.x - element.width,
7743
7807
  element.y + element.height / 2
7744
7808
  ),
7745
- pointFrom7(
7809
+ pointFrom8(
7746
7810
  element.x + element.width * 2,
7747
7811
  element.y + element.height / 2
7748
7812
  )
7749
7813
  )
7750
7814
  ] : [
7751
7815
  lineSegment4(
7752
- pointFrom7(
7816
+ pointFrom8(
7753
7817
  element.x - element.width,
7754
7818
  element.y - element.height
7755
7819
  ),
7756
- pointFrom7(
7820
+ pointFrom8(
7757
7821
  element.x + element.width * 2,
7758
7822
  element.y + element.height * 2
7759
7823
  )
7760
7824
  ),
7761
7825
  lineSegment4(
7762
- pointFrom7(
7826
+ pointFrom8(
7763
7827
  element.x + element.width * 2,
7764
7828
  element.y - element.height
7765
7829
  ),
7766
- pointFrom7(
7830
+ pointFrom8(
7767
7831
  element.x - element.width,
7768
7832
  element.y + element.height * 2
7769
7833
  )
@@ -7784,30 +7848,30 @@ var determineFocusPoint = (element, elementsMap, focus, adjacentPoint) => {
7784
7848
  return center;
7785
7849
  }
7786
7850
  const candidates = (element.type === "diamond" ? [
7787
- pointFrom7(element.x, element.y + element.height / 2),
7788
- pointFrom7(element.x + element.width / 2, element.y),
7789
- pointFrom7(
7851
+ pointFrom8(element.x, element.y + element.height / 2),
7852
+ pointFrom8(element.x + element.width / 2, element.y),
7853
+ pointFrom8(
7790
7854
  element.x + element.width,
7791
7855
  element.y + element.height / 2
7792
7856
  ),
7793
- pointFrom7(
7857
+ pointFrom8(
7794
7858
  element.x + element.width / 2,
7795
7859
  element.y + element.height
7796
7860
  )
7797
7861
  ] : [
7798
- pointFrom7(element.x, element.y),
7799
- pointFrom7(element.x + element.width, element.y),
7800
- pointFrom7(
7862
+ pointFrom8(element.x, element.y),
7863
+ pointFrom8(element.x + element.width, element.y),
7864
+ pointFrom8(
7801
7865
  element.x + element.width,
7802
7866
  element.y + element.height
7803
7867
  ),
7804
- pointFrom7(element.x, element.y + element.height)
7868
+ pointFrom8(element.x, element.y + element.height)
7805
7869
  ]).map(
7806
7870
  (p) => pointFromVector5(
7807
7871
  vectorScale6(vectorFromPoint6(p, center), Math.abs(focus)),
7808
7872
  center
7809
7873
  )
7810
- ).map((p) => pointRotateRads6(p, center, element.angle));
7874
+ ).map((p) => pointRotateRads7(p, center, element.angle));
7811
7875
  const selected = [
7812
7876
  vectorCross3(
7813
7877
  vectorFromPoint6(adjacentPoint, candidates[0]),
@@ -8052,8 +8116,8 @@ var BindableElement = class {
8052
8116
  };
8053
8117
  var getGlobalFixedPointForBindableElement = (fixedPointRatio, element, elementsMap) => {
8054
8118
  const [fixedX, fixedY] = normalizeFixedPoint(fixedPointRatio);
8055
- return pointRotateRads6(
8056
- pointFrom7(
8119
+ return pointRotateRads7(
8120
+ pointFrom8(
8057
8121
  element.x + element.width * fixedX,
8058
8122
  element.y + element.height * fixedY
8059
8123
  ),
@@ -8068,7 +8132,7 @@ var getGlobalFixedPoints = (arrow, elementsMap) => {
8068
8132
  arrow.startBinding.fixedPoint,
8069
8133
  startElement,
8070
8134
  elementsMap
8071
- ) : pointFrom7(
8135
+ ) : pointFrom8(
8072
8136
  arrow.x + arrow.points[0][0],
8073
8137
  arrow.y + arrow.points[0][1]
8074
8138
  );
@@ -8076,7 +8140,7 @@ var getGlobalFixedPoints = (arrow, elementsMap) => {
8076
8140
  arrow.endBinding.fixedPoint,
8077
8141
  endElement,
8078
8142
  elementsMap
8079
- ) : pointFrom7(
8143
+ ) : pointFrom8(
8080
8144
  arrow.x + arrow.points[arrow.points.length - 1][0],
8081
8145
  arrow.y + arrow.points[arrow.points.length - 1][1]
8082
8146
  );
@@ -8106,7 +8170,7 @@ var getNormalizedPoints = ({
8106
8170
  const offsetY = points[0][1];
8107
8171
  return {
8108
8172
  points: points.map((p) => {
8109
- return pointFrom8(p[0] - offsetX, p[1] - offsetY);
8173
+ return pointFrom9(p[0] - offsetX, p[1] - offsetY);
8110
8174
  }),
8111
8175
  offsetX,
8112
8176
  offsetY
@@ -8127,9 +8191,10 @@ var LinearElementEditor = class _LinearElementEditor {
8127
8191
  segmentMidPointHoveredCoords;
8128
8192
  elbowed;
8129
8193
  customLineAngle;
8130
- constructor(element, elementsMap) {
8194
+ isEditing;
8195
+ constructor(element, elementsMap, isEditing = false) {
8131
8196
  this.elementId = element.id;
8132
- if (!pointsEqual6(element.points[0], pointFrom8(0, 0))) {
8197
+ if (!pointsEqual6(element.points[0], pointFrom9(0, 0))) {
8133
8198
  console.error("Linear element is not normalized", Error().stack);
8134
8199
  mutateElement(
8135
8200
  element,
@@ -8158,6 +8223,7 @@ var LinearElementEditor = class _LinearElementEditor {
8158
8223
  this.segmentMidPointHoveredCoords = null;
8159
8224
  this.elbowed = isElbowArrow(element) && element.elbowed;
8160
8225
  this.customLineAngle = null;
8226
+ this.isEditing = isEditing;
8161
8227
  }
8162
8228
  // ---------------------------------------------------------------------------
8163
8229
  // static methods
@@ -8175,11 +8241,11 @@ var LinearElementEditor = class _LinearElementEditor {
8175
8241
  return null;
8176
8242
  }
8177
8243
  static handleBoxSelection(event, appState, setState, elementsMap) {
8178
- if (!appState.editingLinearElement || !appState.selectionElement) {
8244
+ if (!appState.selectedLinearElement?.isEditing || !appState.selectionElement) {
8179
8245
  return false;
8180
8246
  }
8181
- const { editingLinearElement } = appState;
8182
- const { selectedPointsIndices, elementId } = editingLinearElement;
8247
+ const { selectedLinearElement } = appState;
8248
+ const { selectedPointsIndices, elementId } = selectedLinearElement;
8183
8249
  const element = _LinearElementEditor.getElement(elementId, elementsMap);
8184
8250
  if (!element) {
8185
8251
  return false;
@@ -8201,8 +8267,8 @@ var LinearElementEditor = class _LinearElementEditor {
8201
8267
  return true;
8202
8268
  });
8203
8269
  setState({
8204
- editingLinearElement: {
8205
- ...editingLinearElement,
8270
+ selectedLinearElement: {
8271
+ ...selectedLinearElement,
8206
8272
  selectedPointsIndices: nextSelectedPoints.length ? nextSelectedPoints : null
8207
8273
  }
8208
8274
  });
@@ -8242,7 +8308,7 @@ var LinearElementEditor = class _LinearElementEditor {
8242
8308
  element,
8243
8309
  elementsMap,
8244
8310
  referencePoint,
8245
- pointFrom8(scenePointerX, scenePointerY),
8311
+ pointFrom9(scenePointerX, scenePointerY),
8246
8312
  event[KEYS2.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),
8247
8313
  customLineAngle
8248
8314
  );
@@ -8253,7 +8319,7 @@ var LinearElementEditor = class _LinearElementEditor {
8253
8319
  [
8254
8320
  selectedIndex,
8255
8321
  {
8256
- point: pointFrom8(
8322
+ point: pointFrom9(
8257
8323
  width + referencePoint[0],
8258
8324
  height + referencePoint[1]
8259
8325
  ),
@@ -8283,7 +8349,7 @@ var LinearElementEditor = class _LinearElementEditor {
8283
8349
  scenePointerX - linearElementEditor.pointerOffset.x,
8284
8350
  scenePointerY - linearElementEditor.pointerOffset.y,
8285
8351
  event[KEYS2.CTRL_OR_CMD] ? null : app.getEffectiveGridSize()
8286
- ) : pointFrom8(
8352
+ ) : pointFrom9(
8287
8353
  element.points[pointIndex][0] + deltaX,
8288
8354
  element.points[pointIndex][1] + deltaY
8289
8355
  );
@@ -8356,7 +8422,6 @@ var LinearElementEditor = class _LinearElementEditor {
8356
8422
  };
8357
8423
  return {
8358
8424
  ...app.state,
8359
- editingLinearElement: app.state.editingLinearElement ? newLinearElementEditor : null,
8360
8425
  selectedLinearElement: newLinearElementEditor,
8361
8426
  suggestedBindings
8362
8427
  };
@@ -8440,7 +8505,7 @@ var LinearElementEditor = class _LinearElementEditor {
8440
8505
  }
8441
8506
  static getEditorMidPoints = (element, elementsMap, appState) => {
8442
8507
  const boundText = getBoundTextElement(element, elementsMap);
8443
- if (!isElbowArrow(element) && !appState.editingLinearElement && element.points.length > 2 && !boundText) {
8508
+ if (!isElbowArrow(element) && !appState.selectedLinearElement?.isEditing && element.points.length > 2 && !boundText) {
8444
8509
  return [];
8445
8510
  }
8446
8511
  const points = _LinearElementEditor.getPointsGlobalCoordinates(
@@ -8490,18 +8555,18 @@ var LinearElementEditor = class _LinearElementEditor {
8490
8555
  element,
8491
8556
  elementsMap
8492
8557
  );
8493
- if (points.length >= 3 && !appState.editingLinearElement && !isElbowArrow(element)) {
8558
+ if (points.length >= 3 && !appState.selectedLinearElement?.isEditing && !isElbowArrow(element)) {
8494
8559
  return null;
8495
8560
  }
8496
8561
  const threshold = (_LinearElementEditor.POINT_HANDLE_SIZE + 1) / appState.zoom.value;
8497
8562
  const existingSegmentMidpointHitCoords = linearElementEditor.segmentMidPointHoveredCoords;
8498
8563
  if (existingSegmentMidpointHitCoords) {
8499
8564
  const distance3 = pointDistance5(
8500
- pointFrom8(
8565
+ pointFrom9(
8501
8566
  existingSegmentMidpointHitCoords[0],
8502
8567
  existingSegmentMidpointHitCoords[1]
8503
8568
  ),
8504
- pointFrom8(scenePointer.x, scenePointer.y)
8569
+ pointFrom9(scenePointer.x, scenePointer.y)
8505
8570
  );
8506
8571
  if (distance3 <= threshold) {
8507
8572
  return existingSegmentMidpointHitCoords;
@@ -8517,7 +8582,7 @@ var LinearElementEditor = class _LinearElementEditor {
8517
8582
  if (midPoints[index] !== null) {
8518
8583
  const distance3 = pointDistance5(
8519
8584
  midPoints[index],
8520
- pointFrom8(scenePointer.x, scenePointer.y)
8585
+ pointFrom9(scenePointer.x, scenePointer.y)
8521
8586
  );
8522
8587
  if (distance3 <= threshold) {
8523
8588
  return midPoints[index];
@@ -8556,7 +8621,7 @@ var LinearElementEditor = class _LinearElementEditor {
8556
8621
  "Invalid segment index while calculating elbow arrow mid point"
8557
8622
  );
8558
8623
  const p = pointCenter2(element.points[index - 1], element.points[index]);
8559
- return pointFrom8(element.x + p[0], element.y + p[1]);
8624
+ return pointFrom9(element.x + p[0], element.y + p[1]);
8560
8625
  }
8561
8626
  const [lines, curves] = deconstructLinearOrFreeDrawElement2(element);
8562
8627
  invariant6(
@@ -8630,7 +8695,7 @@ var LinearElementEditor = class _LinearElementEditor {
8630
8695
  segmentMidpoint,
8631
8696
  elementsMap
8632
8697
  );
8633
- } else if (event.altKey && appState.editingLinearElement) {
8698
+ } else if (event.altKey && appState.selectedLinearElement?.isEditing) {
8634
8699
  if (linearElementEditor.lastUncommittedPoint == null) {
8635
8700
  scene.mutateElement(element, {
8636
8701
  points: [
@@ -8696,12 +8761,12 @@ var LinearElementEditor = class _LinearElementEditor {
8696
8761
  const [x1, y1, x2, y2] = getElementAbsoluteCoords2(element, elementsMap);
8697
8762
  const cx = (x1 + x2) / 2;
8698
8763
  const cy = (y1 + y2) / 2;
8699
- const targetPoint = clickedPointIndex > -1 && pointRotateRads7(
8700
- pointFrom8(
8764
+ const targetPoint = clickedPointIndex > -1 && pointRotateRads8(
8765
+ pointFrom9(
8701
8766
  element.x + element.points[clickedPointIndex][0],
8702
8767
  element.y + element.points[clickedPointIndex][1]
8703
8768
  ),
8704
- pointFrom8(cx, cy),
8769
+ pointFrom9(cx, cy),
8705
8770
  element.angle
8706
8771
  );
8707
8772
  const nextSelectedPointsIndices = clickedPointIndex > -1 || event.shiftKey ? event.shiftKey || linearElementEditor.selectedPointsIndices?.includes(clickedPointIndex) ? normalizeSelectedPoints([
@@ -8740,14 +8805,14 @@ var LinearElementEditor = class _LinearElementEditor {
8740
8805
  }
8741
8806
  static handlePointerMove(event, scenePointerX, scenePointerY, app) {
8742
8807
  const appState = app.state;
8743
- if (!appState.editingLinearElement) {
8808
+ if (!appState.selectedLinearElement?.isEditing) {
8744
8809
  return null;
8745
8810
  }
8746
- const { elementId, lastUncommittedPoint } = appState.editingLinearElement;
8811
+ const { elementId, lastUncommittedPoint } = appState.selectedLinearElement;
8747
8812
  const elementsMap = app.scene.getNonDeletedElementsMap();
8748
8813
  const element = _LinearElementEditor.getElement(elementId, elementsMap);
8749
8814
  if (!element) {
8750
- return appState.editingLinearElement;
8815
+ return appState.selectedLinearElement;
8751
8816
  }
8752
8817
  const { points } = element;
8753
8818
  const lastPoint = points[points.length - 1];
@@ -8755,10 +8820,10 @@ var LinearElementEditor = class _LinearElementEditor {
8755
8820
  if (lastPoint === lastUncommittedPoint) {
8756
8821
  _LinearElementEditor.deletePoints(element, app, [points.length - 1]);
8757
8822
  }
8758
- return {
8759
- ...appState.editingLinearElement,
8823
+ return appState.selectedLinearElement?.lastUncommittedPoint ? {
8824
+ ...appState.selectedLinearElement,
8760
8825
  lastUncommittedPoint: null
8761
- };
8826
+ } : appState.selectedLinearElement;
8762
8827
  }
8763
8828
  let newPoint;
8764
8829
  if (shouldRotateWithDiscreteAngle(event) && points.length >= 2) {
@@ -8767,10 +8832,10 @@ var LinearElementEditor = class _LinearElementEditor {
8767
8832
  element,
8768
8833
  elementsMap,
8769
8834
  lastCommittedPoint,
8770
- pointFrom8(scenePointerX, scenePointerY),
8835
+ pointFrom9(scenePointerX, scenePointerY),
8771
8836
  event[KEYS2.CTRL_OR_CMD] ? null : app.getEffectiveGridSize()
8772
8837
  );
8773
- newPoint = pointFrom8(
8838
+ newPoint = pointFrom9(
8774
8839
  width + lastCommittedPoint[0],
8775
8840
  height + lastCommittedPoint[1]
8776
8841
  );
@@ -8778,8 +8843,8 @@ var LinearElementEditor = class _LinearElementEditor {
8778
8843
  newPoint = _LinearElementEditor.createPointAt(
8779
8844
  element,
8780
8845
  elementsMap,
8781
- scenePointerX - appState.editingLinearElement.pointerOffset.x,
8782
- scenePointerY - appState.editingLinearElement.pointerOffset.y,
8846
+ scenePointerX - appState.selectedLinearElement.pointerOffset.x,
8847
+ scenePointerY - appState.selectedLinearElement.pointerOffset.y,
8783
8848
  event[KEYS2.CTRL_OR_CMD] || isElbowArrow(element) ? null : app.getEffectiveGridSize()
8784
8849
  );
8785
8850
  }
@@ -8800,7 +8865,7 @@ var LinearElementEditor = class _LinearElementEditor {
8800
8865
  _LinearElementEditor.addPoints(element, app.scene, [newPoint]);
8801
8866
  }
8802
8867
  return {
8803
- ...appState.editingLinearElement,
8868
+ ...appState.selectedLinearElement,
8804
8869
  lastUncommittedPoint: element.points[element.points.length - 1]
8805
8870
  };
8806
8871
  }
@@ -8810,9 +8875,9 @@ var LinearElementEditor = class _LinearElementEditor {
8810
8875
  const cx = (x1 + x2) / 2;
8811
8876
  const cy = (y1 + y2) / 2;
8812
8877
  const { x, y } = element;
8813
- return pointRotateRads7(
8814
- pointFrom8(x + p[0], y + p[1]),
8815
- pointFrom8(cx, cy),
8878
+ return pointRotateRads8(
8879
+ pointFrom9(x + p[0], y + p[1]),
8880
+ pointFrom9(cx, cy),
8816
8881
  element.angle
8817
8882
  );
8818
8883
  }
@@ -8823,9 +8888,9 @@ var LinearElementEditor = class _LinearElementEditor {
8823
8888
  const cy = (y1 + y2) / 2;
8824
8889
  return element.points.map((p) => {
8825
8890
  const { x, y } = element;
8826
- return pointRotateRads7(
8827
- pointFrom8(x + p[0], y + p[1]),
8828
- pointFrom8(cx, cy),
8891
+ return pointRotateRads8(
8892
+ pointFrom9(x + p[0], y + p[1]),
8893
+ pointFrom9(cx, cy),
8829
8894
  element.angle
8830
8895
  );
8831
8896
  });
@@ -8837,15 +8902,15 @@ var LinearElementEditor = class _LinearElementEditor {
8837
8902
  const cy = (y1 + y2) / 2;
8838
8903
  const p = element.points[index];
8839
8904
  const { x, y } = element;
8840
- return p ? pointRotateRads7(
8841
- pointFrom8(x + p[0], y + p[1]),
8842
- pointFrom8(cx, cy),
8905
+ return p ? pointRotateRads8(
8906
+ pointFrom9(x + p[0], y + p[1]),
8907
+ pointFrom9(cx, cy),
8843
8908
  element.angle
8844
- ) : pointRotateRads7(pointFrom8(x, y), pointFrom8(cx, cy), element.angle);
8909
+ ) : pointRotateRads8(pointFrom9(x, y), pointFrom9(cx, cy), element.angle);
8845
8910
  }
8846
8911
  static pointFromAbsoluteCoords(element, absoluteCoords, elementsMap) {
8847
8912
  if (isElbowArrow(element)) {
8848
- return pointFrom8(
8913
+ return pointFrom9(
8849
8914
  absoluteCoords[0] - element.x,
8850
8915
  absoluteCoords[1] - element.y
8851
8916
  );
@@ -8853,12 +8918,12 @@ var LinearElementEditor = class _LinearElementEditor {
8853
8918
  const [x1, y1, x2, y2] = getElementAbsoluteCoords2(element, elementsMap);
8854
8919
  const cx = (x1 + x2) / 2;
8855
8920
  const cy = (y1 + y2) / 2;
8856
- const [x, y] = pointRotateRads7(
8857
- pointFrom8(absoluteCoords[0], absoluteCoords[1]),
8858
- pointFrom8(cx, cy),
8921
+ const [x, y] = pointRotateRads8(
8922
+ pointFrom9(absoluteCoords[0], absoluteCoords[1]),
8923
+ pointFrom9(cx, cy),
8859
8924
  -element.angle
8860
8925
  );
8861
- return pointFrom8(x - element.x, y - element.y);
8926
+ return pointFrom9(x - element.x, y - element.y);
8862
8927
  }
8863
8928
  static getPointIndexUnderCursor(element, elementsMap, zoom, x, y) {
8864
8929
  const pointHandles = _LinearElementEditor.getPointsGlobalCoordinates(
@@ -8868,7 +8933,7 @@ var LinearElementEditor = class _LinearElementEditor {
8868
8933
  let idx = pointHandles.length;
8869
8934
  while (--idx > -1) {
8870
8935
  const p = pointHandles[idx];
8871
- if (pointDistance5(pointFrom8(x, y), pointFrom8(p[0], p[1])) * zoom.value < // +1px to account for outline stroke
8936
+ if (pointDistance5(pointFrom9(x, y), pointFrom9(p[0], p[1])) * zoom.value < // +1px to account for outline stroke
8872
8937
  _LinearElementEditor.POINT_HANDLE_SIZE + 1) {
8873
8938
  return idx;
8874
8939
  }
@@ -8880,12 +8945,12 @@ var LinearElementEditor = class _LinearElementEditor {
8880
8945
  const [x1, y1, x2, y2] = getElementAbsoluteCoords2(element, elementsMap);
8881
8946
  const cx = (x1 + x2) / 2;
8882
8947
  const cy = (y1 + y2) / 2;
8883
- const [rotatedX, rotatedY] = pointRotateRads7(
8884
- pointFrom8(pointerOnGrid[0], pointerOnGrid[1]),
8885
- pointFrom8(cx, cy),
8948
+ const [rotatedX, rotatedY] = pointRotateRads8(
8949
+ pointFrom9(pointerOnGrid[0], pointerOnGrid[1]),
8950
+ pointFrom9(cx, cy),
8886
8951
  -element.angle
8887
8952
  );
8888
- return pointFrom8(rotatedX - element.x, rotatedY - element.y);
8953
+ return pointFrom9(rotatedX - element.x, rotatedY - element.y);
8889
8954
  }
8890
8955
  /**
8891
8956
  * Normalizes line points so that the start point is at [0,0]. This is
@@ -8906,11 +8971,11 @@ var LinearElementEditor = class _LinearElementEditor {
8906
8971
  // ---------------------------------------------------------------------------
8907
8972
  static duplicateSelectedPoints(appState, scene) {
8908
8973
  invariant6(
8909
- appState.editingLinearElement,
8974
+ appState.selectedLinearElement?.isEditing,
8910
8975
  "Not currently editing a linear element"
8911
8976
  );
8912
8977
  const elementsMap = scene.getNonDeletedElementsMap();
8913
- const { selectedPointsIndices, elementId } = appState.editingLinearElement;
8978
+ const { selectedPointsIndices, elementId } = appState.selectedLinearElement;
8914
8979
  const element = _LinearElementEditor.getElement(elementId, elementsMap);
8915
8980
  invariant6(
8916
8981
  element,
@@ -8934,7 +8999,7 @@ var LinearElementEditor = class _LinearElementEditor {
8934
8999
  pointAddedToEnd = true;
8935
9000
  }
8936
9001
  acc.push(
8937
- nextPoint ? pointFrom8((p[0] + nextPoint[0]) / 2, (p[1] + nextPoint[1]) / 2) : pointFrom8(p[0], p[1])
9002
+ nextPoint ? pointFrom9((p[0] + nextPoint[0]) / 2, (p[1] + nextPoint[1]) / 2) : pointFrom9(p[0], p[1])
8938
9003
  );
8939
9004
  nextSelectedIndices.push(indexCursor + 1);
8940
9005
  ++indexCursor;
@@ -8950,27 +9015,27 @@ var LinearElementEditor = class _LinearElementEditor {
8950
9015
  /* @__PURE__ */ new Map([
8951
9016
  [
8952
9017
  element.points.length - 1,
8953
- { point: pointFrom8(lastPoint[0] + 30, lastPoint[1] + 30) }
9018
+ { point: pointFrom9(lastPoint[0] + 30, lastPoint[1] + 30) }
8954
9019
  ]
8955
9020
  ])
8956
9021
  );
8957
9022
  }
8958
9023
  return {
8959
9024
  ...appState,
8960
- editingLinearElement: {
8961
- ...appState.editingLinearElement,
9025
+ selectedLinearElement: {
9026
+ ...appState.selectedLinearElement,
8962
9027
  selectedPointsIndices: nextSelectedIndices
8963
9028
  }
8964
9029
  };
8965
9030
  }
8966
9031
  static deletePoints(element, app, pointIndices) {
8967
- const isUncommittedPoint = app.state.editingLinearElement?.lastUncommittedPoint === element.points[element.points.length - 1];
9032
+ const isUncommittedPoint = app.state.selectedLinearElement?.isEditing && app.state.selectedLinearElement?.lastUncommittedPoint === element.points[element.points.length - 1];
8968
9033
  const nextPoints = element.points.filter((_, idx) => {
8969
9034
  return !pointIndices.includes(idx);
8970
9035
  });
8971
9036
  const isPolygon = isLineElement(element) && element.polygon;
8972
9037
  if (isPolygon && (isUncommittedPoint || pointIndices.includes(0) || pointIndices.includes(element.points.length - 1))) {
8973
- nextPoints[0] = pointFrom8(
9038
+ nextPoints[0] = pointFrom9(
8974
9039
  nextPoints[nextPoints.length - 1][0],
8975
9040
  nextPoints[nextPoints.length - 1][1]
8976
9041
  );
@@ -8991,7 +9056,7 @@ var LinearElementEditor = class _LinearElementEditor {
8991
9056
  static addPoints(element, scene, addedPoints) {
8992
9057
  const nextPoints = [...element.points, ...addedPoints];
8993
9058
  if (isLineElement(element) && element.polygon) {
8994
- nextPoints[0] = pointFrom8(
9059
+ nextPoints[0] = pointFrom9(
8995
9060
  nextPoints[nextPoints.length - 1][0],
8996
9061
  nextPoints[nextPoints.length - 1][1]
8997
9062
  );
@@ -9016,7 +9081,7 @@ var LinearElementEditor = class _LinearElementEditor {
9016
9081
  const lastPointUpdate = pointUpdates.get(points.length - 1);
9017
9082
  if (firstPointUpdate) {
9018
9083
  pointUpdates.set(points.length - 1, {
9019
- point: pointFrom8(
9084
+ point: pointFrom9(
9020
9085
  firstPointUpdate.point[0],
9021
9086
  firstPointUpdate.point[1]
9022
9087
  ),
@@ -9024,19 +9089,19 @@ var LinearElementEditor = class _LinearElementEditor {
9024
9089
  });
9025
9090
  } else if (lastPointUpdate) {
9026
9091
  pointUpdates.set(0, {
9027
- point: pointFrom8(lastPointUpdate.point[0], lastPointUpdate.point[1]),
9092
+ point: pointFrom9(lastPointUpdate.point[0], lastPointUpdate.point[1]),
9028
9093
  isDragging: lastPointUpdate.isDragging
9029
9094
  });
9030
9095
  }
9031
9096
  }
9032
- const updatedOriginPoint = pointUpdates.get(0)?.point ?? pointFrom8(0, 0);
9097
+ const updatedOriginPoint = pointUpdates.get(0)?.point ?? pointFrom9(0, 0);
9033
9098
  const [offsetX, offsetY] = updatedOriginPoint;
9034
9099
  const nextPoints = isElbowArrow(element) ? [
9035
9100
  pointUpdates.get(0)?.point ?? points[0],
9036
9101
  pointUpdates.get(points.length - 1)?.point ?? points[points.length - 1]
9037
9102
  ] : points.map((p, idx) => {
9038
9103
  const current = pointUpdates.get(idx)?.point ?? p;
9039
- return pointFrom8(
9104
+ return pointFrom9(
9040
9105
  current[0] - offsetX,
9041
9106
  current[1] - offsetY
9042
9107
  );
@@ -9070,10 +9135,10 @@ var LinearElementEditor = class _LinearElementEditor {
9070
9135
  }
9071
9136
  const origin = linearElementEditor.pointerDownState.origin;
9072
9137
  const dist = pointDistance5(
9073
- pointFrom8(origin.x, origin.y),
9074
- pointFrom8(pointerCoords.x, pointerCoords.y)
9138
+ pointFrom9(origin.x, origin.y),
9139
+ pointFrom9(pointerCoords.x, pointerCoords.y)
9075
9140
  );
9076
- if (!appState.editingLinearElement && dist < DRAGGING_THRESHOLD / appState.zoom.value) {
9141
+ if (!appState.selectedLinearElement?.isEditing && dist < DRAGGING_THRESHOLD / appState.zoom.value) {
9077
9142
  return false;
9078
9143
  }
9079
9144
  return true;
@@ -9139,9 +9204,9 @@ var LinearElementEditor = class _LinearElementEditor {
9139
9204
  const prevCenterY = (prevCoords[1] + prevCoords[3]) / 2;
9140
9205
  const dX = prevCenterX - nextCenterX;
9141
9206
  const dY = prevCenterY - nextCenterY;
9142
- const rotatedOffset = pointRotateRads7(
9143
- pointFrom8(offsetX, offsetY),
9144
- pointFrom8(dX, dY),
9207
+ const rotatedOffset = pointRotateRads8(
9208
+ pointFrom9(offsetX, offsetY),
9209
+ pointFrom9(dX, dY),
9145
9210
  element.angle
9146
9211
  );
9147
9212
  scene.mutateElement(element, {
@@ -9176,9 +9241,9 @@ var LinearElementEditor = class _LinearElementEditor {
9176
9241
  gridY,
9177
9242
  customLineAngle
9178
9243
  );
9179
- return pointRotateRads7(
9180
- pointFrom8(width, height),
9181
- pointFrom8(0, 0),
9244
+ return pointRotateRads8(
9245
+ pointFrom9(width, height),
9246
+ pointFrom9(0, 0),
9182
9247
  -element.angle
9183
9248
  );
9184
9249
  }
@@ -9223,34 +9288,34 @@ var LinearElementEditor = class _LinearElementEditor {
9223
9288
  );
9224
9289
  const boundTextX2 = boundTextX1 + boundTextElement.width;
9225
9290
  const boundTextY2 = boundTextY1 + boundTextElement.height;
9226
- const centerPoint = pointFrom8(cx, cy);
9227
- const topLeftRotatedPoint = pointRotateRads7(
9228
- pointFrom8(x1, y1),
9291
+ const centerPoint = pointFrom9(cx, cy);
9292
+ const topLeftRotatedPoint = pointRotateRads8(
9293
+ pointFrom9(x1, y1),
9229
9294
  centerPoint,
9230
9295
  element.angle
9231
9296
  );
9232
- const topRightRotatedPoint = pointRotateRads7(
9233
- pointFrom8(x2, y1),
9297
+ const topRightRotatedPoint = pointRotateRads8(
9298
+ pointFrom9(x2, y1),
9234
9299
  centerPoint,
9235
9300
  element.angle
9236
9301
  );
9237
- const counterRotateBoundTextTopLeft = pointRotateRads7(
9238
- pointFrom8(boundTextX1, boundTextY1),
9302
+ const counterRotateBoundTextTopLeft = pointRotateRads8(
9303
+ pointFrom9(boundTextX1, boundTextY1),
9239
9304
  centerPoint,
9240
9305
  -element.angle
9241
9306
  );
9242
- const counterRotateBoundTextTopRight = pointRotateRads7(
9243
- pointFrom8(boundTextX2, boundTextY1),
9307
+ const counterRotateBoundTextTopRight = pointRotateRads8(
9308
+ pointFrom9(boundTextX2, boundTextY1),
9244
9309
  centerPoint,
9245
9310
  -element.angle
9246
9311
  );
9247
- const counterRotateBoundTextBottomLeft = pointRotateRads7(
9248
- pointFrom8(boundTextX1, boundTextY2),
9312
+ const counterRotateBoundTextBottomLeft = pointRotateRads8(
9313
+ pointFrom9(boundTextX1, boundTextY2),
9249
9314
  centerPoint,
9250
9315
  -element.angle
9251
9316
  );
9252
- const counterRotateBoundTextBottomRight = pointRotateRads7(
9253
- pointFrom8(boundTextX2, boundTextY2),
9317
+ const counterRotateBoundTextBottomRight = pointRotateRads8(
9318
+ pointFrom9(boundTextX2, boundTextY2),
9254
9319
  centerPoint,
9255
9320
  -element.angle
9256
9321
  );
@@ -9366,11 +9431,11 @@ var LinearElementEditor = class _LinearElementEditor {
9366
9431
  );
9367
9432
  fixedSegments[index] = {
9368
9433
  index,
9369
- start: pointFrom8(
9434
+ start: pointFrom9(
9370
9435
  !isHorizontal ? x - element.x : element.points[index - 1][0],
9371
9436
  isHorizontal ? y - element.y : element.points[index - 1][1]
9372
9437
  ),
9373
- end: pointFrom8(
9438
+ end: pointFrom9(
9374
9439
  !isHorizontal ? x - element.x : element.points[index][0],
9375
9440
  isHorizontal ? y - element.y : element.points[index][1]
9376
9441
  )
@@ -9382,7 +9447,7 @@ var LinearElementEditor = class _LinearElementEditor {
9382
9447
  scene.mutateElement(element, {
9383
9448
  fixedSegments: nextFixedSegments
9384
9449
  });
9385
- const point = pointFrom8(
9450
+ const point = pointFrom9(
9386
9451
  element.x + (element.fixedSegments[offset].start[0] + element.fixedSegments[offset].end[0]) / 2,
9387
9452
  element.y + (element.fixedSegments[offset].start[1] + element.fixedSegments[offset].end[1]) / 2
9388
9453
  );
@@ -9420,7 +9485,7 @@ var normalizeSelectedPoints = (points) => {
9420
9485
  // src/frame.ts
9421
9486
  init_define_import_meta_env();
9422
9487
  import { arrayToMap as arrayToMap5 } from "@excalidraw/common";
9423
- import { isPointWithinBounds as isPointWithinBounds2, pointFrom as pointFrom10 } from "@excalidraw/math";
9488
+ import { isPointWithinBounds as isPointWithinBounds2, pointFrom as pointFrom11 } from "@excalidraw/math";
9424
9489
 
9425
9490
  // ../utils/src/bbox.ts
9426
9491
  init_define_import_meta_env();
@@ -9471,24 +9536,24 @@ import {
9471
9536
  } from "@excalidraw/element";
9472
9537
  import {
9473
9538
  rangeIncludesValue,
9474
- pointFrom as pointFrom9,
9475
- pointRotateRads as pointRotateRads8,
9539
+ pointFrom as pointFrom10,
9540
+ pointRotateRads as pointRotateRads9,
9476
9541
  rangeInclusive
9477
9542
  } from "@excalidraw/math";
9478
9543
  var getNonLinearElementRelativePoints = (element) => {
9479
9544
  if (element.type === "diamond") {
9480
9545
  return [
9481
- pointFrom9(element.width / 2, 0),
9482
- pointFrom9(element.width, element.height / 2),
9483
- pointFrom9(element.width / 2, element.height),
9484
- pointFrom9(0, element.height / 2)
9546
+ pointFrom10(element.width / 2, 0),
9547
+ pointFrom10(element.width, element.height / 2),
9548
+ pointFrom10(element.width / 2, element.height),
9549
+ pointFrom10(0, element.height / 2)
9485
9550
  ];
9486
9551
  }
9487
9552
  return [
9488
- pointFrom9(0, 0),
9489
- pointFrom9(0 + element.width, 0),
9490
- pointFrom9(0 + element.width, element.height),
9491
- pointFrom9(0, element.height)
9553
+ pointFrom10(0, 0),
9554
+ pointFrom10(0 + element.width, 0),
9555
+ pointFrom10(0 + element.width, element.height),
9556
+ pointFrom10(0, element.height)
9492
9557
  ];
9493
9558
  };
9494
9559
  var getElementRelativePoints = (element) => {
@@ -9522,9 +9587,9 @@ var getMinMaxPoints = (points) => {
9522
9587
  var getRotatedBBox = (element) => {
9523
9588
  const points = getElementRelativePoints(element);
9524
9589
  const { cx, cy } = getMinMaxPoints(points);
9525
- const centerPoint = pointFrom9(cx, cy);
9590
+ const centerPoint = pointFrom10(cx, cy);
9526
9591
  const rotatedPoints = points.map(
9527
- (p) => pointRotateRads8(p, centerPoint, element.angle)
9592
+ (p) => pointRotateRads9(p, centerPoint, element.angle)
9528
9593
  );
9529
9594
  const { minX, minY, maxX, maxY } = getMinMaxPoints(rotatedPoints);
9530
9595
  return [
@@ -9826,6 +9891,55 @@ var getNewGroupIdsForDuplication = (groupIds, editingGroupId, mapper) => {
9826
9891
  }
9827
9892
  return copy;
9828
9893
  };
9894
+ var getSelectedElementsByGroup = (selectedElements, elementsMap, appState) => {
9895
+ const selectedGroupIds = getSelectedGroupIds(appState);
9896
+ const unboundElements = selectedElements.filter(
9897
+ (element) => !isBoundToContainer(element)
9898
+ );
9899
+ const groups = /* @__PURE__ */ new Map();
9900
+ const elements = /* @__PURE__ */ new Map();
9901
+ const addToElementsMap = (element) => {
9902
+ const currentElementMembers = elements.get(element.id) || [];
9903
+ const boundTextElement = getBoundTextElement(element, elementsMap);
9904
+ if (boundTextElement) {
9905
+ currentElementMembers.push(boundTextElement);
9906
+ }
9907
+ elements.set(element.id, [...currentElementMembers, element]);
9908
+ };
9909
+ const addToGroupsMap = (element, groupId) => {
9910
+ const currentGroupMembers = groups.get(groupId) || [];
9911
+ const boundTextElement = getBoundTextElement(element, elementsMap);
9912
+ if (boundTextElement) {
9913
+ currentGroupMembers.push(boundTextElement);
9914
+ }
9915
+ groups.set(groupId, [...currentGroupMembers, element]);
9916
+ };
9917
+ const handleSingleSelectedGroupCase = (element, selectedGroupId) => {
9918
+ const indexOfSelectedGroupId = element.groupIds.indexOf(selectedGroupId, 0);
9919
+ const nestedGroupCount = element.groupIds.slice(
9920
+ 0,
9921
+ indexOfSelectedGroupId
9922
+ ).length;
9923
+ return nestedGroupCount > 0 ? addToGroupsMap(element, element.groupIds[indexOfSelectedGroupId - 1]) : addToElementsMap(element);
9924
+ };
9925
+ const isAllInSameGroup = selectedElements.every(
9926
+ (element) => isSelectedViaGroup(appState, element)
9927
+ );
9928
+ unboundElements.forEach((element) => {
9929
+ const selectedGroupId = getSelectedGroupIdForElement(
9930
+ element,
9931
+ appState.selectedGroupIds
9932
+ );
9933
+ if (!selectedGroupId) {
9934
+ addToElementsMap(element);
9935
+ } else if (selectedGroupIds.length === 1 && isAllInSameGroup) {
9936
+ handleSingleSelectedGroupCase(element, selectedGroupId);
9937
+ } else {
9938
+ addToGroupsMap(element, selectedGroupId);
9939
+ }
9940
+ });
9941
+ return Array.from(groups.values()).concat(Array.from(elements.values()));
9942
+ };
9829
9943
 
9830
9944
  // src/selection.ts
9831
9945
  var excludeElementsInFramesFromSelection = (selectedElements) => {
@@ -10039,9 +10153,9 @@ var elementOverlapsWithFrame = (element, frame, elementsMap) => {
10039
10153
  var isCursorInFrame = (cursorCoords, frame, elementsMap) => {
10040
10154
  const [fx1, fy1, fx2, fy2] = getElementAbsoluteCoords2(frame, elementsMap);
10041
10155
  return isPointWithinBounds2(
10042
- pointFrom10(fx1, fy1),
10043
- pointFrom10(cursorCoords.x, cursorCoords.y),
10044
- pointFrom10(fx2, fy2)
10156
+ pointFrom11(fx1, fy1),
10157
+ pointFrom11(cursorCoords.x, cursorCoords.y),
10158
+ pointFrom11(fx2, fy2)
10045
10159
  );
10046
10160
  };
10047
10161
  var groupsAreAtLeastIntersectingTheFrame = (elements, groupIds, frame) => {
@@ -10513,6 +10627,11 @@ var getCanvasPadding = (element) => {
10513
10627
  return element.strokeWidth * 12;
10514
10628
  case "text":
10515
10629
  return element.fontSize / 2;
10630
+ case "arrow":
10631
+ if (element.endArrowhead || element.endArrowhead) {
10632
+ return 40;
10633
+ }
10634
+ return 20;
10516
10635
  default:
10517
10636
  return 20;
10518
10637
  }
@@ -11100,6 +11219,58 @@ function getFreeDrawPath2D(element) {
11100
11219
  return pathsCache.get(element);
11101
11220
  }
11102
11221
  function getFreeDrawSvgPath(element) {
11222
+ return getSvgPathFromStroke(getFreedrawOutlinePoints(element));
11223
+ }
11224
+ function getFreedrawOutlineAsSegments(element, points, elementsMap) {
11225
+ const bounds = getElementBounds(
11226
+ {
11227
+ ...element,
11228
+ angle: 0
11229
+ },
11230
+ elementsMap
11231
+ );
11232
+ const center = pointFrom12(
11233
+ (bounds[0] + bounds[2]) / 2,
11234
+ (bounds[1] + bounds[3]) / 2
11235
+ );
11236
+ invariant7(points.length >= 2, "Freepath outline must have at least 2 points");
11237
+ return points.slice(2).reduce(
11238
+ (acc, curr) => {
11239
+ acc.push(
11240
+ lineSegment5(
11241
+ acc[acc.length - 1][1],
11242
+ pointRotateRads10(
11243
+ pointFrom12(curr[0] + element.x, curr[1] + element.y),
11244
+ center,
11245
+ element.angle
11246
+ )
11247
+ )
11248
+ );
11249
+ return acc;
11250
+ },
11251
+ [
11252
+ lineSegment5(
11253
+ pointRotateRads10(
11254
+ pointFrom12(
11255
+ points[0][0] + element.x,
11256
+ points[0][1] + element.y
11257
+ ),
11258
+ center,
11259
+ element.angle
11260
+ ),
11261
+ pointRotateRads10(
11262
+ pointFrom12(
11263
+ points[1][0] + element.x,
11264
+ points[1][1] + element.y
11265
+ ),
11266
+ center,
11267
+ element.angle
11268
+ )
11269
+ )
11270
+ ]
11271
+ );
11272
+ }
11273
+ function getFreedrawOutlinePoints(element) {
11103
11274
  const inputPoints = element.simulatePressure ? element.points : element.points.length ? element.points.map(([x, y], i) => [x, y, element.pressures[i]]) : [[0, 0, 0.5]];
11104
11275
  const options = {
11105
11276
  simulatePressure: element.simulatePressure,
@@ -11112,7 +11283,7 @@ function getFreeDrawSvgPath(element) {
11112
11283
  last: !!element.lastCommittedPoint
11113
11284
  // LastCommittedPoint is added on pointerup
11114
11285
  };
11115
- return getSvgPathFromStroke(ae(inputPoints, options));
11286
+ return ae(inputPoints, options);
11116
11287
  }
11117
11288
  function med(A2, B2) {
11118
11289
  return [(A2[0] + B2[0]) / 2, (A2[1] + B2[1]) / 2];
@@ -11139,7 +11310,7 @@ function getSvgPathFromStroke(points) {
11139
11310
  // src/comparisons.ts
11140
11311
  init_define_import_meta_env();
11141
11312
  var hasBackground = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "line" || type === "freedraw";
11142
- var hasStrokeColor = (type) => type !== "image" && type !== "frame" && type !== "magicframe";
11313
+ var hasStrokeColor = (type) => type === "rectangle" || type === "ellipse" || type === "diamond" || type === "freedraw" || type === "arrow" || type === "line" || type === "text";
11143
11314
  var hasStrokeWidth = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "freedraw" || type === "arrow" || type === "line";
11144
11315
  var hasStrokeStyle = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "arrow" || type === "line";
11145
11316
  var canChangeRoundness = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "line" || type === "diamond" || type === "image";
@@ -11395,26 +11566,26 @@ var generateLinearCollisionShape = (element) => {
11395
11566
  switch (element.type) {
11396
11567
  case "line":
11397
11568
  case "arrow": {
11398
- const points = element.points.length ? element.points : [pointFrom11(0, 0)];
11569
+ const points = element.points.length ? element.points : [pointFrom13(0, 0)];
11399
11570
  if (isElbowArrow(element)) {
11400
11571
  return generator.path(generateElbowArrowShape(points, 16), options).sets[0].ops;
11401
11572
  } else if (!element.roundness) {
11402
11573
  return points.map((point, idx) => {
11403
- const p = pointRotateRads9(
11404
- pointFrom11(element.x + point[0], element.y + point[1]),
11574
+ const p = pointRotateRads11(
11575
+ pointFrom13(element.x + point[0], element.y + point[1]),
11405
11576
  center,
11406
11577
  element.angle
11407
11578
  );
11408
11579
  return {
11409
11580
  op: idx === 0 ? "move" : "lineTo",
11410
- data: pointFrom11(p[0] - element.x, p[1] - element.y)
11581
+ data: pointFrom13(p[0] - element.x, p[1] - element.y)
11411
11582
  };
11412
11583
  });
11413
11584
  }
11414
11585
  return generator.curve(points, options).sets[0].ops.slice(0, element.points.length).map((op, i) => {
11415
11586
  if (i === 0) {
11416
- const p = pointRotateRads9(
11417
- pointFrom11(
11587
+ const p = pointRotateRads11(
11588
+ pointFrom13(
11418
11589
  element.x + op.data[0],
11419
11590
  element.y + op.data[1]
11420
11591
  ),
@@ -11423,30 +11594,30 @@ var generateLinearCollisionShape = (element) => {
11423
11594
  );
11424
11595
  return {
11425
11596
  op: "move",
11426
- data: pointFrom11(p[0] - element.x, p[1] - element.y)
11597
+ data: pointFrom13(p[0] - element.x, p[1] - element.y)
11427
11598
  };
11428
11599
  }
11429
11600
  return {
11430
11601
  op: "bcurveTo",
11431
11602
  data: [
11432
- pointRotateRads9(
11433
- pointFrom11(
11603
+ pointRotateRads11(
11604
+ pointFrom13(
11434
11605
  element.x + op.data[0],
11435
11606
  element.y + op.data[1]
11436
11607
  ),
11437
11608
  center,
11438
11609
  element.angle
11439
11610
  ),
11440
- pointRotateRads9(
11441
- pointFrom11(
11611
+ pointRotateRads11(
11612
+ pointFrom13(
11442
11613
  element.x + op.data[2],
11443
11614
  element.y + op.data[3]
11444
11615
  ),
11445
11616
  center,
11446
11617
  element.angle
11447
11618
  ),
11448
- pointRotateRads9(
11449
- pointFrom11(
11619
+ pointRotateRads11(
11620
+ pointFrom13(
11450
11621
  element.x + op.data[4],
11451
11622
  element.y + op.data[5]
11452
11623
  ),
@@ -11454,7 +11625,7 @@ var generateLinearCollisionShape = (element) => {
11454
11625
  element.angle
11455
11626
  )
11456
11627
  ].map(
11457
- (p) => pointFrom11(p[0] - element.x, p[1] - element.y)
11628
+ (p) => pointFrom13(p[0] - element.x, p[1] - element.y)
11458
11629
  ).flat()
11459
11630
  };
11460
11631
  });
@@ -11469,8 +11640,8 @@ var generateLinearCollisionShape = (element) => {
11469
11640
  );
11470
11641
  return generator.curve(simplifiedPoints, options).sets[0].ops.slice(0, element.points.length).map((op, i) => {
11471
11642
  if (i === 0) {
11472
- const p = pointRotateRads9(
11473
- pointFrom11(
11643
+ const p = pointRotateRads11(
11644
+ pointFrom13(
11474
11645
  element.x + op.data[0],
11475
11646
  element.y + op.data[1]
11476
11647
  ),
@@ -11479,30 +11650,30 @@ var generateLinearCollisionShape = (element) => {
11479
11650
  );
11480
11651
  return {
11481
11652
  op: "move",
11482
- data: pointFrom11(p[0] - element.x, p[1] - element.y)
11653
+ data: pointFrom13(p[0] - element.x, p[1] - element.y)
11483
11654
  };
11484
11655
  }
11485
11656
  return {
11486
11657
  op: "bcurveTo",
11487
11658
  data: [
11488
- pointRotateRads9(
11489
- pointFrom11(
11659
+ pointRotateRads11(
11660
+ pointFrom13(
11490
11661
  element.x + op.data[0],
11491
11662
  element.y + op.data[1]
11492
11663
  ),
11493
11664
  center,
11494
11665
  element.angle
11495
11666
  ),
11496
- pointRotateRads9(
11497
- pointFrom11(
11667
+ pointRotateRads11(
11668
+ pointFrom13(
11498
11669
  element.x + op.data[2],
11499
11670
  element.y + op.data[3]
11500
11671
  ),
11501
11672
  center,
11502
11673
  element.angle
11503
11674
  ),
11504
- pointRotateRads9(
11505
- pointFrom11(
11675
+ pointRotateRads11(
11676
+ pointFrom13(
11506
11677
  element.x + op.data[4],
11507
11678
  element.y + op.data[5]
11508
11679
  ),
@@ -11510,7 +11681,7 @@ var generateLinearCollisionShape = (element) => {
11510
11681
  element.angle
11511
11682
  )
11512
11683
  ].map(
11513
- (p) => pointFrom11(p[0] - element.x, p[1] - element.y)
11684
+ (p) => pointFrom13(p[0] - element.x, p[1] - element.y)
11514
11685
  ).flat()
11515
11686
  };
11516
11687
  });
@@ -11607,7 +11778,7 @@ var generateElementShape = (element, generator, {
11607
11778
  case "arrow": {
11608
11779
  let shape;
11609
11780
  const options = generateRoughOptions(element);
11610
- const points = element.points.length ? element.points : [pointFrom11(0, 0)];
11781
+ const points = element.points.length ? element.points : [pointFrom13(0, 0)];
11611
11782
  if (isElbowArrow(element)) {
11612
11783
  if (!points.every(
11613
11784
  (point) => Math.abs(point[0]) <= 1e6 && Math.abs(point[1]) <= 1e6
@@ -11769,14 +11940,14 @@ var getElementShape = (element, elementsMap) => {
11769
11940
  return shouldTestInside(element) ? getClosedCurveShape(
11770
11941
  element,
11771
11942
  roughShape,
11772
- pointFrom11(element.x, element.y),
11943
+ pointFrom13(element.x, element.y),
11773
11944
  element.angle,
11774
- pointFrom11(cx, cy)
11945
+ pointFrom13(cx, cy)
11775
11946
  ) : getCurveShape(
11776
11947
  roughShape,
11777
- pointFrom11(element.x, element.y),
11948
+ pointFrom13(element.x, element.y),
11778
11949
  element.angle,
11779
- pointFrom11(cx, cy)
11950
+ pointFrom13(cx, cy)
11780
11951
  );
11781
11952
  }
11782
11953
  case "ellipse":
@@ -11785,7 +11956,7 @@ var getElementShape = (element, elementsMap) => {
11785
11956
  const [, , , , cx, cy] = getElementAbsoluteCoords2(element, elementsMap);
11786
11957
  return getFreedrawShape(
11787
11958
  element,
11788
- pointFrom11(cx, cy),
11959
+ pointFrom13(cx, cy),
11789
11960
  shouldTestInside(element)
11790
11961
  );
11791
11962
  }
@@ -11804,9 +11975,9 @@ var toggleLinePolygonState = (element, nextPolygonState) => {
11804
11975
  firstPoint[1] - lastPoint[1]
11805
11976
  );
11806
11977
  if (distance3 > LINE_POLYGON_POINT_MERGE_DISTANCE || updatedPoints.length < 4) {
11807
- updatedPoints.push(pointFrom11(firstPoint[0], firstPoint[1]));
11978
+ updatedPoints.push(pointFrom13(firstPoint[0], firstPoint[1]));
11808
11979
  } else {
11809
- updatedPoints[updatedPoints.length - 1] = pointFrom11(
11980
+ updatedPoints[updatedPoints.length - 1] = pointFrom13(
11810
11981
  firstPoint[0],
11811
11982
  firstPoint[1]
11812
11983
  );
@@ -11860,9 +12031,9 @@ var ElementBounds = class _ElementBounds {
11860
12031
  if (isFreeDrawElement(element)) {
11861
12032
  const [minX, minY, maxX, maxY] = getBoundsFromPoints(
11862
12033
  element.points.map(
11863
- ([x, y]) => pointRotateRads10(
11864
- pointFrom12(x, y),
11865
- pointFrom12(cx - element.x, cy - element.y),
12034
+ ([x, y]) => pointRotateRads12(
12035
+ pointFrom14(x, y),
12036
+ pointFrom14(cx - element.x, cy - element.y),
11866
12037
  element.angle
11867
12038
  )
11868
12039
  )
@@ -11876,24 +12047,24 @@ var ElementBounds = class _ElementBounds {
11876
12047
  } else if (isLinearElement(element)) {
11877
12048
  bounds = getLinearElementRotatedBounds(element, cx, cy, elementsMap);
11878
12049
  } else if (element.type === "diamond") {
11879
- const [x11, y11] = pointRotateRads10(
11880
- pointFrom12(cx, y1),
11881
- pointFrom12(cx, cy),
12050
+ const [x11, y11] = pointRotateRads12(
12051
+ pointFrom14(cx, y1),
12052
+ pointFrom14(cx, cy),
11882
12053
  element.angle
11883
12054
  );
11884
- const [x12, y12] = pointRotateRads10(
11885
- pointFrom12(cx, y2),
11886
- pointFrom12(cx, cy),
12055
+ const [x12, y12] = pointRotateRads12(
12056
+ pointFrom14(cx, y2),
12057
+ pointFrom14(cx, cy),
11887
12058
  element.angle
11888
12059
  );
11889
- const [x22, y22] = pointRotateRads10(
11890
- pointFrom12(x1, cy),
11891
- pointFrom12(cx, cy),
12060
+ const [x22, y22] = pointRotateRads12(
12061
+ pointFrom14(x1, cy),
12062
+ pointFrom14(cx, cy),
11892
12063
  element.angle
11893
12064
  );
11894
- const [x21, y21] = pointRotateRads10(
11895
- pointFrom12(x2, cy),
11896
- pointFrom12(cx, cy),
12065
+ const [x21, y21] = pointRotateRads12(
12066
+ pointFrom14(x2, cy),
12067
+ pointFrom14(cx, cy),
11897
12068
  element.angle
11898
12069
  );
11899
12070
  const minX = Math.min(x11, x12, x22, x21);
@@ -11910,24 +12081,24 @@ var ElementBounds = class _ElementBounds {
11910
12081
  const hh = Math.hypot(h * cos, w * sin);
11911
12082
  bounds = [cx - ww, cy - hh, cx + ww, cy + hh];
11912
12083
  } else {
11913
- const [x11, y11] = pointRotateRads10(
11914
- pointFrom12(x1, y1),
11915
- pointFrom12(cx, cy),
12084
+ const [x11, y11] = pointRotateRads12(
12085
+ pointFrom14(x1, y1),
12086
+ pointFrom14(cx, cy),
11916
12087
  element.angle
11917
12088
  );
11918
- const [x12, y12] = pointRotateRads10(
11919
- pointFrom12(x1, y2),
11920
- pointFrom12(cx, cy),
12089
+ const [x12, y12] = pointRotateRads12(
12090
+ pointFrom14(x1, y2),
12091
+ pointFrom14(cx, cy),
11921
12092
  element.angle
11922
12093
  );
11923
- const [x22, y22] = pointRotateRads10(
11924
- pointFrom12(x2, y2),
11925
- pointFrom12(cx, cy),
12094
+ const [x22, y22] = pointRotateRads12(
12095
+ pointFrom14(x2, y2),
12096
+ pointFrom14(cx, cy),
11926
12097
  element.angle
11927
12098
  );
11928
- const [x21, y21] = pointRotateRads10(
11929
- pointFrom12(x2, y1),
11930
- pointFrom12(cx, cy),
12099
+ const [x21, y21] = pointRotateRads12(
12100
+ pointFrom14(x2, y1),
12101
+ pointFrom14(cx, cy),
11931
12102
  element.angle
11932
12103
  );
11933
12104
  const minX = Math.min(x11, x12, x22, x21);
@@ -11981,20 +12152,38 @@ var getElementLineSegments = (element, elementsMap) => {
11981
12152
  element,
11982
12153
  elementsMap
11983
12154
  );
11984
- const center = pointFrom12(cx, cy);
12155
+ const center = pointFrom14(cx, cy);
11985
12156
  if (shape.type === "polycurve") {
11986
12157
  const curves = shape.data;
11987
- const points = curves.map((curve4) => pointsOnBezierCurves(curve4, 10)).flat();
11988
- let i = 0;
12158
+ const pointsOnCurves = curves.map(
12159
+ (curve4) => pointsOnBezierCurves(curve4, 10)
12160
+ );
11989
12161
  const segments = [];
11990
- while (i < points.length - 1) {
11991
- segments.push(
11992
- lineSegment5(
11993
- pointFrom12(points[i][0], points[i][1]),
11994
- pointFrom12(points[i + 1][0], points[i + 1][1])
11995
- )
11996
- );
11997
- i++;
12162
+ if (isLineElement(element) && !element.polygon || isArrowElement(element)) {
12163
+ for (const points of pointsOnCurves) {
12164
+ let i = 0;
12165
+ while (i < points.length - 1) {
12166
+ segments.push(
12167
+ lineSegment6(
12168
+ pointFrom14(points[i][0], points[i][1]),
12169
+ pointFrom14(points[i + 1][0], points[i + 1][1])
12170
+ )
12171
+ );
12172
+ i++;
12173
+ }
12174
+ }
12175
+ } else {
12176
+ const points = pointsOnCurves.flat();
12177
+ let i = 0;
12178
+ while (i < points.length - 1) {
12179
+ segments.push(
12180
+ lineSegment6(
12181
+ pointFrom14(points[i][0], points[i][1]),
12182
+ pointFrom14(points[i + 1][0], points[i + 1][1])
12183
+ )
12184
+ );
12185
+ i++;
12186
+ }
11998
12187
  }
11999
12188
  return segments;
12000
12189
  } else if (shape.type === "polyline") {
@@ -12014,10 +12203,10 @@ var getElementLineSegments = (element, elementsMap) => {
12014
12203
  const container = getContainerElement(element, elementsMap);
12015
12204
  if (container && isLinearElement(container)) {
12016
12205
  const segments2 = [
12017
- lineSegment5(pointFrom12(x1, y1), pointFrom12(x2, y1)),
12018
- lineSegment5(pointFrom12(x2, y1), pointFrom12(x2, y2)),
12019
- lineSegment5(pointFrom12(x2, y2), pointFrom12(x1, y2)),
12020
- lineSegment5(pointFrom12(x1, y2), pointFrom12(x1, y1))
12206
+ lineSegment6(pointFrom14(x1, y1), pointFrom14(x2, y1)),
12207
+ lineSegment6(pointFrom14(x2, y1), pointFrom14(x2, y2)),
12208
+ lineSegment6(pointFrom14(x2, y2), pointFrom14(x1, y2)),
12209
+ lineSegment6(pointFrom14(x1, y2), pointFrom14(x1, y1))
12021
12210
  ];
12022
12211
  return segments2;
12023
12212
  }
@@ -12025,7 +12214,7 @@ var getElementLineSegments = (element, elementsMap) => {
12025
12214
  const points = shape.data;
12026
12215
  const segments = [];
12027
12216
  for (let i = 0; i < points.length - 1; i++) {
12028
- segments.push(lineSegment5(points[i], points[i + 1]));
12217
+ segments.push(lineSegment6(points[i], points[i + 1]));
12029
12218
  }
12030
12219
  return segments;
12031
12220
  } else if (shape.type === "ellipse") {
@@ -12040,16 +12229,16 @@ var getElementLineSegments = (element, elementsMap) => {
12040
12229
  [cx, y2],
12041
12230
  [x1, cy],
12042
12231
  [x2, cy]
12043
- ].map((point) => pointRotateRads10(point, center, element.angle));
12232
+ ].map((point) => pointRotateRads12(point, center, element.angle));
12044
12233
  return [
12045
- lineSegment5(nw, ne),
12046
- lineSegment5(sw, se2),
12047
- lineSegment5(nw, sw),
12048
- lineSegment5(ne, se2),
12049
- lineSegment5(nw, e),
12050
- lineSegment5(sw, e),
12051
- lineSegment5(ne, w),
12052
- lineSegment5(se2, w)
12234
+ lineSegment6(nw, ne),
12235
+ lineSegment6(sw, se2),
12236
+ lineSegment6(nw, sw),
12237
+ lineSegment6(ne, se2),
12238
+ lineSegment6(nw, e),
12239
+ lineSegment6(sw, e),
12240
+ lineSegment6(ne, w),
12241
+ lineSegment6(se2, w)
12053
12242
  ];
12054
12243
  };
12055
12244
  var _isRectanguloidElement = (element) => {
@@ -12057,9 +12246,9 @@ var _isRectanguloidElement = (element) => {
12057
12246
  };
12058
12247
  var getRotatedSides = (sides, center, angle) => {
12059
12248
  return sides.map((side) => {
12060
- return lineSegment5(
12061
- pointRotateRads10(side[0], center, angle),
12062
- pointRotateRads10(side[1], center, angle)
12249
+ return lineSegment6(
12250
+ pointRotateRads12(side[0], center, angle),
12251
+ pointRotateRads12(side[1], center, angle)
12063
12252
  );
12064
12253
  });
12065
12254
  };
@@ -12069,14 +12258,14 @@ var getSegmentsOnCurve = (curve4, center, angle) => {
12069
12258
  const segments = [];
12070
12259
  while (i < points.length - 1) {
12071
12260
  segments.push(
12072
- lineSegment5(
12073
- pointRotateRads10(
12074
- pointFrom12(points[i][0], points[i][1]),
12261
+ lineSegment6(
12262
+ pointRotateRads12(
12263
+ pointFrom14(points[i][0], points[i][1]),
12075
12264
  center,
12076
12265
  angle
12077
12266
  ),
12078
- pointRotateRads10(
12079
- pointFrom12(points[i + 1][0], points[i + 1][1]),
12267
+ pointRotateRads12(
12268
+ pointFrom14(points[i + 1][0], points[i + 1][1]),
12080
12269
  center,
12081
12270
  angle
12082
12271
  )
@@ -12087,7 +12276,7 @@ var getSegmentsOnCurve = (curve4, center, angle) => {
12087
12276
  return segments;
12088
12277
  };
12089
12278
  var getSegmentsOnEllipse = (ellipse4) => {
12090
- const center = pointFrom12(
12279
+ const center = pointFrom14(
12091
12280
  ellipse4.x + ellipse4.width / 2,
12092
12281
  ellipse4.y + ellipse4.height / 2
12093
12282
  );
@@ -12101,12 +12290,12 @@ var getSegmentsOnEllipse = (ellipse4) => {
12101
12290
  const t = i * deltaT;
12102
12291
  const x = center[0] + a2 * Math.cos(t);
12103
12292
  const y = center[1] + b2 * Math.sin(t);
12104
- points.push(pointRotateRads10(pointFrom12(x, y), center, ellipse4.angle));
12293
+ points.push(pointRotateRads12(pointFrom14(x, y), center, ellipse4.angle));
12105
12294
  }
12106
12295
  for (let i = 0; i < points.length - 1; i++) {
12107
- segments.push(lineSegment5(points[i], points[i + 1]));
12296
+ segments.push(lineSegment6(points[i], points[i + 1]));
12108
12297
  }
12109
- segments.push(lineSegment5(points[points.length - 1], points[0]));
12298
+ segments.push(lineSegment6(points[points.length - 1], points[0]));
12110
12299
  return segments;
12111
12300
  };
12112
12301
  var getRectangleBoxAbsoluteCoords = (boxSceneCoords) => {
@@ -12184,17 +12373,17 @@ var getCubicBezierCurveBound = (p0, p1, p2, p3) => {
12184
12373
  return [minX, minY, maxX, maxY];
12185
12374
  };
12186
12375
  var getMinMaxXYFromCurvePathOps = (ops, transformXY) => {
12187
- let currentP = pointFrom12(0, 0);
12376
+ let currentP = pointFrom14(0, 0);
12188
12377
  const { minX, minY, maxX, maxY } = ops.reduce(
12189
12378
  (limits, { op, data }) => {
12190
12379
  if (op === "move") {
12191
12380
  const p = pointFromArray3(data);
12192
- invariant7(p != null, "Op data is not a point");
12381
+ invariant8(p != null, "Op data is not a point");
12193
12382
  currentP = p;
12194
12383
  } else if (op === "bcurveTo") {
12195
- const _p1 = pointFrom12(data[0], data[1]);
12196
- const _p2 = pointFrom12(data[2], data[3]);
12197
- const _p3 = pointFrom12(data[4], data[5]);
12384
+ const _p1 = pointFrom14(data[0], data[1]);
12385
+ const _p2 = pointFrom14(data[2], data[3]);
12386
+ const _p3 = pointFrom14(data[4], data[5]);
12198
12387
  const p1 = transformXY ? transformXY(_p1) : _p1;
12199
12388
  const p2 = transformXY ? transformXY(_p2) : _p2;
12200
12389
  const p3 = transformXY ? transformXY(_p3) : _p3;
@@ -12275,18 +12464,18 @@ var getArrowheadPoints = (element, shape, position, arrowhead) => {
12275
12464
  }
12276
12465
  const index = position === "start" ? 1 : ops.length - 1;
12277
12466
  const data = ops[index].data;
12278
- invariant7(data.length === 6, "Op data length is not 6");
12279
- const p3 = pointFrom12(data[4], data[5]);
12280
- const p2 = pointFrom12(data[2], data[3]);
12281
- const p1 = pointFrom12(data[0], data[1]);
12467
+ invariant8(data.length === 6, "Op data length is not 6");
12468
+ const p3 = pointFrom14(data[4], data[5]);
12469
+ const p2 = pointFrom14(data[2], data[3]);
12470
+ const p1 = pointFrom14(data[0], data[1]);
12282
12471
  const prevOp = ops[index - 1];
12283
- let p0 = pointFrom12(0, 0);
12472
+ let p0 = pointFrom14(0, 0);
12284
12473
  if (prevOp.op === "move") {
12285
12474
  const p = pointFromArray3(prevOp.data);
12286
- invariant7(p != null, "Op data is not a point");
12475
+ invariant8(p != null, "Op data is not a point");
12287
12476
  p0 = p;
12288
12477
  } else if (prevOp.op === "bcurveTo") {
12289
- p0 = pointFrom12(prevOp.data[4], prevOp.data[5]);
12478
+ p0 = pointFrom14(prevOp.data[4], prevOp.data[5]);
12290
12479
  }
12291
12480
  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);
12292
12481
  const [x2, y2] = position === "start" ? p0 : p3;
@@ -12311,26 +12500,26 @@ var getArrowheadPoints = (element, shape, position, arrowhead) => {
12311
12500
  }
12312
12501
  const angle = getArrowheadAngle(arrowhead);
12313
12502
  if (arrowhead === "crowfoot_many" || arrowhead === "crowfoot_one_or_many") {
12314
- const [x32, y32] = pointRotateRads10(
12315
- pointFrom12(x2, y2),
12316
- pointFrom12(xs, ys),
12503
+ const [x32, y32] = pointRotateRads12(
12504
+ pointFrom14(x2, y2),
12505
+ pointFrom14(xs, ys),
12317
12506
  degreesToRadians(-angle)
12318
12507
  );
12319
- const [x42, y42] = pointRotateRads10(
12320
- pointFrom12(x2, y2),
12321
- pointFrom12(xs, ys),
12508
+ const [x42, y42] = pointRotateRads12(
12509
+ pointFrom14(x2, y2),
12510
+ pointFrom14(xs, ys),
12322
12511
  degreesToRadians(angle)
12323
12512
  );
12324
12513
  return [xs, ys, x32, y32, x42, y42];
12325
12514
  }
12326
- const [x3, y3] = pointRotateRads10(
12327
- pointFrom12(xs, ys),
12328
- pointFrom12(x2, y2),
12515
+ const [x3, y3] = pointRotateRads12(
12516
+ pointFrom14(xs, ys),
12517
+ pointFrom14(x2, y2),
12329
12518
  -angle * Math.PI / 180
12330
12519
  );
12331
- const [x4, y4] = pointRotateRads10(
12332
- pointFrom12(xs, ys),
12333
- pointFrom12(x2, y2),
12520
+ const [x4, y4] = pointRotateRads12(
12521
+ pointFrom14(xs, ys),
12522
+ pointFrom14(x2, y2),
12334
12523
  degreesToRadians(angle)
12335
12524
  );
12336
12525
  if (arrowhead === "diamond" || arrowhead === "diamond_outline") {
@@ -12338,16 +12527,16 @@ var getArrowheadPoints = (element, shape, position, arrowhead) => {
12338
12527
  let oy;
12339
12528
  if (position === "start") {
12340
12529
  const [px, py] = element.points.length > 1 ? element.points[1] : [0, 0];
12341
- [ox, oy] = pointRotateRads10(
12342
- pointFrom12(x2 + minSize * 2, y2),
12343
- pointFrom12(x2, y2),
12530
+ [ox, oy] = pointRotateRads12(
12531
+ pointFrom14(x2 + minSize * 2, y2),
12532
+ pointFrom14(x2, y2),
12344
12533
  Math.atan2(py - y2, px - x2)
12345
12534
  );
12346
12535
  } else {
12347
12536
  const [px, py] = element.points.length > 1 ? element.points[element.points.length - 2] : [0, 0];
12348
- [ox, oy] = pointRotateRads10(
12349
- pointFrom12(x2 - minSize * 2, y2),
12350
- pointFrom12(x2, y2),
12537
+ [ox, oy] = pointRotateRads12(
12538
+ pointFrom14(x2 - minSize * 2, y2),
12539
+ pointFrom14(x2, y2),
12351
12540
  Math.atan2(y2 - py, x2 - px)
12352
12541
  );
12353
12542
  }
@@ -12376,9 +12565,9 @@ var getLinearElementRotatedBounds = (element, cx, cy, elementsMap) => {
12376
12565
  const boundTextElement = getBoundTextElement(element, elementsMap);
12377
12566
  if (element.points.length < 2) {
12378
12567
  const [pointX, pointY] = element.points[0];
12379
- const [x, y] = pointRotateRads10(
12380
- pointFrom12(element.x + pointX, element.y + pointY),
12381
- pointFrom12(cx, cy),
12568
+ const [x, y] = pointRotateRads12(
12569
+ pointFrom14(element.x + pointX, element.y + pointY),
12570
+ pointFrom14(cx, cy),
12382
12571
  element.angle
12383
12572
  );
12384
12573
  let coords2 = [x, y, x, y];
@@ -12401,9 +12590,9 @@ var getLinearElementRotatedBounds = (element, cx, cy, elementsMap) => {
12401
12590
  const cachedShape = ShapeCache.get(element)?.[0];
12402
12591
  const shape = cachedShape ?? generateLinearElementShape(element);
12403
12592
  const ops = getCurvePathOps(shape);
12404
- const transformXY = ([x, y]) => pointRotateRads10(
12405
- pointFrom12(element.x + x, element.y + y),
12406
- pointFrom12(cx, cy),
12593
+ const transformXY = ([x, y]) => pointRotateRads12(
12594
+ pointFrom14(element.x + x, element.y + y),
12595
+ pointFrom14(cx, cy),
12407
12596
  element.angle
12408
12597
  );
12409
12598
  const res = getMinMaxXYFromCurvePathOps(ops, transformXY);
@@ -12514,8 +12703,8 @@ var getClosestElementBounds = (elements, from) => {
12514
12703
  elements.forEach((element) => {
12515
12704
  const [x1, y1, x2, y2] = getElementBounds(element, elementsMap);
12516
12705
  const distance3 = pointDistance7(
12517
- pointFrom12((x1 + x2) / 2, (y1 + y2) / 2),
12518
- pointFrom12(from.x, from.y)
12706
+ pointFrom14((x1 + x2) / 2, (y1 + y2) / 2),
12707
+ pointFrom14(from.x, from.y)
12519
12708
  );
12520
12709
  if (distance3 < minDistance) {
12521
12710
  minDistance = distance3;
@@ -12551,7 +12740,7 @@ var getVisibleSceneBounds = ({
12551
12740
  -scrollY + height / zoom.value
12552
12741
  ];
12553
12742
  };
12554
- var getCenterForBounds = (bounds) => pointFrom12(
12743
+ var getCenterForBounds = (bounds) => pointFrom14(
12555
12744
  bounds[0] + (bounds[2] - bounds[0]) / 2,
12556
12745
  bounds[1] + (bounds[3] - bounds[1]) / 2
12557
12746
  );
@@ -12565,23 +12754,23 @@ var aabbForElement = (element, elementsMap, offset) => {
12565
12754
  midY: element.y + element.height / 2
12566
12755
  };
12567
12756
  const center = elementCenterPoint(element, elementsMap);
12568
- const [topLeftX, topLeftY] = pointRotateRads10(
12569
- pointFrom12(bbox.minX, bbox.minY),
12757
+ const [topLeftX, topLeftY] = pointRotateRads12(
12758
+ pointFrom14(bbox.minX, bbox.minY),
12570
12759
  center,
12571
12760
  element.angle
12572
12761
  );
12573
- const [topRightX, topRightY] = pointRotateRads10(
12574
- pointFrom12(bbox.maxX, bbox.minY),
12762
+ const [topRightX, topRightY] = pointRotateRads12(
12763
+ pointFrom14(bbox.maxX, bbox.minY),
12575
12764
  center,
12576
12765
  element.angle
12577
12766
  );
12578
- const [bottomRightX, bottomRightY] = pointRotateRads10(
12579
- pointFrom12(bbox.maxX, bbox.maxY),
12767
+ const [bottomRightX, bottomRightY] = pointRotateRads12(
12768
+ pointFrom14(bbox.maxX, bbox.maxY),
12580
12769
  center,
12581
12770
  element.angle
12582
12771
  );
12583
- const [bottomLeftX, bottomLeftY] = pointRotateRads10(
12584
- pointFrom12(bbox.minX, bbox.maxY),
12772
+ const [bottomLeftX, bottomLeftY] = pointRotateRads12(
12773
+ pointFrom14(bbox.minX, bbox.maxY),
12585
12774
  center,
12586
12775
  element.angle
12587
12776
  );
@@ -12613,7 +12802,7 @@ var doBoundsIntersect = (bounds1, bounds2) => {
12613
12802
  };
12614
12803
  var elementCenterPoint = (element, elementsMap, xOffset = 0, yOffset = 0) => {
12615
12804
  const [x, y] = getCenterForBounds(getElementBounds(element, elementsMap));
12616
- return pointFrom12(x + xOffset, y + yOffset);
12805
+ return pointFrom14(x + xOffset, y + yOffset);
12617
12806
  };
12618
12807
 
12619
12808
  // src/sizeHelpers.ts
@@ -12742,11 +12931,11 @@ var getNormalizedDimensions = (element) => {
12742
12931
 
12743
12932
  // src/align.ts
12744
12933
  init_define_import_meta_env();
12745
- var alignElements = (selectedElements, alignment, scene) => {
12746
- const elementsMap = scene.getNonDeletedElementsMap();
12747
- const groups = getMaximumGroups(
12934
+ var alignElements = (selectedElements, alignment, scene, appState) => {
12935
+ const groups = getSelectedElementsByGroup(
12748
12936
  selectedElements,
12749
- elementsMap
12937
+ scene.getNonDeletedElementsMap(),
12938
+ appState
12750
12939
  );
12751
12940
  const selectionBoundingBox = getCommonBoundingBox(selectedElements);
12752
12941
  return groups.flatMap((group) => {
@@ -13182,8 +13371,9 @@ var Store = class {
13182
13371
  constructor(app) {
13183
13372
  this.app = app;
13184
13373
  }
13185
- // internally used by history
13374
+ // for internal use by history
13186
13375
  onDurableIncrementEmitter = new Emitter();
13376
+ // for public use as part of onIncrement API
13187
13377
  onStoreIncrementEmitter = new Emitter();
13188
13378
  scheduledMacroActions = /* @__PURE__ */ new Set();
13189
13379
  scheduledMicroActions = [];
@@ -13439,7 +13629,7 @@ var EphemeralIncrement = class extends StoreIncrement {
13439
13629
  this.change = change;
13440
13630
  }
13441
13631
  };
13442
- var StoreDelta = class {
13632
+ var StoreDelta = class _StoreDelta {
13443
13633
  constructor(id, elements, appState) {
13444
13634
  this.id = id;
13445
13635
  this.elements = elements;
@@ -13477,10 +13667,23 @@ var StoreDelta = class {
13477
13667
  */
13478
13668
  static load({
13479
13669
  id,
13480
- elements: { added, removed, updated }
13670
+ elements: { added, removed, updated },
13671
+ appState: { delta: appStateDelta }
13481
13672
  }) {
13482
13673
  const elements = ElementsDelta.create(added, removed, updated);
13483
- return new this(id, elements, AppStateDelta.empty());
13674
+ const appState = AppStateDelta.create(appStateDelta);
13675
+ return new this(id, elements, appState);
13676
+ }
13677
+ /**
13678
+ * Squash the passed deltas into the aggregated delta instance.
13679
+ */
13680
+ static squash(...deltas) {
13681
+ const aggregatedDelta = _StoreDelta.empty();
13682
+ for (const delta of deltas) {
13683
+ aggregatedDelta.elements.squash(delta.elements);
13684
+ aggregatedDelta.appState.squash(delta.appState);
13685
+ }
13686
+ return aggregatedDelta;
13484
13687
  }
13485
13688
  /**
13486
13689
  * Inverse store delta, creates new instance of `StoreDelta`.
@@ -13491,8 +13694,12 @@ var StoreDelta = class {
13491
13694
  /**
13492
13695
  * Apply the delta to the passed elements and appState, does not modify the snapshot.
13493
13696
  */
13494
- static applyTo(delta, elements, appState) {
13495
- const [nextElements, elementsContainVisibleChange] = delta.elements.applyTo(elements);
13697
+ static applyTo(delta, elements, appState, options) {
13698
+ const [nextElements, elementsContainVisibleChange] = delta.elements.applyTo(
13699
+ elements,
13700
+ StoreSnapshot.empty().elements,
13701
+ options
13702
+ );
13496
13703
  const [nextAppState, appStateContainsVisibleChange] = delta.appState.applyTo(appState, nextElements);
13497
13704
  const appliedVisibleChanges = elementsContainVisibleChange || appStateContainsVisibleChange;
13498
13705
  return [nextElements, nextAppState, appliedVisibleChanges];
@@ -13513,6 +13720,9 @@ var StoreDelta = class {
13513
13720
  }
13514
13721
  );
13515
13722
  }
13723
+ static empty() {
13724
+ return _StoreDelta.create(ElementsDelta.empty(), AppStateDelta.empty());
13725
+ }
13516
13726
  isEmpty() {
13517
13727
  return this.elements.isEmpty() && this.appState.isEmpty();
13518
13728
  }
@@ -13753,8 +13963,7 @@ var getDefaultObservedAppState = () => {
13753
13963
  viewBackgroundColor: COLOR_PALETTE2.white,
13754
13964
  selectedElementIds: {},
13755
13965
  selectedGroupIds: {},
13756
- editingLinearElementId: null,
13757
- selectedLinearElementId: null,
13966
+ selectedLinearElement: null,
13758
13967
  croppingElementId: null,
13759
13968
  activeLockedId: null,
13760
13969
  lockedMultiSelections: {}
@@ -13770,10 +13979,10 @@ var getObservedAppState = (appState) => {
13770
13979
  croppingElementId: appState.croppingElementId,
13771
13980
  activeLockedId: appState.activeLockedId,
13772
13981
  lockedMultiSelections: appState.lockedMultiSelections,
13773
- editingLinearElementId: appState.editingLinearElement?.elementId ?? // prefer app state, as it's likely newer
13774
- appState.editingLinearElementId ?? // fallback to observed app state, as it's likely older coming from a previous snapshot
13775
- null,
13776
- selectedLinearElementId: appState.selectedLinearElement?.elementId ?? appState.selectedLinearElementId ?? null
13982
+ selectedLinearElement: appState.selectedLinearElement ? {
13983
+ elementId: appState.selectedLinearElement.elementId,
13984
+ isEditing: !!appState.selectedLinearElement.isEditing
13985
+ } : null
13777
13986
  };
13778
13987
  Reflect.defineProperty(observedAppState, hiddenObservedAppStateProp, {
13779
13988
  value: true,
@@ -14337,9 +14546,9 @@ var Scene = class {
14337
14546
  getFramesIncludingDeleted() {
14338
14547
  return this.frames;
14339
14548
  }
14340
- constructor(elements = null) {
14549
+ constructor(elements = null, options) {
14341
14550
  if (elements) {
14342
- this.replaceAllElements(elements);
14551
+ this.replaceAllElements(elements, options);
14343
14552
  }
14344
14553
  }
14345
14554
  getSelectedElements(opts) {
@@ -14404,10 +14613,12 @@ var Scene = class {
14404
14613
  }
14405
14614
  return didChange;
14406
14615
  }
14407
- replaceAllElements(nextElements) {
14616
+ replaceAllElements(nextElements, options) {
14408
14617
  const _nextElements = toArray(nextElements);
14409
14618
  const nextFrameLikes = [];
14410
- validateIndicesThrottled(_nextElements);
14619
+ if (!options?.skipValidation) {
14620
+ validateIndicesThrottled(_nextElements);
14621
+ }
14411
14622
  this.elements = syncInvalidIndices2(_nextElements);
14412
14623
  this.elementsMap.clear();
14413
14624
  this.elements.forEach((element) => {
@@ -14577,10 +14788,19 @@ var Delta = class _Delta {
14577
14788
  static isEmpty(delta) {
14578
14789
  return !Object.keys(delta.deleted).length && !Object.keys(delta.inserted).length;
14579
14790
  }
14791
+ /**
14792
+ * Merges two deltas into a new one.
14793
+ */
14794
+ static merge(delta1, delta2, delta3 = _Delta.empty()) {
14795
+ return _Delta.create(
14796
+ { ...delta1.deleted, ...delta2.deleted, ...delta3.deleted },
14797
+ { ...delta1.inserted, ...delta2.inserted, ...delta3.inserted }
14798
+ );
14799
+ }
14580
14800
  /**
14581
14801
  * Merges deleted and inserted object partials.
14582
14802
  */
14583
- static mergeObjects(prev, added, removed) {
14803
+ static mergeObjects(prev, added, removed = {}) {
14584
14804
  const cloned = { ...prev };
14585
14805
  for (const key of Object.keys(removed)) {
14586
14806
  delete cloned[key];
@@ -14801,6 +15021,9 @@ var AppStateDelta = class _AppStateDelta {
14801
15021
  constructor(delta) {
14802
15022
  this.delta = delta;
14803
15023
  }
15024
+ static create(delta) {
15025
+ return new _AppStateDelta(delta);
15026
+ }
14804
15027
  static calculate(prevAppState, nextAppState) {
14805
15028
  const delta = Delta.calculate(
14806
15029
  prevAppState,
@@ -14822,50 +15045,98 @@ var AppStateDelta = class _AppStateDelta {
14822
15045
  const inversedDelta = Delta.create(this.delta.inserted, this.delta.deleted);
14823
15046
  return new _AppStateDelta(inversedDelta);
14824
15047
  }
15048
+ squash(delta) {
15049
+ if (delta.isEmpty()) {
15050
+ return this;
15051
+ }
15052
+ const mergedDeletedSelectedElementIds = Delta.mergeObjects(
15053
+ this.delta.deleted.selectedElementIds ?? {},
15054
+ delta.delta.deleted.selectedElementIds ?? {}
15055
+ );
15056
+ const mergedInsertedSelectedElementIds = Delta.mergeObjects(
15057
+ this.delta.inserted.selectedElementIds ?? {},
15058
+ delta.delta.inserted.selectedElementIds ?? {}
15059
+ );
15060
+ const mergedDeletedSelectedGroupIds = Delta.mergeObjects(
15061
+ this.delta.deleted.selectedGroupIds ?? {},
15062
+ delta.delta.deleted.selectedGroupIds ?? {}
15063
+ );
15064
+ const mergedInsertedSelectedGroupIds = Delta.mergeObjects(
15065
+ this.delta.inserted.selectedGroupIds ?? {},
15066
+ delta.delta.inserted.selectedGroupIds ?? {}
15067
+ );
15068
+ const mergedDeletedLockedMultiSelections = Delta.mergeObjects(
15069
+ this.delta.deleted.lockedMultiSelections ?? {},
15070
+ delta.delta.deleted.lockedMultiSelections ?? {}
15071
+ );
15072
+ const mergedInsertedLockedMultiSelections = Delta.mergeObjects(
15073
+ this.delta.inserted.lockedMultiSelections ?? {},
15074
+ delta.delta.inserted.lockedMultiSelections ?? {}
15075
+ );
15076
+ const mergedInserted = {};
15077
+ const mergedDeleted = {};
15078
+ if (Object.keys(mergedDeletedSelectedElementIds).length || Object.keys(mergedInsertedSelectedElementIds).length) {
15079
+ mergedDeleted.selectedElementIds = mergedDeletedSelectedElementIds;
15080
+ mergedInserted.selectedElementIds = mergedInsertedSelectedElementIds;
15081
+ }
15082
+ if (Object.keys(mergedDeletedSelectedGroupIds).length || Object.keys(mergedInsertedSelectedGroupIds).length) {
15083
+ mergedDeleted.selectedGroupIds = mergedDeletedSelectedGroupIds;
15084
+ mergedInserted.selectedGroupIds = mergedInsertedSelectedGroupIds;
15085
+ }
15086
+ if (Object.keys(mergedDeletedLockedMultiSelections).length || Object.keys(mergedInsertedLockedMultiSelections).length) {
15087
+ mergedDeleted.lockedMultiSelections = mergedDeletedLockedMultiSelections;
15088
+ mergedInserted.lockedMultiSelections = mergedInsertedLockedMultiSelections;
15089
+ }
15090
+ this.delta = Delta.merge(
15091
+ this.delta,
15092
+ delta.delta,
15093
+ Delta.create(mergedDeleted, mergedInserted)
15094
+ );
15095
+ return this;
15096
+ }
14825
15097
  applyTo(appState, nextElements) {
14826
15098
  try {
14827
15099
  const {
14828
- selectedElementIds: removedSelectedElementIds = {},
14829
- selectedGroupIds: removedSelectedGroupIds = {}
15100
+ selectedElementIds: deletedSelectedElementIds = {},
15101
+ selectedGroupIds: deletedSelectedGroupIds = {},
15102
+ lockedMultiSelections: deletedLockedMultiSelections = {}
14830
15103
  } = this.delta.deleted;
14831
15104
  const {
14832
- selectedElementIds: addedSelectedElementIds = {},
14833
- selectedGroupIds: addedSelectedGroupIds = {},
14834
- selectedLinearElementId,
14835
- editingLinearElementId,
15105
+ selectedElementIds: insertedSelectedElementIds = {},
15106
+ selectedGroupIds: insertedSelectedGroupIds = {},
15107
+ lockedMultiSelections: insertedLockedMultiSelections = {},
15108
+ selectedLinearElement: insertedSelectedLinearElement,
14836
15109
  ...directlyApplicablePartial
14837
15110
  } = this.delta.inserted;
14838
15111
  const mergedSelectedElementIds = Delta.mergeObjects(
14839
15112
  appState.selectedElementIds,
14840
- addedSelectedElementIds,
14841
- removedSelectedElementIds
15113
+ insertedSelectedElementIds,
15114
+ deletedSelectedElementIds
14842
15115
  );
14843
15116
  const mergedSelectedGroupIds = Delta.mergeObjects(
14844
15117
  appState.selectedGroupIds,
14845
- addedSelectedGroupIds,
14846
- removedSelectedGroupIds
15118
+ insertedSelectedGroupIds,
15119
+ deletedSelectedGroupIds
14847
15120
  );
14848
- const selectedLinearElement = selectedLinearElementId && nextElements.has(selectedLinearElementId) ? new LinearElementEditor(
14849
- nextElements.get(
14850
- selectedLinearElementId
14851
- ),
14852
- nextElements
14853
- ) : null;
14854
- const editingLinearElement = editingLinearElementId && nextElements.has(editingLinearElementId) ? new LinearElementEditor(
15121
+ const mergedLockedMultiSelections = Delta.mergeObjects(
15122
+ appState.lockedMultiSelections,
15123
+ insertedLockedMultiSelections,
15124
+ deletedLockedMultiSelections
15125
+ );
15126
+ const selectedLinearElement = insertedSelectedLinearElement && nextElements.has(insertedSelectedLinearElement.elementId) ? new LinearElementEditor(
14855
15127
  nextElements.get(
14856
- editingLinearElementId
15128
+ insertedSelectedLinearElement.elementId
14857
15129
  ),
14858
- nextElements
15130
+ nextElements,
15131
+ insertedSelectedLinearElement.isEditing
14859
15132
  ) : null;
14860
15133
  const nextAppState = {
14861
15134
  ...appState,
14862
15135
  ...directlyApplicablePartial,
14863
15136
  selectedElementIds: mergedSelectedElementIds,
14864
15137
  selectedGroupIds: mergedSelectedGroupIds,
14865
- selectedLinearElement: typeof selectedLinearElementId !== "undefined" ? selectedLinearElement : appState.selectedLinearElement,
14866
- // otherwise assign what we had before
14867
- editingLinearElement: typeof editingLinearElementId !== "undefined" ? editingLinearElement : appState.editingLinearElement
14868
- // otherwise assign what we had before
15138
+ lockedMultiSelections: mergedLockedMultiSelections,
15139
+ selectedLinearElement: typeof insertedSelectedLinearElement !== "undefined" ? selectedLinearElement : appState.selectedLinearElement
14869
15140
  };
14870
15141
  const constainsVisibleChanges = this.filterInvisibleChanges(
14871
15142
  appState,
@@ -14955,57 +15226,44 @@ var AppStateDelta = class _AppStateDelta {
14955
15226
  nextAppState[key] = null;
14956
15227
  }
14957
15228
  break;
14958
- case "selectedLinearElementId":
14959
- case "editingLinearElementId":
14960
- const appStateKey = _AppStateDelta.convertToAppStateKey(key);
14961
- const linearElement = nextAppState[appStateKey];
14962
- if (!linearElement) {
15229
+ case "selectedLinearElement":
15230
+ const nextLinearElement = nextAppState[key];
15231
+ if (!nextLinearElement) {
14963
15232
  visibleDifferenceFlag.value = true;
14964
15233
  } else {
14965
- const element = nextElements.get(linearElement.elementId);
15234
+ const element = nextElements.get(nextLinearElement.elementId);
14966
15235
  if (element && !element.isDeleted) {
14967
15236
  visibleDifferenceFlag.value = true;
14968
15237
  } else {
14969
- nextAppState[appStateKey] = null;
15238
+ nextAppState[key] = null;
14970
15239
  }
14971
15240
  }
14972
15241
  break;
14973
- case "lockedMultiSelections": {
15242
+ case "lockedMultiSelections":
14974
15243
  const prevLockedUnits = prevAppState[key] || {};
14975
15244
  const nextLockedUnits = nextAppState[key] || {};
14976
15245
  if (!isShallowEqual2(prevLockedUnits, nextLockedUnits)) {
14977
15246
  visibleDifferenceFlag.value = true;
14978
15247
  }
14979
15248
  break;
14980
- }
14981
- case "activeLockedId": {
15249
+ case "activeLockedId":
14982
15250
  const prevHitLockedId = prevAppState[key] || null;
14983
15251
  const nextHitLockedId = nextAppState[key] || null;
14984
15252
  if (prevHitLockedId !== nextHitLockedId) {
14985
15253
  visibleDifferenceFlag.value = true;
14986
15254
  }
14987
15255
  break;
14988
- }
14989
- default: {
15256
+ default:
14990
15257
  assertNever4(
14991
15258
  key,
14992
15259
  `Unknown ObservedElementsAppState's key "${key}"`,
14993
15260
  true
14994
15261
  );
14995
- }
14996
15262
  }
14997
15263
  }
14998
15264
  }
14999
15265
  return visibleDifferenceFlag.value;
15000
15266
  }
15001
- static convertToAppStateKey(key) {
15002
- switch (key) {
15003
- case "selectedLinearElementId":
15004
- return "selectedLinearElement";
15005
- case "editingLinearElementId":
15006
- return "editingLinearElement";
15007
- }
15008
- }
15009
15267
  static filterSelectedElements(selectedElementIds, elements, visibleDifferenceFlag) {
15010
15268
  const ids = Object.keys(selectedElementIds);
15011
15269
  if (!ids.length) {
@@ -15044,8 +15302,7 @@ var AppStateDelta = class _AppStateDelta {
15044
15302
  editingGroupId,
15045
15303
  selectedGroupIds,
15046
15304
  selectedElementIds,
15047
- editingLinearElementId,
15048
- selectedLinearElementId,
15305
+ selectedLinearElement,
15049
15306
  croppingElementId,
15050
15307
  lockedMultiSelections,
15051
15308
  activeLockedId,
@@ -15082,12 +15339,6 @@ var AppStateDelta = class _AppStateDelta {
15082
15339
  "lockedMultiSelections",
15083
15340
  (prevValue) => prevValue ?? {}
15084
15341
  );
15085
- Delta.diffObjects(
15086
- deleted,
15087
- inserted,
15088
- "activeLockedId",
15089
- (prevValue) => prevValue ?? null
15090
- );
15091
15342
  } catch (e) {
15092
15343
  console.error(`Couldn't postprocess appstate change deltas.`);
15093
15344
  if (isTestEnv8() || isDevEnv7()) {
@@ -15166,13 +15417,17 @@ var ElementsDelta = class _ElementsDelta {
15166
15417
  static satisfiesCommmonInvariants = ({
15167
15418
  deleted,
15168
15419
  inserted
15169
- }) => !!(deleted.version && inserted.version && // versions are required integers
15170
- Number.isInteger(deleted.version) && Number.isInteger(inserted.version) && // versions should be positive, zero included
15420
+ }) => !!// versions are required integers
15421
+ (Number.isInteger(deleted.version) && Number.isInteger(inserted.version) && // versions should be positive, zero included
15171
15422
  deleted.version >= 0 && inserted.version >= 0 && // versions should never be the same
15172
15423
  deleted.version !== inserted.version);
15424
+ static satisfiesUniqueInvariants = (elementsDelta, id) => {
15425
+ const { added, removed, updated } = elementsDelta;
15426
+ return [added[id], removed[id], updated[id]].filter(Boolean).length === 1;
15427
+ };
15173
15428
  static validate(elementsDelta, type, satifiesSpecialInvariants) {
15174
15429
  for (const [id, delta] of Object.entries(elementsDelta[type])) {
15175
- if (!this.satisfiesCommmonInvariants(delta) || !satifiesSpecialInvariants(delta)) {
15430
+ if (!this.satisfiesCommmonInvariants(delta) || !this.satisfiesUniqueInvariants(elementsDelta, id) || !satifiesSpecialInvariants(delta)) {
15176
15431
  console.error(
15177
15432
  `Broken invariant for "${type}" delta, element "${id}", delta:`,
15178
15433
  delta
@@ -15199,7 +15454,7 @@ var ElementsDelta = class _ElementsDelta {
15199
15454
  for (const prevElement of prevElements.values()) {
15200
15455
  const nextElement = nextElements.get(prevElement.id);
15201
15456
  if (!nextElement) {
15202
- const deleted = { ...prevElement, isDeleted: false };
15457
+ const deleted = { ...prevElement };
15203
15458
  const inserted = {
15204
15459
  isDeleted: true,
15205
15460
  version: prevElement.version + 1,
@@ -15210,7 +15465,11 @@ var ElementsDelta = class _ElementsDelta {
15210
15465
  inserted,
15211
15466
  _ElementsDelta.stripIrrelevantProps
15212
15467
  );
15213
- removed[prevElement.id] = delta;
15468
+ if (!prevElement.isDeleted) {
15469
+ removed[prevElement.id] = delta;
15470
+ } else {
15471
+ updated[prevElement.id] = delta;
15472
+ }
15214
15473
  }
15215
15474
  }
15216
15475
  for (const nextElement of nextElements.values()) {
@@ -15222,15 +15481,18 @@ var ElementsDelta = class _ElementsDelta {
15222
15481
  versionNonce: randomInteger4()
15223
15482
  };
15224
15483
  const inserted = {
15225
- ...nextElement,
15226
- isDeleted: false
15484
+ ...nextElement
15227
15485
  };
15228
15486
  const delta = Delta.create(
15229
15487
  deleted,
15230
15488
  inserted,
15231
15489
  _ElementsDelta.stripIrrelevantProps
15232
15490
  );
15233
- added[nextElement.id] = delta;
15491
+ if (!nextElement.isDeleted) {
15492
+ added[nextElement.id] = delta;
15493
+ } else {
15494
+ updated[nextElement.id] = delta;
15495
+ }
15234
15496
  continue;
15235
15497
  }
15236
15498
  if (prevElement.versionNonce !== nextElement.versionNonce) {
@@ -15251,9 +15513,7 @@ var ElementsDelta = class _ElementsDelta {
15251
15513
  }
15252
15514
  continue;
15253
15515
  }
15254
- if (!Delta.isEmpty(delta)) {
15255
- updated[nextElement.id] = delta;
15256
- }
15516
+ updated[nextElement.id] = delta;
15257
15517
  }
15258
15518
  }
15259
15519
  return _ElementsDelta.create(added, removed, updated);
@@ -15264,8 +15524,8 @@ var ElementsDelta = class _ElementsDelta {
15264
15524
  inverse() {
15265
15525
  const inverseInternal = (deltas) => {
15266
15526
  const inversedDeltas = {};
15267
- for (const [id, delta] of Object.entries(deltas)) {
15268
- inversedDeltas[id] = Delta.create(delta.inserted, delta.deleted);
15527
+ for (const [id, { inserted, deleted }] of Object.entries(deltas)) {
15528
+ inversedDeltas[id] = Delta.create({ ...inserted }, { ...deleted });
15269
15529
  }
15270
15530
  return inversedDeltas;
15271
15531
  };
@@ -15343,26 +15603,30 @@ var ElementsDelta = class _ElementsDelta {
15343
15603
  // redistribute the deltas as `isDeleted` could have been updated
15344
15604
  });
15345
15605
  }
15346
- applyTo(elements, snapshot = StoreSnapshot.empty().elements, options = {
15347
- excludedProperties: /* @__PURE__ */ new Set()
15348
- }) {
15606
+ applyTo(elements, snapshot = StoreSnapshot.empty().elements, options) {
15349
15607
  let nextElements = new Map(elements);
15350
15608
  let changedElements;
15351
15609
  const flags = {
15352
15610
  containsVisibleDifference: false,
15353
- containsZindexDifference: false
15611
+ containsZindexDifference: false,
15612
+ applyDirection: void 0
15354
15613
  };
15355
15614
  try {
15356
15615
  const applyDeltas = _ElementsDelta.createApplier(
15616
+ elements,
15357
15617
  nextElements,
15358
15618
  snapshot,
15359
- options,
15360
- flags
15619
+ flags,
15620
+ options
15361
15621
  );
15362
15622
  const addedElements = applyDeltas(this.added);
15363
15623
  const removedElements = applyDeltas(this.removed);
15364
15624
  const updatedElements = applyDeltas(this.updated);
15365
- const affectedElements = this.resolveConflicts(elements, nextElements);
15625
+ const affectedElements = this.resolveConflicts(
15626
+ elements,
15627
+ nextElements,
15628
+ flags.applyDirection
15629
+ );
15366
15630
  changedElements = new Map([
15367
15631
  ...addedElements,
15368
15632
  ...removedElements,
@@ -15382,9 +15646,7 @@ var ElementsDelta = class _ElementsDelta {
15382
15646
  changedElements,
15383
15647
  flags
15384
15648
  );
15385
- const tempScene = new Scene(nextElements);
15386
- _ElementsDelta.redrawTextBoundingBoxes(tempScene, changedElements);
15387
- _ElementsDelta.redrawBoundArrows(tempScene, changedElements);
15649
+ _ElementsDelta.redrawElements(nextElements, changedElements);
15388
15650
  } catch (e) {
15389
15651
  console.error(
15390
15652
  `Couldn't mutate elements after applying elements change`,
@@ -15397,7 +15659,82 @@ var ElementsDelta = class _ElementsDelta {
15397
15659
  return [nextElements, flags.containsVisibleDifference];
15398
15660
  }
15399
15661
  }
15400
- static createApplier = (nextElements, snapshot, options, flags) => (deltas) => {
15662
+ squash(delta) {
15663
+ if (delta.isEmpty()) {
15664
+ return this;
15665
+ }
15666
+ const { added, removed, updated } = delta;
15667
+ const mergeBoundElements = (prevDelta, nextDelta) => {
15668
+ const mergedDeletedBoundElements = Delta.mergeArrays(
15669
+ prevDelta.deleted.boundElements ?? [],
15670
+ nextDelta.deleted.boundElements ?? [],
15671
+ void 0,
15672
+ (x) => x.id
15673
+ ) ?? [];
15674
+ const mergedInsertedBoundElements = Delta.mergeArrays(
15675
+ prevDelta.inserted.boundElements ?? [],
15676
+ nextDelta.inserted.boundElements ?? [],
15677
+ void 0,
15678
+ (x) => x.id
15679
+ ) ?? [];
15680
+ if (!mergedDeletedBoundElements.length && !mergedInsertedBoundElements.length) {
15681
+ return;
15682
+ }
15683
+ return Delta.create(
15684
+ {
15685
+ boundElements: mergedDeletedBoundElements
15686
+ },
15687
+ {
15688
+ boundElements: mergedInsertedBoundElements
15689
+ }
15690
+ );
15691
+ };
15692
+ for (const [id, nextDelta] of Object.entries(added)) {
15693
+ const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];
15694
+ if (!prevDelta) {
15695
+ this.added[id] = nextDelta;
15696
+ } else {
15697
+ const mergedDelta = mergeBoundElements(prevDelta, nextDelta);
15698
+ delete this.removed[id];
15699
+ delete this.updated[id];
15700
+ this.added[id] = Delta.merge(prevDelta, nextDelta, mergedDelta);
15701
+ }
15702
+ }
15703
+ for (const [id, nextDelta] of Object.entries(removed)) {
15704
+ const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];
15705
+ if (!prevDelta) {
15706
+ this.removed[id] = nextDelta;
15707
+ } else {
15708
+ const mergedDelta = mergeBoundElements(prevDelta, nextDelta);
15709
+ delete this.added[id];
15710
+ delete this.updated[id];
15711
+ this.removed[id] = Delta.merge(prevDelta, nextDelta, mergedDelta);
15712
+ }
15713
+ }
15714
+ for (const [id, nextDelta] of Object.entries(updated)) {
15715
+ const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];
15716
+ if (!prevDelta) {
15717
+ this.updated[id] = nextDelta;
15718
+ } else {
15719
+ const mergedDelta = mergeBoundElements(prevDelta, nextDelta);
15720
+ const updatedDelta = Delta.merge(prevDelta, nextDelta, mergedDelta);
15721
+ if (prevDelta === this.added[id]) {
15722
+ this.added[id] = updatedDelta;
15723
+ } else if (prevDelta === this.removed[id]) {
15724
+ this.removed[id] = updatedDelta;
15725
+ } else {
15726
+ this.updated[id] = updatedDelta;
15727
+ }
15728
+ }
15729
+ }
15730
+ if (isTestEnv8() || isDevEnv7()) {
15731
+ _ElementsDelta.validate(this, "added", _ElementsDelta.satisfiesAddition);
15732
+ _ElementsDelta.validate(this, "removed", _ElementsDelta.satisfiesRemoval);
15733
+ _ElementsDelta.validate(this, "updated", _ElementsDelta.satisfiesUpdate);
15734
+ }
15735
+ return this;
15736
+ }
15737
+ static createApplier = (prevElements, nextElements, snapshot, flags, options) => (deltas) => {
15401
15738
  const getElement = _ElementsDelta.createGetter(
15402
15739
  nextElements,
15403
15740
  snapshot,
@@ -15406,14 +15743,20 @@ var ElementsDelta = class _ElementsDelta {
15406
15743
  return Object.entries(deltas).reduce((acc, [id, delta]) => {
15407
15744
  const element = getElement(id, delta.inserted);
15408
15745
  if (element) {
15409
- const newElement2 = _ElementsDelta.applyDelta(
15746
+ const nextElement = _ElementsDelta.applyDelta(
15410
15747
  element,
15411
15748
  delta,
15412
- options,
15413
- flags
15749
+ flags,
15750
+ options
15414
15751
  );
15415
- nextElements.set(newElement2.id, newElement2);
15416
- acc.set(newElement2.id, newElement2);
15752
+ nextElements.set(nextElement.id, nextElement);
15753
+ acc.set(nextElement.id, nextElement);
15754
+ if (!flags.applyDirection) {
15755
+ const prevElement = prevElements.get(id);
15756
+ if (prevElement) {
15757
+ flags.applyDirection = prevElement.version > nextElement.version ? "backward" : "forward";
15758
+ }
15759
+ }
15417
15760
  }
15418
15761
  return acc;
15419
15762
  }, /* @__PURE__ */ new Map());
@@ -15438,13 +15781,13 @@ var ElementsDelta = class _ElementsDelta {
15438
15781
  }
15439
15782
  return element;
15440
15783
  };
15441
- static applyDelta(element, delta, options, flags) {
15784
+ static applyDelta(element, delta, flags, options) {
15442
15785
  const directlyApplicablePartial = {};
15443
15786
  for (const key of Object.keys(delta.inserted)) {
15444
15787
  if (key === "boundElements") {
15445
15788
  continue;
15446
15789
  }
15447
- if (options.excludedProperties.has(key)) {
15790
+ if (options?.excludedProperties?.has(key)) {
15448
15791
  continue;
15449
15792
  }
15450
15793
  const value = delta.inserted[key];
@@ -15472,7 +15815,7 @@ var ElementsDelta = class _ElementsDelta {
15472
15815
  if (!flags.containsZindexDifference) {
15473
15816
  flags.containsZindexDifference = delta.deleted.index !== delta.inserted.index;
15474
15817
  }
15475
- return newElementWith(element, directlyApplicablePartial);
15818
+ return newElementWith(element, directlyApplicablePartial, true);
15476
15819
  }
15477
15820
  /**
15478
15821
  * Check for visible changes regardless of whether they were removed, added or updated.
@@ -15497,25 +15840,32 @@ var ElementsDelta = class _ElementsDelta {
15497
15840
  *
15498
15841
  * @returns all elements affected by the conflict resolution
15499
15842
  */
15500
- resolveConflicts(prevElements, nextElements) {
15843
+ resolveConflicts(prevElements, nextElements, applyDirection = "forward") {
15501
15844
  const nextAffectedElements = /* @__PURE__ */ new Map();
15502
15845
  const updater = (element, updates) => {
15503
15846
  const nextElement = nextElements.get(element.id);
15504
15847
  if (!nextElement) {
15505
15848
  return;
15506
15849
  }
15850
+ const prevElement = prevElements.get(element.id);
15851
+ const nextVersion = applyDirection === "forward" ? nextElement.version + 1 : nextElement.version - 1;
15852
+ const elementUpdates = updates;
15507
15853
  let affectedElement;
15508
- if (prevElements.get(element.id) === nextElement) {
15854
+ if (prevElement === nextElement) {
15509
15855
  affectedElement = newElementWith(
15510
15856
  nextElement,
15511
- updates
15857
+ {
15858
+ ...elementUpdates,
15859
+ version: nextVersion
15860
+ },
15861
+ true
15512
15862
  );
15513
15863
  } else {
15514
- affectedElement = mutateElement(
15515
- nextElement,
15516
- nextElements,
15517
- updates
15518
- );
15864
+ affectedElement = mutateElement(nextElement, nextElements, {
15865
+ ...elementUpdates,
15866
+ // don't modify the version further, if it's already different
15867
+ version: prevElement?.version !== nextElement.version ? nextElement.version : nextVersion
15868
+ });
15519
15869
  }
15520
15870
  nextAffectedElements.set(affectedElement.id, affectedElement);
15521
15871
  nextElements.set(affectedElement.id, affectedElement);
@@ -15540,19 +15890,10 @@ var ElementsDelta = class _ElementsDelta {
15540
15890
  const prevAffectedElements = new Map(
15541
15891
  Array.from(prevElements).filter(([id]) => nextAffectedElements.has(id))
15542
15892
  );
15543
- const { added, removed, updated } = _ElementsDelta.calculate(
15544
- prevAffectedElements,
15545
- nextAffectedElements
15893
+ this.squash(
15894
+ // technically we could do better here if perf. would become an issue
15895
+ _ElementsDelta.calculate(prevAffectedElements, nextAffectedElements)
15546
15896
  );
15547
- for (const [id, delta] of Object.entries(added)) {
15548
- this.added[id] = delta;
15549
- }
15550
- for (const [id, delta] of Object.entries(removed)) {
15551
- this.removed[id] = delta;
15552
- }
15553
- for (const [id, delta] of Object.entries(updated)) {
15554
- this.updated[id] = delta;
15555
- }
15556
15897
  return nextAffectedElements;
15557
15898
  }
15558
15899
  /**
@@ -15587,6 +15928,20 @@ var ElementsDelta = class _ElementsDelta {
15587
15928
  );
15588
15929
  BindableElement.rebindAffected(nextElements, nextElement(), updater);
15589
15930
  }
15931
+ static redrawElements(nextElements, changedElements) {
15932
+ try {
15933
+ const tempScene = new Scene(nextElements, { skipValidation: true });
15934
+ _ElementsDelta.redrawTextBoundingBoxes(tempScene, changedElements);
15935
+ _ElementsDelta.redrawBoundArrows(tempScene, changedElements);
15936
+ } catch (e) {
15937
+ console.error(`Couldn't redraw elements`, e);
15938
+ if (isTestEnv8() || isDevEnv7()) {
15939
+ throw e;
15940
+ }
15941
+ } finally {
15942
+ return nextElements;
15943
+ }
15944
+ }
15590
15945
  static redrawTextBoundingBoxes(scene, changed) {
15591
15946
  const elements = scene.getNonDeletedElementsMap();
15592
15947
  const boxesToRedraw = /* @__PURE__ */ new Map();
@@ -15679,10 +16034,14 @@ var ElementsDelta = class _ElementsDelta {
15679
16034
 
15680
16035
  // src/distribute.ts
15681
16036
  init_define_import_meta_env();
15682
- var distributeElements = (selectedElements, elementsMap, distribution) => {
16037
+ var distributeElements = (selectedElements, elementsMap, distribution, appState) => {
15683
16038
  const [start, mid, end, extent] = distribution.axis === "x" ? ["minX", "midX", "maxX", "width"] : ["minY", "midY", "maxY", "height"];
15684
16039
  const bounds = getCommonBoundingBox(selectedElements);
15685
- const groups = getMaximumGroups(selectedElements, elementsMap).map((group) => [group, getCommonBoundingBox(group)]).sort((a2, b2) => a2[1][mid] - b2[1][mid]);
16040
+ const groups = getSelectedElementsByGroup(
16041
+ selectedElements,
16042
+ elementsMap,
16043
+ appState
16044
+ ).map((group) => [group, getCommonBoundingBox(group)]).sort((a2, b2) => a2[1][mid] - b2[1][mid]);
15686
16045
  let span = 0;
15687
16046
  for (const group of groups) {
15688
16047
  span += group[1][extent];
@@ -16325,7 +16684,7 @@ var newImageElement = (opts) => {
16325
16684
 
16326
16685
  // src/embeddable.ts
16327
16686
  var embeddedLinkCache = /* @__PURE__ */ new Map();
16328
- var RE_YOUTUBE = /^(?:http(?:s)?:\/\/)?(?:www\.)?youtu(?:be\.com|\.be)\/(embed\/|watch\?v=|shorts\/|playlist\?list=|embed\/videoseries\?list=)?([a-zA-Z0-9_-]+)(?:\?t=|&t=|\?start=|&start=)?([a-zA-Z0-9_-]+)?[^\s]*$/;
16687
+ var RE_YOUTUBE = /^(?:http(?:s)?:\/\/)?(?:www\.)?youtu(?:be\.com|\.be)\/(embed\/|watch\?v=|shorts\/|playlist\?list=|embed\/videoseries\?list=)?([a-zA-Z0-9_-]+)/;
16329
16688
  var RE_VIMEO = /^(?:http(?:s)?:\/\/)?(?:(?:w){3}\.)?(?:player\.)?vimeo\.com\/(?:video\/)?([^?\s]+)(?:\?.*)?$/;
16330
16689
  var RE_FIGMA = /^https:\/\/(?:www\.)?figma\.com/;
16331
16690
  var RE_GH_GIST = /^https:\/\/gist\.github\.com\/([\w_-]+)\/([\w_-]+)/;
@@ -16338,6 +16697,28 @@ var RE_GENERIC_EMBED = /^<(?:iframe|blockquote)[\s\S]*?\s(?:src|href)=["']([^"']
16338
16697
  var RE_GIPHY = /giphy.com\/(?:clips|embed|gifs)\/[a-zA-Z0-9]*?-?([a-zA-Z0-9]+)(?:[^a-zA-Z0-9]|$)/;
16339
16698
  var RE_REDDIT = /^(?:http(?:s)?:\/\/)?(?:www\.)?reddit\.com\/r\/([a-zA-Z0-9_]+)\/comments\/([a-zA-Z0-9_]+)\/([a-zA-Z0-9_]+)\/?(?:\?[^#\s]*)?(?:#[^\s]*)?$/;
16340
16699
  var RE_REDDIT_EMBED = /^<blockquote[\s\S]*?\shref=["'](https?:\/\/(?:www\.)?reddit\.com\/[^"']*)/i;
16700
+ var parseYouTubeTimestamp = (url) => {
16701
+ let timeParam;
16702
+ try {
16703
+ const urlObj = new URL(url.startsWith("http") ? url : `https://${url}`);
16704
+ timeParam = urlObj.searchParams.get("t") || urlObj.searchParams.get("start");
16705
+ } catch (error) {
16706
+ const timeMatch2 = url.match(/[?&#](?:t|start)=([^&#\s]+)/);
16707
+ timeParam = timeMatch2?.[1];
16708
+ }
16709
+ if (!timeParam) {
16710
+ return 0;
16711
+ }
16712
+ if (/^\d+$/.test(timeParam)) {
16713
+ return parseInt(timeParam, 10);
16714
+ }
16715
+ const timeMatch = timeParam.match(/^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/);
16716
+ if (!timeMatch) {
16717
+ return 0;
16718
+ }
16719
+ const [, hours = "0", minutes = "0", seconds = "0"] = timeMatch;
16720
+ return parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseInt(seconds);
16721
+ };
16341
16722
  var ALLOWED_DOMAINS = /* @__PURE__ */ new Set([
16342
16723
  "youtube.com",
16343
16724
  "youtu.be",
@@ -16386,7 +16767,8 @@ var getEmbedLink = (link) => {
16386
16767
  let aspectRatio = { w: 560, h: 840 };
16387
16768
  const ytLink = link.match(RE_YOUTUBE);
16388
16769
  if (ytLink?.[2]) {
16389
- const time = ytLink[3] ? `&start=${ytLink[3]}` : ``;
16770
+ const startTime = parseYouTubeTimestamp(originalLink);
16771
+ const time = startTime > 0 ? `&start=${startTime}` : ``;
16390
16772
  const isPortrait = link.includes("shorts");
16391
16773
  type = "video";
16392
16774
  switch (ytLink[1]) {
@@ -16651,8 +17033,8 @@ var embeddableURLValidator = (url, validateEmbeddable) => {
16651
17033
 
16652
17034
  // src/flowchart.ts
16653
17035
  init_define_import_meta_env();
16654
- import { KEYS as KEYS3, invariant as invariant8, toBrandedType as toBrandedType2 } from "@excalidraw/common";
16655
- import { pointFrom as pointFrom13 } from "@excalidraw/math";
17036
+ import { KEYS as KEYS3, invariant as invariant9, toBrandedType as toBrandedType2 } from "@excalidraw/common";
17037
+ import { pointFrom as pointFrom15 } from "@excalidraw/math";
16656
17038
  var VERTICAL_OFFSET = 100;
16657
17039
  var HORIZONTAL_OFFSET = 100;
16658
17040
  var getLinkDirectionFromKey = (key) => {
@@ -16681,7 +17063,7 @@ var getNodeRelatives = (type, node, elementsMap, direction) => {
16681
17063
  if (!relative) {
16682
17064
  return acc;
16683
17065
  }
16684
- invariant8(
17066
+ invariant9(
16685
17067
  isBindableElement(relative),
16686
17068
  "not an ExcalidrawBindableElement"
16687
17069
  );
@@ -16797,7 +17179,7 @@ var addNewNode = (element, appState, direction, scene) => {
16797
17179
  fillStyle: element.fillStyle,
16798
17180
  strokeStyle: element.strokeStyle
16799
17181
  });
16800
- invariant8(
17182
+ invariant9(
16801
17183
  isFlowchartNodeElement(nextNode),
16802
17184
  "not an ExcalidrawFlowchartNodeElement"
16803
17185
  );
@@ -16855,7 +17237,7 @@ var addNewNodes = (startNode, appState, direction, scene, numberOfNodes) => {
16855
17237
  fillStyle: startNode.fillStyle,
16856
17238
  strokeStyle: startNode.strokeStyle
16857
17239
  });
16858
- invariant8(
17240
+ invariant9(
16859
17241
  isFlowchartNodeElement(nextNode),
16860
17242
  "not an ExcalidrawFlowchartNodeElement"
16861
17243
  );
@@ -16932,7 +17314,7 @@ var createBindingArrow = (startBindingElement, endBindingElement, direction, app
16932
17314
  strokeWidth: startBindingElement.strokeWidth,
16933
17315
  opacity: startBindingElement.opacity,
16934
17316
  roughness: startBindingElement.roughness,
16935
- points: [pointFrom13(0, 0), pointFrom13(endX, endY)],
17317
+ points: [pointFrom15(0, 0), pointFrom15(endX, endY)],
16936
17318
  elbowed: true
16937
17319
  });
16938
17320
  const elementsMap = scene.getNonDeletedElementsMap();
@@ -17081,7 +17463,7 @@ var FlowChartCreator = class {
17081
17463
  }
17082
17464
  if (startNode.frameId) {
17083
17465
  const frame = elementsMap.get(startNode.frameId);
17084
- invariant8(
17466
+ invariant9(
17085
17467
  frame && isFrameElement(frame),
17086
17468
  "not an ExcalidrawFrameElement"
17087
17469
  );
@@ -17216,13 +17598,80 @@ var normalizeSVG = (SVGString) => {
17216
17598
  }
17217
17599
  };
17218
17600
 
17601
+ // src/positionElementsOnGrid.ts
17602
+ init_define_import_meta_env();
17603
+ var positionElementsOnGrid = (elements, centerX, centerY, padding = 50) => {
17604
+ if (!elements || elements.length === 0) {
17605
+ return [];
17606
+ }
17607
+ const res = [];
17608
+ const atomicUnits = Array.isArray(elements[0]) ? elements : elements.map((element) => [element]);
17609
+ const numUnits = atomicUnits.length;
17610
+ const numColumns = Math.max(1, Math.ceil(Math.sqrt(numUnits)));
17611
+ const rows = [];
17612
+ for (let i = 0; i < numUnits; i += numColumns) {
17613
+ rows.push(atomicUnits.slice(i, i + numColumns));
17614
+ }
17615
+ let totalGridActualHeight = 0;
17616
+ const rowProperties = rows.map((rowUnits) => {
17617
+ let rowWidth = 0;
17618
+ let maxUnitHeightInRow = 0;
17619
+ const unitBounds = rowUnits.map((unit) => {
17620
+ const [minX, minY, maxX, maxY] = getCommonBounds(unit);
17621
+ return {
17622
+ elements: unit,
17623
+ bounds: [minX, minY, maxX, maxY],
17624
+ width: maxX - minX,
17625
+ height: maxY - minY
17626
+ };
17627
+ });
17628
+ unitBounds.forEach((unitBound, index) => {
17629
+ rowWidth += unitBound.width;
17630
+ if (index < unitBounds.length - 1) {
17631
+ rowWidth += padding;
17632
+ }
17633
+ if (unitBound.height > maxUnitHeightInRow) {
17634
+ maxUnitHeightInRow = unitBound.height;
17635
+ }
17636
+ });
17637
+ totalGridActualHeight += maxUnitHeightInRow;
17638
+ return {
17639
+ unitBounds,
17640
+ width: rowWidth,
17641
+ maxHeight: maxUnitHeightInRow
17642
+ };
17643
+ });
17644
+ const totalGridHeightWithPadding = totalGridActualHeight + Math.max(0, rows.length - 1) * padding;
17645
+ let currentY = centerY - totalGridHeightWithPadding / 2;
17646
+ rowProperties.forEach((rowProp) => {
17647
+ const { unitBounds, width: rowWidth, maxHeight: rowMaxHeight } = rowProp;
17648
+ let currentX = centerX - rowWidth / 2;
17649
+ unitBounds.forEach((unitBound) => {
17650
+ const [originalMinX, originalMinY] = unitBound.bounds;
17651
+ const offsetX = currentX - originalMinX;
17652
+ const offsetY = currentY - originalMinY;
17653
+ unitBound.elements.forEach((element) => {
17654
+ res.push(
17655
+ newElementWith(element, {
17656
+ x: element.x + offsetX,
17657
+ y: element.y + offsetY
17658
+ })
17659
+ );
17660
+ });
17661
+ currentX += unitBound.width + padding;
17662
+ });
17663
+ currentY += rowMaxHeight + padding;
17664
+ });
17665
+ return res;
17666
+ };
17667
+
17219
17668
  // src/resizeElements.ts
17220
17669
  init_define_import_meta_env();
17221
17670
  import {
17222
17671
  pointCenter as pointCenter3,
17223
17672
  normalizeRadians as normalizeRadians2,
17224
- pointFrom as pointFrom14,
17225
- pointRotateRads as pointRotateRads11
17673
+ pointFrom as pointFrom16,
17674
+ pointRotateRads as pointRotateRads13
17226
17675
  } from "@excalidraw/math";
17227
17676
  import {
17228
17677
  MIN_FONT_SIZE,
@@ -17350,7 +17799,16 @@ var rotateSingleElement = (element, scene, pointerX, pointerY, shouldRotateWithD
17350
17799
  if (boundTextElementId) {
17351
17800
  const textElement = scene.getElement(boundTextElementId);
17352
17801
  if (textElement && !isArrowElement(element)) {
17353
- scene.mutateElement(textElement, { angle });
17802
+ const { x, y } = computeBoundTextPosition(
17803
+ element,
17804
+ textElement,
17805
+ scene.getNonDeletedElementsMap()
17806
+ );
17807
+ scene.mutateElement(textElement, {
17808
+ angle,
17809
+ x,
17810
+ y
17811
+ });
17354
17812
  }
17355
17813
  }
17356
17814
  };
@@ -17387,7 +17845,7 @@ var resizeSingleTextElement = (origElement, element, scene, transformHandleType,
17387
17845
  return;
17388
17846
  }
17389
17847
  if (transformHandleType.includes("n") || transformHandleType.includes("s")) {
17390
- const previousOrigin = pointFrom14(origElement.x, origElement.y);
17848
+ const previousOrigin = pointFrom16(origElement.x, origElement.y);
17391
17849
  const newOrigin = getResizedOrigin(
17392
17850
  previousOrigin,
17393
17851
  origElement.width,
@@ -17428,7 +17886,7 @@ var resizeSingleTextElement = (origElement, element, scene, transformHandleType,
17428
17886
  element.lineHeight
17429
17887
  );
17430
17888
  const newHeight = metrics2.height;
17431
- const previousOrigin = pointFrom14(origElement.x, origElement.y);
17889
+ const previousOrigin = pointFrom16(origElement.x, origElement.y);
17432
17890
  const newOrigin = getResizedOrigin(
17433
17891
  previousOrigin,
17434
17892
  origElement.width,
@@ -17464,9 +17922,9 @@ var rotateMultipleElements = (originalElements, elements, scene, pointerX, point
17464
17922
  const cx = (x1 + x2) / 2;
17465
17923
  const cy = (y1 + y2) / 2;
17466
17924
  const origAngle = originalElements.get(element.id)?.angle ?? element.angle;
17467
- const [rotatedCX, rotatedCY] = pointRotateRads11(
17468
- pointFrom14(cx, cy),
17469
- pointFrom14(centerX, centerY),
17925
+ const [rotatedCX, rotatedCY] = pointRotateRads13(
17926
+ pointFrom16(cx, cy),
17927
+ pointFrom16(centerX, centerY),
17470
17928
  centerAngle + origAngle - element.angle
17471
17929
  );
17472
17930
  const updates = isElbowArrow(element) ? {
@@ -17483,9 +17941,14 @@ var rotateMultipleElements = (originalElements, elements, scene, pointerX, point
17483
17941
  });
17484
17942
  const boundText = getBoundTextElement(element, elementsMap);
17485
17943
  if (boundText && !isArrowElement(element)) {
17944
+ const { x, y } = computeBoundTextPosition(
17945
+ element,
17946
+ boundText,
17947
+ elementsMap
17948
+ );
17486
17949
  scene.mutateElement(boundText, {
17487
- x: boundText.x + (rotatedCX - cx),
17488
- y: boundText.y + (rotatedCY - cy),
17950
+ x,
17951
+ y,
17489
17952
  angle: normalizeRadians2(centerAngle + origAngle)
17490
17953
  });
17491
17954
  }
@@ -17498,44 +17961,44 @@ var getResizeOffsetXY = (transformHandleType, selectedElements, elementsMap, x,
17498
17961
  const cx = (x1 + x2) / 2;
17499
17962
  const cy = (y1 + y2) / 2;
17500
17963
  const angle = selectedElements.length === 1 ? selectedElements[0].angle : 0;
17501
- [x, y] = pointRotateRads11(
17502
- pointFrom14(x, y),
17503
- pointFrom14(cx, cy),
17964
+ [x, y] = pointRotateRads13(
17965
+ pointFrom16(x, y),
17966
+ pointFrom16(cx, cy),
17504
17967
  -angle
17505
17968
  );
17506
17969
  switch (transformHandleType) {
17507
17970
  case "n":
17508
- return pointRotateRads11(
17509
- pointFrom14(x - (x1 + x2) / 2, y - y1),
17510
- pointFrom14(0, 0),
17971
+ return pointRotateRads13(
17972
+ pointFrom16(x - (x1 + x2) / 2, y - y1),
17973
+ pointFrom16(0, 0),
17511
17974
  angle
17512
17975
  );
17513
17976
  case "s":
17514
- return pointRotateRads11(
17515
- pointFrom14(x - (x1 + x2) / 2, y - y2),
17516
- pointFrom14(0, 0),
17977
+ return pointRotateRads13(
17978
+ pointFrom16(x - (x1 + x2) / 2, y - y2),
17979
+ pointFrom16(0, 0),
17517
17980
  angle
17518
17981
  );
17519
17982
  case "w":
17520
- return pointRotateRads11(
17521
- pointFrom14(x - x1, y - (y1 + y2) / 2),
17522
- pointFrom14(0, 0),
17983
+ return pointRotateRads13(
17984
+ pointFrom16(x - x1, y - (y1 + y2) / 2),
17985
+ pointFrom16(0, 0),
17523
17986
  angle
17524
17987
  );
17525
17988
  case "e":
17526
- return pointRotateRads11(
17527
- pointFrom14(x - x2, y - (y1 + y2) / 2),
17528
- pointFrom14(0, 0),
17989
+ return pointRotateRads13(
17990
+ pointFrom16(x - x2, y - (y1 + y2) / 2),
17991
+ pointFrom16(0, 0),
17529
17992
  angle
17530
17993
  );
17531
17994
  case "nw":
17532
- return pointRotateRads11(pointFrom14(x - x1, y - y1), pointFrom14(0, 0), angle);
17995
+ return pointRotateRads13(pointFrom16(x - x1, y - y1), pointFrom16(0, 0), angle);
17533
17996
  case "ne":
17534
- return pointRotateRads11(pointFrom14(x - x2, y - y1), pointFrom14(0, 0), angle);
17997
+ return pointRotateRads13(pointFrom16(x - x2, y - y1), pointFrom16(0, 0), angle);
17535
17998
  case "sw":
17536
- return pointRotateRads11(pointFrom14(x - x1, y - y2), pointFrom14(0, 0), angle);
17999
+ return pointRotateRads13(pointFrom16(x - x1, y - y2), pointFrom16(0, 0), angle);
17537
18000
  case "se":
17538
- return pointRotateRads11(pointFrom14(x - x2, y - y2), pointFrom14(0, 0), angle);
18001
+ return pointRotateRads13(pointFrom16(x - x2, y - y2), pointFrom16(0, 0), angle);
17539
18002
  default:
17540
18003
  return [0, 0];
17541
18004
  }
@@ -17698,10 +18161,10 @@ var resizeSingleElement = (nextWidth, nextHeight, latestElement, origElement, or
17698
18161
  nextHeight,
17699
18162
  true
17700
18163
  );
17701
- let previousOrigin = pointFrom14(origElement.x, origElement.y);
18164
+ let previousOrigin = pointFrom16(origElement.x, origElement.y);
17702
18165
  if (isLinearElement(origElement)) {
17703
18166
  const [x1, y1] = getElementBounds(origElement, originalElementsMap);
17704
- previousOrigin = pointFrom14(x1, y1);
18167
+ previousOrigin = pointFrom16(x1, y1);
17705
18168
  }
17706
18169
  const newOrigin = getResizedOrigin(
17707
18170
  previousOrigin,
@@ -17724,7 +18187,7 @@ var resizeSingleElement = (nextWidth, nextHeight, latestElement, origElement, or
17724
18187
  newOrigin.x += scaledX;
17725
18188
  newOrigin.y += scaledY;
17726
18189
  rescaledPoints.points = rescaledPoints.points.map(
17727
- (p) => pointFrom14(p[0] - scaledX, p[1] - scaledY)
18190
+ (p) => pointFrom16(p[0] - scaledX, p[1] - scaledY)
17728
18191
  );
17729
18192
  }
17730
18193
  if (nextWidth < 0) {
@@ -17787,11 +18250,11 @@ var getNextSingleWidthAndHeightFromPointer = (latestElement, origElement, handle
17787
18250
  origElement.height,
17788
18251
  true
17789
18252
  );
17790
- const startTopLeft = pointFrom14(x1, y1);
17791
- const startBottomRight = pointFrom14(x2, y2);
18253
+ const startTopLeft = pointFrom16(x1, y1);
18254
+ const startBottomRight = pointFrom16(x2, y2);
17792
18255
  const startCenter = pointCenter3(startTopLeft, startBottomRight);
17793
- const rotatedPointer = pointRotateRads11(
17794
- pointFrom14(pointerX, pointerY),
18256
+ const rotatedPointer = pointRotateRads13(
18257
+ pointFrom16(pointerX, pointerY),
17795
18258
  startCenter,
17796
18259
  -origElement.angle
17797
18260
  );
@@ -18149,20 +18612,20 @@ var resizeMultipleElements = (selectedElements, elementsMap, handleDirection, sc
18149
18612
  // src/resizeTest.ts
18150
18613
  init_define_import_meta_env();
18151
18614
  import {
18152
- pointFrom as pointFrom16,
18615
+ pointFrom as pointFrom18,
18153
18616
  pointOnLineSegment,
18154
- pointRotateRads as pointRotateRads13
18617
+ pointRotateRads as pointRotateRads15
18155
18618
  } from "@excalidraw/math";
18156
- import { SIDE_RESIZING_THRESHOLD } from "@excalidraw/common";
18619
+ import {
18620
+ SIDE_RESIZING_THRESHOLD
18621
+ } from "@excalidraw/common";
18157
18622
 
18158
18623
  // src/transformHandles.ts
18159
18624
  init_define_import_meta_env();
18160
18625
  import {
18161
- DEFAULT_TRANSFORM_HANDLE_SPACING,
18162
- isAndroid,
18163
- isIOS
18626
+ DEFAULT_TRANSFORM_HANDLE_SPACING
18164
18627
  } from "@excalidraw/common";
18165
- import { pointFrom as pointFrom15, pointRotateRads as pointRotateRads12 } from "@excalidraw/math";
18628
+ import { pointFrom as pointFrom17, pointRotateRads as pointRotateRads14 } from "@excalidraw/math";
18166
18629
  var transformHandleSizes = {
18167
18630
  mouse: 8,
18168
18631
  pen: 16,
@@ -18203,24 +18666,21 @@ var OMIT_SIDES_FOR_LINE_BACKSLASH = {
18203
18666
  w: true
18204
18667
  };
18205
18668
  var generateTransformHandle = (x, y, width, height, cx, cy, angle) => {
18206
- const [xx, yy] = pointRotateRads12(
18207
- pointFrom15(x + width / 2, y + height / 2),
18208
- pointFrom15(cx, cy),
18669
+ const [xx, yy] = pointRotateRads14(
18670
+ pointFrom17(x + width / 2, y + height / 2),
18671
+ pointFrom17(cx, cy),
18209
18672
  angle
18210
18673
  );
18211
18674
  return [xx - width / 2, yy - height / 2, width, height];
18212
18675
  };
18213
- var canResizeFromSides = (device) => {
18214
- if (device.viewport.isMobile) {
18215
- return false;
18216
- }
18217
- if (device.isTouchScreen && (isAndroid || isIOS)) {
18676
+ var canResizeFromSides = (editorInterface) => {
18677
+ if (editorInterface.formFactor === "phone" && editorInterface.userAgent.isMobileDevice) {
18218
18678
  return false;
18219
18679
  }
18220
18680
  return true;
18221
18681
  };
18222
- var getOmitSidesForDevice = (device) => {
18223
- if (canResizeFromSides(device)) {
18682
+ var getOmitSidesForEditorInterface = (editorInterface) => {
18683
+ if (canResizeFromSides(editorInterface)) {
18224
18684
  return DEFAULT_OMIT_SIDES;
18225
18685
  }
18226
18686
  return {};
@@ -18370,8 +18830,8 @@ var getTransformHandles = (element, zoom, elementsMap, pointerType = "mouse", om
18370
18830
  isImageElement(element) ? 0 : void 0
18371
18831
  );
18372
18832
  };
18373
- var shouldShowBoundingBox = (elements, appState) => {
18374
- if (appState.editingLinearElement) {
18833
+ var hasBoundingBox = (elements, appState, editorInterface) => {
18834
+ if (appState.selectedLinearElement?.isEditing) {
18375
18835
  return false;
18376
18836
  }
18377
18837
  if (elements.length > 1) {
@@ -18384,12 +18844,12 @@ var shouldShowBoundingBox = (elements, appState) => {
18384
18844
  if (!isLinearElement(element)) {
18385
18845
  return true;
18386
18846
  }
18387
- return element.points.length > 2;
18847
+ return element.points.length > 2 && !editorInterface.userAgent.isMobileDevice;
18388
18848
  };
18389
18849
 
18390
18850
  // src/resizeTest.ts
18391
18851
  var isInsideTransformHandle = (transformHandle, x, y) => x >= transformHandle[0] && x <= transformHandle[0] + transformHandle[2] && y >= transformHandle[1] && y <= transformHandle[1] + transformHandle[3];
18392
- var resizeTest = (element, elementsMap, appState, x, y, zoom, pointerType, device) => {
18852
+ var resizeTest = (element, elementsMap, appState, x, y, zoom, pointerType, editorInterface) => {
18393
18853
  if (!appState.selectedElementIds[element.id]) {
18394
18854
  return false;
18395
18855
  }
@@ -18398,7 +18858,7 @@ var resizeTest = (element, elementsMap, appState, x, y, zoom, pointerType, devic
18398
18858
  zoom,
18399
18859
  elementsMap,
18400
18860
  pointerType,
18401
- getOmitSidesForDevice(device)
18861
+ getOmitSidesForEditorInterface(editorInterface)
18402
18862
  );
18403
18863
  if (rotationTransformHandle && isInsideTransformHandle(rotationTransformHandle, x, y)) {
18404
18864
  return "rotation";
@@ -18413,7 +18873,7 @@ var resizeTest = (element, elementsMap, appState, x, y, zoom, pointerType, devic
18413
18873
  if (filter.length > 0) {
18414
18874
  return filter[0];
18415
18875
  }
18416
- if (canResizeFromSides(device)) {
18876
+ if (canResizeFromSides(editorInterface)) {
18417
18877
  const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords2(
18418
18878
  element,
18419
18879
  elementsMap
@@ -18422,14 +18882,14 @@ var resizeTest = (element, elementsMap, appState, x, y, zoom, pointerType, devic
18422
18882
  const SPACING = isImageElement(element) ? 0 : SIDE_RESIZING_THRESHOLD / zoom.value;
18423
18883
  const ZOOMED_SIDE_RESIZING_THRESHOLD = SIDE_RESIZING_THRESHOLD / zoom.value;
18424
18884
  const sides = getSelectionBorders(
18425
- pointFrom16(x1 - SPACING, y1 - SPACING),
18426
- pointFrom16(x2 + SPACING, y2 + SPACING),
18427
- pointFrom16(cx, cy),
18885
+ pointFrom18(x1 - SPACING, y1 - SPACING),
18886
+ pointFrom18(x2 + SPACING, y2 + SPACING),
18887
+ pointFrom18(cx, cy),
18428
18888
  element.angle
18429
18889
  );
18430
18890
  for (const [dir, side] of Object.entries(sides)) {
18431
18891
  if (pointOnLineSegment(
18432
- pointFrom16(x, y),
18892
+ pointFrom18(x, y),
18433
18893
  side,
18434
18894
  ZOOMED_SIDE_RESIZING_THRESHOLD
18435
18895
  )) {
@@ -18440,7 +18900,7 @@ var resizeTest = (element, elementsMap, appState, x, y, zoom, pointerType, devic
18440
18900
  }
18441
18901
  return false;
18442
18902
  };
18443
- var getElementWithTransformHandleType = (elements, appState, scenePointerX, scenePointerY, zoom, pointerType, elementsMap, device) => {
18903
+ var getElementWithTransformHandleType = (elements, appState, scenePointerX, scenePointerY, zoom, pointerType, elementsMap, editorInterface) => {
18444
18904
  return elements.reduce((result, element) => {
18445
18905
  if (result) {
18446
18906
  return result;
@@ -18453,18 +18913,18 @@ var getElementWithTransformHandleType = (elements, appState, scenePointerX, scen
18453
18913
  scenePointerY,
18454
18914
  zoom,
18455
18915
  pointerType,
18456
- device
18916
+ editorInterface
18457
18917
  );
18458
18918
  return transformHandleType ? { element, transformHandleType } : null;
18459
18919
  }, null);
18460
18920
  };
18461
- var getTransformHandleTypeFromCoords = ([x1, y1, x2, y2], scenePointerX, scenePointerY, zoom, pointerType, device) => {
18921
+ var getTransformHandleTypeFromCoords = ([x1, y1, x2, y2], scenePointerX, scenePointerY, zoom, pointerType, editorInterface) => {
18462
18922
  const transformHandles = getTransformHandlesFromCoords(
18463
18923
  [x1, y1, x2, y2, (x1 + x2) / 2, (y1 + y2) / 2],
18464
18924
  0,
18465
18925
  zoom,
18466
18926
  pointerType,
18467
- getOmitSidesForDevice(device)
18927
+ getOmitSidesForEditorInterface(editorInterface)
18468
18928
  );
18469
18929
  const found = Object.keys(transformHandles).find((key) => {
18470
18930
  const transformHandle = transformHandles[key];
@@ -18473,19 +18933,19 @@ var getTransformHandleTypeFromCoords = ([x1, y1, x2, y2], scenePointerX, scenePo
18473
18933
  if (found) {
18474
18934
  return found;
18475
18935
  }
18476
- if (canResizeFromSides(device)) {
18936
+ if (canResizeFromSides(editorInterface)) {
18477
18937
  const cx = (x1 + x2) / 2;
18478
18938
  const cy = (y1 + y2) / 2;
18479
18939
  const SPACING = SIDE_RESIZING_THRESHOLD / zoom.value;
18480
18940
  const sides = getSelectionBorders(
18481
- pointFrom16(x1 - SPACING, y1 - SPACING),
18482
- pointFrom16(x2 + SPACING, y2 + SPACING),
18483
- pointFrom16(cx, cy),
18941
+ pointFrom18(x1 - SPACING, y1 - SPACING),
18942
+ pointFrom18(x2 + SPACING, y2 + SPACING),
18943
+ pointFrom18(cx, cy),
18484
18944
  0
18485
18945
  );
18486
18946
  for (const [dir, side] of Object.entries(sides)) {
18487
18947
  if (pointOnLineSegment(
18488
- pointFrom16(scenePointerX, scenePointerY),
18948
+ pointFrom18(scenePointerX, scenePointerY),
18489
18949
  side,
18490
18950
  SPACING
18491
18951
  )) {
@@ -18542,10 +19002,10 @@ var getCursorForResizingElement = (resizingElement) => {
18542
19002
  return cursor ? `${cursor}-resize` : "";
18543
19003
  };
18544
19004
  var getSelectionBorders = ([x1, y1], [x2, y2], center, angle) => {
18545
- const topLeft = pointRotateRads13(pointFrom16(x1, y1), center, angle);
18546
- const topRight = pointRotateRads13(pointFrom16(x2, y1), center, angle);
18547
- const bottomLeft = pointRotateRads13(pointFrom16(x1, y2), center, angle);
18548
- const bottomRight = pointRotateRads13(pointFrom16(x2, y2), center, angle);
19005
+ const topLeft = pointRotateRads15(pointFrom18(x1, y1), center, angle);
19006
+ const topRight = pointRotateRads15(pointFrom18(x2, y1), center, angle);
19007
+ const bottomLeft = pointRotateRads15(pointFrom18(x1, y2), center, angle);
19008
+ const bottomRight = pointRotateRads15(pointFrom18(x2, y2), center, angle);
18549
19009
  return {
18550
19010
  n: [topLeft, topRight],
18551
19011
  e: [topRight, bottomRight],
@@ -19086,6 +19546,8 @@ export {
19086
19546
  getFrameLikeTitle,
19087
19547
  getFreeDrawPath2D,
19088
19548
  getFreeDrawSvgPath,
19549
+ getFreedrawOutlineAsSegments,
19550
+ getFreedrawOutlinePoints,
19089
19551
  getGlobalFixedPointForBindableElement,
19090
19552
  getGlobalFixedPoints,
19091
19553
  getHeadingForElbowArrowSnap,
@@ -19107,7 +19569,7 @@ export {
19107
19569
  getNonDeletedGroupIds,
19108
19570
  getNormalizedDimensions,
19109
19571
  getObservedAppState,
19110
- getOmitSidesForDevice,
19572
+ getOmitSidesForEditorInterface,
19111
19573
  getOriginalContainerHeightFromCache,
19112
19574
  getPerfectElementSize,
19113
19575
  getPredecessors,
@@ -19119,6 +19581,7 @@ export {
19119
19581
  getRootElements,
19120
19582
  getSceneVersion,
19121
19583
  getSelectedElements,
19584
+ getSelectedElementsByGroup,
19122
19585
  getSelectedGroupForElement,
19123
19586
  getSelectedGroupIdForElement,
19124
19587
  getSelectedGroupIds,
@@ -19144,6 +19607,7 @@ export {
19144
19607
  handleBindTextResize,
19145
19608
  hasBackground,
19146
19609
  hasBoundTextElement,
19610
+ hasBoundingBox,
19147
19611
  hasStrokeColor,
19148
19612
  hasStrokeStyle,
19149
19613
  hasStrokeWidth,
@@ -19250,6 +19714,7 @@ export {
19250
19714
  parseTokens,
19251
19715
  pathsCache,
19252
19716
  pointInsideBounds,
19717
+ positionElementsOnGrid,
19253
19718
  redrawTextBoundingBox,
19254
19719
  refreshTextDimensions,
19255
19720
  removeAllElementsFromFrame,
@@ -19271,7 +19736,6 @@ export {
19271
19736
  shouldAllowVerticalAlign,
19272
19737
  shouldApplyFrameClip,
19273
19738
  shouldEnableBindingForPointerEvent,
19274
- shouldShowBoundingBox,
19275
19739
  shouldTestInside,
19276
19740
  showSelectedShapeActions,
19277
19741
  snapToMid,