@excalidraw/element 0.18.0-4872083 → 0.18.0-4ce38fb

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 (119) hide show
  1. package/dist/dev/index.js +5645 -3994
  2. package/dist/dev/index.js.map +4 -4
  3. package/dist/prod/index.js +16 -15
  4. package/dist/types/common/src/colors.d.ts +13 -7
  5. package/dist/types/common/src/constants.d.ts +54 -0
  6. package/dist/types/common/src/keys.d.ts +2 -0
  7. package/dist/types/common/src/random.d.ts +7 -0
  8. package/dist/types/common/src/utils.d.ts +5 -0
  9. package/dist/types/element/src/Scene.d.ts +1 -1
  10. package/dist/types/element/src/binding.d.ts +13 -7
  11. package/dist/types/element/src/collision.d.ts +14 -5
  12. package/dist/types/element/src/comparisons.d.ts +5 -3
  13. package/dist/types/element/src/delta.d.ts +23 -1
  14. package/dist/types/element/src/duplicate.d.ts +60 -0
  15. package/dist/types/element/src/flowchart.d.ts +5 -1
  16. package/dist/types/element/src/frame.d.ts +2 -2
  17. package/dist/types/element/src/index.d.ts +2 -0
  18. package/dist/types/element/src/linearElementEditor.d.ts +10 -0
  19. package/dist/types/element/src/listMarker.d.ts +34 -0
  20. package/dist/types/element/src/mutateElement.d.ts +1 -1
  21. package/dist/types/element/src/newElement.d.ts +39 -3
  22. package/dist/types/element/src/renderElement.d.ts +21 -4
  23. package/dist/types/element/src/shape.d.ts +15 -1
  24. package/dist/types/element/src/sizeHelpers.d.ts +6 -0
  25. package/dist/types/element/src/stickyNote.d.ts +183 -0
  26. package/dist/types/element/src/textElement.d.ts +9 -1
  27. package/dist/types/element/src/transform.d.ts +25 -6
  28. package/dist/types/element/src/typeChecks.d.ts +3 -2
  29. package/dist/types/element/src/types.d.ts +35 -6
  30. package/dist/types/element/src/utils.d.ts +15 -4
  31. package/dist/types/element/src/zindex.d.ts +1 -1
  32. package/dist/types/excalidraw/actions/actionAddToLibrary.d.ts +60 -3
  33. package/dist/types/excalidraw/actions/actionAlign.d.ts +6 -6
  34. package/dist/types/excalidraw/actions/actionBoundText.d.ts +40 -2
  35. package/dist/types/excalidraw/actions/actionCanvas.d.ts +140 -7
  36. package/dist/types/excalidraw/actions/actionClipboard.d.ts +40 -2
  37. package/dist/types/excalidraw/actions/actionCropEditor.d.ts +20 -1
  38. package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +61 -4
  39. package/dist/types/excalidraw/actions/actionDeselect.d.ts +23 -1
  40. package/dist/types/excalidraw/actions/actionDistribute.d.ts +2 -2
  41. package/dist/types/excalidraw/actions/actionElementLink.d.ts +20 -1
  42. package/dist/types/excalidraw/actions/actionElementLock.d.ts +40 -2
  43. package/dist/types/excalidraw/actions/actionExport.d.ts +40 -2
  44. package/dist/types/excalidraw/actions/actionFinalize.d.ts +1 -0
  45. package/dist/types/excalidraw/actions/actionFrame.d.ts +111 -4
  46. package/dist/types/excalidraw/actions/actionGroup.d.ts +40 -2
  47. package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +71 -2
  48. package/dist/types/excalidraw/actions/actionLink.d.ts +20 -1
  49. package/dist/types/excalidraw/actions/actionMenu.d.ts +20 -1
  50. package/dist/types/excalidraw/actions/actionProperties.d.ts +50 -8
  51. package/dist/types/excalidraw/actions/actionSelectAll.d.ts +20 -1
  52. package/dist/types/excalidraw/actions/actionStyles.d.ts +21 -2
  53. package/dist/types/excalidraw/actions/actionToggleArrowBinding.d.ts +20 -1
  54. package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +20 -1
  55. package/dist/types/excalidraw/actions/actionToggleMidpointSnapping.d.ts +20 -1
  56. package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +20 -1
  57. package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +20 -1
  58. package/dist/types/excalidraw/actions/actionToggleShowHints.d.ts +197 -0
  59. package/dist/types/excalidraw/actions/actionToggleStats.d.ts +20 -1
  60. package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +20 -1
  61. package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +20 -1
  62. package/dist/types/excalidraw/actions/colorTargets.d.ts +39 -0
  63. package/dist/types/excalidraw/actions/index.d.ts +1 -0
  64. package/dist/types/excalidraw/actions/types.d.ts +1 -1
  65. package/dist/types/excalidraw/appState.d.ts +23 -1
  66. package/dist/types/excalidraw/components/App.arrowText.d.ts +28 -30
  67. package/dist/types/excalidraw/components/App.bucketFill.d.ts +10 -0
  68. package/dist/types/excalidraw/components/App.clipboard.d.ts +31 -0
  69. package/dist/types/excalidraw/components/App.cursor.d.ts +8 -0
  70. package/dist/types/excalidraw/components/App.d.ts +110 -199
  71. package/dist/types/excalidraw/components/App.duplicate.d.ts +101 -0
  72. package/dist/types/excalidraw/components/App.pan.d.ts +62 -0
  73. package/dist/types/excalidraw/components/App.text.d.ts +146 -0
  74. package/dist/types/excalidraw/components/App.textTool.d.ts +140 -0
  75. package/dist/types/excalidraw/components/App.toolDrag.d.ts +63 -0
  76. package/dist/types/excalidraw/components/App.viewport.d.ts +41 -1
  77. package/dist/types/excalidraw/components/App.wheel.d.ts +26 -0
  78. package/dist/types/excalidraw/components/ColorPicker/ColorPicker.d.ts +6 -2
  79. package/dist/types/excalidraw/components/ColorPicker/CustomColorList.d.ts +3 -1
  80. package/dist/types/excalidraw/components/ColorPicker/Picker.d.ts +4 -1
  81. package/dist/types/excalidraw/components/ColorPicker/PickerColorList.d.ts +4 -2
  82. package/dist/types/excalidraw/components/ColorPicker/ShadeList.d.ts +4 -2
  83. package/dist/types/excalidraw/components/ColorPicker/TopPicks.d.ts +8 -1
  84. package/dist/types/excalidraw/components/ColorPicker/colorTopPicksDnD.d.ts +11 -0
  85. package/dist/types/excalidraw/components/FileDropOverlay.d.ts +2 -0
  86. package/dist/types/excalidraw/components/FontPicker/FontPicker.d.ts +4 -1
  87. package/dist/types/excalidraw/components/FontPicker/FontPickerList.d.ts +6 -1
  88. package/dist/types/excalidraw/components/FontPicker/fontTopPicksDnD.d.ts +12 -0
  89. package/dist/types/excalidraw/components/IconButton.d.ts +2 -0
  90. package/dist/types/excalidraw/components/LibraryMenuSection.d.ts +6 -2
  91. package/dist/types/excalidraw/components/LibraryUnit.d.ts +7 -2
  92. package/dist/types/excalidraw/components/Tools.d.ts +7 -2
  93. package/dist/types/excalidraw/components/Tooltip.d.ts +15 -1
  94. package/dist/types/excalidraw/components/TopPicksDnD/TopPicksContextMenu.d.ts +14 -0
  95. package/dist/types/excalidraw/components/TopPicksDnD/TopPicksTip.d.ts +11 -0
  96. package/dist/types/excalidraw/components/TopPicksDnD/topPicksDnD.d.ts +58 -0
  97. package/dist/types/excalidraw/components/canvases/NewElementCanvas.d.ts +2 -0
  98. package/dist/types/excalidraw/components/icons.d.ts +2 -0
  99. package/dist/types/excalidraw/components/main-menu/DefaultItems.d.ts +2 -0
  100. package/dist/types/excalidraw/components/shapeActionPredicates.d.ts +2 -2
  101. package/dist/types/excalidraw/data/blob.d.ts +40 -2
  102. package/dist/types/excalidraw/data/json.d.ts +20 -1
  103. package/dist/types/excalidraw/fonts/Fonts.d.ts +3 -2
  104. package/dist/types/excalidraw/hooks/useTextEditorFocus.d.ts +5 -5
  105. package/dist/types/excalidraw/lasso/utils.d.ts +2 -0
  106. package/dist/types/excalidraw/renderOverrides.d.ts +9 -0
  107. package/dist/types/excalidraw/renderer/helpers.d.ts +25 -0
  108. package/dist/types/excalidraw/renderer/interactiveScene.d.ts +1 -1
  109. package/dist/types/excalidraw/scene/Renderer.d.ts +64 -2
  110. package/dist/types/excalidraw/scene/index.d.ts +1 -1
  111. package/dist/types/excalidraw/scene/types.d.ts +3 -1
  112. package/dist/types/excalidraw/types.d.ts +140 -18
  113. package/dist/types/excalidraw/viewport.d.ts +33 -1
  114. package/dist/types/excalidraw/wysiwyg/textWysiwyg.d.ts +12 -1
  115. package/dist/types/math/src/curve.d.ts +19 -12
  116. package/dist/types/math/src/segment.d.ts +6 -0
  117. package/dist/types/utils/src/export.d.ts +1 -0
  118. package/dist/types/utils/src/shape.d.ts +2 -2
  119. package/package.json +4 -4
@@ -1,8 +1,8 @@
1
1
  import React from "react";
2
2
  import { AppEventBus, type EXPORT_IMAGE_TYPES, Emitter, type EditorInterface, type StylesPanelMode } from "@excalidraw/common";
3
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";
4
+ import type { ExcalidrawElement, NonDeleted, NonDeletedExcalidrawElement, ExcalidrawFrameLikeElement, ExcalidrawIframeElement, ExcalidrawEmbeddableElement, Ordered, SceneElementsMap } from "@excalidraw/element/types";
5
+ import type { TransformHandleDirection } from "@excalidraw/element";
6
6
  import type { Mutable } from "@excalidraw/common/utility-types";
7
7
  import { ActionManager } from "../actions/manager";
8
8
  import { History } from "../history";
@@ -15,15 +15,22 @@ import { isOverScrollBars } from "../scene/scrollbars";
15
15
  import { LassoTrail } from "../lasso";
16
16
  import { EraserTrail } from "../eraser";
17
17
  import { AppArrowText } from "./App.arrowText";
18
+ import { AppClipboard } from "./App.clipboard";
19
+ import { AppText } from "./App.text";
20
+ import { AppTextTool } from "./App.textTool";
18
21
  import { AppBucketFill } from "./App.bucketFill";
22
+ import { AppToolDrag } from "./App.toolDrag";
19
23
  import { AppCursor } from "./App.cursor";
20
24
  import { AppDrawShape } from "./App.drawshape";
25
+ import { AppDuplicate } from "./App.duplicate";
21
26
  import { AppFlowchart } from "./App.flowchart";
27
+ import { AppPan } from "./App.pan";
22
28
  import { AppViewport } from "./App.viewport";
29
+ import { AppWheel } from "./App.wheel";
23
30
  import { CursorHints } from "./CursorHint";
24
31
  import { type OnStateChange } from "./AppStateObserver";
25
32
  import type { ExportedElements } from "../data";
26
- import type { AppClassProperties, AppProps, AppState, ExcalidrawImperativeAPI, BinaryFiles, LibraryItems, SceneData, FrameNameBoundsCache, SidebarName, SidebarTabName, ToolType, OnUserFollowedPayload, ExcalidrawImperativeAPIEventMap, GenerateDiagramToCode, NullableGridSize, UIConfig } from "../types";
33
+ import type { AppClassProperties, AppProps, AppState, ElementRenderOverrides, ExcalidrawImperativeAPI, BinaryFiles, LibraryItems, PointerDownState, SceneData, FrameNameBoundsCache, SidebarName, SidebarTabName, KeyboardModifiersObject, ToolType, OnUserFollowedPayload, ExcalidrawImperativeAPIEventMap, GenerateDiagramToCode, NullableGridSize, UIConfig } from "../types";
27
34
  import type { RoughCanvas } from "roughjs/bin/canvas";
28
35
  import type { ActionResult } from "../actions/types";
29
36
  declare const editorLifecycleEventBehavior: {
@@ -82,6 +89,9 @@ declare class App extends React.Component<AppProps, AppState> {
82
89
  editorInterface: EditorInterface;
83
90
  private stylesPanelMode;
84
91
  private excalidrawContainerRef;
92
+ private zenModeTransitionTimer;
93
+ get ownerDocument(): Document;
94
+ get ownerWindow(): Window & typeof globalThis;
85
95
  scene: Scene;
86
96
  fonts: Fonts;
87
97
  renderer: Renderer;
@@ -93,7 +103,7 @@ declare class App extends React.Component<AppProps, AppState> {
93
103
  library: AppClassProperties["library"];
94
104
  libraryItemsFromStorage: LibraryItems | undefined;
95
105
  id: string;
96
- private store;
106
+ store: Store;
97
107
  private history;
98
108
  excalidrawContainerValue: {
99
109
  container: HTMLDivElement | null;
@@ -119,14 +129,27 @@ declare class App extends React.Component<AppProps, AppState> {
119
129
  private appStateObserver;
120
130
  onStateChange: OnStateChange;
121
131
  bucketFill: AppBucketFill;
132
+ duplicate: AppDuplicate;
133
+ toolDrag: AppToolDrag;
122
134
  flowchart: AppFlowchart;
123
135
  cursor: AppCursor;
124
136
  arrowText: AppArrowText;
137
+ pan: AppPan;
138
+ textTool: AppTextTool;
139
+ clipboard: AppClipboard;
140
+ text: AppText;
125
141
  viewport: AppViewport;
142
+ wheel: AppWheel;
126
143
  bindModeHandler: ReturnType<typeof setTimeout> | null;
127
- private textWysiwygSubmitHandler;
128
144
  hitLinkElement?: NonDeletedExcalidrawElement;
129
145
  lastPointerDownEvent: React.PointerEvent<HTMLElement> | null;
146
+ /**
147
+ * the handle of the resize in progress while `state.isResizing` — for UI
148
+ * that words itself by handle (a sticky note's corners resize
149
+ * proportionally, its edges freely); not app state, so it costs no
150
+ * re-render of its own
151
+ */
152
+ activeResizeHandle: TransformHandleDirection | null;
130
153
  lastPointerUpEvent: React.PointerEvent<HTMLElement> | PointerEvent | null;
131
154
  lastPointerUpIsDoubleClick: boolean;
132
155
  lastPointerMoveEvent: PointerEvent | null;
@@ -184,7 +207,10 @@ declare class App extends React.Component<AppProps, AppState> {
184
207
  allHitElements: NonDeleted<ExcalidrawElement>[];
185
208
  wasAddedToSelection: boolean;
186
209
  hasBeenDuplicated: boolean;
210
+ advancedListMarkers: readonly import("@excalidraw/element").ListMarkerAdvance[];
211
+ editedTextId: import("@excalidraw/element/types").ExcalidrawTextElement["id"] | null;
187
212
  hasHitCommonBoundingBoxOfSelectedElements: boolean;
213
+ arrowLabel: boolean;
188
214
  };
189
215
  withCmdOrCtrl: boolean;
190
216
  drag: {
@@ -246,7 +272,10 @@ declare class App extends React.Component<AppProps, AppState> {
246
272
  allHitElements: NonDeleted<ExcalidrawElement>[];
247
273
  wasAddedToSelection: boolean;
248
274
  hasBeenDuplicated: boolean;
275
+ advancedListMarkers: readonly import("@excalidraw/element").ListMarkerAdvance[];
276
+ editedTextId: import("@excalidraw/element/types").ExcalidrawTextElement["id"] | null;
249
277
  hasHitCommonBoundingBoxOfSelectedElements: boolean;
278
+ arrowLabel: boolean;
250
279
  };
251
280
  withCmdOrCtrl: boolean;
252
281
  drag: {
@@ -278,6 +307,12 @@ declare class App extends React.Component<AppProps, AppState> {
278
307
  missingPointerEventCleanupEmitter: Emitter<[event: PointerEvent | null]>;
279
308
  onRemoveEventListenersEmitter: Emitter<[]>;
280
309
  api: ExcalidrawImperativeAPI;
310
+ private elementRenderOverrides;
311
+ /** offsets of `elementRenderOverrides`; keeps its identity while they don't change */
312
+ private elementRenderOffsets;
313
+ private renderOverridesUpdatePending;
314
+ private getRenderOverrideConfig;
315
+ private getElementRenderState;
281
316
  private createExcalidrawAPI;
282
317
  constructor(props: AppProps);
283
318
  /**
@@ -361,8 +396,12 @@ declare class App extends React.Component<AppProps, AppState> {
361
396
  * If disabled, returns null.
362
397
  */
363
398
  getEffectiveGridSize: () => NullableGridSize;
364
- private getTextCreationGridPoint;
365
399
  private getHTMLIFrameElement;
400
+ /**
401
+ * AI-generated iframe elements aren't interactive while their generation
402
+ * is still in progress (the partial content is render-only).
403
+ */
404
+ private isIframeLikeInteractive;
366
405
  private handleIframeLikeElementHover;
367
406
  /** @returns true if iframe-like element click handled */
368
407
  private handleIframeLikeCenterClick;
@@ -403,7 +442,8 @@ declare class App extends React.Component<AppProps, AppState> {
403
442
  private onBlur;
404
443
  private onUnload;
405
444
  private disableEvent;
406
- private preventBrowserZoomWheel;
445
+ private isFileDropEnabled;
446
+ private onDragOver;
407
447
  private handleNavigationModeKeyDown;
408
448
  /**
409
449
  * PageUp/PageDown scroll the canvas by a page — vertically, or
@@ -448,16 +488,20 @@ declare class App extends React.Component<AppProps, AppState> {
448
488
  private onFullscreenChange;
449
489
  private removeEventListeners;
450
490
  private addEventListeners;
491
+ getSnapshotBeforeUpdate(prevProps: AppProps, prevState: AppState): null;
492
+ /**
493
+ * Flags the container while toggling zen mode so that UI chrome
494
+ * (backgrounds etc.) animates only then, and hover transitions stay
495
+ * instant. A data attribute so that React doesn't reset it on re-render.
496
+ */
497
+ private markZenModeTransition;
498
+ private unmarkZenModeTransition;
451
499
  componentDidUpdate(prevProps: AppProps, prevState: AppState): void;
452
500
  private renderInteractiveSceneCallback;
453
501
  private onScroll;
454
- private onCut;
455
- private onCopy;
456
502
  private static resetTapTwice;
457
503
  private onTouchStart;
458
504
  private onTouchEnd;
459
- private insertClipboardContent;
460
- pasteFromClipboard: (event: ClipboardEvent) => Promise<void>;
461
505
  addElementsFromPasteOrLibrary: (opts: {
462
506
  elements: readonly ExcalidrawElement[];
463
507
  files: BinaryFiles | null;
@@ -469,8 +513,6 @@ declare class App extends React.Component<AppProps, AppState> {
469
513
  fit?: SetViewportOptions["fit"];
470
514
  preserveFrameChildrenOrder?: boolean;
471
515
  }) => void;
472
- private addElementsFromMixedContentPaste;
473
- private addTextFromPaste;
474
516
  setAppState: React.Component<any, AppState>["setState"];
475
517
  removePointer: (event: React.PointerEvent<HTMLElement> | PointerEvent) => void;
476
518
  toggleLock: (source?: "keyboard" | "ui") => void;
@@ -482,9 +524,11 @@ declare class App extends React.Component<AppProps, AppState> {
482
524
  * imperative API emitter */
483
525
  emitUserFollowIntent: (payload: OnUserFollowedPayload) => void;
484
526
  /** emits an UNFOLLOW intent if currently following someone — use on
485
- * user-initiated viewport changes which should break follow mode */
527
+ * viewport changes that take the view over from the followed user (user
528
+ * pans and zooms, `setViewport` navigation) */
486
529
  requestUnfollow: () => void;
487
530
  setToast: (toast: AppState["toast"]) => void;
531
+ private showSceneReplacedToast;
488
532
  restoreFileFromShare: () => Promise<void>;
489
533
  /**
490
534
  * adds supplied files to existing files in the appState.
@@ -509,6 +553,10 @@ declare class App extends React.Component<AppProps, AppState> {
509
553
  */
510
554
  captureUpdate?: SceneData["captureUpdate"];
511
555
  }) => void;
556
+ /**
557
+ * see {@link ExcalidrawImperativeAPI.setElementRenderOverrides} for details
558
+ */
559
+ setElementRenderOverrides: (overrides: ElementRenderOverrides | null) => void;
512
560
  applyDeltas: (deltas: StoreDelta[], options?: ApplyToOptions) => [SceneElementsMap, AppState, boolean];
513
561
  mutateElement: <TElement extends Mutable<ExcalidrawElement>>(element: TElement, updates: ElementUpdate<TElement>, informMutation?: boolean) => TElement;
514
562
  triggerRender: (
@@ -556,13 +604,7 @@ declare class App extends React.Component<AppProps, AppState> {
556
604
  private onGestureStart;
557
605
  private onGestureChange;
558
606
  private onGestureEnd;
559
- private handleTextWysiwyg;
560
- private deselectElements;
561
- private getSelectedTextElement;
562
- private getSelectedTextEditingContainerAtPosition;
563
- getTextElementAtPosition(x: number, y: number): NonDeleted<ExcalidrawTextElement> | null;
564
- private isHittingTextAutoResizeHandle;
565
- private handleTextAutoResizeHandlePointerDown;
607
+ deselectElements(): void;
566
608
  getElementAtPosition(x: number, y: number, opts?: ({
567
609
  includeBoundTextElement?: boolean;
568
610
  includeLockedElements?: boolean;
@@ -571,167 +613,17 @@ declare class App extends React.Component<AppProps, AppState> {
571
613
  }) & {
572
614
  preferSelected?: boolean;
573
615
  }): NonDeleted<ExcalidrawElement> | null;
574
- private getElementsAtPosition;
575
- getElementHitThreshold(element: ExcalidrawElement): number;
576
- private hitElement;
577
- getTextBindableContainerAtPosition(x: number, y: number): (Readonly<{
578
- id: string;
579
- x: number;
580
- y: number;
581
- strokeColor: string;
582
- backgroundColor: string;
583
- fillStyle: import("@excalidraw/element/types").FillStyle;
584
- strokeWidth: number;
585
- strokeStyle: import("@excalidraw/element/types").StrokeStyle;
586
- roundness: null | {
587
- type: import("@excalidraw/element/types").RoundnessType;
588
- value?: number;
589
- };
590
- roughness: number;
591
- opacity: number;
592
- width: number;
593
- height: number;
594
- angle: Radians;
595
- seed: number;
596
- version: number;
597
- versionNonce: number;
598
- index: import("@excalidraw/element/types").FractionalIndex | null;
599
- isDeleted: boolean;
600
- groupIds: readonly import("@excalidraw/element/types").GroupId[];
601
- frameId: string | null;
602
- boundElements: readonly import("@excalidraw/element/types").BoundElement[] | null;
603
- updated: number;
604
- link: string | null;
605
- locked: boolean;
606
- customData?: Record<string, any>;
607
- }> & {
608
- type: "rectangle";
609
- } & {
610
- isDeleted: false;
611
- }) | (Readonly<{
612
- id: string;
613
- x: number;
614
- y: number;
615
- strokeColor: string;
616
- backgroundColor: string;
617
- fillStyle: import("@excalidraw/element/types").FillStyle;
618
- strokeWidth: number;
619
- strokeStyle: import("@excalidraw/element/types").StrokeStyle;
620
- roundness: null | {
621
- type: import("@excalidraw/element/types").RoundnessType;
622
- value?: number;
623
- };
624
- roughness: number;
625
- opacity: number;
626
- width: number;
627
- height: number;
628
- angle: Radians;
629
- seed: number;
630
- version: number;
631
- versionNonce: number;
632
- index: import("@excalidraw/element/types").FractionalIndex | null;
633
- isDeleted: boolean;
634
- groupIds: readonly import("@excalidraw/element/types").GroupId[];
635
- frameId: string | null;
636
- boundElements: readonly import("@excalidraw/element/types").BoundElement[] | null;
637
- updated: number;
638
- link: string | null;
639
- locked: boolean;
640
- customData?: Record<string, any>;
641
- }> & {
642
- type: "diamond";
643
- } & {
644
- isDeleted: false;
645
- }) | (Readonly<{
646
- id: string;
647
- x: number;
648
- y: number;
649
- strokeColor: string;
650
- backgroundColor: string;
651
- fillStyle: import("@excalidraw/element/types").FillStyle;
652
- strokeWidth: number;
653
- strokeStyle: import("@excalidraw/element/types").StrokeStyle;
654
- roundness: null | {
655
- type: import("@excalidraw/element/types").RoundnessType;
656
- value?: number;
657
- };
658
- roughness: number;
659
- opacity: number;
660
- width: number;
661
- height: number;
662
- angle: Radians;
663
- seed: number;
664
- version: number;
665
- versionNonce: number;
666
- index: import("@excalidraw/element/types").FractionalIndex | null;
667
- isDeleted: boolean;
668
- groupIds: readonly import("@excalidraw/element/types").GroupId[];
669
- frameId: string | null;
670
- boundElements: readonly import("@excalidraw/element/types").BoundElement[] | null;
671
- updated: number;
672
- link: string | null;
673
- locked: boolean;
674
- customData?: Record<string, any>;
675
- }> & {
676
- type: "ellipse";
677
- } & {
678
- isDeleted: false;
679
- }) | (Readonly<{
680
- id: string;
681
- x: number;
682
- y: number;
683
- strokeColor: string;
684
- backgroundColor: string;
685
- fillStyle: import("@excalidraw/element/types").FillStyle;
686
- strokeWidth: number;
687
- strokeStyle: import("@excalidraw/element/types").StrokeStyle;
688
- roundness: null | {
689
- type: import("@excalidraw/element/types").RoundnessType;
690
- value?: number;
691
- };
692
- roughness: number;
693
- opacity: number;
694
- width: number;
695
- height: number;
696
- angle: Radians;
697
- seed: number;
698
- version: number;
699
- versionNonce: number;
700
- index: import("@excalidraw/element/types").FractionalIndex | null;
701
- isDeleted: boolean;
702
- groupIds: readonly import("@excalidraw/element/types").GroupId[];
703
- frameId: string | null;
704
- boundElements: readonly import("@excalidraw/element/types").BoundElement[] | null;
705
- updated: number;
706
- link: string | null;
707
- locked: boolean;
708
- customData?: Record<string, any>;
709
- }> & Readonly<{
710
- type: "line" | "arrow";
711
- points: readonly LocalPoint[];
712
- startBinding: import("@excalidraw/element/types").FixedPointBinding | null;
713
- endBinding: import("@excalidraw/element/types").FixedPointBinding | null;
714
- startArrowhead: import("@excalidraw/element/types").Arrowhead | null;
715
- endArrowhead: import("@excalidraw/element/types").Arrowhead | null;
716
- }> & Readonly<{
717
- type: "arrow";
718
- elbowed: boolean;
719
- }> & {
720
- isDeleted: false;
721
- }) | null;
722
- /**
723
- * Whether a text element's content is still being authored.
724
- *
725
- * Creating a text reverts the tool to selection during pointerdown, so the
726
- * pointerup that follows looks like an ordinary canvas click and would
727
- * capture the still-empty element as a history entry of its own. Undo would
728
- * then rewind only the typing, restoring an invisible, zero-content element
729
- * (and, for an endpoint label, leaving the arrow bound to it) rather than
730
- * removing it. The editor's own submit captures the finished text instead,
731
- * so the whole create-and-type lands in a single entry.
616
+ getElementsAtPosition(x: number, y: number, opts?: {
617
+ includeBoundTextElement?: boolean;
618
+ includeLockedElements?: boolean;
619
+ }): NonDeleted<ExcalidrawElement>[];
620
+ /**
621
+ * Whether the element's frame clips it away at the position — hitting a
622
+ * frame's element from outside the frame is not considered a hit.
732
623
  */
733
- private isEditingTextContent;
734
- private startTextEditing;
624
+ isClippedByFrameAt(x: number, y: number, element: ExcalidrawElement): boolean;
625
+ getElementHitThreshold(element: ExcalidrawElement): number;
626
+ hitElement(x: number, y: number, element: NonDeletedExcalidrawElement, considerBoundingBox?: boolean): boolean;
735
627
  private startImageCropping;
736
628
  private finishImageCropping;
737
629
  private shouldHandleBrowserCanvasDoubleClick;
@@ -784,8 +676,19 @@ declare class App extends React.Component<AppProps, AppState> {
784
676
  private handleCanvasPointerMove;
785
677
  private handleEraser;
786
678
  private handleTouchMove;
679
+ /**
680
+ * Applies the hover affordances of a selected linear element: the cursor,
681
+ * plus the hovered-handle state that renders them highlighted.
682
+ */
787
683
  handleHoverSelectedLinearElement(linearElementEditor: LinearElementEditor, scenePointerX: number, scenePointerY: number): void;
788
684
  private handleCanvasPointerDown;
685
+ /**
686
+ * The browser took the pointer over (scroll, pinch, palm rejection): no
687
+ * pointerup will follow, so the gesture is torn down here and now — the
688
+ * same cleanup a lost pointerup gets at the next press, only not left
689
+ * lying in wait for it, where its replay would tangle with that press.
690
+ */
691
+ private handleCanvasPointerCancel;
789
692
  private handleCanvasPointerUp;
790
693
  private maybeOpenContextMenuAfterPointerDownOnTouchDevices;
791
694
  private resetContextMenuTimer;
@@ -795,7 +698,6 @@ declare class App extends React.Component<AppProps, AppState> {
795
698
  * pointerup handlers manually
796
699
  */
797
700
  private maybeCleanupAfterMissingPointerUp;
798
- handleCanvasPanUsingWheelOrSpaceDrag: (event: React.PointerEvent<HTMLElement> | MouseEvent) => boolean;
799
701
  private updateGestureOnPointerDown;
800
702
  /**
801
703
  * Tracks the pointer within the ongoing multi-touch gesture and applies
@@ -811,7 +713,6 @@ declare class App extends React.Component<AppProps, AppState> {
811
713
  private handleSelectionOnPointerDown;
812
714
  private isASelectedElement;
813
715
  private isHittingCommonBoundingBoxOfSelectedElements;
814
- private handleTextOnPointerDown;
815
716
  private handleFreeDrawElementOnPointerDown;
816
717
  insertIframeElement: ({ sceneX, sceneY, width, height, }: {
817
718
  sceneX: number;
@@ -826,12 +727,14 @@ declare class App extends React.Component<AppProps, AppState> {
826
727
  }) => NonDeleted<ExcalidrawEmbeddableElement> | undefined;
827
728
  private newImagePlaceholder;
828
729
  private handleLinearElementOnPointerDown;
829
- private getCurrentItemRoundness;
830
- private getCurrentItemStrokeWidth;
730
+ getCurrentItemRoundness(elementType: "selection" | "rectangle" | "stickynote" | "diamond" | "ellipse" | "iframe" | "embeddable"): {
731
+ type: 2 | 3;
732
+ } | null;
733
+ getCurrentItemStrokeWidth(elementType: ExcalidrawElement["type"]): number;
831
734
  private createGenericElementOnPointerDown;
832
735
  private createFrameElementOnPointerDown;
833
- private maybeCacheReferenceSnapPoints;
834
- private maybeCacheVisibleGaps;
736
+ maybeCacheReferenceSnapPoints(event: KeyboardModifiersObject, selectedElements: readonly NonDeletedExcalidrawElement[], recomputeAnyways?: boolean): void;
737
+ maybeCacheVisibleGaps(event: KeyboardModifiersObject, selectedElements: readonly NonDeletedExcalidrawElement[], recomputeAnyways?: boolean): void;
835
738
  private onKeyDownFromPointerDownHandler;
836
739
  private onKeyUpFromPointerDownHandler;
837
740
  private onPointerMoveFromPointerDownHandler;
@@ -858,23 +761,31 @@ declare class App extends React.Component<AppProps, AppState> {
858
761
  private scheduleImageRefresh;
859
762
  private clearSelection;
860
763
  private handleInteractiveCanvasRef;
861
- private insertImages;
764
+ insertImages: (imageFiles: File[], sceneX: number, sceneY: number) => Promise<void>;
862
765
  private handleAppOnDrop;
863
- loadFileToCanvas: (file: File, fileHandle: FileSystemFileHandle | null) => Promise<void>;
766
+ /** @returns true if the file replaced the scene */
767
+ loadFileToCanvas: (file: File, fileHandle: FileSystemFileHandle | null, insertPosition?: {
768
+ clientX: number;
769
+ clientY: number;
770
+ }) => Promise<true | undefined>;
864
771
  private handleCanvasContextMenu;
865
- private maybeDragNewGenericElement;
772
+ /** opens the context menu for the element under the pointer, or the canvas */
773
+ openContextMenu: (pointer: {
774
+ clientX: number;
775
+ clientY: number;
776
+ button?: number;
777
+ pointerType?: string;
778
+ }) => void;
779
+ maybeDragNewGenericElement: (pointerDownState: PointerDownState, event: MouseEvent | KeyboardEvent, informMutation?: boolean) => void;
866
780
  private maybeHandleCrop;
867
781
  private maybeHandleResize;
868
782
  private getContextMenuItems;
869
- private handleWheel;
870
- getTextWysiwygSnappedToCenterPosition(x: number, y: number, appState: AppState, container?: ExcalidrawTextContainer | null): {
871
- viewportX: number;
872
- viewportY: number;
873
- elementCenterX: number;
874
- elementCenterY: number;
875
- } | undefined;
876
- private savePointer;
877
- private resetShouldCacheIgnoreZoomDebounced;
783
+ savePointer: (x: number, y: number, button: "up" | "down") => void;
784
+ resetShouldCacheIgnoreZoomDebounced: {
785
+ (): void;
786
+ flush(): void;
787
+ cancel(): void;
788
+ };
878
789
  private updateDOMRect;
879
790
  refresh: () => void;
880
791
  private getCanvasOffsets;
@@ -0,0 +1,101 @@
1
+ import { duplicateElements } from "@excalidraw/element";
2
+ import type { ExcalidrawElement, ExcalidrawTextElement } from "@excalidraw/element/types";
3
+ import type { PointerDownState } from "../types";
4
+ import type App from "./App";
5
+ type Duplication = Pick<ReturnType<typeof duplicateElements>, "duplicatedElements" | "duplicateElementsMap" | "origElementsMap" | "origIdToDuplicateId" | "duplicateIdToOrigId">;
6
+ /**
7
+ * Owns the duplication paths which involve the host (`props.onDuplicate`):
8
+ * duplicating elements into the scene (paste, library insert etc.), and
9
+ * duplicating the dragged selection (alt-drag). The duplicate action shares
10
+ * `runOnDuplicate()`.
11
+ */
12
+ export declare class AppDuplicate {
13
+ private app;
14
+ private dependencies;
15
+ constructor(app: App, dependencies: {
16
+ /** pointers currently down */
17
+ getPointerCount: () => number;
18
+ });
19
+ /**
20
+ * Hands the duplication over to the host's `props.onDuplicate` (if any),
21
+ * and reconciles what it returned with the duplicates.
22
+ *
23
+ * @returns next elements, and the duplicates that weren't vetoed
24
+ */
25
+ runOnDuplicate: (duplication: Duplication, nextElements: ExcalidrawElement[],
26
+ /** excludes the duplicated elements */
27
+ prevElements: readonly ExcalidrawElement[]) => {
28
+ elements: ExcalidrawElement[];
29
+ duplicatedElements: import("@excalidraw/element/types").NonDeletedExcalidrawElement[];
30
+ };
31
+ /**
32
+ * Runs `update` once what's pending is committed, capturing what it changes
33
+ * (if it returns `true`) as a separate undo step.
34
+ */
35
+ private afterCommit;
36
+ /**
37
+ * Advances the list markers of the duplicated texts (`1.` -> `2.`) once
38
+ * the duplication is committed, as a separate undo step, so that undo
39
+ * reverts the markers first.
40
+ */
41
+ advanceListMarkers: (duplicatedElements: readonly ExcalidrawElement[]) => void;
42
+ /**
43
+ * The text whose editing an alt-press on it ended, while the press is
44
+ * handed over to the canvas (see `handOverTextEditorPress()`).
45
+ */
46
+ handedOverTextId: ExcalidrawTextElement["id"] | null;
47
+ /**
48
+ * An alt-press on the text being edited, once it ended the editing, is
49
+ * handed over to the canvas, for the text to be alt-dragged (duplicated) as
50
+ * on the canvas — its duplicate is then edited on drop.
51
+ */
52
+ handOverTextEditorPress: (event: PointerEvent, textElementId: ExcalidrawTextElement["id"]) => void;
53
+ /**
54
+ * The pointer down a handed-over press is replayed as (see
55
+ * `handOverTextEditorPress()`) moves what was edited — the text, or its
56
+ * container — and nothing beneath the editor, which reaches past the text:
57
+ * no resize handle, nor an arrow's point, midpoint or label.
58
+ *
59
+ * @returns `false` if the pointer down isn't a handed-over press
60
+ */
61
+ hitEditedElement: (pointerDownState: PointerDownState) => boolean;
62
+ /**
63
+ * On alt-drag drop: the list markers advanced along with the drag go back,
64
+ * for the drag to be committed as is, and forth again once it is, as
65
+ * a separate undo step (before the browser gets to paint either).
66
+ *
67
+ * A duplicate is then edited (once the drop is committed): a single list
68
+ * item with text after its marker, with that text selected (`1. |foo|`),
69
+ * as it's likely to differ from the original's — or else the duplicate of
70
+ * the text the drag ended the editing of, with all of it selected.
71
+ */
72
+ commitDraggedDuplicates: ({ hit }: PointerDownState, { editText, }: {
73
+ /** `false` if the drag didn't end with a genuine pointerup */
74
+ editText: boolean;
75
+ }) => void;
76
+ private editDuplicatedText;
77
+ /**
78
+ * Duplicates elements so that they end up centered at the scene coords
79
+ * (and in the frame at that point, if any). Doesn't update the scene.
80
+ *
81
+ * @returns `null` if the host vetoed the duplication
82
+ */
83
+ duplicateAtSceneCoords: (elements: readonly ExcalidrawElement[], { x, y }: {
84
+ x: number;
85
+ y: number;
86
+ }, opts?: {
87
+ retainSeed?: boolean;
88
+ preserveFrameChildrenOrder?: boolean;
89
+ }) => {
90
+ nextElements: ExcalidrawElement[];
91
+ duplicatedElements: import("@excalidraw/element/types").NonDeletedExcalidrawElement[];
92
+ } | null;
93
+ /**
94
+ * Duplicates the selection being dragged: the originals go back to where
95
+ * the drag started, and the drag continues with the duplicates.
96
+ *
97
+ * If the host vetoes the duplication, the originals keep being dragged.
98
+ */
99
+ duplicateDraggedSelection: (pointerDownState: PointerDownState, event: PointerEvent) => void;
100
+ }
101
+ export {};
@@ -0,0 +1,62 @@
1
+ import type React from "react";
2
+ import type App from "./App";
3
+ /**
4
+ * The drag-pan: a pointer drag that moves the canvas — the wheel or the
5
+ * secondary button, the main button while space is held or the hand tool
6
+ * is active, or any button in view mode. One session at a time, owning its
7
+ * window listeners and teardown; wheel input is gated on it (see
8
+ * `AppWheel`).
9
+ *
10
+ * A secondary-button session is a pan only once the pointer travels past
11
+ * the drag threshold; released before that, it is a right-click. The
12
+ * platform's `contextmenu` event opens the menu for a right-click where it
13
+ * follows the release (Windows), as it always has; where it comes with the
14
+ * press (macOS, Linux) it is swallowed — a drag cannot be told from a
15
+ * click yet — and the session opens the menu on release instead.
16
+ */
17
+ export declare class AppPan {
18
+ private app;
19
+ private dependencies;
20
+ /** space held down turns a main-button drag into a pan */
21
+ private spaceHeld;
22
+ private active;
23
+ /** the secondary-button session, while one is active */
24
+ private secondary;
25
+ /** the platform fires `contextmenu` on mouseup (Windows) or on mousedown
26
+ * (macOS, Linux); the one belonging to a secondary-button session is not a
27
+ * new click, whichever side of the session it lands on */
28
+ private suppressNextContextMenu;
29
+ /** applies the pointer move the session is holding back for its next
30
+ * frame, if any */
31
+ private pendingMoveFlush;
32
+ private teardown;
33
+ constructor(app: App, dependencies: {
34
+ /** pointers currently down (a two-finger gesture is not a pan) */
35
+ getPointerCount: () => number;
36
+ /** a scrollbar being dragged (App's own drag, not a pan session) */
37
+ isDraggingScrollBar: () => boolean;
38
+ });
39
+ isActive: () => boolean;
40
+ isSpaceHeld: () => boolean;
41
+ setSpaceHeld: (held: boolean) => void;
42
+ /**
43
+ * Whether the pointer is navigating the viewport rather than acting on the
44
+ * scene — space held to pan, a pan in progress, a scrollbar drag, or the
45
+ * hand tool. Hover and cursor then belong to the navigation.
46
+ */
47
+ isNavigating: () => boolean;
48
+ /** applies the pointer move still waiting for its frame, if any */
49
+ flushMove: () => void;
50
+ /** ends the active session, if any — pointerup may never arrive (the user
51
+ * tabs away, a new pointerdown lands first) */
52
+ end: () => void;
53
+ /**
54
+ * Whether a `contextmenu` event belongs to a secondary-button session and
55
+ * must not open the menu: it came with the press (the session decides on
56
+ * release), or it follows a release that turned out to be a drag.
57
+ */
58
+ consumesContextMenuEvent: () => boolean;
59
+ /** starts a session for the pointerdown if it qualifies; returns whether
60
+ * it did */
61
+ start: (event: React.PointerEvent<HTMLElement> | MouseEvent) => boolean;
62
+ }