@excalidraw/math 0.18.0-2b0e4c9 → 0.18.0-2b1c2a9

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 (192) hide show
  1. package/dist/dev/index.js +311 -114
  2. package/dist/dev/index.js.map +4 -4
  3. package/dist/prod/index.js +1 -1
  4. package/dist/types/common/src/colors.d.ts +20 -1
  5. package/dist/types/common/src/constants.d.ts +12 -7
  6. package/dist/types/common/src/keys.d.ts +2 -0
  7. package/dist/types/common/src/points.d.ts +1 -1
  8. package/dist/types/common/src/utils.d.ts +1 -43
  9. package/dist/types/element/src/Scene.d.ts +6 -4
  10. package/dist/types/element/src/align.d.ts +2 -2
  11. package/dist/types/element/src/arrowEndpointText.d.ts +49 -0
  12. package/dist/types/element/src/arrows/focus.d.ts +5 -2
  13. package/dist/types/element/src/binding.d.ts +17 -8
  14. package/dist/types/element/src/bounds.d.ts +22 -7
  15. package/dist/types/element/src/bucketFill.d.ts +110 -0
  16. package/dist/types/element/src/collision.d.ts +1 -1
  17. package/dist/types/element/src/comparisons.d.ts +5 -4
  18. package/dist/types/element/src/convertToShape.d.ts +23 -0
  19. package/dist/types/element/src/distribute.d.ts +2 -2
  20. package/dist/types/element/src/dragElements.d.ts +27 -0
  21. package/dist/types/element/src/duplicate.d.ts +4 -3
  22. package/dist/types/element/src/embeddable.d.ts +2 -2
  23. package/dist/types/element/src/flowchart.d.ts +7 -7
  24. package/dist/types/element/src/fractionalIndex.d.ts +2 -2
  25. package/dist/types/element/src/frame.d.ts +9 -8
  26. package/dist/types/element/src/groups.d.ts +9 -9
  27. package/dist/types/element/src/index.d.ts +4 -1
  28. package/dist/types/element/src/linearElementEditor.d.ts +27 -10
  29. package/dist/types/element/src/newElement.d.ts +15 -0
  30. package/dist/types/element/src/renderElement.d.ts +0 -3
  31. package/dist/types/element/src/resizeElements.d.ts +2 -2
  32. package/dist/types/element/src/selection.d.ts +11 -7
  33. package/dist/types/element/src/shape.d.ts +13 -1
  34. package/dist/types/element/src/sortElements.d.ts +10 -0
  35. package/dist/types/element/src/textElement.d.ts +14 -10
  36. package/dist/types/element/src/textWrapping.d.ts +26 -0
  37. package/dist/types/element/src/transform.d.ts +2 -2
  38. package/dist/types/element/src/typeChecks.d.ts +26 -25
  39. package/dist/types/element/src/types.d.ts +15 -1
  40. package/dist/types/element/src/utils.d.ts +7 -3
  41. package/dist/types/element/src/zindex.d.ts +2 -2
  42. package/dist/types/excalidraw/actions/actionAddToLibrary.d.ts +48 -21
  43. package/dist/types/excalidraw/actions/actionAlign.d.ts +6 -6
  44. package/dist/types/excalidraw/actions/actionBoundText.d.ts +33 -15
  45. package/dist/types/excalidraw/actions/actionCanvas.d.ts +174 -947
  46. package/dist/types/excalidraw/actions/actionClipboard.d.ts +32 -14
  47. package/dist/types/excalidraw/actions/actionCropEditor.d.ts +16 -7
  48. package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +50 -22
  49. package/dist/types/excalidraw/actions/{actionEmbeddable.d.ts → actionDeselect.d.ts} +30 -36
  50. package/dist/types/excalidraw/actions/actionDistribute.d.ts +2 -3
  51. package/dist/types/excalidraw/actions/actionElementLink.d.ts +16 -7
  52. package/dist/types/excalidraw/actions/actionElementLock.d.ts +33 -15
  53. package/dist/types/excalidraw/actions/actionExport.d.ts +34 -16
  54. package/dist/types/excalidraw/actions/actionFinalize.d.ts +1 -0
  55. package/dist/types/excalidraw/actions/actionFrame.d.ts +61 -205
  56. package/dist/types/excalidraw/actions/actionGroup.d.ts +48 -30
  57. package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +21 -9
  58. package/dist/types/excalidraw/actions/actionLink.d.ts +17 -8
  59. package/dist/types/excalidraw/actions/actionMenu.d.ts +16 -7
  60. package/dist/types/excalidraw/actions/actionProperties.d.ts +62 -32
  61. package/dist/types/excalidraw/actions/actionSelectAll.d.ts +21 -12
  62. package/dist/types/excalidraw/actions/actionStyles.d.ts +17 -7
  63. package/dist/types/excalidraw/actions/actionTextAutoResize.d.ts +3 -3
  64. package/dist/types/excalidraw/actions/actionToggleArrowBinding.d.ts +17 -8
  65. package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +20 -12
  66. package/dist/types/excalidraw/actions/actionToggleMidpointSnapping.d.ts +17 -8
  67. package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +17 -8
  68. package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +20 -12
  69. package/dist/types/excalidraw/actions/actionToggleShapeSwitch.d.ts +1 -1
  70. package/dist/types/excalidraw/actions/actionToggleStats.d.ts +17 -8
  71. package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +18 -9
  72. package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +17 -8
  73. package/dist/types/excalidraw/actions/index.d.ts +2 -2
  74. package/dist/types/excalidraw/actions/manager.d.ts +1 -0
  75. package/dist/types/excalidraw/actions/shortcuts.d.ts +1 -1
  76. package/dist/types/excalidraw/actions/types.d.ts +8 -4
  77. package/dist/types/excalidraw/{animated-trail.d.ts → animatedTrail.d.ts} +4 -3
  78. package/dist/types/excalidraw/appState.d.ts +12 -5
  79. package/dist/types/excalidraw/components/Actions.d.ts +17 -12
  80. package/dist/types/excalidraw/components/ActiveConfirmDialog.d.ts +1 -1
  81. package/dist/types/excalidraw/components/App.arrowText.d.ts +104 -0
  82. package/dist/types/excalidraw/components/App.bucketFill.d.ts +48 -0
  83. package/dist/types/excalidraw/components/App.cursor.d.ts +38 -0
  84. package/dist/types/excalidraw/components/App.d.ts +391 -68
  85. package/dist/types/excalidraw/components/App.drawshape.d.ts +55 -0
  86. package/dist/types/excalidraw/components/App.flowchart.d.ts +21 -0
  87. package/dist/types/excalidraw/components/App.viewport.d.ts +73 -0
  88. package/dist/types/excalidraw/components/ColorPicker/ColorPicker.d.ts +9 -3
  89. package/dist/types/excalidraw/components/ColorPicker/CustomColorList.d.ts +3 -1
  90. package/dist/types/excalidraw/components/ColorPicker/Picker.d.ts +3 -1
  91. package/dist/types/excalidraw/components/ColorPicker/PickerColorList.d.ts +9 -2
  92. package/dist/types/excalidraw/components/ColorPicker/ShadeList.d.ts +4 -2
  93. package/dist/types/excalidraw/components/ColorPicker/TopPicks.d.ts +8 -1
  94. package/dist/types/excalidraw/components/ColorPicker/colorPickerUtils.d.ts +1 -1
  95. package/dist/types/excalidraw/components/ColorPicker/keyboardNavHandlers.d.ts +2 -1
  96. package/dist/types/excalidraw/components/ColorPicker/topPicksDnD.d.ts +31 -0
  97. package/dist/types/excalidraw/components/CommandPalette/defaultCommandPaletteItems.d.ts +1 -2
  98. package/dist/types/excalidraw/components/ConvertElementTypePopup.d.ts +2 -2
  99. package/dist/types/excalidraw/components/CursorHint.d.ts +46 -0
  100. package/dist/types/excalidraw/components/EyeDropper.d.ts +1 -1
  101. package/dist/types/excalidraw/components/{ToolButton.d.ts → IconButton.d.ts} +16 -19
  102. package/dist/types/excalidraw/components/Island.d.ts +7 -0
  103. package/dist/types/excalidraw/components/LaserPointerButton.d.ts +2 -4
  104. package/dist/types/excalidraw/components/LayerUI.d.ts +5 -2
  105. package/dist/types/excalidraw/components/LibraryMenu.d.ts +1 -1
  106. package/dist/types/excalidraw/components/LockButton.d.ts +3 -4
  107. package/dist/types/excalidraw/components/MagicButton.d.ts +0 -2
  108. package/dist/types/excalidraw/components/MobileMenu.d.ts +4 -4
  109. package/dist/types/excalidraw/components/MobileToolbar.d.ts +9 -0
  110. package/dist/types/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.d.ts +1 -1
  111. package/dist/types/excalidraw/components/PenModeButton.d.ts +2 -5
  112. package/dist/types/excalidraw/components/Popover.d.ts +1 -3
  113. package/dist/types/excalidraw/components/{ButtonIcon.d.ts → RadioButton.d.ts} +2 -5
  114. package/dist/types/excalidraw/components/Range.d.ts +10 -4
  115. package/dist/types/excalidraw/components/SVGLayer.d.ts +1 -1
  116. package/dist/types/excalidraw/components/SearchMenu.d.ts +1 -1
  117. package/dist/types/excalidraw/components/Sidebar/Sidebar.d.ts +1 -1
  118. package/dist/types/excalidraw/components/Stats/Angle.d.ts +2 -2
  119. package/dist/types/excalidraw/components/Stats/Dimension.d.ts +2 -2
  120. package/dist/types/excalidraw/components/Stats/DragInput.d.ts +2 -2
  121. package/dist/types/excalidraw/components/Stats/MultiAngle.d.ts +2 -2
  122. package/dist/types/excalidraw/components/Stats/MultiDimension.d.ts +2 -2
  123. package/dist/types/excalidraw/components/Stats/MultiPosition.d.ts +2 -2
  124. package/dist/types/excalidraw/components/Stats/Position.d.ts +3 -3
  125. package/dist/types/excalidraw/components/Stats/utils.d.ts +1 -1
  126. package/dist/types/excalidraw/components/TTDDialog/TTDContext.d.ts +4 -4
  127. package/dist/types/excalidraw/components/TTDDialog/useTTDChatStorage.d.ts +3 -3
  128. package/dist/types/excalidraw/components/ToolPopover.d.ts +3 -6
  129. package/dist/types/excalidraw/components/Toolbar.d.ts +11 -0
  130. package/dist/types/excalidraw/components/Tools.d.ts +146 -0
  131. package/dist/types/excalidraw/components/UserList.d.ts +3 -2
  132. package/dist/types/excalidraw/components/ViewportStatusFrame/ViewportStatusFrame.d.ts +11 -0
  133. package/dist/types/excalidraw/components/canvases/InteractiveCanvas.d.ts +4 -1
  134. package/dist/types/excalidraw/components/canvases/NewElementCanvas.d.ts +1 -0
  135. package/dist/types/excalidraw/components/canvases/StaticCanvas.d.ts +1 -1
  136. package/dist/types/excalidraw/components/dropdownMenu/DropdownMenuItemContentRadio.d.ts +2 -1
  137. package/dist/types/excalidraw/components/footer/Footer.d.ts +3 -1
  138. package/dist/types/excalidraw/components/hyperlink/helpers.d.ts +2 -2
  139. package/dist/types/excalidraw/components/icons.d.ts +6 -1
  140. package/dist/types/excalidraw/components/main-menu/DefaultItems.d.ts +8 -4
  141. package/dist/types/excalidraw/components/positionElementBesideCursor.d.ts +26 -0
  142. package/dist/types/excalidraw/components/shapeActionPredicates.d.ts +39 -0
  143. package/dist/types/excalidraw/data/blob.d.ts +36 -18
  144. package/dist/types/excalidraw/data/index.d.ts +4 -4
  145. package/dist/types/excalidraw/data/json.d.ts +24 -15
  146. package/dist/types/excalidraw/data/library.d.ts +1 -1
  147. package/dist/types/excalidraw/drawShapeTrail.d.ts +16 -0
  148. package/dist/types/excalidraw/eraser/index.d.ts +2 -3
  149. package/dist/types/excalidraw/fonts/Fonts.d.ts +3 -2
  150. package/dist/types/excalidraw/hooks/useAppStateValue.d.ts +29 -0
  151. package/dist/types/excalidraw/hooks/useLibraryItemSvg.d.ts +1 -1
  152. package/dist/types/excalidraw/hooks/useTextEditorFocus.d.ts +5 -5
  153. package/dist/types/excalidraw/{laser-trails.d.ts → laserTrails.d.ts} +5 -7
  154. package/dist/types/excalidraw/lasso/index.d.ts +2 -3
  155. package/dist/types/excalidraw/lasso/utils.d.ts +2 -0
  156. package/dist/types/excalidraw/renderer/animation.d.ts +5 -1
  157. package/dist/types/excalidraw/renderer/helpers.d.ts +7 -0
  158. package/dist/types/excalidraw/renderer/interactiveScene.d.ts +1 -3
  159. package/dist/types/excalidraw/scene/Renderer.d.ts +427 -19
  160. package/dist/types/excalidraw/scene/export.d.ts +3 -3
  161. package/dist/types/excalidraw/scene/index.d.ts +2 -2
  162. package/dist/types/excalidraw/scene/types.d.ts +4 -3
  163. package/dist/types/excalidraw/snapping.d.ts +7 -7
  164. package/dist/types/excalidraw/textAutoResizeHandle.d.ts +15 -0
  165. package/dist/types/excalidraw/types.d.ts +436 -24
  166. package/dist/types/excalidraw/viewport.d.ts +275 -0
  167. package/dist/types/excalidraw/wysiwyg/textWysiwyg.d.ts +6 -3
  168. package/dist/types/fractional-indexing/src/index.d.ts +29 -0
  169. package/dist/types/laser-pointer/src/index.d.ts +2 -0
  170. package/dist/types/laser-pointer/src/math.d.ts +16 -0
  171. package/dist/types/laser-pointer/src/simplify.d.ts +2 -0
  172. package/dist/types/laser-pointer/src/state.d.ts +36 -0
  173. package/dist/types/math/src/constants.d.ts +0 -1
  174. package/dist/types/math/src/curve.d.ts +23 -13
  175. package/dist/types/math/src/index.d.ts +1 -0
  176. package/dist/types/math/src/pca.d.ts +79 -0
  177. package/dist/types/math/src/point.d.ts +2 -1
  178. package/dist/types/math/src/polygon.d.ts +25 -1
  179. package/dist/types/math/src/segment.d.ts +6 -0
  180. package/dist/types/utils/src/export.d.ts +3 -3
  181. package/dist/types/utils/src/index.d.ts +1 -2
  182. package/package.json +2 -2
  183. package/dist/types/excalidraw/animation-frame-handler.d.ts +0 -16
  184. package/dist/types/excalidraw/components/FollowMode/FollowMode.d.ts +0 -10
  185. package/dist/types/excalidraw/components/HandButton.d.ts +0 -10
  186. package/dist/types/excalidraw/components/MobileToolBar.d.ts +0 -10
  187. package/dist/types/excalidraw/components/shapes.d.ts +0 -263
  188. package/dist/types/excalidraw/cursor.d.ts +0 -5
  189. package/dist/types/excalidraw/scene/scroll.d.ts +0 -18
  190. package/dist/types/excalidraw/scene/zoom.d.ts +0 -12
  191. package/dist/types/utils/src/bbox.d.ts +0 -9
  192. package/dist/types/utils/src/withinBounds.d.ts +0 -19
@@ -1,21 +1,29 @@
1
1
  import React from "react";
2
2
  import { AppEventBus, type EXPORT_IMAGE_TYPES, Emitter, type EditorInterface, type StylesPanelMode } from "@excalidraw/common";
3
- import { LinearElementEditor, FlowChartCreator, Scene, Store, type ElementUpdate, StoreDelta, type ApplyToOptions } from "@excalidraw/element";
4
- import type { ExcalidrawElement, NonDeleted, NonDeletedExcalidrawElement, ExcalidrawFrameLikeElement, ExcalidrawIframeElement, ExcalidrawEmbeddableElement, Ordered, SceneElementsMap } from "@excalidraw/element/types";
3
+ import { LinearElementEditor, Scene, Store, type ElementUpdate, StoreDelta, type ApplyToOptions } from "@excalidraw/element";
4
+ import type { LocalPoint, Radians } from "@excalidraw/math";
5
+ import type { ExcalidrawElement, ExcalidrawTextElement, NonDeleted, NonDeletedExcalidrawElement, ExcalidrawTextContainer, ExcalidrawFrameLikeElement, ExcalidrawIframeElement, ExcalidrawEmbeddableElement, Ordered, SceneElementsMap } from "@excalidraw/element/types";
5
6
  import type { Mutable } from "@excalidraw/common/utility-types";
6
7
  import { ActionManager } from "../actions/manager";
7
- import { AnimationFrameHandler } from "../animation-frame-handler";
8
8
  import { History } from "../history";
9
9
  import { Fonts } from "../fonts";
10
10
  import { type WritableAtom } from "../editor-jotai";
11
11
  import { Renderer } from "../scene/Renderer";
12
- import { LaserTrails } from "../laser-trails";
12
+ import { type SetViewportOptions } from "../viewport";
13
+ import { LaserTrails } from "../laserTrails";
13
14
  import { isOverScrollBars } from "../scene/scrollbars";
14
15
  import { LassoTrail } from "../lasso";
15
16
  import { EraserTrail } from "../eraser";
17
+ import { AppArrowText } from "./App.arrowText";
18
+ import { AppBucketFill } from "./App.bucketFill";
19
+ import { AppCursor } from "./App.cursor";
20
+ import { AppDrawShape } from "./App.drawshape";
21
+ import { AppFlowchart } from "./App.flowchart";
22
+ import { AppViewport } from "./App.viewport";
23
+ import { CursorHints } from "./CursorHint";
16
24
  import { type OnStateChange } from "./AppStateObserver";
17
25
  import type { ExportedElements } from "../data";
18
- import type { AppClassProperties, AppProps, AppState, ExcalidrawImperativeAPI, BinaryFiles, LibraryItems, SceneData, FrameNameBoundsCache, SidebarName, SidebarTabName, ToolType, OnUserFollowedPayload, ExcalidrawImperativeAPIEventMap, GenerateDiagramToCode, NullableGridSize, Offsets } from "../types";
26
+ import type { AppClassProperties, AppProps, AppState, ExcalidrawImperativeAPI, BinaryFiles, LibraryItems, SceneData, FrameNameBoundsCache, SidebarName, SidebarTabName, ToolType, OnUserFollowedPayload, ExcalidrawImperativeAPIEventMap, GenerateDiagramToCode, NullableGridSize, UIConfig } from "../types";
19
27
  import type { RoughCanvas } from "roughjs/bin/canvas";
20
28
  import type { ActionResult } from "../actions/types";
21
29
  declare const editorLifecycleEventBehavior: {
@@ -74,10 +82,15 @@ declare class App extends React.Component<AppProps, AppState> {
74
82
  editorInterface: EditorInterface;
75
83
  private stylesPanelMode;
76
84
  private excalidrawContainerRef;
85
+ get ownerDocument(): Document;
86
+ get ownerWindow(): Window & typeof globalThis;
77
87
  scene: Scene;
78
88
  fonts: Fonts;
79
89
  renderer: Renderer;
80
90
  visibleElements: readonly NonDeletedExcalidrawElement[];
91
+ /** whether the last render had any renderable elements (excludes e.g. the
92
+ * in-progress `newElement` and the edited text element) */
93
+ private hasRenderableElements;
81
94
  private resizeObserver;
82
95
  library: AppClassProperties["library"];
83
96
  libraryItemsFromStorage: LibraryItems | undefined;
@@ -107,31 +120,34 @@ declare class App extends React.Component<AppProps, AppState> {
107
120
  onEvent: AppEventBus<ExcalidrawImperativeAPIEventMap, typeof editorLifecycleEventBehavior>["on"];
108
121
  private appStateObserver;
109
122
  onStateChange: OnStateChange;
110
- flowChartCreator: FlowChartCreator;
111
- private flowChartNavigator;
123
+ bucketFill: AppBucketFill;
124
+ flowchart: AppFlowchart;
125
+ cursor: AppCursor;
126
+ arrowText: AppArrowText;
127
+ viewport: AppViewport;
112
128
  bindModeHandler: ReturnType<typeof setTimeout> | null;
129
+ private textWysiwygSubmitHandler;
113
130
  hitLinkElement?: NonDeletedExcalidrawElement;
114
131
  lastPointerDownEvent: React.PointerEvent<HTMLElement> | null;
115
132
  lastPointerUpEvent: React.PointerEvent<HTMLElement> | PointerEvent | null;
133
+ lastPointerUpIsDoubleClick: boolean;
116
134
  lastPointerMoveEvent: PointerEvent | null;
117
135
  /** current frame pointer cords */
118
136
  lastPointerMoveCoords: {
119
137
  x: number;
120
138
  y: number;
121
139
  } | null;
140
+ private lastCompletedCanvasClicks;
122
141
  /** previous frame pointer coords */
123
142
  previousPointerMoveCoords: {
124
143
  x: number;
125
144
  y: number;
126
145
  } | null;
127
- lastViewportPosition: {
128
- x: number;
129
- y: number;
130
- };
131
- animationFrameHandler: AnimationFrameHandler;
146
+ drawShape: AppDrawShape;
132
147
  laserTrails: LaserTrails;
133
148
  eraserTrail: EraserTrail;
134
149
  lassoTrail: LassoTrail;
150
+ cursorHints: CursorHints;
135
151
  onChangeEmitter: Emitter<[elements: readonly ExcalidrawElement[], appState: AppState, files: BinaryFiles]>;
136
152
  onPointerDownEmitter: Emitter<[activeTool: {
137
153
  lastActiveTool: import("../types").ActiveTool | null;
@@ -171,6 +187,7 @@ declare class App extends React.Component<AppProps, AppState> {
171
187
  wasAddedToSelection: boolean;
172
188
  hasBeenDuplicated: boolean;
173
189
  hasHitCommonBoundingBoxOfSelectedElements: boolean;
190
+ arrowLabel: boolean;
174
191
  };
175
192
  withCmdOrCtrl: boolean;
176
193
  drag: {
@@ -233,6 +250,7 @@ declare class App extends React.Component<AppProps, AppState> {
233
250
  wasAddedToSelection: boolean;
234
251
  hasBeenDuplicated: boolean;
235
252
  hasHitCommonBoundingBoxOfSelectedElements: boolean;
253
+ arrowLabel: boolean;
236
254
  };
237
255
  withCmdOrCtrl: boolean;
238
256
  drag: {
@@ -266,6 +284,75 @@ declare class App extends React.Component<AppProps, AppState> {
266
284
  api: ExcalidrawImperativeAPI;
267
285
  private createExcalidrawAPI;
268
286
  constructor(props: AppProps);
287
+ /**
288
+ * Whether the editor accepts user input (pointer, keyboard, wheel, touch,
289
+ * clipboard, drag&drop). When `false`, the editor is fully inert for the
290
+ * user, but remains controllable through the imperative API.
291
+ *
292
+ * All user-input entry points must consult this getter (directly or by
293
+ * not being attached/rendered at all).
294
+ */
295
+ isInteractionEnabled(props?: Pick<AppProps, "interaction">): boolean;
296
+ /**
297
+ * Whether element links render their link icon and are clickable.
298
+ * True when fully interactive, or when `interaction: { enabled: { links:
299
+ * true } }`
300
+ * (in which case clicking anywhere on a linked element opens the link,
301
+ * same as in view mode).
302
+ */
303
+ isLinksEnabled(props?: Pick<AppProps, "interaction">): boolean;
304
+ /**
305
+ * Whether canvas navigation — panning & zooming, view-mode style — is
306
+ * enabled. True when fully interactive, or when `interaction: { enabled:
307
+ * { navigation: true } }`. Respects `appState.scrollConstraints`.
308
+ */
309
+ isNavigationEnabled(props?: Pick<AppProps, "interaction">): boolean;
310
+ /**
311
+ * Whether embeddable & iframe elements are interactive (hover & click to
312
+ * activate, view-mode style). True when fully interactive, or when
313
+ * allowed via `interaction.enabled.embeds` / `.interactiveContent`.
314
+ */
315
+ isEmbedsEnabled(props?: Pick<AppProps, "interaction">): boolean;
316
+ /**
317
+ * Whether the browser's own zoom (ctrl/cmd + wheel, pinch, keyboard
318
+ * shortcuts) stays available over the non-interactive editor.
319
+ * Prevented by default.
320
+ */
321
+ isBrowserZoomEnabled(props?: Pick<AppProps, "interaction">): boolean;
322
+ /**
323
+ * Whether the tool can be activated & driven by user input. False when
324
+ * disabled via `UIOptions.tools`, or when the editor is non-interactive
325
+ * and the tool isn't kept user-driven via `interaction.enabled.tools`.
326
+ *
327
+ * (Once UI tool availability is split from input availability — e.g.
328
+ * `props.ui.tools` vs `interaction.disabled.tools` — the UI axis moves
329
+ * out into its own predicate.)
330
+ *
331
+ * We purposely widen the `tool` type so this helper can be called with
332
+ * any tool without having to type check it.
333
+ */
334
+ isToolSupported: <T extends ToolType | "custom">(tool: T, props?: Pick<AppProps, "interaction" | "UIOptions">) => boolean;
335
+ /**
336
+ * Whether the active tool is locked in place — via the tool lock
337
+ * (padlock / Q) or by being host-forced (`props.activeTool`). A locked
338
+ * tool doesn't revert to the selection tool after use, and elements drawn
339
+ * with it aren't selected. Forcing deliberately does not mutate
340
+ * `activeTool.locked`, which is the user's persisted padlock preference.
341
+ */
342
+ isToolLocked(): boolean;
343
+ /**
344
+ * Whether the active tool captures the primary pointer instead of the
345
+ * view-mode drag-to-pan — the laser and host-implemented custom tools do;
346
+ * while non-interactive, any tool allowed via
347
+ * `interaction.enabled.tools` does. (Editing tools capture the pointer
348
+ * trivially since view mode implies they're not active; this predicate only
349
+ * matters where view-mode gates apply.)
350
+ */
351
+ isActiveToolPointerCapturing(): boolean;
352
+ /** Whether Excalidraw's full default UI is rendered. */
353
+ isDefaultUIEnabled(props?: Pick<AppProps, "ui">): boolean;
354
+ /** Whether an individual default UI control is rendered. */
355
+ isUIControlEnabled(control: keyof UIConfig["enabled"], props?: Pick<AppProps, "ui">): boolean;
269
356
  updateEditorAtom: <Value, Args extends unknown[], Result>(atom: WritableAtom<Value, Args, Result>, ...args: Args) => Result;
270
357
  private onWindowMessage;
271
358
  private handleSkipBindMode;
@@ -278,10 +365,17 @@ declare class App extends React.Component<AppProps, AppState> {
278
365
  * If disabled, returns null.
279
366
  */
280
367
  getEffectiveGridSize: () => NullableGridSize;
368
+ private getTextCreationGridPoint;
281
369
  private getHTMLIFrameElement;
370
+ /**
371
+ * AI-generated iframe elements aren't interactive while their generation
372
+ * is still in progress (the partial content is render-only).
373
+ */
374
+ private isIframeLikeInteractive;
282
375
  private handleIframeLikeElementHover;
283
376
  /** @returns true if iframe-like element click handled */
284
377
  private handleIframeLikeCenterClick;
378
+ private isDoubleClick;
285
379
  private isIframeLikeElementCenter;
286
380
  private updateEmbedValidationStatus;
287
381
  private updateEmbeddables;
@@ -298,7 +392,7 @@ declare class App extends React.Component<AppProps, AppState> {
298
392
  getSceneElements: () => readonly Ordered<NonDeletedExcalidrawElement>[];
299
393
  onInsertElements: (elements: readonly ExcalidrawElement[]) => void;
300
394
  onExportImage: (type: keyof typeof EXPORT_IMAGE_TYPES, elements: ExportedElements, opts: {
301
- exportingFrame: ExcalidrawFrameLikeElement | null;
395
+ exportingFrame: NonDeleted<ExcalidrawFrameLikeElement> | null;
302
396
  }) => Promise<void>;
303
397
  private magicGenerations;
304
398
  private updateMagicGeneration;
@@ -314,9 +408,34 @@ declare class App extends React.Component<AppProps, AppState> {
314
408
  private openEyeDropper;
315
409
  dismissLinearEditor: () => void;
316
410
  syncActionResult: (actionResult: ActionResult) => void;
411
+ scheduleCapture: () => void;
317
412
  private onBlur;
318
413
  private onUnload;
319
414
  private disableEvent;
415
+ private preventBrowserZoomWheel;
416
+ private handleNavigationModeKeyDown;
417
+ /**
418
+ * PageUp/PageDown scroll the canvas by a page — vertically, or
419
+ * horizontally with shift. Respects `appState.scrollConstraints`
420
+ * (via `viewport.translate`).
421
+ */
422
+ private maybeHandlePageScrollKeyDown;
423
+ private preventBrowserZoomKeyDown;
424
+ /** Ends active input sessions before switching to a view-mode/non-interactive
425
+ * mode. */
426
+ private terminateActiveInteraction;
427
+ private handleInteractionStateChange;
428
+ /** whether the two values reference the same tool (incl. custom subtype) */
429
+ private isSameForcedTool;
430
+ /**
431
+ * Keeps `state.activeTool` synced to the host-controlled
432
+ * `props.activeTool`. `setActiveTool` refuses non-matching activations
433
+ * while forced (user input, API); this backstop covers the writers that
434
+ * bypass the funnel (`actionFinalize`/`actionDeselect`, `restore()` on
435
+ * scene load, ...) and re-applies the tool once it becomes activatable
436
+ * (e.g. `interaction` config changes).
437
+ */
438
+ private handleForcedToolChange;
320
439
  private resetHistory;
321
440
  private resetStore;
322
441
  /**
@@ -356,7 +475,8 @@ declare class App extends React.Component<AppProps, AppState> {
356
475
  clientY: number;
357
476
  } | "cursor" | "center";
358
477
  retainSeed?: boolean;
359
- fitToContent?: boolean;
478
+ fit?: SetViewportOptions["fit"];
479
+ preserveFrameChildrenOrder?: boolean;
360
480
  }) => void;
361
481
  private addElementsFromMixedContentPaste;
362
482
  private addTextFromPaste;
@@ -365,47 +485,14 @@ declare class App extends React.Component<AppProps, AppState> {
365
485
  toggleLock: (source?: "keyboard" | "ui") => void;
366
486
  updateFrameRendering: (opts: Partial<AppState["frameRendering"]> | ((prevState: AppState["frameRendering"]) => Partial<AppState["frameRendering"]>)) => void;
367
487
  togglePenMode: (force: boolean | null) => void;
368
- onHandToolToggle: () => void;
369
- /**
370
- * Zooms on canvas viewport center
371
- */
372
- zoomCanvas: (
373
- /**
374
- * Decimal fraction, auto-clamped between MIN_ZOOM and MAX_ZOOM.
375
- * 1 = 100% zoom, 2 = 200% zoom, 0.5 = 50% zoom
376
- */
377
- value: number) => void;
378
- private cancelInProgressAnimation;
379
- scrollToContent: (
380
- /**
381
- * target to scroll to
382
- *
383
- * - string - id of element or group, or url containing elementLink
384
- * - ExcalidrawElement | ExcalidrawElement[] - element(s) objects
385
- */
386
- target?: string | ExcalidrawElement | readonly ExcalidrawElement[], opts?: ({
387
- fitToContent?: boolean;
388
- fitToViewport?: never;
389
- viewportZoomFactor?: number;
390
- animate?: boolean;
391
- duration?: number;
392
- } | {
393
- fitToContent?: never;
394
- fitToViewport?: boolean;
395
- /** when fitToViewport=true, how much screen should the content cover,
396
- * between 0.1 (10%) and 1 (100%)
397
- */
398
- viewportZoomFactor?: number;
399
- animate?: boolean;
400
- duration?: number;
401
- }) & {
402
- minZoom?: number;
403
- maxZoom?: number;
404
- canvasOffsets?: Offsets;
405
- }) => void;
406
- private maybeUnfollowRemoteUser;
407
- /** use when changing scrollX/scrollY/zoom based on user interaction */
408
- private translateCanvas;
488
+ revealIfHidden: (elements: NonDeletedExcalidrawElement[]) => void;
489
+ /** emits a follow/unfollow intent to the host (which owns the
490
+ * `userToFollow` state) via both the `onUserFollow` prop and the
491
+ * imperative API emitter */
492
+ emitUserFollowIntent: (payload: OnUserFollowedPayload) => void;
493
+ /** emits an UNFOLLOW intent if currently following someone — use on
494
+ * user-initiated viewport changes which should break follow mode */
495
+ requestUnfollow: () => void;
409
496
  setToast: (toast: AppState["toast"]) => void;
410
497
  restoreFileFromShare: () => Promise<void>;
411
498
  /**
@@ -433,7 +520,9 @@ declare class App extends React.Component<AppProps, AppState> {
433
520
  }) => void;
434
521
  applyDeltas: (deltas: StoreDelta[], options?: ApplyToOptions) => [SceneElementsMap, AppState, boolean];
435
522
  mutateElement: <TElement extends Mutable<ExcalidrawElement>>(element: TElement, updates: ElementUpdate<TElement>, informMutation?: boolean) => TElement;
436
- private triggerRender;
523
+ triggerRender: (
524
+ /** force always re-renders canvas even if no change */
525
+ force?: boolean) => void;
437
526
  /**
438
527
  * @returns whether the menu was toggled on or off
439
528
  */
@@ -443,10 +532,8 @@ declare class App extends React.Component<AppProps, AppState> {
443
532
  force?: boolean;
444
533
  }) => boolean;
445
534
  private updateCurrentCursorPosition;
446
- getEditorUIOffsets: () => Offsets;
447
535
  private onKeyDown;
448
536
  private onKeyUp;
449
- private isToolSupported;
450
537
  setActiveTool: (tool: ({
451
538
  type: ToolType;
452
539
  } | {
@@ -455,10 +542,18 @@ declare class App extends React.Component<AppProps, AppState> {
455
542
  }) & {
456
543
  locked?: boolean;
457
544
  fromSelection?: boolean;
458
- }, keepSelection?: boolean) => void;
545
+ }, opts?: {
546
+ keepSelection?: boolean;
547
+ /**
548
+ * When `true`, re-activating an already-active toggle tool (see
549
+ * `TOGGLE_TOOLS`) switches back to the previously active tool.
550
+ * Activation is idempotent by default; toggle tools always record the
551
+ * previously active tool regardless (so ESC and the next `toggle`
552
+ * activation can switch back to it).
553
+ */
554
+ toggle?: boolean;
555
+ }) => void;
459
556
  setOpenDialog: (dialogType: AppState["openDialog"]) => void;
460
- private setCursor;
461
- private resetCursor;
462
557
  /**
463
558
  * returns whether user is making a gesture with >= 2 fingers (points)
464
559
  * on o touch screen (not on a trackpad). Currently only relates to Darwin
@@ -472,22 +567,239 @@ declare class App extends React.Component<AppProps, AppState> {
472
567
  private onGestureEnd;
473
568
  private handleTextWysiwyg;
474
569
  private deselectElements;
475
- private getTextElementAtPosition;
476
- private getElementAtPosition;
477
- private getElementsAtPosition;
570
+ private getSelectedTextElement;
571
+ private getSelectedTextEditingContainerAtPosition;
572
+ getTextElementAtPosition(x: number, y: number): NonDeleted<ExcalidrawTextElement> | null;
573
+ private isHittingTextAutoResizeHandle;
574
+ private handleTextAutoResizeHandlePointerDown;
575
+ getElementAtPosition(x: number, y: number, opts?: ({
576
+ includeBoundTextElement?: boolean;
577
+ includeLockedElements?: boolean;
578
+ } | {
579
+ allHitElements: NonDeleted<ExcalidrawElement>[];
580
+ }) & {
581
+ preferSelected?: boolean;
582
+ }): NonDeleted<ExcalidrawElement> | null;
583
+ getElementsAtPosition(x: number, y: number, opts?: {
584
+ includeBoundTextElement?: boolean;
585
+ includeLockedElements?: boolean;
586
+ }): NonDeleted<ExcalidrawElement>[];
478
587
  getElementHitThreshold(element: ExcalidrawElement): number;
479
- private hitElement;
480
- private getTextBindableContainerAtPosition;
588
+ hitElement(x: number, y: number, element: NonDeletedExcalidrawElement, considerBoundingBox?: boolean): boolean;
589
+ getTextBindableContainerAtPosition(x: number, y: number): (Readonly<{
590
+ id: string;
591
+ x: number;
592
+ y: number;
593
+ strokeColor: string;
594
+ backgroundColor: string;
595
+ fillStyle: import("@excalidraw/element/types").FillStyle;
596
+ strokeWidth: number;
597
+ strokeStyle: import("@excalidraw/element/types").StrokeStyle;
598
+ roundness: null | {
599
+ type: import("@excalidraw/element/types").RoundnessType;
600
+ value?: number;
601
+ };
602
+ roughness: number;
603
+ opacity: number;
604
+ width: number;
605
+ height: number;
606
+ angle: Radians;
607
+ seed: number;
608
+ version: number;
609
+ versionNonce: number;
610
+ index: import("@excalidraw/element/types").FractionalIndex | null;
611
+ isDeleted: boolean;
612
+ groupIds: readonly import("@excalidraw/element/types").GroupId[];
613
+ frameId: string | null;
614
+ boundElements: readonly import("@excalidraw/element/types").BoundElement[] | null;
615
+ updated: number;
616
+ link: string | null;
617
+ locked: boolean;
618
+ customData?: Record<string, any>;
619
+ }> & {
620
+ type: "rectangle";
621
+ } & {
622
+ isDeleted: false;
623
+ }) | (Readonly<{
624
+ id: string;
625
+ x: number;
626
+ y: number;
627
+ strokeColor: string;
628
+ backgroundColor: string;
629
+ fillStyle: import("@excalidraw/element/types").FillStyle;
630
+ strokeWidth: number;
631
+ strokeStyle: import("@excalidraw/element/types").StrokeStyle;
632
+ roundness: null | {
633
+ type: import("@excalidraw/element/types").RoundnessType;
634
+ value?: number;
635
+ };
636
+ roughness: number;
637
+ opacity: number;
638
+ width: number;
639
+ height: number;
640
+ angle: Radians;
641
+ seed: number;
642
+ version: number;
643
+ versionNonce: number;
644
+ index: import("@excalidraw/element/types").FractionalIndex | null;
645
+ isDeleted: boolean;
646
+ groupIds: readonly import("@excalidraw/element/types").GroupId[];
647
+ frameId: string | null;
648
+ boundElements: readonly import("@excalidraw/element/types").BoundElement[] | null;
649
+ updated: number;
650
+ link: string | null;
651
+ locked: boolean;
652
+ customData?: Record<string, any>;
653
+ }> & {
654
+ type: "diamond";
655
+ } & {
656
+ isDeleted: false;
657
+ }) | (Readonly<{
658
+ id: string;
659
+ x: number;
660
+ y: number;
661
+ strokeColor: string;
662
+ backgroundColor: string;
663
+ fillStyle: import("@excalidraw/element/types").FillStyle;
664
+ strokeWidth: number;
665
+ strokeStyle: import("@excalidraw/element/types").StrokeStyle;
666
+ roundness: null | {
667
+ type: import("@excalidraw/element/types").RoundnessType;
668
+ value?: number;
669
+ };
670
+ roughness: number;
671
+ opacity: number;
672
+ width: number;
673
+ height: number;
674
+ angle: Radians;
675
+ seed: number;
676
+ version: number;
677
+ versionNonce: number;
678
+ index: import("@excalidraw/element/types").FractionalIndex | null;
679
+ isDeleted: boolean;
680
+ groupIds: readonly import("@excalidraw/element/types").GroupId[];
681
+ frameId: string | null;
682
+ boundElements: readonly import("@excalidraw/element/types").BoundElement[] | null;
683
+ updated: number;
684
+ link: string | null;
685
+ locked: boolean;
686
+ customData?: Record<string, any>;
687
+ }> & {
688
+ type: "ellipse";
689
+ } & {
690
+ isDeleted: false;
691
+ }) | (Readonly<{
692
+ id: string;
693
+ x: number;
694
+ y: number;
695
+ strokeColor: string;
696
+ backgroundColor: string;
697
+ fillStyle: import("@excalidraw/element/types").FillStyle;
698
+ strokeWidth: number;
699
+ strokeStyle: import("@excalidraw/element/types").StrokeStyle;
700
+ roundness: null | {
701
+ type: import("@excalidraw/element/types").RoundnessType;
702
+ value?: number;
703
+ };
704
+ roughness: number;
705
+ opacity: number;
706
+ width: number;
707
+ height: number;
708
+ angle: Radians;
709
+ seed: number;
710
+ version: number;
711
+ versionNonce: number;
712
+ index: import("@excalidraw/element/types").FractionalIndex | null;
713
+ isDeleted: boolean;
714
+ groupIds: readonly import("@excalidraw/element/types").GroupId[];
715
+ frameId: string | null;
716
+ boundElements: readonly import("@excalidraw/element/types").BoundElement[] | null;
717
+ updated: number;
718
+ link: string | null;
719
+ locked: boolean;
720
+ customData?: Record<string, any>;
721
+ }> & Readonly<{
722
+ type: "line" | "arrow";
723
+ points: readonly LocalPoint[];
724
+ startBinding: import("@excalidraw/element/types").FixedPointBinding | null;
725
+ endBinding: import("@excalidraw/element/types").FixedPointBinding | null;
726
+ startArrowhead: import("@excalidraw/element/types").Arrowhead | null;
727
+ endArrowhead: import("@excalidraw/element/types").Arrowhead | null;
728
+ }> & Readonly<{
729
+ type: "arrow";
730
+ elbowed: boolean;
731
+ }> & {
732
+ isDeleted: false;
733
+ }) | null;
734
+ /**
735
+ * Whether a text element's content is still being authored.
736
+ *
737
+ * Creating a text reverts the tool to selection during pointerdown, so the
738
+ * pointerup that follows looks like an ordinary canvas click and would
739
+ * capture the still-empty element as a history entry of its own. Undo would
740
+ * then rewind only the typing, restoring an invisible, zero-content element
741
+ * (and, for an endpoint label, leaving the arrow bound to it) rather than
742
+ * removing it. The editor's own submit captures the finished text instead,
743
+ * so the whole create-and-type lands in a single entry.
744
+ */
745
+ private isEditingTextContent;
481
746
  private startTextEditing;
482
747
  private startImageCropping;
483
748
  private finishImageCropping;
749
+ private shouldHandleBrowserCanvasDoubleClick;
484
750
  private handleCanvasDoubleClick;
751
+ private handleCanvasClick;
485
752
  private getElementLinkAtPosition;
486
753
  private handleElementLinkClick;
487
- private getTopLayerFrameAtSceneCoords;
754
+ /**
755
+ * Applies (or clears) the element-link hover affordances — pointer cursor
756
+ * and tooltip — based on the current `hitLinkElement`. Returns whether a
757
+ * link is being hovered.
758
+ */
759
+ private applyElementLinkHoverAffordance;
760
+ /**
761
+ * On touchscreens (where no hover precedes the tap) re-derives
762
+ * `hitLinkElement`, then opens the hit element link, if any.
763
+ * Returns whether a link click was handled.
764
+ */
765
+ private maybeHandleElementLinkClick;
766
+ /**
767
+ * Restricted pointer handling for the non-interactive editor with links
768
+ * and/or embeds allowed (`interaction.enabled.links` / `.embeds` /
769
+ * `.interactiveContent`) — runs only the element-link & embed concerns
770
+ * (shared with the full pointer handlers above) so they behave like in
771
+ * view mode without the rest of the canvas pointer machinery.
772
+ */
773
+ private handleInteractiveContentPointerMove;
774
+ private handleInteractiveContentPointerUp;
775
+ /**
776
+ * finds candidate frame under cursor (when dragging frame children/elements
777
+ * inside frames)
778
+ */
779
+ getTopLayerFrameAtSceneCoords: (
780
+ /**
781
+ * should be already grid aligned (basically should be what the call site
782
+ * sets the element's coords to, if applicable)
783
+ */
784
+ sceneCoords: {
785
+ x: number;
786
+ y: number;
787
+ }, opts?: {
788
+ /** to exclude selected elements when dragging, etc. */
789
+ excludeElementIds?: AppState["selectedElementIds"];
790
+ currentFrameId?: ExcalidrawElement["frameId"];
791
+ }) => NonDeleted<ExcalidrawFrameLikeElement> | null;
792
+ private updateFrameToHighlight;
793
+ private maybeUpdateFrameToHighlightOnPointerMove;
794
+ insertNewElements: (elements: readonly ExcalidrawElement[]) => void;
795
+ insertNewElement: (element: ExcalidrawElement) => void;
488
796
  private handleCanvasPointerMove;
489
797
  private handleEraser;
490
798
  private handleTouchMove;
799
+ /**
800
+ * Applies the hover affordances of a selected linear element: the cursor,
801
+ * plus the hovered-handle state that renders them highlighted.
802
+ */
491
803
  handleHoverSelectedLinearElement(linearElementEditor: LinearElementEditor, scenePointerX: number, scenePointerY: number): void;
492
804
  private handleCanvasPointerDown;
493
805
  private handleCanvasPointerUp;
@@ -501,6 +813,11 @@ declare class App extends React.Component<AppProps, AppState> {
501
813
  private maybeCleanupAfterMissingPointerUp;
502
814
  handleCanvasPanUsingWheelOrSpaceDrag: (event: React.PointerEvent<HTMLElement> | MouseEvent) => boolean;
503
815
  private updateGestureOnPointerDown;
816
+ /**
817
+ * Tracks the pointer within the ongoing multi-touch gesture and applies
818
+ * the two-finger pinch zoom/pan, if any.
819
+ */
820
+ private updateMultiTouchGesture;
504
821
  private initialPointerDownState;
505
822
  private handleDraggingScrollBar;
506
823
  private clearSelectionIfNotUsingSelection;
@@ -526,6 +843,7 @@ declare class App extends React.Component<AppProps, AppState> {
526
843
  private newImagePlaceholder;
527
844
  private handleLinearElementOnPointerDown;
528
845
  private getCurrentItemRoundness;
846
+ private getCurrentItemStrokeWidth;
529
847
  private createGenericElementOnPointerDown;
530
848
  private createFrameElementOnPointerDown;
531
849
  private maybeCacheReferenceSnapPoints;
@@ -565,7 +883,12 @@ declare class App extends React.Component<AppProps, AppState> {
565
883
  private maybeHandleResize;
566
884
  private getContextMenuItems;
567
885
  private handleWheel;
568
- private getTextWysiwygSnappedToCenterPosition;
886
+ getTextWysiwygSnappedToCenterPosition(x: number, y: number, appState: AppState, container?: ExcalidrawTextContainer | null): {
887
+ viewportX: number;
888
+ viewportY: number;
889
+ elementCenterX: number;
890
+ elementCenterY: number;
891
+ } | undefined;
569
892
  private savePointer;
570
893
  private resetShouldCacheIgnoreZoomDebounced;
571
894
  private updateDOMRect;
@@ -0,0 +1,55 @@
1
+ import { DrawShapeTrail } from "../drawShapeTrail";
2
+ import type App from "./App";
3
+ import type { PointerDownState } from "../types";
4
+ /**
5
+ * Captures the App state management for the drawShape tool (free-form
6
+ * sketch converted into a recognized excalidraw element). Pointer events
7
+ * are piped here from App.
8
+ *
9
+ * The gesture is committed by `finalize()` — recognize → (maybe upgrade
10
+ * line to arrow) → insert → bind endpoints — which is invoked from within
11
+ * `actionFinalize`, the editor's single finalization funnel. Whatever
12
+ * triggers a finalize (the gesture's own pointerup, a mid-gesture paste
13
+ * switching tools, …), the pending sketch resolves there exactly once.
14
+ */
15
+ export declare class AppDrawShape {
16
+ private app;
17
+ trail: DrawShapeTrail;
18
+ /** a pointerdown started a sketch that `finalize()` hasn't resolved yet */
19
+ private gestureInProgress;
20
+ constructor(app: App);
21
+ stop: () => void;
22
+ hasPendingGesture: () => boolean;
23
+ handlePointerDown: (pointerDownState: PointerDownState) => void;
24
+ /** returns true when the pointermove was consumed by the shape preview */
25
+ handlePointerMove: (pointerCoords: {
26
+ x: number;
27
+ y: number;
28
+ }) => boolean;
29
+ /**
30
+ * Binds both endpoints of a freshly inserted drawShape arrow to the
31
+ * bindable elements they hover, if any.
32
+ *
33
+ * Endpoints bind in "orbit" mode — the arrow starts/ends at the target's
34
+ * outline — even when the stroke was started or released inside the shape
35
+ * (a sketched connector aims at the shape, not at a point inside it). The
36
+ * exception is a sketch contained in a single shape: both ends then bind
37
+ * "inside" and stay where they were drawn, like the interactive
38
+ * inside→inside flow.
39
+ */
40
+ private bindRecognizedArrow;
41
+ /**
42
+ * A sketched line that connects a bindable element with something else —
43
+ * another element or blank canvas — was meant as a connector: upgrade it
44
+ * to an arrow (called before insertion). A line touching no shape, or
45
+ * contained in a single shape (an annotation, not a connector), stays a
46
+ * line.
47
+ */
48
+ private maybeUpgradeLineToArrow;
49
+ /**
50
+ * Commits the pending sketch, if any, and clears the trail. Invoked from
51
+ * within `actionFinalize` — never call directly, execute `actionFinalize`
52
+ * instead so element insertion flows into the action's returned elements.
53
+ */
54
+ finalize: () => void;
55
+ }