diff --git a/dev-docs/docs/@excalidraw/excalidraw/api/children-components/sidebar.mdx b/dev-docs/docs/@excalidraw/excalidraw/api/children-components/sidebar.mdx index 08445a1c3..ed12f6470 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/api/children-components/sidebar.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/api/children-components/sidebar.mdx @@ -80,7 +80,7 @@ A given tab trigger button that switches to a given sidebar tab. It must be rend | `className` | `string` | No | | | `style` | `React.CSSProperties` | No | | -You can use the [`ref.toggleSidebar({ name: "custom" })`](/docs/@excalidraw/excalidraw/api/props/ref#toggleSidebar) api to control the sidebar, but we export a trigger button to make UI use cases easier. +You can use the [`ref.toggleSidebar({ name: "custom" })`](/docs/@excalidraw/excalidraw/api/props/excalidraw-api#toggleSidebar) api to control the sidebar, but we export a trigger button to make UI use cases easier. ## Example diff --git a/dev-docs/docs/@excalidraw/excalidraw/api/excalidraw-element-skeleton.mdx b/dev-docs/docs/@excalidraw/excalidraw/api/excalidraw-element-skeleton.mdx index 3c1baeeaf..838896c42 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/api/excalidraw-element-skeleton.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/api/excalidraw-element-skeleton.mdx @@ -10,13 +10,17 @@ The [`ExcalidrawElementSkeleton`](https://github.com/excalidraw/excalidraw/blob/ **_Signature_** -
-  convertToExcalidrawElements(elements:{" "}
-  
-    ExcalidrawElementSkeleton
-  
-  )
-
+```ts +convertToExcalidrawElements( + elements: ExcalidrawElementSkeleton, + opts?: { regenerateIds: boolean } +): ExcalidrawElement[] +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `elements` | [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/src/data/transform.ts#L137) | | The Excalidraw element Skeleton which needs to be converted to Excalidraw elements. | +| `opts` | `{ regenerateIds: boolean }` | ` {regenerateIds: true}` | By default `id` will be regenerated for all the elements irrespective of whether you pass the `id` so if you don't want the ids to regenerated, you can set this attribute to `false`. | **_How to use_** @@ -24,13 +28,13 @@ The [`ExcalidrawElementSkeleton`](https://github.com/excalidraw/excalidraw/blob/ import { convertToExcalidrawElements } from "@excalidraw/excalidraw"; ``` -This function converts the Excalidraw Element Skeleton to excalidraw elements which could be then rendered on the canvas. Hence calling this function is necessary before passing it to APIs like [`initialData`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/initialdata), [`updateScene`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/ref#updatescene) if you are using the Skeleton API +This function converts the Excalidraw Element Skeleton to excalidraw elements which could be then rendered on the canvas. Hence calling this function is necessary before passing it to APIs like [`initialData`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/initialdata), [`updateScene`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/excalidraw-api#updatescene) if you are using the Skeleton API ## Supported Features ### Rectangle, Ellipse, and Diamond -To create these shapes you need to pass its `type` and `x` and `y` coordinates for position. The rest of the attributes are optional_. +To create these shapes you need to pass its `type` and `x` and `y` coordinates for position. The rest of the attributes are optional\_. For the Skeleton API to work, `convertToExcalidrawElements` needs to be called before passing it to Excalidraw Component via initialData, updateScene or any such API. @@ -427,3 +431,45 @@ convertToExcalidrawElements([ ``` ![image](https://github.com/excalidraw/excalidraw/assets/11256141/a8b047c8-2eed-4aea-82a2-e1e6bbddb8d4) + +### Frames + +To create a frame, you need to pass `type`, `children` (list of Excalidraw element ids). The rest of the attributes are optional. + +```ts +{ + type: "frame"; + children: readonly ExcalidrawElement["id"][]; + name?: string; + } & Partial); +``` + +```ts +convertToExcalidrawElements([ + { + "type": "rectangle", + "x": 10, + "y": 10, + "strokeWidth": 2, + "id": "1" + }, + { + "type": "diamond", + "x": 120, + "y": 20, + "backgroundColor": "#fff3bf", + "strokeWidth": 2, + "label": { + "text": "HELLO EXCALIDRAW", + "strokeColor": "#099268", + "fontSize": 30 + }, + "id": "2" + }, + { + "type": "frame", + "children": ["1", "2"], + "name": "My frame" + }] +} +``` diff --git a/dev-docs/docs/@excalidraw/excalidraw/api/props/ref.mdx b/dev-docs/docs/@excalidraw/excalidraw/api/props/excalidraw-api.mdx similarity index 81% rename from dev-docs/docs/@excalidraw/excalidraw/api/props/ref.mdx rename to dev-docs/docs/@excalidraw/excalidraw/api/props/excalidraw-api.mdx index 6edcc9b9e..22e9034fd 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/api/props/ref.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/api/props/excalidraw-api.mdx @@ -1,27 +1,26 @@ -# ref +# excalidrawAPI
-  
-    createRef
-  {" "}
-  |{" "}
-  useRef{" "}
-  |{" "}
-  
-    callbackRef
-  {" "}
-  | 
- { current: { readyPromise: - resolvablePromise - } } + (api:{" "} + + ExcalidrawAPI + + ) => void;
-You can pass a `ref` when you want to access some excalidraw APIs. We expose the below APIs: +Once the callback is triggered, you will need to store the api in state to access it later. + +```jsx showLineNumbers +export default function App() { + const [excalidrawAPI, setExcalidrawAPI] = useState(null); + return setExcalidrawAPI(api)}} />; +} +``` + +You can use this prop when you want to access some [Excalidraw APIs](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L616). We expose the below APIs :point_down: | API | Signature | Usage | | --- | --- | --- | -| ready | `boolean` | This is set to true once Excalidraw is rendered | -| [readyPromise](#readypromise) | `function` | 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](#readypromise) | | [updateScene](#updatescene) | `function` | updates the scene with the sceneData | | [updateLibrary](#updatelibrary) | `function` | updates the scene with the sceneData | | [addFiles](#addfiles) | `function` | add files data to the appState | @@ -39,54 +38,15 @@ You can pass a `ref` when you want to access some excalidraw APIs. We expose the | [setCursor](#setcursor) | `function` | This API can be used to set customise the mouse cursor on the canvas | | [resetCursor](#resetcursor) | `function` | This API can be used to reset to default mouse cursor on the canvas | | [toggleMenu](#togglemenu) | `function` | Toggles specific menus on/off | +| [onChange](#onChange) | `function` | Subscribes to change events | +| [onPointerDown](#onPointerDown) | `function` | Subscribes to `pointerdown` events | +| [onPointerUp](#onPointerUp) | `function` | Subscribes to `pointerup` events | -## readyPromise +:::info The `Ref` support has been removed in v0.17.0 so if you are using refs, please update the integration to use the `excalidrawAPI`. -
-  const excalidrawRef = { current:{ readyPromise:
-  
-     resolvablePromise
-  
-   } }
-
+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. -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. - -```jsx showLineNumbers -const resolvablePromise = () => { - let resolve; - let reject; - const promise = new Promise((_resolve, _reject) => { - resolve = _resolve; - reject = _reject; - }); - promise.resolve = resolve; - promise.reject = reject; - return promise; -}; - -const App = () => { - const excalidrawRef = useMemo( - () => ({ - current: { - readyPromise: resolvablePromise(), - }, - }), - [], - ); - - useEffect(() => { - excalidrawRef.current.readyPromise.then((api) => { - console.log("loaded", api); - }); - }, [excalidrawRef]); - return ( -
- -
- ); -}; -``` +::: ## updateScene @@ -387,14 +347,25 @@ This API can be used to get the files present in the scene. It may contain files This API has the below signature. It sets the `tool` passed in param as the active tool. -
-  (tool: 
{ type:{" "} - - SHAPES - - [number]["value"]| "eraser" } | -
{ type: "custom"; customType: string }) => void -
+```ts +( + tool: ( + | ( + | { type: Exclude } + | { + type: Extract; + insertOnCanvasDirectly?: boolean; + } + ) + | { type: "custom"; customType: string } + ) & { locked?: boolean }, +) => {}; +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `type` | [ToolType](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L91) | `selection` | The tool type which should be set as active tool. When setting `image` as active tool, the insertion onto canvas when using image tool is disabled by default, so you can enable it by setting `insertOnCanvasDirectly` to `true` | +| `locked` | `boolean` | `false` | Indicates whether the the active tool should be locked. It behaves the same way when using the `lock` tool in the editor interface | ## setCursor @@ -421,3 +392,51 @@ This API is especially useful when you render a custom [``](/docs/@exc ``` This API can be used to reset to default mouse cursor. + +## onChange + +```tsx +( + callback: ( + elements: readonly ExcalidrawElement[], + appState: AppState, + files: BinaryFiles, + ) => void +) => () => void +``` + +Subscribes to change events, similar to [`props.onChange`](/docs/@excalidraw/excalidraw/api/props#onchange). + +Returns an unsubscribe function. + +## onPointerDown + +```tsx +( + callback: ( + activeTool: AppState["activeTool"], + pointerDownState: PointerDownState, + event: React.PointerEvent, + ) => void, +) => () => void +``` + +Subscribes to canvas `pointerdown` events. + +Returns an unsubscribe function. + +## onPointerUp + +```tsx +( + callback: ( + activeTool: AppState["activeTool"], + pointerDownState: PointerDownState, + event: PointerEvent, + ) => void, +) => () => void +``` + +Subscribes to canvas `pointerup` events. + +Returns an unsubscribe function. diff --git a/dev-docs/docs/@excalidraw/excalidraw/api/props/props.mdx b/dev-docs/docs/@excalidraw/excalidraw/api/props/props.mdx index 5764528b6..069b15901 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/api/props/props.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/api/props/props.mdx @@ -1,11 +1,11 @@ # Props -All `props` are *optional*. +All `props` are _optional_. | Name | Type | Default | Description | | --- | --- | --- | --- | -| [`initialData`](/docs/@excalidraw/excalidraw/api/props/initialdata) | `object` | `null` | Promise | `null` | The initial data with which app loads. | -| [`ref`](/docs/@excalidraw/excalidraw/api/props/ref) | `object` | _ | `Ref` to be passed to Excalidraw | +| [`initialData`](/docs/@excalidraw/excalidraw/api/props/initialdata) | `object` | `null` | Promise | `null` | The initial data with which app loads. | +| [`excalidrawAPI`](/docs/@excalidraw/excalidraw/api/props/excalidraw-api) | `function` | _ | Callback triggered with the excalidraw api once rendered | | [`isCollaborating`](#iscollaborating) | `boolean` | _ | This indicates if the app is in `collaboration` mode | | [`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`. | | [`onPointerUpdate`](#onpointerupdate) | `function` | _ | Callback triggered when mouse pointer is updated. | @@ -37,7 +37,7 @@ Beyond attributes that Excalidraw elements already support, you can store `custo You can use this to add any extra information you need to keep track of. -You can add `customData` to elements when passing them as [`initialData`](/docs/@excalidraw/excalidraw/api/props/initialdata), or using [`updateScene`](/docs/@excalidraw/excalidraw/api/props/ref#updatescene) / [`updateLibrary`](/docs/@excalidraw/excalidraw/api/props/ref#updatelibrary) afterwards. +You can add `customData` to elements when passing them as [`initialData`](/docs/@excalidraw/excalidraw/api/props/initialdata), or using [`updateScene`](/docs/@excalidraw/excalidraw/api/props/excalidraw-api#updatescene) / [`updateLibrary`](/docs/@excalidraw/excalidraw/api/props/excalidraw-api#updatelibrary) afterwards. ```js showLineNumbers { @@ -93,8 +93,16 @@ This callback is triggered when mouse pointer is updated. This prop if passed will be triggered on pointer down events and has the below signature. +
-(activeTool:  AppState["activeTool"], pointerDownState: PointerDownState) => void
+(activeTool:{" "}
+  
+    {" "}
+    AppState["activeTool"]
+  
+  , pointerDownState: 
+    PointerDownState
+  ) => void
 
### onScrollChange @@ -110,7 +118,11 @@ This prop if passed will be triggered when canvas is scrolled and has the below 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
+  (data:{" "}
+  
+    ClipboardData
+  
+  , event: ClipboardEvent | null) => boolean
 
This callback must return a `boolean` value or a [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise) which resolves to a boolean value. @@ -136,8 +148,11 @@ It is invoked with empty items when user clears the library. You can use this ca 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
+  (element:{" "}
+  
+    ExcalidrawElement
+  
+  , event: CustomEvent<{ nativeEvent: MouseEvent }>) => void
 
Example: @@ -180,30 +195,30 @@ import { defaultLang, languages } from "@excalidraw/excalidraw"; ### 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. +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. +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. +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](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. +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 unless *UIOptions.canvasActions.toggleTheme* is set to `true`, in which case the `theme` prop will control Excalidraw's default theme with ability to allow theme switching (you must take care of updating the `theme` prop when you detect a change to `appState.theme` from the [onChange](#onchange) callback). +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 unless _UIOptions.canvasActions.toggleTheme_ is set to `true`, in which case the `theme` prop will control Excalidraw's default theme with ability to allow theme switching (you must take care of updating the `theme` prop when you detect a change to `appState.theme` from the [onChange](#onchange) callback). You can use [`THEME`](/docs/@excalidraw/excalidraw/api/utils#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. +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. ### detectScroll @@ -236,4 +251,4 @@ validateEmbeddable?: boolean | string[] | RegExp | RegExp[] | ((link: string) => This is an optional property. By default we support a handful of well-known sites. You may allow additional sites or disallow the default ones by supplying a custom validator. If you pass `true`, all URLs will be allowed. You can also supply a list of hostnames, RegExp (or list of RegExp objects), or a function. If the function returns `undefined`, the built-in validator will be used. -Supplying a list of hostnames (with or without `www.`) is the preferred way to allow a specific list of domains. \ No newline at end of file +Supplying a list of hostnames (with or without `www.`) is the preferred way to allow a specific list of domains. diff --git a/dev-docs/docs/@excalidraw/excalidraw/api/props/ui-options.mdx b/dev-docs/docs/@excalidraw/excalidraw/api/props/ui-options.mdx index d7551e366..ac91f9e00 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/api/props/ui-options.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/api/props/ui-options.mdx @@ -1,6 +1,6 @@ # UIOptions -This prop can be used to customise UI of Excalidraw. Currently we support customising [`canvasActions`](#canvasactions), [`dockedSidebarBreakpoint`](#dockedsidebarbreakpoint) and [`welcomeScreen`](#welcmescreen). +This prop can be used to customise UI of Excalidraw. Currently we support customising [`canvasActions`](#canvasactions), [`dockedSidebarBreakpoint`](#dockedsidebarbreakpoint) [`welcomeScreen`](#welcmescreen) and [`tools`](#tools).
   {
@@ -70,3 +70,12 @@ function App() {
   );
 }
 ```
+
+## tools
+
+This `prop ` controls the visibility of the tools in the editor.
+Currently you can control the visibility of `image` tool via this prop.
+
+| Prop | Type | Default | Description |
+| --- | --- | --- | --- |
+| image | boolean | true | Decides whether `image` tool should be visible.
\ No newline at end of file
diff --git a/dev-docs/docs/@excalidraw/excalidraw/api/utils/utils-intro.md b/dev-docs/docs/@excalidraw/excalidraw/api/utils/utils-intro.md
index 262e6f7c7..9f3d3287c 100644
--- a/dev-docs/docs/@excalidraw/excalidraw/api/utils/utils-intro.md
+++ b/dev-docs/docs/@excalidraw/excalidraw/api/utils/utils-intro.md
@@ -129,7 +129,7 @@ if (contents.type === MIME_TYPES.excalidraw) {
 
 
 loadSceneOrLibraryFromBlob(
  - blob: Blob, + blob: Blob,
  localAppState: AppState | null,
  localElements: ExcalidrawElement[] | null,
  fileHandle?: FileSystemHandle | null
@@ -164,9 +164,9 @@ import { isLinearElement } from "@excalidraw/excalidraw"; **Signature** -```tsx +
 isLinearElement(elementType?: ExcalidrawElement): boolean
-```
+
### getNonDeletedElements @@ -195,8 +195,10 @@ import { mergeLibraryItems } from "@excalidraw/excalidraw"; **_Signature_**
-mergeLibraryItems(localItems: LibraryItems,
  - otherItems: LibraryItems) => LibraryItems +mergeLibraryItems(
  + localItems: LibraryItems,
  + otherItems: LibraryItems
+): LibraryItems
### parseLibraryTokensFromUrl @@ -331,13 +333,15 @@ const App = () => ( render(); ``` -The `device` has the following `attributes` +The `device` has the following `attributes`, some grouped into `viewport` and `editor` objects, per context. | Name | Type | Description | | --- | --- | --- | -| `isMobile` | `boolean` | Set to `true` when the device is `mobile` | -| `isTouchScreen` | `boolean` | Set to `true` for `touch` devices | -| `canDeviceFitSidebar` | `boolean` | Implies whether there is enough space to fit the `sidebar` | +| `viewport.isMobile` | `boolean` | Set to `true` when viewport is in `mobile` breakpoint | +| `viewport.isLandscape` | `boolean` | Set to `true` when the viewport is in `landscape` mode | +| `editor.canFitSidebar` | `boolean` | Set to `true` if there's enough space to fit the `sidebar` | +| `editor.isMobile` | `boolean` | Set to `true` when editor container is in `mobile` breakpoint | +| `isTouchScreen` | `boolean` | Set to `true` for `touch` when touch event detected | ### i18n @@ -382,3 +386,94 @@ function App() { ); } ``` + +### getCommonBounds + +This util can be used to get the common bounds of the passed elements. + +**_Signature_** + +```ts +getCommonBounds( + elements: readonly ExcalidrawElement[] +): readonly [ + minX: number, + minY: number, + maxX: number, + maxY: number, +] +``` + +**_How to use_** + +```js +import { getCommonBounds } from "@excalidraw/excalidraw"; +``` + +### elementsOverlappingBBox + +To filter `elements` that are inside, overlap, or contain the `bounds` rectangle. + +The bounds check is approximate and does not precisely follow the element's shape. You can also supply `errorMargin` which effectively makes the `bounds` larger by that amount. + +This API has 3 `type`s of operation: `overlap`, `contain`, and `inside`: + +- `overlap` - filters elements that are overlapping or inside bounds. +- `contain` - filters elements that are inside bounds or bounds inside elements. +- `inside` - filters elements that are inside bounds. + +**_Signature_** + +
+elementsOverlappingBBox(
  + elements: readonly NonDeletedExcalidrawElement[];
  + bounds: Bounds | ExcalidrawElement;
  + errorMargin?: number;
  + type: "overlap" | "contain" | "inside";
+): NonDeletedExcalidrawElement[]; +
+ +**_How to use_** + +```js +import { elementsOverlappingBBox } from "@excalidraw/excalidraw"; +``` + +### isElementInsideBBox + +Lower-level API than `elementsOverlappingBBox` to check if a single `element` is inside `bounds`. If `eitherDirection=true`, returns `true` if `element` is fully inside `bounds` rectangle, or vice versa. When `false`, it returns `true` only for the former case. + +**_Signature_** + +
+isElementInsideBBox(
  + element: NonDeletedExcalidrawElement,
  + bounds: Bounds,
  + eitherDirection = false,
+): boolean +
+ +**_How to use_** + +```js +import { isElementInsideBBox } from "@excalidraw/excalidraw"; +``` + +### elementPartiallyOverlapsWithOrContainsBBox + +Checks if `element` is overlapping the `bounds` rectangle, or is fully inside. + +**_Signature_** + +
+elementPartiallyOverlapsWithOrContainsBBox(
  + element: NonDeletedExcalidrawElement,
  + bounds: Bounds,
+): boolean +
+ +**_How to use_** + +```js +import { elementPartiallyOverlapsWithOrContainsBBox } from "@excalidraw/excalidraw"; +``` diff --git a/dev-docs/docs/@excalidraw/excalidraw/faq.mdx b/dev-docs/docs/@excalidraw/excalidraw/faq.mdx index 4274972ab..5c66a603f 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/faq.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/faq.mdx @@ -31,6 +31,17 @@ We strongly recommend turning it off. You can follow the steps below on how to d If disabling this setting doesn't fix the display of text elements, please consider opening an [issue](https://github.com/excalidraw/excalidraw/issues/new) on our GitHub, or message us on [Discord](https://discord.gg/UexuTaE). +### ReferenceError: process is not defined + +When using `vite` or any build tools, you will have to make sure the `process` is accessible as we are accessing `process.env.IS_PREACT` to decide whether to use `preact` build. + +Since Vite removes env variables by default, you can update the vite config to ensure its available :point_down: + +``` + define: { + "process.env.IS_PREACT": process.env.IS_PREACT, + }, +``` ## Need help? diff --git a/dev-docs/docs/@excalidraw/excalidraw/integration.mdx b/dev-docs/docs/@excalidraw/excalidraw/integration.mdx index 6eada99ec..aa8e002c5 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/integration.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/integration.mdx @@ -30,32 +30,17 @@ function App() { } ``` -### Rendering Excalidraw only on client +### Next.js Since _Excalidraw_ doesn't support server side rendering, you should render the component once the host is `mounted`. Here are two ways on how you can render **Excalidraw** on **Next.js**. -1. Importing Excalidraw once **client** is rendered. -```jsx showLineNumbers -import { useState, useEffect } from "react"; -export default function App() { - const [Excalidraw, setExcalidraw] = useState(null); - useEffect(() => { - import("@excalidraw/excalidraw").then((comp) => - setExcalidraw(comp.Excalidraw), - ); - }, []); - return <>{Excalidraw && }; -} -``` -Here is a working [demo](https://codesandbox.io/p/sandbox/excalidraw-with-next-5xb3d) +1. Using **Next.js Dynamic** import [Recommended]. -2. Using **Next.js Dynamic** import. - -Since Excalidraw doesn't server side rendering so you can also use `dynamic import` to render by setting `ssr` to `false`. However one drawback is the `Refs` don't work with dynamic import in Next.js. We are working on overcoming this and have a better API. +Since Excalidraw doesn't support server side rendering so you can also use `dynamic import` to render by setting `ssr` to `false`. ```jsx showLineNumbers import dynamic from "next/dynamic"; @@ -72,8 +57,47 @@ export default function App() { Here is a working [demo](https://codesandbox.io/p/sandbox/excalidraw-with-next-dynamic-k8yjq2). + +2. Importing Excalidraw once **client** is rendered. + +```jsx showLineNumbers +import { useState, useEffect } from "react"; +export default function App() { + const [Excalidraw, setExcalidraw] = useState(null); + useEffect(() => { + import("@excalidraw/excalidraw").then((comp) => + setExcalidraw(comp.Excalidraw), + ); + }, []); + return <>{Excalidraw && }; +} +``` + +Here is a working [demo](https://codesandbox.io/p/sandbox/excalidraw-with-next-5xb3d) + The `types` are available at `@excalidraw/excalidraw/types`, you can view [example for typescript](https://codesandbox.io/s/excalidraw-types-9h2dm) +### Preact + +Since we support `umd` build ships with `react/jsx-runtime` and `react-dom/client` inlined with the package. This conflicts with `Preact` and hence the build doesn't work directly with `Preact`. + +However we have shipped a separate build for `Preact` so if you are using `Preact` you need to set `process.env.IS_PREACT` to `true` to use the `Preact` build. + +Once the above `env` variable is set, you will be able to use the package in `Preact` as well. + +:::info + +When using `vite` or any build tools, you will have to make sure the `process` is accessible as we are accessing `process.env.IS_PREACT` to decide whether to use `preact` build. + +Since Vite removes env variables by default, you can update the vite config to ensure its available :point_down: + +``` + define: { + "process.env.IS_PREACT": process.env.IS_PREACT, + }, +``` +::: + ## Browser To use it in a browser directly: diff --git a/dev-docs/docusaurus.config.js b/dev-docs/docusaurus.config.js index 706101f66..6b1c0d469 100644 --- a/dev-docs/docusaurus.config.js +++ b/dev-docs/docusaurus.config.js @@ -1,6 +1,11 @@ // @ts-check // Note: type annotations allow type checking and IDEs autocompletion +// Set the env variable to false so the excalidraw npm package doesn't throw +// process undefined as docusaurus doesn't expose env variables by default + +process.env.IS_PREACT = "false"; + /** @type {import('@docusaurus/types').Config} */ const config = { title: "Excalidraw developer docs", @@ -139,7 +144,15 @@ const config = { }, }), themes: ["@docusaurus/theme-live-codeblock"], - plugins: ["docusaurus-plugin-sass"], + plugins: [ + "docusaurus-plugin-sass", + [ + "docusaurus2-dotenv", + { + systemvars: true, + }, + ], + ], }; module.exports = config; diff --git a/dev-docs/package.json b/dev-docs/package.json index 4601891c9..baaee2fa5 100644 --- a/dev-docs/package.json +++ b/dev-docs/package.json @@ -18,7 +18,7 @@ "@docusaurus/core": "2.2.0", "@docusaurus/preset-classic": "2.2.0", "@docusaurus/theme-live-codeblock": "2.2.0", - "@excalidraw/excalidraw": "0.15.2-eb020d0", + "@excalidraw/excalidraw": "0.17.0-7284-25ea35d", "@mdx-js/react": "^1.6.22", "clsx": "^1.2.1", "docusaurus-plugin-sass": "0.2.3", @@ -30,6 +30,7 @@ "devDependencies": { "@docusaurus/module-type-aliases": "2.0.0-rc.1", "@tsconfig/docusaurus": "^1.0.5", + "docusaurus2-dotenv": "1.4.0", "typescript": "^4.7.4" }, "browserslist": { diff --git a/dev-docs/sidebars.js b/dev-docs/sidebars.js index 2b4ab8d86..8510ef135 100644 --- a/dev-docs/sidebars.js +++ b/dev-docs/sidebars.js @@ -53,7 +53,7 @@ const sidebars = { }, items: [ "@excalidraw/excalidraw/api/props/initialdata", - "@excalidraw/excalidraw/api/props/ref", + "@excalidraw/excalidraw/api/props/excalidraw-api", "@excalidraw/excalidraw/api/props/render-props", "@excalidraw/excalidraw/api/props/ui-options", ], diff --git a/dev-docs/yarn.lock b/dev-docs/yarn.lock index b22621f31..f343e051d 100644 --- a/dev-docs/yarn.lock +++ b/dev-docs/yarn.lock @@ -1718,10 +1718,10 @@ url-loader "^4.1.1" webpack "^5.73.0" -"@excalidraw/excalidraw@0.15.2-eb020d0": - version "0.15.2-eb020d0" - resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.15.2-eb020d0.tgz#25bd61e6f23da7c084fb16a3e0fe0dd9ad8e6533" - integrity sha512-TKGLzpOVqFQcwK1GFKTDXgg1s2U6tc5KE3qXuv87osbzOtftQn3x4+VH61vwdj11l00nEN80SMdXUC43T9uJqQ== +"@excalidraw/excalidraw@0.17.0-7284-25ea35d": + version "0.17.0-7284-25ea35d" + resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.17.0-7284-25ea35d.tgz#dd42ccc757e81d064f55bb0cac96c344fb557358" + integrity sha512-VVe0bdnmsZeIcbfoK2DgJefWmCmyQDFRvssCfxP3l2g/W8/6uKiKG+WNylu1D9dGveMfg1Io7XG2/PGRyD8OrQ== "@hapi/hoek@^9.0.0": version "9.3.0" @@ -3567,6 +3567,13 @@ docusaurus-plugin-sass@0.2.3: dependencies: sass-loader "^10.1.1" +docusaurus2-dotenv@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/docusaurus2-dotenv/-/docusaurus2-dotenv-1.4.0.tgz#9ab900e29de9081f9f1f28f7224ff63760385641" + integrity sha512-iWqem5fnBAyeBBtX75Fxp71uUAnwFaXzOmade8zAhN4vL3RG9m27sLSRwjJGVVgIkEo3esjGyCcTGTiCjfi+sg== + dependencies: + dotenv-webpack "1.7.0" + dom-converter@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" @@ -3652,6 +3659,25 @@ dot-prop@^5.2.0: dependencies: is-obj "^2.0.0" +dotenv-defaults@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/dotenv-defaults/-/dotenv-defaults-1.1.1.tgz#032c024f4b5906d9990eb06d722dc74cc60ec1bd" + integrity sha512-6fPRo9o/3MxKvmRZBD3oNFdxODdhJtIy1zcJeUSCs6HCy4tarUpd+G67UTU9tF6OWXeSPqsm4fPAB+2eY9Rt9Q== + dependencies: + dotenv "^6.2.0" + +dotenv-webpack@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/dotenv-webpack/-/dotenv-webpack-1.7.0.tgz#4384d8c57ee6f405c296278c14a9f9167856d3a1" + integrity sha512-wwNtOBW/6gLQSkb8p43y0Wts970A3xtNiG/mpwj9MLUhtPCQG6i+/DSXXoNN7fbPCU/vQ7JjwGmgOeGZSSZnsw== + dependencies: + dotenv-defaults "^1.0.2" + +dotenv@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064" + integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w== + duplexer3@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" diff --git a/src/packages/excalidraw/CHANGELOG.md b/src/packages/excalidraw/CHANGELOG.md index 203da05b2..8110aad84 100644 --- a/src/packages/excalidraw/CHANGELOG.md +++ b/src/packages/excalidraw/CHANGELOG.md @@ -206,7 +206,7 @@ Please add the latest change on the top under the correct section. - Support creating containers, linear elements, text containers, labelled arrows and arrow bindings programatically [#6546](https://github.com/excalidraw/excalidraw/pull/6546) - Introducing Web-Embeds (alias iframe element)[#6691](https://github.com/excalidraw/excalidraw/pull/6691) - Added [`props.validateEmbeddable`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props#validateEmbeddable) to customize embeddable src url validation. [#6691](https://github.com/excalidraw/excalidraw/pull/6691) -- Add support for `opts.fitToViewport` and `opts.viewportZoomFactor` in the [`ExcalidrawAPI.scrollToContent`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/ref#scrolltocontent) API. [#6581](https://github.com/excalidraw/excalidraw/pull/6581). +- Add support for `opts.fitToViewport` and `opts.viewportZoomFactor` in the [`ExcalidrawAPI.scrollToContent`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/excalidraw-api#scrolltocontent) API. [#6581](https://github.com/excalidraw/excalidraw/pull/6581). - Properly sanitize element `link` urls. [#6728](https://github.com/excalidraw/excalidraw/pull/6728). - Sidebar component now supports tabs — for more detailed description of new behavior and breaking changes, see the linked PR. [#6213](https://github.com/excalidraw/excalidraw/pull/6213) - Exposed `DefaultSidebar` component to allow modifying the default sidebar, such as adding custom tabs to it. [#6213](https://github.com/excalidraw/excalidraw/pull/6213) @@ -485,7 +485,7 @@ Please add the latest change on the top under the correct section. ### Features -- [`ExcalidrawAPI.scrollToContent`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/ref#scrolltocontent) has new opts object allowing you to fit viewport to content, and animate the scrolling. [#6319](https://github.com/excalidraw/excalidraw/pull/6319) +- [`ExcalidrawAPI.scrollToContent`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/excalidraw-api#scrolltocontent) has new opts object allowing you to fit viewport to content, and animate the scrolling. [#6319](https://github.com/excalidraw/excalidraw/pull/6319) - Expose `useI18n()` hook return an object containing `t()` i18n helper and current `langCode`. You can use this in components you render as `` children to render any of our i18n locale strings. [#6224](https://github.com/excalidraw/excalidraw/pull/6224)