Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@audaos/excalidraw

excalidraw53MIT0.30.4TypeScript support: included

Excalidraw as a React component

excalidraw, excalidraw-embed, react, npm, npm excalidraw

readme

Excalidraw

Excalidraw exported as a component to directly embed in your projects.

Installation

You can use npm

npm install react react-dom @excalidraw/excalidraw

or via yarn

yarn add react react-dom @excalidraw/excalidraw

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 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/dist/

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.

Note

If you don't want to wait for the next stable release and try out the unreleased changes you can use @excalidraw/excalidraw-next.

Demo

Try here.

Usage

Using Web Bundler

If you are using a Web bundler (for instance, Webpack), you can import it as an ES6 module as shown below

<summary>View Example</summary>
import React, { useEffect, useState, useRef } from "react";
import Excalidraw from "@excalidraw/excalidraw";
import InitialData from "./initialData";

import "./styles.scss";

export default function App() {
  const excalidrawRef = useRef(null);

  const [viewModeEnabled, setViewModeEnabled] = useState(false);
  const [zenModeEnabled, setZenModeEnabled] = useState(false);
  const [gridModeEnabled, setGridModeEnabled] = useState(false);

  const updateScene = () => {
    const sceneData = {
      elements: [
        {
          type: "rectangle",
          version: 141,
          versionNonce: 361174001,
          isDeleted: false,
          id: "oDVXy8D6rom3H1-LLH2-f",
          fillStyle: "hachure",
          strokeWidth: 1,
          strokeStyle: "solid",
          roughness: 1,
          opacity: 100,
          angle: 0,
          x: 100.50390625,
          y: 93.67578125,
          strokeColor: "#c92a2a",
          backgroundColor: "transparent",
          width: 186.47265625,
          height: 141.9765625,
          seed: 1968410350,
          groupIds: [],
        },
      ],
      appState: {
        viewBackgroundColor: "#edf2ff",
      },
    };
    excalidrawRef.current.updateScene(sceneData);
  };

  return (
    <div className="App">
      <h1> Excalidraw Example</h1>
      <div className="button-wrapper">
        <button className="update-scene" onClick={updateScene}>
          Update Scene
        </button>
        <button
          className="reset-scene"
          onClick={() => {
            excalidrawRef.current.resetScene();
          }}
        >
          Reset Scene
        </button>
        <label>
          <input
            type="checkbox"
            checked={viewModeEnabled}
            onChange={() => setViewModeEnabled(!viewModeEnabled)}
          />
          View mode
        </label>
        <label>
          <input
            type="checkbox"
            checked={zenModeEnabled}
            onChange={() => setZenModeEnabled(!zenModeEnabled)}
          />
          Zen mode
        </label>
        <label>
          <input
            type="checkbox"
            checked={gridModeEnabled}
            onChange={() => setGridModeEnabled(!gridModeEnabled)}
          />
          Grid mode
        </label>
      </div>
      <div className="excalidraw-wrapper">
        <Excalidraw
          ref={excalidrawRef}
          initialData={InitialData}
          onChange={(elements, state) =>
            console.log("Elements :", elements, "State : ", state)
          }
          onPointerUpdate={(payload) => console.log(payload)}
          onCollabButtonClick={() =>
            window.alert("You clicked on collab button")
          }
          viewModeEnabled={viewModeEnabled}
          zenModeEnabled={zenModeEnabled}
          gridModeEnabled={gridModeEnabled}
        />
      </div>
    </div>
  );
}

To view the full example visit :point_down:

Edit excalidraw

Since Excalidraw doesn't support server side rendering yet, you should render the component once the host is mounted.

import { useState, useEffect } from "react";
export default function IndexPage() {
  const [Comp, setComp] = useState(null);
  useEffect(() => {
    import("@excalidraw/excalidraw").then((comp) => setComp(comp.default));
  }, []);
  return <>{Comp && <Comp />}</>;
}

The types are available at @excalidraw/excalidraw/types, you can view example for typescript

In Browser

To use it in a browser directly:

For development use :point_down:

<script
  type="text/javascript"
  src="https://unpkg.com/@excalidraw/excalidraw/dist/excalidraw.development.js"
></script>

For production use :point_down:

<script
  type="text/javascript"
  src="https://unpkg.com/@excalidraw/excalidraw/dist/excalidraw.production.min.js"
></script>

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.

<summary>View Example</summary>
<!DOCTYPE html>
<html>
  <head>
    <title>Excalidraw in browser</title>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/react@16.14.0/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16.13.1/umd/react-dom.development.js"></script>

    <script
      type="text/javascript"
      src="https://unpkg.com/@excalidraw/excalidraw/dist/excalidraw.development.js"
    ></script>
  </head>

  <body>
    <div class="container">
      <h1>Excalidraw Embed Example</h1>
      <div id="app"></div>
    </div>
    <script type="text/javascript" src="src/index.js"></script>
  </body>
</html>
/*eslint-disable */
import "./styles.css";
import InitialData from "./initialData";

const App = () => {
  const excalidrawRef = React.useRef(null);

  const [viewModeEnabled, setViewModeEnabled] = React.useState(false);
  const [zenModeEnabled, setZenModeEnabled] = React.useState(false);
  const [gridModeEnabled, setGridModeEnabled] = React.useState(false);

  const updateScene = () => {
    const sceneData = {
      elements: [
        {
          type: "rectangle",
          version: 141,
          versionNonce: 361174001,
          isDeleted: false,
          id: "oDVXy8D6rom3H1-LLH2-f",
          fillStyle: "hachure",
          strokeWidth: 1,
          strokeStyle: "solid",
          roughness: 1,
          opacity: 100,
          angle: 0,
          x: 100.50390625,
          y: 93.67578125,
          strokeColor: "#c92a2a",
          backgroundColor: "transparent",
          width: 186.47265625,
          height: 141.9765625,
          seed: 1968410350,
          groupIds: [],
        },
      ],
      appState: {
        viewBackgroundColor: "#edf2ff",
      },
    };
    excalidrawRef.current.updateScene(sceneData);
  };

  return React.createElement(
    React.Fragment,
    null,
    React.createElement(
      "div",
      { className: "button-wrapper" },
      React.createElement(
        "button",
        {
          className: "update-scene",
          onClick: updateScene,
        },
        "Update Scene",
      ),
      React.createElement(
        "button",
        {
          className: "reset-scene",
          onClick: () => excalidrawRef.current.resetScene(),
        },
        "Reset Scene",
      ),
      React.createElement(
        "label",
        null,
        React.createElement("input", {
          type: "checkbox",
          checked: viewModeEnabled,
          onChange: () => setViewModeEnabled(!viewModeEnabled),
        }),
        "View mode",
      ),
      React.createElement(
        "label",
        null,
        React.createElement("input", {
          type: "checkbox",
          checked: zenModeEnabled,
          onChange: () => setZenModeEnabled(!zenModeEnabled),
        }),
        "Zen mode",
      ),
      React.createElement(
        "label",
        null,
        React.createElement("input", {
          type: "checkbox",
          checked: gridModeEnabled,
          onChange: () => setGridModeEnabled(!gridModeEnabled),
        }),
        "Grid mode",
      ),
    ),
    React.createElement(
      "div",
      {
        className: "excalidraw-wrapper",
        ref: excalidrawWrapperRef,
      },
      React.createElement(Excalidraw.default, {
        initialData: InitialData,
        onChange: (elements, state) =>
          console.log("Elements :", elements, "State : ", state),
        onPointerUpdate: (payload) => console.log(payload),
        onCollabButtonClick: () => window.alert("You clicked on collab button"),
        viewModeEnabled: viewModeEnabled,
        zenModeEnabled: zenModeEnabled,
        gridModeEnabled: gridModeEnabled,
      }),
    ),
  );
};

const excalidrawWrapper = document.getElementById("app");

ReactDOM.render(React.createElement(App), excalidrawWrapper);

To view the full example visit :point_down:

Edit excalidraw-in-browser

Customizing styles

Excalidraw is using CSS variables to style certain components. To override them, you should set your own on the .excalidraw and .excalidraw.theme--dark (for dark mode variables) selectors.

Make sure the selector has higher specificity, e.g. by prefixing it with your app's selector:

.your-app .excalidraw {
  --color-primary: red;
}
.your-app .excalidraw.theme--dark {
  --color-primary: pink;
}

Most notably, you can customize the primary colors, by overriding these variables:

  • --color-primary
  • --color-primary-darker
  • --color-primary-darkest
  • --color-primary-light
  • --color-primary-contrast-offset — a slightly darker (in light mode), or lighter (in dark mode) --color-primary color to fix contrast issues (see Chubb illusion). It will fall back to --color-primary if not present.

For a complete list of variables, check theme.scss, though most of them will not make sense to override.

Props

Name Type Default Description
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
{elements?: ExcalidrawElement[], appState?: AppState } 
null The initial data with which app loads.
ref createRef | useRef | callbackRef |
{ current: { readyPromise: resolvablePromise } }
| Ref to be passed to Excalidraw
onCollabButtonClick Function | Callback to be triggered when the collab button is clicked
isCollaborating boolean | This implies if the app is in collaboration mode
onPointerUpdate Function | Callback triggered when mouse pointer is updated.
langCode string en Language code string
renderTopRightUI Function | Function that renders custom UI in top right corner
renderFooter Function | Function that renders custom UI footer
renderCustomStats Function | Function that can be used to render custom stats on the stats dialog.
viewModeEnabled boolean | This implies if the app is in view mode.
zenModeEnabled boolean | This implies if the zen mode is enabled
gridModeEnabled boolean | This implies if the grid mode is enabled
libraryReturnUrl string | What URL should libraries.excalidraw.com be installed to
theme THEME.LIGHT | THEME.LIGHT THEME.LIGHT The theme of the Excalidraw component
name string | Name of the drawing
UIOptions
{ canvasActions:  CanvasActions }
DEFAULT UI OPTIONS To customise UI options. Currently we support customising canvas actions
onPaste
(data: ClipboardData, event: ClipboardEvent | null) => boolean
| Callback to be triggered if passed when the something is pasted in to the scene
detectScroll boolean true Indicates whether to update the offsets when nearest ancestor is scrolled.
handleKeyboardGlobally boolean false Indicates whether to bind the keyboard events to document.
onLibraryChange
(items: LibraryItems) => void | Promise<any> 
| The callback if supplied is triggered when the library is updated and receives the library items.
autoFocus boolean false Implies whether to focus the Excalidraw component on page load
generateIdForFile `(file: File) => string Promise<string>` Allows you to override id generation for files added on canvas
onLinkOpen
(element: NonDeletedExcalidrawElement, event: CustomEvent) 
| This prop if passed will be triggered when link of an element is clicked

Dimensions of Excalidraw

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

Every time component updates, this callback if passed will get triggered and has the below signature.

(excalidrawElements, appState, files) => void;

1.excalidrawElements: Array of excalidrawElements in the scene.

2.appState: AppState of the scene.

  1. files: The [BinaryFiles](BinaryFiles which are added to the scene.

Here you can try saving the data to your backend or local storage for example.

initialData

This helps to load Excalidraw with initialData. It must be an object or a promise which resolves to an object containing the below optional fields.

Name Type Description
elements ExcalidrawElement[] The elements with which Excalidraw should be mounted.
appState AppState The App state with which Excalidraw should be mounted.
scrollToContent boolean This attribute implies whether to scroll to the nearest element to center once Excalidraw is mounted. By default, it will not scroll the nearest element to the center. Make sure you pass initialData.appState.scrollX and initialData.appState.scrollY when scrollToContent is false so that scroll positions are retained
libraryItems LibraryItems This library items with which Excalidraw should be mounted.
files BinaryFiles The files added to the scene.
{
  "elements": [
    {
      "type": "rectangle",
      "version": 141,
      "versionNonce": 361174001,
      "isDeleted": false,
      "id": "oDVXy8D6rom3H1-LLH2-f",
      "fillStyle": "hachure",
      "strokeWidth": 1,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 100.50390625,
      "y": 93.67578125,
      "strokeColor": "#000000",
      "backgroundColor": "transparent",
      "width": 186.47265625,
      "height": 141.9765625,
      "seed": 1968410350,
      "groupIds": []
    }
  ],
  "appState": { "zenModeEnabled": true, "viewBackgroundColor": "#AFEEEE" }
}

You might want to use this when you want to load excalidraw with some initial elements and app state.

ref

You can pass a ref when you want to access some excalidraw APIs. We expose the below APIs:

API signature Usage
ready boolean This is set to true once Excalidraw is rendered
readyPromise resolvablePromise This promise will be resolved with the api once excalidraw has rendered. This will be helpful when you want do some action on the host app once this promise resolves. For this to work you will have to pass ref as shown here
updateScene
(scene: sceneData) => void 
updates the scene with the sceneData
addFiles
(files: BinaryFileData) => void 
add files data to the appState
resetScene ({ resetLoadingState: boolean }) => void Resets the scene. If resetLoadingState is passed as true then it will also force set the loading state to false.
getSceneElementsIncludingDeleted
 () => ExcalidrawElement[]
Returns all the elements including the deleted in the scene
getSceneElements
 () => ExcalidrawElement[]
Returns all the elements excluding the deleted in the scene
getAppState
 () => AppState
Returns current appState
history { clear: () => void } This is the history API. history.clear() will clear the history
scrollToContent
 (target?: ExcalidrawElement | ExcalidrawElement[]) => void 
Scroll the nearest element out of the elements supplied to the center. Defaults to the elements on the scene.
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
setToastMessage (message: string) => void This API can be used to show the toast with custom message.
id string Unique ID for the excalidraw component.
getFiles
() => files 
This API can be used to get the files present in the scene. It may contain files that aren't referenced by any element, so if you're persisting the files to a storage, you should compare them against stored elements.

readyPromise

const excalidrawRef = { current: { readyPromise: resolvablePromise}}

Since plain object is passed as a ref, the readyPromise is resolved as soon as the component is mounted. Most of the time you will not need this unless you have a specific use case where you can't pass the ref in the react way and want to do some action on the host when this promise resolves. You can check the example for the usage.

updateScene

(scene: sceneData) => void

You can use this function to update the scene with the sceneData. It accepts the below attributes.

Name Type Description
elements ImportedDataState["elements"] The elements to be updated in the scene
appState ImportedDataState["appState"] The appState to be updated in the scene.
collaborators
Map<string, Collaborator>
The list of collaborators to be updated in the scene.
commitToHistory boolean Implies if the history (undo/redo) should be recorded. Defaults to false.
libraryItems LibraryItems The libraryItems to be update in the scene.

addFiles

(files: BinaryFileData) => void 

Adds supplied files data to the appState.files cache on top of existing files present in the cache.

onCollabButtonClick

This callback is triggered when clicked on the collab button in excalidraw. If not supplied, the collab dialog button is not rendered.

isCollaborating

This prop indicates if the app is in collaboration mode.

onPointerUpdate

This callback is triggered when mouse pointer is updated.

({ x, y }, button, pointersMap}) => void;

1.{x, y}: Pointer coordinates

2.button: The position of the button. This will be one of ["down", "up"]

3.pointersMap: pointers map of the scene

(exportedElements, appState, canvas) => void
  1. exportedElements: An array of non deleted elements which needs to be exported.
  2. appState: AppState of the scene.
  3. canvas: The HTMLCanvasElement of the scene.

langCode

Determines the language of the UI. It should be one of the available language codes. Defaults to en (English). We also export default language and supported languages which you can import as shown below.

import { defaultLang, languages } from "@excalidraw/excalidraw";
name type
defaultLang string
languages Language[]

renderTopRightUI

(isMobile: boolean, appState: AppState) => JSX

A function returning JSX to render custom UI in the top right corner of the app.

renderFooter

(isMobile: boolean, appState: AppState) => JSX

A function returning JSX to render 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.

zenModeEnabled

This prop indicates whether the app is in zen mode. When supplied, the value takes precedence over intialData.appState.zenModeEnabled, the zen mode will be fully controlled by the host app, and users won't be able to toggle it from within the app.

gridModeEnabled

This prop indicates whether the shows the grid. When supplied, the value takes precedence over intialData.appState.gridModeEnabled, the grid will be fully controlled by the host app, and users won't be able to toggle it from within the app.

libraryReturnUrl

If supplied, this URL will be used when user tries to install a library from 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

This prop controls Excalidraw's theme. When supplied, the value takes precedence over intialData.appState.theme, the theme will be fully controlled by the host app, and users won't be able to toggle it from within the app. You can use THEME to specify the theme.

name

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. 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 false | exportOpts
{ saveFileToDisk: true }
This prop allows to customize the UI inside the export dialog. By default it shows the "saveFileToDisk". If this prop is false the export button will not be rendered. For more details visit exportOpts.
loadScene boolean true Implies whether to show Load button
saveToActiveFile boolean true Implies whether to show Save button to save to current file
theme boolean true Implies whether to show Theme toggle
saveAsImage boolean true Implies whether to show Save as image button

exportOpts

The below attributes can be set in UIOptions.canvasActions.export to customize the export dialog. If UIOptions.canvasActions.export is false the export button will not be rendered.

Attribute Type Default Description
saveFileToDisk boolean true Implies if save file to disk button should be shown
onExportToBackend
 (exportedElements: readonly NonDeletedExcalidrawElement[],appState: AppState,canvas: HTMLCanvasElement | null) => void 
| This callback is triggered when the shareable-link button is clicked in the export dialog. The link button will only be shown if this callback is passed.
renderCustomUI
 (exportedElements: readonly NonDeletedExcalidrawElement[],appState: AppState,canvas: HTMLCanvasElement | null) => void 
| This callback should be supplied if you want to render custom UI in the export dialog.

onPaste

This callback is triggered if passed when something is pasted into the scene. You can use this callback in case you want to do something additional when the paste event occurs.

(data: ClipboardData, event: ClipboardEvent | null) => boolean

This callback must return a boolean value or a promise which resolves to a boolean value.

In case you want to prevent the excalidraw paste action you must return false, it will stop the native excalidraw clipboard management flow (nothing will be pasted into the scene).

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).

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 to see it in action.

detectScroll

Indicates whether Excalidraw should listen for scroll event on the nearest scrollable container in the DOM tree and recompute the coordinates (e.g. to correctly handle the cursor) when the component's position changes. You can disable this when you either know this doesn't affect your app or you want to take care of it yourself (calling the refresh() method).

handleKeyboardGlobally

Indicates whether to bind keyboard events to document. Disabled by default, meaning the keyboard events are bound to the Excalidraw component. This allows for multiple Excalidraw components to live on the same page, and ensures that Excalidraw keyboard handling doesn't collide with your app's (or the browser) when the component isn't focused.

Enable this if you want Excalidraw to handle keyboard even if the component isn't focused (e.g. a user is interacting with the navbar, sidebar, or similar).

onLibraryChange

This callback if supplied will get triggered when the library is updated and has the below signature.

(items: LibraryItems) => void | Promise<any>

It is invoked with empty items when user clears the library. You can use this callback when you want to do something additional when library is updated for example persisting it to local storage.

id

The unique id of the excalidraw component. This can be used to identify the excalidraw component, for example importing the library items to the excalidraw component from where it was initiated when you have multiple excalidraw components rendered on the same page as shown in multiple excalidraw demo.

autoFocus

This prop implies whether to focus the Excalidraw component on page load. Defaults to false.

generateIdForFile

Allows you to override id generation for files added on canvas (images). By default, an SHA-1 digest of the file is used.

(file: File) => string | Promise<string>

onLinkOpen

This prop if passed will be triggered when clicked on link. To handle the redirect yourself (such as when using your own router for internal links), you must call event.preventDefault().

(element: ExcalidrawElement, event: CustomEvent<{ nativeEvent: MouseEvent }>) => void

Example:

const history = useHistory();

// open internal links using the app's router, but opens external links in
// a new tab/window
const onLinkOpen: ExcalidrawProps["onLinkOpen"] = useCallback(
  (element, event) => {
    const link = element.link;
    const { nativeEvent } = event.detail;
    const isNewTab = nativeEvent.ctrlKey || nativeEvent.metaKey;
    const isNewWindow = nativeEvent.shiftKey;
    const isInternalLink =
      link.startsWith("/") || link.includes(window.location.origin);
    if (isInternalLink && !isNewTab && !isNewWindow) {
      history.push(link.replace(window.location.origin, ""));
      // signal that we're handling the redirect ourselves
      event.preventDefault();
    }
  },
  [history],
);

Does it support collaboration ?

No, Excalidraw package doesn't come with collaboration built in, since the implementation is specific to each host app. We expose APIs which you can use to communicate with Excalidraw which you can use to implement it. You can check our own implementation here.

Restore utilities

restoreAppState

Signature

restoreAppState(appState: ImportedDataState["appState"], localAppState: Partial<AppState> | null): AppState

How to use

import { restoreAppState } from "@excalidraw/excalidraw";

This function will make sure all the keys have appropriate values in appState and if any key is missing, it will be set to default value.

When localAppState is supplied, it's used in place of values that are missing (undefined) in appState instead of defaults. Use this as a way to not override user's defaults if you persist them. Required: supply null/undefined if not applicable.

restoreElements

Signature

restoreElements(elements: ImportedDataState["elements"], localElements: ExcalidrawElement[] | null | undefined): ExcalidrawElement[]

How to use

import { restoreElements } from "@excalidraw/excalidraw";

This function will make sure all properties of element is correctly set and if any attribute is missing, it will be set to default value.

When localElements are supplied, they are used to ensure that existing restored elements reuse version (and increment it), and regenerate versionNonce. Use this when you import elements which may already be present in the scene to ensure that you do not disregard the newly imported elements if you're using element version to detect the updates.

restore

Signature

restoreElements(data: ImportedDataState, localAppState: Partial<AppState> | null | undefined, localElements: ExcalidrawElement[] | null | undefined): DataState

See restoreAppState() about localAppState, and restoreElements() about localElements.

How to use

import { restore } from "@excalidraw/excalidraw";

This function makes sure elements and state is set to appropriate values and set to default value if not present. It is a combination of restoreElements and restoreAppState.

Export utilities

exportToCanvas

Signature

exportToCanvas({
  elements,
  appState
  getDimensions,
  files
}: ExportOpts
Name Type Default Description
elements Excalidraw Element [] | The elements to be exported to canvas
appState AppState defaultAppState The app state of the scene
getDimensions (width: number, height: number) => { width: number, height: number, scale?: number } undefined A function which returns the width, height, and optionally scale (defaults 1), with which canvas is to be exported.
maxWidthOrHeight number undefined The maximum width or height of the exported image. If provided, getDimensions is ignored.
files [BinaryFiles](The BinaryFiles undefined The files added to the scene.

How to use

import { exportToCanvas } from "@excalidraw/excalidraw";

This function returns the canvas with the exported elements, appState and dimensions.

exportToBlob

Signature

exportToBlob(
  opts: ExportOpts & {
  mimeType?: string,
  quality?: number;
})
Name Type Default Description
opts | This param is passed to exportToCanvas. You can refer to exportToCanvas
mimeType string "image/png" Indicates the image format
quality number 0.92 A value between 0 and 1 indicating the image quality. Applies only to image/jpeg/image/webp MIME types.

How to use

import { exportToBlob } from "@excalidraw/excalidraw";

Returns a promise which resolves with a blob. It internally uses canvas.ToBlob.

exportToSvg

Signature

exportToSvg({
  elements: ExcalidrawElement[],
  appState: AppState,
  exportPadding?: number,
  metadata?: string,
  files?: BinaryFiles
})
Name Type Default Description
elements Excalidraw Element [] | The elements to exported as svg
appState AppState defaultAppState The app state of the scene
exportPadding number 10 The padding to be added on canvas
files [BinaryFiles](The BinaryFiles undefined The files added to the scene.

This function returns a promise which resolves to svg of the exported drawing.

Additional attributes of appState for export\* APIs
Name Type Default Description
exportBackground boolean true Indicates whether background should be exported
viewBackgroundColor string #fff The default background color
exportWithDarkMode boolean false Indicates whether to export with dark mode
exportEmbedScene boolean false Indicates whether scene data should be embedded in svg. This will increase the svg size.

Extra API's

serializeAsJSON

Signature

serializeAsJSON({
  elements: ExcalidrawElement[],
  appState: AppState,
}): string

Takes the scene elements and state and returns a JSON string. Deleted elementsas well as most properties from AppState are removed from the resulting JSON. (see serializeAsJSON() source for details).

getSceneVersion

How to use

import { getSceneVersion } from "@excalidraw/excalidraw";
getSceneVersion(elements:  ExcalidrawElement[])

This function returns the current scene version.

isInvisiblySmallElement

Signature

isInvisiblySmallElement(element:  ExcalidrawElement): boolean

How to use

import { isInvisiblySmallElement } from "@excalidraw/excalidraw";

Returns true if element is invisibly small (e.g. width & height are zero).

loadLibraryFromBlob

import { loadLibraryFromBlob } from "@excalidraw/excalidraw";

Signature

loadLibraryFromBlob(blob: Blob)

This function loads the library from the blob.

loadFromBlob

How to use

import { loadFromBlob } from "@excalidraw/excalidraw";

Signature

loadFromBlob(blob: Blob, localAppState:  AppState | null)

This function loads the scene data from the blob. If you pass localAppState, localAppState value will be preferred over the appState derived from blob

getFreeDrawSvgPath

How to use

import { getFreeDrawSvgPath } from "@excalidraw/excalidraw";

Signature

getFreeDrawSvgPath(element: ExcalidrawFreeDrawElement

This function returns the free draw svg path for the element.

isLinearElement

How to use

import { isLinearElement } from "@excalidraw/excalidraw";

Signature

isLinearElement(elementType?: ExcalidrawElement): boolean

This function returns true if the element is linear type (arrow |line) else returns false.

getNonDeletedElements

How to use

import { getNonDeletedElements } from "@excalidraw/excalidraw";

Signature

getNonDeletedElements(elements:  readonly ExcalidrawElement[]): as readonly NonDeletedExcalidrawElement[]

This function returns an array of deleted elements.

Exported constants

FONT_FAMILY

How to use

import { FONT_FAMILY } from "@excalidraw/excalidraw";

FONT_FAMILY contains all the font families used in Excalidraw as explained below

Font Family Description
Virgil The handwritten font
Helvetica The Normal Font
Cascadia The Code Font

Defaults to FONT_FAMILY.Virgil unless passed in initialData.appState.currentItemFontFamily.

THEME

How to use

import { THEME } from "@excalidraw/excalidraw";

THEME contains all the themes supported by Excalidraw as explained below

Theme Description
LIGHT The light theme
DARK The Dark theme

Defaults to THEME.LIGHT unless passed in initialData.appState.theme

Need help?

Check out the existing Q&A. If you have any queries or need help, ask us here.

Development

Install the dependencies

yarn

Start the server

yarn start

http://localhost:3001 will open in your default browser.

The example is same as the codesandbox example

Create a test release

You can create a test release by posting the below comment in your pull request

@excalibot release package

Once the version is released @excalibot will post a comment with the release version.

changelog

Changelog

Unreleased

Excalidraw API

Features

Fixes

  • Allow returning null in renderFooter prop #5282.

  • Use window.EXCALIDRAW_ASSET_PATH for fonts when exporting to svg #5065.

  • Library menu now properly rerenders if open when library is updated using updateScene({ libraryItems }) #4995.

Refactor

  • Rename appState.elementLocked to appState.activeTool.locked #4983.
  • Expose serializeLibraryAsJSON helper that we use when saving Excalidraw Library to a file.
BREAKING CHANGE

You will need to pass activeTool.locked instead of elementType from now onwards in appState.

BREAKING CHANGE

You will need to pass activeTool instead of elementType from now onwards in appState

Build

  • Use only named exports #5045.

BREAKING CHANGE

You will need to import the named export from now onwards to use the component

Using bundler :point_down:

import { Excalidraw } from "@excalidraw/excalidraw";

In Browser :point_down:

React.createElement(ExcalidrawLib.Excalidraw, opts);

Excalidraw Library

Chore

  • Transpile browser-fs-access dependency so that its for await syntax doesn't force es2018 requirement onto dependent projects #5041.

0.11.0 (2022-02-17)

Excalidraw API

Features

  • Add onLinkOpen prop which will be triggered when clicked on element hyperlink if present #4694.
  • Support updating library using updateScene API #4546.

  • Introduced primary colors to the app. The colors can be overridden. Check readme on how to do so #4387.

  • exportToBlob now automatically sets appState.exportBackground to true if exporting to image/jpeg MIME type (to ensure that alpha channel is not compressed to black color) #4342.

    BREAKING CHANGE

    Remove getElementMap util #4306.

  • Changes to exportToCanvas util function #4321:

    • Add maxWidthOrHeight?: number attribute.
    • scale returned from getDimensions() is now optional (default to 1).
  • Image support added for host PR

    General notes:

    • File data are encoded as DataURLs (base64) for portability reasons.

    ExcalidrawAPI:

    • added getFiles() to get current BinaryFiles (Record<FileId, BinaryFileData>). It may contain files that aren't referenced by any element, so if you're persisting the files to a storage, you should compare them against stored elements.

    Excalidraw app props:

    • added generateIdForFile(file: File) optional prop so you can generate your own ids for added files.
    • onChange(elements, appState, files) prop callback is now passed BinaryFiles as third argument.
    • onPaste(data, event) data prop should contain data.files (BinaryFiles) if the elements pasted are referencing new files.
    • initialData object now supports additional files (BinaryFiles) attribute.

    Other notes:

    • .excalidraw files may now contain top-level files key in format of Record<FileId, BinaryFileData> when exporting any (image) elements.
    • Changes were made to various export utilities exported from the package so that they take files, you can refer to the docs for the same.
  • Export isLinearElement and getNonDeletedElements #4072.

  • Support renderTopRightUI in mobile UI #4065.

  • Export THEME constant from the package so host can use this when passing the theme #4055.

    BREAKING CHANGE

    The Appearance type is now removed and renamed to Theme so Theme type needs to be used.

Fixes

  • Reset unmounted state on the component once component mounts to fix the mounting/unmounting repeatedly when used with useEffect #4682.
  • Panning the canvas using mousewheel-drag and space-drag now prevents the browser from scrolling the container/page #4489.
  • Scope drag and drop events to Excalidraw container to prevent overriding host application drag and drop events #4445.

Build

 @excalibot trigger release

#4750.

  • Added an example to test and develop the package locally using yarn start #4488

  • Remove file-loader so font assets are not duplicated by webpack and use webpack asset modules for font generation #4380.

  • We're now compiling to es2017 target. Notably, async/await is not compiled down to generators. #4341.


Excalidraw Library

This section lists the updates made to the excalidraw library and will not affect the integration.

Features

  • Show group/group and link action in mobile #4795

  • Support background fill for freedraw shapes #4610

  • Keep selected tool on canvas reset #4728

  • Make whole element clickable in view mode when it has hyperlink #4735

  • Allow any precision when zooming #4730

  • Throttle pointermove events per framerate #4727

  • Support hyperlinks 🔥 #4620

  • Added penMode for palm rejection #4657

  • Support unbinding bound text #4686

  • Sync local storage state across tabs when out of sync #4545

  • Support contextMenuLabel to be of function type to support dynamic labels #4654

  • Support decreasing/increasing fontSize via keyboard #4553

  • Link to new LP for excalidraw plus #4549

  • Update stroke color of bounded text along with container #4541

  • Hints and shortcuts help around deep selection #4502

  • Support updating text properties by clicking on container #4499

  • Bind text to shapes when pressing enter and support sticky notes 🎉 #4343

  • Change boundElementIdsboundElements #4404

  • Support selecting multiple points when editing line #4373

  • Horizontally center toolbar menu commit link

  • Add support for rounded corners in diamond #4369

  • Allow zooming up to 3000% #4358

  • Stop discarding precision when rendering #4357

  • Support Image binding #4347

  • Add element.updated #4070

  • Compress shareLink data when uploading to json server #4225

  • Supply version param when installing libraries #4305

  • Log FS abortError to console #4279

  • Add validation for website and remove validation for library item name #4269

  • Allow publishing libraries from UI #4115

  • Create confirm dialog to use instead of window.confirm #4256

  • Allow letters in IDs for storing files in backend #4224

  • Remove support for V1 unencrypted backend #4189

  • Use separate backend for local storage #4187

  • Add hint around canvas panning #4159

  • Stop using production services for development #4113

  • Add triangle arrowhead #4024

  • Add rewrite to webex landing page #4102

  • Switch collab server #4092

  • Use dialog component for clear canvas instead of window confirm #4075

Fixes

  • Rename --color-primary-chubb to --color-primary-contrast-offset and fallback to primary color if not present #4803

  • Add commits directly pushed to master in changelog #4798

  • Don't bump element version when adding files data #4794

  • Mobile link click #4742

  • ContextMenu timer & pointers not correctly reset on iOS #4765

  • Use absolute coords when rendering link popover #4753

  • Changing font size when text is not selected or edited #4751

  • Disable contextmenu on non-secondary pen events or touch #4675

  • Mobile context menu won't show on long press #4741

  • Do not open links twice #4738

  • Make link icon clickable in mobile #4736

  • Apple Pen missing strokes #4705

  • Freedraw slow movement jittery lines #4726

  • Disable three finger pinch zoom in penMode #4725

  • Remove click listener for opening popup #4700

  • Link popup position not accounting for offsets #4695

  • PenMode darkmode style #4692

  • Typing _+ in wysiwyg not working #4681

  • Keyboard-zooming in wysiwyg should zoom canvas #4676

  • SceneCoordsToViewportCoords, jumping text when there is an offset #4413 (#4630)

  • Right-click object menu displays partially off-screen #4572 (#4631)

  • Support collaboration in bound text #4573

  • Cmd/ctrl native browser behavior blocked in inputs #4589

  • Use cached width when calculating min width during resize #4585

  • Support collaboration in bounded text #4580

  • Port for collab server and update docs #4569

  • Don't mutate the bounded text if not updated when submitted #4543

  • Prevent canvas drag while editing text #4552

  • Support shift+P for freedraw #4550

  • Prefer spreadsheet data over image #4533

  • Show text properties button states correctly for bounded text #4542

  • Rotate bounded text when container is rotated before typing #4535

  • Undo should work when selecting bounded textr #4537

  • Reduce padding to 5px for bounded text #4530

  • Bound text doesn't inherit container #4521

  • Text wrapping with grid #4505 (#4506)

  • Check if process is defined before using so it works in browser #4497

  • Pending review fixes for sticky notes #4493

  • Pasted elements except binded text once paste action is complete #4472

  • Don't select binded text when ungrouping #4470

  • Set height correctly when text properties updated while editing in container until first submit #4469

  • Align and distribute binded text in container and cleanup #4468

  • Move binded text when moving container using keyboard #4466

  • Support dragging binded text in container selected in a group #4462

  • Vertically align single line when deleting text in bounded container #4460

  • Update height correctly when updating text properties in binded text #4459

  • Align library item previews to center #4447

  • Vertically center align text when text deleted #4457

  • Vertically center the first line as user starts typing in container #4454

  • Switch cursor to center of container when adding text when dimensions are too small #4452

  • Vertically center align the bounded text correctly when zoomed #4444

  • Support updating stroke color for text by typing in color picker input #4415

  • Bound text not atomic with container when changing z-index #4414

  • Update viewport coords correctly when editing text #4416

  • Use word-break break-word only and update text editor height only when binded to container #4410

  • Husky not able to execute pre-commit on windows #4370

  • Make firebase config parsing not fail on undefined env #4381

  • Adding to library via contextmenu when no image is selected #4356

  • Export scale quality regression #4316

  • Remove 100% height from tooltip container to fix layout issues #3980

  • Inline ENV variables when building excalidraw package #4311

  • SVG export in dark mode with embedded bitmap image #4285

  • New FS API not working on Linux #4280

  • Url -> URL for consistency #4277

  • Prevent adding images to library via contextMenu #4264

  • Account for libraries v2 when prompting #4263

  • Skia rendering issues #4200

  • Ellipse roughness when 0 #4194

  • Proper string for invalid SVG #4191

  • Images not initialized correctly #4157

  • Image-related fixes #4147

  • Rewrite collab element reconciliation to fix z-index issues #4076

  • Redirect excalidraw.com/about to for-webex.excalidraw.com #4104

  • Redirect to webex LP instead of rewrite to fix SW #4103

  • Clear image/shape cache of affected elements when adding files #4089

  • Clear LibraryUnit DOM on unmount #4084

  • Pasting images on firefox #4085

Refactor

  • Simplify zoom by removing zoom.translation #4477

  • Deduplicate encryption helpers #4146

Performance

  • Cache approx line height in textwysiwg #4651

Build

  • Rename release command to 'release package' #4783

  • Deploy excalidraw package example #4762

  • Allow package.json changes when autoreleasing next #4068


0.10.0 (2021-10-13)

Excalidraw API

Fixes

  • Don't show save file to disk button in export dialog when saveFileToDisk passed as false in UIOptions.canvasActions.export #4073.

  • onPaste prop should return false to prevent the native excalidraw paste action #3974.

    BREAKING CHANGE

    • Earlier the paste action was prevented when the prop onPaste returned true, but now it should return false to prevent the paste action. This was done to make it semantically more correct and intuitive.

Build

  • Enable jsx transform in webpack #4049

Docs

  • Correct exportToBackend in README to onExportToBackend #3952

Excalidraw Library

This section lists the updates made to the excalidraw library and will not affect the integration.

Features

  • Improve freedraw shape #3984

  • Make color ARIA labels better #3871

  • Add origin trial tokens #3853

  • Re-order zoom buttons #3837

  • Add undo/redo buttons & tweak footer #3832

  • Resave to png/svg with metadata if you loaded your scene from a png/svg file #3645

Fixes

  • Abstract and fix legacy fs #4032

  • Context menu positioning #4025

  • Added alert for bad encryption key #3998

  • OnPaste should return false to prevent paste action #3974

  • Help-icon now visible on Safari #3939

  • Permanent zoom mode #3931

  • Undo/redo buttons gap in Safari #3836

  • Prevent gradual canvas misalignment #3833

  • Color picker shortcuts not working when elements selected #3817


0.9.0 (2021-07-10)

Excalidraw API

Features

  • restore(data, localAppState, localElements) and restoreElements(elements, localElements) now take localElements argument which will be used to ensure existing elements' versions are used and incremented. This fixes an issue where importing the same file would resolve to elements with older versions, potentially causing issues when reconciling #3797.

    BREAKING CHANGE

    • localElements argument is mandatory (can be null/undefined) if using TypeScript.
  • Support appState.exportEmbedScene attribute in exportToSvg which allows to embed the scene data #3777.

    BREAKING CHANGE

    • The attribute metadata is now removed as metadata was only used to embed scene data which is now supported with the appState.exportEmbedScene attribute.
    • exportToSvg now resolves to a promise which resolves to svg of the exported drawing.
  • Expose loadLibraryFromBlob, loadFromBlob, and getFreeDrawSvgPath #3764.

  • Expose FONT_FAMILY so that consumer can use when passing initialData.appState.currentItemFontFamily #3710.

  • Added prop autoFocus to focus the excalidraw component on page load when enabled, defaults to false #3691.

    Note: Earlier Excalidraw component was focused by default on page load, you need to enable autoFocus prop to retain the same behaviour.

  • Added prop UIOptions.canvasActions.export.renderCustomUI to support Custom UI rendering inside export dialog #3666.

  • Added prop UIOptions.canvasActions.saveAsImage to show/hide the Save as image button in the canvas actions. Defaults to true hence the Save as Image button is rendered #3662.

  • Export dialog can be customised with UiOptions.canvasActions.export #3658.

    Also, UIOptions is now memoized to avoid unnecessary rerenders.

    BREAKING CHANGE

    • UIOptions.canvasActions.saveAsScene is now renamed to UiOptions.canvasActions.export.saveFileToDisk. Defaults to true hence the save file to disk button is rendered inside the export dialog.
    • exportToBackend is now renamed to UIOptions.canvasActions.export.exportToBackend. If this prop is not passed, the shareable-link button will not be rendered, same as before.

Fixes

  • Use excalidraw Id in elements so every element has unique id #3696.

Refactor

  • BREAKING CHANGE

    • Rename UIOptions.canvasActions.saveScene to UIOptions.canvasActions.saveToActiveFile#3657.
    • Removed shouldAddWatermark: boolean attribute from options for export APIs #3639.
    • Removed appState.shouldAddWatermark so in case you were passing shouldAddWatermark in initialData.AppState it will not work anymore.

Excalidraw Library

This section lists the updates made to the excalidraw library and will not affect the integration.

Features

  • Switch to selection tool on library item insert #3773

  • Show active file name when saving to current file #3733

  • Add hint around text editing #3708

  • Change library icon to be more clear #3583

  • Pass current theme when installing libraries #3701

  • Update virgil font #3692

  • Support exporting json to excalidraw plus #3678

  • Save exportScale in AppState #3580

  • Add shortcuts for stroke and background color picker #3318

  • Exporting redesign #3613

  • Auto-position tooltip and support overflowing container #3631

  • Auto release @excalidraw/excalidraw-next on every change #3614

  • Allow inner-drag-selecting with cmd/ctrl #3603

Fixes

  • view mode cursor adjustments #3809.

  • Pass next release to updatePackageVersion & replace ## unreleased with new version #3806

  • Include deleted elements when passing to restore #3802

  • Import React before using jsx #3804

  • Ensure s and g shortcuts work on no selection #3800

  • Keep binding for attached arrows after changing text #3754

  • Deselect elements on viewMode toggle #3741

  • Allow pointer events for disable zen mode button #3743

  • Use rgba instead of shorthand alpha #3688

  • Color pickers not opening on mobile #3676

  • On contextMenu, use selected element regardless of z-index #3668

  • SelectedGroupIds not being stored in history #3630

  • Overscroll on touch devices #3663

  • Small UI issues around image export dialog #3642

  • Normalize linear element points on restore #3633

  • Disable pointer-events on footer-center container #3629

Refactor

  • Delete React SyntheticEvent persist #3700

  • Code clean up #3681

Performance

  • Improve arrow head sizing #3480

Build

  • Add release script to update relevant files and commit for next release #3805

  • Add script to update changelog before a stable release #3784

  • Add script to update readme before stable release #3781


0.8.0 (2021-05-15)

Excalidraw API

These section lists the updates which may affect your integration, so it is recommended to go through this when upgrading the version.

Features

  • Support updating any appState properties in updateScene API. Earlier only appState.viewBackgroundColor was supported, now any attribute can be updated with this API.
  • Expose serializeAsJSON helper that we use when saving Excalidraw scene to a file #3538.
  • Add support to render custom UI in the top right corner via renderTopRightUI prop #3539, #3572 .

    This also removes the GitHub icon, keeping it local to the https://excalidraw.com app.

Fixes

  • The encryption shield icon is now removed from excalidraw package as it was specific to excalidraw app and is now rendered via renderFooter prop. In case you were hiding this icon earlier, you need not do that anymore #3577.

    Now appState is also passed to renderFooter prop.

Excalidraw Library

These section lists the updates made to the excalidraw library and will not affect the integration.

Features

  • Shortcut key for nerd stats #3552.
  • Better rendering of curved rectangles #3562.
  • Improved freedraw #3512.
  • Add shortcut for dark mode #3543.
  • Adds rounded icons, joins and caps.#3521.

Fixes

  • Exporting freedraw with color to svg #3565.
  • Handle render errors #3557.
  • Restore on paste or lib import #3558.
  • Improve mobile user experience #3508.
  • Prevent selecting .visually-hidden elements #3501.

Perf

  • Reduce SVG export size by more than half by reducing precision to 2 decimal places #3567.
  • Remove backdrop-filter to improve perf #3506

0.7.0 (2021-04-26)

Excalidraw API

Features

  • scrollToContent API now supports passing just a single Excalidraw element, or none at all (which will default to current elements on the scene) #3482.

    BREAKING CHANGE

  • Make library local to given excalidraw instance (previously, all instances on the same page shared one global library) #3451.

    • Added prop onLibraryChange which if supplied will be called when library is updated.

    • Added attribute libraryItems to prop initialData which can be used to load excalidraw with existing library items.

    • Assign a unique id to the excalidraw component. The id can be accessed via ref.

    BREAKING CHANGE

  • Bind the keyboard events to component and added a prop handleKeyboardGlobally which if set to true will bind the keyboard events to document #3430.

    BREAKING CHANGE

    • Earlier keyboard events were bind to document but now its bind to Excalidraw component by default. So you will need to set handleKeyboardGlobally to true if you want the previous behaviour (bind the keyboard events to document).
  • Recompute offsets on scroll of the nearest scrollable container #3408. This can be disabled by setting detectScroll to false.

  • Add onPaste prop to handle custom clipboard behaviours #3420.

Fixes

  • Changing z-index of elements (sorting them below/above other elements) now updates their version and versionNonce (only applies to the selected elements). This fix will allow you account for z-index changes if you're syncing just the elements that changed (and not the whole scene) #3483.
  • Only handle cut/paste events inside excalidraw #3484.

  • Make history local to a given Excalidraw instance. This fixes a case where history was getting shared when you have multiple Excalidraw components on the same page #3481.

  • Use active Excalidraw component when editing text. This fixes a case where text editing was not working when you have multiple Excalidraw components on the same page #3478.

  • Fix library being pasted off-center #3462.

  • When switching theme, apply it only to the active Excalidraw component. This fixes a case where the theme was getting applied to the first Excalidraw component if you had multiple Excalidraw components on the same page #3446.

Refactor

  • BREAKING CHANGE

    • Removed exposing getSyncableElements helper which was specific to excalidraw app collab implementation #3471. If you happened to use it, you can easily reimplement it yourself using the newly exposed isInvisiblySmallElement helper:

      const getSyncableElements = (elements: readonly ExcalidrawElement[]) =>
        elements.filter((el) => el.isDeleted || !isInvisiblySmallElement(el));

Build

  • Add vendor prefixes to css rules #3476.

Types

  • Renamed the following types in case you depend on them (via #3427):
    • DataStateExportedDataState
    • LibraryDataExportedLibraryData

Excalidraw Library

Features

  • Support tab-to-indent when editing text #3411.

  • App now breaks into mobile view using the component dimensions, not viewport dimensions. This fixes a case where the app would break sooner than necessary when the component's size is smaller than viewport #3414.

  • Add screenshots to manifest.json #3369.

  • Enable drop event on the whole component #3406.

Fixes

  • Focus on last active element when dialog closes #3447.

  • Fix incorrectly caching png file handle #3407.

  • Fix popover position incorrect on Safari for non-zero offsets/scroll #3399.


0.6.0 (2021-04-04)

Excalidraw API

Features

  • Add UIOptions prop to customise canvas actions which includes customising background color picker, clear canvas, export, load, save, save as & theme toggle #3364. Check the readme for more details.
  • Calculate width/height of canvas based on excalidraw component (".excalidraw" selector) & also resize and update offsets whenever the dimensions of excalidraw component gets updated #3379. You also don't need to add a resize handler anymore for excalidraw as its handled now in excalidraw itself.

    BREAKING CHANGE

    • width/height props have been removed. Instead now it takes 100% of width and height of the container so you need to make sure the container in which you are rendering Excalidraw has non zero dimensions (It should have non zero width and height so Excalidraw can match the dimensions of containing block)
  • Calculate offsets when excalidraw container resizes using resize observer api #3374.
  • Export types for the package so now it can be used with typescript #3337. The types are available at @excalidraw/excalidraw/types.
  • Add renderCustomStats prop to render extra stats on host, and expose setToastMessage API via refs which can be used to show toast with custom message #3360.
  • Support passing a CSRF token when importing libraries to prevent prompting before installation. The token is passed from https://libraries.excalidraw.com using the token URL key #3329.
  • BREAKING CHANGE

    Use location.hash when importing libraries to fix installation issues. This will require host apps to add a hashchange listener and call the newly exposed excalidrawAPI.importLibrary(url) API when applicable #3320. Check the readme for more details.
  • Append location.pathname to libraryReturnUrl default url #3325.
  • Support image elements #3424.

Build

  • Expose separate builds for dev and prod and support source maps in dev build #3330. Check the readme for more details.

    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 to refresh #3398.

Excalidraw Library

Features

  • Reopen library menu on import from file #3383.
  • Don't unnecessarily prompt when installing libraries #3329.
  • Add option to flip single element on the context menu #2520.
  • Replace fontSize and fontFamily text with icons #2857.

Fixes

  • Export dialog canvas positioning #3397.
  • Don't share collab types with core #3353.
  • Support d&d of files without extension #3168.
  • Positions stats for linear elements #3331.
  • Debounce.flush invokes func even if never queued before #3326.
  • State selection state on opening contextMenu #3333.
  • Add unique key for library header to resolve dev warnings #3316.
  • disallow create text in viewMode on mobile #3219.
  • Make help toggle tabbable #3310
  • Show Windows share icon for Windows users #3306.
  • Don't scroll to content on INIT websocket message #3291.

Refactor

  • Use arrow function where possible #3315.

0.5.0 (2021-03-21)

Excalidraw API

Features

  • Set the target to window.name if present during excalidraw libraries installation so it opens in same tab for the host. If window.name is not set it will open in a new tab #3299.
  • Add name prop to indicate 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 #3273.
  • Export API setCanvasOffsets via ref to set the offsets for Excalidraw#3265.

    BREAKING CHANGE

    • offsetLeft and offsetTop props have been removed now so you have to use the setCanvasOffsets via ref to achieve the same.
  • Export API to export the drawing to canvas, svg and blob #3258. For more info you can check the readme
  • Add a theme prop to indicate Excalidraw's theme. #3228. When this prop is passed, the theme is fully controlled by host app.
  • Support libraryReturnUrl prop to indicate what URL to install libraries to #3227.

Refactor

  • BREAKING CHANGE

    • Rename prop initialData.scrollToCenter and setScrollToCenter API exposed via ref to initialData.scrollToContent and setScrollToContent respectively#3261.
  • Rename appearance to theme #3237.

    BREAKING CHANGE

    • Since appState.appearance is renamed to appState.theme so wherever appState.appearance including initialData.appState.appearance should be renamed to appState.theme and initialData.appState.theme respectively. If the appearance was persisted earlier, now it needs to passed as theme.
    • The class Appearance_dark is renamed to theme--dark.
    • The class Appearance_dark-background-none is renamed to theme--dark-background-none.

Excalidraw Library

Features

  • Support pasting file contents & always prefer system clip #3257
  • Add label for name field and use input when editable in export dialog #3286
  • Implement the Web Share Target API #3230.

Fixes

  • Don't show export and delete when library is empty #3288
  • Overflow in textinput in export dialog #3284.
  • Bail on noop updates for newElementWith #3279.
  • Prevent State continuously updated when holding ctrl/cmd #3283
  • Debounce flush not invoked if lastArgs not defined #3281.
  • Stop preventing canvas pointerdown/tapend events #3207.
  • Double scrollbar on modals #3226.

0.4.3 (2021-03-12)

Excalidraw API

Fixes

  • Allow copy of excalidraw elements only when inside excalidraw #3206.
  • Position text editor absolute and fix the offsets so it doesn't remain fixed when the container is scrolled #3200.
  • Scope CSS variables so that host CSS vars don't clash with excalidraw #3199.

Excalidraw Library

  • Apply correct translation when text editor overflows when zoom not 100% #3225
  • Don't overflow text beyond width of Excalidraw #3215.

0.4.2

Excalidraw API

Fixes

  • Wrap excalidraw in position relative so host need not do it anymore & hide scrollbars in zen mode #3174.
  • Reduce the scroll debounce timeout to 100ms so offsets gets updated faster if changed when container scrolled #3182.
  • Rerender UI on renderFooter prop change #3183

Excalidraw Library

Fixes

  • Temporarily downgrade browser-fs-access to fix legacy FS API #3172

0.4.1

Excalidraw API

Fixes

  • Use Array.from when spreading over set so that typescript transpiles correctly in the umd build#3165.

Excalidraw Library

Features

  • Add export info on copy PNG to clipboard toast message #3159.
  • Use the latest version of Virgil #3124.
  • Support exporting with dark mode #3046.

Fixes

  • Cursor being leaked outside of canvas #3161.
  • Hide scrollbars in zenMode #3144.

0.4.0

Excalidraw API

Features

  • Expose window.EXCALIDRAW_ASSET_PATH which host can use to load assets from a different URL. By default it will be loaded from https://unpkg.com/@excalidraw/excalidraw{currentVersion}/dist/#3068.

    Also now the assets will have a hash in filename so cache bursting can easily happen with version bump.

  • Add support for scrollToCenter in initialData so host can control whether to scroll to center on mount #3070.

  • Export restore, restoreAppState and restoreElements to host #3049

Fixes

  • Show user state only when userState is passed on remote pointers during collaboration #3050

Excalidraw Library

Features

  • Adjust line-confirm-threshold based on zoom #2884

Fixes

  • Hide scrollbars on mobile #3044

0.3.1

Excalidraw API

Fixes

  • Support Excalidraw inside scrollable container #3018

Excalidraw Library

Fixes

  • Allow to toggle between modes when view only mode to make UI consistent #3009

0.3.0

Excalidraw API

Features

  • Allow host to pass color for collaborator #2943. The unused prop user is now removed.
  • Add zenModeEnabled and gridModeEnabled prop which enables zen mode and grid mode respectively #2901. When this prop is used, the zen mode / grid mode will be fully controlled by the host app.
  • Allow host to pass userState for collaborator to show the current user state #2877.
  • Add viewModeEnabled prop which enabled the view mode #2840. When this prop is used, the view mode will not show up in context menu is so it is fully controlled by host.
  • Expose getAppState on excalidrawRef #2834.

Build

  • Remove publicPath so host can use __webpack_public_path__ to host the assets#2835

Excalidraw Library

Features

  • Add the ability to clear library #2997
  • Updates to Collaboration and RTL UX #2994
  • Show toast when saving to existing file #2988
  • Support supplying custom scale when exporting canvas #2904
  • Show version in the stats dialog #2908
  • Add idle detection to collaboration feature #2877
  • Add view mode in Excalidraw #2840
  • Increase max zoom #2881
  • Remove copy & paste from context menu on desktop #2872
  • Add separators on context menu #2659
  • Add ctrl-y to redo #2831
  • Add view mode #2840.
  • Remove copy, cut, and paste actions from contextmenu #2872
  • Support Ctrl-Y shortcut to redo on Windows #2831.

Fixes

  • Refresh wysiwyg position on canvas resize #3008
  • Update the lang attribute with the current lang. #2995
  • Rename 'Grid mode' to 'Show grid' #2944
  • Deal with users on systems that don't handle emoji #2941
  • Mobile toolbar tooltip regression #2939
  • Hide collaborator list on mobile if empty #2938
  • Toolbar unnecessarily eats too much width #2924
  • Mistakenly hardcoding scale #2925
  • Text editor not visible in dark mode #2920
  • Incorrect z-index of text editor #2914
  • Make scrollbars draggable when offsets are set #2916
  • Pointer-events being disabled on free-draw #2912
  • Track zenmode and grid mode usage #2900
  • Disable UI pointer-events on canvas drag #2856
  • Stop flooring scroll positions #2883
  • Apply initialData appState for zenmode and grid stats and refactor check param for actions #2871
  • Show correct state of Nerd stats in context menu when nerd stats dialog closed #2874
  • Remote pointers not accounting for offset #2855
  • Toggle help dialog when "shift+?" is pressed #2828
  • Add safe check for process so Excalidraw can be loaded via script #2824
  • Fix UI pointer-events not disabled when dragging on canvas #2856.
  • Fix remote pointers not accounting for offset #2855.

Refactor

  • Remove duplicate key handling #2878
  • Reuse scss variables in js for SSOT #2867
  • Rename browser-nativefs to browser-fs-access #2862
  • Rewrite collabWrapper to remove TDZs and simplify #2834

Chore

  • Use Sentence case for Live collaboration

0.2.1

Excalidraw API

Build

  • Bundle css files with js #2819. The host would not need to import css files separately.

0.2.0

Excalidraw API

Features

  • Exported few Extra API's which can be used by the host to communicate with Excalidraw.

  • Remove language picker, and add langCode, renderFooter #2644:

    • BREAKING: removed the language picker from UI. It is now the host app's responsibility to implement a language picker if desirable, using the newly added renderFooter prop. The reasoning is that the i18n should be controlled by the app itself, not by the nested Excalidraw component.
    • Added langCode prop to control the UI language.
  • Add support for exportToBackend prop to allow host apps to implement shareable links #2612

Fixes

  • Hide collaboration button when the prop onCollabButtonClick is not provided #2598

Excalidraw Library

Features

  • Add toast #2772
  • Add cmd+o shortcut to load scene #2732
  • Require use of a preset dialog size; adjust dialog sizing #2684
  • Add line chart and paste dialog selection #2670
  • Tweak editing behavior #2668
  • Change title to Excalidraw after a timeout
  • Checkmark to toggle context-menu-items #2645
  • Add zoom to selection #2522
  • Insert Library items in the middle of the screen #2527
  • Show shortcut context menu #2501
  • Aligns arrowhead schemas #2517
  • Add Cut to menus #2511
  • More Arrowheads: dot, bar #2486
  • Support CSV graphs and improve the look and feel #2495

Fixes

  • Fix compile error #2685
  • Center zoom on iPhone and iPad #2642
  • Allow text-selecting in dialogs & reset cursor #2783
  • Don't render due to zoom after unmount #2779
  • Track the chart type correctly #2773
  • Fix late-render due to debounced zoom #2779
  • Fix initialization when browser tab not focused #2677
  • Consistent case for export locale strings #2622
  • Remove unnecessary console.error as it was polluting Sentry #2637
  • Fix scroll-to-center on init for non-zero canvas offsets #2445
  • Fix resizing the pasted charts #2586
  • Fix element visibility and zoom on cursor when canvas offset isn't 0. #2534
  • Fix Library Menu Layout #2502
  • Support number with commas in charts #2636
  • Don't break zoom when zooming in on UI #2638

Improvements

  • Added Zen Mode to the context menu #2734
  • Do not reset to selection for draw tool [#2721]((https://github.com/excalidraw/excalidraw/pull/2721)
  • Make dialogs look more like dialogs #2686
  • Browse libraries styles fixed #2694
  • Change hint for 2-point lines on resize #2655
  • Align items in context menu #2640
  • Do not reset to selection when using the draw tool #2721
  • Display proper tooltip for 2-point lines during resize, and normalize modifier key labels in hints #2655
  • Improve error message around importing images #2619
  • Add tooltip with icon for embedding scenes #2532
  • RTL support for the stats dialog #2530
  • Expand canvas padding based on zoom. #2515
  • Hide shortcuts on pickers for mobile #2508
  • Hide stats and scrollToContent-button when mobile menus open #2509

Refactor

  • refactor: Converting span to kbd tag #2774
  • Media queries #2680
  • Remove duplicate entry from en.json#2654
  • Remove the word toggle from labels #2648 -

Docs

  • Document some of the more exotic element props #2673

0.1.1

Fix

  • Update the homepage URL so it redirects to correct readme #2498

0.1.0

First release of @excalidraw/excalidraw