@excalidraw/math 0.18.0-2b0e4c9 → 0.18.0-39103bd

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 (172) hide show
  1. package/dist/dev/index.js +303 -100
  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 +1 -1
  5. package/dist/types/common/src/constants.d.ts +11 -7
  6. package/dist/types/common/src/points.d.ts +1 -1
  7. package/dist/types/common/src/utils.d.ts +1 -43
  8. package/dist/types/element/src/Scene.d.ts +6 -4
  9. package/dist/types/element/src/align.d.ts +2 -2
  10. package/dist/types/element/src/arrowEndpointText.d.ts +49 -0
  11. package/dist/types/element/src/arrows/focus.d.ts +5 -2
  12. package/dist/types/element/src/binding.d.ts +17 -8
  13. package/dist/types/element/src/bounds.d.ts +22 -7
  14. package/dist/types/element/src/collision.d.ts +1 -1
  15. package/dist/types/element/src/comparisons.d.ts +5 -4
  16. package/dist/types/element/src/convertToShape.d.ts +23 -0
  17. package/dist/types/element/src/distribute.d.ts +2 -2
  18. package/dist/types/element/src/dragElements.d.ts +27 -0
  19. package/dist/types/element/src/duplicate.d.ts +4 -3
  20. package/dist/types/element/src/embeddable.d.ts +2 -2
  21. package/dist/types/element/src/flowchart.d.ts +7 -7
  22. package/dist/types/element/src/fractionalIndex.d.ts +2 -2
  23. package/dist/types/element/src/frame.d.ts +9 -8
  24. package/dist/types/element/src/groups.d.ts +9 -9
  25. package/dist/types/element/src/index.d.ts +3 -1
  26. package/dist/types/element/src/linearElementEditor.d.ts +17 -10
  27. package/dist/types/element/src/newElement.d.ts +14 -0
  28. package/dist/types/element/src/renderElement.d.ts +0 -3
  29. package/dist/types/element/src/resizeElements.d.ts +2 -2
  30. package/dist/types/element/src/selection.d.ts +11 -7
  31. package/dist/types/element/src/shape.d.ts +1 -1
  32. package/dist/types/element/src/textElement.d.ts +13 -10
  33. package/dist/types/element/src/textWrapping.d.ts +26 -0
  34. package/dist/types/element/src/transform.d.ts +2 -2
  35. package/dist/types/element/src/typeChecks.d.ts +26 -25
  36. package/dist/types/element/src/types.d.ts +8 -1
  37. package/dist/types/element/src/utils.d.ts +1 -1
  38. package/dist/types/element/src/zindex.d.ts +2 -2
  39. package/dist/types/excalidraw/actions/actionAddToLibrary.d.ts +33 -15
  40. package/dist/types/excalidraw/actions/actionAlign.d.ts +6 -6
  41. package/dist/types/excalidraw/actions/actionBoundText.d.ts +23 -11
  42. package/dist/types/excalidraw/actions/actionCanvas.d.ts +139 -933
  43. package/dist/types/excalidraw/actions/actionClipboard.d.ts +22 -10
  44. package/dist/types/excalidraw/actions/actionCropEditor.d.ts +11 -5
  45. package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +35 -16
  46. package/dist/types/excalidraw/actions/{actionEmbeddable.d.ts → actionDeselect.d.ts} +25 -34
  47. package/dist/types/excalidraw/actions/actionDistribute.d.ts +2 -3
  48. package/dist/types/excalidraw/actions/actionElementLink.d.ts +11 -5
  49. package/dist/types/excalidraw/actions/actionElementLock.d.ts +23 -11
  50. package/dist/types/excalidraw/actions/actionExport.d.ts +24 -12
  51. package/dist/types/excalidraw/actions/actionFrame.d.ts +45 -199
  52. package/dist/types/excalidraw/actions/actionGroup.d.ts +38 -26
  53. package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +15 -7
  54. package/dist/types/excalidraw/actions/actionLink.d.ts +12 -6
  55. package/dist/types/excalidraw/actions/actionMenu.d.ts +11 -5
  56. package/dist/types/excalidraw/actions/actionProperties.d.ts +49 -28
  57. package/dist/types/excalidraw/actions/actionSelectAll.d.ts +16 -10
  58. package/dist/types/excalidraw/actions/actionStyles.d.ts +12 -5
  59. package/dist/types/excalidraw/actions/actionTextAutoResize.d.ts +3 -3
  60. package/dist/types/excalidraw/actions/actionToggleArrowBinding.d.ts +12 -6
  61. package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +15 -10
  62. package/dist/types/excalidraw/actions/actionToggleMidpointSnapping.d.ts +12 -6
  63. package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +12 -6
  64. package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +15 -10
  65. package/dist/types/excalidraw/actions/actionToggleShapeSwitch.d.ts +1 -1
  66. package/dist/types/excalidraw/actions/actionToggleStats.d.ts +12 -6
  67. package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +13 -7
  68. package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +12 -6
  69. package/dist/types/excalidraw/actions/index.d.ts +2 -2
  70. package/dist/types/excalidraw/actions/manager.d.ts +1 -0
  71. package/dist/types/excalidraw/actions/shortcuts.d.ts +1 -1
  72. package/dist/types/excalidraw/actions/types.d.ts +8 -4
  73. package/dist/types/excalidraw/{animated-trail.d.ts → animatedTrail.d.ts} +4 -3
  74. package/dist/types/excalidraw/appState.d.ts +7 -5
  75. package/dist/types/excalidraw/components/Actions.d.ts +17 -12
  76. package/dist/types/excalidraw/components/ActiveConfirmDialog.d.ts +1 -1
  77. package/dist/types/excalidraw/components/App.arrowText.d.ts +72 -0
  78. package/dist/types/excalidraw/components/App.cursor.d.ts +31 -0
  79. package/dist/types/excalidraw/components/App.d.ts +358 -64
  80. package/dist/types/excalidraw/components/App.drawshape.d.ts +55 -0
  81. package/dist/types/excalidraw/components/App.flowchart.d.ts +21 -0
  82. package/dist/types/excalidraw/components/App.viewport.d.ts +73 -0
  83. package/dist/types/excalidraw/components/ColorPicker/ColorPicker.d.ts +2 -2
  84. package/dist/types/excalidraw/components/ColorPicker/colorPickerUtils.d.ts +1 -1
  85. package/dist/types/excalidraw/components/CommandPalette/defaultCommandPaletteItems.d.ts +1 -2
  86. package/dist/types/excalidraw/components/ConvertElementTypePopup.d.ts +2 -2
  87. package/dist/types/excalidraw/components/CursorHint.d.ts +46 -0
  88. package/dist/types/excalidraw/components/EyeDropper.d.ts +1 -1
  89. package/dist/types/excalidraw/components/{ToolButton.d.ts → IconButton.d.ts} +16 -19
  90. package/dist/types/excalidraw/components/Island.d.ts +7 -0
  91. package/dist/types/excalidraw/components/LaserPointerButton.d.ts +2 -4
  92. package/dist/types/excalidraw/components/LayerUI.d.ts +4 -2
  93. package/dist/types/excalidraw/components/LibraryMenu.d.ts +1 -1
  94. package/dist/types/excalidraw/components/LockButton.d.ts +3 -4
  95. package/dist/types/excalidraw/components/MagicButton.d.ts +0 -2
  96. package/dist/types/excalidraw/components/MobileMenu.d.ts +4 -4
  97. package/dist/types/excalidraw/components/MobileToolbar.d.ts +9 -0
  98. package/dist/types/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.d.ts +1 -1
  99. package/dist/types/excalidraw/components/PenModeButton.d.ts +2 -5
  100. package/dist/types/excalidraw/components/Popover.d.ts +1 -3
  101. package/dist/types/excalidraw/components/{ButtonIcon.d.ts → RadioButton.d.ts} +2 -5
  102. package/dist/types/excalidraw/components/Range.d.ts +10 -4
  103. package/dist/types/excalidraw/components/SVGLayer.d.ts +1 -1
  104. package/dist/types/excalidraw/components/SearchMenu.d.ts +1 -1
  105. package/dist/types/excalidraw/components/Sidebar/Sidebar.d.ts +1 -1
  106. package/dist/types/excalidraw/components/Stats/Angle.d.ts +2 -2
  107. package/dist/types/excalidraw/components/Stats/Dimension.d.ts +2 -2
  108. package/dist/types/excalidraw/components/Stats/DragInput.d.ts +2 -2
  109. package/dist/types/excalidraw/components/Stats/MultiAngle.d.ts +2 -2
  110. package/dist/types/excalidraw/components/Stats/MultiDimension.d.ts +2 -2
  111. package/dist/types/excalidraw/components/Stats/MultiPosition.d.ts +2 -2
  112. package/dist/types/excalidraw/components/Stats/Position.d.ts +3 -3
  113. package/dist/types/excalidraw/components/Stats/utils.d.ts +1 -1
  114. package/dist/types/excalidraw/components/TTDDialog/TTDContext.d.ts +4 -4
  115. package/dist/types/excalidraw/components/TTDDialog/useTTDChatStorage.d.ts +3 -3
  116. package/dist/types/excalidraw/components/ToolPopover.d.ts +3 -6
  117. package/dist/types/excalidraw/components/Toolbar.d.ts +11 -0
  118. package/dist/types/excalidraw/components/Tools.d.ts +145 -0
  119. package/dist/types/excalidraw/components/canvases/InteractiveCanvas.d.ts +4 -1
  120. package/dist/types/excalidraw/components/canvases/NewElementCanvas.d.ts +1 -0
  121. package/dist/types/excalidraw/components/canvases/StaticCanvas.d.ts +1 -1
  122. package/dist/types/excalidraw/components/dropdownMenu/DropdownMenuItemContentRadio.d.ts +2 -1
  123. package/dist/types/excalidraw/components/footer/Footer.d.ts +3 -1
  124. package/dist/types/excalidraw/components/hyperlink/helpers.d.ts +2 -2
  125. package/dist/types/excalidraw/components/icons.d.ts +3 -1
  126. package/dist/types/excalidraw/components/main-menu/DefaultItems.d.ts +8 -4
  127. package/dist/types/excalidraw/components/positionElementBesideCursor.d.ts +26 -0
  128. package/dist/types/excalidraw/components/shapeActionPredicates.d.ts +39 -0
  129. package/dist/types/excalidraw/data/blob.d.ts +26 -14
  130. package/dist/types/excalidraw/data/index.d.ts +4 -4
  131. package/dist/types/excalidraw/data/json.d.ts +19 -13
  132. package/dist/types/excalidraw/data/library.d.ts +1 -1
  133. package/dist/types/excalidraw/drawShapeTrail.d.ts +16 -0
  134. package/dist/types/excalidraw/eraser/index.d.ts +2 -3
  135. package/dist/types/excalidraw/hooks/useAppStateValue.d.ts +29 -0
  136. package/dist/types/excalidraw/hooks/useLibraryItemSvg.d.ts +1 -1
  137. package/dist/types/excalidraw/{laser-trails.d.ts → laserTrails.d.ts} +5 -7
  138. package/dist/types/excalidraw/lasso/index.d.ts +2 -3
  139. package/dist/types/excalidraw/renderer/animation.d.ts +5 -1
  140. package/dist/types/excalidraw/renderer/interactiveScene.d.ts +1 -3
  141. package/dist/types/excalidraw/scene/Renderer.d.ts +426 -19
  142. package/dist/types/excalidraw/scene/export.d.ts +3 -3
  143. package/dist/types/excalidraw/scene/index.d.ts +2 -2
  144. package/dist/types/excalidraw/scene/types.d.ts +4 -3
  145. package/dist/types/excalidraw/snapping.d.ts +7 -7
  146. package/dist/types/excalidraw/textAutoResizeHandle.d.ts +15 -0
  147. package/dist/types/excalidraw/types.d.ts +369 -20
  148. package/dist/types/excalidraw/viewport.d.ts +272 -0
  149. package/dist/types/excalidraw/wysiwyg/textWysiwyg.d.ts +6 -3
  150. package/dist/types/fractional-indexing/src/index.d.ts +29 -0
  151. package/dist/types/laser-pointer/src/index.d.ts +2 -0
  152. package/dist/types/laser-pointer/src/math.d.ts +16 -0
  153. package/dist/types/laser-pointer/src/simplify.d.ts +2 -0
  154. package/dist/types/laser-pointer/src/state.d.ts +36 -0
  155. package/dist/types/math/src/constants.d.ts +0 -1
  156. package/dist/types/math/src/curve.d.ts +4 -1
  157. package/dist/types/math/src/index.d.ts +1 -0
  158. package/dist/types/math/src/pca.d.ts +79 -0
  159. package/dist/types/math/src/point.d.ts +2 -1
  160. package/dist/types/math/src/polygon.d.ts +25 -1
  161. package/dist/types/utils/src/export.d.ts +3 -3
  162. package/dist/types/utils/src/index.d.ts +1 -2
  163. package/package.json +2 -2
  164. package/dist/types/excalidraw/animation-frame-handler.d.ts +0 -16
  165. package/dist/types/excalidraw/components/HandButton.d.ts +0 -10
  166. package/dist/types/excalidraw/components/MobileToolBar.d.ts +0 -10
  167. package/dist/types/excalidraw/components/shapes.d.ts +0 -263
  168. package/dist/types/excalidraw/cursor.d.ts +0 -5
  169. package/dist/types/excalidraw/scene/scroll.d.ts +0 -18
  170. package/dist/types/excalidraw/scene/zoom.d.ts +0 -12
  171. package/dist/types/utils/src/bbox.d.ts +0 -9
  172. package/dist/types/utils/src/withinBounds.d.ts +0 -19
@@ -1,21 +1,28 @@
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, Arrowhead, 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 { AppCursor } from "./App.cursor";
19
+ import { AppDrawShape } from "./App.drawshape";
20
+ import { AppFlowchart } from "./App.flowchart";
21
+ import { AppViewport } from "./App.viewport";
22
+ import { CursorHints } from "./CursorHint";
16
23
  import { type OnStateChange } from "./AppStateObserver";
17
24
  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";
25
+ import type { AppClassProperties, AppProps, AppState, ExcalidrawImperativeAPI, BinaryFiles, LibraryItems, SceneData, FrameNameBoundsCache, SidebarName, SidebarTabName, ToolType, OnUserFollowedPayload, ExcalidrawImperativeAPIEventMap, GenerateDiagramToCode, NullableGridSize, UIConfig } from "../types";
19
26
  import type { RoughCanvas } from "roughjs/bin/canvas";
20
27
  import type { ActionResult } from "../actions/types";
21
28
  declare const editorLifecycleEventBehavior: {
@@ -78,6 +85,9 @@ declare class App extends React.Component<AppProps, AppState> {
78
85
  fonts: Fonts;
79
86
  renderer: Renderer;
80
87
  visibleElements: readonly NonDeletedExcalidrawElement[];
88
+ /** whether the last render had any renderable elements (excludes e.g. the
89
+ * in-progress `newElement` and the edited text element) */
90
+ private hasRenderableElements;
81
91
  private resizeObserver;
82
92
  library: AppClassProperties["library"];
83
93
  libraryItemsFromStorage: LibraryItems | undefined;
@@ -107,31 +117,36 @@ declare class App extends React.Component<AppProps, AppState> {
107
117
  onEvent: AppEventBus<ExcalidrawImperativeAPIEventMap, typeof editorLifecycleEventBehavior>["on"];
108
118
  private appStateObserver;
109
119
  onStateChange: OnStateChange;
110
- flowChartCreator: FlowChartCreator;
111
- private flowChartNavigator;
120
+ flowchart: AppFlowchart;
121
+ cursor: AppCursor;
122
+ arrowText: AppArrowText;
123
+ viewport: AppViewport;
112
124
  bindModeHandler: ReturnType<typeof setTimeout> | null;
125
+ private textWysiwygSubmitHandler;
113
126
  hitLinkElement?: NonDeletedExcalidrawElement;
114
127
  lastPointerDownEvent: React.PointerEvent<HTMLElement> | null;
115
128
  lastPointerUpEvent: React.PointerEvent<HTMLElement> | PointerEvent | null;
129
+ lastPointerUpIsDoubleClick: boolean;
116
130
  lastPointerMoveEvent: PointerEvent | null;
117
131
  /** current frame pointer cords */
118
132
  lastPointerMoveCoords: {
119
133
  x: number;
120
134
  y: number;
121
135
  } | null;
136
+ private lastCompletedCanvasClicks;
137
+ /** arrowheads removed via endpoint double-click toggle, so a subsequent
138
+ * toggle can restore the original arrowhead (keyed by `elementId:side`) */
139
+ private removedArrowheads;
122
140
  /** previous frame pointer coords */
123
141
  previousPointerMoveCoords: {
124
142
  x: number;
125
143
  y: number;
126
144
  } | null;
127
- lastViewportPosition: {
128
- x: number;
129
- y: number;
130
- };
131
- animationFrameHandler: AnimationFrameHandler;
145
+ drawShape: AppDrawShape;
132
146
  laserTrails: LaserTrails;
133
147
  eraserTrail: EraserTrail;
134
148
  lassoTrail: LassoTrail;
149
+ cursorHints: CursorHints;
135
150
  onChangeEmitter: Emitter<[elements: readonly ExcalidrawElement[], appState: AppState, files: BinaryFiles]>;
136
151
  onPointerDownEmitter: Emitter<[activeTool: {
137
152
  lastActiveTool: import("../types").ActiveTool | null;
@@ -266,6 +281,74 @@ declare class App extends React.Component<AppProps, AppState> {
266
281
  api: ExcalidrawImperativeAPI;
267
282
  private createExcalidrawAPI;
268
283
  constructor(props: AppProps);
284
+ /**
285
+ * Whether the editor accepts user input (pointer, keyboard, wheel, touch,
286
+ * clipboard, drag&drop). When `false`, the editor is fully inert for the
287
+ * user, but remains controllable through the imperative API.
288
+ *
289
+ * All user-input entry points must consult this getter (directly or by
290
+ * not being attached/rendered at all).
291
+ */
292
+ isInteractionEnabled(props?: Pick<AppProps, "interaction">): boolean;
293
+ /**
294
+ * Whether element links render their link icon and are clickable.
295
+ * True when fully interactive, or when `interaction: { enabled: { links:
296
+ * true } }`
297
+ * (in which case clicking anywhere on a linked element opens the link,
298
+ * same as in view mode).
299
+ */
300
+ isLinksEnabled(props?: Pick<AppProps, "interaction">): boolean;
301
+ /**
302
+ * Whether canvas navigation — panning & zooming, view-mode style — is
303
+ * enabled. True when fully interactive, or when `interaction: { enabled:
304
+ * { navigation: true } }`. Respects `appState.scrollConstraints`.
305
+ */
306
+ isNavigationEnabled(props?: Pick<AppProps, "interaction">): boolean;
307
+ /**
308
+ * Whether embeddable & iframe elements are interactive (hover & click to
309
+ * activate, view-mode style). True when fully interactive, or when
310
+ * allowed via `interaction.enabled.embeds` / `.interactiveContent`.
311
+ */
312
+ isEmbedsEnabled(props?: Pick<AppProps, "interaction">): boolean;
313
+ /**
314
+ * Whether the browser's own zoom (ctrl/cmd + wheel, pinch, keyboard
315
+ * shortcuts) stays available over the non-interactive editor.
316
+ * Prevented by default.
317
+ */
318
+ isBrowserZoomEnabled(props?: Pick<AppProps, "interaction">): boolean;
319
+ /**
320
+ * Whether the tool can be activated & driven by user input. False when
321
+ * disabled via `UIOptions.tools`, or when the editor is non-interactive
322
+ * and the tool isn't kept user-driven via `interaction.enabled.tools`.
323
+ *
324
+ * (Once UI tool availability is split from input availability — e.g.
325
+ * `props.ui.tools` vs `interaction.disabled.tools` — the UI axis moves
326
+ * out into its own predicate.)
327
+ *
328
+ * We purposely widen the `tool` type so this helper can be called with
329
+ * any tool without having to type check it.
330
+ */
331
+ isToolSupported: <T extends ToolType | "custom">(tool: T, props?: Pick<AppProps, "interaction" | "UIOptions">) => boolean;
332
+ /**
333
+ * Whether the active tool is locked in place — via the tool lock
334
+ * (padlock / Q) or by being host-forced (`props.activeTool`). A locked
335
+ * tool doesn't revert to the selection tool after use, and elements drawn
336
+ * with it aren't selected. Forcing deliberately does not mutate
337
+ * `activeTool.locked`, which is the user's persisted padlock preference.
338
+ */
339
+ isToolLocked(): boolean;
340
+ /**
341
+ * Whether the active tool captures the primary pointer instead of the
342
+ * view-mode drag-to-pan — the laser always does; while non-interactive,
343
+ * any tool allowed via `interaction.enabled.tools` does. (Editing tools
344
+ * capture the pointer trivially since view mode implies they're not
345
+ * active; this predicate only matters where view-mode gates apply.)
346
+ */
347
+ isActiveToolPointerCapturing(): boolean;
348
+ /** Whether Excalidraw's full default UI is rendered. */
349
+ isDefaultUIEnabled(props?: Pick<AppProps, "ui">): boolean;
350
+ /** Whether an individual default UI control is rendered. */
351
+ isUIControlEnabled(control: keyof UIConfig["enabled"], props?: Pick<AppProps, "ui">): boolean;
269
352
  updateEditorAtom: <Value, Args extends unknown[], Result>(atom: WritableAtom<Value, Args, Result>, ...args: Args) => Result;
270
353
  private onWindowMessage;
271
354
  private handleSkipBindMode;
@@ -278,10 +361,12 @@ declare class App extends React.Component<AppProps, AppState> {
278
361
  * If disabled, returns null.
279
362
  */
280
363
  getEffectiveGridSize: () => NullableGridSize;
364
+ private getTextCreationGridPoint;
281
365
  private getHTMLIFrameElement;
282
366
  private handleIframeLikeElementHover;
283
367
  /** @returns true if iframe-like element click handled */
284
368
  private handleIframeLikeCenterClick;
369
+ private isDoubleClick;
285
370
  private isIframeLikeElementCenter;
286
371
  private updateEmbedValidationStatus;
287
372
  private updateEmbeddables;
@@ -298,7 +383,7 @@ declare class App extends React.Component<AppProps, AppState> {
298
383
  getSceneElements: () => readonly Ordered<NonDeletedExcalidrawElement>[];
299
384
  onInsertElements: (elements: readonly ExcalidrawElement[]) => void;
300
385
  onExportImage: (type: keyof typeof EXPORT_IMAGE_TYPES, elements: ExportedElements, opts: {
301
- exportingFrame: ExcalidrawFrameLikeElement | null;
386
+ exportingFrame: NonDeleted<ExcalidrawFrameLikeElement> | null;
302
387
  }) => Promise<void>;
303
388
  private magicGenerations;
304
389
  private updateMagicGeneration;
@@ -317,6 +402,30 @@ declare class App extends React.Component<AppProps, AppState> {
317
402
  private onBlur;
318
403
  private onUnload;
319
404
  private disableEvent;
405
+ private preventBrowserZoomWheel;
406
+ private handleNavigationModeKeyDown;
407
+ /**
408
+ * PageUp/PageDown scroll the canvas by a page — vertically, or
409
+ * horizontally with shift. Respects `appState.scrollConstraints`
410
+ * (via `viewport.translate`).
411
+ */
412
+ private maybeHandlePageScrollKeyDown;
413
+ private preventBrowserZoomKeyDown;
414
+ /** Ends active input sessions before switching to a view-mode/non-interactive
415
+ * mode. */
416
+ private terminateActiveInteraction;
417
+ private handleInteractionStateChange;
418
+ /** whether the two values reference the same tool (incl. custom subtype) */
419
+ private isSameForcedTool;
420
+ /**
421
+ * Keeps `state.activeTool` synced to the host-controlled
422
+ * `props.activeTool`. `setActiveTool` refuses non-matching activations
423
+ * while forced (user input, API); this backstop covers the writers that
424
+ * bypass the funnel (`actionFinalize`/`actionDeselect`, `restore()` on
425
+ * scene load, ...) and re-applies the tool once it becomes activatable
426
+ * (e.g. `interaction` config changes).
427
+ */
428
+ private handleForcedToolChange;
320
429
  private resetHistory;
321
430
  private resetStore;
322
431
  /**
@@ -356,7 +465,8 @@ declare class App extends React.Component<AppProps, AppState> {
356
465
  clientY: number;
357
466
  } | "cursor" | "center";
358
467
  retainSeed?: boolean;
359
- fitToContent?: boolean;
468
+ fit?: SetViewportOptions["fit"];
469
+ preserveFrameChildrenOrder?: boolean;
360
470
  }) => void;
361
471
  private addElementsFromMixedContentPaste;
362
472
  private addTextFromPaste;
@@ -365,47 +475,8 @@ declare class App extends React.Component<AppProps, AppState> {
365
475
  toggleLock: (source?: "keyboard" | "ui") => void;
366
476
  updateFrameRendering: (opts: Partial<AppState["frameRendering"]> | ((prevState: AppState["frameRendering"]) => Partial<AppState["frameRendering"]>)) => void;
367
477
  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;
478
+ revealIfHidden: (elements: NonDeletedExcalidrawElement[]) => void;
406
479
  private maybeUnfollowRemoteUser;
407
- /** use when changing scrollX/scrollY/zoom based on user interaction */
408
- private translateCanvas;
409
480
  setToast: (toast: AppState["toast"]) => void;
410
481
  restoreFileFromShare: () => Promise<void>;
411
482
  /**
@@ -433,7 +504,9 @@ declare class App extends React.Component<AppProps, AppState> {
433
504
  }) => void;
434
505
  applyDeltas: (deltas: StoreDelta[], options?: ApplyToOptions) => [SceneElementsMap, AppState, boolean];
435
506
  mutateElement: <TElement extends Mutable<ExcalidrawElement>>(element: TElement, updates: ElementUpdate<TElement>, informMutation?: boolean) => TElement;
436
- private triggerRender;
507
+ triggerRender: (
508
+ /** force always re-renders canvas even if no change */
509
+ force?: boolean) => void;
437
510
  /**
438
511
  * @returns whether the menu was toggled on or off
439
512
  */
@@ -443,10 +516,8 @@ declare class App extends React.Component<AppProps, AppState> {
443
516
  force?: boolean;
444
517
  }) => boolean;
445
518
  private updateCurrentCursorPosition;
446
- getEditorUIOffsets: () => Offsets;
447
519
  private onKeyDown;
448
520
  private onKeyUp;
449
- private isToolSupported;
450
521
  setActiveTool: (tool: ({
451
522
  type: ToolType;
452
523
  } | {
@@ -455,10 +526,18 @@ declare class App extends React.Component<AppProps, AppState> {
455
526
  }) & {
456
527
  locked?: boolean;
457
528
  fromSelection?: boolean;
458
- }, keepSelection?: boolean) => void;
529
+ }, opts?: {
530
+ keepSelection?: boolean;
531
+ /**
532
+ * When `true`, re-activating an already-active toggle tool (see
533
+ * `TOGGLE_TOOLS`) switches back to the previously active tool.
534
+ * Activation is idempotent by default; toggle tools always record the
535
+ * previously active tool regardless (so ESC and the next `toggle`
536
+ * activation can switch back to it).
537
+ */
538
+ toggle?: boolean;
539
+ }) => void;
459
540
  setOpenDialog: (dialogType: AppState["openDialog"]) => void;
460
- private setCursor;
461
- private resetCursor;
462
541
  /**
463
542
  * returns whether user is making a gesture with >= 2 fingers (points)
464
543
  * on o touch screen (not on a trackpad). Currently only relates to Darwin
@@ -472,19 +551,223 @@ declare class App extends React.Component<AppProps, AppState> {
472
551
  private onGestureEnd;
473
552
  private handleTextWysiwyg;
474
553
  private deselectElements;
475
- private getTextElementAtPosition;
476
- private getElementAtPosition;
554
+ private getSelectedTextElement;
555
+ private getSelectedTextEditingContainerAtPosition;
556
+ getTextElementAtPosition(x: number, y: number): NonDeleted<ExcalidrawTextElement> | null;
557
+ private isHittingTextAutoResizeHandle;
558
+ private handleTextAutoResizeHandlePointerDown;
559
+ getElementAtPosition(x: number, y: number, opts?: ({
560
+ includeBoundTextElement?: boolean;
561
+ includeLockedElements?: boolean;
562
+ } | {
563
+ allHitElements: NonDeleted<ExcalidrawElement>[];
564
+ }) & {
565
+ preferSelected?: boolean;
566
+ }): NonDeleted<ExcalidrawElement> | null;
477
567
  private getElementsAtPosition;
478
568
  getElementHitThreshold(element: ExcalidrawElement): number;
479
569
  private hitElement;
480
- private getTextBindableContainerAtPosition;
570
+ getTextBindableContainerAtPosition(x: number, y: number): (Readonly<{
571
+ id: string;
572
+ x: number;
573
+ y: number;
574
+ strokeColor: string;
575
+ backgroundColor: string;
576
+ fillStyle: import("@excalidraw/element/types").FillStyle;
577
+ strokeWidth: number;
578
+ strokeStyle: import("@excalidraw/element/types").StrokeStyle;
579
+ roundness: null | {
580
+ type: import("@excalidraw/element/types").RoundnessType;
581
+ value?: number;
582
+ };
583
+ roughness: number;
584
+ opacity: number;
585
+ width: number;
586
+ height: number;
587
+ angle: Radians;
588
+ seed: number;
589
+ version: number;
590
+ versionNonce: number;
591
+ index: import("@excalidraw/element/types").FractionalIndex | null;
592
+ isDeleted: boolean;
593
+ groupIds: readonly import("@excalidraw/element/types").GroupId[];
594
+ frameId: string | null;
595
+ boundElements: readonly import("@excalidraw/element/types").BoundElement[] | null;
596
+ updated: number;
597
+ link: string | null;
598
+ locked: boolean;
599
+ customData?: Record<string, any>;
600
+ }> & {
601
+ type: "rectangle";
602
+ } & {
603
+ isDeleted: false;
604
+ }) | (Readonly<{
605
+ id: string;
606
+ x: number;
607
+ y: number;
608
+ strokeColor: string;
609
+ backgroundColor: string;
610
+ fillStyle: import("@excalidraw/element/types").FillStyle;
611
+ strokeWidth: number;
612
+ strokeStyle: import("@excalidraw/element/types").StrokeStyle;
613
+ roundness: null | {
614
+ type: import("@excalidraw/element/types").RoundnessType;
615
+ value?: number;
616
+ };
617
+ roughness: number;
618
+ opacity: number;
619
+ width: number;
620
+ height: number;
621
+ angle: Radians;
622
+ seed: number;
623
+ version: number;
624
+ versionNonce: number;
625
+ index: import("@excalidraw/element/types").FractionalIndex | null;
626
+ isDeleted: boolean;
627
+ groupIds: readonly import("@excalidraw/element/types").GroupId[];
628
+ frameId: string | null;
629
+ boundElements: readonly import("@excalidraw/element/types").BoundElement[] | null;
630
+ updated: number;
631
+ link: string | null;
632
+ locked: boolean;
633
+ customData?: Record<string, any>;
634
+ }> & {
635
+ type: "diamond";
636
+ } & {
637
+ isDeleted: false;
638
+ }) | (Readonly<{
639
+ id: string;
640
+ x: number;
641
+ y: number;
642
+ strokeColor: string;
643
+ backgroundColor: string;
644
+ fillStyle: import("@excalidraw/element/types").FillStyle;
645
+ strokeWidth: number;
646
+ strokeStyle: import("@excalidraw/element/types").StrokeStyle;
647
+ roundness: null | {
648
+ type: import("@excalidraw/element/types").RoundnessType;
649
+ value?: number;
650
+ };
651
+ roughness: number;
652
+ opacity: number;
653
+ width: number;
654
+ height: number;
655
+ angle: Radians;
656
+ seed: number;
657
+ version: number;
658
+ versionNonce: number;
659
+ index: import("@excalidraw/element/types").FractionalIndex | null;
660
+ isDeleted: boolean;
661
+ groupIds: readonly import("@excalidraw/element/types").GroupId[];
662
+ frameId: string | null;
663
+ boundElements: readonly import("@excalidraw/element/types").BoundElement[] | null;
664
+ updated: number;
665
+ link: string | null;
666
+ locked: boolean;
667
+ customData?: Record<string, any>;
668
+ }> & {
669
+ type: "ellipse";
670
+ } & {
671
+ isDeleted: false;
672
+ }) | (Readonly<{
673
+ id: string;
674
+ x: number;
675
+ y: number;
676
+ strokeColor: string;
677
+ backgroundColor: string;
678
+ fillStyle: import("@excalidraw/element/types").FillStyle;
679
+ strokeWidth: number;
680
+ strokeStyle: import("@excalidraw/element/types").StrokeStyle;
681
+ roundness: null | {
682
+ type: import("@excalidraw/element/types").RoundnessType;
683
+ value?: number;
684
+ };
685
+ roughness: number;
686
+ opacity: number;
687
+ width: number;
688
+ height: number;
689
+ angle: Radians;
690
+ seed: number;
691
+ version: number;
692
+ versionNonce: number;
693
+ index: import("@excalidraw/element/types").FractionalIndex | null;
694
+ isDeleted: boolean;
695
+ groupIds: readonly import("@excalidraw/element/types").GroupId[];
696
+ frameId: string | null;
697
+ boundElements: readonly import("@excalidraw/element/types").BoundElement[] | null;
698
+ updated: number;
699
+ link: string | null;
700
+ locked: boolean;
701
+ customData?: Record<string, any>;
702
+ }> & Readonly<{
703
+ type: "line" | "arrow";
704
+ points: readonly LocalPoint[];
705
+ startBinding: import("@excalidraw/element/types").FixedPointBinding | null;
706
+ endBinding: import("@excalidraw/element/types").FixedPointBinding | null;
707
+ startArrowhead: Arrowhead | null;
708
+ endArrowhead: Arrowhead | null;
709
+ }> & Readonly<{
710
+ type: "arrow";
711
+ elbowed: boolean;
712
+ }> & {
713
+ isDeleted: false;
714
+ }) | null;
715
+ /**
716
+ * Whether a text element's content is still being authored.
717
+ *
718
+ * Creating a text reverts the tool to selection during pointerdown, so the
719
+ * pointerup that follows looks like an ordinary canvas click and would
720
+ * capture the still-empty element as a history entry of its own. Undo would
721
+ * then rewind only the typing, restoring an invisible, zero-content element
722
+ * (and, for an endpoint label, leaving the arrow bound to it) rather than
723
+ * removing it. The editor's own submit captures the finished text instead,
724
+ * so the whole create-and-type lands in a single entry.
725
+ */
726
+ private isEditingTextContent;
481
727
  private startTextEditing;
482
728
  private startImageCropping;
483
729
  private finishImageCropping;
730
+ private shouldHandleBrowserCanvasDoubleClick;
731
+ /**
732
+ * Toggles the arrowhead at the given endpoint between no arrowhead and the
733
+ * arrowhead it had before the last toggle (falling back to the current
734
+ * default arrowhead).
735
+ */
736
+ private toggleArrowheadAtEndpoint;
484
737
  private handleCanvasDoubleClick;
738
+ private handleCanvasClick;
485
739
  private getElementLinkAtPosition;
486
740
  private handleElementLinkClick;
741
+ /**
742
+ * Applies (or clears) the element-link hover affordances — pointer cursor
743
+ * and tooltip — based on the current `hitLinkElement`. Returns whether a
744
+ * link is being hovered.
745
+ */
746
+ private applyElementLinkHoverAffordance;
747
+ /**
748
+ * On touchscreens (where no hover precedes the tap) re-derives
749
+ * `hitLinkElement`, then opens the hit element link, if any.
750
+ * Returns whether a link click was handled.
751
+ */
752
+ private maybeHandleElementLinkClick;
753
+ /**
754
+ * Restricted pointer handling for the non-interactive editor with links
755
+ * and/or embeds allowed (`interaction.enabled.links` / `.embeds` /
756
+ * `.interactiveContent`) — runs only the element-link & embed concerns
757
+ * (shared with the full pointer handlers above) so they behave like in
758
+ * view mode without the rest of the canvas pointer machinery.
759
+ */
760
+ private handleInteractiveContentPointerMove;
761
+ private handleInteractiveContentPointerUp;
762
+ /**
763
+ * finds candidate frame under cursor (when dragging frame children/elements
764
+ * inside frames)
765
+ */
487
766
  private getTopLayerFrameAtSceneCoords;
767
+ private updateFrameToHighlight;
768
+ private maybeUpdateFrameToHighlightOnPointerMove;
769
+ insertNewElements: (elements: readonly ExcalidrawElement[]) => void;
770
+ insertNewElement: (element: ExcalidrawElement) => void;
488
771
  private handleCanvasPointerMove;
489
772
  private handleEraser;
490
773
  private handleTouchMove;
@@ -501,6 +784,11 @@ declare class App extends React.Component<AppProps, AppState> {
501
784
  private maybeCleanupAfterMissingPointerUp;
502
785
  handleCanvasPanUsingWheelOrSpaceDrag: (event: React.PointerEvent<HTMLElement> | MouseEvent) => boolean;
503
786
  private updateGestureOnPointerDown;
787
+ /**
788
+ * Tracks the pointer within the ongoing multi-touch gesture and applies
789
+ * the two-finger pinch zoom/pan, if any.
790
+ */
791
+ private updateMultiTouchGesture;
504
792
  private initialPointerDownState;
505
793
  private handleDraggingScrollBar;
506
794
  private clearSelectionIfNotUsingSelection;
@@ -526,6 +814,7 @@ declare class App extends React.Component<AppProps, AppState> {
526
814
  private newImagePlaceholder;
527
815
  private handleLinearElementOnPointerDown;
528
816
  private getCurrentItemRoundness;
817
+ private getCurrentItemStrokeWidth;
529
818
  private createGenericElementOnPointerDown;
530
819
  private createFrameElementOnPointerDown;
531
820
  private maybeCacheReferenceSnapPoints;
@@ -565,7 +854,12 @@ declare class App extends React.Component<AppProps, AppState> {
565
854
  private maybeHandleResize;
566
855
  private getContextMenuItems;
567
856
  private handleWheel;
568
- private getTextWysiwygSnappedToCenterPosition;
857
+ getTextWysiwygSnappedToCenterPosition(x: number, y: number, appState: AppState, container?: ExcalidrawTextContainer | null): {
858
+ viewportX: number;
859
+ viewportY: number;
860
+ elementCenterX: number;
861
+ elementCenterY: number;
862
+ } | undefined;
569
863
  private savePointer;
570
864
  private resetShouldCacheIgnoreZoomDebounced;
571
865
  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
+ }
@@ -0,0 +1,21 @@
1
+ import type React from "react";
2
+ import type App from "./App";
3
+ import type { PendingExcalidrawElements } from "../types";
4
+ /**
5
+ * Captures the App state management for the flowchart functionality.
6
+ */
7
+ export declare class AppFlowchart {
8
+ private app;
9
+ private creator;
10
+ private navigator;
11
+ constructor(app: App);
12
+ get pendingNodes(): PendingExcalidrawElements | null;
13
+ get isCreatingChart(): boolean;
14
+ /** ends any in-progress flowchart creation/navigation session */
15
+ clear: () => void;
16
+ handleKeyEvent: (event: React.KeyboardEvent | KeyboardEvent) => boolean;
17
+ private resolveKeyboardEventToOperation;
18
+ private selectAndReveal;
19
+ private captureUpdate;
20
+ private static getLinkDirectionFromKey;
21
+ }