From cee00767df5f94759e7911082f049160d65befc7 Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Fri, 10 Nov 2023 15:33:43 +0530 Subject: [PATCH] feat: support excalidrawAPI and remove refs support (#7251) * feat: support excalidrawAPI and remove refs support * update changelog * remove ready and readyPromise * update changelog * update changelog --- excalidraw-app/index.tsx | 2 +- src/components/App.tsx | 18 +++++------------- src/packages/excalidraw/CHANGELOG.md | 8 ++++++++ src/packages/excalidraw/example/App.tsx | 4 +++- src/packages/excalidraw/index.tsx | 22 ++++++---------------- src/tests/packages/events.test.tsx | 4 +++- src/tests/tool.test.tsx | 4 +++- src/types.ts | 17 +++-------------- 8 files changed, 32 insertions(+), 47 deletions(-) diff --git a/excalidraw-app/index.tsx b/excalidraw-app/index.tsx index 5b2e29818c..7708fc1901 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 7f21b9cc3b..a001e24269 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 1574442713..974bbb7efd 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 ac12c65afd..2458c112de 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 231af57999..907dc7a8e0 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 84a43c6b5e..41ffbbf8ed 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 3fe0f2d72e..c1290c8f15 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"];