diff --git a/excalidraw-app/index.tsx b/excalidraw-app/index.tsx index 5b2e2981..7708fc19 100644 --- a/excalidraw-app/index.tsx +++ b/excalidraw-app/index.tsx @@ -691,7 +691,7 @@ const ExcalidrawWrapper = () => { })} > { super(props); const defaultAppState = getDefaultAppState(); const { - excalidrawRef, + excalidrawAPI, viewModeEnabled = false, zenModeEnabled = false, gridModeEnabled = false, @@ -571,14 +570,8 @@ class App extends React.Component { this.rc = rough.canvas(this.canvas); this.renderer = new Renderer(this.scene); - if (excalidrawRef) { - const readyPromise = - ("current" in excalidrawRef && excalidrawRef.current?.readyPromise) || - resolvablePromise(); - + if (excalidrawAPI) { const api: ExcalidrawImperativeAPI = { - ready: true, - readyPromise, updateScene: this.updateScene, updateLibrary: this.library.updateLibrary, addFiles: this.addFiles, @@ -603,12 +596,11 @@ class App extends React.Component { onPointerDown: (cb) => this.onPointerDownEmitter.on(cb), onPointerUp: (cb) => this.onPointerUpEmitter.on(cb), } as const; - if (typeof excalidrawRef === "function") { - excalidrawRef(api); + if (typeof excalidrawAPI === "function") { + excalidrawAPI(api); } else { - excalidrawRef.current = api; + console.error("excalidrawAPI should be a function!"); } - readyPromise.resolve(api); } this.excalidrawContainerValue = { diff --git a/src/packages/excalidraw/CHANGELOG.md b/src/packages/excalidraw/CHANGELOG.md index 7f21b9cc..a001e242 100644 --- a/src/packages/excalidraw/CHANGELOG.md +++ b/src/packages/excalidraw/CHANGELOG.md @@ -15,6 +15,14 @@ Please add the latest change on the top under the correct section. ### Features +- Support `excalidrawAPI` prop for accessing the Excalidraw API [#7251](https://github.com/excalidraw/excalidraw/pull/7251). + +#### BREAKING CHANGE + +- The `Ref` support has been removed in v0.17.0 so if you are using refs, please update the integration to use the [`excalidrawAPI`](http://localhost:3003/docs/@excalidraw/excalidraw/api/props/excalidraw-api) + +- Additionally `ready` and `readyPromise` from the API have been discontinued. These APIs were found to be superfluous, and as part of the effort to streamline the APIs and maintain simplicity, they were removed in version v0.17.0. + - Export [`getCommonBounds`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/utils#getcommonbounds) helper from the package [#7247](https://github.com/excalidraw/excalidraw/pull/7247). - Support frames via programmatic API [#7205](https://github.com/excalidraw/excalidraw/pull/7205). diff --git a/src/packages/excalidraw/example/App.tsx b/src/packages/excalidraw/example/App.tsx index 15744427..974bbb7e 100644 --- a/src/packages/excalidraw/example/App.tsx +++ b/src/packages/excalidraw/example/App.tsx @@ -665,7 +665,9 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
setExcalidrawAPI(api)} + excalidrawAPI={(api: ExcalidrawImperativeAPI) => + setExcalidrawAPI(api) + } initialData={initialStatePromiseRef.current.promise} onChange={(elements, state) => { console.info("Elements :", elements, "State : ", state); diff --git a/src/packages/excalidraw/index.tsx b/src/packages/excalidraw/index.tsx index ac12c65a..2458c112 100644 --- a/src/packages/excalidraw/index.tsx +++ b/src/packages/excalidraw/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, forwardRef } from "react"; +import React, { useEffect } from "react"; import { InitializeApp } from "../../components/InitializeApp"; import App from "../../components/App"; import { isShallowEqual } from "../../utils"; @@ -6,7 +6,7 @@ import { isShallowEqual } from "../../utils"; import "../../css/app.scss"; import "../../css/styles.scss"; -import { AppProps, ExcalidrawAPIRefValue, ExcalidrawProps } from "../../types"; +import { AppProps, ExcalidrawProps } from "../../types"; import { defaultLang } from "../../i18n"; import { DEFAULT_UI_OPTIONS } from "../../constants"; import { Provider } from "jotai"; @@ -20,7 +20,7 @@ const ExcalidrawBase = (props: ExcalidrawProps) => { const { onChange, initialData, - excalidrawRef, + excalidrawAPI, isCollaborating = false, onPointerUpdate, renderTopRightUI, @@ -95,7 +95,7 @@ const ExcalidrawBase = (props: ExcalidrawProps) => { { ); }; -type PublicExcalidrawProps = Omit; - -const areEqual = ( - prevProps: PublicExcalidrawProps, - nextProps: PublicExcalidrawProps, -) => { +const areEqual = (prevProps: ExcalidrawProps, nextProps: ExcalidrawProps) => { // short-circuit early if (prevProps.children !== nextProps.children) { return false; @@ -189,12 +184,7 @@ const areEqual = ( return isUIOptionsSame && isShallowEqual(prev, next); }; -const forwardedRefComp = forwardRef< - ExcalidrawAPIRefValue, - PublicExcalidrawProps ->((props, ref) => ); - -export const Excalidraw = React.memo(forwardedRefComp, areEqual); +export const Excalidraw = React.memo(ExcalidrawBase, areEqual); Excalidraw.displayName = "Excalidraw"; export { diff --git a/src/tests/packages/events.test.tsx b/src/tests/packages/events.test.tsx index 231af579..907dc7a8 100644 --- a/src/tests/packages/events.test.tsx +++ b/src/tests/packages/events.test.tsx @@ -15,7 +15,9 @@ describe("event callbacks", () => { beforeEach(async () => { const excalidrawAPIPromise = resolvablePromise(); await render( - excalidrawAPIPromise.resolve(api as any)} />, + excalidrawAPIPromise.resolve(api as any)} + />, ); excalidrawAPI = await excalidrawAPIPromise; }); diff --git a/src/tests/tool.test.tsx b/src/tests/tool.test.tsx index 84a43c6b..41ffbbf8 100644 --- a/src/tests/tool.test.tsx +++ b/src/tests/tool.test.tsx @@ -14,7 +14,9 @@ describe("setActiveTool()", () => { beforeEach(async () => { const excalidrawAPIPromise = resolvablePromise(); await render( - excalidrawAPIPromise.resolve(api as any)} />, + excalidrawAPIPromise.resolve(api as any)} + />, ); excalidrawAPI = await excalidrawAPIPromise; }); diff --git a/src/types.ts b/src/types.ts index 3fe0f2d7..c1290c8f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -23,7 +23,7 @@ import { LinearElementEditor } from "./element/linearElementEditor"; import { SuggestedBinding } from "./element/binding"; import { ImportedDataState } from "./data/types"; import type App from "./components/App"; -import type { ResolvablePromise, throttleRAF } from "./utils"; +import type { throttleRAF } from "./utils"; import { Spreadsheet } from "./charts"; import { Language } from "./i18n"; import { ClipboardData } from "./clipboard"; @@ -34,7 +34,7 @@ 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, ForwardRef, ValueOf } from "./utility-types"; +import { Merge, ValueOf } from "./utility-types"; export type Point = Readonly; @@ -362,15 +362,6 @@ export type LibraryItemsSource = | Promise; // ----------------------------------------------------------------------------- -// NOTE ready/readyPromise props are optional for host apps' sake (our own -// implem guarantees existence) -export type ExcalidrawAPIRefValue = - | ExcalidrawImperativeAPI - | { - readyPromise?: ResolvablePromise; - ready?: false; - }; - export type ExcalidrawInitialDataState = Merge< ImportedDataState, { @@ -390,7 +381,7 @@ export interface ExcalidrawProps { | ExcalidrawInitialDataState | null | Promise; - excalidrawRef?: ForwardRef; + excalidrawAPI?: (api: ExcalidrawImperativeAPI) => void; isCollaborating?: boolean; onPointerUpdate?: (payload: { pointer: { x: number; y: number; tool: "pointer" | "laser" }; @@ -630,8 +621,6 @@ export type ExcalidrawImperativeAPI = { refresh: InstanceType["refresh"]; setToast: InstanceType["setToast"]; addFiles: (data: BinaryFileData[]) => void; - readyPromise: ResolvablePromise; - ready: true; id: string; setActiveTool: InstanceType["setActiveTool"]; setCursor: InstanceType["setCursor"];