From 90fd4a95dfd7b0876954916b66a443f27d673fdd Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Sun, 4 Apr 2021 22:05:02 +0530 Subject: [PATCH] =?UTF-8?q?refactor:=20=20rename=20setCanvasOffsets=20to?= =?UTF-8?q?=20refresh=20and=20release=20@excalidraw/excalidraw=20v0.6.0=20?= =?UTF-8?q?=F0=9F=8E=89=20=20(#3398)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: Release @excalidraw/excalidraw v0.6.0 * update * fix * Update src/packages/excalidraw/README.md Co-authored-by: David Luzar * rename setCanvasOffsets to refresh * fix * fix * typo fix Co-authored-by: David Luzar --- src/components/App.tsx | 6 +- src/packages/excalidraw/CHANGELOG.md | 8 +- src/packages/excalidraw/README.md | 149 ++++++++++++++----------- src/packages/excalidraw/README_NEXT.md | 2 +- src/packages/excalidraw/package.json | 2 +- 5 files changed, 94 insertions(+), 73 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index 14df48cc..d5c3c0a5 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -274,7 +274,7 @@ export type ExcalidrawImperativeAPI = { setScrollToContent: InstanceType["setScrollToContent"]; getSceneElements: InstanceType["getSceneElements"]; getAppState: () => InstanceType["state"]; - setCanvasOffsets: InstanceType["setCanvasOffsets"]; + refresh: InstanceType["refresh"]; importLibrary: InstanceType["importLibraryFromUrl"]; setToastMessage: InstanceType["setToastMessage"]; readyPromise: ResolvablePromise; @@ -335,7 +335,7 @@ class App extends React.Component { setScrollToContent: this.setScrollToContent, getSceneElements: this.getSceneElements, getAppState: () => this.state, - setCanvasOffsets: this.setCanvasOffsets, + refresh: this.refresh, importLibrary: this.importLibraryFromUrl, setToastMessage: this.setToastMessage, } as const; @@ -4107,7 +4107,7 @@ class App extends React.Component { } }; - public setCanvasOffsets = () => { + public refresh = () => { this.setState({ ...this.getCanvasOffsets() }); }; diff --git a/src/packages/excalidraw/CHANGELOG.md b/src/packages/excalidraw/CHANGELOG.md index dbd3437c..c0aa17d8 100644 --- a/src/packages/excalidraw/CHANGELOG.md +++ b/src/packages/excalidraw/CHANGELOG.md @@ -12,7 +12,7 @@ The change should be grouped under one of the below section and must contain PR Please add the latest change on the top under the correct section. --> -## Unreleased +## 0.6.0 (2021-04-04) ## Excalidraw API @@ -36,6 +36,12 @@ Please add the latest change on the top under the correct section. #### BREAKING CHANGE - If you are using script tag to embed excalidraw then the name of the file will have to be updated to `excalidraw.production.min.js` instead of `excalidraw.min.js`. If you want to use dev build you can use `excalidraw.development.js` +### Refactor + +#### BREAKING CHANGE + +- Rename the API `setCanvasOffsets` exposed via [`ref`](https://github.com/excalidraw/excalidraw/blob/master/src/components/App.tsx#L265) to `refresh` [#3398](https://github.com/excalidraw/excalidraw/pull/3398). + --- ## 0.5.0 (2021-03-21) diff --git a/src/packages/excalidraw/README.md b/src/packages/excalidraw/README.md index f8c81fc6..9d31a7a5 100644 --- a/src/packages/excalidraw/README.md +++ b/src/packages/excalidraw/README.md @@ -16,13 +16,13 @@ or via yarn yarn add react react-dom @excalidraw/excalidraw ``` -After installation you will see a folder `excalidraw-assets` in `dist` directory which contains the assets needed for this app. +After installation you will see a folder `excalidraw-assets` and `excalidraw-assets-dev` in `dist` directory which contains the assets needed for this app in prod and dev mode respectively. -Move the folder `excalidraw-assets` to the path where your assets are served. +Move the folder `excalidraw-assets` and `excalidraw-assets-dev` to the path where your assets are served. By default it will try to load the files from `https://unpkg.com/@excalidraw/excalidraw/{currentVersion}/dist/` -If you want to load assets from a different path you can set a variable `window.EXCALIDRAW_ASSET_PATH` to the url from where you want to load the assets. +If you want to load assets from a different path you can set a variable `window.EXCALIDRAW_ASSET_PATH` depending on environment (for example if you have different URL's for dev and prod) to the url from where you want to load the assets. ### Demo @@ -45,33 +45,11 @@ import "./styles.scss"; export default function App() { const excalidrawRef = useRef(null); - const excalidrawWrapperRef = useRef(null); - const [dimensions, setDimensions] = useState({ - width: undefined, - height: undefined, - }); const [viewModeEnabled, setViewModeEnabled] = useState(false); const [zenModeEnabled, setZenModeEnabled] = useState(false); const [gridModeEnabled, setGridModeEnabled] = useState(false); - useEffect(() => { - setDimensions({ - width: excalidrawWrapperRef.current.getBoundingClientRect().width, - height: excalidrawWrapperRef.current.getBoundingClientRect().height, - }); - const onResize = () => { - setDimensions({ - width: excalidrawWrapperRef.current.getBoundingClientRect().width, - height: excalidrawWrapperRef.current.getBoundingClientRect().height, - }); - }; - - window.addEventListener("resize", onResize); - - return () => window.removeEventListener("resize", onResize); - }, [excalidrawWrapperRef]); - const updateScene = () => { const sceneData = { elements: [ @@ -144,13 +122,11 @@ export default function App() { Grid mode -
+
+ onChange={(elements, state) => { console.log("Elements :", elements, "State : ", state) } onPointerUpdate={(payload) => console.log(payload)} @@ -171,6 +147,8 @@ To view the full example visit :point_down: [![Edit excalidraw](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/excalidraw-ehlz3?fontsize=14&hidenavigation=1&theme=dark) + + Since Excalidraw doesn't support server side rendering yet so you will have to make sure the component is rendered once host is mounted. ```js @@ -184,13 +162,31 @@ export default function IndexPage() { } ``` - +The `types` are available at `@excalidraw/excalidraw/types`, you can view [example for typescript](https://codesandbox.io/s/excalidraw-types-9h2dm) #### In Browser To use it in a browser directly: -You will need to make sure `react`, `react-dom` is available as shown below. +For development use :point_down: + +```js + +``` + +For production use :point_down: + +```js + +``` + +You will need to make sure `react`, `react-dom` is available as shown in the below example. For prod please use the production versions of `react`, `react-dom`.
View Example @@ -205,7 +201,7 @@ You will need to make sure `react`, `react-dom` is available as shown below. @@ -226,33 +222,11 @@ import InitialData from "./initialData"; const App = () => { const excalidrawRef = React.useRef(null); - const excalidrawWrapperRef = React.useRef(null); - const [dimensions, setDimensions] = React.useState({ - width: undefined, - height: undefined, - }); const [viewModeEnabled, setViewModeEnabled] = React.useState(false); const [zenModeEnabled, setZenModeEnabled] = React.useState(false); const [gridModeEnabled, setGridModeEnabled] = React.useState(false); - React.useEffect(() => { - setDimensions({ - width: excalidrawWrapperRef.current.getBoundingClientRect().width, - height: excalidrawWrapperRef.current.getBoundingClientRect().height, - }); - const onResize = () => { - setDimensions({ - width: excalidrawWrapperRef.current.getBoundingClientRect().width, - height: excalidrawWrapperRef.current.getBoundingClientRect().height, - }); - }; - - window.addEventListener("resize", onResize); - - return () => window.removeEventListener("resize", onResize); - }, [excalidrawWrapperRef]); - const updateScene = () => { const sceneData = { elements: [ @@ -345,9 +319,6 @@ const App = () => { ref: excalidrawWrapperRef, }, React.createElement(Excalidraw.default, { - ref: excalidrawRef, - width: dimensions.width, - height: dimensions.height, initialData: InitialData, onChange: (elements, state) => console.log("Elements :", elements, "State : ", state), @@ -376,8 +347,6 @@ To view the full example visit :point_down: | Name | Type | Default | Description | | --- | --- | --- | --- | -| [`width`](#width) | Number | `window.innerWidth` | The width of Excalidraw component | -| [`height`](#height) | Number | `window.innerHeight` | The height of Excalidraw component | | [`onChange`](#onChange) | Function | | This callback is triggered whenever the component updates due to any change. This callback will receive the excalidraw elements and the current app state. | | [`initialData`](#initialData) |
{elements?: ExcalidrawElement[], appState?: AppState } 
| null | The initial data with which app loads. | | [`ref`](#ref) | [`createRef`](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) or [`callbackRef`](https://reactjs.org/docs/refs-and-the-dom.html#callback-refs) or
{ current: { readyPromise: resolvablePromise } }
| | Ref to be passed to Excalidraw | @@ -387,20 +356,18 @@ To view the full example visit :point_down: | [`onExportToBackend`](#onExportToBackend) | Function | | Callback triggered when link button is clicked on export dialog | | [`langCode`](#langCode) | string | `en` | Language code string | | [`renderFooter `](#renderFooter) | Function | | Function that renders custom UI footer | +| [`renderCustomStats`](#renderCustomStats) | Function | | Function that can be used to render custom stats on the stats dialog. | | [`viewModeEnabled`](#viewModeEnabled) | boolean | | This implies if the app is in view mode. | | [`zenModeEnabled`](#zenModeEnabled) | boolean | | This implies if the zen mode is enabled | | [`gridModeEnabled`](#gridModeEnabled) | boolean | | This implies if the grid mode is enabled | | [`libraryReturnUrl`](#libraryReturnUrl) | string | | What URL should [libraries.excalidraw.com](https://libraries.excalidraw.com) be installed to | | [`theme`](#theme) | `light` or `dark` | | The theme of the Excalidraw component | | [`name`](#name) | string | | Name of the drawing | +| [`UIOptions`](#UIOptions) |
{ canvasActions:  CanvasActions }
| [DEFAULT UI OPTIONS](https://github.com/excalidraw/excalidraw/blob/master/src/constants.ts#L129) | To customise UI options. Currently we support customising [`canvas actions`](#canvasActions) | -#### `width` +### Dimensions of Excalidraw -This props defines the `width` of the Excalidraw component. Defaults to `window.innerWidth` if not passed. - -#### `height` - -This props defines the `height` of the Excalidraw component. Defaults to `window.innerHeight` if not passed. +Excalidraw takes `100%` of `width` and `height` of the containing block so make sure the container in which you render Excalidraw has non zero dimensions. #### `onChange` @@ -472,7 +439,9 @@ You can pass a `ref` when you want to access some excalidraw APIs. We expose the | getAppState |
 () => AppState
| Returns current appState | | history | `{ clear: () => void }` | This is the history API. `history.clear()` will clear the history | | setScrollToContent |
 (ExcalidrawElement[]) => void 
| Scroll to the nearest element to center | -| setCanvasOffsets | `() => void` | Updates the offsets for the Excalidraw component so that the coordinates are computed correctly (for example the cursor position). You should call this API when your app changes the dimensions/position of the Excalidraw container, such as when toggling a sidebar. You don't have to call this when the position is changed on page scroll (we handled that ourselves). | +| refresh | `() => void` | Updates the offsets for the Excalidraw component so that the coordinates are computed correctly (for example the cursor position). You don't have to call this when the position is changed on page scroll or when the excalidraw container resizes (we handle that ourselves). For any other cases if the position of excalidraw is updated (example due to scroll on parent container and not page scroll) you should call this API. | +| [importLibrary](#importlibrary) | `(url: string, token?: string) => void` | Imports library from given URL | +| setToastMessage | `(message: string) => void` | This API can be used to show the toast with custom message. | #### `readyPromise` @@ -531,6 +500,10 @@ import { defaultLang, languages } from "@excalidraw/excalidraw"; A function that renders (returns JSX) custom UI footer. For example, you can use this to render a language picker that was previously being rendered by Excalidraw itself (for now, you'll need to implement your own language picker). +#### `renderCustomStats` + +A function that can be used to render custom stats (returns JSX) in the nerd stats dialog. For example you can use this prop to render the size of the elements in the storage. + #### `viewModeEnabled` This prop indicates whether the app is in `view mode`. When supplied, the value takes precedence over `intialData.appState.viewModeEnabled`, the `view mode` will be fully controlled by the host app, and users won't be able to toggle it from within the app. @@ -545,7 +518,7 @@ This prop indicates whether the shows the grid. When supplied, the value takes p #### `libraryReturnUrl` -If supplied, this URL will be used when user tries to install a library from [libraries.excalidraw.com](https://libraries.excalidraw.com). Defaults to `window.location.origin`. To install the libraries in the same tab from which it was opened, you need to set `window.name` (to any alphanumeric string) — if it's not set it will open in a new tab. +If supplied, this URL will be used when user tries to install a library from [libraries.excalidraw.com](https://libraries.excalidraw.com). Defaults to `window.location.origin + window.location.pathname`. To install the libraries in the same tab from which it was opened, you need to set `window.name` (to any alphanumeric string) — if it's not set it will open in a new tab. #### `theme` @@ -555,10 +528,52 @@ This prop controls Excalidraw's theme. When supplied, the value takes precedence This prop sets the name of the drawing which will be used when exporting the drawing. When supplied, the value takes precedence over `intialData.appState.name`, the `name` will be fully controlled by host app and the users won't be able to edit from within Excalidraw. +### `UIOptions` + +This prop can be used to customise UI of Excalidraw. Currently we support customising only [`canvasActions`](#canvasActions). It accepts the below parameters + +
+{ canvasActions:  CanvasActions }
+
+ +#### canvasActions + +| Attribute | Type | Default | Description | +| --- | --- | --- | --- | +| `changeViewBackgroundColor` | boolean | true | Implies whether to show `Background color picker` | +| `clearCanvas` | boolean | true | Implies whether to show `Clear canvas button` | +| `export` | boolean | true | Implies whether to show `Export button` | +| `loadScene` | boolean | true | Implies whether to show `Load button` | +| `saveAsScene` | boolean | true | Implies whether to show `Save as button` | +| `saveScene` | boolean | true | Implies whether to show `Save button` | +| `theme` | boolean | true | Implies whether to show `Theme toggle` | + ### Does it support collaboration ? No Excalidraw package doesn't come with collaboration, since this would have different implementations on the consumer so we expose the API's which you can use to communicate with Excalidraw as mentioned above. If you are interested in understanding how Excalidraw does it you can check it [here](https://github.com/excalidraw/excalidraw/blob/master/src/excalidraw-app/index.tsx). +### importLibrary + +Imports library from given URL. You should call this on `hashchange`, passing the `addLibrary` value if you detect it as shown below. Optionally pass a CSRF `token` to skip prompting during installation (retrievable via `token` key from the url coming from [https://libraries.excalidraw.com](https://libraries.excalidraw.com/)). + +```js +useEffect(() => { + const onHashChange = () => { + const hash = new URLSearchParams(window.location.hash.slice(1)); + const libraryUrl = hash.get("addLibrary"); + if (libraryUrl) { + excalidrawRef.current.importLibrary(libraryUrl, hash.get("token")); + } + }; + window.addEventListener("hashchange", onHashChange, false); + return () => { + window.removeEventListener("hashchange", onHashChange); + }; +}, []); +``` + +Try out the [Demo](#Demo) to see it in action. + ### Extra API's #### `getSceneVersion` diff --git a/src/packages/excalidraw/README_NEXT.md b/src/packages/excalidraw/README_NEXT.md index 6a3ed9ba..c356864b 100644 --- a/src/packages/excalidraw/README_NEXT.md +++ b/src/packages/excalidraw/README_NEXT.md @@ -440,7 +440,7 @@ You can pass a `ref` when you want to access some excalidraw APIs. We expose the | getAppState |
 () => AppState
| Returns current appState | | history | `{ clear: () => void }` | This is the history API. `history.clear()` will clear the history | | setScrollToContent |
 (ExcalidrawElement[]) => void 
| Scroll to the nearest element to center | -| setCanvasOffsets | `() => void` | Updates the offsets for the Excalidraw component so that the coordinates are computed correctly (for example the cursor position). You don't have to call this when the position is changed on page scroll or when the excalidraw container resizes (we handle that ourselves). For any other cases if the position of excalidraw is updated (example due to scroll on parent container and not page scroll) you should call this API. | +| refresh | `() => void` | Updates the offsets for the Excalidraw component so that the coordinates are computed correctly (for example the cursor position). You don't have to call this when the position is changed on page scroll or when the excalidraw container resizes (we handle that ourselves). For any other cases if the position of excalidraw is updated (example due to scroll on parent container and not page scroll) you should call this API. | | importLibrary | `(url: string, token?: string) => void` | Imports library from given URL. You should call this on `hashchange`, passing the `addLibrary` value if you detect it. Optionally pass a CSRF `token` to skip prompting during installation (retrievable via `token` key from the url coming from [https://libraries.excalidraw.com](https://libraries.excalidraw.com/)). | | setToastMessage | `(message: string) => void` | This API can be used to show the toast with custom message. | diff --git a/src/packages/excalidraw/package.json b/src/packages/excalidraw/package.json index d44ce149..8124d8fc 100644 --- a/src/packages/excalidraw/package.json +++ b/src/packages/excalidraw/package.json @@ -1,6 +1,6 @@ { "name": "@excalidraw/excalidraw", - "version": "0.5.0", + "version": "0.6.0", "main": "main.js", "types": "types/packages/excalidraw/index.d.ts", "files": [