@excalidraw/excalidraw 0.17.1-c0b80a0 → 0.17.1-c329470

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 (178) hide show
  1. package/dist/browser/dev/excalidraw-assets-dev/{chunk-JGDL4H2X.js → chunk-3DLVY5XU.js} +8272 -6864
  2. package/dist/browser/dev/excalidraw-assets-dev/chunk-3DLVY5XU.js.map +7 -0
  3. package/dist/browser/dev/excalidraw-assets-dev/{chunk-V7NFEZA6.js → chunk-NOAEU4NM.js} +9 -2
  4. package/dist/browser/dev/excalidraw-assets-dev/chunk-NOAEU4NM.js.map +7 -0
  5. package/dist/browser/dev/excalidraw-assets-dev/{en-ZSVWGT55.js → en-7IBTMWBG.js} +2 -2
  6. package/dist/browser/dev/excalidraw-assets-dev/{image-RJG3J34Y.js → image-N5AC7SEK.js} +2 -6
  7. package/dist/browser/dev/index.css +85 -50
  8. package/dist/browser/dev/index.css.map +3 -3
  9. package/dist/browser/dev/index.js +4375 -3766
  10. package/dist/browser/dev/index.js.map +4 -4
  11. package/dist/browser/prod/excalidraw-assets/{chunk-LDVEIXGO.js → chunk-7CSIPVOW.js} +2 -2
  12. package/dist/browser/prod/excalidraw-assets/chunk-TX3BU7T2.js +47 -0
  13. package/dist/browser/prod/excalidraw-assets/{en-UPNEHLDS.js → en-LOGQBETY.js} +1 -1
  14. package/dist/browser/prod/excalidraw-assets/image-3V4U7GZE.js +1 -0
  15. package/dist/browser/prod/index.css +1 -1
  16. package/dist/browser/prod/index.js +40 -40
  17. package/dist/dev/index.css +85 -50
  18. package/dist/dev/index.css.map +3 -3
  19. package/dist/dev/index.js +8688 -6706
  20. package/dist/dev/index.js.map +4 -4
  21. package/dist/{prod/locales/en-ZXYG7GCR.json → dev/locales/en-V6KXFSCK.json} +8 -1
  22. package/dist/excalidraw/actions/actionAlign.d.ts +7 -6
  23. package/dist/excalidraw/actions/actionAlign.js +14 -14
  24. package/dist/excalidraw/actions/actionClipboard.d.ts +7 -3
  25. package/dist/excalidraw/actions/actionDeleteSelected.d.ts +7 -3
  26. package/dist/excalidraw/actions/actionDeleteSelected.js +103 -34
  27. package/dist/excalidraw/actions/actionDuplicateSelection.js +105 -95
  28. package/dist/excalidraw/actions/actionFlip.js +16 -7
  29. package/dist/excalidraw/actions/actionFrame.d.ts +493 -0
  30. package/dist/excalidraw/actions/actionFrame.js +45 -2
  31. package/dist/excalidraw/actions/actionGroup.js +6 -4
  32. package/dist/excalidraw/actions/actionProperties.js +145 -116
  33. package/dist/excalidraw/actions/actionSelectAll.js +4 -3
  34. package/dist/excalidraw/actions/shortcuts.d.ts +1 -1
  35. package/dist/excalidraw/actions/shortcuts.js +1 -0
  36. package/dist/excalidraw/actions/types.d.ts +1 -1
  37. package/dist/excalidraw/align.d.ts +2 -1
  38. package/dist/excalidraw/align.js +15 -6
  39. package/dist/excalidraw/clipboard.d.ts +27 -5
  40. package/dist/excalidraw/clipboard.js +55 -28
  41. package/dist/excalidraw/components/Actions.d.ts +2 -1
  42. package/dist/excalidraw/components/Actions.js +4 -2
  43. package/dist/excalidraw/components/ActiveConfirmDialog.d.ts +1 -1
  44. package/dist/excalidraw/components/ActiveConfirmDialog.js +2 -3
  45. package/dist/excalidraw/components/App.d.ts +1 -0
  46. package/dist/excalidraw/components/App.js +216 -111
  47. package/dist/excalidraw/components/ColorPicker/ColorInput.js +2 -3
  48. package/dist/excalidraw/components/ColorPicker/ColorPicker.js +2 -3
  49. package/dist/excalidraw/components/ColorPicker/CustomColorList.js +1 -1
  50. package/dist/excalidraw/components/ColorPicker/Picker.js +1 -1
  51. package/dist/excalidraw/components/ColorPicker/PickerColorList.js +1 -1
  52. package/dist/excalidraw/components/ColorPicker/ShadeList.js +1 -1
  53. package/dist/excalidraw/components/ColorPicker/colorPickerUtils.d.ts +1 -1
  54. package/dist/excalidraw/components/ColorPicker/colorPickerUtils.js +1 -1
  55. package/dist/excalidraw/components/CommandPalette/CommandPalette.js +3 -3
  56. package/dist/excalidraw/components/ConfirmDialog.js +17 -5
  57. package/dist/excalidraw/components/Dialog.js +2 -3
  58. package/dist/excalidraw/components/EyeDropper.d.ts +1 -1
  59. package/dist/excalidraw/components/EyeDropper.js +1 -1
  60. package/dist/excalidraw/components/IconPicker.d.ts +2 -2
  61. package/dist/excalidraw/components/IconPicker.js +56 -53
  62. package/dist/excalidraw/components/LayerUI.js +6 -6
  63. package/dist/excalidraw/components/LibraryMenu.d.ts +2 -16
  64. package/dist/excalidraw/components/LibraryMenu.js +70 -28
  65. package/dist/excalidraw/components/LibraryMenuHeaderContent.js +4 -5
  66. package/dist/excalidraw/components/MobileMenu.js +1 -1
  67. package/dist/excalidraw/components/OverwriteConfirm/OverwriteConfirm.js +2 -3
  68. package/dist/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.d.ts +1 -1
  69. package/dist/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.js +2 -3
  70. package/dist/excalidraw/components/Range.d.ts +9 -0
  71. package/dist/excalidraw/components/Range.js +24 -0
  72. package/dist/excalidraw/components/SearchMenu.d.ts +1 -1
  73. package/dist/excalidraw/components/SearchMenu.js +3 -4
  74. package/dist/excalidraw/components/Sidebar/Sidebar.d.ts +1 -1
  75. package/dist/excalidraw/components/Sidebar/Sidebar.js +2 -3
  76. package/dist/excalidraw/components/Stats/Collapsible.d.ts +2 -1
  77. package/dist/excalidraw/components/Stats/Collapsible.js +2 -2
  78. package/dist/excalidraw/components/Stats/Dimension.js +94 -8
  79. package/dist/excalidraw/components/Stats/MultiDimension.js +8 -5
  80. package/dist/excalidraw/components/Stats/Position.js +63 -3
  81. package/dist/excalidraw/components/Stats/index.js +21 -4
  82. package/dist/excalidraw/components/Stats/utils.d.ts +1 -1
  83. package/dist/excalidraw/components/Stats/utils.js +2 -55
  84. package/dist/excalidraw/components/TTDDialog/TTDDialog.js +1 -1
  85. package/dist/excalidraw/components/ToolButton.js +4 -9
  86. package/dist/excalidraw/components/hoc/withInternalFallback.js +3 -3
  87. package/dist/excalidraw/components/hyperlink/Hyperlink.js +6 -12
  88. package/dist/excalidraw/components/icons.d.ts +9 -0
  89. package/dist/excalidraw/components/icons.js +4 -4
  90. package/dist/excalidraw/components/main-menu/DefaultItems.js +2 -3
  91. package/dist/excalidraw/constants.d.ts +5 -1
  92. package/dist/excalidraw/constants.js +9 -1
  93. package/dist/excalidraw/context/tunnels.d.ts +2 -1
  94. package/dist/excalidraw/context/tunnels.js +3 -1
  95. package/dist/excalidraw/data/blob.d.ts +1 -0
  96. package/dist/excalidraw/data/blob.js +7 -3
  97. package/dist/excalidraw/data/filesystem.d.ts +2 -1
  98. package/dist/excalidraw/data/filesystem.js +1 -0
  99. package/dist/excalidraw/data/image.d.ts +0 -6
  100. package/dist/excalidraw/data/image.js +1 -43
  101. package/dist/excalidraw/data/index.js +6 -6
  102. package/dist/excalidraw/data/library.d.ts +9 -3
  103. package/dist/excalidraw/data/library.js +43 -6
  104. package/dist/excalidraw/data/restore.js +26 -8
  105. package/dist/excalidraw/data/url.d.ts +0 -1
  106. package/dist/excalidraw/data/url.js +2 -4
  107. package/dist/excalidraw/editor-jotai.d.ts +56 -0
  108. package/dist/excalidraw/editor-jotai.js +8 -0
  109. package/dist/excalidraw/element/binding.d.ts +9 -6
  110. package/dist/excalidraw/element/binding.js +124 -44
  111. package/dist/excalidraw/element/bounds.js +10 -0
  112. package/dist/excalidraw/element/cropElement.d.ts +5 -0
  113. package/dist/excalidraw/element/cropElement.js +28 -1
  114. package/dist/excalidraw/element/dragElements.js +13 -7
  115. package/dist/excalidraw/element/elbowArrow.d.ts +16 -0
  116. package/dist/excalidraw/element/elbowArrow.js +1268 -0
  117. package/dist/excalidraw/element/embeddable.js +4 -5
  118. package/dist/excalidraw/element/flowchart.d.ts +1 -1
  119. package/dist/excalidraw/element/flowchart.js +25 -9
  120. package/dist/excalidraw/element/heading.d.ts +5 -1
  121. package/dist/excalidraw/element/heading.js +5 -1
  122. package/dist/excalidraw/element/image.js +19 -5
  123. package/dist/excalidraw/element/linearElementEditor.d.ts +9 -10
  124. package/dist/excalidraw/element/linearElementEditor.js +97 -38
  125. package/dist/excalidraw/element/mutateElement.d.ts +3 -1
  126. package/dist/excalidraw/element/mutateElement.js +31 -4
  127. package/dist/excalidraw/element/newElement.d.ts +8 -12
  128. package/dist/excalidraw/element/newElement.js +36 -21
  129. package/dist/excalidraw/element/resizeElements.d.ts +20 -5
  130. package/dist/excalidraw/element/resizeElements.js +593 -361
  131. package/dist/excalidraw/element/sortElements.js +1 -4
  132. package/dist/excalidraw/element/types.d.ts +23 -1
  133. package/dist/excalidraw/fonts/Fonts.d.ts +0 -16
  134. package/dist/excalidraw/fonts/Fonts.js +6 -31
  135. package/dist/excalidraw/frame.d.ts +11 -5
  136. package/dist/excalidraw/frame.js +146 -35
  137. package/dist/excalidraw/groups.js +3 -0
  138. package/dist/excalidraw/hooks/useLibraryItemSvg.d.ts +1 -1
  139. package/dist/excalidraw/hooks/useLibraryItemSvg.js +2 -3
  140. package/dist/excalidraw/hooks/useScrollPosition.js +1 -1
  141. package/dist/excalidraw/i18n.js +3 -4
  142. package/dist/excalidraw/index.js +3 -4
  143. package/dist/excalidraw/locales/en.json +8 -1
  144. package/dist/excalidraw/renderer/interactiveScene.js +43 -32
  145. package/dist/excalidraw/renderer/staticScene.js +6 -4
  146. package/dist/excalidraw/renderer/staticSvgScene.js +1 -1
  147. package/dist/excalidraw/scene/Shape.js +40 -17
  148. package/dist/excalidraw/scene/comparisons.d.ts +0 -477
  149. package/dist/excalidraw/scene/comparisons.js +0 -37
  150. package/dist/excalidraw/scene/export.d.ts +7 -0
  151. package/dist/excalidraw/scene/export.js +107 -43
  152. package/dist/excalidraw/scene/index.d.ts +1 -1
  153. package/dist/excalidraw/scene/index.js +1 -1
  154. package/dist/excalidraw/scene/selection.js +4 -1
  155. package/dist/excalidraw/types.d.ts +15 -0
  156. package/dist/excalidraw/utility-types.d.ts +1 -0
  157. package/dist/excalidraw/utils.d.ts +8 -1
  158. package/dist/excalidraw/utils.js +9 -0
  159. package/dist/excalidraw/visualdebug.d.ts +8 -1
  160. package/dist/excalidraw/visualdebug.js +3 -0
  161. package/dist/math/line.d.ts +19 -0
  162. package/dist/math/line.js +32 -3
  163. package/dist/math/point.d.ts +10 -0
  164. package/dist/math/point.js +12 -1
  165. package/dist/prod/index.css +1 -1
  166. package/dist/prod/index.js +29 -44
  167. package/dist/{dev/locales/en-ZXYG7GCR.json → prod/locales/en-V6KXFSCK.json} +8 -1
  168. package/package.json +5 -2
  169. package/dist/browser/dev/excalidraw-assets-dev/chunk-JGDL4H2X.js.map +0 -7
  170. package/dist/browser/dev/excalidraw-assets-dev/chunk-V7NFEZA6.js.map +0 -7
  171. package/dist/browser/prod/excalidraw-assets/chunk-S2XKB3DE.js +0 -62
  172. package/dist/browser/prod/excalidraw-assets/image-OFI2YYMP.js +0 -1
  173. package/dist/excalidraw/element/routing.d.ts +0 -12
  174. package/dist/excalidraw/element/routing.js +0 -642
  175. package/dist/excalidraw/jotai.d.ts +0 -34
  176. package/dist/excalidraw/jotai.js +0 -18
  177. /package/dist/browser/dev/excalidraw-assets-dev/{en-ZSVWGT55.js.map → en-7IBTMWBG.js.map} +0 -0
  178. /package/dist/browser/dev/excalidraw-assets-dev/{image-RJG3J34Y.js.map → image-N5AC7SEK.js.map} +0 -0
@@ -1 +0,0 @@
1
- import{bh as a,ch as b,dh as c,eh as d,fh as e}from"./chunk-S2XKB3DE.js";import"./chunk-M2JW2GFW.js";import"./chunk-SXMPUQ6M.js";export{c as decodePngMetadata,e as decodeSvgMetadata,b as encodePngMetadata,d as encodeSvgMetadata,a as getTEXtChunk};
@@ -1,12 +0,0 @@
1
- import { type LocalPoint, type Vector } from "../../math";
2
- import type { ElementUpdate } from "./mutateElement";
3
- import type { ExcalidrawElbowArrowElement, NonDeletedSceneElementsMap, SceneElementsMap } from "./types";
4
- export declare const mutateElbowArrow: (arrow: ExcalidrawElbowArrowElement, elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, nextPoints: readonly LocalPoint[], offset?: Vector, otherUpdates?: Omit<ElementUpdate<ExcalidrawElbowArrowElement>, "angle" | "x" | "y" | "width" | "height" | "elbowed" | "points">, options?: {
5
- isDragging?: boolean;
6
- informMutation?: boolean;
7
- }) => void;
8
- export declare const updateElbowArrow: (arrow: ExcalidrawElbowArrowElement, elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, nextPoints: readonly LocalPoint[], offset?: Vector, options?: {
9
- isDragging?: boolean;
10
- disableBinding?: boolean;
11
- informMutation?: boolean;
12
- }) => ElementUpdate<ExcalidrawElbowArrowElement> | null;
@@ -1,642 +0,0 @@
1
- import { pointFrom, pointScaleFromOrigin, pointTranslate, vector, vectorCross, vectorFromPoint, vectorScale, } from "../../math";
2
- import BinaryHeap from "../binaryheap";
3
- import { getSizeFromPoints } from "../points";
4
- import { aabbForElement, pointInsideBounds } from "../shapes";
5
- import { isAnyTrue, toBrandedType, tupleToCoors } from "../utils";
6
- import { bindPointToSnapToElementOutline, distanceToBindableElement, avoidRectangularCorner, getHoveredElementForBinding, FIXED_BINDING_DISTANCE, getHeadingForElbowArrowSnap, getGlobalFixedPointForBindableElement, snapToMid, } from "./binding";
7
- import { compareHeading, flipHeading, HEADING_DOWN, HEADING_LEFT, HEADING_RIGHT, HEADING_UP, vectorToHeading, } from "./heading";
8
- import { mutateElement } from "./mutateElement";
9
- import { isBindableElement, isRectanguloidElement } from "./typeChecks";
10
- const BASE_PADDING = 40;
11
- export const mutateElbowArrow = (arrow, elementsMap, nextPoints, offset, otherUpdates, options) => {
12
- const update = updateElbowArrow(arrow, elementsMap, nextPoints, offset, options);
13
- if (update) {
14
- mutateElement(arrow, {
15
- ...otherUpdates,
16
- ...update,
17
- angle: 0,
18
- }, options?.informMutation);
19
- }
20
- else {
21
- console.error("Elbow arrow cannot find a route");
22
- }
23
- };
24
- export const updateElbowArrow = (arrow, elementsMap, nextPoints, offset, options) => {
25
- const origStartGlobalPoint = pointTranslate(pointTranslate(nextPoints[0], vector(arrow.x, arrow.y)), offset);
26
- const origEndGlobalPoint = pointTranslate(pointTranslate(nextPoints[nextPoints.length - 1], vector(arrow.x, arrow.y)), offset);
27
- const startElement = arrow.startBinding &&
28
- getBindableElementForId(arrow.startBinding.elementId, elementsMap);
29
- const endElement = arrow.endBinding &&
30
- getBindableElementForId(arrow.endBinding.elementId, elementsMap);
31
- const [hoveredStartElement, hoveredEndElement] = options?.isDragging
32
- ? getHoveredElements(origStartGlobalPoint, origEndGlobalPoint, elementsMap)
33
- : [startElement, endElement];
34
- const startGlobalPoint = getGlobalPoint(arrow.startBinding?.fixedPoint, origStartGlobalPoint, origEndGlobalPoint, elementsMap, startElement, hoveredStartElement, options?.isDragging);
35
- const endGlobalPoint = getGlobalPoint(arrow.endBinding?.fixedPoint, origEndGlobalPoint, origStartGlobalPoint, elementsMap, endElement, hoveredEndElement, options?.isDragging);
36
- const startHeading = getBindPointHeading(startGlobalPoint, endGlobalPoint, elementsMap, hoveredStartElement, origStartGlobalPoint);
37
- const endHeading = getBindPointHeading(endGlobalPoint, startGlobalPoint, elementsMap, hoveredEndElement, origEndGlobalPoint);
38
- const startPointBounds = [
39
- startGlobalPoint[0] - 2,
40
- startGlobalPoint[1] - 2,
41
- startGlobalPoint[0] + 2,
42
- startGlobalPoint[1] + 2,
43
- ];
44
- const endPointBounds = [
45
- endGlobalPoint[0] - 2,
46
- endGlobalPoint[1] - 2,
47
- endGlobalPoint[0] + 2,
48
- endGlobalPoint[1] + 2,
49
- ];
50
- const startElementBounds = hoveredStartElement
51
- ? aabbForElement(hoveredStartElement, offsetFromHeading(startHeading, arrow.startArrowhead
52
- ? FIXED_BINDING_DISTANCE * 6
53
- : FIXED_BINDING_DISTANCE * 2, 1))
54
- : startPointBounds;
55
- const endElementBounds = hoveredEndElement
56
- ? aabbForElement(hoveredEndElement, offsetFromHeading(endHeading, arrow.endArrowhead
57
- ? FIXED_BINDING_DISTANCE * 6
58
- : FIXED_BINDING_DISTANCE * 2, 1))
59
- : endPointBounds;
60
- const boundsOverlap = pointInsideBounds(startGlobalPoint, hoveredEndElement
61
- ? aabbForElement(hoveredEndElement, offsetFromHeading(endHeading, BASE_PADDING, BASE_PADDING))
62
- : endPointBounds) ||
63
- pointInsideBounds(endGlobalPoint, hoveredStartElement
64
- ? aabbForElement(hoveredStartElement, offsetFromHeading(startHeading, BASE_PADDING, BASE_PADDING))
65
- : startPointBounds);
66
- const commonBounds = commonAABB(boundsOverlap
67
- ? [startPointBounds, endPointBounds]
68
- : [startElementBounds, endElementBounds]);
69
- const dynamicAABBs = generateDynamicAABBs(boundsOverlap ? startPointBounds : startElementBounds, boundsOverlap ? endPointBounds : endElementBounds, commonBounds, boundsOverlap
70
- ? offsetFromHeading(startHeading, !hoveredStartElement && !hoveredEndElement ? 0 : BASE_PADDING, 0)
71
- : offsetFromHeading(startHeading, !hoveredStartElement && !hoveredEndElement
72
- ? 0
73
- : BASE_PADDING -
74
- (arrow.startArrowhead
75
- ? FIXED_BINDING_DISTANCE * 6
76
- : FIXED_BINDING_DISTANCE * 2), BASE_PADDING), boundsOverlap
77
- ? offsetFromHeading(endHeading, !hoveredStartElement && !hoveredEndElement ? 0 : BASE_PADDING, 0)
78
- : offsetFromHeading(endHeading, !hoveredStartElement && !hoveredEndElement
79
- ? 0
80
- : BASE_PADDING -
81
- (arrow.endArrowhead
82
- ? FIXED_BINDING_DISTANCE * 6
83
- : FIXED_BINDING_DISTANCE * 2), BASE_PADDING), boundsOverlap, hoveredStartElement && aabbForElement(hoveredStartElement), hoveredEndElement && aabbForElement(hoveredEndElement));
84
- const startDonglePosition = getDonglePosition(dynamicAABBs[0], startHeading, startGlobalPoint);
85
- const endDonglePosition = getDonglePosition(dynamicAABBs[1], endHeading, endGlobalPoint);
86
- // Canculate Grid positions
87
- const grid = calculateGrid(dynamicAABBs, startDonglePosition ? startDonglePosition : startGlobalPoint, startHeading, endDonglePosition ? endDonglePosition : endGlobalPoint, endHeading, commonBounds);
88
- const startDongle = startDonglePosition && pointToGridNode(startDonglePosition, grid);
89
- const endDongle = endDonglePosition && pointToGridNode(endDonglePosition, grid);
90
- // Do not allow stepping on the true end or true start points
91
- const endNode = pointToGridNode(endGlobalPoint, grid);
92
- if (endNode && hoveredEndElement) {
93
- endNode.closed = true;
94
- }
95
- const startNode = pointToGridNode(startGlobalPoint, grid);
96
- if (startNode && arrow.startBinding) {
97
- startNode.closed = true;
98
- }
99
- const dongleOverlap = startDongle &&
100
- endDongle &&
101
- (pointInsideBounds(startDongle.pos, dynamicAABBs[1]) ||
102
- pointInsideBounds(endDongle.pos, dynamicAABBs[0]));
103
- // Create path to end dongle from start dongle
104
- const path = astar(startDongle ? startDongle : startNode, endDongle ? endDongle : endNode, grid, startHeading ? startHeading : HEADING_RIGHT, endHeading ? endHeading : HEADING_RIGHT, dongleOverlap ? [] : dynamicAABBs);
105
- if (path) {
106
- const points = path.map((node) => [
107
- node.pos[0],
108
- node.pos[1],
109
- ]);
110
- startDongle && points.unshift(startGlobalPoint);
111
- endDongle && points.push(endGlobalPoint);
112
- return normalizedArrowElementUpdate(simplifyElbowArrowPoints(points), 0, 0);
113
- }
114
- return null;
115
- };
116
- const offsetFromHeading = (heading, head, side) => {
117
- switch (heading) {
118
- case HEADING_UP:
119
- return [head, side, side, side];
120
- case HEADING_RIGHT:
121
- return [side, head, side, side];
122
- case HEADING_DOWN:
123
- return [side, side, head, side];
124
- }
125
- return [side, side, side, head];
126
- };
127
- /**
128
- * Routing algorithm based on the A* path search algorithm.
129
- * @see https://www.geeksforgeeks.org/a-search-algorithm/
130
- *
131
- * Binary heap is used to optimize node lookup.
132
- * See {@link calculateGrid} for the grid calculation details.
133
- *
134
- * Additional modifications added due to aesthetic route reasons:
135
- * 1) Arrow segment direction change is penalized by specific linear constant (bendMultiplier)
136
- * 2) Arrow segments are not allowed to go "backwards", overlapping with the previous segment
137
- */
138
- const astar = (start, end, grid, startHeading, endHeading, aabbs) => {
139
- const bendMultiplier = m_dist(start.pos, end.pos);
140
- const open = new BinaryHeap((node) => node.f);
141
- open.push(start);
142
- while (open.size() > 0) {
143
- // Grab the lowest f(x) to process next. Heap keeps this sorted for us.
144
- const current = open.pop();
145
- if (!current || current.closed) {
146
- // Current is not passable, continue with next element
147
- continue;
148
- }
149
- // End case -- result has been found, return the traced path.
150
- if (current === end) {
151
- return pathTo(start, current);
152
- }
153
- // Normal case -- move current from open to closed, process each of its neighbors.
154
- current.closed = true;
155
- // Find all neighbors for the current node.
156
- const neighbors = getNeighbors(current.addr, grid);
157
- for (let i = 0; i < 4; i++) {
158
- const neighbor = neighbors[i];
159
- if (!neighbor || neighbor.closed) {
160
- // Not a valid node to process, skip to next neighbor.
161
- continue;
162
- }
163
- // Intersect
164
- const neighborHalfPoint = pointScaleFromOrigin(neighbor.pos, current.pos, 0.5);
165
- if (isAnyTrue(...aabbs.map((aabb) => pointInsideBounds(neighborHalfPoint, aabb)))) {
166
- continue;
167
- }
168
- // The g score is the shortest distance from start to current node.
169
- // We need to check if the path we have arrived at this neighbor is the shortest one we have seen yet.
170
- const neighborHeading = neighborIndexToHeading(i);
171
- const previousDirection = current.parent
172
- ? vectorToHeading(vectorFromPoint(current.pos, current.parent.pos))
173
- : startHeading;
174
- // Do not allow going in reverse
175
- const reverseHeading = flipHeading(previousDirection);
176
- const neighborIsReverseRoute = compareHeading(reverseHeading, neighborHeading) ||
177
- (gridAddressesEqual(start.addr, neighbor.addr) &&
178
- compareHeading(neighborHeading, startHeading)) ||
179
- (gridAddressesEqual(end.addr, neighbor.addr) &&
180
- compareHeading(neighborHeading, endHeading));
181
- if (neighborIsReverseRoute) {
182
- continue;
183
- }
184
- const directionChange = previousDirection !== neighborHeading;
185
- const gScore = current.g +
186
- m_dist(neighbor.pos, current.pos) +
187
- (directionChange ? Math.pow(bendMultiplier, 3) : 0);
188
- const beenVisited = neighbor.visited;
189
- if (!beenVisited || gScore < neighbor.g) {
190
- const estBendCount = estimateSegmentCount(neighbor, end, neighborHeading, endHeading);
191
- // Found an optimal (so far) path to this node. Take score for node to see how good it is.
192
- neighbor.visited = true;
193
- neighbor.parent = current;
194
- neighbor.h =
195
- m_dist(end.pos, neighbor.pos) +
196
- estBendCount * Math.pow(bendMultiplier, 2);
197
- neighbor.g = gScore;
198
- neighbor.f = neighbor.g + neighbor.h;
199
- if (!beenVisited) {
200
- // Pushing to heap will put it in proper place based on the 'f' value.
201
- open.push(neighbor);
202
- }
203
- else {
204
- // Already seen the node, but since it has been rescored we need to reorder it in the heap
205
- open.rescoreElement(neighbor);
206
- }
207
- }
208
- }
209
- }
210
- return null;
211
- };
212
- const pathTo = (start, node) => {
213
- let curr = node;
214
- const path = [];
215
- while (curr.parent) {
216
- path.unshift(curr);
217
- curr = curr.parent;
218
- }
219
- path.unshift(start);
220
- return path;
221
- };
222
- const m_dist = (a, b) => Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
223
- /**
224
- * Create dynamically resizing, always touching
225
- * bounding boxes having a minimum extent represented
226
- * by the given static bounds.
227
- */
228
- const generateDynamicAABBs = (a, b, common, startDifference, endDifference, disableSideHack, startElementBounds, endElementBounds) => {
229
- const startEl = startElementBounds ?? a;
230
- const endEl = endElementBounds ?? b;
231
- const [startUp, startRight, startDown, startLeft] = startDifference ?? [
232
- 0, 0, 0, 0,
233
- ];
234
- const [endUp, endRight, endDown, endLeft] = endDifference ?? [0, 0, 0, 0];
235
- const first = [
236
- a[0] > b[2]
237
- ? a[1] > b[3] || a[3] < b[1]
238
- ? Math.min((startEl[0] + endEl[2]) / 2, a[0] - startLeft)
239
- : (startEl[0] + endEl[2]) / 2
240
- : a[0] > b[0]
241
- ? a[0] - startLeft
242
- : common[0] - startLeft,
243
- a[1] > b[3]
244
- ? a[0] > b[2] || a[2] < b[0]
245
- ? Math.min((startEl[1] + endEl[3]) / 2, a[1] - startUp)
246
- : (startEl[1] + endEl[3]) / 2
247
- : a[1] > b[1]
248
- ? a[1] - startUp
249
- : common[1] - startUp,
250
- a[2] < b[0]
251
- ? a[1] > b[3] || a[3] < b[1]
252
- ? Math.max((startEl[2] + endEl[0]) / 2, a[2] + startRight)
253
- : (startEl[2] + endEl[0]) / 2
254
- : a[2] < b[2]
255
- ? a[2] + startRight
256
- : common[2] + startRight,
257
- a[3] < b[1]
258
- ? a[0] > b[2] || a[2] < b[0]
259
- ? Math.max((startEl[3] + endEl[1]) / 2, a[3] + startDown)
260
- : (startEl[3] + endEl[1]) / 2
261
- : a[3] < b[3]
262
- ? a[3] + startDown
263
- : common[3] + startDown,
264
- ];
265
- const second = [
266
- b[0] > a[2]
267
- ? b[1] > a[3] || b[3] < a[1]
268
- ? Math.min((endEl[0] + startEl[2]) / 2, b[0] - endLeft)
269
- : (endEl[0] + startEl[2]) / 2
270
- : b[0] > a[0]
271
- ? b[0] - endLeft
272
- : common[0] - endLeft,
273
- b[1] > a[3]
274
- ? b[0] > a[2] || b[2] < a[0]
275
- ? Math.min((endEl[1] + startEl[3]) / 2, b[1] - endUp)
276
- : (endEl[1] + startEl[3]) / 2
277
- : b[1] > a[1]
278
- ? b[1] - endUp
279
- : common[1] - endUp,
280
- b[2] < a[0]
281
- ? b[1] > a[3] || b[3] < a[1]
282
- ? Math.max((endEl[2] + startEl[0]) / 2, b[2] + endRight)
283
- : (endEl[2] + startEl[0]) / 2
284
- : b[2] < a[2]
285
- ? b[2] + endRight
286
- : common[2] + endRight,
287
- b[3] < a[1]
288
- ? b[0] > a[2] || b[2] < a[0]
289
- ? Math.max((endEl[3] + startEl[1]) / 2, b[3] + endDown)
290
- : (endEl[3] + startEl[1]) / 2
291
- : b[3] < a[3]
292
- ? b[3] + endDown
293
- : common[3] + endDown,
294
- ];
295
- const c = commonAABB([first, second]);
296
- if (!disableSideHack &&
297
- first[2] - first[0] + second[2] - second[0] > c[2] - c[0] + 0.00000000001 &&
298
- first[3] - first[1] + second[3] - second[1] > c[3] - c[1] + 0.00000000001) {
299
- const [endCenterX, endCenterY] = [
300
- (second[0] + second[2]) / 2,
301
- (second[1] + second[3]) / 2,
302
- ];
303
- if (b[0] > a[2] && a[1] > b[3]) {
304
- // BOTTOM LEFT
305
- const cX = first[2] + (second[0] - first[2]) / 2;
306
- const cY = second[3] + (first[1] - second[3]) / 2;
307
- if (vectorCross(vector(a[2] - endCenterX, a[1] - endCenterY), vector(a[0] - endCenterX, a[3] - endCenterY)) > 0) {
308
- return [
309
- [first[0], first[1], cX, first[3]],
310
- [cX, second[1], second[2], second[3]],
311
- ];
312
- }
313
- return [
314
- [first[0], cY, first[2], first[3]],
315
- [second[0], second[1], second[2], cY],
316
- ];
317
- }
318
- else if (a[2] < b[0] && a[3] < b[1]) {
319
- // TOP LEFT
320
- const cX = first[2] + (second[0] - first[2]) / 2;
321
- const cY = first[3] + (second[1] - first[3]) / 2;
322
- if (vectorCross(vector(a[0] - endCenterX, a[1] - endCenterY), vector(a[2] - endCenterX, a[3] - endCenterY)) > 0) {
323
- return [
324
- [first[0], first[1], first[2], cY],
325
- [second[0], cY, second[2], second[3]],
326
- ];
327
- }
328
- return [
329
- [first[0], first[1], cX, first[3]],
330
- [cX, second[1], second[2], second[3]],
331
- ];
332
- }
333
- else if (a[0] > b[2] && a[3] < b[1]) {
334
- // TOP RIGHT
335
- const cX = second[2] + (first[0] - second[2]) / 2;
336
- const cY = first[3] + (second[1] - first[3]) / 2;
337
- if (vectorCross(vector(a[2] - endCenterX, a[1] - endCenterY), vector(a[0] - endCenterX, a[3] - endCenterY)) > 0) {
338
- return [
339
- [cX, first[1], first[2], first[3]],
340
- [second[0], second[1], cX, second[3]],
341
- ];
342
- }
343
- return [
344
- [first[0], first[1], first[2], cY],
345
- [second[0], cY, second[2], second[3]],
346
- ];
347
- }
348
- else if (a[0] > b[2] && a[1] > b[3]) {
349
- // BOTTOM RIGHT
350
- const cX = second[2] + (first[0] - second[2]) / 2;
351
- const cY = second[3] + (first[1] - second[3]) / 2;
352
- if (vectorCross(vector(a[0] - endCenterX, a[1] - endCenterY), vector(a[2] - endCenterX, a[3] - endCenterY)) > 0) {
353
- return [
354
- [cX, first[1], first[2], first[3]],
355
- [second[0], second[1], cX, second[3]],
356
- ];
357
- }
358
- return [
359
- [first[0], cY, first[2], first[3]],
360
- [second[0], second[1], second[2], cY],
361
- ];
362
- }
363
- }
364
- return [first, second];
365
- };
366
- /**
367
- * Calculates the grid which is used as nodes at
368
- * the grid line intersections by the A* algorithm.
369
- *
370
- * NOTE: This is not a uniform grid. It is built at
371
- * various intersections of bounding boxes.
372
- */
373
- const calculateGrid = (aabbs, start, startHeading, end, endHeading, common) => {
374
- const horizontal = new Set();
375
- const vertical = new Set();
376
- if (startHeading === HEADING_LEFT || startHeading === HEADING_RIGHT) {
377
- vertical.add(start[1]);
378
- }
379
- else {
380
- horizontal.add(start[0]);
381
- }
382
- if (endHeading === HEADING_LEFT || endHeading === HEADING_RIGHT) {
383
- vertical.add(end[1]);
384
- }
385
- else {
386
- horizontal.add(end[0]);
387
- }
388
- aabbs.forEach((aabb) => {
389
- horizontal.add(aabb[0]);
390
- horizontal.add(aabb[2]);
391
- vertical.add(aabb[1]);
392
- vertical.add(aabb[3]);
393
- });
394
- horizontal.add(common[0]);
395
- horizontal.add(common[2]);
396
- vertical.add(common[1]);
397
- vertical.add(common[3]);
398
- const _vertical = Array.from(vertical).sort((a, b) => a - b);
399
- const _horizontal = Array.from(horizontal).sort((a, b) => a - b);
400
- return {
401
- row: _vertical.length,
402
- col: _horizontal.length,
403
- data: _vertical.flatMap((y, row) => _horizontal.map((x, col) => ({
404
- f: 0,
405
- g: 0,
406
- h: 0,
407
- closed: false,
408
- visited: false,
409
- parent: null,
410
- addr: [col, row],
411
- pos: [x, y],
412
- }))),
413
- };
414
- };
415
- const getDonglePosition = (bounds, heading, p) => {
416
- switch (heading) {
417
- case HEADING_UP:
418
- return pointFrom(p[0], bounds[1]);
419
- case HEADING_RIGHT:
420
- return pointFrom(bounds[2], p[1]);
421
- case HEADING_DOWN:
422
- return pointFrom(p[0], bounds[3]);
423
- }
424
- return pointFrom(bounds[0], p[1]);
425
- };
426
- const estimateSegmentCount = (start, end, startHeading, endHeading) => {
427
- if (endHeading === HEADING_RIGHT) {
428
- switch (startHeading) {
429
- case HEADING_RIGHT: {
430
- if (start.pos[0] >= end.pos[0]) {
431
- return 4;
432
- }
433
- if (start.pos[1] === end.pos[1]) {
434
- return 0;
435
- }
436
- return 2;
437
- }
438
- case HEADING_UP:
439
- if (start.pos[1] > end.pos[1] && start.pos[0] < end.pos[0]) {
440
- return 1;
441
- }
442
- return 3;
443
- case HEADING_DOWN:
444
- if (start.pos[1] < end.pos[1] && start.pos[0] < end.pos[0]) {
445
- return 1;
446
- }
447
- return 3;
448
- case HEADING_LEFT:
449
- if (start.pos[1] === end.pos[1]) {
450
- return 4;
451
- }
452
- return 2;
453
- }
454
- }
455
- else if (endHeading === HEADING_LEFT) {
456
- switch (startHeading) {
457
- case HEADING_RIGHT:
458
- if (start.pos[1] === end.pos[1]) {
459
- return 4;
460
- }
461
- return 2;
462
- case HEADING_UP:
463
- if (start.pos[1] > end.pos[1] && start.pos[0] > end.pos[0]) {
464
- return 1;
465
- }
466
- return 3;
467
- case HEADING_DOWN:
468
- if (start.pos[1] < end.pos[1] && start.pos[0] > end.pos[0]) {
469
- return 1;
470
- }
471
- return 3;
472
- case HEADING_LEFT:
473
- if (start.pos[0] <= end.pos[0]) {
474
- return 4;
475
- }
476
- if (start.pos[1] === end.pos[1]) {
477
- return 0;
478
- }
479
- return 2;
480
- }
481
- }
482
- else if (endHeading === HEADING_UP) {
483
- switch (startHeading) {
484
- case HEADING_RIGHT:
485
- if (start.pos[1] > end.pos[1] && start.pos[0] < end.pos[0]) {
486
- return 1;
487
- }
488
- return 3;
489
- case HEADING_UP:
490
- if (start.pos[1] >= end.pos[1]) {
491
- return 4;
492
- }
493
- if (start.pos[0] === end.pos[0]) {
494
- return 0;
495
- }
496
- return 2;
497
- case HEADING_DOWN:
498
- if (start.pos[0] === end.pos[0]) {
499
- return 4;
500
- }
501
- return 2;
502
- case HEADING_LEFT:
503
- if (start.pos[1] > end.pos[1] && start.pos[0] > end.pos[0]) {
504
- return 1;
505
- }
506
- return 3;
507
- }
508
- }
509
- else if (endHeading === HEADING_DOWN) {
510
- switch (startHeading) {
511
- case HEADING_RIGHT:
512
- if (start.pos[1] < end.pos[1] && start.pos[0] < end.pos[0]) {
513
- return 1;
514
- }
515
- return 3;
516
- case HEADING_UP:
517
- if (start.pos[0] === end.pos[0]) {
518
- return 4;
519
- }
520
- return 2;
521
- case HEADING_DOWN:
522
- if (start.pos[1] <= end.pos[1]) {
523
- return 4;
524
- }
525
- if (start.pos[0] === end.pos[0]) {
526
- return 0;
527
- }
528
- return 2;
529
- case HEADING_LEFT:
530
- if (start.pos[1] < end.pos[1] && start.pos[0] > end.pos[0]) {
531
- return 1;
532
- }
533
- return 3;
534
- }
535
- }
536
- return 0;
537
- };
538
- /**
539
- * Get neighboring points for a gived grid address
540
- */
541
- const getNeighbors = ([col, row], grid) => [
542
- gridNodeFromAddr([col, row - 1], grid),
543
- gridNodeFromAddr([col + 1, row], grid),
544
- gridNodeFromAddr([col, row + 1], grid),
545
- gridNodeFromAddr([col - 1, row], grid),
546
- ];
547
- const gridNodeFromAddr = ([col, row], grid) => {
548
- if (col < 0 || col >= grid.col || row < 0 || row >= grid.row) {
549
- return null;
550
- }
551
- return grid.data[row * grid.col + col] ?? null;
552
- };
553
- /**
554
- * Get node for global point on canvas (if exists)
555
- */
556
- const pointToGridNode = (point, grid) => {
557
- for (let col = 0; col < grid.col; col++) {
558
- for (let row = 0; row < grid.row; row++) {
559
- const candidate = gridNodeFromAddr([col, row], grid);
560
- if (candidate &&
561
- point[0] === candidate.pos[0] &&
562
- point[1] === candidate.pos[1]) {
563
- return candidate;
564
- }
565
- }
566
- }
567
- return null;
568
- };
569
- const commonAABB = (aabbs) => [
570
- Math.min(...aabbs.map((aabb) => aabb[0])),
571
- Math.min(...aabbs.map((aabb) => aabb[1])),
572
- Math.max(...aabbs.map((aabb) => aabb[2])),
573
- Math.max(...aabbs.map((aabb) => aabb[3])),
574
- ];
575
- /// #region Utils
576
- const getBindableElementForId = (id, elementsMap) => {
577
- const element = elementsMap.get(id);
578
- if (element && isBindableElement(element)) {
579
- return element;
580
- }
581
- return null;
582
- };
583
- const normalizedArrowElementUpdate = (global, externalOffsetX, externalOffsetY) => {
584
- const offsetX = global[0][0];
585
- const offsetY = global[0][1];
586
- const points = global.map((p) => pointTranslate(p, vectorScale(vectorFromPoint(global[0]), -1)));
587
- return {
588
- points,
589
- x: offsetX + (externalOffsetX ?? 0),
590
- y: offsetY + (externalOffsetY ?? 0),
591
- ...getSizeFromPoints(points),
592
- };
593
- };
594
- /// If last and current segments have the same heading, skip the middle point
595
- const simplifyElbowArrowPoints = (points) => points
596
- .slice(2)
597
- .reduce((result, p) => compareHeading(vectorToHeading(vectorFromPoint(result[result.length - 1], result[result.length - 2])), vectorToHeading(vectorFromPoint(p, result[result.length - 1])))
598
- ? [...result.slice(0, -1), p]
599
- : [...result, p], [points[0] ?? [0, 0], points[1] ?? [1, 0]]);
600
- const neighborIndexToHeading = (idx) => {
601
- switch (idx) {
602
- case 0:
603
- return HEADING_UP;
604
- case 1:
605
- return HEADING_RIGHT;
606
- case 2:
607
- return HEADING_DOWN;
608
- }
609
- return HEADING_LEFT;
610
- };
611
- const getGlobalPoint = (fixedPointRatio, initialPoint, otherPoint, elementsMap, boundElement, hoveredElement, isDragging) => {
612
- if (isDragging) {
613
- if (hoveredElement) {
614
- const snapPoint = getSnapPoint(initialPoint, otherPoint, hoveredElement, elementsMap);
615
- return snapToMid(hoveredElement, snapPoint);
616
- }
617
- return initialPoint;
618
- }
619
- if (boundElement) {
620
- const fixedGlobalPoint = getGlobalFixedPointForBindableElement(fixedPointRatio || [0, 0], boundElement);
621
- // NOTE: Resize scales the binding position point too, so we need to update it
622
- return Math.abs(distanceToBindableElement(boundElement, fixedGlobalPoint, elementsMap) -
623
- FIXED_BINDING_DISTANCE) > 0.01
624
- ? getSnapPoint(initialPoint, otherPoint, boundElement, elementsMap)
625
- : fixedGlobalPoint;
626
- }
627
- return initialPoint;
628
- };
629
- const getSnapPoint = (p, otherPoint, element, elementsMap) => bindPointToSnapToElementOutline(isRectanguloidElement(element) ? avoidRectangularCorner(element, p) : p, otherPoint, element, elementsMap);
630
- const getBindPointHeading = (p, otherPoint, elementsMap, hoveredElement, origPoint) => getHeadingForElbowArrowSnap(p, otherPoint, hoveredElement, hoveredElement &&
631
- aabbForElement(hoveredElement, Array(4).fill(distanceToBindableElement(hoveredElement, p, elementsMap))), elementsMap, origPoint);
632
- const getHoveredElements = (origStartGlobalPoint, origEndGlobalPoint, elementsMap) => {
633
- // TODO: Might be a performance bottleneck and the Map type
634
- // remembers the insertion order anyway...
635
- const nonDeletedSceneElementsMap = toBrandedType(new Map([...elementsMap].filter((el) => !el[1].isDeleted)));
636
- const elements = Array.from(elementsMap.values());
637
- return [
638
- getHoveredElementForBinding(tupleToCoors(origStartGlobalPoint), elements, nonDeletedSceneElementsMap, true),
639
- getHoveredElementForBinding(tupleToCoors(origEndGlobalPoint), elements, nonDeletedSceneElementsMap, true),
640
- ];
641
- };
642
- const gridAddressesEqual = (a, b) => a[0] === b[0] && a[1] === b[1];