@excalidraw/math 0.18.0-1118751 → 0.18.0-143b5b6

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 (59) hide show
  1. package/dist/types/common/src/constants.d.ts +3 -0
  2. package/dist/types/common/src/utils.d.ts +5 -0
  3. package/dist/types/element/src/binding.d.ts +8 -0
  4. package/dist/types/element/src/collision.d.ts +6 -0
  5. package/dist/types/element/src/index.d.ts +1 -0
  6. package/dist/types/element/src/listMarker.d.ts +34 -0
  7. package/dist/types/element/src/newElement.d.ts +15 -1
  8. package/dist/types/element/src/textElement.d.ts +7 -0
  9. package/dist/types/excalidraw/actions/actionAddToLibrary.d.ts +27 -3
  10. package/dist/types/excalidraw/actions/actionBoundText.d.ts +18 -2
  11. package/dist/types/excalidraw/actions/actionCanvas.d.ts +63 -7
  12. package/dist/types/excalidraw/actions/actionClipboard.d.ts +18 -2
  13. package/dist/types/excalidraw/actions/actionCropEditor.d.ts +9 -1
  14. package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +27 -3
  15. package/dist/types/excalidraw/actions/actionDeselect.d.ts +12 -1
  16. package/dist/types/excalidraw/actions/actionElementLink.d.ts +9 -1
  17. package/dist/types/excalidraw/actions/actionElementLock.d.ts +18 -2
  18. package/dist/types/excalidraw/actions/actionExport.d.ts +18 -2
  19. package/dist/types/excalidraw/actions/actionFrame.d.ts +27 -3
  20. package/dist/types/excalidraw/actions/actionGroup.d.ts +18 -2
  21. package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +9 -1
  22. package/dist/types/excalidraw/actions/actionLink.d.ts +9 -1
  23. package/dist/types/excalidraw/actions/actionMenu.d.ts +9 -1
  24. package/dist/types/excalidraw/actions/actionProperties.d.ts +18 -2
  25. package/dist/types/excalidraw/actions/actionSelectAll.d.ts +9 -1
  26. package/dist/types/excalidraw/actions/actionStyles.d.ts +9 -1
  27. package/dist/types/excalidraw/actions/actionToggleArrowBinding.d.ts +9 -1
  28. package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +9 -1
  29. package/dist/types/excalidraw/actions/actionToggleMidpointSnapping.d.ts +9 -1
  30. package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +9 -1
  31. package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +9 -1
  32. package/dist/types/excalidraw/actions/actionToggleShowHints.d.ts +197 -0
  33. package/dist/types/excalidraw/actions/actionToggleStats.d.ts +9 -1
  34. package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +9 -1
  35. package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +9 -1
  36. package/dist/types/excalidraw/actions/index.d.ts +1 -0
  37. package/dist/types/excalidraw/actions/types.d.ts +1 -1
  38. package/dist/types/excalidraw/appState.d.ts +1 -0
  39. package/dist/types/excalidraw/components/App.arrowText.d.ts +5 -39
  40. package/dist/types/excalidraw/components/App.clipboard.d.ts +31 -0
  41. package/dist/types/excalidraw/components/App.d.ts +58 -258
  42. package/dist/types/excalidraw/components/App.duplicate.d.ts +52 -2
  43. package/dist/types/excalidraw/components/App.modifiers.d.ts +38 -0
  44. package/dist/types/excalidraw/components/App.pan.d.ts +8 -0
  45. package/dist/types/excalidraw/components/App.selectionTool.d.ts +57 -0
  46. package/dist/types/excalidraw/components/App.text.d.ts +146 -0
  47. package/dist/types/excalidraw/components/App.textTool.d.ts +140 -0
  48. package/dist/types/excalidraw/components/App.viewport.d.ts +41 -1
  49. package/dist/types/excalidraw/components/FileDropOverlay.d.ts +2 -0
  50. package/dist/types/excalidraw/components/LibraryMenuSection.d.ts +6 -2
  51. package/dist/types/excalidraw/components/LibraryUnit.d.ts +7 -2
  52. package/dist/types/excalidraw/components/Tooltip.d.ts +15 -1
  53. package/dist/types/excalidraw/components/main-menu/DefaultItems.d.ts +1 -0
  54. package/dist/types/excalidraw/data/blob.d.ts +18 -2
  55. package/dist/types/excalidraw/data/json.d.ts +9 -1
  56. package/dist/types/excalidraw/types.d.ts +35 -13
  57. package/dist/types/excalidraw/viewport.d.ts +22 -1
  58. package/dist/types/excalidraw/wysiwyg/textWysiwyg.d.ts +12 -1
  59. package/package.json +2 -2
@@ -0,0 +1,146 @@
1
+ import { type Bounds, type StylesPanelMode } from "@excalidraw/common";
2
+ import type { ArrowEndpoint } from "@excalidraw/element";
3
+ import type { ExcalidrawElement, ExcalidrawTextContainer, ExcalidrawTextElement, NonDeleted, NonDeletedExcalidrawElement } from "@excalidraw/element/types";
4
+ import { textWysiwyg } from "../wysiwyg/textWysiwyg";
5
+ import type App from "./App";
6
+ import type { AppState, Offsets, ViewportUIName } from "../types";
7
+ type AppTextDependencies = {
8
+ getContainer: () => HTMLDivElement | null;
9
+ getStylesPanelMode: () => StylesPanelMode;
10
+ };
11
+ /**
12
+ * Texts, but for the text tool's pointer interaction (`AppTextTool`):
13
+ *
14
+ * - the editing session: what text to edit, or create, and where
15
+ * (`startTextEditing`), and the editor's lifecycle (`handleTextWysiwyg`)
16
+ * - the part of the canvas a typed or pasted text is kept within
17
+ * (`getTextViewportOffsets`, `getMaxTextWidth`)
18
+ * - the queries that find the text or container to edit at a position
19
+ * - the handle that turns a fixed-width text back into a growing one
20
+ *
21
+ * Every way into editing ends up here: Enter, double-click, pointerup on a
22
+ * selected text or container, the text tool, a drag-created text or sticky
23
+ * note, and a sticky note dropped from the toolbar.
24
+ */
25
+ export declare class AppText {
26
+ private app;
27
+ private dependencies;
28
+ constructor(app: App, dependencies: AppTextDependencies);
29
+ textWysiwygSubmitHandler: ReturnType<typeof textWysiwyg> | null;
30
+ private getTextCreationGridPoint;
31
+ /**
32
+ * The side panels, besides the sidebar, that a typed or pasted text is
33
+ * kept clear of: the stats panel, and the full styles panel (desktop),
34
+ * which shows next to a text while it's edited, and once it's pasted and
35
+ * selected.
36
+ */
37
+ getTextSidePanels: () => ViewportUIName[];
38
+ /**
39
+ * The part of the canvas a typed or pasted text is kept within, as offsets
40
+ * from its edges (screen px): all of it but the sidebar and the side
41
+ * panels (see getTextSidePanels), less some room at each side. The stats
42
+ * panel covers the top of a side only, and counts only for a text beside
43
+ * it: one (given by its scene bounds) with rows within that room of it.
44
+ */
45
+ getTextViewportOffsets: (textBounds?: Bounds) => Required<Offsets>;
46
+ /**
47
+ * The widest a text may grow to as it's typed or pasted, in scene units:
48
+ * TEXT_MAX_WRAP_WIDTH, or less, so that a text never outgrows the part of
49
+ * the canvas it's kept within.
50
+ */
51
+ getMaxTextWidth: (offsets: Required<Offsets>) => number;
52
+ handleTextWysiwyg(element: NonDeleted<ExcalidrawTextElement>, { isExistingElement, initialCaretSceneCoords, initialSelection, }: {
53
+ isExistingElement?: boolean;
54
+ /**
55
+ * supply null if no caret positioning is desired, and instead
56
+ * text should be auto-selected
57
+ */
58
+ initialCaretSceneCoords?: {
59
+ x: number;
60
+ y: number;
61
+ } | null;
62
+ /** range of the text to select (takes precedence over the caret) */
63
+ initialSelection?: {
64
+ start: number;
65
+ end: number;
66
+ } | null;
67
+ }): void;
68
+ private getSelectedTextElement;
69
+ getSelectedTextEditingContainerAtPosition(hitElement: NonDeletedExcalidrawElement | null, sceneCoords: {
70
+ x: number;
71
+ y: number;
72
+ }): ExcalidrawTextContainer | null | undefined;
73
+ getTextElementAtPosition(x: number, y: number): NonDeleted<ExcalidrawTextElement> | null;
74
+ isHittingTextAutoResizeHandle: (selectedElements: NonDeleted<ExcalidrawElement>[], point: Readonly<{
75
+ x: number;
76
+ y: number;
77
+ }>) => boolean;
78
+ handleTextAutoResizeHandlePointerDown: (selectedElements: NonDeleted<ExcalidrawElement>[], point: Readonly<{
79
+ x: number;
80
+ y: number;
81
+ }>) => boolean;
82
+ /**
83
+ * The text container at a position — an arrow hit on its path, any other
84
+ * container hit anywhere in its bounds (frames are skipped so a container
85
+ * inside one can be hit, and a frame's children are only hit inside it,
86
+ * where they are drawn). Purely positional: the selection plays no part.
87
+ *
88
+ * Only what hides the rest ends the search — a filled element or an image
89
+ * (as for arrow binding), or an arrow — so containers below a transparent
90
+ * one stay in reach whatever their z-order. Of the containers found, the
91
+ * innermost one centered on the position wins, since that is where its
92
+ * label would go (an arrow counting as innermost: it is pointed at, not just
93
+ * enclosing); failing that, the top-most.
94
+ */
95
+ getTextBindableContainerAtPosition(x: number, y: number): NonDeleted<ExcalidrawTextContainer>;
96
+ /**
97
+ * Whether a text element's content is still being authored.
98
+ *
99
+ * Creating a text reverts the tool to selection during pointerdown, so the
100
+ * pointerup that follows looks like an ordinary canvas click and would
101
+ * capture the still-empty element as a history entry of its own. Undo would
102
+ * then rewind only the typing, restoring an invisible, zero-content element
103
+ * (and, for an endpoint label, leaving the arrow bound to it) rather than
104
+ * removing it. The editor's own submit captures the finished text instead,
105
+ * so the whole create-and-type lands in a single entry.
106
+ */
107
+ isEditingTextContent(): boolean;
108
+ startTextEditing: ({ sceneX, sceneY, insertAtParentCenter, container, autoEdit, initialCaretSceneCoords, initialSelection, arrowEndpoint, textElement, }: {
109
+ /** X position to insert text at */
110
+ sceneX: number;
111
+ /** Y position to insert text at */
112
+ sceneY: number;
113
+ /** whether to attempt to insert at element center if applicable */
114
+ insertAtParentCenter?: boolean;
115
+ container?: ExcalidrawTextContainer | null;
116
+ autoEdit?: boolean;
117
+ initialCaretSceneCoords?: {
118
+ x: number;
119
+ y: number;
120
+ };
121
+ /** range of an existing text to select (takes precedence over the caret) */
122
+ initialSelection?: {
123
+ start: number;
124
+ end: number;
125
+ };
126
+ /**
127
+ * creates the text as a label for this arrow endpoint: the binding then
128
+ * dictates the text's position and alignment, overriding (sceneX, sceneY)
129
+ */
130
+ arrowEndpoint?: ArrowEndpoint | null;
131
+ /**
132
+ * the text to edit: an element to edit exactly that one; `null` to always
133
+ * create, never adopting a selected text or one under the pointer;
134
+ * `undefined` to resolve it here — a single selected text, the label of a
135
+ * selected or passed arrow container, else the text at (sceneX, sceneY)
136
+ */
137
+ textElement?: NonDeleted<ExcalidrawTextElement> | null;
138
+ }) => void;
139
+ getTextWysiwygSnappedToCenterPosition(x: number, y: number, appState: AppState, container?: ExcalidrawTextContainer | null): {
140
+ viewportX: number;
141
+ viewportY: number;
142
+ elementCenterX: number;
143
+ elementCenterY: number;
144
+ } | undefined;
145
+ }
146
+ export {};
@@ -0,0 +1,140 @@
1
+ import type { ArrowEndpoint } from "@excalidraw/element";
2
+ import type { ExcalidrawTextContainer, ExcalidrawTextElement, NonDeleted } from "@excalidraw/element/types";
3
+ import type React from "react";
4
+ import type App from "./App";
5
+ import type { PointerDownState } from "../types";
6
+ type ScenePoint = {
7
+ x: number;
8
+ y: number;
9
+ };
10
+ /** the modifier state a target depends on — off a pointer or keyboard event */
11
+ export type Modifiers = Pick<KeyboardEvent, "ctrlKey" | "metaKey">;
12
+ /** What a text-tool click at a position does. */
13
+ export type TextToolTarget =
14
+ /** binds a new text to a free arrow endpoint */
15
+ {
16
+ type: "endpoint";
17
+ endpoint: ArrowEndpoint;
18
+ }
19
+ /** edits this text (a label included, at its derived position) */
20
+ | {
21
+ type: "text";
22
+ element: NonDeleted<ExcalidrawTextElement>;
23
+ }
24
+ /** binds a new label to this empty container (an arrow included) */
25
+ | {
26
+ type: "container";
27
+ element: NonDeleted<ExcalidrawTextContainer>;
28
+ }
29
+ /** creates free text at the pointer */
30
+ | {
31
+ type: "free";
32
+ };
33
+ /**
34
+ * The text tool's pointer interaction.
35
+ *
36
+ * Everything hangs off one question — what would a click at this position
37
+ * do (`getTargetAt`)? — answered once and used for the hover affordance
38
+ * (`appState.textToolHover`), the cursor and the pointerdown itself, so the
39
+ * affordance can never promise something the click won't deliver.
40
+ *
41
+ * A click on an empty container's center is armed on pointerdown and
42
+ * committed on pointerup as a bound label; dragging past the autowrap
43
+ * threshold first turns it into a free fixed-width text at the origin
44
+ * instead.
45
+ *
46
+ * Text editing itself (`app.text.startTextEditing`, see `AppText`) is
47
+ * shared with Enter, double-click and the other entry points.
48
+ */
49
+ export declare class AppTextTool {
50
+ private app;
51
+ constructor(app: App);
52
+ /**
53
+ * A click on an empty container's center, armed on pointerdown and decided
54
+ * on the pointer's way out: a click binds a label, a drag creates free
55
+ * text instead. Deferring is what keeps the drag from first binding to
56
+ * (and provisionally enlarging) the container.
57
+ */
58
+ private pending;
59
+ /**
60
+ * The modifiers the hover was last resolved with — what a refresh without
61
+ * an event of its own (the viewport moving under a still pointer) uses.
62
+ */
63
+ private lastModifiers;
64
+ /**
65
+ * What a click at this position would do, in the order the click resolves
66
+ * it: a free arrow endpoint (the smaller, more deliberate target; z-aware,
67
+ * and off while ctrl/cmd disables binding) → the text under the pointer,
68
+ * which the click edits → an empty container near its center, which gets
69
+ * a label unless ctrl/cmd opts out → free text at the pointer.
70
+ *
71
+ * Ctrl/cmd is "no binding" throughout the tool, as elsewhere in the
72
+ * editor. For the container it is read off the event rather than the
73
+ * arrow-binding preference: a label is not an arrow binding.
74
+ */
75
+ getTargetAt: (scenePointer: ScenePoint, modifiers: Modifiers) => TextToolTarget;
76
+ /**
77
+ * Keeps `appState.textToolHover` — the affordance for what a click would
78
+ * do — in sync with the pointer, and returns the target (for the cursor).
79
+ * Suppressed while something else owns the interaction: a text being
80
+ * edited or drag-sized, a multi-point element, a box selection, a drag of
81
+ * the selection, or the pointer over a scrollbar.
82
+ */
83
+ updateHover: (scenePointer: ScenePoint, modifiers: Modifiers, isOverScrollBar?: boolean) => TextToolTarget | null;
84
+ /**
85
+ * Re-resolves the hover — and the cursor that goes with it — where the
86
+ * pointer last was, for what changes a click's outcome without the pointer
87
+ * moving: the ctrl/cmd toggle (pass its event), or the viewport scrolling
88
+ * or zooming under the pointer (no event; the last modifiers stand). The
89
+ * scene position is re-derived from the pointer's viewport position, so a
90
+ * moved viewport resolves what is under the pointer now.
91
+ *
92
+ * Nothing to refresh with another tool or without a hovering pointer — a
93
+ * finger never hovers (its last move is where it lifted), and the
94
+ * affordance a press armed is cleared when the press resolves or is
95
+ * canceled. The cursor is left to viewport navigation (space/wheel
96
+ * panning, a scrollbar drag, the hand tool), as on pointermove.
97
+ */
98
+ refresh: (modifiers?: Modifiers) => void;
99
+ /**
100
+ * Drops a pending center click without acting on it — the tool was left,
101
+ * the browser took the pointer (pointercancel), or a second finger turned
102
+ * the press into a pinch/pan — so no pointerup of ours will decide it. The
103
+ * outline it armed goes with it: while pending, the hover is that click's.
104
+ */
105
+ cancel: () => void;
106
+ clearHover: () => void;
107
+ private setHover;
108
+ /**
109
+ * The cursor for what a click would do: a pointer over the arrow anchors
110
+ * text would attach to, a text cursor over text the click would edit, the
111
+ * tool's crosshair otherwise — also while the affordance is suppressed
112
+ * (editing, drag-sizing), where a click has nothing to point at.
113
+ */
114
+ cursorFor: (target: TextToolTarget | null) => string;
115
+ handlePointerDown: (event: React.PointerEvent<HTMLElement>, pointerDownState: PointerDownState) => void;
116
+ /**
117
+ * The pointer-move half of a pending center click. Once the pointer has
118
+ * moved past the autowrap threshold the click is a drag: free text is
119
+ * created at the origin and sized by the drag from here on. Horizontal
120
+ * only (a text is only ever sized that way) and in screen space, and
121
+ * deliberately wider than the generic drag threshold so a jittery click
122
+ * still binds. Returns whether a pending click owned the move.
123
+ */
124
+ handlePointerMove: (event: PointerEvent, pointerDownState: PointerDownState) => boolean;
125
+ /**
126
+ * The pointer-up half: a genuine pointerup binds the label. The
127
+ * missing-pointerup cleanup replays this with the pointerdown event (a
128
+ * second finger landing mid-press), and a tool switch orphans the click —
129
+ * both discard it instead.
130
+ */
131
+ handlePointerUp: (event: PointerEvent, pointerDownState: PointerDownState) => void;
132
+ private isDrag;
133
+ private resolvePending;
134
+ /**
135
+ * The click has been acted on: drop the affordance, revert the tool unless
136
+ * it is locked, restore the cursor.
137
+ */
138
+ private finish;
139
+ }
140
+ export {};
@@ -40,6 +40,43 @@ export declare class AppViewport {
40
40
  * user pan/zoom input. */
41
41
  get isLockedTransitionPending(): boolean;
42
42
  invalidateUIOffset: (name: ViewportUIName) => void;
43
+ /**
44
+ * The side a rendered side UI (`data-viewport-ui="side"`) docks to, and
45
+ * how far it reaches into the canvas from it, in screen px.
46
+ */
47
+ private measureSide;
48
+ /**
49
+ * The side a named surface docks to while it's hidden, and how far it
50
+ * reaches into the canvas from it: as last measured, else approximately.
51
+ */
52
+ private getReservedSide;
53
+ private querySideUI;
54
+ /**
55
+ * Where a rendered side UI is, relative to the editor's container, in
56
+ * screen px; null when it isn't rendered.
57
+ */
58
+ getSideUIRect: (name: ViewportUIName) => {
59
+ left: number;
60
+ right: number;
61
+ top: number;
62
+ bottom: number;
63
+ } | null;
64
+ /**
65
+ * How far the named side UIs reach into the canvas, in screen px, from
66
+ * the left and the right: the part of the canvas they cover. Zero at a
67
+ * side none of them is rendered at — e.g. with the sidebar closed, or on
68
+ * phones, where it's an overlay that doesn't count as viewport UI — unless
69
+ * a hidden one is reserved (see `ViewportOffsetsOptions.reserve`).
70
+ */
71
+ getSideInsets: (names: readonly ViewportUIName[], opts?: Pick<ViewportOffsetsOptions, "reserve">) => {
72
+ left: number;
73
+ right: number;
74
+ };
75
+ /** How far the sidebar reaches into the canvas (see `getSideInsets`). */
76
+ getSidebarInsets: () => {
77
+ left: number;
78
+ right: number;
79
+ };
43
80
  /**
44
81
  * Resolves user-supplied viewport offsets into concrete per-side pixel
45
82
  * values. Static sides take precedence over UI-derived sides.
@@ -54,7 +91,10 @@ export declare class AppViewport {
54
91
  resolveInitialViewport: (opts: Omit<SetViewportOptions, "animation">, elementsMap: NonDeletedSceneElementsMap, appState: AppState) => (Viewport & {
55
92
  scrollConstraints: ScrollConstraints | null;
56
93
  }) | null;
57
- /** Navigates to a target and optionally installs scroll/zoom constraints. */
94
+ /**
95
+ * Navigates to a target and optionally installs scroll/zoom constraints.
96
+ * Navigating stops following a collaborator, as a user's pan does.
97
+ */
58
98
  setViewport: (opts: SetViewportOptions | null) => void;
59
99
  /** Use when changing scrollX/scrollY/zoom based on user interaction. */
60
100
  translate: <K extends keyof AppState>(state: AppState | Pick<AppState, K> | null | ((prevState: Readonly<AppState>, props: Readonly<AppProps>) => AppState | Pick<AppState, K> | null), opts?: {
@@ -0,0 +1,2 @@
1
+ import "./FileDropOverlay.scss";
2
+ export declare const FileDropOverlay: () => import("react/jsx-runtime").JSX.Element | null;
@@ -15,9 +15,13 @@ interface Props {
15
15
  isItemSelected: (id: LibraryItem["id"] | null) => boolean;
16
16
  svgCache: SvgCache;
17
17
  itemsRenderedPerBatch: number;
18
+ /** larger items with their name below */
19
+ showNames?: boolean;
18
20
  }
19
- export declare const LibraryMenuSectionGrid: ({ children, }: {
21
+ export declare const LibraryMenuSectionGrid: ({ children, showNames, }: {
20
22
  children: ReactNode;
23
+ /** fewer columns, for items rendered with `showNames` */
24
+ showNames?: boolean;
21
25
  }) => import("react/jsx-runtime").JSX.Element;
22
- export declare const LibraryMenuSection: React.MemoExoticComponent<({ items, onItemSelectToggle, onItemDrag, isItemSelected, onClick, svgCache, itemsRenderedPerBatch, }: Props) => import("react/jsx-runtime").JSX.Element>;
26
+ export declare const LibraryMenuSection: React.MemoExoticComponent<({ items, onItemSelectToggle, onItemDrag, isItemSelected, onClick, svgCache, itemsRenderedPerBatch, showNames, }: Props) => import("react/jsx-runtime").JSX.Element>;
23
27
  export {};
@@ -1,8 +1,11 @@
1
1
  import "./LibraryUnit.scss";
2
2
  import type { LibraryItem } from "../types";
3
3
  import type { SvgCache } from "../hooks/useLibraryItemSvg";
4
- export declare const LibraryUnit: import("react").MemoExoticComponent<({ id, elements, isPending, onClick, selected, onToggle, onDrag, svgCache, }: {
4
+ export declare const LibraryUnit: import("react").MemoExoticComponent<({ id, name, showName, elements, isPending, onClick, selected, onToggle, onDrag, svgCache, }: {
5
5
  id: LibraryItem["id"] | /** for pending item */ null;
6
+ name?: LibraryItem["name"];
7
+ /** render larger, with the name below the item */
8
+ showName?: boolean;
6
9
  elements?: LibraryItem["elements"];
7
10
  isPending?: boolean;
8
11
  onClick: (id: LibraryItem["id"] | null) => void;
@@ -11,4 +14,6 @@ export declare const LibraryUnit: import("react").MemoExoticComponent<({ id, ele
11
14
  onDrag: (id: string, event: React.DragEvent) => void;
12
15
  svgCache: SvgCache;
13
16
  }) => import("react/jsx-runtime").JSX.Element>;
14
- export declare const EmptyLibraryUnit: () => import("react/jsx-runtime").JSX.Element;
17
+ export declare const EmptyLibraryUnit: ({ showName }: {
18
+ showName?: boolean;
19
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -7,12 +7,26 @@ export declare const updateTooltipPosition: (tooltip: HTMLDivElement, item: {
7
7
  width: number;
8
8
  height: number;
9
9
  }, position?: "bottom" | "top") => void;
10
+ export declare const hideTooltip: () => void;
11
+ /**
12
+ * Shows the tooltip for `item`. For elements that can't be wrapped
13
+ * in <Tooltip>. Pair with `hideTooltip()`.
14
+ */
15
+ export declare const showTooltip: (item: HTMLElement, label: string, { long, delay, position, }?: {
16
+ long?: boolean;
17
+ /** show after a short delay (unless a tooltip was visible just now) */
18
+ delay?: boolean;
19
+ position?: "bottom" | "top";
20
+ }) => void;
10
21
  type TooltipProps = {
11
22
  children: React.ReactNode;
12
23
  label: string;
13
24
  long?: boolean;
14
25
  style?: React.CSSProperties;
26
+ className?: string;
15
27
  disabled?: boolean;
28
+ /** show after a short delay (unless a tooltip was visible just now) */
29
+ delay?: boolean;
16
30
  };
17
- export declare const Tooltip: ({ children, label, long, style, disabled, }: TooltipProps) => import("react/jsx-runtime").JSX.Element | null;
31
+ export declare const Tooltip: ({ children, label, long, style, className, disabled, delay, }: TooltipProps) => import("react/jsx-runtime").JSX.Element | null;
18
32
  export {};
@@ -78,6 +78,7 @@ export declare const Preferences: {
78
78
  ToggleSnapMode: () => import("react/jsx-runtime").JSX.Element;
79
79
  ToggleArrowBinding: () => import("react/jsx-runtime").JSX.Element;
80
80
  ToggleMidpointSnapping: () => import("react/jsx-runtime").JSX.Element;
81
+ ToggleShowHints: () => import("react/jsx-runtime").JSX.Element;
81
82
  ToggleGridMode: () => import("react/jsx-runtime").JSX.Element;
82
83
  ToggleZenMode: () => import("react/jsx-runtime").JSX.Element;
83
84
  ToggleViewMode: () => import("react/jsx-runtime").JSX.Element | null;
@@ -78,7 +78,14 @@ fileHandle?: FileSystemFileHandle | null) => Promise<{
78
78
  element: import("@excalidraw/element/types").NonDeleted<import("@excalidraw/element/types").ExcalidrawBindableElement>;
79
79
  midPoint?: import("@excalidraw/math").GlobalPoint;
80
80
  } | null;
81
- hoveredArrowTextAnchor: {
81
+ textToolHover: {
82
+ type: "text";
83
+ elementId: ExcalidrawElement["id"];
84
+ } | {
85
+ type: "container";
86
+ elementId: ExcalidrawElement["id"];
87
+ } | {
88
+ type: "arrow";
82
89
  elementId: import("@excalidraw/element/types").ExcalidrawArrowElement["id"];
83
90
  anchor: "start" | "end" | "label";
84
91
  } | null;
@@ -114,6 +121,7 @@ fileHandle?: FileSystemFileHandle | null) => Promise<{
114
121
  resizingElement: import("@excalidraw/element/types").NonDeletedExcalidrawElement | null;
115
122
  boxSelectionMode: import("../types").BoxSelectionMode;
116
123
  bindingPreference: "enabled" | "disabled";
124
+ showHints: boolean;
117
125
  inputDevice: import("../types").InputDevice;
118
126
  editingFrame: import("@excalidraw/element/types").ExcalidrawFrameLikeElement["id"] | null;
119
127
  preferredSelectionTool: {
@@ -258,7 +266,14 @@ fileHandle?: FileSystemFileHandle | null) => Promise<{
258
266
  element: import("@excalidraw/element/types").NonDeleted<import("@excalidraw/element/types").ExcalidrawBindableElement>;
259
267
  midPoint?: import("@excalidraw/math").GlobalPoint;
260
268
  } | null;
261
- hoveredArrowTextAnchor: {
269
+ textToolHover: {
270
+ type: "text";
271
+ elementId: ExcalidrawElement["id"];
272
+ } | {
273
+ type: "container";
274
+ elementId: ExcalidrawElement["id"];
275
+ } | {
276
+ type: "arrow";
262
277
  elementId: import("@excalidraw/element/types").ExcalidrawArrowElement["id"];
263
278
  anchor: "start" | "end" | "label";
264
279
  } | null;
@@ -294,6 +309,7 @@ fileHandle?: FileSystemFileHandle | null) => Promise<{
294
309
  resizingElement: import("@excalidraw/element/types").NonDeletedExcalidrawElement | null;
295
310
  boxSelectionMode: import("../types").BoxSelectionMode;
296
311
  bindingPreference: "enabled" | "disabled";
312
+ showHints: boolean;
297
313
  inputDevice: import("../types").InputDevice;
298
314
  editingFrame: import("@excalidraw/element/types").ExcalidrawFrameLikeElement["id"] | null;
299
315
  preferredSelectionTool: {
@@ -76,7 +76,14 @@ export declare const loadFromJSON: (localAppState: AppState, localElements: read
76
76
  element: import("@excalidraw/element/types").NonDeleted<import("@excalidraw/element/types").ExcalidrawBindableElement>;
77
77
  midPoint?: import("@excalidraw/math").GlobalPoint;
78
78
  } | null;
79
- hoveredArrowTextAnchor: {
79
+ textToolHover: {
80
+ type: "text";
81
+ elementId: ExcalidrawElement["id"];
82
+ } | {
83
+ type: "container";
84
+ elementId: ExcalidrawElement["id"];
85
+ } | {
86
+ type: "arrow";
80
87
  elementId: import("@excalidraw/element/types").ExcalidrawArrowElement["id"];
81
88
  anchor: "start" | "end" | "label";
82
89
  } | null;
@@ -112,6 +119,7 @@ export declare const loadFromJSON: (localAppState: AppState, localElements: read
112
119
  resizingElement: import("@excalidraw/element/types").NonDeletedExcalidrawElement | null;
113
120
  boxSelectionMode: import("../types").BoxSelectionMode;
114
121
  bindingPreference: "enabled" | "disabled";
122
+ showHints: boolean;
115
123
  inputDevice: import("../types").InputDevice;
116
124
  editingFrame: import("@excalidraw/element/types").ExcalidrawFrameLikeElement["id"] | null;
117
125
  preferredSelectionTool: {
@@ -1,6 +1,6 @@
1
1
  import type { IMAGE_MIME_TYPES, UserIdleState, throttleRAF, MIME_TYPES, EditorInterface, StrokeWidthKey } from "@excalidraw/common";
2
2
  import type { LinearElementEditor } from "@excalidraw/element";
3
- import type { MaybeTransformHandleType } from "@excalidraw/element";
3
+ import type { ListMarkerAdvance, MaybeTransformHandleType } from "@excalidraw/element";
4
4
  import type { PointerType, ExcalidrawLinearElement, NonDeletedExcalidrawElement, NonDeleted, TextAlign, ExcalidrawElement, GroupId, ExcalidrawBindableElement, ExcalidrawArrowElement, Arrowhead, FontFamilyValues, FileId, Theme, StrokeRoundness, ExcalidrawEmbeddableElement, ExcalidrawMagicFrameElement, ExcalidrawFrameLikeElement, ExcalidrawElementType, ExcalidrawIframeLikeElement, OrderedExcalidrawElement, ExcalidrawNonSelectionElement, 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, OnDuplicateData } from "@excalidraw/element";
@@ -141,7 +141,7 @@ export type InteractiveCanvasAppState = Readonly<_CommonCanvasAppState & {
141
141
  isMidpointSnappingEnabled: AppState["isMidpointSnappingEnabled"];
142
142
  gridModeEnabled: AppState["gridModeEnabled"];
143
143
  suggestedBinding: AppState["suggestedBinding"];
144
- hoveredArrowTextAnchor: AppState["hoveredArrowTextAnchor"];
144
+ textToolHover: AppState["textToolHover"];
145
145
  isRotating: AppState["isRotating"];
146
146
  elementsToHighlight: AppState["elementsToHighlight"];
147
147
  collaborators: AppState["collaborators"];
@@ -260,6 +260,8 @@ export interface AppState {
260
260
  bindingPreference: "enabled" | "disabled";
261
261
  /** user preference whether arrow snap to midpoints while binding */
262
262
  isMidpointSnappingEnabled: boolean;
263
+ /** user preference whether to show contextual hints above the toolbar */
264
+ showHints: boolean;
263
265
  /**
264
266
  * user preference for what the wheel does: with a `trackpad` a plain wheel
265
267
  * pans; with a `mouse` a plain wheel zooms. Ctrl/cmd+wheel (how a pinch is
@@ -277,11 +279,20 @@ export interface AppState {
277
279
  midPoint?: GlobalPoint;
278
280
  } | null;
279
281
  /**
280
- * Where on a hovered arrow the text tool would attach text if clicked —
281
- * a free endpoint (binds the arrow to a new text element positioned against
282
- * that endpoint) or the arrow's midpoint (adds a label bound to the arrow).
282
+ * What a text-tool click at the hovered position would act on — the text
283
+ * it would edit, the empty container it would label, or the arrow anchor
284
+ * (a free endpoint, or the midpoint for a label) it would attach text to.
285
+ * `null` when the click would create free text, or the tool isn't active.
286
+ * Drives the hover affordance only.
283
287
  */
284
- hoveredArrowTextAnchor: {
288
+ textToolHover: {
289
+ type: "text";
290
+ elementId: ExcalidrawElement["id"];
291
+ } | {
292
+ type: "container";
293
+ elementId: ExcalidrawElement["id"];
294
+ } | {
295
+ type: "arrow";
285
296
  elementId: ExcalidrawArrowElement["id"];
286
297
  anchor: "start" | "end" | "label";
287
298
  } | null;
@@ -296,6 +307,10 @@ export interface AppState {
296
307
  * frame-like element whose name is currently being edited
297
308
  */
298
309
  editingFrame: ExcalidrawFrameLikeElement["id"] | null;
310
+ /**
311
+ * Elements the UI highlights with a bounding-box outline — those that
312
+ * would get added to a frame being dragged/resized.
313
+ */
299
314
  elementsToHighlight: readonly NonDeletedExcalidrawElement[] | null;
300
315
  /**
301
316
  * set when a new text is created or when an existing text is being edited
@@ -472,7 +487,7 @@ export type SearchMatch = {
472
487
  showOnCanvas: boolean;
473
488
  }[];
474
489
  };
475
- export type UIAppState = Omit<AppState, "cursorButton" | "scrollX" | "scrollY" | "zoom" | "shouldCacheIgnoreZoom" | "snapLines" | "originSnapOffset" | "suggestedBinding" | "hoveredArrowTextAnchor" | "frameToHighlight" | "elementsToHighlight">;
490
+ export type UIAppState = Omit<AppState, "cursorButton" | "scrollX" | "scrollY" | "zoom" | "shouldCacheIgnoreZoom" | "snapLines" | "originSnapOffset" | "suggestedBinding" | "textToolHover" | "frameToHighlight" | "elementsToHighlight">;
476
491
  export type NormalizedZoomValue = number & {
477
492
  _brand: "normalizedZoom";
478
493
  };
@@ -961,7 +976,7 @@ export type AppClassProperties = {
961
976
  scene: App["scene"];
962
977
  syncActionResult: App["syncActionResult"];
963
978
  fonts: App["fonts"];
964
- pasteFromClipboard: App["pasteFromClipboard"];
979
+ clipboard: App["clipboard"];
965
980
  id: App["id"];
966
981
  onInsertElements: App["onInsertElements"];
967
982
  onExportImage: App["onExportImage"];
@@ -979,11 +994,14 @@ export type AppClassProperties = {
979
994
  flowchart: App["flowchart"];
980
995
  drawShape: App["drawShape"];
981
996
  arrowText: App["arrowText"];
997
+ textTool: App["textTool"];
982
998
  cursor: App["cursor"];
983
999
  bucketFill: App["bucketFill"];
984
1000
  duplicate: App["duplicate"];
985
1001
  toolDrag: App["toolDrag"];
986
1002
  activeResizeHandle: App["activeResizeHandle"];
1003
+ selectionTool: App["selectionTool"];
1004
+ modifiers: App["modifiers"];
987
1005
  isToolLocked: App["isToolLocked"];
988
1006
  getEffectiveGridSize: App["getEffectiveGridSize"];
989
1007
  setPlugins: App["setPlugins"];
@@ -1036,7 +1054,10 @@ export type PointerDownState = Readonly<{
1036
1054
  element: NonDeleted<ExcalidrawElement> | null;
1037
1055
  allHitElements: NonDeleted<ExcalidrawElement>[];
1038
1056
  wasAddedToSelection: boolean;
1057
+ cycleTarget: NonDeleted<ExcalidrawElement> | null;
1039
1058
  hasBeenDuplicated: boolean;
1059
+ advancedListMarkers: readonly ListMarkerAdvance[];
1060
+ editedTextId: ExcalidrawTextElement["id"] | null;
1040
1061
  hasHitCommonBoundingBoxOfSelectedElements: boolean;
1041
1062
  arrowLabel: boolean;
1042
1063
  };
@@ -1270,9 +1291,10 @@ export type ViewportOffsets = Offsets & {
1270
1291
  /**
1271
1292
  * Value of the `data-viewport-ui-name` attribute, identifying a
1272
1293
  * conditionally-rendered surface (marked with `data-viewport-ui`) so that
1273
- * `getViewportOffsets` can reserve space for it while it's hidden (see the
1274
- * `reserve` option). Whenever a named surface is rendered, its measured
1275
- * footprint is remembered; reserving uses that remembered footprint, or an
1276
- * approximate default if the surface hasn't been rendered yet.
1294
+ * it can be measured on its own, and so that `getViewportOffsets` can
1295
+ * reserve space for it while it's hidden (see the `reserve` option).
1296
+ * Whenever a named surface is rendered, its measured footprint is
1297
+ * remembered; reserving uses that remembered footprint, or an approximate
1298
+ * default if the surface hasn't been rendered yet.
1277
1299
  */
1278
- export type ViewportUIName = "sidebar" | "stylesPanel";
1300
+ export type ViewportUIName = "sidebar" | "stylesPanel" | "stats";