123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758 |
- import React from "react";
- import {
- PointerType,
- ExcalidrawLinearElement,
- NonDeletedExcalidrawElement,
- NonDeleted,
- TextAlign,
- ExcalidrawElement,
- GroupId,
- ExcalidrawBindableElement,
- Arrowhead,
- ChartType,
- FontFamilyValues,
- FileId,
- ExcalidrawImageElement,
- Theme,
- StrokeRoundness,
- ExcalidrawEmbeddableElement,
- ExcalidrawMagicFrameElement,
- ExcalidrawFrameLikeElement,
- ExcalidrawElementType,
- ExcalidrawIframeLikeElement,
- } from "./element/types";
- import { Action } from "./actions/types";
- import { Point as RoughPoint } from "roughjs/bin/geometry";
- import { LinearElementEditor } from "./element/linearElementEditor";
- import { SuggestedBinding } from "./element/binding";
- import { ImportedDataState } from "./data/types";
- import type App from "./components/App";
- import type { throttleRAF } from "./utils";
- import { Spreadsheet } from "./charts";
- import { Language } from "./i18n";
- import { ClipboardData } from "./clipboard";
- import { isOverScrollBars } from "./scene/scrollbars";
- import { MaybeTransformHandleType } from "./element/transformHandles";
- import Library from "./data/library";
- import type { FileSystemHandle } from "./data/filesystem";
- import type { IMAGE_MIME_TYPES, MIME_TYPES } from "./constants";
- import { ContextMenuItems } from "./components/ContextMenu";
- import { SnapLine } from "./snapping";
- import { Merge, ValueOf } from "./utility-types";
- export type Point = Readonly<RoughPoint>;
- export type SocketId = string & { _brand: "SocketId" };
- export type Collaborator = Readonly<{
- pointer?: CollaboratorPointer;
- button?: "up" | "down";
- selectedElementIds?: AppState["selectedElementIds"];
- username?: string | null;
- userState?: UserIdleState;
- color?: {
- background: string;
- stroke: string;
- };
- // The url of the collaborator's avatar, defaults to username initials
- // if not present
- avatarUrl?: string;
- // user id. If supplied, we'll filter out duplicates when rendering user avatars.
- id?: string;
- socketId?: SocketId;
- isCurrentUser?: boolean;
- }>;
- export type CollaboratorPointer = {
- x: number;
- y: number;
- tool: "pointer" | "laser";
- };
- export type DataURL = string & { _brand: "DataURL" };
- export type BinaryFileData = {
- mimeType:
- | ValueOf<typeof IMAGE_MIME_TYPES>
- // future user or unknown file type
- | typeof MIME_TYPES.binary;
- id: FileId;
- dataURL: DataURL;
- /**
- * Epoch timestamp in milliseconds
- */
- created: number;
- /**
- * Indicates when the file was last retrieved from storage to be loaded
- * onto the scene. We use this flag to determine whether to delete unused
- * files from storage.
- *
- * Epoch timestamp in milliseconds.
- */
- lastRetrieved?: number;
- };
- export type BinaryFileMetadata = Omit<BinaryFileData, "dataURL">;
- export type BinaryFiles = Record<ExcalidrawElement["id"], BinaryFileData>;
- export type ToolType =
- | "selection"
- | "rectangle"
- | "diamond"
- | "ellipse"
- | "arrow"
- | "line"
- | "freedraw"
- | "text"
- | "image"
- | "eraser"
- | "hand"
- | "frame"
- | "magicframe"
- | "embeddable"
- | "laser";
- export type ElementOrToolType = ExcalidrawElementType | ToolType | "custom";
- export type ActiveTool =
- | {
- type: ToolType;
- customType: null;
- }
- | {
- type: "custom";
- customType: string;
- };
- export type SidebarName = string;
- export type SidebarTabName = string;
- export type UserToFollow = {
- socketId: SocketId;
- username: string;
- };
- type _CommonCanvasAppState = {
- zoom: AppState["zoom"];
- scrollX: AppState["scrollX"];
- scrollY: AppState["scrollY"];
- width: AppState["width"];
- height: AppState["height"];
- viewModeEnabled: AppState["viewModeEnabled"];
- editingGroupId: AppState["editingGroupId"]; // TODO: move to interactive canvas if possible
- selectedElementIds: AppState["selectedElementIds"]; // TODO: move to interactive canvas if possible
- frameToHighlight: AppState["frameToHighlight"]; // TODO: move to interactive canvas if possible
- offsetLeft: AppState["offsetLeft"];
- offsetTop: AppState["offsetTop"];
- theme: AppState["theme"];
- pendingImageElementId: AppState["pendingImageElementId"];
- };
- export type StaticCanvasAppState = Readonly<
- _CommonCanvasAppState & {
- shouldCacheIgnoreZoom: AppState["shouldCacheIgnoreZoom"];
- /** null indicates transparent bg */
- viewBackgroundColor: AppState["viewBackgroundColor"] | null;
- exportScale: AppState["exportScale"];
- selectedElementsAreBeingDragged: AppState["selectedElementsAreBeingDragged"];
- gridSize: AppState["gridSize"];
- frameRendering: AppState["frameRendering"];
- }
- >;
- export type InteractiveCanvasAppState = Readonly<
- _CommonCanvasAppState & {
- // renderInteractiveScene
- activeEmbeddable: AppState["activeEmbeddable"];
- editingLinearElement: AppState["editingLinearElement"];
- selectionElement: AppState["selectionElement"];
- selectedGroupIds: AppState["selectedGroupIds"];
- selectedLinearElement: AppState["selectedLinearElement"];
- multiElement: AppState["multiElement"];
- isBindingEnabled: AppState["isBindingEnabled"];
- suggestedBindings: AppState["suggestedBindings"];
- isRotating: AppState["isRotating"];
- elementsToHighlight: AppState["elementsToHighlight"];
- // Collaborators
- collaborators: AppState["collaborators"];
- // SnapLines
- snapLines: AppState["snapLines"];
- zenModeEnabled: AppState["zenModeEnabled"];
- }
- >;
- export interface AppState {
- contextMenu: {
- items: ContextMenuItems;
- top: number;
- left: number;
- } | null;
- showWelcomeScreen: boolean;
- isLoading: boolean;
- errorMessage: React.ReactNode;
- activeEmbeddable: {
- element: NonDeletedExcalidrawElement;
- state: "hover" | "active";
- } | null;
- draggingElement: NonDeletedExcalidrawElement | null;
- resizingElement: NonDeletedExcalidrawElement | null;
- multiElement: NonDeleted<ExcalidrawLinearElement> | null;
- selectionElement: NonDeletedExcalidrawElement | null;
- isBindingEnabled: boolean;
- startBoundElement: NonDeleted<ExcalidrawBindableElement> | null;
- suggestedBindings: SuggestedBinding[];
- frameToHighlight: NonDeleted<ExcalidrawFrameLikeElement> | null;
- frameRendering: {
- enabled: boolean;
- name: boolean;
- outline: boolean;
- clip: boolean;
- };
- editingFrame: string | null;
- elementsToHighlight: NonDeleted<ExcalidrawElement>[] | null;
- // element being edited, but not necessarily added to elements array yet
- // (e.g. text element when typing into the input)
- editingElement: NonDeletedExcalidrawElement | null;
- editingLinearElement: LinearElementEditor | null;
- activeTool: {
- /**
- * indicates a previous tool we should revert back to if we deselect the
- * currently active tool. At the moment applies to `eraser` and `hand` tool.
- */
- lastActiveTool: ActiveTool | null;
- locked: boolean;
- } & ActiveTool;
- penMode: boolean;
- penDetected: boolean;
- exportBackground: boolean;
- exportEmbedScene: boolean;
- exportWithDarkMode: boolean;
- exportScale: number;
- currentItemStrokeColor: string;
- currentItemBackgroundColor: string;
- currentItemFillStyle: ExcalidrawElement["fillStyle"];
- currentItemStrokeWidth: number;
- currentItemStrokeStyle: ExcalidrawElement["strokeStyle"];
- currentItemRoughness: number;
- currentItemOpacity: number;
- currentItemFontFamily: FontFamilyValues;
- currentItemFontSize: number;
- currentItemTextAlign: TextAlign;
- currentItemStartArrowhead: Arrowhead | null;
- currentItemEndArrowhead: Arrowhead | null;
- currentItemRoundness: StrokeRoundness;
- viewBackgroundColor: string;
- scrollX: number;
- scrollY: number;
- cursorButton: "up" | "down";
- scrolledOutside: boolean;
- name: string;
- isResizing: boolean;
- isRotating: boolean;
- zoom: Zoom;
- openMenu: "canvas" | "shape" | null;
- openPopup: "canvasBackground" | "elementBackground" | "elementStroke" | null;
- openSidebar: { name: SidebarName; tab?: SidebarTabName } | null;
- openDialog:
- | null
- | { name: "imageExport" | "help" | "jsonExport" }
- | {
- name: "settings";
- source:
- | "tool" // when magicframe tool is selected
- | "generation" // when magicframe generate button is clicked
- | "settings"; // when AI settings dialog is explicitly invoked
- tab: "text-to-diagram" | "diagram-to-code";
- }
- | { name: "ttd"; tab: "text-to-diagram" | "mermaid" };
- /**
- * Reflects user preference for whether the default sidebar should be docked.
- *
- * NOTE this is only a user preference and does not reflect the actual docked
- * state of the sidebar, because the host apps can override this through
- * a DefaultSidebar prop, which is not reflected back to the appState.
- */
- defaultSidebarDockedPreference: boolean;
- lastPointerDownWith: PointerType;
- selectedElementIds: Readonly<{ [id: string]: true }>;
- previousSelectedElementIds: { [id: string]: true };
- selectedElementsAreBeingDragged: boolean;
- shouldCacheIgnoreZoom: boolean;
- toast: { message: string; closable?: boolean; duration?: number } | null;
- zenModeEnabled: boolean;
- theme: Theme;
- gridSize: number | null;
- viewModeEnabled: boolean;
- /** top-most selected groups (i.e. does not include nested groups) */
- selectedGroupIds: { [groupId: string]: boolean };
- /** group being edited when you drill down to its constituent element
- (e.g. when you double-click on a group's element) */
- editingGroupId: GroupId | null;
- width: number;
- height: number;
- offsetTop: number;
- offsetLeft: number;
- fileHandle: FileSystemHandle | null;
- collaborators: Map<SocketId, Collaborator>;
- showStats: boolean;
- currentChartType: ChartType;
- pasteDialog:
- | {
- shown: false;
- data: null;
- }
- | {
- shown: true;
- data: Spreadsheet;
- };
- /** imageElement waiting to be placed on canvas */
- pendingImageElementId: ExcalidrawImageElement["id"] | null;
- showHyperlinkPopup: false | "info" | "editor";
- selectedLinearElement: LinearElementEditor | null;
- snapLines: readonly SnapLine[];
- originSnapOffset: {
- x: number;
- y: number;
- } | null;
- objectsSnapModeEnabled: boolean;
- /** the user's clientId & username who is being followed on the canvas */
- userToFollow: UserToFollow | null;
- /** the clientIds of the users following the current user */
- followedBy: Set<SocketId>;
- }
- export type UIAppState = Omit<
- AppState,
- | "suggestedBindings"
- | "startBoundElement"
- | "cursorButton"
- | "scrollX"
- | "scrollY"
- >;
- export type NormalizedZoomValue = number & { _brand: "normalizedZoom" };
- export type Zoom = Readonly<{
- value: NormalizedZoomValue;
- }>;
- export type PointerCoords = Readonly<{
- x: number;
- y: number;
- }>;
- export type Gesture = {
- pointers: Map<number, PointerCoords>;
- lastCenter: { x: number; y: number } | null;
- initialDistance: number | null;
- initialScale: number | null;
- };
- export declare class GestureEvent extends UIEvent {
- readonly rotation: number;
- readonly scale: number;
- }
- // libraries
- // -----------------------------------------------------------------------------
- /** @deprecated legacy: do not use outside of migration paths */
- export type LibraryItem_v1 = readonly NonDeleted<ExcalidrawElement>[];
- /** @deprecated legacy: do not use outside of migration paths */
- type LibraryItems_v1 = readonly LibraryItem_v1[];
- /** v2 library item */
- export type LibraryItem = {
- id: string;
- status: "published" | "unpublished";
- elements: readonly NonDeleted<ExcalidrawElement>[];
- /** timestamp in epoch (ms) */
- created: number;
- name?: string;
- error?: string;
- };
- export type LibraryItems = readonly LibraryItem[];
- export type LibraryItems_anyVersion = LibraryItems | LibraryItems_v1;
- export type LibraryItemsSource =
- | ((
- currentLibraryItems: LibraryItems,
- ) =>
- | Blob
- | LibraryItems_anyVersion
- | Promise<LibraryItems_anyVersion | Blob>)
- | Blob
- | LibraryItems_anyVersion
- | Promise<LibraryItems_anyVersion | Blob>;
- // -----------------------------------------------------------------------------
- export type ExcalidrawInitialDataState = Merge<
- ImportedDataState,
- {
- libraryItems?:
- | Required<ImportedDataState>["libraryItems"]
- | Promise<Required<ImportedDataState>["libraryItems"]>;
- }
- >;
- export type OnUserFollowedPayload = {
- userToFollow: UserToFollow;
- action: "FOLLOW" | "UNFOLLOW";
- };
- export interface ExcalidrawProps {
- onChange?: (
- elements: readonly ExcalidrawElement[],
- appState: AppState,
- files: BinaryFiles,
- ) => void;
- initialData?:
- | ExcalidrawInitialDataState
- | null
- | Promise<ExcalidrawInitialDataState | null>;
- excalidrawAPI?: (api: ExcalidrawImperativeAPI) => void;
- isCollaborating?: boolean;
- onPointerUpdate?: (payload: {
- pointer: { x: number; y: number; tool: "pointer" | "laser" };
- button: "down" | "up";
- pointersMap: Gesture["pointers"];
- }) => void;
- onPaste?: (
- data: ClipboardData,
- event: ClipboardEvent | null,
- ) => Promise<boolean> | boolean;
- renderTopRightUI?: (
- isMobile: boolean,
- appState: UIAppState,
- ) => JSX.Element | null;
- langCode?: Language["code"];
- viewModeEnabled?: boolean;
- zenModeEnabled?: boolean;
- gridModeEnabled?: boolean;
- objectsSnapModeEnabled?: boolean;
- libraryReturnUrl?: string;
- theme?: Theme;
- name?: string;
- renderCustomStats?: (
- elements: readonly NonDeletedExcalidrawElement[],
- appState: UIAppState,
- ) => JSX.Element;
- UIOptions?: Partial<UIOptions>;
- detectScroll?: boolean;
- handleKeyboardGlobally?: boolean;
- onLibraryChange?: (libraryItems: LibraryItems) => void | Promise<any>;
- autoFocus?: boolean;
- generateIdForFile?: (file: File) => string | Promise<string>;
- onLinkOpen?: (
- element: NonDeletedExcalidrawElement,
- event: CustomEvent<{
- nativeEvent: MouseEvent | React.PointerEvent<HTMLCanvasElement>;
- }>,
- ) => void;
- onPointerDown?: (
- activeTool: AppState["activeTool"],
- pointerDownState: PointerDownState,
- ) => void;
- onPointerUp?: (
- activeTool: AppState["activeTool"],
- pointerDownState: PointerDownState,
- ) => void;
- onScrollChange?: (scrollX: number, scrollY: number, zoom: Zoom) => void;
- onUserFollow?: (payload: OnUserFollowedPayload) => void;
- children?: React.ReactNode;
- validateEmbeddable?:
- | boolean
- | string[]
- | RegExp
- | RegExp[]
- | ((link: string) => boolean | undefined);
- renderEmbeddable?: (
- element: NonDeleted<ExcalidrawEmbeddableElement>,
- appState: AppState,
- ) => JSX.Element | null;
- aiEnabled?: boolean;
- }
- export type SceneData = {
- elements?: ImportedDataState["elements"];
- appState?: ImportedDataState["appState"];
- collaborators?: Map<SocketId, Collaborator>;
- commitToHistory?: boolean;
- };
- export enum UserIdleState {
- ACTIVE = "active",
- AWAY = "away",
- IDLE = "idle",
- }
- export type ExportOpts = {
- saveFileToDisk?: boolean;
- onExportToBackend?: (
- exportedElements: readonly NonDeletedExcalidrawElement[],
- appState: UIAppState,
- files: BinaryFiles,
- ) => void;
- renderCustomUI?: (
- exportedElements: readonly NonDeletedExcalidrawElement[],
- appState: UIAppState,
- files: BinaryFiles,
- canvas: HTMLCanvasElement,
- ) => JSX.Element;
- };
- // NOTE at the moment, if action name corresponds to canvasAction prop, its
- // truthiness value will determine whether the action is rendered or not
- // (see manager renderAction). We also override canvasAction values in
- // Excalidraw package index.tsx.
- export type CanvasActions = Partial<{
- changeViewBackgroundColor: boolean;
- clearCanvas: boolean;
- export: false | ExportOpts;
- loadScene: boolean;
- saveToActiveFile: boolean;
- toggleTheme: boolean | null;
- saveAsImage: boolean;
- }>;
- export type UIOptions = Partial<{
- dockedSidebarBreakpoint: number;
- canvasActions: CanvasActions;
- tools: {
- image: boolean;
- };
- /** @deprecated does nothing. Will be removed in 0.15 */
- welcomeScreen?: boolean;
- }>;
- export type AppProps = Merge<
- ExcalidrawProps,
- {
- UIOptions: Merge<
- UIOptions,
- {
- canvasActions: Required<CanvasActions> & { export: ExportOpts };
- }
- >;
- detectScroll: boolean;
- handleKeyboardGlobally: boolean;
- isCollaborating: boolean;
- children?: React.ReactNode;
- aiEnabled: boolean;
- }
- >;
- /** A subset of App class properties that we need to use elsewhere
- * in the app, eg Manager. Factored out into a separate type to keep DRY. */
- export type AppClassProperties = {
- props: AppProps;
- interactiveCanvas: HTMLCanvasElement | null;
- /** static canvas */
- canvas: HTMLCanvasElement;
- focusContainer(): void;
- library: Library;
- imageCache: Map<
- FileId,
- {
- image: HTMLImageElement | Promise<HTMLImageElement>;
- mimeType: ValueOf<typeof IMAGE_MIME_TYPES>;
- }
- >;
- files: BinaryFiles;
- device: App["device"];
- scene: App["scene"];
- pasteFromClipboard: App["pasteFromClipboard"];
- id: App["id"];
- onInsertElements: App["onInsertElements"];
- onExportImage: App["onExportImage"];
- lastViewportPosition: App["lastViewportPosition"];
- scrollToContent: App["scrollToContent"];
- addFiles: App["addFiles"];
- addElementsFromPasteOrLibrary: App["addElementsFromPasteOrLibrary"];
- togglePenMode: App["togglePenMode"];
- setActiveTool: App["setActiveTool"];
- setOpenDialog: App["setOpenDialog"];
- insertEmbeddableElement: App["insertEmbeddableElement"];
- onMagicframeToolSelect: App["onMagicframeToolSelect"];
- };
- export type PointerDownState = Readonly<{
- // The first position at which pointerDown happened
- origin: Readonly<{ x: number; y: number }>;
- // Same as "origin" but snapped to the grid, if grid is on
- originInGrid: Readonly<{ x: number; y: number }>;
- // Scrollbar checks
- scrollbars: ReturnType<typeof isOverScrollBars>;
- // The previous pointer position
- lastCoords: { x: number; y: number };
- // map of original elements data
- originalElements: Map<string, NonDeleted<ExcalidrawElement>>;
- resize: {
- // Handle when resizing, might change during the pointer interaction
- handleType: MaybeTransformHandleType;
- // This is determined on the initial pointer down event
- isResizing: boolean;
- // This is determined on the initial pointer down event
- offset: { x: number; y: number };
- // This is determined on the initial pointer down event
- arrowDirection: "origin" | "end";
- // This is a center point of selected elements determined on the initial pointer down event (for rotation only)
- center: { x: number; y: number };
- };
- hit: {
- // The element the pointer is "hitting", is determined on the initial
- // pointer down event
- element: NonDeleted<ExcalidrawElement> | null;
- // The elements the pointer is "hitting", is determined on the initial
- // pointer down event
- allHitElements: NonDeleted<ExcalidrawElement>[];
- // This is determined on the initial pointer down event
- wasAddedToSelection: boolean;
- // Whether selected element(s) were duplicated, might change during the
- // pointer interaction
- hasBeenDuplicated: boolean;
- hasHitCommonBoundingBoxOfSelectedElements: boolean;
- };
- withCmdOrCtrl: boolean;
- drag: {
- // Might change during the pointer interaction
- hasOccurred: boolean;
- // Might change during the pointer interaction
- offset: { x: number; y: number } | null;
- };
- // We need to have these in the state so that we can unsubscribe them
- eventListeners: {
- // It's defined on the initial pointer down event
- onMove: null | ReturnType<typeof throttleRAF>;
- // It's defined on the initial pointer down event
- onUp: null | ((event: PointerEvent) => void);
- // It's defined on the initial pointer down event
- onKeyDown: null | ((event: KeyboardEvent) => void);
- // It's defined on the initial pointer down event
- onKeyUp: null | ((event: KeyboardEvent) => void);
- };
- boxSelection: {
- hasOccurred: boolean;
- };
- }>;
- export type UnsubscribeCallback = () => void;
- export type ExcalidrawImperativeAPI = {
- updateScene: InstanceType<typeof App>["updateScene"];
- updateLibrary: InstanceType<typeof Library>["updateLibrary"];
- resetScene: InstanceType<typeof App>["resetScene"];
- getSceneElementsIncludingDeleted: InstanceType<
- typeof App
- >["getSceneElementsIncludingDeleted"];
- history: {
- clear: InstanceType<typeof App>["resetHistory"];
- };
- scrollToContent: InstanceType<typeof App>["scrollToContent"];
- getSceneElements: InstanceType<typeof App>["getSceneElements"];
- getAppState: () => InstanceType<typeof App>["state"];
- getFiles: () => InstanceType<typeof App>["files"];
- registerAction: (action: Action) => void;
- refresh: InstanceType<typeof App>["refresh"];
- setToast: InstanceType<typeof App>["setToast"];
- addFiles: (data: BinaryFileData[]) => void;
- id: string;
- setActiveTool: InstanceType<typeof App>["setActiveTool"];
- setCursor: InstanceType<typeof App>["setCursor"];
- resetCursor: InstanceType<typeof App>["resetCursor"];
- toggleSidebar: InstanceType<typeof App>["toggleSidebar"];
- /**
- * Disables rendering of frames (including element clipping), but currently
- * the frames are still interactive in edit mode. As such, this API should be
- * used in conjunction with view mode (props.viewModeEnabled).
- */
- updateFrameRendering: InstanceType<typeof App>["updateFrameRendering"];
- onChange: (
- callback: (
- elements: readonly ExcalidrawElement[],
- appState: AppState,
- files: BinaryFiles,
- ) => void,
- ) => UnsubscribeCallback;
- onPointerDown: (
- callback: (
- activeTool: AppState["activeTool"],
- pointerDownState: PointerDownState,
- event: React.PointerEvent<HTMLElement>,
- ) => void,
- ) => UnsubscribeCallback;
- onPointerUp: (
- callback: (
- activeTool: AppState["activeTool"],
- pointerDownState: PointerDownState,
- event: PointerEvent,
- ) => void,
- ) => UnsubscribeCallback;
- onScrollChange: (
- callback: (scrollX: number, scrollY: number, zoom: Zoom) => void,
- ) => UnsubscribeCallback;
- onUserFollow: (
- callback: (payload: OnUserFollowedPayload) => void,
- ) => UnsubscribeCallback;
- };
- export type Device = Readonly<{
- viewport: {
- isMobile: boolean;
- isLandscape: boolean;
- };
- editor: {
- isMobile: boolean;
- canFitSidebar: boolean;
- };
- isTouchScreen: boolean;
- }>;
- type FrameNameBounds = {
- x: number;
- y: number;
- width: number;
- height: number;
- angle: number;
- };
- export type FrameNameBoundsCache = {
- get: (
- frameElement: ExcalidrawFrameLikeElement | ExcalidrawMagicFrameElement,
- ) => FrameNameBounds | null;
- _cache: Map<
- string,
- FrameNameBounds & {
- zoom: AppState["zoom"]["value"];
- versionNonce: ExcalidrawFrameLikeElement["versionNonce"];
- }
- >;
- };
- export type KeyboardModifiersObject = {
- ctrlKey: boolean;
- shiftKey: boolean;
- altKey: boolean;
- metaKey: boolean;
- };
- export type Primitive =
- | number
- | string
- | boolean
- | bigint
- | symbol
- | null
- | undefined;
- export type JSONValue = string | number | boolean | null | object;
- export type EmbedsValidationStatus = Map<
- ExcalidrawIframeLikeElement["id"],
- boolean
- >;
- export type ElementsPendingErasure = Set<ExcalidrawElement["id"]>;
|