diff options
| author | kj_sh604 | 2026-03-15 16:19:35 -0400 |
|---|---|---|
| committer | kj_sh604 | 2026-03-15 16:19:35 -0400 |
| commit | bc297e5e496d9f48ef77581b7fb41fdf328a62cf (patch) | |
| tree | 66192466eef76ee4c5cf71a9788ae9fe947514d4 /dev-docs/docs/@excalidraw/excalidraw/integration.mdx | |
| parent | f6538b8f1a78a7d72a41916ac79376f8c2d30193 (diff) | |
refactor: dev-docs/
Diffstat (limited to 'dev-docs/docs/@excalidraw/excalidraw/integration.mdx')
| -rw-r--r-- | dev-docs/docs/@excalidraw/excalidraw/integration.mdx | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/dev-docs/docs/@excalidraw/excalidraw/integration.mdx b/dev-docs/docs/@excalidraw/excalidraw/integration.mdx new file mode 100644 index 0000000..117877b --- /dev/null +++ b/dev-docs/docs/@excalidraw/excalidraw/integration.mdx @@ -0,0 +1,238 @@ +# Integration + +## Module bundler + +If you are using a module bundler (for instance, Webpack), you can import it as an ES6 module as shown below + +```js +import { Excalidraw } from "@excalidraw/excalidraw"; +``` + +:::info + +Throughout the documentation we use live, editable Excalidraw examples like the one shown below. + +While we aim for the examples to closely reflect what you'd get if you rendered it yourself, we actually initialize it with some props behind the scenes. +For example, we're passing a `theme` prop to it based on the current color theme of the docs you're just reading. + +::: + +```jsx live +function App() { + return ( + <> + <h1 style={{ textAlign: "center" }}>Excalidraw Example</h1> + <div style={{ height: "500px" }}> + <Excalidraw /> + </div> + </> + ); +} +``` + +### Next.js + +Since Excalidraw doesn't support `server side rendering` so it should be rendered only on `client`. The way to achieve this in next.js is using `next.js dynamic import`. + +If you want to only import `Excalidraw` component you can do :point_down: + +```jsx showLineNumbers +import dynamic from "next/dynamic"; +const Excalidraw = dynamic( + async () => (await import("@excalidraw/excalidraw")).Excalidraw, + { + ssr: false, + }, +); +export default function App() { + return <Excalidraw />; +} +``` + +However the above component only works for named component exports. If you want to import some util / constant or something else apart from Excalidraw, then this approach will not work. Instead you can write a wrapper over Excalidraw and import the wrapper dynamically. + +If you are using `pages router` then importing the wrapper dynamically would work, where as if you are using `app router` then you will have to also add `useClient` directive on top of the file in addition to dynamically importing the wrapper as shown :point_down: + +<Tabs> + <TabItem value="Excalidraw Wrapper" label="Excalidraw Wrapper" > + + ```jsx showLineNumbers + "use client"; + import { Excalidraw, convertToExcalidrawElements } from "@excalidraw/excalidraw"; + + import "@excalidraw/excalidraw/index.css"; + + const ExcalidrawWrapper: React.FC = () => { + console.info(convertToExcalidrawElements([{ + type: "rectangle", + id: "rect-1", + width: 186.47265625, + height: 141.9765625, + },])); + return ( + <div style={{height:"500px", width:"500px"}}> + <Excalidraw /> + </div> + ); + }; + export default ExcalidrawWrapper; + ``` + + </TabItem> + + <TabItem value="pages" label="Pages router"> + + ```jsx showLineNumbers + import dynamic from "next/dynamic"; + + // Since client components get prerenderd on server as well hence importing + // the excalidraw stuff dynamically with ssr false + + const ExcalidrawWrapper = dynamic( + async () => (await import("../excalidrawWrapper")).default, + { + ssr: false, + }, + ); + + export default function Page() { + return ( + <ExcalidrawWrapper /> + ); + } + ``` + </TabItem> + + <TabItem value="app" label="App router"> + + ```jsx showLineNumbers + import dynamic from "next/dynamic"; + + // Since client components get prerenderd on server as well hence importing + // the excalidraw stuff dynamically with ssr false + + const ExcalidrawWrapper = dynamic( + async () => (await import("../excalidrawWrapper")).default, + { + ssr: false, + }, + ); + + export default function Page() { + return ( + <ExcalidrawWrapper /> + ); + } + ``` + + </TabItem> +</Tabs> + +{/* Link should be updated to point to the latest! */} +Here is a [source code](https://github.com/excalidraw/excalidraw/tree/master/examples/with-nextjs) for the example with app and pages router. You you can try it out [here](https://excalidraw-package-example-with-nextjs.vercel.app/). + +The `types` are available at `@excalidraw/excalidraw/types`, check [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/master/examples/with-script-in-browser) example for details. + +### 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": JSON.stringify("true"), + }, +``` +::: + +## Browser + +To use it Excalidraw in a browser directly, use the following setup :point_down: + +> **Note**: We rely on import maps to de-duplicate `react`, `react-dom` and `react/jsx-runtime` versions. + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +<Tabs> + <TabItem value="html" label="html"> + +```html +<!DOCTYPE html> +<html> + <head> + <title>Excalidraw in browser</title> + <meta charset="UTF-8" /> + <link + rel="stylesheet" + href="https://esm.sh/@excalidraw/excalidraw@0.18.0/dist/dev/index.css" + /> + <link rel="stylesheet" href="./index.css" /> + <script> + window.EXCALIDRAW_ASSET_PATH = "https://esm.sh/@excalidraw/excalidraw@0.18.0/dist/prod/"; + </script> + <script type="importmap"> + { + "imports": { + "react": "https://esm.sh/react@19.0.0", + "react/jsx-runtime": "https://esm.sh/react@19.0.0/jsx-runtime", + "react-dom": "https://esm.sh/react-dom@19.0.0" + } + } + </script> + </head> + + <body> + <div class="container"> + <h1>Excalidraw Embed Example</h1> + <div id="app"></div> + </div> + <script type="text/javascript" src="packages/excalidraw/index.js"></script> + </body> +</html> +``` + +</TabItem> +<TabItem value="js" label="Javascript"> + +```js showLineNumbers +// See https://www.npmjs.com/package/@excalidraw/excalidraw documentation. +import * as ExcalidrawLib from 'https://esm.sh/@excalidraw/excalidraw@0.18.0/dist/dev/index.js?external=react,react-dom'; +import React from "https://esm.sh/react@19.0.0"; +import ReactDOM from "https://esm.sh/react-dom@19.0.0" + +window.ExcalidrawLib = ExcalidrawLib; +console.log("Excalidraw library", ExcalidrawLib); + +const App = () => { + return React.createElement( + React.Fragment, + null, + React.createElement( + "div", + { + style: { height: "500px" }, + }, + React.createElement(ExcalidrawLib.Excalidraw), + ), + ); +}; + +const excalidrawWrapper = document.getElementById("app"); +const root = ReactDOM.createRoot(excalidrawWrapper); +root.render(React.createElement(App)); +``` + +</TabItem> +</Tabs> + +You can try it out [here](https://jsfiddle.net/vfn6dm14/3/). |
