@myoc/math 0.19.521 → 0.19.523

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 (152) hide show
  1. package/dist/dev/index.js +261 -92
  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 +14 -0
  5. package/dist/types/common/src/constants.d.ts +3 -0
  6. package/dist/types/common/src/keys.d.ts +2 -0
  7. package/dist/types/common/src/points.d.ts +1 -1
  8. package/dist/types/common/src/utils.d.ts +1 -1
  9. package/dist/types/element/src/Scene.d.ts +1 -1
  10. package/dist/types/element/src/align.d.ts +2 -2
  11. package/dist/types/element/src/arrowEndpointText.d.ts +49 -0
  12. package/dist/types/element/src/arrows/focus.d.ts +5 -2
  13. package/dist/types/element/src/binding.d.ts +17 -8
  14. package/dist/types/element/src/bounds.d.ts +5 -9
  15. package/dist/types/element/src/bucketFill.d.ts +110 -0
  16. package/dist/types/element/src/collision.d.ts +1 -1
  17. package/dist/types/element/src/comparisons.d.ts +4 -4
  18. package/dist/types/element/src/convertToShape.d.ts +23 -0
  19. package/dist/types/element/src/distribute.d.ts +2 -2
  20. package/dist/types/element/src/dragElements.d.ts +27 -0
  21. package/dist/types/element/src/duplicate.d.ts +3 -3
  22. package/dist/types/element/src/embeddable.d.ts +2 -2
  23. package/dist/types/element/src/flowchart.d.ts +7 -7
  24. package/dist/types/element/src/fractionalIndex.d.ts +2 -2
  25. package/dist/types/element/src/frame.d.ts +4 -4
  26. package/dist/types/element/src/groups.d.ts +9 -9
  27. package/dist/types/element/src/index.d.ts +4 -1
  28. package/dist/types/element/src/linearElementEditor.d.ts +17 -10
  29. package/dist/types/element/src/newElement.d.ts +13 -0
  30. package/dist/types/element/src/renderElement.d.ts +0 -3
  31. package/dist/types/element/src/resizeElements.d.ts +2 -2
  32. package/dist/types/element/src/selection.d.ts +5 -5
  33. package/dist/types/element/src/shape.d.ts +12 -0
  34. package/dist/types/element/src/sortElements.d.ts +10 -0
  35. package/dist/types/element/src/textElement.d.ts +12 -9
  36. package/dist/types/element/src/transform.d.ts +2 -2
  37. package/dist/types/element/src/typeChecks.d.ts +25 -25
  38. package/dist/types/element/src/types.d.ts +2 -1
  39. package/dist/types/element/src/zindex.d.ts +2 -2
  40. package/dist/types/excalidraw/actions/actionAlign.d.ts +6 -6
  41. package/dist/types/excalidraw/actions/actionBoundText.d.ts +24 -8
  42. package/dist/types/excalidraw/actions/actionCanvas.d.ts +134 -967
  43. package/dist/types/excalidraw/actions/actionClipboard.d.ts +24 -8
  44. package/dist/types/excalidraw/actions/actionCropEditor.d.ts +12 -4
  45. package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +38 -13
  46. package/dist/types/excalidraw/actions/actionDeselect.d.ts +9 -4
  47. package/dist/types/excalidraw/actions/actionDistribute.d.ts +2 -3
  48. package/dist/types/excalidraw/actions/actionElementLink.d.ts +12 -4
  49. package/dist/types/excalidraw/actions/actionElementLock.d.ts +25 -9
  50. package/dist/types/excalidraw/actions/actionExport.d.ts +26 -10
  51. package/dist/types/excalidraw/actions/actionFrame.d.ts +47 -205
  52. package/dist/types/excalidraw/actions/actionGroup.d.ts +39 -23
  53. package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +15 -6
  54. package/dist/types/excalidraw/actions/actionLink.d.ts +13 -5
  55. package/dist/types/excalidraw/actions/actionMenu.d.ts +12 -4
  56. package/dist/types/excalidraw/actions/actionProperties.d.ts +43 -24
  57. package/dist/types/excalidraw/actions/actionSelectAll.d.ts +17 -9
  58. package/dist/types/excalidraw/actions/actionStyles.d.ts +12 -4
  59. package/dist/types/excalidraw/actions/actionTextAutoResize.d.ts +1 -1
  60. package/dist/types/excalidraw/actions/actionToggleArrowBinding.d.ts +14 -6
  61. package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +16 -9
  62. package/dist/types/excalidraw/actions/actionToggleMidpointSnapping.d.ts +13 -5
  63. package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +13 -5
  64. package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +16 -9
  65. package/dist/types/excalidraw/actions/actionToggleStats.d.ts +13 -5
  66. package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +14 -6
  67. package/dist/types/excalidraw/actions/index.d.ts +2 -3
  68. package/dist/types/excalidraw/actions/manager.d.ts +1 -0
  69. package/dist/types/excalidraw/actions/shortcuts.d.ts +1 -1
  70. package/dist/types/excalidraw/actions/types.d.ts +8 -4
  71. package/dist/types/excalidraw/appState.d.ts +10 -5
  72. package/dist/types/excalidraw/components/Actions.d.ts +18 -14
  73. package/dist/types/excalidraw/components/App.arrowText.d.ts +72 -0
  74. package/dist/types/excalidraw/components/App.bucketFill.d.ts +48 -0
  75. package/dist/types/excalidraw/components/App.cursor.d.ts +30 -0
  76. package/dist/types/excalidraw/components/App.d.ts +389 -61
  77. package/dist/types/excalidraw/components/App.drawshape.d.ts +55 -0
  78. package/dist/types/excalidraw/components/App.flowchart.d.ts +21 -0
  79. package/dist/types/excalidraw/components/App.viewport.d.ts +73 -0
  80. package/dist/types/excalidraw/components/ColorPicker/ColorPicker.d.ts +9 -3
  81. package/dist/types/excalidraw/components/ColorPicker/CustomColorList.d.ts +3 -1
  82. package/dist/types/excalidraw/components/ColorPicker/Picker.d.ts +3 -1
  83. package/dist/types/excalidraw/components/ColorPicker/PickerColorList.d.ts +9 -2
  84. package/dist/types/excalidraw/components/ColorPicker/ShadeList.d.ts +4 -2
  85. package/dist/types/excalidraw/components/ColorPicker/TopPicks.d.ts +8 -1
  86. package/dist/types/excalidraw/components/ColorPicker/keyboardNavHandlers.d.ts +2 -1
  87. package/dist/types/excalidraw/components/ColorPicker/topPicksDnD.d.ts +31 -0
  88. package/dist/types/excalidraw/components/ConvertElementTypePopup.d.ts +1 -1
  89. package/dist/types/excalidraw/components/CursorHint.d.ts +46 -0
  90. package/dist/types/excalidraw/components/{ToolButton.d.ts → IconButton.d.ts} +16 -19
  91. package/dist/types/excalidraw/components/Island.d.ts +7 -0
  92. package/dist/types/excalidraw/components/LaserPointerButton.d.ts +2 -4
  93. package/dist/types/excalidraw/components/LayerUI.d.ts +5 -2
  94. package/dist/types/excalidraw/components/LockButton.d.ts +9 -0
  95. package/dist/types/excalidraw/components/MobileMenu.d.ts +4 -4
  96. package/dist/types/excalidraw/components/{MobileToolBar.d.ts → MobileToolbar.d.ts} +3 -4
  97. package/dist/types/excalidraw/components/PenModeButton.d.ts +2 -5
  98. package/dist/types/excalidraw/components/Popover.d.ts +1 -3
  99. package/dist/types/excalidraw/components/{ButtonIcon.d.ts → RadioButton.d.ts} +2 -5
  100. package/dist/types/excalidraw/components/Stats/Angle.d.ts +2 -2
  101. package/dist/types/excalidraw/components/Stats/Dimension.d.ts +2 -2
  102. package/dist/types/excalidraw/components/Stats/DragInput.d.ts +2 -2
  103. package/dist/types/excalidraw/components/Stats/MultiAngle.d.ts +2 -2
  104. package/dist/types/excalidraw/components/Stats/MultiDimension.d.ts +2 -2
  105. package/dist/types/excalidraw/components/Stats/MultiPosition.d.ts +2 -2
  106. package/dist/types/excalidraw/components/Stats/Position.d.ts +3 -3
  107. package/dist/types/excalidraw/components/Stats/utils.d.ts +1 -1
  108. package/dist/types/excalidraw/components/ToolPopover.d.ts +3 -6
  109. package/dist/types/excalidraw/components/Toolbar.d.ts +13 -0
  110. package/dist/types/excalidraw/components/Tools.d.ts +151 -0
  111. package/dist/types/excalidraw/components/UserList.d.ts +3 -2
  112. package/dist/types/excalidraw/components/ViewportStatusFrame/ViewportStatusFrame.d.ts +11 -0
  113. package/dist/types/excalidraw/components/canvases/InteractiveCanvas.d.ts +2 -0
  114. package/dist/types/excalidraw/components/footer/Footer.d.ts +3 -1
  115. package/dist/types/excalidraw/components/hyperlink/helpers.d.ts +2 -2
  116. package/dist/types/excalidraw/components/icons.d.ts +4 -1
  117. package/dist/types/excalidraw/components/main-menu/DefaultItems.d.ts +0 -2
  118. package/dist/types/excalidraw/components/positionElementBesideCursor.d.ts +26 -0
  119. package/dist/types/excalidraw/components/shapeActionPredicates.d.ts +39 -0
  120. package/dist/types/excalidraw/context/tunnels.d.ts +0 -1
  121. package/dist/types/excalidraw/data/blob.d.ts +14 -6
  122. package/dist/types/excalidraw/data/index.d.ts +4 -4
  123. package/dist/types/excalidraw/data/json.d.ts +20 -12
  124. package/dist/types/excalidraw/drawShapeTrail.d.ts +16 -0
  125. package/dist/types/excalidraw/hooks/useAppStateValue.d.ts +29 -0
  126. package/dist/types/excalidraw/lasso/utils.d.ts +2 -0
  127. package/dist/types/excalidraw/renderer/interactiveScene.d.ts +10 -3
  128. package/dist/types/excalidraw/scene/Renderer.d.ts +11 -11
  129. package/dist/types/excalidraw/scene/export.d.ts +3 -3
  130. package/dist/types/excalidraw/scene/index.d.ts +1 -1
  131. package/dist/types/excalidraw/scene/types.d.ts +4 -3
  132. package/dist/types/excalidraw/snapping.d.ts +7 -7
  133. package/dist/types/excalidraw/types.d.ts +432 -28
  134. package/dist/types/excalidraw/viewport.d.ts +283 -0
  135. package/dist/types/excalidraw/wysiwyg/textWysiwyg.d.ts +2 -3
  136. package/dist/types/laser-pointer/src/state.d.ts +1 -0
  137. package/dist/types/math/src/index.d.ts +1 -0
  138. package/dist/types/math/src/pca.d.ts +79 -0
  139. package/dist/types/math/src/polygon.d.ts +25 -1
  140. package/dist/types/utils/src/export.d.ts +3 -3
  141. package/package.json +2 -2
  142. package/dist/types/excalidraw/actions/actionEmbeddable.d.ts +0 -180
  143. package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +0 -183
  144. package/dist/types/excalidraw/components/DefaultSidebar.d.ts +0 -27
  145. package/dist/types/excalidraw/components/ElementCanvasButtons.d.ts +0 -7
  146. package/dist/types/excalidraw/components/FollowMode/FollowMode.d.ts +0 -10
  147. package/dist/types/excalidraw/components/HandButton.d.ts +0 -10
  148. package/dist/types/excalidraw/components/MagicButton.d.ts +0 -10
  149. package/dist/types/excalidraw/cursor.d.ts +0 -5
  150. package/dist/types/excalidraw/scene/scroll.d.ts +0 -18
  151. package/dist/types/excalidraw/scene/zoom.d.ts +0 -12
  152. package/dist/types/excalidraw/scroll.d.ts +0 -46
@@ -1,7 +1,7 @@
1
1
  import type { IMAGE_MIME_TYPES, UserIdleState, throttleRAF, MIME_TYPES, ColorTuple, EditorInterface, StrokeWidthKey } from "@excalidraw/common";
2
2
  import type { LinearElementEditor } from "@excalidraw/element";
3
3
  import type { MaybeTransformHandleType } from "@excalidraw/element";
4
- import type { PointerType, ExcalidrawLinearElement, NonDeletedExcalidrawElement, NonDeleted, TextAlign, ExcalidrawElement, GroupId, ExcalidrawBindableElement, Arrowhead, FontFamilyValues, FileId, Theme, StrokeRoundness, ExcalidrawEmbeddableElement, ExcalidrawMagicFrameElement, ExcalidrawFrameLikeElement, ExcalidrawElementType, ExcalidrawIframeLikeElement, OrderedExcalidrawElement, ExcalidrawNonSelectionElement, ArrangeAlgorithms, BindMode, ExcalidrawTextElement, StrokeVariability } from "@excalidraw/element/types";
4
+ import type { PointerType, ExcalidrawLinearElement, NonDeletedExcalidrawElement, NonDeleted, TextAlign, ExcalidrawElement, GroupId, ExcalidrawBindableElement, ExcalidrawArrowElement, Arrowhead, FontFamilyValues, FileId, Theme, StrokeRoundness, ExcalidrawEmbeddableElement, ExcalidrawMagicFrameElement, ExcalidrawFrameLikeElement, ExcalidrawElementType, ExcalidrawIframeLikeElement, OrderedExcalidrawElement, ExcalidrawNonSelectionElement, ArrangeAlgorithms, BindMode, ExcalidrawTextElement, StrokeVariability } from "@excalidraw/element/types";
5
5
  import type { Merge, MaybePromise, ValueOf, MakeBrand } from "@excalidraw/common/utility-types";
6
6
  import type { CaptureUpdateActionType, DurableIncrement, EphemeralIncrement } from "@excalidraw/element";
7
7
  import type { GlobalPoint } from "@excalidraw/math";
@@ -12,6 +12,7 @@ import type App from "./components/App";
12
12
  import type { ContextMenuCustomItem, ContextMenuItems } from "./components/ContextMenu";
13
13
  import type { SnapLine } from "./snapping";
14
14
  import type { ImportedDataState } from "./data/types";
15
+ import type { SetViewportOptions } from "./viewport";
15
16
  import type { Language } from "./i18n";
16
17
  import type { isOverScrollBars } from "./scene/scrollbars";
17
18
  import type React from "react";
@@ -87,7 +88,42 @@ export type BinaryFileData = {
87
88
  export type BinaryFileMetadata = Omit<BinaryFileData, "dataURL">;
88
89
  export type BinaryFiles = Record<ExcalidrawElement["id"], BinaryFileData>;
89
90
  export type ImageContextMenuItem = ContextMenuCustomItem;
90
- export type ToolType = "selection" | "lasso" | "rectangle" | "diamond" | "ellipse" | "arrow" | "line" | "freedraw" | "text" | "image" | "eraser" | "hand" | "frame" | "magicframe" | "embeddable" | "laser";
91
+ export type ImageStatusStyle = {
92
+ backgroundColor?: string;
93
+ color?: string;
94
+ trackColor?: string;
95
+ };
96
+ export type ImageDownloadErrorStatus = ImageStatusStyle & {
97
+ /** Optional error message rendered below the error icon. */
98
+ text?: string;
99
+ /** Makes the rendered download error icon actionable when supplied. */
100
+ onClick?: (fileId: FileId) => void;
101
+ };
102
+ export type ImageUploadProgressStatus = ImageStatusStyle & {
103
+ /**
104
+ * `pending` renders the cloud indicator before upload starts.
105
+ * `uploading` renders the progress ring around the cloud.
106
+ * `error` renders the cloud warning indicator.
107
+ */
108
+ state?: "pending" | "uploading" | "error";
109
+ progress?: number;
110
+ /** Optional upload error message for host-owned UI/toasts. */
111
+ text?: string;
112
+ /** Makes the rendered upload progress indicator actionable when supplied. */
113
+ onClick?: (fileId: FileId) => void;
114
+ };
115
+ export type ImageStatus = {
116
+ downloadError?: ImageDownloadErrorStatus | null;
117
+ uploadProgress?: ImageUploadProgressStatus | null;
118
+ };
119
+ export type RenderCustomizations = {
120
+ /**
121
+ * Host-controlled color for transient canvas traces whose visibility depends
122
+ * on the embedding app background, such as eraser and draw-to-shape trails.
123
+ */
124
+ traceColor?: string;
125
+ };
126
+ export type ToolType = "selection" | "lasso" | "rectangle" | "diamond" | "ellipse" | "arrow" | "line" | "freedraw" | "text" | "image" | "eraser" | "hand" | "frame" | "magicframe" | "embeddable" | "laser" | "autoshape" | "bucketfill";
91
127
  export type ElementOrToolType = ExcalidrawElementType | ToolType | "custom";
92
128
  export type ActiveTool = {
93
129
  type: ToolType;
@@ -141,7 +177,9 @@ export type InteractiveCanvasAppState = Readonly<_CommonCanvasAppState & {
141
177
  newElement: AppState["newElement"];
142
178
  isBindingEnabled: AppState["isBindingEnabled"];
143
179
  isMidpointSnappingEnabled: AppState["isMidpointSnappingEnabled"];
180
+ gridModeEnabled: AppState["gridModeEnabled"];
144
181
  suggestedBinding: AppState["suggestedBinding"];
182
+ hoveredArrowTextAnchor: AppState["hoveredArrowTextAnchor"];
145
183
  isRotating: AppState["isRotating"];
146
184
  elementsToHighlight: AppState["elementsToHighlight"];
147
185
  collaborators: AppState["collaborators"];
@@ -197,6 +235,41 @@ export type EditorPreferences = {
197
235
  normalise?: NormalisePreferences;
198
236
  };
199
237
  export type BoxSelectionMode = "contain" | "overlap";
238
+ /**
239
+ * A box, in scene coordinates, that pan & zoom are constrained to.
240
+ *
241
+ * This is a private type. For public API, only use specific properties,
242
+ * needed.
243
+ */
244
+ export type ScrollConstraints = {
245
+ x: number;
246
+ y: number;
247
+ width: number;
248
+ height: number;
249
+ /** when set, panning is constrained so the viewport stays within the box */
250
+ lockScroll: boolean;
251
+ /** when set, the viewport cannot zoom out below `zoom` */
252
+ lockZoom: boolean;
253
+ /**
254
+ * The zoom resolved after the `setViewport` navigation settled.
255
+ */
256
+ zoom: number;
257
+ /**
258
+ * Pixel amount the viewport may overscroll past its resting clamp before
259
+ * snapping back (rubberband). Screen pixels, zoom-independent. Resolved
260
+ * from `lock.overscroll` at the time the lock was installed (`true` →
261
+ * default give, `false` → 0).
262
+ */
263
+ overscroll: number;
264
+ /**
265
+ * Extra scrollable margin around the box (CSS-style), letting the viewport
266
+ * scroll past each box edge to reveal that much empty space. Values are
267
+ * viewport pixels and zoom-independent (a fixed on-screen distance).
268
+ * Resolved from the `offsets` passed to `setViewport` (see
269
+ * {@link ViewportOffsets}) at the time the lock was installed.
270
+ */
271
+ offsets?: Offsets;
272
+ };
200
273
  export interface AppState {
201
274
  contextMenu: {
202
275
  items: ContextMenuItems;
@@ -261,6 +334,15 @@ export interface AppState {
261
334
  element: NonDeleted<ExcalidrawBindableElement>;
262
335
  midPoint?: GlobalPoint;
263
336
  } | null;
337
+ /**
338
+ * Where on a hovered arrow the text tool would attach text if clicked —
339
+ * a free endpoint (binds the arrow to a new text element positioned against
340
+ * that endpoint) or the arrow's midpoint (adds a label bound to the arrow).
341
+ */
342
+ hoveredArrowTextAnchor: {
343
+ elementId: ExcalidrawArrowElement["id"];
344
+ anchor: "start" | "end" | "label";
345
+ } | null;
264
346
  frameToHighlight: NonDeleted<ExcalidrawFrameLikeElement> | null;
265
347
  frameRendering: {
266
348
  enabled: boolean;
@@ -268,8 +350,11 @@ export interface AppState {
268
350
  outline: boolean;
269
351
  clip: boolean;
270
352
  };
271
- editingFrame: string | null;
272
- elementsToHighlight: NonDeleted<ExcalidrawElement>[] | null;
353
+ /**
354
+ * frame-like element whose name is currently being edited
355
+ */
356
+ editingFrame: ExcalidrawFrameLikeElement["id"] | null;
357
+ elementsToHighlight: readonly NonDeletedExcalidrawElement[] | null;
273
358
  /**
274
359
  * set when a new text is created or when an existing text is being edited
275
360
  */
@@ -312,6 +397,7 @@ export interface AppState {
312
397
  viewBackgroundColor: string;
313
398
  scrollX: number;
314
399
  scrollY: number;
400
+ scrollConstraints: ScrollConstraints | null;
315
401
  cursorButton: "up" | "down";
316
402
  scrolledOutside: boolean;
317
403
  name: string | null;
@@ -395,10 +481,6 @@ export interface AppState {
395
481
  y: number;
396
482
  } | null;
397
483
  objectsSnapModeEnabled: boolean;
398
- /** the user's socket id & username who is being followed on the canvas */
399
- userToFollow: UserToFollow | null;
400
- /** the socket ids of the users following the current user */
401
- followedBy: Set<SocketId>;
402
484
  /** image cropping */
403
485
  isCropping: boolean;
404
486
  croppingElementId: ExcalidrawElement["id"] | null;
@@ -413,6 +495,17 @@ export interface AppState {
413
495
  [groupId: string]: true;
414
496
  };
415
497
  bindMode: BindMode;
498
+ /** user-customized color-picker top picks (pinned via drag & drop from the
499
+ * color picker popup). `null` means no customization (defaults, or
500
+ * host-supplied `topPicks`, are used). Kept per picker. */
501
+ colorTopPicks: {
502
+ elementStroke: readonly string[] | null;
503
+ elementBackground: readonly string[] | null;
504
+ /** the bucket-fill tool keeps a list separate from `elementBackground`
505
+ * even though both drive `currentItemBackgroundColor` (its defaults and
506
+ * use case differ — no transparent) */
507
+ bucketFill: readonly string[] | null;
508
+ };
416
509
  }
417
510
  export type SearchMatch = {
418
511
  id: string;
@@ -425,7 +518,7 @@ export type SearchMatch = {
425
518
  showOnCanvas: boolean;
426
519
  }[];
427
520
  };
428
- export type UIAppState = Omit<AppState, "cursorButton" | "scrollX" | "scrollY">;
521
+ export type UIAppState = Omit<AppState, "cursorButton" | "scrollX" | "scrollY" | "zoom" | "shouldCacheIgnoreZoom" | "snapLines" | "originSnapOffset" | "suggestedBinding" | "hoveredArrowTextAnchor" | "frameToHighlight" | "elementsToHighlight">;
429
522
  export type NormalizedZoomValue = number & {
430
523
  _brand: "normalizedZoom";
431
524
  };
@@ -450,10 +543,30 @@ export declare class GestureEvent extends UIEvent {
450
543
  readonly scale: number;
451
544
  }
452
545
  export type ExcalidrawInitialDataState = ImportedDataState;
546
+ export type ExcalidrawInitialState = {
547
+ viewport?: Omit<SetViewportOptions, "animation">;
548
+ };
453
549
  export type OnUserFollowedPayload = {
454
550
  userToFollow: UserToFollow;
455
551
  action: "FOLLOW" | "UNFOLLOW";
456
552
  };
553
+ export type ViewportStatusFrame = {
554
+ /** the badge (bottom-center pill) */
555
+ label?: {
556
+ label: React.ReactNode;
557
+ icon?: React.ReactNode;
558
+ /** badge background; defaults to var(--color-primary-hover) */
559
+ background?: string;
560
+ /** badge text color; defaults to var(--color-primary-light) */
561
+ color?: string;
562
+ /** makes the badge label interactive */
563
+ onClick?: () => void;
564
+ /** renders a close button when set */
565
+ onClose?: () => void;
566
+ };
567
+ /** viewport-edge border: CSS color, or `false` for none */
568
+ border: false | string;
569
+ };
457
570
  export type OnExportProgress = {
458
571
  type: "progress";
459
572
  message?: React.ReactNode;
@@ -466,7 +579,113 @@ export type CompressImageFileOpts = {
466
579
  maxWidthOrHeight: number;
467
580
  };
468
581
  export type CompressImageFile = (file: File, opts: CompressImageFileOpts) => Promise<File>;
582
+ export type InteractionConfig = {
583
+ /**
584
+ * Interactions that stay enabled while the editor is otherwise
585
+ * non-interactive. Opt-in: anything omitted or `false` is disabled.
586
+ */
587
+ enabled?: {
588
+ /**
589
+ * Element links render their link icon and stay clickable — clicking
590
+ * anywhere on a linked element opens the link, same as in view mode.
591
+ * When disabled, link icons are not rendered at all.
592
+ *
593
+ * @default false
594
+ */
595
+ links?: boolean;
596
+ /**
597
+ * Embeddable & iframe elements stay interactive — hovering & clicking
598
+ * activates them so their content can be used, same as in view mode.
599
+ *
600
+ * @default false
601
+ */
602
+ embeds?: boolean;
603
+ /**
604
+ * Umbrella for all interactive content on canvas — shorthand for
605
+ * enabling `links` & `embeds` (and future interactive content kinds)
606
+ * together. Additive: `interactiveContent: true` enables them
607
+ * regardless of their individual values.
608
+ *
609
+ * @default false
610
+ */
611
+ interactiveContent?: boolean;
612
+ /**
613
+ * Canvas navigation — panning (pointer drag, wheel, PageUp/PageDown)
614
+ * and zooming (ctrl/cmd + wheel, pinch, and the canvas zoom &
615
+ * zoom-to-fit shortcuts: ctrl/cmd +/-/0, shift+1/2/3), same as in view
616
+ * mode. Respects `appState.scrollConstraints` if set, so it composes
617
+ * with viewport locking. The rest of the keyboard stays disabled. Note
618
+ * the editor consumes wheel & touch input again when enabled, so the
619
+ * page no longer scrolls over the editor.
620
+ *
621
+ * @default false
622
+ */
623
+ navigation?: boolean;
624
+ /**
625
+ * Whether the browser's own zoom remains available over the editor —
626
+ * ctrl/cmd + wheel, pinch, and (while the editor has focus)
627
+ * ctrl/cmd +/-/0 shortcuts. Prevented by default, mirroring the
628
+ * interactive editor. Regular page scrolling stays available either way.
629
+ * With `navigation` enabled, the zoom input (wheel, pinch, keyboard
630
+ * shortcuts) zooms the canvas instead either way, making this moot.
631
+ *
632
+ * @default false
633
+ */
634
+ browserZoom?: boolean;
635
+ /**
636
+ * Tools that stay user-driven while the editor is otherwise
637
+ * non-interactive: pointer input keeps driving the listed tool when it's
638
+ * the active tool. Does not enable user-driven tool *switching* — the
639
+ * keyboard stays disabled and tool selection remains host-driven
640
+ * (`ExcalidrawAPI.setActiveTool`).
641
+ *
642
+ * Composes with `navigation`: the enabled tool wins the primary-pointer
643
+ * drag, while wheel input (and wheel-button drag) still pans/zooms.
644
+ */
645
+ tools?: {
646
+ /**
647
+ * The laser pointer stays usable — pointer strokes draw laser trails
648
+ * and pointer positions keep broadcasting via `onPointerUpdate`, so
649
+ * e.g. collaborators see a presenter's laser & cursor.
650
+ *
651
+ * @default false
652
+ */
653
+ laser?: boolean;
654
+ /**
655
+ * Custom tools (`activeTool.type === "custom"`) stay usable — the
656
+ * editor keeps dispatching `onPointerDown` / `onPointerUp` for them.
657
+ * Tool behavior is host-implemented; activate custom tools with
658
+ * `locked: true` or they revert to the selection tool (and go inert)
659
+ * after the first pointer interaction.
660
+ *
661
+ * @default false
662
+ */
663
+ custom?: boolean;
664
+ };
665
+ };
666
+ };
667
+ export type UIConfig = {
668
+ /**
669
+ * Default UI controls that stay enabled while the rest of Excalidraw's
670
+ * default UI is hidden. Opt-in: anything omitted or `false` is disabled.
671
+ */
672
+ enabled: {
673
+ /**
674
+ * The zoom-out, reset-zoom, and zoom-in controls.
675
+ *
676
+ * @default false
677
+ */
678
+ zoom?: boolean;
679
+ /**
680
+ * The button shown when the viewport is scrolled away from all content.
681
+ *
682
+ * @default false
683
+ */
684
+ scrollBackToContent?: boolean;
685
+ };
686
+ };
469
687
  export interface ExcalidrawProps {
688
+ className?: string;
470
689
  onChange?: (elements: readonly OrderedExcalidrawElement[], appState: AppState, files: BinaryFiles) => void;
471
690
  onThemeChange?: (theme: Theme | "system") => void;
472
691
  /**
@@ -474,6 +693,7 @@ export interface ExcalidrawProps {
474
693
  */
475
694
  onIncrement?: (event: DurableIncrement | EphemeralIncrement) => void;
476
695
  initialData?: (() => MaybePromise<ExcalidrawInitialDataState | null>) | MaybePromise<ExcalidrawInitialDataState | null>;
696
+ initialState?: ExcalidrawInitialState;
477
697
  /**
478
698
  * Invoked as soon as the Excalidraw API is available
479
699
  * NOTE editor is not yet mounted, and state is not yet initialized
@@ -520,10 +740,74 @@ export interface ExcalidrawProps {
520
740
  langCode?: Language["code"];
521
741
  viewModeEnabled?: boolean;
522
742
  viewModeOnly?: boolean;
523
- zenModeEnabled?: boolean;
743
+ /**
744
+ * Whether the editor accepts user input (pointer, keyboard, wheel, touch,
745
+ * clipboard, drag&drop). When `false`, the scene still renders and reacts
746
+ * to programmatic updates (imperative API), but the user cannot affect it
747
+ * in any way. Implies view mode.
748
+ *
749
+ * Pass a config object to keep specific interactions enabled while the
750
+ * editor is otherwise non-interactive (see `InteractionConfig`):
751
+ *
752
+ * ```tsx
753
+ * <Excalidraw interaction={{ enabled: { links: true } }} />
754
+ * ```
755
+ *
756
+ * @default true
757
+ */
758
+ interaction?: boolean | InteractionConfig;
759
+ /**
760
+ * Whether Excalidraw's default UI is rendered — toolbar, default menus,
761
+ * footer controls, sidebars, and canvas popups. Host UI passed through
762
+ * children (including exported components such as `MainMenu` and `Footer`)
763
+ * or render props continues to render, together with any supporting dialogs
764
+ * it opens.
765
+ *
766
+ * Canvas content (elements, text editing surface, frame names, embeds) still
767
+ * renders, and the editor remains interactive unless `interaction` is set to
768
+ * `false`.
769
+ *
770
+ * Pass a config object to keep specific default controls rendered while the
771
+ * rest of the default UI is hidden (see `UIConfig`):
772
+ *
773
+ * ```tsx
774
+ * <Excalidraw ui={{ enabled: { zoom: true } }} />
775
+ * ```
776
+ *
777
+ * NOTE: this is WIP and what default UI is/is not rendered when ui=false
778
+ * may yet change.
779
+ *
780
+ * @default true
781
+ */
782
+ ui?: boolean | UIConfig;
783
+ /**
784
+ * Forces the active editor tool (controlled). While set, user- and
785
+ * API-driven tool switching is ignored — `setActiveTool` refuses with a
786
+ * console warning, non-forced toolbar buttons render disabled — and the
787
+ * editor snaps back if internal flows reset the tool. The forced tool
788
+ * behaves as if locked (see the tool lock / padlock): it doesn't revert to
789
+ * the selection tool after use, and elements drawn with it aren't
790
+ * auto-selected — without mutating `appState.activeTool.locked`, so the
791
+ * user's persisted padlock preference stays untouched. Unset to return
792
+ * tool control to the editor (the current tool stays active).
793
+ *
794
+ * The forced tool must be activatable to take effect: not disabled via
795
+ * `UIOptions.tools`, and — while the editor is non-interactive — allowed
796
+ * via `interaction.enabled.tools`. Otherwise the editor stays on (or, when
797
+ * non-interactive, resets to) the `selection` tool, and the forced tool is
798
+ * applied once it becomes activatable. `image` cannot be forced (its
799
+ * activation opens the file picker).
800
+ */
801
+ activeTool?: {
802
+ type: Exclude<ToolType, "image">;
803
+ } | {
804
+ type: "custom";
805
+ customType: string;
806
+ };
524
807
  gridModeEnabled?: boolean;
525
808
  objectsSnapModeEnabled?: boolean;
526
809
  theme?: Theme;
810
+ renderCustomizations?: RenderCustomizations;
527
811
  name?: string;
528
812
  renderCustomStats?: (elements: readonly NonDeletedExcalidrawElement[], appState: UIAppState) => JSX.Element;
529
813
  editorPreferences?: EditorPreferences;
@@ -536,7 +820,7 @@ export interface ExcalidrawProps {
536
820
  detectScroll?: boolean;
537
821
  handleKeyboardGlobally?: boolean;
538
822
  autoFocus?: boolean;
539
- compressImageFile: CompressImageFile;
823
+ compressImageFile?: CompressImageFile;
540
824
  generateIdForFile?: (file: File) => string | Promise<string>;
541
825
  generateLinkForSelection?: (id: string, type: "element" | "group") => string;
542
826
  onLinkOpen?: (element: NonDeletedExcalidrawElement, event: CustomEvent<{
@@ -557,6 +841,21 @@ export interface ExcalidrawProps {
557
841
  strokeColorTopPicks?: ColorTuple;
558
842
  backgroundColorTopPicks?: ColorTuple;
559
843
  renderScrollbars?: boolean;
844
+ viewportStatusFrame?: ViewportStatusFrame | null;
845
+ /**
846
+ * Rendered inside the UserList "who's here" dropdown (desktop) and inline
847
+ * in the mobile menu's collaborators section, below a divider. Accepts a
848
+ * render function — called with `isMobile` so hosts can render different
849
+ * UI for each surface — in addition to a plain node.
850
+ */
851
+ currentUserControls?: React.ReactNode | ((isMobile: boolean) => React.ReactNode);
852
+ /**
853
+ * The user being followed on the canvas, if any. Controlled by the host —
854
+ * the editor never sets it; it emits follow/unfollow intents via
855
+ * `onUserFollow` (prop or imperative API) and renders the followed
856
+ * user's avatar highlight from this value.
857
+ */
858
+ userToFollow?: UserToFollow | null;
560
859
  /**
561
860
  * Called before exporting to a file.
562
861
  *
@@ -632,11 +931,11 @@ export type AppProps = Merge<ExcalidrawProps, {
632
931
  };
633
932
  }>;
634
933
  imageOptions: Required<ImageOptions>;
635
- wheelZoomsOnDefault?: boolean;
636
934
  detectScroll: boolean;
637
935
  handleKeyboardGlobally: boolean;
638
936
  isCollaborating: boolean;
639
937
  children?: React.ReactNode;
938
+ wheelZoomsOnDefault?: boolean;
640
939
  }>;
641
940
  /** A subset of App class properties that we need to use elsewhere
642
941
  * in the app, eg Manager. Factored out into a separate type to keep DRY. */
@@ -658,6 +957,8 @@ export type AppClassProperties = {
658
957
  }>;
659
958
  imageLoadingProgress: App["imageLoadingProgress"];
660
959
  imageLoadingProgressEmitter: App["imageLoadingProgressEmitter"];
960
+ imageStatus: App["imageStatus"];
961
+ imageStatusEmitter: App["imageStatusEmitter"];
661
962
  imagePlaceholderUpdateEmitter: App["imagePlaceholderUpdateEmitter"];
662
963
  files: BinaryFiles;
663
964
  editorInterface: App["editorInterface"];
@@ -668,6 +969,7 @@ export type AppClassProperties = {
668
969
  id: App["id"];
669
970
  onInsertElements: App["onInsertElements"];
670
971
  onExportImage: App["onExportImage"];
972
+ viewport: App["viewport"];
671
973
  lastViewportPosition: App["lastViewportPosition"];
672
974
  scrollToViewport: App["scrollToViewport"];
673
975
  scrollToContent: App["scrollToContent"];
@@ -675,17 +977,18 @@ export type AppClassProperties = {
675
977
  addElementsFromPaste: App["addElementsFromPaste"];
676
978
  togglePenMode: App["togglePenMode"];
677
979
  toggleLock: App["toggleLock"];
980
+ openEyeDropper: App["openEyeDropper"];
678
981
  setActiveTool: App["setActiveTool"];
679
982
  setOpenDialog: App["setOpenDialog"];
680
983
  insertEmbeddableElement: App["insertEmbeddableElement"];
681
- onMagicframeToolSelect: App["onMagicframeToolSelect"];
682
984
  getName: App["getName"];
683
985
  dismissLinearEditor: App["dismissLinearEditor"];
684
- flowChartCreator: App["flowChartCreator"];
986
+ flowchart: App["flowchart"];
987
+ drawShape: App["drawShape"];
988
+ cursor: App["cursor"];
989
+ bucketFill: App["bucketFill"];
990
+ isToolLocked: App["isToolLocked"];
685
991
  getEffectiveGridSize: App["getEffectiveGridSize"];
686
- setPlugins: App["setPlugins"];
687
- plugins: App["plugins"];
688
- getEditorUIOffsets: App["getEditorUIOffsets"];
689
992
  visibleElements: App["visibleElements"];
690
993
  excalidrawContainerValue: App["excalidrawContainerValue"];
691
994
  onPointerUpEmitter: App["onPointerUpEmitter"];
@@ -694,8 +997,13 @@ export type AppClassProperties = {
694
997
  onEvent: App["onEvent"];
695
998
  onStateChange: App["onStateChange"];
696
999
  lastPointerMoveCoords: App["lastPointerMoveCoords"];
1000
+ lastPointerMoveEvent: App["lastPointerMoveEvent"];
697
1001
  bindModeHandler: App["bindModeHandler"];
1002
+ emitUserFollowIntent: App["emitUserFollowIntent"];
1003
+ requestUnfollow: App["requestUnfollow"];
698
1004
  setAppState: App["setAppState"];
1005
+ isInteractionEnabled: App["isInteractionEnabled"];
1006
+ isNavigationEnabled: App["isNavigationEnabled"];
699
1007
  };
700
1008
  export type PointerDownState = Readonly<{
701
1009
  origin: Readonly<{
@@ -783,20 +1091,24 @@ export interface ExcalidrawImperativeAPI {
783
1091
  getName: InstanceType<typeof App>["getName"];
784
1092
  scrollToViewport: InstanceType<typeof App>["scrollToViewport"];
785
1093
  scrollToContent: InstanceType<typeof App>["scrollToContent"];
1094
+ setViewport: InstanceType<typeof App>["viewport"]["setViewport"];
1095
+ getViewportOffsets: InstanceType<typeof App>["viewport"]["getOffsets"];
786
1096
  registerAction: (action: Action) => void;
787
1097
  refresh: InstanceType<typeof App>["refresh"];
788
1098
  setToast: InstanceType<typeof App>["setToast"];
789
1099
  addFiles: (data: BinaryFileData[]) => void;
790
1100
  addImagePlaceholder: (fileId: FileId, file: File) => Promise<void>;
791
- setImageLoadingProgress: (fileId: FileId, progress: number | null) => void;
1101
+ setDownloadProgress: (fileId: FileId, progress: number | null) => void;
1102
+ setDownloadError: (fileId: FileId, error: boolean | ImageDownloadErrorStatus | null) => void;
1103
+ setUploadProgress: (fileId: FileId, progress: number | "pending" | "error" | null, status?: Omit<ImageUploadProgressStatus, "progress"> | null) => void;
792
1104
  addImageElementsToScene: (imageFiles: {
793
1105
  file: File;
794
1106
  customData: Record<string, any>;
795
1107
  }[], sceneX: number, sceneY: number) => Promise<void>;
796
1108
  id: string;
797
1109
  setActiveTool: InstanceType<typeof App>["setActiveTool"];
798
- setCursor: InstanceType<typeof App>["setCursor"];
799
- resetCursor: InstanceType<typeof App>["resetCursor"];
1110
+ setCursor: InstanceType<typeof App>["cursor"]["set"];
1111
+ resetCursor: InstanceType<typeof App>["cursor"]["reset"];
800
1112
  toggleSidebar: InstanceType<typeof App>["toggleSidebar"];
801
1113
  getEditorInterface: () => EditorInterface;
802
1114
  /**
@@ -819,7 +1131,6 @@ export type FrameNameBounds = {
819
1131
  y: number;
820
1132
  width: number;
821
1133
  height: number;
822
- angle: number;
823
1134
  };
824
1135
  export type FrameNameBoundsCache = {
825
1136
  get: (frameElement: ExcalidrawFrameLikeElement | ExcalidrawMagicFrameElement) => FrameNameBounds | null;
@@ -838,18 +1149,111 @@ export type Primitive = number | string | boolean | bigint | symbol | null | und
838
1149
  export type JSONValue = string | number | boolean | null | object;
839
1150
  export type EmbedsValidationStatus = Map<ExcalidrawIframeLikeElement["id"], boolean>;
840
1151
  export type ElementsPendingErasure = Set<ExcalidrawElement["id"]>;
841
- export type PendingExcalidrawElements = ExcalidrawElement[];
1152
+ export type PendingExcalidrawElements = NonDeletedExcalidrawElement[];
842
1153
  /** Runtime gridSize value. Null indicates disabled grid. */
843
1154
  export type NullableGridSize = (AppState["gridSize"] & MakeBrand<"NullableGridSize">) | null;
844
- export type GenerateDiagramToCode = (props: {
845
- frame: ExcalidrawMagicFrameElement;
846
- children: readonly ExcalidrawElement[];
847
- }) => MaybePromise<{
848
- html: string;
849
- }>;
850
1155
  export type Offsets = Partial<{
851
1156
  top: number;
852
1157
  right: number;
853
1158
  bottom: number;
854
1159
  left: number;
855
1160
  }>;
1161
+ /**
1162
+ * Value of the `data-viewport-ui` attribute, marking a DOM node as a UI
1163
+ * surface that occludes the canvas. Such nodes are measured by
1164
+ * `getViewportOffsets` to compute the default per-side viewport offsets:
1165
+ *
1166
+ * - `top` / `bottom` — offsets that side by the node's bottom/top edge
1167
+ * - `side` — a panel hugging the left or right edge. Which side is not
1168
+ * declared but resolved geometrically: if the node's horizontal center
1169
+ * lies in the left half of the viewport it counts against the left
1170
+ * offset (by its right edge), otherwise against the right offset (by
1171
+ * `viewportWidth - left edge`). Measuring the rendered position instead
1172
+ * of declaring a side means RTL layouts and host-configurable docking
1173
+ * (e.g. sidebar side) are handled for free — but it assumes the surface
1174
+ * actually hugs one edge; don't mark a centered/near-full-width node as
1175
+ * `side` (its midpoint would classify it to one side and the offset
1176
+ * would swallow most of the viewport).
1177
+ *
1178
+ * The attribute should only be present while the surface is actually
1179
+ * rendered — omit it (don't just hide the node) when the surface shouldn't
1180
+ * push the viewport around.
1181
+ */
1182
+ export type ViewportUIDock = "top" | "bottom" | "side";
1183
+ /**
1184
+ * Options for `getViewportOffsets` (and the `ui` key of
1185
+ * {@link ViewportOffsets}), controlling how offsets are derived from the
1186
+ * currently rendered editor UI.
1187
+ *
1188
+ * NOTE unlike the physical sides of {@link Offsets}, the horizontal values
1189
+ * here are logical, i.e. flipped in RTL layouts (`left` refers to the
1190
+ * reading-direction start side).
1191
+ */
1192
+ export type ViewportOffsetsOptions = {
1193
+ /** padding added to each measured side (default 24) */
1194
+ padding?: number;
1195
+ paddingTop?: number;
1196
+ paddingRight?: number;
1197
+ paddingBottom?: number;
1198
+ paddingLeft?: number;
1199
+ /** final value for the given side, replacing the measured UI size
1200
+ * (padding is not added on top) */
1201
+ top?: number;
1202
+ bottom?: number;
1203
+ left?: number;
1204
+ right?: number;
1205
+ /**
1206
+ * Reserve space for the given conditionally-rendered surfaces even while
1207
+ * they're hidden, so the resulting offsets don't shift when they
1208
+ * (dis)appear. Uses the surface's last-measured footprint, falling back
1209
+ * to an approximate default if it hasn't been rendered yet. Ignored on
1210
+ * phones (where these surfaces never occlude the canvas).
1211
+ */
1212
+ reserve?: {
1213
+ /** styles panel (rendered when a tool or selection is active) */
1214
+ stylesPanel?: boolean;
1215
+ /** sidebar (e.g. library) */
1216
+ sidebar?: boolean;
1217
+ };
1218
+ };
1219
+ /**
1220
+ * Viewport offsets accepted by the `setViewport`-family APIs (`setViewport`,
1221
+ * `props.initialState.viewport`), insetting the usable viewport area per
1222
+ * side so the target isn't fitted/centered underneath overlaid UI.
1223
+ *
1224
+ * Two (combinable) ways to specify:
1225
+ *
1226
+ * - **Static sides** (`top`/`right`/`bottom`/`left`) — absolute pixel
1227
+ * values, used as-is: physical (not flipped in RTL), zoom-independent,
1228
+ * no padding added. Sides not specified default to `0` (unless `ui` is
1229
+ * set, see below).
1230
+ *
1231
+ * - **`ui`** — derive the offsets from the editor UI (toolbar, styles
1232
+ * panel, sidebar...) as rendered at the time the viewport is set,
1233
+ * equivalent to calling `getViewportOffsets()`. Pass `true` for the
1234
+ * defaults, or options ({@link ViewportOffsetsOptions}) to customize
1235
+ * padding or reserve space for currently-hidden surfaces.
1236
+ *
1237
+ * When both are given, a static side always wins for that side — it
1238
+ * replaces whatever `ui` would yield (including `ui`'s own side overrides,
1239
+ * which — unlike the physical static sides — are RTL-relative). The
1240
+ * remaining sides fall back to the `ui`-derived values.
1241
+ *
1242
+ * @example
1243
+ * { top: 40 } // top 40px, other sides 0
1244
+ * { ui: true } // measured UI + default padding
1245
+ * { ui: { reserve: { stylesPanel: true } } } // + keep space for hidden panel
1246
+ * { top: 40, ui: true } // top exactly 40px, rest from UI
1247
+ */
1248
+ export type ViewportOffsets = Offsets & {
1249
+ ui?: true | ViewportOffsetsOptions;
1250
+ };
1251
+ /**
1252
+ * Value of the `data-viewport-ui-name` attribute, identifying a
1253
+ * conditionally-rendered surface (marked with `data-viewport-ui`) so that
1254
+ * `getViewportOffsets` can reserve space for it while it's hidden (see the
1255
+ * `reserve` option). Whenever a named surface is rendered, its measured
1256
+ * footprint is remembered; reserving uses that remembered footprint, or an
1257
+ * approximate default if the surface hasn't been rendered yet.
1258
+ */
1259
+ export type ViewportUIName = "sidebar" | "stylesPanel";