@excalidraw/excalidraw 0.16.1-4765f55 → 0.16.1-4c35eba

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 (40) hide show
  1. package/dist/excalidraw.development.js +51 -18
  2. package/dist/excalidraw.production.min.js +1 -1
  3. package/package.json +1 -1
  4. package/types/actions/actionAddToLibrary.d.ts +18 -0
  5. package/types/actions/actionBoundText.d.ts +12 -0
  6. package/types/actions/actionCanvas.d.ts +66 -0
  7. package/types/actions/actionClipboard.d.ts +30 -0
  8. package/types/actions/actionDeleteSelected.d.ts +18 -0
  9. package/types/actions/actionElementLock.d.ts +12 -0
  10. package/types/actions/actionExport.d.ts +54 -0
  11. package/types/actions/actionFinalize.d.ts +12 -0
  12. package/types/actions/actionFrame.d.ts +18 -0
  13. package/types/actions/actionGroup.d.ts +12 -0
  14. package/types/actions/actionLinearEditor.d.ts +6 -0
  15. package/types/actions/actionMenu.d.ts +18 -0
  16. package/types/actions/actionProperties.d.ts +78 -0
  17. package/types/actions/actionSelectAll.d.ts +6 -0
  18. package/types/actions/actionStyles.d.ts +6 -0
  19. package/types/actions/actionToggleGridMode.d.ts +6 -0
  20. package/types/actions/actionToggleObjectsSnapMode.d.ts +143 -0
  21. package/types/actions/actionToggleStats.d.ts +6 -0
  22. package/types/actions/actionToggleViewMode.d.ts +6 -0
  23. package/types/actions/actionToggleZenMode.d.ts +6 -0
  24. package/types/actions/index.d.ts +1 -0
  25. package/types/actions/shortcuts.d.ts +1 -1
  26. package/types/actions/types.d.ts +1 -1
  27. package/types/appState.d.ts +1 -0
  28. package/types/components/App.d.ts +2 -0
  29. package/types/element/Hyperlink.d.ts +6 -0
  30. package/types/element/bounds.d.ts +4 -5
  31. package/types/element/dragElements.d.ts +11 -2
  32. package/types/element/embeddable.d.ts +6 -0
  33. package/types/element/linearElementEditor.d.ts +6 -0
  34. package/types/element/resizeElements.d.ts +2 -2
  35. package/types/keys.d.ts +1 -0
  36. package/types/math.d.ts +2 -0
  37. package/types/renderer/renderSnaps.d.ts +2 -0
  38. package/types/scene/selection.d.ts +1 -0
  39. package/types/snapping.d.ts +108 -0
  40. package/types/types.d.ts +16 -0
@@ -142,6 +142,12 @@ export declare const actionChangeFillStyle: {
142
142
  pendingImageElementId: string | null;
143
143
  showHyperlinkPopup: false | "editor" | "info";
144
144
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
145
+ snapLines: import("../snapping").SnapLine[];
146
+ originSnapOffset: {
147
+ x: number;
148
+ y: number;
149
+ } | null;
150
+ objectsSnapModeEnabled: boolean;
145
151
  };
146
152
  commitToHistory: true;
147
153
  };
@@ -273,6 +279,12 @@ export declare const actionChangeStrokeWidth: {
273
279
  pendingImageElementId: string | null;
274
280
  showHyperlinkPopup: false | "editor" | "info";
275
281
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
282
+ snapLines: import("../snapping").SnapLine[];
283
+ originSnapOffset: {
284
+ x: number;
285
+ y: number;
286
+ } | null;
287
+ objectsSnapModeEnabled: boolean;
276
288
  };
277
289
  commitToHistory: true;
278
290
  };
@@ -404,6 +416,12 @@ export declare const actionChangeSloppiness: {
404
416
  pendingImageElementId: string | null;
405
417
  showHyperlinkPopup: false | "editor" | "info";
406
418
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
419
+ snapLines: import("../snapping").SnapLine[];
420
+ originSnapOffset: {
421
+ x: number;
422
+ y: number;
423
+ } | null;
424
+ objectsSnapModeEnabled: boolean;
407
425
  };
408
426
  commitToHistory: true;
409
427
  };
@@ -535,6 +553,12 @@ export declare const actionChangeStrokeStyle: {
535
553
  pendingImageElementId: string | null;
536
554
  showHyperlinkPopup: false | "editor" | "info";
537
555
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
556
+ snapLines: import("../snapping").SnapLine[];
557
+ originSnapOffset: {
558
+ x: number;
559
+ y: number;
560
+ } | null;
561
+ objectsSnapModeEnabled: boolean;
538
562
  };
539
563
  commitToHistory: true;
540
564
  };
@@ -666,6 +690,12 @@ export declare const actionChangeOpacity: {
666
690
  pendingImageElementId: string | null;
667
691
  showHyperlinkPopup: false | "editor" | "info";
668
692
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
693
+ snapLines: import("../snapping").SnapLine[];
694
+ originSnapOffset: {
695
+ x: number;
696
+ y: number;
697
+ } | null;
698
+ objectsSnapModeEnabled: boolean;
669
699
  };
670
700
  commitToHistory: true;
671
701
  };
@@ -797,6 +827,12 @@ export declare const actionChangeFontSize: {
797
827
  pendingImageElementId: string | null;
798
828
  showHyperlinkPopup: false | "editor" | "info";
799
829
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
830
+ snapLines: import("../snapping").SnapLine[];
831
+ originSnapOffset: {
832
+ x: number;
833
+ y: number;
834
+ } | null;
835
+ objectsSnapModeEnabled: boolean;
800
836
  };
801
837
  commitToHistory: boolean;
802
838
  };
@@ -928,6 +964,12 @@ export declare const actionDecreaseFontSize: {
928
964
  pendingImageElementId: string | null;
929
965
  showHyperlinkPopup: false | "editor" | "info";
930
966
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
967
+ snapLines: import("../snapping").SnapLine[];
968
+ originSnapOffset: {
969
+ x: number;
970
+ y: number;
971
+ } | null;
972
+ objectsSnapModeEnabled: boolean;
931
973
  };
932
974
  commitToHistory: boolean;
933
975
  };
@@ -1059,6 +1101,12 @@ export declare const actionIncreaseFontSize: {
1059
1101
  pendingImageElementId: string | null;
1060
1102
  showHyperlinkPopup: false | "editor" | "info";
1061
1103
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
1104
+ snapLines: import("../snapping").SnapLine[];
1105
+ originSnapOffset: {
1106
+ x: number;
1107
+ y: number;
1108
+ } | null;
1109
+ objectsSnapModeEnabled: boolean;
1062
1110
  };
1063
1111
  commitToHistory: boolean;
1064
1112
  };
@@ -1190,6 +1238,12 @@ export declare const actionChangeFontFamily: {
1190
1238
  pendingImageElementId: string | null;
1191
1239
  showHyperlinkPopup: false | "editor" | "info";
1192
1240
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
1241
+ snapLines: import("../snapping").SnapLine[];
1242
+ originSnapOffset: {
1243
+ x: number;
1244
+ y: number;
1245
+ } | null;
1246
+ objectsSnapModeEnabled: boolean;
1193
1247
  };
1194
1248
  commitToHistory: true;
1195
1249
  };
@@ -1321,6 +1375,12 @@ export declare const actionChangeTextAlign: {
1321
1375
  pendingImageElementId: string | null;
1322
1376
  showHyperlinkPopup: false | "editor" | "info";
1323
1377
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
1378
+ snapLines: import("../snapping").SnapLine[];
1379
+ originSnapOffset: {
1380
+ x: number;
1381
+ y: number;
1382
+ } | null;
1383
+ objectsSnapModeEnabled: boolean;
1324
1384
  };
1325
1385
  commitToHistory: true;
1326
1386
  };
@@ -1454,6 +1514,12 @@ export declare const actionChangeVerticalAlign: {
1454
1514
  pendingImageElementId: string | null;
1455
1515
  showHyperlinkPopup: false | "editor" | "info";
1456
1516
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
1517
+ snapLines: import("../snapping").SnapLine[];
1518
+ originSnapOffset: {
1519
+ x: number;
1520
+ y: number;
1521
+ } | null;
1522
+ objectsSnapModeEnabled: boolean;
1457
1523
  };
1458
1524
  commitToHistory: true;
1459
1525
  };
@@ -1585,6 +1651,12 @@ export declare const actionChangeRoundness: {
1585
1651
  pendingImageElementId: string | null;
1586
1652
  showHyperlinkPopup: false | "editor" | "info";
1587
1653
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
1654
+ snapLines: import("../snapping").SnapLine[];
1655
+ originSnapOffset: {
1656
+ x: number;
1657
+ y: number;
1658
+ } | null;
1659
+ objectsSnapModeEnabled: boolean;
1588
1660
  };
1589
1661
  commitToHistory: true;
1590
1662
  };
@@ -1719,6 +1791,12 @@ export declare const actionChangeArrowhead: {
1719
1791
  pendingImageElementId: string | null;
1720
1792
  showHyperlinkPopup: false | "editor" | "info";
1721
1793
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
1794
+ snapLines: import("../snapping").SnapLine[];
1795
+ originSnapOffset: {
1796
+ x: number;
1797
+ y: number;
1798
+ } | null;
1799
+ objectsSnapModeEnabled: boolean;
1722
1800
  };
1723
1801
  commitToHistory: true;
1724
1802
  };
@@ -125,6 +125,12 @@ export declare const actionSelectAll: {
125
125
  };
126
126
  pendingImageElementId: string | null;
127
127
  showHyperlinkPopup: false | "editor" | "info";
128
+ snapLines: import("../snapping").SnapLine[];
129
+ originSnapOffset: {
130
+ x: number;
131
+ y: number;
132
+ } | null;
133
+ objectsSnapModeEnabled: boolean;
128
134
  };
129
135
  commitToHistory: true;
130
136
  };
@@ -122,6 +122,12 @@ export declare const actionCopyStyles: {
122
122
  pendingImageElementId: string | null;
123
123
  showHyperlinkPopup: false | "editor" | "info";
124
124
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
125
+ snapLines: import("../snapping").SnapLine[];
126
+ originSnapOffset: {
127
+ x: number;
128
+ y: number;
129
+ } | null;
130
+ objectsSnapModeEnabled: boolean;
125
131
  };
126
132
  commitToHistory: false;
127
133
  };
@@ -9,6 +9,7 @@ export declare const actionToggleGridMode: {
9
9
  perform(elements: readonly import("../element/types").ExcalidrawElement[], appState: Readonly<AppState>): {
10
10
  appState: {
11
11
  gridSize: number | null;
12
+ objectsSnapModeEnabled: false;
12
13
  contextMenu: {
13
14
  items: import("../components/ContextMenu").ContextMenuItems;
14
15
  top: number;
@@ -126,6 +127,11 @@ export declare const actionToggleGridMode: {
126
127
  pendingImageElementId: string | null;
127
128
  showHyperlinkPopup: false | "editor" | "info";
128
129
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
130
+ snapLines: import("../snapping").SnapLine[];
131
+ originSnapOffset: {
132
+ x: number;
133
+ y: number;
134
+ } | null;
129
135
  };
130
136
  commitToHistory: false;
131
137
  };
@@ -0,0 +1,143 @@
1
+ export declare const actionToggleObjectsSnapMode: {
2
+ name: "objectsSnapMode";
3
+ viewMode: true;
4
+ trackEvent: {
5
+ category: "canvas";
6
+ predicate: (appState: Readonly<import("../types").AppState>) => boolean;
7
+ };
8
+ perform(elements: readonly import("../element/types").ExcalidrawElement[], appState: Readonly<import("../types").AppState>): {
9
+ appState: {
10
+ objectsSnapModeEnabled: boolean;
11
+ gridSize: null;
12
+ contextMenu: {
13
+ items: import("../components/ContextMenu").ContextMenuItems;
14
+ top: number;
15
+ left: number;
16
+ } | null;
17
+ showWelcomeScreen: boolean;
18
+ isLoading: boolean;
19
+ errorMessage: import("react").ReactNode;
20
+ activeEmbeddable: {
21
+ element: import("../element/types").NonDeletedExcalidrawElement;
22
+ state: "active" | "hover";
23
+ } | null;
24
+ draggingElement: import("../element/types").NonDeletedExcalidrawElement | null;
25
+ resizingElement: import("../element/types").NonDeletedExcalidrawElement | null;
26
+ multiElement: import("../element/types").NonDeleted<import("../element/types").ExcalidrawLinearElement> | null;
27
+ selectionElement: import("../element/types").NonDeletedExcalidrawElement | null;
28
+ isBindingEnabled: boolean;
29
+ startBoundElement: import("../element/types").NonDeleted<import("../element/types").ExcalidrawBindableElement> | null;
30
+ suggestedBindings: import("../element/binding").SuggestedBinding[];
31
+ frameToHighlight: import("../element/types").NonDeleted<import("../element/types").ExcalidrawFrameElement> | null;
32
+ frameRendering: {
33
+ enabled: boolean;
34
+ name: boolean;
35
+ outline: boolean;
36
+ clip: boolean;
37
+ };
38
+ editingFrame: string | null;
39
+ elementsToHighlight: import("../element/types").NonDeleted<import("../element/types").ExcalidrawElement>[] | null;
40
+ editingElement: import("../element/types").NonDeletedExcalidrawElement | null;
41
+ editingLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
42
+ activeTool: {
43
+ lastActiveTool: import("../types").LastActiveTool;
44
+ locked: boolean;
45
+ } & ({
46
+ type: "line" | "arrow" | "text" | "selection" | "rectangle" | "diamond" | "ellipse" | "embeddable" | "image" | "frame" | "freedraw" | "eraser" | "hand";
47
+ customType: null;
48
+ } | {
49
+ type: "custom";
50
+ customType: string;
51
+ });
52
+ penMode: boolean;
53
+ penDetected: boolean;
54
+ exportBackground: boolean;
55
+ exportEmbedScene: boolean;
56
+ exportWithDarkMode: boolean;
57
+ exportScale: number;
58
+ currentItemStrokeColor: string;
59
+ currentItemBackgroundColor: string;
60
+ currentItemFillStyle: import("../element/types").FillStyle;
61
+ currentItemStrokeWidth: number;
62
+ currentItemStrokeStyle: import("../element/types").StrokeStyle;
63
+ currentItemRoughness: number;
64
+ currentItemOpacity: number;
65
+ currentItemFontFamily: number;
66
+ currentItemFontSize: number;
67
+ currentItemTextAlign: string;
68
+ currentItemStartArrowhead: import("../element/types").Arrowhead | null;
69
+ currentItemEndArrowhead: import("../element/types").Arrowhead | null;
70
+ currentItemRoundness: import("../element/types").StrokeRoundness;
71
+ viewBackgroundColor: string;
72
+ scrollX: number;
73
+ scrollY: number;
74
+ cursorButton: "up" | "down";
75
+ scrolledOutside: boolean;
76
+ name: string;
77
+ isResizing: boolean;
78
+ isRotating: boolean;
79
+ zoom: Readonly<{
80
+ value: import("../types").NormalizedZoomValue;
81
+ }>;
82
+ openMenu: "canvas" | "shape" | null;
83
+ openPopup: "canvasBackground" | "elementBackground" | "elementStroke" | null;
84
+ openSidebar: {
85
+ name: string;
86
+ tab?: string | undefined;
87
+ } | null;
88
+ openDialog: "imageExport" | "help" | "jsonExport" | null;
89
+ defaultSidebarDockedPreference: boolean;
90
+ lastPointerDownWith: import("../element/types").PointerType;
91
+ selectedElementIds: Readonly<{
92
+ [id: string]: true;
93
+ }>;
94
+ previousSelectedElementIds: {
95
+ [id: string]: true;
96
+ };
97
+ selectedElementsAreBeingDragged: boolean;
98
+ shouldCacheIgnoreZoom: boolean;
99
+ toast: {
100
+ message: string;
101
+ closable?: boolean | undefined;
102
+ duration?: number | undefined;
103
+ } | null;
104
+ zenModeEnabled: boolean;
105
+ theme: import("../element/types").Theme;
106
+ viewModeEnabled: boolean;
107
+ selectedGroupIds: {
108
+ [groupId: string]: boolean;
109
+ };
110
+ editingGroupId: string | null;
111
+ width: number;
112
+ height: number;
113
+ offsetTop: number;
114
+ offsetLeft: number;
115
+ fileHandle: import("browser-fs-access").FileSystemHandle | null;
116
+ collaborators: Map<string, import("../types").Collaborator>;
117
+ showStats: boolean;
118
+ currentChartType: import("../element/types").ChartType;
119
+ pasteDialog: {
120
+ shown: false;
121
+ data: null;
122
+ } | {
123
+ shown: true;
124
+ data: import("../charts").Spreadsheet;
125
+ };
126
+ pendingImageElementId: string | null;
127
+ showHyperlinkPopup: false | "editor" | "info";
128
+ selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
129
+ snapLines: import("../snapping").SnapLine[];
130
+ originSnapOffset: {
131
+ x: number;
132
+ y: number;
133
+ } | null;
134
+ };
135
+ commitToHistory: false;
136
+ };
137
+ checked: (appState: Readonly<import("../types").AppState>) => boolean;
138
+ predicate: (elements: readonly import("../element/types").ExcalidrawElement[], appState: import("../types").AppState, appProps: import("../types").ExcalidrawProps) => boolean;
139
+ contextItemLabel: string;
140
+ keyTest: (event: KeyboardEvent | import("react").KeyboardEvent<Element>) => boolean;
141
+ } & {
142
+ keyTest?: ((event: KeyboardEvent | import("react").KeyboardEvent<Element>) => boolean) | undefined;
143
+ };
@@ -124,6 +124,12 @@ export declare const actionToggleStats: {
124
124
  pendingImageElementId: string | null;
125
125
  showHyperlinkPopup: false | "editor" | "info";
126
126
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
127
+ snapLines: import("../snapping").SnapLine[];
128
+ originSnapOffset: {
129
+ x: number;
130
+ y: number;
131
+ } | null;
132
+ objectsSnapModeEnabled: boolean;
127
133
  };
128
134
  commitToHistory: false;
129
135
  };
@@ -125,6 +125,12 @@ export declare const actionToggleViewMode: {
125
125
  pendingImageElementId: string | null;
126
126
  showHyperlinkPopup: false | "editor" | "info";
127
127
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
128
+ snapLines: import("../snapping").SnapLine[];
129
+ originSnapOffset: {
130
+ x: number;
131
+ y: number;
132
+ } | null;
133
+ objectsSnapModeEnabled: boolean;
128
134
  };
129
135
  commitToHistory: false;
130
136
  };
@@ -125,6 +125,12 @@ export declare const actionToggleZenMode: {
125
125
  pendingImageElementId: string | null;
126
126
  showHyperlinkPopup: false | "editor" | "info";
127
127
  selectedLinearElement: import("../element/linearElementEditor").LinearElementEditor | null;
128
+ snapLines: import("../snapping").SnapLine[];
129
+ originSnapOffset: {
130
+ x: number;
131
+ y: number;
132
+ } | null;
133
+ objectsSnapModeEnabled: boolean;
128
134
  };
129
135
  commitToHistory: false;
130
136
  };
@@ -17,6 +17,7 @@ export { actionFlipHorizontal, actionFlipVertical } from "./actionFlip";
17
17
  export { actionCopy, actionCut, actionCopyAsPng, actionCopyAsSvg, copyText, } from "./actionClipboard";
18
18
  export { actionToggleGridMode } from "./actionToggleGridMode";
19
19
  export { actionToggleZenMode } from "./actionToggleZenMode";
20
+ export { actionToggleObjectsSnapMode } from "./actionToggleObjectsSnapMode";
20
21
  export { actionToggleStats } from "./actionToggleStats";
21
22
  export { actionUnbindText, actionBindText } from "./actionBoundText";
22
23
  export { actionLink } from "../element/Hyperlink";
@@ -1,4 +1,4 @@
1
1
  import { SubtypeOf } from "../utility-types";
2
2
  import { ActionName } from "./types";
3
- export type ShortcutName = SubtypeOf<ActionName, "toggleTheme" | "loadScene" | "clearCanvas" | "cut" | "copy" | "paste" | "copyStyles" | "pasteStyles" | "selectAll" | "deleteSelectedElements" | "duplicateSelection" | "sendBackward" | "bringForward" | "sendToBack" | "bringToFront" | "copyAsPng" | "copyAsSvg" | "group" | "ungroup" | "gridMode" | "zenMode" | "stats" | "addToLibrary" | "viewMode" | "flipHorizontal" | "flipVertical" | "hyperlink" | "toggleElementLock"> | "saveScene" | "imageExport";
3
+ export type ShortcutName = SubtypeOf<ActionName, "toggleTheme" | "loadScene" | "clearCanvas" | "cut" | "copy" | "paste" | "copyStyles" | "pasteStyles" | "selectAll" | "deleteSelectedElements" | "duplicateSelection" | "sendBackward" | "bringForward" | "sendToBack" | "bringToFront" | "copyAsPng" | "copyAsSvg" | "group" | "ungroup" | "gridMode" | "zenMode" | "objectsSnapMode" | "stats" | "addToLibrary" | "viewMode" | "flipHorizontal" | "flipVertical" | "hyperlink" | "toggleElementLock"> | "saveScene" | "imageExport";
4
4
  export declare const getShortcutFromShortcutName: (name: ShortcutName) => string;
@@ -15,7 +15,7 @@ export type ActionResult = {
15
15
  type ActionFn = (elements: readonly ExcalidrawElement[], appState: Readonly<AppState>, formData: any, app: AppClassProperties) => ActionResult | Promise<ActionResult>;
16
16
  export type UpdaterFn = (res: ActionResult) => void;
17
17
  export type ActionFilterFn = (action: Action) => void;
18
- export type ActionName = "copy" | "cut" | "paste" | "copyAsPng" | "copyAsSvg" | "copyText" | "sendBackward" | "bringForward" | "sendToBack" | "bringToFront" | "copyStyles" | "selectAll" | "pasteStyles" | "gridMode" | "zenMode" | "stats" | "changeStrokeColor" | "changeBackgroundColor" | "changeFillStyle" | "changeStrokeWidth" | "changeStrokeShape" | "changeSloppiness" | "changeStrokeStyle" | "changeArrowhead" | "changeOpacity" | "changeFontSize" | "toggleCanvasMenu" | "toggleEditMenu" | "undo" | "redo" | "finalize" | "changeProjectName" | "changeExportBackground" | "changeExportEmbedScene" | "changeExportScale" | "saveToActiveFile" | "saveFileToDisk" | "loadScene" | "duplicateSelection" | "deleteSelectedElements" | "changeViewBackgroundColor" | "clearCanvas" | "zoomIn" | "zoomOut" | "resetZoom" | "zoomToFit" | "zoomToFitSelection" | "zoomToFitSelectionInViewport" | "changeFontFamily" | "changeTextAlign" | "changeVerticalAlign" | "toggleFullScreen" | "toggleShortcuts" | "group" | "ungroup" | "goToCollaborator" | "addToLibrary" | "changeRoundness" | "alignTop" | "alignBottom" | "alignLeft" | "alignRight" | "alignVerticallyCentered" | "alignHorizontallyCentered" | "distributeHorizontally" | "distributeVertically" | "flipHorizontal" | "flipVertical" | "viewMode" | "exportWithDarkMode" | "toggleTheme" | "increaseFontSize" | "decreaseFontSize" | "unbindText" | "hyperlink" | "bindText" | "unlockAllElements" | "toggleElementLock" | "toggleLinearEditor" | "toggleEraserTool" | "toggleHandTool" | "selectAllElementsInFrame" | "removeAllElementsFromFrame" | "updateFrameRendering" | "setFrameAsActiveTool" | "setEmbeddableAsActiveTool" | "createContainerFromText" | "wrapTextInContainer";
18
+ export type ActionName = "copy" | "cut" | "paste" | "copyAsPng" | "copyAsSvg" | "copyText" | "sendBackward" | "bringForward" | "sendToBack" | "bringToFront" | "copyStyles" | "selectAll" | "pasteStyles" | "gridMode" | "zenMode" | "objectsSnapMode" | "stats" | "changeStrokeColor" | "changeBackgroundColor" | "changeFillStyle" | "changeStrokeWidth" | "changeStrokeShape" | "changeSloppiness" | "changeStrokeStyle" | "changeArrowhead" | "changeOpacity" | "changeFontSize" | "toggleCanvasMenu" | "toggleEditMenu" | "undo" | "redo" | "finalize" | "changeProjectName" | "changeExportBackground" | "changeExportEmbedScene" | "changeExportScale" | "saveToActiveFile" | "saveFileToDisk" | "loadScene" | "duplicateSelection" | "deleteSelectedElements" | "changeViewBackgroundColor" | "clearCanvas" | "zoomIn" | "zoomOut" | "resetZoom" | "zoomToFit" | "zoomToFitSelection" | "zoomToFitSelectionInViewport" | "changeFontFamily" | "changeTextAlign" | "changeVerticalAlign" | "toggleFullScreen" | "toggleShortcuts" | "group" | "ungroup" | "goToCollaborator" | "addToLibrary" | "changeRoundness" | "alignTop" | "alignBottom" | "alignLeft" | "alignRight" | "alignVerticallyCentered" | "alignHorizontallyCentered" | "distributeHorizontally" | "distributeVertically" | "flipHorizontal" | "flipVertical" | "viewMode" | "exportWithDarkMode" | "toggleTheme" | "increaseFontSize" | "decreaseFontSize" | "unbindText" | "hyperlink" | "bindText" | "unlockAllElements" | "toggleElementLock" | "toggleLinearEditor" | "toggleEraserTool" | "toggleHandTool" | "selectAllElementsInFrame" | "removeAllElementsFromFrame" | "updateFrameRendering" | "setFrameAsActiveTool" | "setEmbeddableAsActiveTool" | "createContainerFromText" | "wrapTextInContainer";
19
19
  export type PanelComponentProps = {
20
20
  elements: readonly ExcalidrawElement[];
21
21
  appState: AppState;
@@ -64,6 +64,7 @@ export declare const clearAppStateForLocalStorage: (appState: Partial<AppState>)
64
64
  showStats?: boolean | undefined;
65
65
  currentChartType?: import("./element/types").ChartType | undefined;
66
66
  selectedLinearElement?: import("./element/linearElementEditor").LinearElementEditor | null | undefined;
67
+ objectsSnapModeEnabled?: boolean | undefined;
67
68
  };
68
69
  export declare const cleanAppStateForExport: (appState: Partial<AppState>) => {
69
70
  viewBackgroundColor?: string | undefined;
@@ -220,6 +220,8 @@ declare class App extends React.Component<AppProps, AppState> {
220
220
  private getCurrentItemRoundness;
221
221
  private createGenericElementOnPointerDown;
222
222
  private createFrameElementOnPointerDown;
223
+ private maybeCacheReferenceSnapPoints;
224
+ private maybeCacheVisibleGaps;
223
225
  private onKeyDownFromPointerDownHandler;
224
226
  private onKeyUpFromPointerDownHandler;
225
227
  private onPointerMoveFromPointerDownHandler;
@@ -136,6 +136,12 @@ export declare const actionLink: {
136
136
  };
137
137
  pendingImageElementId: string | null;
138
138
  selectedLinearElement: import("./linearElementEditor").LinearElementEditor | null;
139
+ snapLines: import("../snapping").SnapLine[];
140
+ originSnapOffset: {
141
+ x: number;
142
+ y: number;
143
+ } | null;
144
+ objectsSnapModeEnabled: boolean;
139
145
  };
140
146
  commitToHistory: true;
141
147
  };
@@ -15,11 +15,6 @@ export declare class ElementBounds {
15
15
  private static calculateBounds;
16
16
  }
17
17
  export declare const getElementAbsoluteCoords: (element: ExcalidrawElement, includeBoundText?: boolean) => [number, number, number, number, number, number];
18
- /**
19
- * for a given element, `getElementLineSegments` returns line segments
20
- * that can be used for visual collision detection (useful for frames)
21
- * as opposed to bounding box collision detection
22
- */
23
18
  export declare const getElementLineSegments: (element: ExcalidrawElement) => [Point, Point][];
24
19
  /**
25
20
  * Scene -> Scene coords, but in x1,x2,y1,y2 format.
@@ -34,6 +29,10 @@ export declare const getMinMaxXYFromCurvePathOps: (ops: Op[], transformXY?: ((x:
34
29
  export declare const getArrowheadPoints: (element: ExcalidrawLinearElement, shape: Drawable[], position: "start" | "end", arrowhead: Arrowhead) => number[] | null;
35
30
  export declare const getElementBounds: (element: ExcalidrawElement) => Bounds;
36
31
  export declare const getCommonBounds: (elements: readonly ExcalidrawElement[]) => Bounds;
32
+ export declare const getDraggedElementsBounds: (elements: ExcalidrawElement[], dragOffset: {
33
+ x: number;
34
+ y: number;
35
+ }) => number[];
37
36
  export declare const getResizedElementAbsoluteCoords: (element: ExcalidrawElement, nextWidth: number, nextHeight: number, normalizePoints: boolean) => [number, number, number, number];
38
37
  export declare const getElementPointsCoords: (element: ExcalidrawLinearElement, points: readonly (readonly [number, number])[]) => [number, number, number, number];
39
38
  export declare const getClosestElementBounds: (elements: readonly ExcalidrawElement[], from: {
@@ -1,6 +1,15 @@
1
1
  import { NonDeletedExcalidrawElement } from "./types";
2
2
  import { AppState, PointerDownState } from "../types";
3
3
  import Scene from "../scene/Scene";
4
- export declare const dragSelectedElements: (pointerDownState: PointerDownState, selectedElements: NonDeletedExcalidrawElement[], pointerX: number, pointerY: number, lockDirection: boolean | undefined, distanceX: number | undefined, distanceY: number | undefined, appState: AppState, scene: Scene) => void;
4
+ export declare const dragSelectedElements: (pointerDownState: PointerDownState, selectedElements: NonDeletedExcalidrawElement[], offset: {
5
+ x: number;
6
+ y: number;
7
+ }, appState: AppState, scene: Scene, snapOffset: {
8
+ x: number;
9
+ y: number;
10
+ }, gridSize: AppState["gridSize"]) => void;
5
11
  export declare const getDragOffsetXY: (selectedElements: NonDeletedExcalidrawElement[], x: number, y: number) => [number, number];
6
- export declare const dragNewElement: (draggingElement: NonDeletedExcalidrawElement, elementType: AppState["activeTool"]["type"], originX: number, originY: number, x: number, y: number, width: number, height: number, shouldMaintainAspectRatio: boolean, shouldResizeFromCenter: boolean, widthAspectRatio?: number | null) => void;
12
+ export declare const dragNewElement: (draggingElement: NonDeletedExcalidrawElement, elementType: AppState["activeTool"]["type"], originX: number, originY: number, x: number, y: number, width: number, height: number, shouldMaintainAspectRatio: boolean, shouldResizeFromCenter: boolean, widthAspectRatio?: number | null, originOffset?: {
13
+ x: number;
14
+ y: number;
15
+ } | null) => void;
@@ -142,6 +142,12 @@ export declare const actionSetEmbeddableAsActiveTool: {
142
142
  pendingImageElementId: string | null;
143
143
  showHyperlinkPopup: false | "editor" | "info";
144
144
  selectedLinearElement: import("./linearElementEditor").LinearElementEditor | null;
145
+ snapLines: import("../snapping").SnapLine[];
146
+ originSnapOffset: {
147
+ x: number;
148
+ y: number;
149
+ } | null;
150
+ objectsSnapModeEnabled: boolean;
145
151
  };
146
152
  commitToHistory: false;
147
153
  };
@@ -239,6 +239,12 @@ export declare class LinearElementEditor {
239
239
  pendingImageElementId: string | null;
240
240
  showHyperlinkPopup: false | "editor" | "info";
241
241
  selectedLinearElement: LinearElementEditor | null;
242
+ snapLines: import("../snapping").SnapLine[];
243
+ originSnapOffset: {
244
+ x: number;
245
+ y: number;
246
+ } | null;
247
+ objectsSnapModeEnabled: boolean;
242
248
  };
243
249
  };
244
250
  static deletePoints(element: NonDeleted<ExcalidrawLinearElement>, pointIndices: readonly number[]): void;
@@ -1,8 +1,8 @@
1
1
  import { ExcalidrawLinearElement, NonDeletedExcalidrawElement, NonDeleted } from "./types";
2
2
  import { MaybeTransformHandleType, TransformHandleDirection } from "./transformHandles";
3
- import { PointerDownState } from "../types";
3
+ import { AppState, PointerDownState } from "../types";
4
4
  export declare const normalizeAngle: (angle: number) => number;
5
- export declare const transformElements: (pointerDownState: PointerDownState, transformHandleType: MaybeTransformHandleType, selectedElements: readonly NonDeletedExcalidrawElement[], resizeArrowDirection: "origin" | "end", shouldRotateWithDiscreteAngle: boolean, shouldResizeFromCenter: boolean, shouldMaintainAspectRatio: boolean, pointerX: number, pointerY: number, centerX: number, centerY: number) => boolean;
5
+ export declare const transformElements: (pointerDownState: PointerDownState, transformHandleType: MaybeTransformHandleType, selectedElements: readonly NonDeletedExcalidrawElement[], resizeArrowDirection: "origin" | "end", shouldRotateWithDiscreteAngle: boolean, shouldResizeFromCenter: boolean, shouldMaintainAspectRatio: boolean, pointerX: number, pointerY: number, centerX: number, centerY: number, appState: AppState) => boolean;
6
6
  export declare const resizeSingleElement: (originalElements: PointerDownState["originalElements"], shouldMaintainAspectRatio: boolean, element: NonDeletedExcalidrawElement, transformHandleDirection: TransformHandleDirection, shouldResizeFromCenter: boolean, pointerX: number, pointerY: number) => void;
7
7
  export declare const resizeMultipleElements: (pointerDownState: PointerDownState, selectedElements: readonly NonDeletedExcalidrawElement[], transformHandleType: "nw" | "ne" | "sw" | "se", shouldResizeFromCenter: boolean, pointerX: number, pointerY: number) => void;
8
8
  export declare const getResizeOffsetXY: (transformHandleType: MaybeTransformHandleType, selectedElements: NonDeletedExcalidrawElement[], x: number, y: number) => [number, number];
package/types/keys.d.ts CHANGED
@@ -19,6 +19,7 @@ export declare const CODES: {
19
19
  readonly V: "KeyV";
20
20
  readonly Z: "KeyZ";
21
21
  readonly R: "KeyR";
22
+ readonly S: "KeyS";
22
23
  };
23
24
  export declare const KEYS: {
24
25
  readonly ARROW_DOWN: "ArrowDown";
package/types/math.d.ts CHANGED
@@ -28,3 +28,5 @@ export declare const getBezierCurveLength: (element: NonDeleted<ExcalidrawLinear
28
28
  export declare const mapIntervalToBezierT: (element: NonDeleted<ExcalidrawLinearElement>, endPoint: readonly [number, number], interval: number) => number;
29
29
  export declare const arePointsEqual: (p1: readonly [number, number], p2: readonly [number, number]) => boolean;
30
30
  export declare const isRightAngle: (angle: number) => boolean;
31
+ export declare const rangesOverlap: ([a0, a1]: [number, number], [b0, b1]: [number, number]) => boolean;
32
+ export declare const rangeIntersection: (rangeA: [number, number], rangeB: [number, number]) => [number, number] | null;
@@ -0,0 +1,2 @@
1
+ import { InteractiveCanvasAppState } from "../types";
2
+ export declare const renderSnaps: (context: CanvasRenderingContext2D, appState: InteractiveCanvasAppState) => void;
@@ -8,6 +8,7 @@ import { AppState, InteractiveCanvasAppState } from "../types";
8
8
  */
9
9
  export declare const excludeElementsInFramesFromSelection: <T extends ExcalidrawElement>(selectedElements: readonly T[]) => T[];
10
10
  export declare const getElementsWithinSelection: (elements: readonly NonDeletedExcalidrawElement[], selection: NonDeletedExcalidrawElement, excludeElementsInFrames?: boolean) => NonDeletedExcalidrawElement[];
11
+ export declare const getVisibleAndNonSelectedElements: (elements: readonly NonDeletedExcalidrawElement[], selectedElements: readonly NonDeletedExcalidrawElement[], appState: AppState) => NonDeletedExcalidrawElement[];
11
12
  export declare const isSomeElementSelected: {
12
13
  (elements: readonly NonDeletedExcalidrawElement[], appState: Pick<AppState, "selectedElementIds">): boolean;
13
14
  clearCache(): void;