merge with master
5
.codesandbox/Dockerfile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
FROM node:18-bullseye
|
||||||
|
|
||||||
|
# Vite wants to open the browser using `open`, so we
|
||||||
|
# need to install those utils.
|
||||||
|
RUN apt update -y && apt install -y xdg-utils
|
@ -27,7 +27,10 @@
|
|||||||
"start": {
|
"start": {
|
||||||
"name": "Start Excalidraw",
|
"name": "Start Excalidraw",
|
||||||
"command": "yarn start",
|
"command": "yarn start",
|
||||||
"runAtStart": true
|
"runAtStart": true,
|
||||||
|
"preview": {
|
||||||
|
"port": 3000
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"name": "Run Tests",
|
"name": "Run Tests",
|
||||||
@ -37,7 +40,11 @@
|
|||||||
"install-deps": {
|
"install-deps": {
|
||||||
"name": "Install Dependencies",
|
"name": "Install Dependencies",
|
||||||
"command": "yarn install",
|
"command": "yarn install",
|
||||||
"restartOn": { "files": ["yarn.lock"] }
|
"restartOn": {
|
||||||
|
"files": ["yarn.lock"],
|
||||||
|
"branch": false,
|
||||||
|
"resume": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,15 @@
|
|||||||
!.eslintrc.json
|
!.eslintrc.json
|
||||||
!.npmrc
|
!.npmrc
|
||||||
!.prettierrc
|
!.prettierrc
|
||||||
|
!excalidraw-app/
|
||||||
!package.json
|
!package.json
|
||||||
!public/
|
!public/
|
||||||
!src/
|
!packages/
|
||||||
!tsconfig.json
|
!tsconfig.json
|
||||||
!yarn.lock
|
!yarn.lock
|
||||||
|
|
||||||
|
# keep (sub)sub directories at the end to exclude from explicit included
|
||||||
|
# e.g. ./packages/excalidraw/{dist,node_modules}
|
||||||
|
**/build
|
||||||
|
**/dist
|
||||||
|
**/node_modules
|
||||||
|
@ -1,29 +1,41 @@
|
|||||||
REACT_APP_BACKEND_V2_GET_URL=https://json-dev.excalidraw.com/api/v2/
|
VITE_APP_BACKEND_V2_GET_URL=https://json-dev.excalidraw.com/api/v2/
|
||||||
REACT_APP_BACKEND_V2_POST_URL=https://json-dev.excalidraw.com/api/v2/post/
|
VITE_APP_BACKEND_V2_POST_URL=https://json-dev.excalidraw.com/api/v2/post/
|
||||||
|
|
||||||
REACT_APP_LIBRARY_URL=https://libraries.excalidraw.com
|
VITE_APP_LIBRARY_URL=https://libraries.excalidraw.com
|
||||||
REACT_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
|
VITE_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
|
||||||
|
|
||||||
# collaboration WebSocket server (https://github.com/excalidraw/excalidraw-room)
|
# collaboration WebSocket server (https://github.com/excalidraw/excalidraw-room)
|
||||||
REACT_APP_WS_SERVER_URL=http://localhost:3002
|
VITE_APP_WS_SERVER_URL=http://localhost:3002
|
||||||
|
|
||||||
# set this only if using the collaboration workflow we use on excalidraw.com
|
VITE_APP_PLUS_LP=https://plus.excalidraw.com
|
||||||
REACT_APP_PORTAL_URL=
|
VITE_APP_PLUS_APP=https://app.excalidraw.com
|
||||||
|
|
||||||
REACT_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}'
|
VITE_APP_AI_BACKEND=http://localhost:3015
|
||||||
|
|
||||||
|
VITE_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}'
|
||||||
|
|
||||||
# put these in your .env.local, or make sure you don't commit!
|
# put these in your .env.local, or make sure you don't commit!
|
||||||
# must be lowercase `true` when turned on
|
# must be lowercase `true` when turned on
|
||||||
#
|
#
|
||||||
# whether to enable Service Workers in development
|
# whether to enable Service Workers in development
|
||||||
REACT_APP_DEV_ENABLE_SW=
|
VITE_APP_DEV_ENABLE_SW=
|
||||||
# whether to disable live reload / HMR. Usuaully what you want to do when
|
# whether to disable live reload / HMR. Usuaully what you want to do when
|
||||||
# debugging Service Workers.
|
# debugging Service Workers.
|
||||||
REACT_APP_DEV_DISABLE_LIVE_RELOAD=
|
VITE_APP_DEV_DISABLE_LIVE_RELOAD=
|
||||||
|
VITE_APP_DISABLE_TRACKING=true
|
||||||
|
|
||||||
FAST_REFRESH=false
|
FAST_REFRESH=false
|
||||||
|
|
||||||
|
# The port the run the dev server
|
||||||
|
VITE_APP_PORT=3000
|
||||||
|
|
||||||
#Debug flags
|
#Debug flags
|
||||||
|
|
||||||
# To enable bounding box for text containers
|
# To enable bounding box for text containers
|
||||||
REACT_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX=
|
VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX=
|
||||||
|
|
||||||
|
# Set this flag to false if you want to open the overlay by default
|
||||||
|
VITE_APP_COLLAPSE_OVERLAY=true
|
||||||
|
|
||||||
|
# Set this flag to false to disable eslint
|
||||||
|
VITE_APP_ENABLE_ESLINT=true
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
REACT_APP_BACKEND_V2_GET_URL=https://json.excalidraw.com/api/v2/
|
VITE_APP_BACKEND_V2_GET_URL=https://json.excalidraw.com/api/v2/
|
||||||
REACT_APP_BACKEND_V2_POST_URL=https://json.excalidraw.com/api/v2/post/
|
VITE_APP_BACKEND_V2_POST_URL=https://json.excalidraw.com/api/v2/post/
|
||||||
|
|
||||||
REACT_APP_LIBRARY_URL=https://libraries.excalidraw.com
|
VITE_APP_LIBRARY_URL=https://libraries.excalidraw.com
|
||||||
REACT_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
|
VITE_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
|
||||||
|
|
||||||
REACT_APP_PORTAL_URL=https://portal.excalidraw.com
|
VITE_APP_PLUS_LP=https://plus.excalidraw.com
|
||||||
# Fill to set socket server URL used for collaboration.
|
VITE_APP_PLUS_APP=https://app.excalidraw.com
|
||||||
# Meant for forks only: excalidraw.com uses custom REACT_APP_PORTAL_URL flow
|
|
||||||
REACT_APP_WS_SERVER_URL=
|
|
||||||
|
|
||||||
REACT_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyAd15pYlMci_xIp9ko6wkEsDzAAA0Dn0RU","authDomain":"excalidraw-room-persistence.firebaseapp.com","databaseURL":"https://excalidraw-room-persistence.firebaseio.com","projectId":"excalidraw-room-persistence","storageBucket":"excalidraw-room-persistence.appspot.com","messagingSenderId":"654800341332","appId":"1:654800341332:web:4a692de832b55bd57ce0c1"}'
|
VITE_APP_AI_BACKEND=https://oss-ai.excalidraw.com
|
||||||
|
|
||||||
# production-only vars
|
# socket server URL used for collaboration
|
||||||
REACT_APP_GOOGLE_ANALYTICS_ID=UA-387204-13
|
VITE_APP_WS_SERVER_URL=https://oss-collab.excalidraw.com
|
||||||
|
|
||||||
REACT_APP_PLUS_APP=https://app.excalidraw.com
|
VITE_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyAd15pYlMci_xIp9ko6wkEsDzAAA0Dn0RU","authDomain":"excalidraw-room-persistence.firebaseapp.com","databaseURL":"https://excalidraw-room-persistence.firebaseio.com","projectId":"excalidraw-room-persistence","storageBucket":"excalidraw-room-persistence.appspot.com","messagingSenderId":"654800341332","appId":"1:654800341332:web:4a692de832b55bd57ce0c1"}'
|
||||||
|
|
||||||
|
VITE_APP_DISABLE_TRACKING=
|
||||||
|
@ -5,4 +5,4 @@ package-lock.json
|
|||||||
firebase/
|
firebase/
|
||||||
dist/
|
dist/
|
||||||
public/workbox
|
public/workbox
|
||||||
src/packages/excalidraw/types
|
packages/excalidraw/types
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
"extends": ["@excalidraw/eslint-config", "react-app"],
|
"extends": ["@excalidraw/eslint-config", "react-app"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"import/no-anonymous-default-export": "off",
|
"import/no-anonymous-default-export": "off",
|
||||||
"no-restricted-globals": "off"
|
"no-restricted-globals": "off",
|
||||||
|
"@typescript-eslint/consistent-type-imports": ["error", { "prefer": "type-imports", "disallowTypeAnnotations": false, "fixStyle": "separate-type-imports" }]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
.github/assets/logo.png
vendored
Before Width: | Height: | Size: 20 KiB |
6
.github/workflows/autorelease-excalidraw.yml
vendored
@ -12,10 +12,10 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
- name: Setup Node.js 14.x
|
- name: Setup Node.js 18.x
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 14.x
|
node-version: 18.x
|
||||||
- name: Set up publish access
|
- name: Set up publish access
|
||||||
run: |
|
run: |
|
||||||
npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
|
npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
|
||||||
@ -23,5 +23,5 @@ jobs:
|
|||||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
- name: Auto release
|
- name: Auto release
|
||||||
run: |
|
run: |
|
||||||
yarn add @actions/core
|
yarn add @actions/core -W
|
||||||
yarn autorelease
|
yarn autorelease
|
||||||
|
6
.github/workflows/autorelease-preview.yml
vendored
@ -32,10 +32,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
ref: ${{ steps.sha.outputs.result }}
|
ref: ${{ steps.sha.outputs.result }}
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
- name: Setup Node.js 14.x
|
- name: Setup Node.js 18.x
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 14.x
|
node-version: 18.x
|
||||||
- name: Set up publish access
|
- name: Set up publish access
|
||||||
run: |
|
run: |
|
||||||
npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
|
npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
|
||||||
@ -44,7 +44,7 @@ jobs:
|
|||||||
- name: Auto release preview
|
- name: Auto release preview
|
||||||
id: "autorelease"
|
id: "autorelease"
|
||||||
run: |
|
run: |
|
||||||
yarn add @actions/core
|
yarn add @actions/core -W
|
||||||
yarn autorelease preview ${{ github.event.issue.number }}
|
yarn autorelease preview ${{ github.event.issue.number }}
|
||||||
- name: Post comment post release
|
- name: Post comment post release
|
||||||
if: always()
|
if: always()
|
||||||
|
6
.github/workflows/lint.yml
vendored
@ -9,14 +9,14 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Setup Node.js 14.x
|
- name: Setup Node.js 18.x
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 14.x
|
node-version: 18.x
|
||||||
|
|
||||||
- name: Install and lint
|
- name: Install and lint
|
||||||
run: |
|
run: |
|
||||||
yarn --frozen-lockfile
|
yarn install
|
||||||
yarn test:other
|
yarn test:other
|
||||||
yarn test:code
|
yarn test:code
|
||||||
yarn test:typecheck
|
yarn test:typecheck
|
||||||
|
8
.github/workflows/locales-coverage.yml
vendored
@ -14,19 +14,19 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
token: ${{ secrets.PUSH_TRANSLATIONS_COVERAGE_PAT }}
|
token: ${{ secrets.PUSH_TRANSLATIONS_COVERAGE_PAT }}
|
||||||
|
|
||||||
- name: Setup Node.js 14.x
|
- name: Setup Node.js 18.x
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 14.x
|
node-version: 18.x
|
||||||
|
|
||||||
- name: Create report file
|
- name: Create report file
|
||||||
run: |
|
run: |
|
||||||
yarn locales-coverage
|
yarn locales-coverage
|
||||||
FILE_CHANGED=$(git diff src/locales/percentages.json)
|
FILE_CHANGED=$(git diff packages/excalidraw/locales/percentages.json)
|
||||||
if [ ! -z "${FILE_CHANGED}" ]; then
|
if [ ! -z "${FILE_CHANGED}" ]; then
|
||||||
git config --global user.name 'Excalidraw Bot'
|
git config --global user.name 'Excalidraw Bot'
|
||||||
git config --global user.email 'bot@excalidraw.com'
|
git config --global user.email 'bot@excalidraw.com'
|
||||||
git add src/locales/percentages.json
|
git add packages/excalidraw/locales/percentages.json
|
||||||
git commit -am "Auto commit: Calculate translation coverage"
|
git commit -am "Auto commit: Calculate translation coverage"
|
||||||
git push
|
git push
|
||||||
fi
|
fi
|
||||||
|
2
.github/workflows/semantic-pr-title.yml
vendored
@ -1,7 +1,7 @@
|
|||||||
name: Semantic PR title
|
name: Semantic PR title
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request_target:
|
pull_request:
|
||||||
types:
|
types:
|
||||||
- opened
|
- opened
|
||||||
- edited
|
- edited
|
||||||
|
4
.github/workflows/sentry-production.yml
vendored
@ -10,10 +10,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Setup Node.js 14.x
|
- name: Setup Node.js 18.x
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 14.x
|
node-version: 18.x
|
||||||
- name: Install and build
|
- name: Install and build
|
||||||
run: |
|
run: |
|
||||||
yarn --frozen-lockfile
|
yarn --frozen-lockfile
|
||||||
|
28
.github/workflows/size-limit.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
name: "Bundle Size check @excalidraw/excalidraw"
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
jobs:
|
||||||
|
size:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
CI_JOB_NUMBER: 1
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Setup Node.js 18.x
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 18.x
|
||||||
|
- name: Install in packages/excalidraw
|
||||||
|
run: yarn
|
||||||
|
working-directory: packages/excalidraw
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
- uses: andresz1/size-limit-action@v1
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
build_script: build:esm
|
||||||
|
skip_step: install
|
||||||
|
directory: packages/excalidraw
|
26
.github/workflows/test-coverage-pr.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
name: Test Coverage PR
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
coverage:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: "Install Node"
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: "18.x"
|
||||||
|
- name: "Install Deps"
|
||||||
|
run: yarn install
|
||||||
|
- name: "Test Coverage"
|
||||||
|
run: yarn test:coverage
|
||||||
|
- name: "Report Coverage"
|
||||||
|
if: always() # Also generate the report if tests are failing
|
||||||
|
uses: davelosert/vitest-coverage-report-action@v2
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
6
.github/workflows/test.yml
vendored
@ -7,11 +7,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Setup Node.js 14.x
|
- name: Setup Node.js 18.x
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 14.x
|
node-version: 18.x
|
||||||
- name: Install and test
|
- name: Install and test
|
||||||
run: |
|
run: |
|
||||||
yarn --frozen-lockfile
|
yarn install
|
||||||
yarn test:app
|
yarn test:app
|
||||||
|
9
.gitignore
vendored
@ -21,8 +21,9 @@ npm-debug.log*
|
|||||||
package-lock.json
|
package-lock.json
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
src/packages/excalidraw/types
|
packages/excalidraw/types
|
||||||
src/packages/excalidraw/example/public/bundle.js
|
|
||||||
src/packages/excalidraw/example/public/excalidraw-assets-dev
|
|
||||||
src/packages/excalidraw/example/public/excalidraw.development.js
|
|
||||||
coverage
|
coverage
|
||||||
|
dev-dist
|
||||||
|
html
|
||||||
|
examples/**/bundle.*
|
||||||
|
meta*.json
|
@ -1,3 +0,0 @@
|
|||||||
## 2020-10-13
|
|
||||||
|
|
||||||
- Added ability to embed scene source into exported PNG/SVG files so you can import the scene from them (open via `Load` button or drag & drop). #2219
|
|
14
Dockerfile
@ -1,17 +1,19 @@
|
|||||||
FROM node:14-alpine AS build
|
FROM node:18 AS build
|
||||||
|
|
||||||
WORKDIR /opt/node_app
|
WORKDIR /opt/node_app
|
||||||
|
|
||||||
COPY package.json yarn.lock ./
|
COPY . .
|
||||||
RUN yarn --ignore-optional --network-timeout 600000
|
|
||||||
|
# do not ignore optional dependencies:
|
||||||
|
# Error: Cannot find module @rollup/rollup-linux-x64-gnu
|
||||||
|
RUN yarn --network-timeout 600000
|
||||||
|
|
||||||
ARG NODE_ENV=production
|
ARG NODE_ENV=production
|
||||||
|
|
||||||
COPY . .
|
|
||||||
RUN yarn build:app:docker
|
RUN yarn build:app:docker
|
||||||
|
|
||||||
FROM nginx:1.21-alpine
|
FROM nginx:1.24-alpine
|
||||||
|
|
||||||
COPY --from=build /opt/node_app/build /usr/share/nginx/html
|
COPY --from=build /opt/node_app/excalidraw-app/build /usr/share/nginx/html
|
||||||
|
|
||||||
HEALTHCHECK CMD wget -q -O /dev/null http://localhost || exit 1
|
HEALTHCHECK CMD wget -q -O /dev/null http://localhost || exit 1
|
||||||
|
15
README.md
@ -1,7 +1,7 @@
|
|||||||
<a href="https://excalidraw.com/" target="_blank" rel="noopener">
|
<a href="https://excalidraw.com/" target="_blank" rel="noopener">
|
||||||
<picture>
|
<picture>
|
||||||
<source media="(prefers-color-scheme: dark)" alt="Excalidraw" srcset="https://excalidraw.nyc3.cdn.digitaloceanspaces.com/github%2FExcalidraw_Github_cover_dark.png" />
|
<source media="(prefers-color-scheme: dark)" alt="Excalidraw" srcset="https://excalidraw.nyc3.cdn.digitaloceanspaces.com/github/excalidraw_github_cover_2_dark.png" />
|
||||||
<img alt="Excalidraw" src="https://excalidraw.nyc3.cdn.digitaloceanspaces.com/github%2FExcalidraw_Github_cover.png" />
|
<img alt="Excalidraw" src="https://excalidraw.nyc3.cdn.digitaloceanspaces.com/github/excalidraw_github_cover_2.png" />
|
||||||
</picture>
|
</picture>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -17,7 +17,7 @@
|
|||||||
An open source virtual hand-drawn style whiteboard. </br>
|
An open source virtual hand-drawn style whiteboard. </br>
|
||||||
Collaborative and end-to-end encrypted. </br>
|
Collaborative and end-to-end encrypted. </br>
|
||||||
<br />
|
<br />
|
||||||
</h3>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
@ -25,6 +25,9 @@
|
|||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/LICENSE">
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/LICENSE">
|
||||||
<img alt="Excalidraw is released under the MIT license." src="https://img.shields.io/badge/license-MIT-blue.svg" />
|
<img alt="Excalidraw is released under the MIT license." src="https://img.shields.io/badge/license-MIT-blue.svg" />
|
||||||
</a>
|
</a>
|
||||||
|
<a href="https://www.npmjs.com/package/@excalidraw/excalidraw">
|
||||||
|
<img alt="npm downloads/month" src="https://img.shields.io/npm/dm/@excalidraw/excalidraw" />
|
||||||
|
</a>
|
||||||
<a href="https://docs.excalidraw.com/docs/introduction/contributing">
|
<a href="https://docs.excalidraw.com/docs/introduction/contributing">
|
||||||
<img alt="PRs welcome!" src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" />
|
<img alt="PRs welcome!" src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" />
|
||||||
</a>
|
</a>
|
||||||
@ -70,7 +73,7 @@ The Excalidraw editor (npm package) supports:
|
|||||||
|
|
||||||
## Excalidraw.com
|
## Excalidraw.com
|
||||||
|
|
||||||
The app hosted at [excalidraw.com](https://excalidraw.com) is a minimal showcase of what you can build with Excalidraw. Its [source code](https://github.com/excalidraw/excalidraw/tree/master/src/excalidraw-app) is part of this repository as well, and the app features:
|
The app hosted at [excalidraw.com](https://excalidraw.com) is a minimal showcase of what you can build with Excalidraw. Its [source code](https://github.com/excalidraw/excalidraw/tree/master/excalidraw-app) is part of this repository as well, and the app features:
|
||||||
|
|
||||||
- 📡 PWA support (works offline).
|
- 📡 PWA support (works offline).
|
||||||
- 🤼 Real-time collaboration.
|
- 🤼 Real-time collaboration.
|
||||||
@ -82,7 +85,7 @@ We'll be adding these features as drop-in plugins for the npm package in the fut
|
|||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
Install the [Excalidraw npm package](https://www.npmjs.com/package/@excalidraw/excalidraw):
|
**Note:** following instructions are for installing the Excalidraw [npm package](https://www.npmjs.com/package/@excalidraw/excalidraw) when integrating Excalidraw into your own app. To run the repository locally for development, please refer to our [Development Guide](https://docs.excalidraw.com/docs/introduction/development).
|
||||||
|
|
||||||
```
|
```
|
||||||
npm install react react-dom @excalidraw/excalidraw
|
npm install react react-dom @excalidraw/excalidraw
|
||||||
@ -94,7 +97,7 @@ or via yarn
|
|||||||
yarn add react react-dom @excalidraw/excalidraw
|
yarn add react react-dom @excalidraw/excalidraw
|
||||||
```
|
```
|
||||||
|
|
||||||
Don't forget to check out our [Documentation](https://docs.excalidraw.com)!
|
Check out our [documentation](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/installation) for more details!
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
files:
|
files:
|
||||||
- source: /src/locales/en.json
|
- source: /packages/excalidraw/locales/en.json
|
||||||
translation: /src/locales/%locale%.json
|
translation: /packages/excalidraw/locales/%locale%.json
|
||||||
|
@ -17,5 +17,6 @@ Below are the currently supported components:
|
|||||||
|
|
||||||
- [MainMenu](/docs/@excalidraw/excalidraw/api/children-components/main-menu)
|
- [MainMenu](/docs/@excalidraw/excalidraw/api/children-components/main-menu)
|
||||||
- [WelcomeScreen](/docs/@excalidraw/excalidraw/api/children-components/welcome-screen)
|
- [WelcomeScreen](/docs/@excalidraw/excalidraw/api/children-components/welcome-screen)
|
||||||
|
- [Sidebar](/docs/@excalidraw/excalidraw/api/children-components/sidebar)
|
||||||
- [Footer](/docs/@excalidraw/excalidraw/api/children-components/footer)
|
- [Footer](/docs/@excalidraw/excalidraw/api/children-components/footer)
|
||||||
- [LiveCollaborationTrigger](/docs/@excalidraw/excalidraw/api/children-components/live-collaboration-trigger)
|
- [LiveCollaborationTrigger](/docs/@excalidraw/excalidraw/api/children-components/live-collaboration-trigger)
|
||||||
|
@ -16,7 +16,6 @@ function App() {
|
|||||||
className="custom-footer"
|
className="custom-footer"
|
||||||
onClick={() => alert("This is dummy footer")}
|
onClick={() => alert("This is dummy footer")}
|
||||||
>
|
>
|
||||||
{" "}
|
|
||||||
custom footer
|
custom footer
|
||||||
</button>
|
</button>
|
||||||
</Footer>
|
</Footer>
|
||||||
@ -35,7 +34,7 @@ Open the `Menu` in the below playground and you will see the `custom footer` ren
|
|||||||
```jsx live noInline
|
```jsx live noInline
|
||||||
const MobileFooter = ({}) => {
|
const MobileFooter = ({}) => {
|
||||||
const device = useDevice();
|
const device = useDevice();
|
||||||
if (device.isMobile) {
|
if (device.editor.isMobile) {
|
||||||
return (
|
return (
|
||||||
<Footer>
|
<Footer>
|
||||||
<button
|
<button
|
||||||
|
@ -14,8 +14,7 @@ function App() {
|
|||||||
Item1
|
Item1
|
||||||
</MainMenu.Item>
|
</MainMenu.Item>
|
||||||
<MainMenu.Item onSelect={() => window.alert("Item2")}>
|
<MainMenu.Item onSelect={() => window.alert("Item2")}>
|
||||||
{" "}
|
Item 2
|
||||||
Item 2{" "}
|
|
||||||
</MainMenu.Item>
|
</MainMenu.Item>
|
||||||
</MainMenu>
|
</MainMenu>
|
||||||
</Excalidraw>
|
</Excalidraw>
|
||||||
@ -39,6 +38,7 @@ To render an item, its recommended to use `MainMenu.Item`.
|
|||||||
| Prop | Type | Required | Default | Description |
|
| Prop | Type | Required | Default | Description |
|
||||||
| --- | --- | :-: | :-: | --- |
|
| --- | --- | :-: | :-: | --- |
|
||||||
| `onSelect` | `function` | Yes | - | Triggered when selected (via mouse). Calling `event.preventDefault()` will stop menu from closing. |
|
| `onSelect` | `function` | Yes | - | Triggered when selected (via mouse). Calling `event.preventDefault()` will stop menu from closing. |
|
||||||
|
| `selected` | `boolean` | No | `false` | Whether item is active |
|
||||||
| `children` | `React.ReactNode` | Yes | - | The content of the menu item |
|
| `children` | `React.ReactNode` | Yes | - | The content of the menu item |
|
||||||
| `icon` | `JSX.Element` | No | - | The icon used in the menu item |
|
| `icon` | `JSX.Element` | No | - | The icon used in the menu item |
|
||||||
| `shortcut` | `string` | No | - | The shortcut to be shown for the menu item |
|
| `shortcut` | `string` | No | - | The shortcut to be shown for the menu item |
|
||||||
@ -71,6 +71,7 @@ function App() {
|
|||||||
| Prop | Type | Required | Default | Description |
|
| Prop | Type | Required | Default | Description |
|
||||||
| --- | --- | :-: | :-: | --- |
|
| --- | --- | :-: | :-: | --- |
|
||||||
| `onSelect` | `function` | No | - | Triggered when selected (via mouse). Calling `event.preventDefault()` will stop menu from closing. |
|
| `onSelect` | `function` | No | - | Triggered when selected (via mouse). Calling `event.preventDefault()` will stop menu from closing. |
|
||||||
|
| `selected` | `boolean` | No | `false` | Whether item is active |
|
||||||
| `href` | `string` | Yes | - | The `href` attribute to be added to the `anchor` element. |
|
| `href` | `string` | Yes | - | The `href` attribute to be added to the `anchor` element. |
|
||||||
| `children` | `React.ReactNode` | Yes | - | The content of the menu item |
|
| `children` | `React.ReactNode` | Yes | - | The content of the menu item |
|
||||||
| `icon` | `JSX.Element` | No | - | The icon used in the menu item |
|
| `icon` | `JSX.Element` | No | - | The icon used in the menu item |
|
||||||
@ -93,7 +94,6 @@ function App() {
|
|||||||
style={{ height: "2rem" }}
|
style={{ height: "2rem" }}
|
||||||
onClick={() => window.alert("custom menu item")}
|
onClick={() => window.alert("custom menu item")}
|
||||||
>
|
>
|
||||||
{" "}
|
|
||||||
custom item
|
custom item
|
||||||
</button>
|
</button>
|
||||||
</MainMenu.ItemCustom>
|
</MainMenu.ItemCustom>
|
||||||
@ -133,7 +133,7 @@ function App() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Here is a [complete list](https://github.com/excalidraw/excalidraw/blob/master/src/components/mainMenu/DefaultItems.tsx) of the default items.
|
Here is a [complete list](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/components/mainMenu/DefaultItems.tsx) of the default items.
|
||||||
|
|
||||||
### MainMenu.Group
|
### MainMenu.Group
|
||||||
|
|
||||||
|
@ -0,0 +1,129 @@
|
|||||||
|
# Sidebar
|
||||||
|
|
||||||
|
The editor comes with a default sidebar on the right in LTR (Left to Right) mode which contains the library. You can also add your own custom sidebar(s) by rendering this component as a child of `<Excalidraw>`.
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
| Prop | Type | Required | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `name` | `string` | Yes | Sidebar name that uniquely identifies it. |
|
||||||
|
| `children` | `React.ReactNode` | Yes | Content you want to render inside the sidebar. |
|
||||||
|
| `onStateChange` | `(state: AppState["openSidebar"]) => void` | No | Invoked on open/close or tab change. No need to act on this event, as the editor manages the sidebar open state on its own. |
|
||||||
|
| `onDock` | `(docked: boolean) => void` | No | Invoked when the user toggles the `dock` button. Passed the current docked state. |
|
||||||
|
| `docked` | `boolean` | No | Indicates whether the sidebar is `docked`. By default, the sidebar is `undocked`. If passed, the docking becomes controlled. |
|
||||||
|
| `className` | `string` | No | |
|
||||||
|
| `style` | `React.CSSProperties` | No | |
|
||||||
|
|
||||||
|
At minimum, each sidebar needs to have a unique `name` prop, and render some content inside it, which can be either composed from the exported sidebar sub-components, or custom elements.
|
||||||
|
|
||||||
|
Unless `docked={true}` is passed, the sidebar will close when the user clicks outside of it. It can also be closed using the close button in the header, if you render the `<Sidebar.Header>` component.
|
||||||
|
|
||||||
|
Further, if the sidebader doesn't comfortably fit in the editor, it won't be dockable. To decide the breakpoint for docking you can use [UIOptions.dockedSidebarBreakpoint](/docs/@excalidraw/excalidraw/api/props/ui-options#dockedsidebarbreakpoint).
|
||||||
|
|
||||||
|
To make your sidebar user-dockable, you need to supply `props.docked` (current docked state) alongside `props.onDock` callback (to listen for and handle docked state changes). The component doesn't track local state for the `docked` prop, so you need to manage it yourself.
|
||||||
|
|
||||||
|
## Sidebar.Header
|
||||||
|
|
||||||
|
| Prop | Type | Required | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `children` | `React.ReactNode` | No | Content you want to render inside the sidebar header next to the `close` / `dock` buttons. |
|
||||||
|
| `className` | `string` | No | |
|
||||||
|
|
||||||
|
Renders a sidebar header which contains a close button, and a dock button (when applicable). You can also render custom content in addition.
|
||||||
|
|
||||||
|
Can be nested inside specific tabs, or rendered as direct child of `<Sidebar>` for the whole sidebar component.
|
||||||
|
|
||||||
|
## Sidebar.Tabs
|
||||||
|
|
||||||
|
| Prop | Type | Required | Description |
|
||||||
|
| ---------- | ----------------- | -------- | ------------------------------ |
|
||||||
|
| `children` | `React.ReactNode` | No | Container for individual tabs. |
|
||||||
|
|
||||||
|
Sidebar may contain inner tabs. Each `<Sidebar.Tab>` must be rendered inside this `<Sidebar.Tabs>` container component.
|
||||||
|
|
||||||
|
## Sidebar.Tab
|
||||||
|
|
||||||
|
| Prop | Type | Required | Description |
|
||||||
|
| ---------- | ----------------- | -------- | ---------------- |
|
||||||
|
| `tab` | `string` | Yes | Unique tab name. |
|
||||||
|
| `children` | `React.ReactNode` | No | Tab content. |
|
||||||
|
|
||||||
|
Content of a given sidebar tab. It must be rendered inside `<Sidebar.Tabs>`.
|
||||||
|
|
||||||
|
## Sidebar.TabTriggers
|
||||||
|
|
||||||
|
| Prop | Type | Required | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `children` | `React.ReactNode` | No | Container for individual tab triggers. |
|
||||||
|
|
||||||
|
Container component for tab trigger buttons to switch between tabs.
|
||||||
|
|
||||||
|
## Sidebar.TabTrigger
|
||||||
|
|
||||||
|
| Prop | Type | Required | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `tab` | `string` | Yes | Tab name to toggle. |
|
||||||
|
| `children` | `React.ReactNode` | No | Tab trigger content, such as a label. |
|
||||||
|
|
||||||
|
A given tab trigger button that switches to a given sidebar tab. It must be rendered inside `<Sidebar.TabTriggers>`.
|
||||||
|
|
||||||
|
## Sidebar.Trigger
|
||||||
|
|
||||||
|
| Prop | Type | Required | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `name` | `string` | Yes | Sidebar name the trigger will control. |
|
||||||
|
| `tab` | `string` | No | Optional tab to open. |
|
||||||
|
| `onToggle` | `(open: boolean) => void` | No | Callback invoked on toggle. |
|
||||||
|
| `title` | `string` | No | A11y title. |
|
||||||
|
| `children` | `React.ReactNode` | No | Content (usually label) you want to render inside the button. |
|
||||||
|
| `icon` | `JSX.Element` | No | Trigger icon if any. |
|
||||||
|
| `className` | `string` | No | |
|
||||||
|
| `style` | `React.CSSProperties` | No | |
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
```tsx live
|
||||||
|
function App() {
|
||||||
|
const [docked, setDocked] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ height: "580px" }}>
|
||||||
|
<Excalidraw
|
||||||
|
UIOptions={{
|
||||||
|
// this effectively makes the sidebar dockable on any screen size,
|
||||||
|
// ignoring if it fits or not
|
||||||
|
dockedSidebarBreakpoint: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Sidebar name="custom" docked={docked} onDock={setDocked}>
|
||||||
|
<Sidebar.Header />
|
||||||
|
<Sidebar.Tabs style={{ padding: "0.5rem" }}>
|
||||||
|
<Sidebar.Tab tab="one">Tab one!</Sidebar.Tab>
|
||||||
|
<Sidebar.Tab tab="two">Tab two!</Sidebar.Tab>
|
||||||
|
<Sidebar.TabTriggers>
|
||||||
|
<Sidebar.TabTrigger tab="one">One</Sidebar.TabTrigger>
|
||||||
|
<Sidebar.TabTrigger tab="two">Two</Sidebar.TabTrigger>
|
||||||
|
</Sidebar.TabTriggers>
|
||||||
|
</Sidebar.Tabs>
|
||||||
|
</Sidebar>
|
||||||
|
|
||||||
|
<Footer>
|
||||||
|
<Sidebar.Trigger
|
||||||
|
name="custom"
|
||||||
|
tab="one"
|
||||||
|
style={{
|
||||||
|
marginLeft: "0.5rem",
|
||||||
|
background: "#70b1ec",
|
||||||
|
color: "white",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Toggle Custom Sidebar
|
||||||
|
</Sidebar.Trigger>
|
||||||
|
</Footer>
|
||||||
|
</Excalidraw>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
@ -37,7 +37,7 @@ Defaults to `THEME.LIGHT` unless passed in `initialData.appState.theme`
|
|||||||
|
|
||||||
### MIME_TYPES
|
### MIME_TYPES
|
||||||
|
|
||||||
[`MIME_TYPES`](https://github.com/excalidraw/excalidraw/blob/master/src/constants.ts#L101) contains all the mime types supported by `Excalidraw`.
|
[`MIME_TYPES`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/constants.ts#L101) contains all the mime types supported by `Excalidraw`.
|
||||||
|
|
||||||
**How to use **
|
**How to use **
|
||||||
|
|
||||||
|
@ -0,0 +1,475 @@
|
|||||||
|
# Creating Elements programmatically
|
||||||
|
|
||||||
|
We support a simplified API to make it easier to generate Excalidraw elements programmatically. This API is in beta and subject to change before stable. You can check the [PR](https://github.com/excalidraw/excalidraw/pull/6546) for more details.
|
||||||
|
|
||||||
|
For this purpose we introduced a new type [`ExcalidrawElementSkeleton`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133). This is the simplified version of [`ExcalidrawElement`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L134) type with the minimum possible attributes so that creating elements programmatically is much easier (especially for cases like binding arrows or creating text containers).
|
||||||
|
|
||||||
|
The [`ExcalidrawElementSkeleton`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133) can be converted to fully qualified Excalidraw elements by using [`convertToExcalidrawElements`](/docs/@excalidraw/excalidraw/api/excalidraw-element-skeleton#converttoexcalidrawelements).
|
||||||
|
|
||||||
|
## convertToExcalidrawElements
|
||||||
|
|
||||||
|
**_Signature_**
|
||||||
|
|
||||||
|
```ts
|
||||||
|
convertToExcalidrawElements(
|
||||||
|
elements: ExcalidrawElementSkeleton,
|
||||||
|
opts?: { regenerateIds: boolean }
|
||||||
|
): ExcalidrawElement[]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `elements` | [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/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_**
|
||||||
|
|
||||||
|
```js
|
||||||
|
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/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\_.
|
||||||
|
|
||||||
|
For the Skeleton API to work, `convertToExcalidrawElements` needs to be called before passing it to Excalidraw Component via initialData, updateScene or any such API.
|
||||||
|
|
||||||
|
```jsx live
|
||||||
|
function App() {
|
||||||
|
const elements = convertToExcalidrawElements([
|
||||||
|
{
|
||||||
|
type: "rectangle",
|
||||||
|
x: 100,
|
||||||
|
y: 250,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "ellipse",
|
||||||
|
x: 250,
|
||||||
|
y: 250,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "diamond",
|
||||||
|
x: 380,
|
||||||
|
y: 250,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
return (
|
||||||
|
<div style={{ height: "500px" }}>
|
||||||
|
<Excalidraw
|
||||||
|
initialData={{
|
||||||
|
elements,
|
||||||
|
appState: { zenModeEnabled: true, viewBackgroundColor: "#a5d8ff" },
|
||||||
|
scrollToContent: true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can pass additional [`properties`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L27) as well to decorate the shapes.
|
||||||
|
|
||||||
|
:::info
|
||||||
|
|
||||||
|
You can copy the below test examples and replace the elements in the live editor above to test it out.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
```js
|
||||||
|
convertToExcalidrawElements([
|
||||||
|
{
|
||||||
|
type: "rectangle",
|
||||||
|
x: 50,
|
||||||
|
y: 250,
|
||||||
|
width: 200,
|
||||||
|
height: 100,
|
||||||
|
backgroundColor: "#c0eb75",
|
||||||
|
strokeWidth: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "ellipse",
|
||||||
|
x: 300,
|
||||||
|
y: 250,
|
||||||
|
width: 200,
|
||||||
|
height: 100,
|
||||||
|
backgroundColor: "#ffc9c9",
|
||||||
|
strokeStyle: "dotted",
|
||||||
|
fillStyle: "solid",
|
||||||
|
strokeWidth: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "diamond",
|
||||||
|
x: 550,
|
||||||
|
y: 250,
|
||||||
|
width: 200,
|
||||||
|
height: 100,
|
||||||
|
backgroundColor: "#a5d8ff",
|
||||||
|
strokeColor: "#1971c2",
|
||||||
|
strokeStyle: "dashed",
|
||||||
|
fillStyle: "cross-hatch",
|
||||||
|
strokeWidth: 2,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Text Element
|
||||||
|
|
||||||
|
The `type`, `x`, `y` and `text` properties are required to create a text element, rest of the attributes are optional
|
||||||
|
|
||||||
|
```js
|
||||||
|
convertToExcalidrawElements([
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
text: "HELLO WORLD!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
x: 100,
|
||||||
|
y: 150,
|
||||||
|
text: "STYLED HELLO WORLD!",
|
||||||
|
fontSize: 20,
|
||||||
|
strokeColor: "#5f3dc4",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Lines and Arrows
|
||||||
|
|
||||||
|
The `type`, `x`, and `y` properties are required, rest of the attributes are optional
|
||||||
|
|
||||||
|
```js
|
||||||
|
convertToExcalidrawElements([
|
||||||
|
{
|
||||||
|
type: "arrow",
|
||||||
|
x: 100,
|
||||||
|
y: 20,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "line",
|
||||||
|
x: 100,
|
||||||
|
y: 60,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### With Addtional properties
|
||||||
|
|
||||||
|
```js
|
||||||
|
convertToExcalidrawElements([
|
||||||
|
{
|
||||||
|
type: "arrow",
|
||||||
|
x: 450,
|
||||||
|
y: 20,
|
||||||
|
startArrowhead: "dot",
|
||||||
|
endArrowhead: "triangle",
|
||||||
|
strokeColor: "#1971c2",
|
||||||
|
strokeWidth: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "line",
|
||||||
|
x: 450,
|
||||||
|
y: 60,
|
||||||
|
strokeColor: "#2f9e44",
|
||||||
|
strokeWidth: 2,
|
||||||
|
strokeStyle: "dotted",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Text Containers
|
||||||
|
|
||||||
|
In addition to `type`, `x` and `y` properties, [`label`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L124C7-L130C59) property is required for text containers. The `text` property in `label` is required, rest of the attributes are optional.
|
||||||
|
|
||||||
|
If you don't provide the dimensions of container, we calculate it based of the label dimensions.
|
||||||
|
|
||||||
|
```js
|
||||||
|
convertToExcalidrawElements([
|
||||||
|
{
|
||||||
|
type: "rectangle",
|
||||||
|
x: 300,
|
||||||
|
y: 290,
|
||||||
|
label: {
|
||||||
|
text: "RECTANGLE TEXT CONTAINER",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "ellipse",
|
||||||
|
x: 500,
|
||||||
|
y: 100,
|
||||||
|
label: {
|
||||||
|
text: "ELLIPSE\n TEXT CONTAINER",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "diamond",
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
label: {
|
||||||
|
text: "DIAMOND\nTEXT CONTAINER",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### With Additional properties
|
||||||
|
|
||||||
|
```js
|
||||||
|
convertToExcalidrawElements([
|
||||||
|
{
|
||||||
|
type: "diamond",
|
||||||
|
x: -120,
|
||||||
|
y: 100,
|
||||||
|
width: 270,
|
||||||
|
backgroundColor: "#fff3bf",
|
||||||
|
strokeWidth: 2,
|
||||||
|
label: {
|
||||||
|
text: "STYLED DIAMOND TEXT CONTAINER",
|
||||||
|
strokeColor: "#099268",
|
||||||
|
fontSize: 20,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "rectangle",
|
||||||
|
x: 180,
|
||||||
|
y: 150,
|
||||||
|
width: 200,
|
||||||
|
strokeColor: "#c2255c",
|
||||||
|
label: {
|
||||||
|
text: "TOP LEFT ALIGNED RECTANGLE TEXT CONTAINER",
|
||||||
|
textAlign: "left",
|
||||||
|
verticalAlign: "top",
|
||||||
|
fontSize: 20,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "ellipse",
|
||||||
|
x: 400,
|
||||||
|
y: 130,
|
||||||
|
strokeColor: "#f08c00",
|
||||||
|
backgroundColor: "#ffec99",
|
||||||
|
width: 200,
|
||||||
|
label: {
|
||||||
|
text: "STYLED ELLIPSE TEXT CONTAINER",
|
||||||
|
strokeColor: "#c2255c",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Labelled Arrows
|
||||||
|
|
||||||
|
Similar to Text Containers, you can create labelled arrows as well.
|
||||||
|
|
||||||
|
```js
|
||||||
|
convertToExcalidrawElements([
|
||||||
|
{
|
||||||
|
type: "arrow",
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
label: {
|
||||||
|
text: "LABELED ARROW",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "arrow",
|
||||||
|
x: 100,
|
||||||
|
y: 200,
|
||||||
|
label: {
|
||||||
|
text: "STYLED LABELED ARROW",
|
||||||
|
strokeColor: "#099268",
|
||||||
|
fontSize: 20,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "arrow",
|
||||||
|
x: 100,
|
||||||
|
y: 300,
|
||||||
|
strokeColor: "#1098ad",
|
||||||
|
strokeWidth: 2,
|
||||||
|
label: {
|
||||||
|
text: "ANOTHER STYLED LABELLED ARROW",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "arrow",
|
||||||
|
x: 100,
|
||||||
|
y: 400,
|
||||||
|
strokeColor: "#1098ad",
|
||||||
|
strokeWidth: 2,
|
||||||
|
label: {
|
||||||
|
text: "ANOTHER STYLED LABELLED ARROW",
|
||||||
|
strokeColor: "#099268",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Arrow bindings
|
||||||
|
|
||||||
|
To bind arrow to a shape you need to specify its [`start`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L86) and [`end`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L54) properties. You need to pass either `type` or `id` property in `start` and `end` properties, rest of the attributes are optional
|
||||||
|
|
||||||
|
```js
|
||||||
|
convertToExcalidrawElements([
|
||||||
|
{
|
||||||
|
type: "arrow",
|
||||||
|
x: 255,
|
||||||
|
y: 239,
|
||||||
|
label: {
|
||||||
|
text: "HELLO WORLD!!",
|
||||||
|
},
|
||||||
|
start: {
|
||||||
|
type: "rectangle",
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
type: "ellipse",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
When position for `start` and `end ` properties are not specified, we compute it according to arrow position.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```js
|
||||||
|
convertToExcalidrawElements([
|
||||||
|
{
|
||||||
|
type: "arrow",
|
||||||
|
x: 255,
|
||||||
|
y: 239,
|
||||||
|
label: {
|
||||||
|
text: "HELLO WORLD!!",
|
||||||
|
},
|
||||||
|
start: {
|
||||||
|
type: "text",
|
||||||
|
text: "HEYYYYY",
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
type: "text",
|
||||||
|
text: "WHATS UP ?",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### When passing `id`
|
||||||
|
|
||||||
|
Useful when you want to bind multiple arrows to one diagram / use some existing diagram
|
||||||
|
|
||||||
|
```js
|
||||||
|
convertToExcalidrawElements([
|
||||||
|
{
|
||||||
|
type: "ellipse",
|
||||||
|
id: "ellipse-1",
|
||||||
|
strokeColor: "#66a80f",
|
||||||
|
x: 390,
|
||||||
|
y: 356,
|
||||||
|
width: 150,
|
||||||
|
height: 150,
|
||||||
|
backgroundColor: "#d8f5a2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "diamond",
|
||||||
|
id: "diamond-1",
|
||||||
|
strokeColor: "#9c36b5",
|
||||||
|
width: 100,
|
||||||
|
x: -30,
|
||||||
|
y: 380,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "arrow",
|
||||||
|
x: 100,
|
||||||
|
y: 440,
|
||||||
|
width: 295,
|
||||||
|
height: 35,
|
||||||
|
strokeColor: "#1864ab",
|
||||||
|
start: {
|
||||||
|
type: "rectangle",
|
||||||
|
width: 150,
|
||||||
|
height: 150,
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
id: "ellipse-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "arrow",
|
||||||
|
x: 60,
|
||||||
|
y: 420,
|
||||||
|
width: 330,
|
||||||
|
strokeColor: "#e67700",
|
||||||
|
start: {
|
||||||
|
id: "diamond-1",
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
id: "ellipse-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 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<ExcalidrawFrameElement>);
|
||||||
|
```
|
||||||
|
|
||||||
|
```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"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
```
|
@ -1,16 +1,28 @@
|
|||||||
# ref
|
# excalidrawAPI
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<a href="https://reactjs.org/docs/refs-and-the-dom.html#creating-refs">createRef</a> | <a href="https://reactjs.org/docs/hooks-reference.html#useref">useRef</a> | <a href="https://reactjs.org/docs/refs-and-the-dom.html#callback-refs">callbackRef</a> | <br/>{ current: { readyPromise: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/utils.ts#L460">resolvablePromise</a> } }
|
(api:{" "}
|
||||||
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L616">
|
||||||
|
ExcalidrawAPI
|
||||||
|
</a>
|
||||||
|
) => void;
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
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 <Excalidraw excalidrawAPI={{(api)=> setExcalidrawAPI(api)}} />;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use this prop when you want to access some [Excalidraw APIs](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L616). We expose the below APIs :point_down:
|
||||||
|
|
||||||
| API | Signature | Usage |
|
| 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 |
|
| [updateScene](#updatescene) | `function` | updates the scene with the sceneData |
|
||||||
| [updateLibrary](#updatelibrary) | `function` | updates the scene with the sceneData |
|
| [updateLibrary](#updatelibrary) | `function` | updates the library |
|
||||||
| [addFiles](#addfiles) | `function` | add files data to the appState |
|
| [addFiles](#addfiles) | `function` | add files data to the appState |
|
||||||
| [resetScene](#resetscene) | `function` | Resets the scene. If `resetLoadingState` is passed as true then it will also force set the loading state to false. |
|
| [resetScene](#resetscene) | `function` | Resets the scene. If `resetLoadingState` is passed as true then it will also force set the loading state to false. |
|
||||||
| [getSceneElementsIncludingDeleted](#getsceneelementsincludingdeleted) | `function` | Returns all the elements including the deleted in the scene |
|
| [getSceneElementsIncludingDeleted](#getsceneelementsincludingdeleted) | `function` | Returns all the elements including the deleted in the scene |
|
||||||
@ -25,61 +37,22 @@ You can pass a `ref` when you want to access some excalidraw APIs. We expose the
|
|||||||
| [setActiveTool](#setactivetool) | `function` | This API can be used to set the active tool |
|
| [setActiveTool](#setactivetool) | `function` | This API can be used to set the active tool |
|
||||||
| [setCursor](#setcursor) | `function` | This API can be used to set customise the mouse cursor on the canvas |
|
| [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 |
|
| [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 |
|
| [toggleSidebar](#toggleSidebar) | `function` | Toggles specific sidebar 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`.
|
||||||
|
|
||||||
<pre>
|
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.
|
||||||
const excalidrawRef = { current:{ readyPromise:
|
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/utils.ts#L460">
|
|
||||||
resolvablePromise
|
|
||||||
</a>
|
|
||||||
} }
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
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 (
|
|
||||||
<div style={{ height: "500px" }}>
|
|
||||||
<Excalidraw ref={excalidrawRef} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## updateScene
|
## updateScene
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
(scene:{" "}
|
(scene:{" "}
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L339">
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L339">
|
||||||
sceneData
|
sceneData
|
||||||
</a>
|
</a>
|
||||||
) => void
|
) => void
|
||||||
@ -89,10 +62,10 @@ You can use this function to update the scene with the sceneData. It accepts the
|
|||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `elements` | [`ImportedDataState["elements"]`](https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L38) | The `elements` to be updated in the scene |
|
| `elements` | [`ImportedDataState["elements"]`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L38) | The `elements` to be updated in the scene |
|
||||||
| `appState` | [`ImportedDataState["appState"]`](https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L39) | The `appState` to be updated in the scene. |
|
| `appState` | [`ImportedDataState["appState"]`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L39) | The `appState` to be updated in the scene. |
|
||||||
| `collaborators` | <code>Map<string, <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37">Collaborator></a></code> | The list of collaborators to be updated in the scene. |
|
| `collaborators` | <code>Map<string, <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L37">Collaborator></a></code> | The list of collaborators to be updated in the scene. |
|
||||||
| `commitToHistory` | `boolean` | Implies if the `history (undo/redo)` should be recorded. Defaults to `false`. |
|
| `commitToStore` | `boolean` | Implies if the change should be captured and commited to the `store`. Commited changes are emmitted and listened to by other components, such as `History` for undo / redo purposes. Defaults to `false`. |
|
||||||
|
|
||||||
```jsx live
|
```jsx live
|
||||||
function App() {
|
function App() {
|
||||||
@ -139,8 +112,10 @@ function App() {
|
|||||||
return (
|
return (
|
||||||
<div style={{ height: "500px" }}>
|
<div style={{ height: "500px" }}>
|
||||||
<p style={{ fontSize: "16px" }}> Click to update the scene</p>
|
<p style={{ fontSize: "16px" }}> Click to update the scene</p>
|
||||||
<button className="custom-button" onClick={updateScene}>Update Scene</button>
|
<button className="custom-button" onClick={updateScene}>
|
||||||
<Excalidraw ref={(api) => setExcalidrawAPI(api)} />
|
Update Scene
|
||||||
|
</button>
|
||||||
|
<Excalidraw excalidrawAPI={(api) => setExcalidrawAPI(api)} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -150,13 +125,13 @@ function App() {
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
(opts: { <br /> libraryItems:{" "}
|
(opts: { <br /> libraryItems:{" "}
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L249">
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L249">
|
||||||
LibraryItemsSource
|
LibraryItemsSource
|
||||||
</a>
|
</a>
|
||||||
;<br /> merge?: boolean; <br /> prompt?: boolean;
|
;<br /> merge?: boolean; <br /> prompt?: boolean;
|
||||||
<br /> openLibraryMenu?: boolean;
|
<br /> openLibraryMenu?: boolean;
|
||||||
<br /> defaultStatus?: "unpublished" | "published"; <br /> }) => Promise<
|
<br /> defaultStatus?: "unpublished" | "published"; <br /> }) => Promise<
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L246">
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L246">
|
||||||
LibraryItems
|
LibraryItems
|
||||||
</a>
|
</a>
|
||||||
>
|
>
|
||||||
@ -166,7 +141,7 @@ You can use this function to update the library. It accepts the below attributes
|
|||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| `libraryItems` | [LibraryItemsSource](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L249) | \_ | The `libraryItems` to be replaced/merged with current library |
|
| `libraryItems` | [LibraryItemsSource](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L249) | \_ | The `libraryItems` to be replaced/merged with current library |
|
||||||
| `merge` | boolean | `false` | Whether to merge with existing library items. |
|
| `merge` | boolean | `false` | Whether to merge with existing library items. |
|
||||||
| `prompt` | boolean | `false` | Whether to prompt user for confirmation. |
|
| `prompt` | boolean | `false` | Whether to prompt user for confirmation. |
|
||||||
| `openLibraryMenu` | boolean | `false` | Keep the library menu open after library is updated. |
|
| `openLibraryMenu` | boolean | `false` | Keep the library menu open after library is updated. |
|
||||||
@ -187,7 +162,8 @@ function App() {
|
|||||||
return (
|
return (
|
||||||
<div style={{ height: "500px" }}>
|
<div style={{ height: "500px" }}>
|
||||||
<p style={{ fontSize: "16px" }}> Click to update the library items</p>
|
<p style={{ fontSize: "16px" }}> Click to update the library items</p>
|
||||||
<button className="custom-button"
|
<button
|
||||||
|
className="custom-button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const libraryItems = [
|
const libraryItems = [
|
||||||
{
|
{
|
||||||
@ -205,17 +181,15 @@ function App() {
|
|||||||
];
|
];
|
||||||
excalidrawAPI.updateLibrary({
|
excalidrawAPI.updateLibrary({
|
||||||
libraryItems,
|
libraryItems,
|
||||||
openLibraryMenu: true
|
openLibraryMenu: true,
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Update Library
|
Update Library
|
||||||
</button>
|
</button>
|
||||||
<Excalidraw
|
<Excalidraw
|
||||||
ref={(api) => setExcalidrawAPI(api)}
|
excalidrawAPI={(api) => setExcalidrawAPI(api)}
|
||||||
// initial data retrieved from https://github.com/excalidraw/excalidraw/blob/master/dev-docs/src/initialData.js
|
// initial data retrieved from https://github.com/excalidraw/excalidraw/blob/master/dev-docs/packages/excalidraw/initialData.js
|
||||||
initialData={{
|
initialData={{
|
||||||
libraryItems: initialData.libraryItems,
|
libraryItems: initialData.libraryItems,
|
||||||
appState: { openSidebar: "library" },
|
appState: { openSidebar: "library" },
|
||||||
@ -230,7 +204,7 @@ function App() {
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
(files:{" "}
|
(files:{" "}
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L59">
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L59">
|
||||||
BinaryFileData
|
BinaryFileData
|
||||||
</a>
|
</a>
|
||||||
) => void
|
) => void
|
||||||
@ -250,7 +224,7 @@ Resets the scene. If `resetLoadingState` is passed as true then it will also for
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
() =>{" "}
|
() =>{" "}
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L115">
|
||||||
ExcalidrawElement[]
|
ExcalidrawElement[]
|
||||||
</a>
|
</a>
|
||||||
</pre>
|
</pre>
|
||||||
@ -261,7 +235,7 @@ Returns all the elements including the deleted in the scene.
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
() => NonDeleted<
|
() => NonDeleted<
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L115">
|
||||||
ExcalidrawElement
|
ExcalidrawElement
|
||||||
</a>
|
</a>
|
||||||
[]>
|
[]>
|
||||||
@ -273,7 +247,7 @@ Returns all the elements excluding the deleted in the scene
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
() =>{" "}
|
() =>{" "}
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">
|
||||||
AppState
|
AppState
|
||||||
</a>
|
</a>
|
||||||
</pre>
|
</pre>
|
||||||
@ -292,19 +266,34 @@ This is the history API. history.clear() will clear the history.
|
|||||||
|
|
||||||
## scrollToContent
|
## scrollToContent
|
||||||
|
|
||||||
<pre>
|
```tsx
|
||||||
(target?:{" "}
|
(
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">
|
target?: ExcalidrawElement | ExcalidrawElement[],
|
||||||
ExcalidrawElement
|
opts?:
|
||||||
</a>{" "}
|
| {
|
||||||
|{" "}
|
fitToContent?: boolean;
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">
|
animate?: boolean;
|
||||||
ExcalidrawElement
|
duration?: number;
|
||||||
</a>
|
}
|
||||||
[]) => void
|
| {
|
||||||
</pre>
|
fitToViewport?: boolean;
|
||||||
|
viewportZoomFactor?: number;
|
||||||
|
animate?: boolean;
|
||||||
|
duration?: number;
|
||||||
|
}
|
||||||
|
) => void
|
||||||
|
```
|
||||||
|
|
||||||
Scroll the nearest element out of the elements supplied to the center. Defaults to the elements on the scene.
|
Scroll the nearest element out of the elements supplied to the center of the viewport. Defaults to the elements on the scene.
|
||||||
|
|
||||||
|
| Attribute | type | default | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| target | [ExcalidrawElement](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L115) | [ExcalidrawElement[]](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L115) | All scene elements | The element(s) to scroll to. |
|
||||||
|
| opts.fitToContent | boolean | false | Whether to fit the elements to viewport by automatically changing zoom as needed. Note that the zoom range is between 10%-100%. |
|
||||||
|
| opts.fitToViewport | boolean | false | Similar to fitToContent but the zoom range is not limited. If elements are smaller than the viewport, zoom will go above 100%. |
|
||||||
|
| opts.viewportZoomFactor | number | 0.7 | when fitToViewport=true, how much screen should the content cover, between 0.1 (10%) and 1 (100%) |
|
||||||
|
| opts.animate | boolean | false | Whether to animate between starting and ending position. Note that for larger scenes the animation may not be smooth due to performance issues. |
|
||||||
|
| opts.duration | number | 500 | Duration of the animation if `opts.animate` is `true`. |
|
||||||
|
|
||||||
## refresh
|
## refresh
|
||||||
|
|
||||||
@ -323,7 +312,7 @@ For any other cases if the position of excalidraw is updated (example due to scr
|
|||||||
This API can be used to show the toast with custom message.
|
This API can be used to show the toast with custom message.
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
({ message: string, closable?:boolean,duration?:number
|
({ message: string, closable?:boolean,duration?:number
|
||||||
} | null) => void
|
} | null) => void
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -347,7 +336,7 @@ The unique id of the excalidraw component. This can be used to identify the exca
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
() =>{" "}
|
() =>{" "}
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L82">
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L82">
|
||||||
files
|
files
|
||||||
</a>
|
</a>
|
||||||
</pre>
|
</pre>
|
||||||
@ -358,29 +347,43 @@ 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.
|
This API has the below signature. It sets the `tool` passed in param as the active tool.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
(
|
||||||
|
tool: (
|
||||||
|
| (
|
||||||
|
| { type: Exclude<ToolType, "image"> }
|
||||||
|
| {
|
||||||
|
type: Extract<ToolType, "image">;
|
||||||
|
insertOnCanvasDirectly?: boolean;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
| { type: "custom"; customType: string }
|
||||||
|
) & { locked?: boolean },
|
||||||
|
) => {};
|
||||||
|
```
|
||||||
|
|
||||||
<pre>
|
| Name | Type | Default | Description |
|
||||||
(tool: <br/> { type: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/shapes.tsx#L15">SHAPES</a>[number]["value"]| "eraser" } |<br/> { type: "custom"; customType: string }) => void
|
| --- | --- | --- | --- |
|
||||||
</pre>
|
| `type` | [ToolType](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/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
|
## setCursor
|
||||||
|
|
||||||
This API can be used to customise the mouse cursor on the canvas and has the below signature.
|
This API can be used to customise the mouse cursor on the canvas and has the below signature. It sets the mouse cursor to the cursor passed in param.
|
||||||
It sets the mouse cursor to the cursor passed in param.
|
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
(cursor: string) => void
|
(cursor: string) => void
|
||||||
```
|
```
|
||||||
|
|
||||||
## toggleMenu
|
## toggleSidebar
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
(type: "library" | "customSidebar", force?: boolean) => boolean;
|
(opts: { name: string; tab?: string; force?: boolean }) => boolean;
|
||||||
```
|
```
|
||||||
|
|
||||||
This API can be used to toggle a specific menu (currently only the sidebars), and returns whether the menu was toggled on or off. If the `force` flag passed, it will force the menu to be toggled either on/off based on the `boolean` passed.
|
This API can be used to toggle sidebar, optionally opening a specific sidebar tab. It returns whether the sidebar was toggled on or off. If the `force` flag passed, it will force the sidebar to be toggled either on/off.
|
||||||
|
|
||||||
This API is especially useful when you render a custom sidebar using [`renderSidebar`](#rendersidebar) prop, and you want to toggle it from your app based on a user action.
|
This API is especially useful when you render a custom [`<Sidebar/>`](/docs/@excalidraw/excalidraw/api/children-components/sidebar), and you want to toggle it from your app based on a user action.
|
||||||
|
|
||||||
## resetCursor
|
## resetCursor
|
||||||
|
|
||||||
@ -389,3 +392,51 @@ This API is especially useful when you render a custom sidebar using [`renderSid
|
|||||||
```
|
```
|
||||||
|
|
||||||
This API can be used to reset to default mouse cursor.
|
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<HTMLElement>,
|
||||||
|
) => 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.
|
@ -1,18 +1,18 @@
|
|||||||
# initialData
|
# initialData
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
{ elements?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a>, appState?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a> }
|
{ elements?: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a>, appState?: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a> }
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
This helps to load Excalidraw with `initialData`. It must be an object or a [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise) which resolves to an object containing the below optional fields.
|
This helps to load Excalidraw with `initialData`. It must be an object or a [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise) which resolves to an object containing the below optional fields.
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `elements` | [ExcalidrawElement[]](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114) | The `elements` with which `Excalidraw` should be mounted. |
|
| `elements` | [ExcalidrawElement[]](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114) | The `elements` with which `Excalidraw` should be mounted. |
|
||||||
| `appState` | [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95) | The `AppState` with which `Excalidraw` should be mounted. |
|
| `appState` | [AppState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95) | The `AppState` with which `Excalidraw` should be mounted. |
|
||||||
| `scrollToContent` | `boolean` | This attribute indicates 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 |
|
| `scrollToContent` | `boolean` | This attribute indicates 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](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L247) | Promise<[LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200)> | This library items with which `Excalidraw` should be mounted. |
|
| `libraryItems` | [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L247) | Promise<[LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L200)> | This library items with which `Excalidraw` should be mounted. |
|
||||||
| `files` | [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L82) | The `files` added to the scene. |
|
| `files` | [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L82) | The `files` added to the scene. |
|
||||||
|
|
||||||
You might want to use this when you want to load excalidraw with some initial elements and app state.
|
You might want to use this when you want to load excalidraw with some initial elements and app state.
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
# Props
|
# Props
|
||||||
|
|
||||||
All `props` are *optional*.
|
All `props` are _optional_.
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| [`initialData`](/docs/@excalidraw/excalidraw/api/props/initialdata) | `object` | `null` | <code>Promise<object | null></code> | `null` | The initial data with which app loads. |
|
| [`initialData`](/docs/@excalidraw/excalidraw/api/props/initialdata) | `object` | `null` | <code>Promise<object | null></code> | `null` | The initial data with which app loads. |
|
||||||
| [`ref`](/docs/@excalidraw/excalidraw/api/props/ref) | `object` | _ | `Ref` to be passed to Excalidraw |
|
| [`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 |
|
| [`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`. |
|
| [`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. |
|
| [`onPointerUpdate`](#onpointerupdate) | `function` | _ | Callback triggered when mouse pointer is updated. |
|
||||||
@ -17,26 +17,27 @@ All `props` are *optional*.
|
|||||||
| [`langCode`](#langcode) | `string` | `en` | Language code string to be used in Excalidraw |
|
| [`langCode`](#langcode) | `string` | `en` | Language code string to be used in Excalidraw |
|
||||||
| [`renderTopRightUI`](/docs/@excalidraw/excalidraw/api/props/render-props#rendertoprightui) | `function` | _ | Render function that renders custom UI in top right corner |
|
| [`renderTopRightUI`](/docs/@excalidraw/excalidraw/api/props/render-props#rendertoprightui) | `function` | _ | Render function that renders custom UI in top right corner |
|
||||||
| [`renderCustomStats`](/docs/@excalidraw/excalidraw/api/props/render-props#rendercustomstats) | `function` | _ | Render function that can be used to render custom stats on the stats dialog. |
|
| [`renderCustomStats`](/docs/@excalidraw/excalidraw/api/props/render-props#rendercustomstats) | `function` | _ | Render function that can be used to render custom stats on the stats dialog. |
|
||||||
| [`renderSidebar`](/docs/@excalidraw/excalidraw/api/props/render-props#rendersidebar) | `function` | _ | Render function that renders custom sidebar. |
|
|
||||||
| [`viewModeEnabled`](#viewmodeenabled) | `boolean` | _ | This indicates if the app is in `view` mode. |
|
| [`viewModeEnabled`](#viewmodeenabled) | `boolean` | _ | This indicates if the app is in `view` mode. |
|
||||||
| [`zenModeEnabled`](#zenmodeenabled) | `boolean` | _ | This indicates if the `zen` mode is enabled |
|
| [`zenModeEnabled`](#zenmodeenabled) | `boolean` | _ | This indicates if the `zen` mode is enabled |
|
||||||
| [`gridModeEnabled`](#gridmodeenabled) | `boolean` | _ | This indicates if the `grid` mode is enabled |
|
| [`gridModeEnabled`](#gridmodeenabled) | `boolean` | _ | This indicates if the `grid` mode is enabled |
|
||||||
| [`libraryReturnUrl`](#libraryreturnurl) | `string` | _ | What URL should [libraries.excalidraw.com](https://libraries.excalidraw.com) be installed to |
|
| [`libraryReturnUrl`](#libraryreturnurl) | `string` | _ | What URL should [libraries.excalidraw.com](https://libraries.excalidraw.com) be installed to |
|
||||||
| [`theme`](#theme) | `"light"` | `"dark"` | `"light"` | The theme of the Excalidraw component |
|
| [`theme`](#theme) | `"light"` | `"dark"` | `"light"` | The theme of the Excalidraw component |
|
||||||
| [`name`](#name) | `string` | | Name of the drawing |
|
| [`name`](#name) | `string` | | Name of the drawing |
|
||||||
| [`UIOptions`](/docs/@excalidraw/excalidraw/api/props/ui-options) | `object` | [DEFAULT UI OPTIONS](https://github.com/excalidraw/excalidraw/blob/master/src/constants.ts#L151) | To customise UI options. Currently we support customising [`canvas actions`](#canvasactions) |
|
| [`UIOptions`](/docs/@excalidraw/excalidraw/api/props/ui-options) | `object` | [DEFAULT UI OPTIONS](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/constants.ts#L151) | To customise UI options. Currently we support customising [`canvas actions`](/docs/@excalidraw/excalidraw/api/props/ui-options#canvasactions) |
|
||||||
| [`detectScroll`](#detectscroll) | `boolean` | `true` | Indicates whether to update the offsets when nearest ancestor is scrolled. |
|
| [`detectScroll`](#detectscroll) | `boolean` | `true` | Indicates whether to update the offsets when nearest ancestor is scrolled. |
|
||||||
| [`handleKeyboardGlobally`](#handlekeyboardglobally) | `boolean` | `false` | Indicates whether to bind the keyboard events to document. |
|
| [`handleKeyboardGlobally`](#handlekeyboardglobally) | `boolean` | `false` | Indicates whether to bind the keyboard events to document. |
|
||||||
| [`autoFocus`](#autofocus) | `boolean` | `false` | indicates whether to focus the Excalidraw component on page load |
|
| [`autoFocus`](#autofocus) | `boolean` | `false` | indicates whether to focus the Excalidraw component on page load |
|
||||||
| [`generateIdForFile`](#generateidforfile) | `function` | _ | Allows you to override `id` generation for files added on canvas |
|
| [`generateIdForFile`](#generateidforfile) | `function` | _ | Allows you to override `id` generation for files added on canvas |
|
||||||
|
| [`validateEmbeddable`](#validateEmbeddable) | string[] | `boolean | RegExp | RegExp[] | ((link: string) => boolean | undefined)` | \_ | use for custom src url validation |
|
||||||
|
| [`renderEmbeddable`](/docs/@excalidraw/excalidraw/api/props/render-props#renderEmbeddable) | `function` | \_ | Render function that can override the built-in `<iframe>` |
|
||||||
|
|
||||||
### Storing custom data on Excalidraw elements
|
### Storing custom data on Excalidraw elements
|
||||||
|
|
||||||
Beyond attributes that Excalidraw elements already support, you can store `custom` data on each `element` in a `customData` object. The type of the attribute is [`Record<string, any>`](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L66) and is optional.
|
Beyond attributes that Excalidraw elements already support, you can store `custom` data on each `element` in a `customData` object. The type of the attribute is [`Record<string, any>`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L66) and is optional.
|
||||||
|
|
||||||
You can use this to add any extra information you need to keep track of.
|
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
|
```js showLineNumbers
|
||||||
{
|
{
|
||||||
@ -58,11 +59,11 @@ Every time component updates, this callback if passed will get triggered and has
|
|||||||
(excalidrawElements, appState, files) => void;
|
(excalidrawElements, appState, files) => void;
|
||||||
```
|
```
|
||||||
|
|
||||||
1. `excalidrawElements`: Array of [excalidrawElements](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114) in the scene.
|
1. `excalidrawElements`: Array of [excalidrawElements](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114) in the scene.
|
||||||
|
|
||||||
2. `appState`: [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95) of the scene.
|
2. `appState`: [AppState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95) of the scene.
|
||||||
|
|
||||||
3. `files`: The [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L64) which are added to the scene.
|
3. `files`: The [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L64) which are added to the scene.
|
||||||
|
|
||||||
Here you can try saving the data to your backend or local storage for example.
|
Here you can try saving the data to your backend or local storage for example.
|
||||||
|
|
||||||
@ -78,22 +79,30 @@ This callback is triggered when mouse pointer is updated.
|
|||||||
|
|
||||||
2.`button`: The position of the button. This will be one of `["down", "up"]`
|
2.`button`: The position of the button. This will be one of `["down", "up"]`
|
||||||
|
|
||||||
3.`pointersMap`: [`pointers`](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L131) map of the scene
|
3.`pointersMap`: [`pointers`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L131) map of the scene
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(exportedElements, appState, canvas) => void
|
(exportedElements, appState, canvas) => void
|
||||||
```
|
```
|
||||||
|
|
||||||
1. `exportedElements`: An array of [non deleted elements](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L87) which needs to be exported.
|
1. `exportedElements`: An array of [non deleted elements](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L87) which needs to be exported.
|
||||||
2. `appState`: [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95) of the scene.
|
2. `appState`: [AppState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95) of the scene.
|
||||||
3. `canvas`: The `HTMLCanvasElement` of the scene.
|
3. `canvas`: The `HTMLCanvasElement` of the scene.
|
||||||
|
|
||||||
### onPointerDown
|
### onPointerDown
|
||||||
|
|
||||||
This prop if passed will be triggered on pointer down events and has the below signature.
|
This prop if passed will be triggered on pointer down events and has the below signature.
|
||||||
|
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
(activeTool: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L115"> AppState["activeTool"]</a>, pointerDownState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L424">PointerDownState</a>) => void
|
(activeTool:{" "}
|
||||||
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L115">
|
||||||
|
{" "}
|
||||||
|
AppState["activeTool"]
|
||||||
|
</a>
|
||||||
|
, pointerDownState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L424">
|
||||||
|
PointerDownState
|
||||||
|
</a>) => void
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
### onScrollChange
|
### onScrollChange
|
||||||
@ -109,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.
|
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.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
(data: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/clipboard.ts#L18">ClipboardData</a>, event: ClipboardEvent | null) => boolean
|
(data:{" "}
|
||||||
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/clipboard.ts#L18">
|
||||||
|
ClipboardData
|
||||||
|
</a>
|
||||||
|
, event: ClipboardEvent | null) => boolean
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
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.
|
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.
|
||||||
@ -122,7 +135,7 @@ This callback if supplied will get triggered when the library is updated and has
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
(items:{" "}
|
(items:{" "}
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200">
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L200">
|
||||||
LibraryItems
|
LibraryItems
|
||||||
</a>
|
</a>
|
||||||
) => void | Promise<any>
|
) => void | Promise<any>
|
||||||
@ -135,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()`.
|
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()`.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement</a>,
|
(element:{" "}
|
||||||
event: CustomEvent<{ nativeEvent: MouseEvent }>) => void
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">
|
||||||
|
ExcalidrawElement
|
||||||
|
</a>
|
||||||
|
, event: CustomEvent<{ nativeEvent: MouseEvent }>) => void
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@ -166,7 +182,7 @@ const onLinkOpen: ExcalidrawProps["onLinkOpen"] = useCallback(
|
|||||||
|
|
||||||
### langCode
|
### langCode
|
||||||
|
|
||||||
Determines the `language` of the UI. It should be one of the [available language codes](https://github.com/excalidraw/excalidraw/blob/master/src/i18n.ts#L14). Defaults to `en` (English). We also export default language and supported languages which you can import as shown below.
|
Determines the `language` of the UI. It should be one of the [available language codes](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/i18n.ts#L14). Defaults to `en` (English). We also export default language and supported languages which you can import as shown below.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { defaultLang, languages } from "@excalidraw/excalidraw";
|
import { defaultLang, languages } from "@excalidraw/excalidraw";
|
||||||
@ -175,34 +191,34 @@ import { defaultLang, languages } from "@excalidraw/excalidraw";
|
|||||||
| name | type |
|
| name | type |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `defaultLang` | `string` |
|
| `defaultLang` | `string` |
|
||||||
| `languages` | [`Language[]`](https://github.com/excalidraw/excalidraw/blob/master/src/i18n.ts#L15) |
|
| `languages` | [`Language[]`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/i18n.ts#L15) |
|
||||||
|
|
||||||
### viewModeEnabled
|
### 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
|
### 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
|
### 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
|
### libraryReturnUrl
|
||||||
|
|
||||||
If supplied, this URL will be used when user tries to install a library from [libraries.excalidraw.com](https://libraries.excalidraw.com).
|
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
|
### 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.
|
You can use [`THEME`](/docs/@excalidraw/excalidraw/api/utils#theme) to specify the theme.
|
||||||
|
|
||||||
### name
|
### 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
|
### detectScroll
|
||||||
@ -215,7 +231,6 @@ Indicates whether to bind keyboard events to `document`. Disabled by default, me
|
|||||||
|
|
||||||
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).
|
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).
|
||||||
|
|
||||||
|
|
||||||
### autoFocus
|
### autoFocus
|
||||||
|
|
||||||
This prop indicates whether to `focus` the Excalidraw component on page load. Defaults to false.
|
This prop indicates whether to `focus` the Excalidraw component on page load. Defaults to false.
|
||||||
@ -228,3 +243,12 @@ Allows you to override `id` generation for files added on canvas (images). By de
|
|||||||
(file: File) => string | Promise<string>
|
(file: File) => string | Promise<string>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### validateEmbeddable
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
validateEmbeddable?: boolean | string[] | RegExp | RegExp[] | ((link: string) => boolean | undefined)
|
||||||
|
```
|
||||||
|
|
||||||
|
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.
|
||||||
|
@ -3,11 +3,10 @@
|
|||||||
## renderTopRightUI
|
## renderTopRightUI
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
(isMobile: boolean, appState:{" "}
|
(isMobile: boolean, appState:
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">
|
||||||
AppState
|
AppState
|
||||||
</a>
|
</a>) => JSX | null
|
||||||
) => JSX | null
|
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
A function returning `JSX` to render `custom` UI in the top right corner of the app.
|
A function returning `JSX` to render `custom` UI in the top right corner of the app.
|
||||||
@ -29,8 +28,7 @@ function App() {
|
|||||||
}}
|
}}
|
||||||
onClick={() => window.alert("This is dummy top right UI")}
|
onClick={() => window.alert("This is dummy top right UI")}
|
||||||
>
|
>
|
||||||
{" "}
|
Click me
|
||||||
Click me{" "}
|
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
@ -55,8 +53,7 @@ function App() {
|
|||||||
<Excalidraw
|
<Excalidraw
|
||||||
renderCustomStats={() => (
|
renderCustomStats={() => (
|
||||||
<p style={{ color: "#70b1ec", fontWeight: "bold" }}>
|
<p style={{ color: "#70b1ec", fontWeight: "bold" }}>
|
||||||
{" "}
|
Dummy stats will be shown here
|
||||||
Dummy stats will be shown here{" "}
|
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@ -65,62 +62,19 @@ function App() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## renderSidebar
|
## renderEmbeddable
|
||||||
|
|
||||||
```tsx
|
<pre>
|
||||||
() => JSX | null;
|
(element: NonDeleted<ExcalidrawEmbeddableElement>, appState:{" "}
|
||||||
```
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">
|
||||||
|
AppState
|
||||||
|
</a>
|
||||||
|
) => JSX.Element | null
|
||||||
|
</pre>
|
||||||
|
|
||||||
You can render `custom sidebar` using this prop. This sidebar is the same that the library menu sidebar is using, and can be used for any purposes your app needs.
|
Allows you to replace the renderer for embeddable elements (which renders `<iframe>` elements).
|
||||||
|
|
||||||
You need to import the `Sidebar` component from `excalidraw` package and pass your content as its `children`. The function `renderSidebar` should return the `Sidebar` instance.
|
| Parameter | Type | Description |
|
||||||
|
|
||||||
### Sidebar
|
|
||||||
The `<Sidebar>` component takes these props (all are optional except `children`):
|
|
||||||
|
|
||||||
| Prop | Type | Description |
|
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `children` | `React.ReactNode` | Content you want to render inside the `sidebar`. |
|
| `element` | `NonDeleted<ExcalidrawEmbeddableElement>` | The embeddable element to be rendered. |
|
||||||
| `onClose` | `function` | Invoked when the component is closed (by user, or the editor). No need to act on this event, as the editor manages the sidebar open state on its own. |
|
| `appState` | `AppState` | The current state of the UI. |
|
||||||
| `onDock` | `function` | Invoked when the user toggles the `dock` button. The callback recieves a `boolean` parameter `isDocked` which indicates whether the sidebar is `docked` |
|
|
||||||
| `docked` | `boolean` | Indicates whether the sidebar is`docked`. By default, the sidebar is `undocked`. If passed, the docking becomes controlled, and you are responsible for updating the `docked` state by listening on `onDock` callback. To decide the breakpoint for docking you can use [UIOptions.dockedSidebarBreakpoint](/docs/@excalidraw/excalidraw/api/props/ui-options#dockedsidebarbreakpoint) for more info on docking. |
|
|
||||||
| `dockable` | `boolean` | Indicates whether to show the `dock` button so that user can `dock` the sidebar. If `false`, you can still dock programmatically by passing `docked` as `true`. |
|
|
||||||
|
|
||||||
The sidebar will always include a header with `close / dock` buttons (when applicable).
|
|
||||||
You can also add custom content to the header, by rendering `<Sidebar.Header>` as a child of the `<Sidebar>` component. Note that the custom header will still include the default buttons.
|
|
||||||
|
|
||||||
|
|
||||||
### Sidebar.Header
|
|
||||||
|
|
||||||
| name | type | description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| children | `React.ReactNode` | Content you want to render inside the sidebar header as a sibling of `close` / `dock` buttons. |
|
|
||||||
|
|
||||||
To control the visibility of the sidebar you can use [`toggleMenu("customSidebar")`](/docs/@excalidraw/excalidraw/api/props/ref#togglemenu) api available via `ref`.
|
|
||||||
|
|
||||||
```tsx live
|
|
||||||
function App() {
|
|
||||||
const [excalidrawAPI, setExcalidrawAPI] = useState(null);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{ height: "500px" }}>
|
|
||||||
<button className="custom-button" onClick={() => excalidrawAPI.toggleMenu("customSidebar")}>
|
|
||||||
{" "}
|
|
||||||
Toggle Custom Sidebar{" "}
|
|
||||||
</button>
|
|
||||||
<Excalidraw
|
|
||||||
UIOptions={{ dockedSidebarBreakpoint: 100 }}
|
|
||||||
ref={(api) => setExcalidrawAPI(api)}
|
|
||||||
renderSidebar={() => {
|
|
||||||
return (
|
|
||||||
<Sidebar dockable={true}>
|
|
||||||
<Sidebar.Header>Custom Sidebar Header </Sidebar.Header>
|
|
||||||
<p style={{ padding: "1rem" }}> custom Sidebar Content </p>
|
|
||||||
</Sidebar>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# UIOptions
|
# 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).
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
{
|
{
|
||||||
<br /> canvasActions?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L372">
|
<br /> canvasActions?: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L372">
|
||||||
CanvasActions
|
CanvasActions
|
||||||
</a>, <br /> dockedSidebarBreakpoint?: number, <br /> welcomeScreen?: boolean <br />
|
</a>, <br /> dockedSidebarBreakpoint?: number, <br /> welcomeScreen?: boolean <br />
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ If `UIOptions.canvasActions.export` is `false` the export button will not be ren
|
|||||||
|
|
||||||
## dockedSidebarBreakpoint
|
## dockedSidebarBreakpoint
|
||||||
|
|
||||||
This prop indicates at what point should we break to a docked, permanent sidebar. If not passed it defaults to [`MQ_RIGHT_SIDEBAR_MAX_WIDTH_PORTRAIT`](https://github.com/excalidraw/excalidraw/blob/master/src/constants.ts#L161).
|
This prop indicates at what point should we break to a docked, permanent sidebar. If not passed it defaults to [`MQ_RIGHT_SIDEBAR_MAX_WIDTH_PORTRAIT`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/constants.ts#L161).
|
||||||
If the _width_ of the _excalidraw_ container exceeds _dockedSidebarBreakpoint_, the sidebar will be `dockable` and the button to `dock` the sidebar will be shown
|
If the _width_ of the _excalidraw_ container exceeds _dockedSidebarBreakpoint_, the sidebar will be `dockable` and the button to `dock` the sidebar will be shown
|
||||||
If user choses to `dock` the sidebar, it will push the right part of the UI towards the left, making space for the sidebar as shown below.
|
If user choses to `dock` the sidebar, it will push the right part of the UI towards the left, making space for the sidebar as shown below.
|
||||||
|
|
||||||
@ -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.
|
||||||
|
@ -20,16 +20,16 @@ exportToCanvas({<br/>
|
|||||||
getDimensions,<br/>
|
getDimensions,<br/>
|
||||||
files,<br/>
|
files,<br/>
|
||||||
exportPadding?: number;<br/>
|
exportPadding?: number;<br/>
|
||||||
}: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L21">ExportOpts</a>
|
}: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/utils.ts#L21">ExportOpts</a>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| `elements` | [Excalidraw Element []](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114) | | The elements to be exported to canvas. |
|
| `elements` | [Excalidraw Element []](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114) | | The elements to be exported to canvas. |
|
||||||
| `appState` | [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L23) | [Default App State](https://github.com/excalidraw/excalidraw/blob/master/src/appState.ts#L17) | The app state of the scene. |
|
| `appState` | [AppState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/utils.ts#L23) | [Default App State](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/appState.ts#L17) | The app state of the scene. |
|
||||||
| [`getDimensions`](#getdimensions) | `function` | _ | A function which returns the `width`, `height`, and optionally `scale` (defaults to `1`), with which canvas is to be exported. |
|
| [`getDimensions`](#getdimensions) | `function` | _ | A function which returns the `width`, `height`, and optionally `scale` (defaults to `1`), with which canvas is to be exported. |
|
||||||
| `maxWidthOrHeight` | `number` | _ | The maximum `width` or `height` of the exported image. If provided, `getDimensions` is ignored. |
|
| `maxWidthOrHeight` | `number` | _ | The maximum `width` or `height` of the exported image. If provided, `getDimensions` is ignored. |
|
||||||
| `files` | [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L59) | _ | The files added to the scene. |
|
| `files` | [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L59) | _ | The files added to the scene. |
|
||||||
| `exportPadding` | `number` | `10` | The `padding` to be added on canvas. |
|
| `exportPadding` | `number` | `10` | The `padding` to be added on canvas. |
|
||||||
|
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ function App() {
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
exportToBlob(<br/>
|
exportToBlob(<br/>
|
||||||
opts: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L14">ExportOpts</a> & {<br/>
|
opts: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/utils.ts#L14">ExportOpts</a> & {<br/>
|
||||||
mimeType?: string,<br/>
|
mimeType?: string,<br/>
|
||||||
quality?: number,<br/>
|
quality?: number,<br/>
|
||||||
exportPadding?: number;<br/>
|
exportPadding?: number;<br/>
|
||||||
@ -134,16 +134,16 @@ Returns a promise which resolves with a [blob](https://developer.mozilla.org/en-
|
|||||||
<pre>
|
<pre>
|
||||||
exportToSvg({<br/>
|
exportToSvg({<br/>
|
||||||
elements:
|
elements:
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">
|
||||||
ExcalidrawElement[]
|
ExcalidrawElement[]
|
||||||
</a>,<br/>
|
</a>,<br/>
|
||||||
appState:
|
appState:
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95"> AppState
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95"> AppState
|
||||||
</a>,<br/>
|
</a>,<br/>
|
||||||
exportPadding: number,<br/>
|
exportPadding: number,<br/>
|
||||||
metadata: string,<br/>
|
metadata: string,<br/>
|
||||||
files:
|
files:
|
||||||
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L59">
|
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L59">
|
||||||
BinaryFiles
|
BinaryFiles
|
||||||
</a>,<br/>
|
</a>,<br/>
|
||||||
});
|
});
|
||||||
@ -151,10 +151,10 @@ exportToSvg({<br/>
|
|||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| elements | [Excalidraw Element []](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114) | | The elements to exported as `svg `|
|
| elements | [Excalidraw Element []](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114) | | The elements to exported as `svg `|
|
||||||
| appState | [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95) | [defaultAppState](https://github.com/excalidraw/excalidraw/blob/master/src/appState.ts#L11) | The `appState` of the scene |
|
| appState | [AppState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95) | [defaultAppState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/appState.ts#L11) | The `appState` of the scene |
|
||||||
| exportPadding | number | 10 | The `padding` to be added on canvas |
|
| exportPadding | number | 10 | The `padding` to be added on canvas |
|
||||||
| files | [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L64) | undefined | The `files` added to the scene. |
|
| files | [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L64) | undefined | The `files` added to the scene. |
|
||||||
|
|
||||||
This function returns a promise which resolves to `svg` of the exported drawing.
|
This function returns a promise which resolves to `svg` of the exported drawing.
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ This function returns a promise which resolves to `svg` of the exported drawing.
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
exportToClipboard(<br/>
|
exportToClipboard(<br/>
|
||||||
opts: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L21">ExportOpts</a> & {<br/>
|
opts: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/utils.ts#L21">ExportOpts</a> & {<br/>
|
||||||
mimeType?: string,<br/>
|
mimeType?: string,<br/>
|
||||||
quality?: number;<br/>
|
quality?: number;<br/>
|
||||||
type: 'png' | 'svg' |'json'<br/>
|
type: 'png' | 'svg' |'json'<br/>
|
||||||
|
@ -8,7 +8,7 @@ id: "restore"
|
|||||||
**_Signature_**
|
**_Signature_**
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
restoreAppState(appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L34">ImportedDataState["appState"]</a>,<br/> localAppState: Partial<<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a>> | null): <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a>
|
restoreAppState(appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L34">ImportedDataState["appState"]</a>,<br/> localAppState: Partial<<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a>> | null): <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
**_How to use_**
|
**_How to use_**
|
||||||
@ -17,7 +17,7 @@ restoreAppState(appState: <a href="https://github.com/excalidraw/excalidraw/blob
|
|||||||
import { restoreAppState } from "@excalidraw/excalidraw";
|
import { restoreAppState } from "@excalidraw/excalidraw";
|
||||||
```
|
```
|
||||||
|
|
||||||
This function will make sure all the `keys` have appropriate `values` in [appState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95) and if any key is missing, it will be set to its `default` value.
|
This function will make sure all the `keys` have appropriate `values` in [appState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95) and if any key is missing, it will be set to its `default` value.
|
||||||
|
|
||||||
When `localAppState` is supplied, it's used in place of values that are missing (`undefined`) in `appState` instead of the defaults.
|
When `localAppState` is supplied, it's used in place of values that are missing (`undefined`) in `appState` instead of the defaults.
|
||||||
Use this as a way to not override user's defaults if you persist them.
|
Use this as a way to not override user's defaults if you persist them.
|
||||||
@ -29,12 +29,31 @@ You can pass `null` / `undefined` if not applicable.
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
restoreElements(
|
restoreElements(
|
||||||
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ImportedDataState["elements"]</a>,<br/>
|
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ImportedDataState["elements"]</a>,<br/>
|
||||||
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a> | null | undefined): <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a>,<br/>
|
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a> | null | undefined): <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a>,<br/>
|
||||||
refreshDimensions?: boolean<br/>
|
opts: { refreshDimensions?: boolean, repairBindings?: boolean }<br/>
|
||||||
)
|
)
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
| Prop | Type | Description |
|
||||||
|
| ---- | ---- | ---- |
|
||||||
|
| `elements` | <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ImportedDataState["elements"]</a> | The `elements` to be restored |
|
||||||
|
| [`localElements`](#localelements) | <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a> | null | undefined | When `localElements` are supplied, they are used to ensure that existing restored elements reuse `version` (and increment it), and regenerate `versionNonce`. |
|
||||||
|
| [`opts`](#opts) | `Object` | The extra optional parameter to configure restored elements
|
||||||
|
|
||||||
|
#### localElements
|
||||||
|
|
||||||
|
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 update
|
||||||
|
|
||||||
|
#### opts
|
||||||
|
The extra optional parameter to configure restored elements. It has the following attributes
|
||||||
|
|
||||||
|
| Prop | Type | Description|
|
||||||
|
| --- | --- | ------|
|
||||||
|
| `refreshDimensions` | `boolean` | Indicates whether we should also `recalculate` text element dimensions. Since this is a potentially costly operation, you may want to disable it if you restore elements in tight loops, such as during collaboration. |
|
||||||
|
| `repairBindings` |`boolean` | Indicates whether the `bindings` for the elements should be repaired. This is to make sure there are no containers with non existent bound text element id and no bound text elements with non existent container id. |
|
||||||
|
|
||||||
**_How to use_**
|
**_How to use_**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -43,9 +62,6 @@ 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 its default value.
|
This function will make sure all properties of element is correctly set and if any attribute is missing, it will be set to its 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.
|
|
||||||
|
|
||||||
Parameter `refreshDimensions` indicates whether we should also `recalculate` text element dimensions. Defaults to `false`. Since this is a potentially costly operation, you may want to disable it if you restore elements in tight loops, such as during collaboration.
|
Parameter `refreshDimensions` indicates whether we should also `recalculate` text element dimensions. Defaults to `false`. Since this is a potentially costly operation, you may want to disable it if you restore elements in tight loops, such as during collaboration.
|
||||||
|
|
||||||
### restore
|
### restore
|
||||||
@ -54,13 +70,15 @@ Parameter `refreshDimensions` indicates whether we should also `recalculate` tex
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
restore(
|
restore(
|
||||||
data: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L34">ImportedDataState</a>,<br/>
|
data: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L34">ImportedDataState</a>,<br/>
|
||||||
localAppState: Partial<<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a>> | null | undefined,<br/>
|
localAppState: Partial<<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a>> | null | undefined,<br/>
|
||||||
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a> | null | undefined<br/>): <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L4">DataState</a>
|
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a> | null | undefined<br/>): <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L4">DataState</a><br/>
|
||||||
|
opts: { refreshDimensions?: boolean, repairBindings?: boolean }<br/>
|
||||||
|
|
||||||
)
|
)
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
See [`restoreAppState()`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#restoreAppState) about `localAppState`, and [`restoreElements()`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#restoreElements) about `localElements`.
|
See [`restoreAppState()`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/excalidraw/README.md#restoreAppState) about `localAppState`, and [`restoreElements()`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/excalidraw/README.md#restoreElements) about `localElements`.
|
||||||
|
|
||||||
**_How to use_**
|
**_How to use_**
|
||||||
|
|
||||||
@ -75,7 +93,7 @@ This function makes sure elements and state is set to appropriate values and set
|
|||||||
**_Signature_**
|
**_Signature_**
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
restoreLibraryItems(libraryItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L34">ImportedDataState["libraryItems"]</a>,<br/>
|
restoreLibraryItems(libraryItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L34">ImportedDataState["libraryItems"]</a>,<br/>
|
||||||
defaultStatus: "published" | "unpublished")
|
defaultStatus: "published" | "unpublished")
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ These are pure Javascript functions exported from the @excalidraw/excalidraw [`@
|
|||||||
|
|
||||||
### serializeAsJSON
|
### serializeAsJSON
|
||||||
|
|
||||||
Takes the scene elements and state and returns a JSON string. `Deleted` elements as well as most properties from `AppState` are removed from the resulting JSON. (see [`serializeAsJSON()`](https://github.com/excalidraw/excalidraw/blob/master/src/data/json.ts#L42) source for details).
|
Takes the scene elements and state and returns a JSON string. `Deleted` elements as well as most properties from `AppState` are removed from the resulting JSON. (see [`serializeAsJSON()`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/json.ts#L42) source for details).
|
||||||
|
|
||||||
If you want to overwrite the `source` field in the `JSON` string, you can set `window.EXCALIDRAW_EXPORT_SOURCE` to the desired value.
|
If you want to overwrite the `source` field in the `JSON` string, you can set `window.EXCALIDRAW_EXPORT_SOURCE` to the desired value.
|
||||||
|
|
||||||
@ -16,8 +16,8 @@ If you want to overwrite the `source` field in the `JSON` string, you can set `w
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
serializeAsJSON({<br/>
|
serializeAsJSON({<br/>
|
||||||
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a>,<br/>
|
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a>,<br/>
|
||||||
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a>,<br/>
|
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a>,<br/>
|
||||||
}): string
|
}): string
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ If you want to overwrite the source field in the JSON string, you can set `windo
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
serializeLibraryAsJSON(
|
serializeLibraryAsJSON(
|
||||||
libraryItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200">LibraryItems[]</a>)
|
libraryItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L200">LibraryItems[]</a>)
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
**How to use**
|
**How to use**
|
||||||
@ -53,7 +53,7 @@ Returns `true` if element is invisibly small (e.g. width & height are zero).
|
|||||||
**_Signature_**
|
**_Signature_**
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
isInvisiblySmallElement(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement</a>): boolean
|
isInvisiblySmallElement(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement</a>): boolean
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
**How to use**
|
**How to use**
|
||||||
@ -80,10 +80,10 @@ excalidrawAPI.updateScene(scene);
|
|||||||
<pre>
|
<pre>
|
||||||
loadFromBlob(<br/>
|
loadFromBlob(<br/>
|
||||||
blob: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>,<br/>
|
blob: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>,<br/>
|
||||||
localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a> | null,<br/>
|
localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a> | null,<br/>
|
||||||
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a> | null,<br/>
|
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a> | null,<br/>
|
||||||
fileHandle?: FileSystemHandle | null <br/>
|
fileHandle?: FileSystemHandle | null <br/>
|
||||||
) => Promise<<a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L61">RestoredDataState</a>>
|
) => Promise<<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/restore.ts#L61">RestoredDataState</a>>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
### loadLibraryFromBlob
|
### loadLibraryFromBlob
|
||||||
@ -129,11 +129,11 @@ if (contents.type === MIME_TYPES.excalidraw) {
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
loadSceneOrLibraryFromBlob(<br/>
|
loadSceneOrLibraryFromBlob(<br/>
|
||||||
blob: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>,
|
blob: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>,<br/>
|
||||||
localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a> | null,<br/>
|
localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a> | null,<br/>
|
||||||
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a> | null,<br/>
|
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a> | null,<br/>
|
||||||
fileHandle?: FileSystemHandle | null<br/>
|
fileHandle?: FileSystemHandle | null<br/>
|
||||||
) => Promise<{ type: string, data: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L53">RestoredDataState</a> | <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L33">ImportedLibraryState</a>}>
|
) => Promise<{ type: string, data: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/restore.ts#L53">RestoredDataState</a> | <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L33">ImportedLibraryState</a>}>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
### getFreeDrawSvgPath
|
### getFreeDrawSvgPath
|
||||||
@ -149,7 +149,7 @@ import { getFreeDrawSvgPath } from "@excalidraw/excalidraw";
|
|||||||
**Signature**
|
**Signature**
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
getFreeDrawSvgPath(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L182">ExcalidrawFreeDrawElement</a>)
|
getFreeDrawSvgPath(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L182">ExcalidrawFreeDrawElement</a>)
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
### isLinearElement
|
### isLinearElement
|
||||||
@ -164,9 +164,9 @@ import { isLinearElement } from "@excalidraw/excalidraw";
|
|||||||
|
|
||||||
**Signature**
|
**Signature**
|
||||||
|
|
||||||
```tsx
|
<pre>
|
||||||
isLinearElement(elementType?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L80">ExcalidrawElement</a>): boolean
|
isLinearElement(elementType?: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L80">ExcalidrawElement</a>): boolean
|
||||||
```
|
</pre>
|
||||||
|
|
||||||
### getNonDeletedElements
|
### getNonDeletedElements
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ import { getNonDeletedElements } from "@excalidraw/excalidraw";
|
|||||||
**Signature**
|
**Signature**
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
getNonDeletedElements(elements:<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114"> readonly ExcalidrawElement[]</a>): as readonly <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L125">NonDeletedExcalidrawElement[]</a>
|
getNonDeletedElements(elements:<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114"> readonly ExcalidrawElement[]</a>): as readonly <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L125">NonDeletedExcalidrawElement[]</a>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
### mergeLibraryItems
|
### mergeLibraryItems
|
||||||
@ -195,8 +195,10 @@ import { mergeLibraryItems } from "@excalidraw/excalidraw";
|
|||||||
**_Signature_**
|
**_Signature_**
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
mergeLibraryItems(localItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L250">LibraryItems</a>,<br/>
|
mergeLibraryItems(<br/>
|
||||||
otherItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200">LibraryItems</a>) => <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L250">LibraryItems</a>
|
localItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L250">LibraryItems</a>,<br/>
|
||||||
|
otherItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L200">LibraryItems</a><br/>
|
||||||
|
): <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L250">LibraryItems</a>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
### parseLibraryTokensFromUrl
|
### parseLibraryTokensFromUrl
|
||||||
@ -237,8 +239,8 @@ export const App = () => {
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
useHandleLibrary(opts: {<br/>
|
useHandleLibrary(opts: {<br/>
|
||||||
excalidrawAPI: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L494">ExcalidrawAPI</a>,<br/>
|
excalidrawAPI: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L494">ExcalidrawAPI</a>,<br/>
|
||||||
getInitialLibraryItems?: () => <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L253">LibraryItemsSource</a><br/>
|
getInitialLibraryItems?: () => <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L253">LibraryItemsSource</a><br/>
|
||||||
});
|
});
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -251,7 +253,7 @@ This function returns the current `scene` version.
|
|||||||
**_Signature_**
|
**_Signature_**
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
getSceneVersion(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a>)
|
getSceneVersion(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a>)
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
**How to use**
|
**How to use**
|
||||||
@ -272,7 +274,7 @@ import { sceneCoordsToViewportCoords } from "@excalidraw/excalidraw";
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
sceneCoordsToViewportCoords({ sceneX: number, sceneY: number },<br/>
|
sceneCoordsToViewportCoords({ sceneX: number, sceneY: number },<br/>
|
||||||
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a><br/>): { x: number, y: number }
|
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a><br/>): { x: number, y: number }
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
### viewportCoordsToSceneCoords
|
### viewportCoordsToSceneCoords
|
||||||
@ -287,7 +289,7 @@ import { viewportCoordsToSceneCoords } from "@excalidraw/excalidraw";
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
viewportCoordsToSceneCoords({ clientX: number, clientY: number },<br/>
|
viewportCoordsToSceneCoords({ clientX: number, clientY: number },<br/>
|
||||||
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a><br/>): {x: number, y: number}
|
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a><br/>): {x: number, y: number}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
### useDevice
|
### useDevice
|
||||||
@ -299,7 +301,7 @@ Open the `main menu` in the below example to view the footer.
|
|||||||
```jsx live noInline
|
```jsx live noInline
|
||||||
const MobileFooter = ({}) => {
|
const MobileFooter = ({}) => {
|
||||||
const device = useDevice();
|
const device = useDevice();
|
||||||
if (device.isMobile) {
|
if (device.editor.isMobile) {
|
||||||
return (
|
return (
|
||||||
<Footer>
|
<Footer>
|
||||||
<button
|
<button
|
||||||
@ -331,11 +333,147 @@ const App = () => (
|
|||||||
render(<App />);
|
render(<App />);
|
||||||
```
|
```
|
||||||
|
|
||||||
The `device` has the following `attributes`
|
The `device` has the following `attributes`, some grouped into `viewport` and `editor` objects, per context.
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `isSmScreen` | `boolean` | Set to `true` when the device small screen is small (Width < `640px` ) |
|
| `viewport.isMobile` | `boolean` | Set to `true` when viewport is in `mobile` breakpoint |
|
||||||
| `isMobile` | `boolean` | Set to `true` when the device is `mobile` |
|
| `viewport.isLandscape` | `boolean` | Set to `true` when the viewport is in `landscape` mode |
|
||||||
| `isTouchScreen` | `boolean` | Set to `true` for `touch` devices |
|
| `editor.canFitSidebar` | `boolean` | Set to `true` if there's enough space to fit the `sidebar` |
|
||||||
| `canDeviceFitSidebar` | `boolean` | Implies whether there is 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
|
||||||
|
|
||||||
|
To help with localization, we export the following.
|
||||||
|
|
||||||
|
| name | type |
|
||||||
|
| --- | --- |
|
||||||
|
| `defaultLang` | `string` |
|
||||||
|
| `languages` | [`Language[]`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/i18n.ts#L15) |
|
||||||
|
| `useI18n` | [`() => { langCode, t }`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/i18n.ts#L15) |
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { defaultLang, languages, useI18n } from "@excalidraw/excalidraw";
|
||||||
|
```
|
||||||
|
|
||||||
|
#### defaultLang
|
||||||
|
|
||||||
|
Default language code, `en`.
|
||||||
|
|
||||||
|
#### languages
|
||||||
|
|
||||||
|
List of supported language codes. You can pass any of these to `Excalidraw`'s [`langCode` prop](/docs/@excalidraw/excalidraw/api/props/#langcode).
|
||||||
|
|
||||||
|
#### useI18n
|
||||||
|
|
||||||
|
A hook that returns the current language code and translation helper function. You can use this to translate strings in the components you render as children of `<Excalidraw>`.
|
||||||
|
|
||||||
|
```jsx live
|
||||||
|
function App() {
|
||||||
|
const { t } = useI18n();
|
||||||
|
return (
|
||||||
|
<div style={{ height: "500px" }}>
|
||||||
|
<Excalidraw>
|
||||||
|
<button
|
||||||
|
style={{ position: "absolute", zIndex: 10, height: "2rem" }}
|
||||||
|
onClick={() => window.alert(t("labels.madeWithExcalidraw"))}
|
||||||
|
>
|
||||||
|
{t("buttons.confirm")}
|
||||||
|
</button>
|
||||||
|
</Excalidraw>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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_**
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
elementsOverlappingBBox(<br/>
|
||||||
|
elements: readonly NonDeletedExcalidrawElement[];<br/>
|
||||||
|
bounds: <a href="https://github.com/excalidraw/excalidraw/blob/9c425224c789d083bf16e0597ce4a429b9ee008e/src/element/bounds.ts#L37-L42">Bounds</a> | ExcalidrawElement;<br/>
|
||||||
|
errorMargin?: number;<br/>
|
||||||
|
type: "overlap" | "contain" | "inside";<br/>
|
||||||
|
): NonDeletedExcalidrawElement[];
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
**_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_**
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
isElementInsideBBox(<br/>
|
||||||
|
element: NonDeletedExcalidrawElement,<br/>
|
||||||
|
bounds: <a href="https://github.com/excalidraw/excalidraw/blob/9c425224c789d083bf16e0597ce4a429b9ee008e/src/element/bounds.ts#L37-L42">Bounds</a>,<br/>
|
||||||
|
eitherDirection = false,<br/>
|
||||||
|
): boolean
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
**_How to use_**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { isElementInsideBBox } from "@excalidraw/excalidraw";
|
||||||
|
```
|
||||||
|
|
||||||
|
### elementPartiallyOverlapsWithOrContainsBBox
|
||||||
|
|
||||||
|
Checks if `element` is overlapping the `bounds` rectangle, or is fully inside.
|
||||||
|
|
||||||
|
**_Signature_**
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
elementPartiallyOverlapsWithOrContainsBBox(<br/>
|
||||||
|
element: NonDeletedExcalidrawElement,<br/>
|
||||||
|
bounds: <a href="https://github.com/excalidraw/excalidraw/blob/9c425224c789d083bf16e0597ce4a429b9ee008e/src/element/bounds.ts#L37-L42">Bounds</a>,<br/>
|
||||||
|
): boolean
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
**_How to use_**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { elementPartiallyOverlapsWithOrContainsBBox } from "@excalidraw/excalidraw";
|
||||||
|
```
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Customizing Styles
|
# 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.
|
Excalidraw uses 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:
|
Make sure the selector has higher specificity, e.g. by prefixing it with your app's selector:
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ Most notably, you can customize the primary colors, by overriding these variable
|
|||||||
- `--color-primary-light`
|
- `--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](https://en.wikipedia.org/wiki/Chubb_illusion)). It will fall back to `--color-primary` if not present.
|
- `--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](https://en.wikipedia.org/wiki/Chubb_illusion)). It will fall back to `--color-primary` if not present.
|
||||||
|
|
||||||
For a complete list of variables, check [theme.scss](https://github.com/excalidraw/excalidraw/blob/master/src/css/theme.scss), though most of them will not make sense to override.
|
For a complete list of variables, check [theme.scss](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/css/theme.scss), though most of them will not make sense to override.
|
||||||
|
|
||||||
```css showLineNumbers
|
```css showLineNumbers
|
||||||
.custom-styles .excalidraw {
|
.custom-styles .excalidraw {
|
||||||
|
@ -13,7 +13,7 @@ To start the example app using the `@excalidraw/excalidraw` package, follow the
|
|||||||
1. Install the dependencies
|
1. Install the dependencies
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd src/packages/excalidraw && yarn
|
cd packages/excalidraw && yarn
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Start the example app
|
2. Start the example app
|
||||||
@ -43,7 +43,7 @@ Once the version is released `@excalibot` will post a comment with the release v
|
|||||||
To release the next stable version follow the below steps:
|
To release the next stable version follow the below steps:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn prerelease version
|
yarn prerelease:excalidraw
|
||||||
```
|
```
|
||||||
|
|
||||||
You need to pass the `version` for which you want to create the release. This will make the changes needed before making the release like updating `package.json`, `changelog` and more.
|
You need to pass the `version` for which you want to create the release. This will make the changes needed before making the release like updating `package.json`, `changelog` and more.
|
||||||
@ -51,7 +51,7 @@ You need to pass the `version` for which you want to create the release. This wi
|
|||||||
The next step is to run the `release` script:
|
The next step is to run the `release` script:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn release
|
yarn release:excalidraw
|
||||||
```
|
```
|
||||||
|
|
||||||
This will publish the package.
|
This will publish the package.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
### Does this package support collaboration ?
|
### Does this package 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](https://github.com/excalidraw/excalidraw/blob/master/src/excalidraw-app/index.tsx). Here is a [detailed answer](https://github.com/excalidraw/excalidraw/discussions/3879#discussioncomment-1110524) on how you can achieve the same.
|
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](https://github.com/excalidraw/excalidraw/blob/master/excalidraw-app/index.tsx). Here is a [detailed answer](https://github.com/excalidraw/excalidraw/discussions/3879#discussioncomment-1110524) on how you can achieve the same.
|
||||||
|
|
||||||
### Turning off Aggressive Anti-Fingerprinting in Brave browser
|
### Turning off Aggressive Anti-Fingerprinting in Brave browser
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ We strongly recommend turning it off. You can follow the steps below on how to d
|
|||||||
|
|
||||||
2. Once opened, look for **Aggressively Block Fingerprinting**
|
2. Once opened, look for **Aggressively Block Fingerprinting**
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
3. Switch to **Block Fingerprinting**
|
3. Switch to **Block Fingerprinting**
|
||||||
|
|
||||||
@ -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).
|
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": JSON.stringify("true"),
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
## Need help?
|
## Need help?
|
||||||
|
|
||||||
|
@ -30,25 +30,131 @@ 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`.
|
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`.
|
||||||
|
|
||||||
The following worfklow shows one way how to render Excalidraw on Next.js. We'll add more detailed and alternative Next.js examples, soon.
|
If you want to only import `Excalidraw` component you can do :point_down:
|
||||||
|
|
||||||
```jsx showLineNumbers
|
```jsx showLineNumbers
|
||||||
import { useState, useEffect } from "react";
|
import dynamic from "next/dynamic";
|
||||||
|
const Excalidraw = dynamic(
|
||||||
|
async () => (await import("@excalidraw/excalidraw")).Excalidraw,
|
||||||
|
{
|
||||||
|
ssr: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [Excalidraw, setExcalidraw] = useState(null);
|
return <Excalidraw />;
|
||||||
useEffect(() => {
|
|
||||||
import("@excalidraw/excalidraw").then((comp) => setExcalidraw(comp.Excalidraw));
|
|
||||||
}, []);
|
|
||||||
return <>{Excalidraw && <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>
|
||||||
|
|
||||||
|
|
||||||
|
Here is a [source code](https://github.com/excalidraw/excalidraw/tree/master/examples/excalidraw/with-nextjs) for the example with app and pages router. You you can try it out [here](https://excalidraw-package-example-with-nextjs-gh6smrdnq-excalidraw.vercel.app/).
|
||||||
|
|
||||||
|
|
||||||
The `types` are available at `@excalidraw/excalidraw/types`, you can view [example for typescript](https://codesandbox.io/s/excalidraw-types-9h2dm)
|
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": JSON.stringify("true"),
|
||||||
|
},
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
## Browser
|
## Browser
|
||||||
|
|
||||||
To use it in a browser directly:
|
To use it in a browser directly:
|
||||||
@ -99,7 +205,7 @@ import TabItem from "@theme/TabItem";
|
|||||||
<h1>Excalidraw Embed Example</h1>
|
<h1>Excalidraw Embed Example</h1>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="src/index.js"></script>
|
<script type="text/javascript" src="packages/excalidraw/index.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
155
dev-docs/docs/@excalidraw/mermaid-to-excalidraw/api.mdx
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
# API
|
||||||
|
|
||||||
|
At the moment the mermaid-to-excalidraw works in two steps. First, you call `parseMermaidToExcalidraw(mermaidSyntax)` on the mermaid diagram definition string, which resolves with elements in a skeleton format — a simplified excalidraw JSON format (docs coming soon). You then pass them to `convertToExcalidrawElements(elements)` to get the fully qualified excalidraw elements you can render in the editor.
|
||||||
|
|
||||||
|
The need for these two steps is due to the [@excalidraw/excalidraw](/docs/@excalidraw/excalidraw/installation) being a **UMD** build so we currently cannot import the `convertToExcalidrawElements()` util alone, until we support a tree-shakeable **ESM** build.
|
||||||
|
|
||||||
|
## parseMermaidToExcalidraw
|
||||||
|
|
||||||
|
This API receives the mermaid syntax as the input, and resolves to skeleton Excalidraw elements. You will need to call `convertToExcalidraw` API to convert them to fully qualified elements that you can render in Excalidraw.
|
||||||
|
|
||||||
|
** Example **
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { parseMermaidToExcalidraw } from "@excalidraw/mermaid-to-excalidraw";
|
||||||
|
import { convertToExcalidrawElements} from "@excalidraw/excalidraw"
|
||||||
|
try {
|
||||||
|
const { elements, files } = await parseMermaid(mermaidSyntax: string, {
|
||||||
|
fontSize: number,
|
||||||
|
});
|
||||||
|
const excalidrawElements = convertToExcalidrawElements(elements);
|
||||||
|
// Render elements and files on Excalidraw
|
||||||
|
} catch (e) {
|
||||||
|
// Parse error, displaying error message to users
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Supported Diagram Types
|
||||||
|
|
||||||
|
Currently only [flowcharts](https://mermaid.js.org/syntax/flowchart.html) are supported. Oother diagram types will be rendered as an image in Excalidraw.
|
||||||
|
|
||||||
|
### Flowchart
|
||||||
|
|
||||||
|
#### Excalidraw Regular Shapes
|
||||||
|
|
||||||
|
**Rectangles**, **Circle**, **Diamond**, and **Arrows** are fully supported in Excalidraw
|
||||||
|
|
||||||
|
```
|
||||||
|
flowchart TD
|
||||||
|
A[Christmas] -->|Get money| B(Go shopping)
|
||||||
|
B --> C{Let me think}
|
||||||
|
C -->|One| D[Laptop]
|
||||||
|
C -->|Two| E[iPhone]
|
||||||
|
C -->|Three| F[Car]
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="https://github.com/excalidraw/excalidraw/assets/11256141/c8ea84fc-e9fb-4652-9a12-154136d1a798" width="250" height="200"/>
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
flowchart LR
|
||||||
|
id1((Hello from Circle))
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="https://github.com/excalidraw/excalidraw/assets/11256141/6202a8b9-8aa7-451e-9478-4d8d75c0f2fa" width="250" height="200"/>
|
||||||
|
|
||||||
|
|
||||||
|
#### Subgraphs
|
||||||
|
|
||||||
|
Subgraphs are grouped diagrams hence they are also supported in Excalidraw
|
||||||
|
|
||||||
|
```
|
||||||
|
flowchart TB
|
||||||
|
c1-->a2
|
||||||
|
subgraph one
|
||||||
|
a1-->a2
|
||||||
|
end
|
||||||
|
subgraph two
|
||||||
|
b1-->b2
|
||||||
|
end
|
||||||
|
subgraph three
|
||||||
|
c1-->c2
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="https://github.com/excalidraw/excalidraw/assets/11256141/098bce52-8f93-437c-9a06-c6972e27c70a" width="350" height="200"/>
|
||||||
|
|
||||||
|
#### Unsupported shapes fallback to Rectangle
|
||||||
|
|
||||||
|
**Subroutine**, **Cylindrical**, **Asymmetric**, **Hexagon**, **Parallelogram**, **Trapezoid** are not supported in Excalidraw hence they fallback to the closest shape **Rectangle**
|
||||||
|
|
||||||
|
```
|
||||||
|
flowchart LR
|
||||||
|
id1[[Subroutine fallback to Rectangle]]
|
||||||
|
id2[(Cylindrical fallback to Rectangle)]
|
||||||
|
id3>Asymmetric fallback to Rectangle]
|
||||||
|
id4{{Hexagon fallback to Rectangle}}
|
||||||
|
id5[/Parallelogram fallback to Rectangle /]
|
||||||
|
id6[/Trapezoid fallback to Rectangle\]
|
||||||
|
```
|
||||||
|
The above shapes are not supported in Excalidraw hence they fallback to Rectangle
|
||||||
|
|
||||||
|
<img src="https://github.com/excalidraw/excalidraw/assets/11256141/cb269473-16c5-4c35-bd7a-d631d8cc5b47" width="350" height="200"/>
|
||||||
|
|
||||||
|
#### Markdown fallback to Regular text
|
||||||
|
|
||||||
|
Since we don't support wysiwyg text editor yet, hence [Markdown Strings](https://mermaid.js.org/syntax/flowchart.html#markdown-strings) will fallback to regular text.
|
||||||
|
|
||||||
|
```
|
||||||
|
flowchart LR
|
||||||
|
A("`Hello **World**`") --> B("`Whats **up** ?`")
|
||||||
|
```
|
||||||
|
<img src="https://github.com/excalidraw/excalidraw/assets/11256141/107bd428-9ab9-42d4-ba12-b1e29c8db478" width="250" height="200"/>
|
||||||
|
|
||||||
|
#### Basic FontAwesome fallback to text
|
||||||
|
|
||||||
|
The [FontAwesome](https://mermaid.js.org/syntax/flowchart.html#basic-support-for-fontawesome) icons aren't support so they won't be rendered in Excalidraw
|
||||||
|
|
||||||
|
```
|
||||||
|
flowchart TD
|
||||||
|
B["fab:fa-twitter for peace"]
|
||||||
|
B-->C[fa:fa-ban forbidden]
|
||||||
|
B-->E(A fa:fa-camera-retro perhaps?)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
<img src="https://github.com/excalidraw/excalidraw/assets/11256141/7a693863-c3f9-42ff-b325-4b3f8303c7af" width="250" height="200"/>
|
||||||
|
|
||||||
|
#### Cross Arrow head fallback to Bar Arrow head
|
||||||
|
|
||||||
|
```
|
||||||
|
flowchart LR
|
||||||
|
Start x--x Stop
|
||||||
|
```
|
||||||
|
<img src="https://github.com/excalidraw/excalidraw/assets/11256141/217dd1ad-7f4e-4c80-8c1c-03647b42d821" width="250" height="200"/>
|
||||||
|
|
||||||
|
|
||||||
|
## Unsupported Diagram Types
|
||||||
|
|
||||||
|
Currently only [flowcharts](https://mermaid.js.org/syntax/flowchart.html) are supported. All other diagram types will be rendered as an image in Excalidraw.
|
||||||
|
|
||||||
|
```
|
||||||
|
erDiagram
|
||||||
|
CUSTOMER ||--o{ ORDER : places
|
||||||
|
ORDER ||--|{ LINE-ITEM : contains
|
||||||
|
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="https://github.com/excalidraw/excalidraw/assets/11256141/c1d3fdb3-32ef-4bf3-a38a-02ac3d7d2cb9" width="300" height="200"/>
|
||||||
|
|
||||||
|
```
|
||||||
|
gitGraph
|
||||||
|
commit
|
||||||
|
commit
|
||||||
|
branch develop
|
||||||
|
checkout develop
|
||||||
|
commit
|
||||||
|
commit
|
||||||
|
checkout main
|
||||||
|
merge develop
|
||||||
|
commit
|
||||||
|
commit
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="https://github.com/excalidraw/excalidraw/assets/11256141/e5dcec0b-d570-4eb4-b981-412a996aa96c" width="400" height="300"/>
|
@ -0,0 +1,7 @@
|
|||||||
|
# Codebase
|
||||||
|
|
||||||
|
The Codebase is divided into 2 Sections
|
||||||
|
|
||||||
|
* [How Parser Works under the hood](/docs/@excalidraw/mermaid-to-excalidraw/codebase/parser) - If you are interested in understanding and deep diving into inner workings of the Parser, then make sure to checkout this section.
|
||||||
|
|
||||||
|
* [Adding a new diagram type](/docs/@excalidraw/mermaid-to-excalidraw/codebase/new-diagram-type) - If you want to help us make the mermaid to Excalidraw Parser more powerful, you will find all information in this section to do so.
|
@ -0,0 +1,54 @@
|
|||||||
|
# Adding a new Diagram Type
|
||||||
|
|
||||||
|
To add a new diagram type to the parser you can follow the below steps :point_down:
|
||||||
|
|
||||||
|
All the code for the parser resides in [`src`](https://github.com/excalidraw/mermaid-to-excalidraw/tree/master/src) folder and for playground resides in [`playground`](https://github.com/excalidraw/mermaid-to-excalidraw/tree/master/playground) folder.
|
||||||
|
|
||||||
|
lets run the playground server in local :point_down:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn start
|
||||||
|
```
|
||||||
|
|
||||||
|
This will start the playground server in port `1234` and open it in browser so you start playing with the playground.
|
||||||
|
|
||||||
|
## Update Supported Diagram Types
|
||||||
|
|
||||||
|
First step is to add the new diagram type in [`SUPPORTED_DIAGRAM_TYPES`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/constants.ts#L2).
|
||||||
|
|
||||||
|
Once this is done the new diagram type won't be rendered as an image but start throwing error since we don't support parsing the data yet.
|
||||||
|
|
||||||
|
## Writing the Diagram Parser
|
||||||
|
|
||||||
|
Once the diagram type is added in previous step. Next step is to write the parser to parse the mermaid diagram.
|
||||||
|
|
||||||
|
For this create a file named `{{diagramType}}.ts` in [`src/parser`](https://github.com/excalidraw/mermaid-to-excalidraw/tree/master/src/parser) and write a function `parseMermaid{{diagramType}}Diagram` similar to how we [`parseMermaidFlowChartDiagram`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/parser/flowchart.ts#L256) for parsing flowchart diagram.
|
||||||
|
|
||||||
|
The main aim of the parser is :point_down:
|
||||||
|
|
||||||
|
1. Determine how elements are connected in the diagram and thus finding arrow and text bindings.
|
||||||
|
|
||||||
|
For this you might have to dig in to the parser `diagram.parser.yy` and which attributes to parse for the new diagram.
|
||||||
|
|
||||||
|
2. Determine the position and dimensions of each element, for this would be using the `svg`
|
||||||
|
|
||||||
|
Once the parser is ready, lets start using it.
|
||||||
|
|
||||||
|
Add the diagram type in switch case in [`parseMermaid`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/parseMermaid.ts#L97) and call the parser for the same.
|
||||||
|
|
||||||
|
## Writing the Excalidraw Skeleton Convertor
|
||||||
|
|
||||||
|
With the completion of previous step, we have all the data, now we need to transform it so to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133) format.
|
||||||
|
|
||||||
|
Similar to [`FlowChartToExcalidrawSkeletonConverter`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/converter/types/flowchart.ts#L24), you have to write the `{{diagramType}}ToExcalidrawSkeletonConverter` which parses the data received in previous step and returns the [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133).
|
||||||
|
|
||||||
|
Thats it, you have added the new diagram type 🥳, now lets test it out!
|
||||||
|
|
||||||
|
## Updating the Playground
|
||||||
|
|
||||||
|
1. Create a file named `{{diagramType}}.ts` in [`playround/testcases/`](https://github.com/excalidraw/mermaid-to-excalidraw/tree/master/playground/testcases). For reference you can check [`flowchart.ts`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/playground/testcases/flowchart.ts).
|
||||||
|
|
||||||
|
2. Incase the new diagram type added is present in [`unsupported.ts`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/playground/testcases/unsupported.ts) then remove it from there.
|
||||||
|
|
||||||
|
3. Verify if the test cases are running fine in playground.
|
||||||
|
|
@ -0,0 +1,177 @@
|
|||||||
|
# Flowchart Parser
|
||||||
|
|
||||||
|
As mentioned in the previous section, we use [getDiagramFromText](https://github.com/mermaid-js/mermaid/blob/00d06c7282a701849793680c1e97da1cfdfcce62/packages/mermaid/src/Diagram.ts#L80) to parse the full defination and get the [Diagram](https://github.com/mermaid-js/mermaid/blob/00d06c7282a701849793680c1e97da1cfdfcce62/packages/mermaid/src/Diagram.ts#L15) json from it.
|
||||||
|
|
||||||
|
In this section we will be diving into how the [flowchart parser](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/parser/flowchart.ts#L256) works behind the scenes.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
We use `diagram.parser.yy` attribute to parse the data. If you want to know more about how the `diagram.parse.yy` attribute looks like, you can check it [here](https://github.com/mermaid-js/mermaid/blob/00d06c7282a701849793680c1e97da1cfdfcce62/packages/mermaid/src/diagrams/flowchart/flowDb.js#L768), however for scope of flowchart we are using **3** APIs from this parser to compute `vertices`, `edges` and `clusters` as we need these data to transform to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133C13-L133C38).
|
||||||
|
|
||||||
|
|
||||||
|
For computing `vertices` and `edge`s lets consider the below svg generated by mermaid
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Computing the vertices
|
||||||
|
|
||||||
|
We use `getVertices` API from `diagram.parse.yy` to get the vertices for a given flowchart.
|
||||||
|
|
||||||
|
Considering the same example this is the response from the API
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"start": {
|
||||||
|
"id": "start",
|
||||||
|
"labelType": "text",
|
||||||
|
"domId": "flowchart-start-1414",
|
||||||
|
"styles": [],
|
||||||
|
"classes": [],
|
||||||
|
"text": "start",
|
||||||
|
"props": {}
|
||||||
|
},
|
||||||
|
"stop": {
|
||||||
|
"id": "stop",
|
||||||
|
"labelType": "text",
|
||||||
|
"domId": "flowchart-stop-1415",
|
||||||
|
"styles": [],
|
||||||
|
"classes": [],
|
||||||
|
"text": "stop",
|
||||||
|
"props": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
The dimensions and position is missing in this response and we need that to transform to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133C13-L133C38), for this we have our own parser [`parseVertex`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/parseMermaid.ts#L178) which takes the above response and uses the `svg` together to compute position, dimensions and cleans up the response.
|
||||||
|
|
||||||
|
The final output from `parseVertex` looks like :point_down:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"start": {
|
||||||
|
"id": "start",
|
||||||
|
"labelType": "text",
|
||||||
|
"text": "start",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 67.796875,
|
||||||
|
"height": 44,
|
||||||
|
"containerStyle": {},
|
||||||
|
"labelStyle": {}
|
||||||
|
},
|
||||||
|
"stop": {
|
||||||
|
"id": "stop",
|
||||||
|
"labelType": "text",
|
||||||
|
"text": "stop",
|
||||||
|
"x": 117.796875,
|
||||||
|
"y": 0,
|
||||||
|
"width": 62.3828125,
|
||||||
|
"height": 44,
|
||||||
|
"containerStyle": {},
|
||||||
|
"labelStyle": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Computing the edges
|
||||||
|
|
||||||
|
The lines and arrows are considered as `edges` in mermaid as shown in the above diagram.
|
||||||
|
We use `getEdges` API from `diagram.parse.yy` to get the edges for a given flowchart.
|
||||||
|
Considering the same example this is the response from the API
|
||||||
|
|
||||||
|
```js
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"start": "start",
|
||||||
|
"end": "stop",
|
||||||
|
"type": "arrow_point",
|
||||||
|
"text": "",
|
||||||
|
"labelType": "text",
|
||||||
|
"stroke": "normal",
|
||||||
|
"length": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Similarly here the dimensions and position is missing and we compute that from the svg. The [`parseEdge`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/parseMermaid.ts#L245) takes the above response along with `svg` and computes the position, dimensions and cleans up the response.
|
||||||
|
|
||||||
|
The final output from `parseEdge` looks like :point_down:
|
||||||
|
|
||||||
|
```js
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"start": "start",
|
||||||
|
"end": "stop",
|
||||||
|
"type": "arrow_point",
|
||||||
|
"text": "",
|
||||||
|
"labelType": "text",
|
||||||
|
"stroke": "normal",
|
||||||
|
"startX": 67.797,
|
||||||
|
"startY": 22,
|
||||||
|
"endX": 117.797,
|
||||||
|
"endY": 22,
|
||||||
|
"reflectionPoints": [
|
||||||
|
{
|
||||||
|
"x": 67.797,
|
||||||
|
"y": 22
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 117.797,
|
||||||
|
"y": 22
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
## Computing the Subgraphs
|
||||||
|
|
||||||
|
`Subgraphs` is collection of elements grouped together. The Subgraphs map to `grouping` elements in Excalidraw.
|
||||||
|
|
||||||
|
Lets consider the below example :point_down:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
We use `getSubgraphs` API to get the subgraph data for a given flowchart.
|
||||||
|
Considering the same example this is the response from the API
|
||||||
|
|
||||||
|
```js
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "one",
|
||||||
|
"nodes": [
|
||||||
|
"flowchart-a2-1399",
|
||||||
|
"flowchart-a1-1400"
|
||||||
|
],
|
||||||
|
"title": "one",
|
||||||
|
"classes": [],
|
||||||
|
"labelType": "text"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
For position and dimensions we use the svg to compute. The [`parseSubgraph`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/parseMermaid.ts#L139) takes the above response along with `svg` and computes the position, dimensions and cleans up the response.
|
||||||
|
|
||||||
|
|
||||||
|
```js
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "one",
|
||||||
|
"nodes": [
|
||||||
|
"flowchart-a2-1399",
|
||||||
|
"flowchart-a1-1400"
|
||||||
|
],
|
||||||
|
"title": "one",
|
||||||
|
"labelType": "text",
|
||||||
|
"nodeIds": [
|
||||||
|
"a2",
|
||||||
|
"a1"
|
||||||
|
],
|
||||||
|
"x": 75.4921875,
|
||||||
|
"y": 0,
|
||||||
|
"width": 121.25,
|
||||||
|
"height": 188,
|
||||||
|
"text": "one"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
@ -0,0 +1,65 @@
|
|||||||
|
# How the Parser works under the hood ?
|
||||||
|
|
||||||
|
[This](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/index.ts) is the entry point of the library.
|
||||||
|
|
||||||
|
|
||||||
|
`parseMermaidToExcalidraw` function is the only function exposed which receives mermaid syntax as the input, parses the mermaid syntax and resolves to Excalidraw Skeleton.
|
||||||
|
|
||||||
|
Lets look at the high level overview at how the parse works :point_down:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Lets dive deeper into individual section now to understand better.
|
||||||
|
|
||||||
|
## Parsing Mermaid diagram
|
||||||
|
|
||||||
|
One of the dependencies of the library is [`mermaid`](https://www.npmjs.com/package/mermaid) library.
|
||||||
|
We need the mermaid diagram in some extractable format so we can parse it to Excalidraw Elements.
|
||||||
|
|
||||||
|
Parsing is broken into two steps
|
||||||
|
1. [`Rendering Mermaid to Svg`](/docs/@excalidraw/mermaid-to-excalidraw/codebase/parser#rendering-mermaid-to-svg) - This helps in determining the position and dimensions of each element in the diagram
|
||||||
|
|
||||||
|
2. [`Parsing the mermaid syntax`](/docs/@excalidraw/mermaid-to-excalidraw/codebase/parser#parsing-the-mermaid-syntax) - We also need to know how elements are connected which isn't possible with svg alone hence we also parse the mermaid syntax which helps in determining the connections and bindings between elements in the diagram.
|
||||||
|
|
||||||
|
### Rendering Mermaid to Svg
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The [`mermaid`](https://www.npmjs.com/package/mermaid) library provides the API `mermaid.render` API which gives the output of the diagram in `svg`.
|
||||||
|
|
||||||
|
|
||||||
|
If the diagram isn't supported, this svg is converted to `dataURL` and can be rendered as an image in Excalidraw.
|
||||||
|
|
||||||
|
|
||||||
|
### Parsing the mermaid syntax
|
||||||
|
|
||||||
|
For this we first need to process the options along with mermaid defination for diagram provided by the user.
|
||||||
|
|
||||||
|
[`processMermaidTextWithOptions`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/parseMermaid.ts#L13) takes the mermaid defination and options and returns the full defination including the mermaid [directives ](https://mermaid.js.org/config/directives.html).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Next we use mermaid api [getDiagramFromText](https://github.com/mermaid-js/mermaid/blob/00d06c7282a701849793680c1e97da1cfdfcce62/packages/mermaid/src/Diagram.ts#L80) to parse the full defination and get the [Diagram](https://github.com/mermaid-js/mermaid/blob/00d06c7282a701849793680c1e97da1cfdfcce62/packages/mermaid/src/Diagram.ts#L15) json from it.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const diagram = await mermaid.mermaidAPI.getDiagramFromText(fullDefinition);
|
||||||
|
```
|
||||||
|
|
||||||
|
Next we write our own parser to parse this diagram.
|
||||||
|
|
||||||
|
### Parsing the Diagram
|
||||||
|
|
||||||
|
For each diagram type, we need a parser as the result of every diagram would differ and dependinng on the data we have to write the parser. Since currently we support flowchart, so here is the [`parseMermaidFlowChartDiagram`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/parser/flowchart.ts#L256) to parse the flowchart diagram.
|
||||||
|
|
||||||
|
If you want to understand how flowchart parser works, you can navigate to [Flowchart Parser](http://localhost:3003/docs/@excalidraw/mermaid-to-excalidraw/codebase/parser/flowchart).
|
||||||
|
|
||||||
|
## Converting to ExcalidrawElementSkeleton
|
||||||
|
|
||||||
|
Now we have all the data, we just need to transform it to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133C13-L133C38) API so it can be rendered in Excalidraw.
|
||||||
|
|
||||||
|
For this we have `converters` which takes the parsed mermaid data and gives back the Excalidraw Skeleton.
|
||||||
|
For Unsupported types, we have already mentioned above that we convert it to `dataURL` and return the ExcalidrawImageSkeleton.
|
||||||
|
|
||||||
|
For supported types, currently only flowchart, we have [flowchartConverter](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/converter/types/flowchart.ts#L24) which parses the data and converts to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133C13-L133C38).
|
||||||
|
|
||||||
|

|
@ -0,0 +1,60 @@
|
|||||||
|
# Development
|
||||||
|
|
||||||
|
This page relates to developing the `@excalidraw/mermaid-to-excalidraw` package itself.
|
||||||
|
|
||||||
|
## Setting up in Local
|
||||||
|
|
||||||
|
To set up the library in local, follow the below steps 👇🏼
|
||||||
|
|
||||||
|
### Clone the Repository
|
||||||
|
|
||||||
|
Go to [@excalidraw/mermaid-to-excalidraw](https://github.com/excalidraw/mermaid-to-excalidraw) and clone the repository to your local.
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone git@github.com:excalidraw/mermaid-to-excalidraw.git
|
||||||
|
```
|
||||||
|
|
||||||
|
### Install the dependencies
|
||||||
|
|
||||||
|
Using `npm`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @excalidraw/mermaid-to-excalidraw
|
||||||
|
```
|
||||||
|
|
||||||
|
Using `yarn`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn add @excalidraw/mermaid-to-excalidraw
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run the playground server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn start
|
||||||
|
```
|
||||||
|
|
||||||
|
This will start the playground server in port `1234` and you start playing with the playground.
|
||||||
|
|
||||||
|
## Creating a test release
|
||||||
|
|
||||||
|
We will soon simplify creating release via commenting on GitHub PR similar till then you can create a release by following the below steps
|
||||||
|
|
||||||
|
1. Create the build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn build
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create the dist folder which we need to publish next.
|
||||||
|
|
||||||
|
2. Publish the library
|
||||||
|
|
||||||
|
Update the package name and version in [package.json](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/package.json) and run the below command to publish it
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn publish
|
||||||
|
```
|
||||||
|
|
||||||
|
And thats all your test release is successfully created 🎉
|
@ -0,0 +1,42 @@
|
|||||||
|
# Installation
|
||||||
|
|
||||||
|
`@excalidraw/mermaid-to-excalidraw` is published to npm. This library is used in [excalidraw](https://excalidraw.com) to transform mermaid syntax to Excalidraw diagrams.
|
||||||
|
|
||||||
|
Using `npm`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @excalidraw/mermaid-to-excalidraw
|
||||||
|
```
|
||||||
|
|
||||||
|
Using `yarn`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn add @excalidraw/mermaid-to-excalidraw
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Once the library is installed, its ready to use.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { parseMermaidToExcalidraw } from "@excalidraw/mermaid-to-excalidraw";
|
||||||
|
import { convertToExcalidrawElements} from "@excalidraw/excalidraw"
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { elements, files } = await parseMermaid(diagramDefinition, {
|
||||||
|
fontSize: DEFAULT_FONT_SIZE,
|
||||||
|
});
|
||||||
|
// currently the elements returned from the parser are in a "skeleton" format
|
||||||
|
// which we need to convert to fully qualified excalidraw elements first
|
||||||
|
const excalidrawElements = convertToExcalidrawElements(elements);
|
||||||
|
|
||||||
|
// Render elements and files on Excalidraw
|
||||||
|
} catch (e) {
|
||||||
|
// Error handling
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Playground
|
||||||
|
|
||||||
|
Try it out [here](https://mermaid-to-excalidraw.vercel.app)
|
||||||
|
|
22
dev-docs/docs/codebase/frames.mdx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Frames
|
||||||
|
|
||||||
|
## Ordering
|
||||||
|
|
||||||
|
Frames should be ordered where frame children come first, followed by the frame element itself:
|
||||||
|
|
||||||
|
```
|
||||||
|
[
|
||||||
|
other_element,
|
||||||
|
frame1_child1,
|
||||||
|
frame1_child2,
|
||||||
|
frame1,
|
||||||
|
other_element,
|
||||||
|
frame2_child1,
|
||||||
|
frame2_child2,
|
||||||
|
frame2,
|
||||||
|
other_element,
|
||||||
|
...
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
If not ordered correctly, the editor will still function, but the elements may not be rendered and clipped correctly. Further, the renderer relies on this ordering for performance optimizations.
|
75
dev-docs/docs/codebase/json-schema.mdx
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# JSON Schema
|
||||||
|
|
||||||
|
The Excalidraw data format uses plaintext JSON.
|
||||||
|
|
||||||
|
## Excalidraw files
|
||||||
|
|
||||||
|
When saving an Excalidraw scene locally to a file, the JSON file (`.excalidraw`) is using the below format.
|
||||||
|
|
||||||
|
### Attributes
|
||||||
|
|
||||||
|
| Attribute | Description | Value |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `type` | The type of the Excalidraw schema | `"excalidraw"` |
|
||||||
|
| `version` | The version of the Excalidraw schema | number |
|
||||||
|
| `source` | The source URL of the Excalidraw application | `"https://excalidraw.com"` |
|
||||||
|
| `elements` | An array of objects representing excalidraw elements on canvas | Array containing excalidraw element objects |
|
||||||
|
| `appState` | Additional application state/configuration | Object containing application state properties |
|
||||||
|
| `files` | Data for excalidraw `image` elements | Object containing image data |
|
||||||
|
|
||||||
|
### JSON Schema example
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
// schema information
|
||||||
|
"type": "excalidraw",
|
||||||
|
"version": 2,
|
||||||
|
"source": "https://excalidraw.com",
|
||||||
|
|
||||||
|
// elements on canvas
|
||||||
|
"elements": [
|
||||||
|
// example element
|
||||||
|
{
|
||||||
|
"id": "pologsyG-tAraPgiN9xP9b",
|
||||||
|
"type": "rectangle",
|
||||||
|
"x": 928,
|
||||||
|
"y": 319,
|
||||||
|
"width": 134,
|
||||||
|
"height": 90
|
||||||
|
/* ...other element properties */
|
||||||
|
}
|
||||||
|
/* other elements */
|
||||||
|
],
|
||||||
|
|
||||||
|
// editor state (canvas config, preferences, ...)
|
||||||
|
"appState": {
|
||||||
|
"gridSize": null,
|
||||||
|
"viewBackgroundColor": "#ffffff"
|
||||||
|
},
|
||||||
|
|
||||||
|
// files data for "image" elements, using format `{ [fileId]: fileData }`
|
||||||
|
"files": {
|
||||||
|
// example of an image data object
|
||||||
|
"3cebd7720911620a3938ce77243696149da03861": {
|
||||||
|
"mimeType": "image/png",
|
||||||
|
"id": "3cebd7720911620a3938c.77243626149da03861",
|
||||||
|
"dataURL": "data:image/png;base64,iVBORWOKGgoAAAANSUhEUgA=",
|
||||||
|
"created": 1690295874454,
|
||||||
|
"lastRetrieved": 1690295874454
|
||||||
|
}
|
||||||
|
/* ...other image data objects */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Excalidraw clipboard format
|
||||||
|
|
||||||
|
When copying selected excalidraw elements to clipboard, the JSON schema is similar to `.excalidraw` format, except it differs in attributes.
|
||||||
|
|
||||||
|
### Attributes
|
||||||
|
|
||||||
|
| Attribute | Description | Example Value |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `type` | The type of the Excalidraw document. | "excalidraw/clipboard" |
|
||||||
|
| `elements` | An array of objects representing excalidraw elements on canvas. | Array containing excalidraw element objects (see example below) |
|
||||||
|
| `files` | Data for excalidraw `image` elements. | Object containing image data |
|
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
Pull requests are welcome. For major changes, please [open an issue](https://github.com/excalidraw/excalidraw/issues/new) first to discuss what you would like to change.
|
Pull requests are welcome. For major changes, please [open an issue](https://github.com/excalidraw/excalidraw/issues/new) first to discuss what you would like to change.
|
||||||
|
|
||||||
|
We have a [roadmap](https://github.com/orgs/excalidraw/projects/3) which we strongly recommend to go through and check if something interests you.
|
||||||
|
For new contributors we would recommend to start with *Easy* tasks.
|
||||||
|
|
||||||
|
In case you want to pick up something from the roadmap, comment on that issue and one of the project maintainers will assign it to you, post which you can discuss in the issue and start working on it.
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
### Option 1 - Manual
|
### Option 1 - Manual
|
||||||
@ -10,7 +15,7 @@ Pull requests are welcome. For major changes, please [open an issue](https://git
|
|||||||
1. Run `yarn` to install dependencies
|
1. Run `yarn` to install dependencies
|
||||||
1. Create a branch for your PR with `git checkout -b your-branch-name`
|
1. Create a branch for your PR with `git checkout -b your-branch-name`
|
||||||
|
|
||||||
> To keep `master` branch pointing to remote repository and make pull requests from branches on your fork. To do this, run:
|
> To keep `master` branch pointing to remote repository and make pull requests from branches on your fork, run:
|
||||||
>
|
>
|
||||||
> ```bash
|
> ```bash
|
||||||
> git remote add upstream https://github.com/excalidraw/excalidraw.git
|
> git remote add upstream https://github.com/excalidraw/excalidraw.git
|
||||||
@ -47,15 +52,6 @@ Make sure the title starts with a semantic prefix:
|
|||||||
- **chore**: Other changes that don't modify src or test files
|
- **chore**: Other changes that don't modify src or test files
|
||||||
- **revert**: Reverts a previous commit
|
- **revert**: Reverts a previous commit
|
||||||
|
|
||||||
### Changelog
|
|
||||||
|
|
||||||
Add a brief description of your pull request to the changelog located here: [changelog](https://github.com/excalidraw/excalidraw/blob/master/CHANGELOG.md)
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
|
|
||||||
- Make sure to prepend to the section corresponding with the semantic prefix you selected in the title
|
|
||||||
- Link to your pull request - this will require updating the CHANGELOG _after_ creating the pull request
|
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
Once you submit your pull request it will automatically be tested. Be sure to check the results of the test and fix any issues that arise.
|
Once you submit your pull request it will automatically be tested. Be sure to check the results of the test and fix any issues that arise.
|
||||||
@ -64,6 +60,10 @@ It's also a good idea to consider if your change should include additional tests
|
|||||||
|
|
||||||
Finally - always manually test your changes using the convenient staging environment deployed for each pull request. As much as local development attempts to replicate production, there can still be subtle differences in behavior. For larger features consider testing your change in multiple browsers as well.
|
Finally - always manually test your changes using the convenient staging environment deployed for each pull request. As much as local development attempts to replicate production, there can still be subtle differences in behavior. For larger features consider testing your change in multiple browsers as well.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Some checks, such as the `lint` and `test`, require approval from the maintainers to run.
|
||||||
|
They will appear as `Expected — Waiting for status to be reported` in the PR checks when they are waiting for approval.
|
||||||
|
:::
|
||||||
|
|
||||||
## Translating
|
## Translating
|
||||||
|
|
||||||
|
@ -14,3 +14,4 @@ These docs are focused on developers, and structured in the following way:
|
|||||||
- [Introduction](/docs/) — development setup and introduction.
|
- [Introduction](/docs/) — development setup and introduction.
|
||||||
- [@excalidraw/excalidraw](/docs/@excalidraw/excalidraw/installation) — docs for the npm package to help you integrate Excalidraw into your own app.
|
- [@excalidraw/excalidraw](/docs/@excalidraw/excalidraw/installation) — docs for the npm package to help you integrate Excalidraw into your own app.
|
||||||
- Editor — IN PROGRESS. Docs describing the internals of the Excalidraw editor to help in contributing to the codebase.
|
- Editor — IN PROGRESS. Docs describing the internals of the Excalidraw editor to help in contributing to the codebase.
|
||||||
|
- [@excalidraw/mermaid-to-excalidraw](/docs/@excalidraw/mermaid-to-excalidraw/installation) - Docs for the mermaid to excalidraw parser
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
// Note: type annotations allow type checking and IDEs autocompletion
|
// 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} */
|
/** @type {import('@docusaurus/types').Config} */
|
||||||
const config = {
|
const config = {
|
||||||
title: "Excalidraw developer docs",
|
title: "Excalidraw developer docs",
|
||||||
@ -10,7 +15,7 @@ const config = {
|
|||||||
baseUrl: "/",
|
baseUrl: "/",
|
||||||
onBrokenLinks: "throw",
|
onBrokenLinks: "throw",
|
||||||
onBrokenMarkdownLinks: "warn",
|
onBrokenMarkdownLinks: "warn",
|
||||||
favicon: "img/favicon.ico",
|
favicon: "img/favicon.png",
|
||||||
organizationName: "Excalidraw", // Usually your GitHub org/user name.
|
organizationName: "Excalidraw", // Usually your GitHub org/user name.
|
||||||
projectName: "excalidraw", // Usually your repo name.
|
projectName: "excalidraw", // Usually your repo name.
|
||||||
|
|
||||||
@ -36,10 +41,7 @@ const config = {
|
|||||||
showLastUpdateTime: true,
|
showLastUpdateTime: true,
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
customCss: [
|
customCss: [require.resolve("./src/css/custom.scss")],
|
||||||
require.resolve("./src/css/custom.scss"),
|
|
||||||
require.resolve("../src/packages/excalidraw/example/App.scss"),
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@ -123,7 +125,7 @@ const config = {
|
|||||||
prism: {
|
prism: {
|
||||||
theme: require("prism-react-renderer/themes/dracula"),
|
theme: require("prism-react-renderer/themes/dracula"),
|
||||||
},
|
},
|
||||||
image: "img/og-image.png",
|
image: "img/og-image-2.png",
|
||||||
docs: {
|
docs: {
|
||||||
sidebar: {
|
sidebar: {
|
||||||
hideable: true,
|
hideable: true,
|
||||||
@ -139,7 +141,15 @@ const config = {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
themes: ["@docusaurus/theme-live-codeblock"],
|
themes: ["@docusaurus/theme-live-codeblock"],
|
||||||
plugins: ["docusaurus-plugin-sass"],
|
plugins: [
|
||||||
|
"docusaurus-plugin-sass",
|
||||||
|
[
|
||||||
|
"docusaurus2-dotenv",
|
||||||
|
{
|
||||||
|
systemvars: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = config;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
"@docusaurus/core": "2.2.0",
|
"@docusaurus/core": "2.2.0",
|
||||||
"@docusaurus/preset-classic": "2.2.0",
|
"@docusaurus/preset-classic": "2.2.0",
|
||||||
"@docusaurus/theme-live-codeblock": "2.2.0",
|
"@docusaurus/theme-live-codeblock": "2.2.0",
|
||||||
"@excalidraw/excalidraw": "0.14.2",
|
"@excalidraw/excalidraw": "0.17.0",
|
||||||
"@mdx-js/react": "^1.6.22",
|
"@mdx-js/react": "^1.6.22",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"docusaurus-plugin-sass": "0.2.3",
|
"docusaurus-plugin-sass": "0.2.3",
|
||||||
@ -30,6 +30,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/module-type-aliases": "2.0.0-rc.1",
|
"@docusaurus/module-type-aliases": "2.0.0-rc.1",
|
||||||
"@tsconfig/docusaurus": "^1.0.5",
|
"@tsconfig/docusaurus": "^1.0.5",
|
||||||
|
"docusaurus2-dotenv": "1.4.0",
|
||||||
"typescript": "^4.7.4"
|
"typescript": "^4.7.4"
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
|
@ -23,7 +23,11 @@ const sidebars = {
|
|||||||
},
|
},
|
||||||
items: ["introduction/development", "introduction/contributing"],
|
items: ["introduction/development", "introduction/contributing"],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "category",
|
||||||
|
label: "Codebase",
|
||||||
|
items: ["codebase/json-schema", "codebase/frames"],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "category",
|
type: "category",
|
||||||
label: "@excalidraw/excalidraw",
|
label: "@excalidraw/excalidraw",
|
||||||
@ -49,7 +53,7 @@ const sidebars = {
|
|||||||
},
|
},
|
||||||
items: [
|
items: [
|
||||||
"@excalidraw/excalidraw/api/props/initialdata",
|
"@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/render-props",
|
||||||
"@excalidraw/excalidraw/api/props/ui-options",
|
"@excalidraw/excalidraw/api/props/ui-options",
|
||||||
],
|
],
|
||||||
@ -64,6 +68,7 @@ const sidebars = {
|
|||||||
items: [
|
items: [
|
||||||
"@excalidraw/excalidraw/api/children-components/main-menu",
|
"@excalidraw/excalidraw/api/children-components/main-menu",
|
||||||
"@excalidraw/excalidraw/api/children-components/welcome-screen",
|
"@excalidraw/excalidraw/api/children-components/welcome-screen",
|
||||||
|
"@excalidraw/excalidraw/api/children-components/sidebar",
|
||||||
"@excalidraw/excalidraw/api/children-components/footer",
|
"@excalidraw/excalidraw/api/children-components/footer",
|
||||||
"@excalidraw/excalidraw/api/children-components/live-collaboration-trigger",
|
"@excalidraw/excalidraw/api/children-components/live-collaboration-trigger",
|
||||||
],
|
],
|
||||||
@ -80,18 +85,48 @@ const sidebars = {
|
|||||||
"@excalidraw/excalidraw/api/utils/restore",
|
"@excalidraw/excalidraw/api/utils/restore",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
"@excalidraw/excalidraw/api/constants",
|
||||||
type: "category",
|
"@excalidraw/excalidraw/api/excalidraw-element-skeleton",
|
||||||
label: "Constants",
|
|
||||||
link: { type: "doc", id: "@excalidraw/excalidraw/api/constants" },
|
|
||||||
items: [],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"@excalidraw/excalidraw/faq",
|
"@excalidraw/excalidraw/faq",
|
||||||
"@excalidraw/excalidraw/development",
|
"@excalidraw/excalidraw/development",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "category",
|
||||||
|
label: "@excalidraw/mermaid-to-excalidraw",
|
||||||
|
link: {
|
||||||
|
type: "doc",
|
||||||
|
id: "@excalidraw/mermaid-to-excalidraw/installation",
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
"@excalidraw/mermaid-to-excalidraw/api",
|
||||||
|
"@excalidraw/mermaid-to-excalidraw/development",
|
||||||
|
{
|
||||||
|
type: "category",
|
||||||
|
label: "Codebase",
|
||||||
|
link: {
|
||||||
|
type: "doc",
|
||||||
|
id: "@excalidraw/mermaid-to-excalidraw/codebase/codebase",
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: "category",
|
||||||
|
label: "How Parser works under the hood?",
|
||||||
|
link: {
|
||||||
|
type: "doc",
|
||||||
|
id: "@excalidraw/mermaid-to-excalidraw/codebase/parser/parser",
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
"@excalidraw/mermaid-to-excalidraw/codebase/parser/flowchart",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"@excalidraw/mermaid-to-excalidraw/codebase/new-diagram-type",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ const FeatureList = [
|
|||||||
Svg: require("@site/static/img/undraw_blank_canvas.svg").default,
|
Svg: require("@site/static/img/undraw_blank_canvas.svg").default,
|
||||||
description: (
|
description: (
|
||||||
<>
|
<>
|
||||||
Want to build your own app powered by Excalidraw by don't know where to
|
Want to build your own app powered by Excalidraw but don't know where to
|
||||||
start?
|
start?
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
|
@ -24,6 +24,8 @@ const ExcalidrawScope = {
|
|||||||
Sidebar: ExcalidrawComp.Sidebar,
|
Sidebar: ExcalidrawComp.Sidebar,
|
||||||
exportToCanvas: ExcalidrawComp.exportToCanvas,
|
exportToCanvas: ExcalidrawComp.exportToCanvas,
|
||||||
initialData,
|
initialData,
|
||||||
|
useI18n: ExcalidrawComp.useI18n,
|
||||||
|
convertToExcalidrawElements: ExcalidrawComp.convertToExcalidrawElements,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ExcalidrawScope;
|
export default ExcalidrawScope;
|
||||||
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 15 KiB |
BIN
dev-docs/static/img/favicon.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
@ -1,4 +1,7 @@
|
|||||||
<svg viewBox="0 0 80 180" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2">
|
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
|
||||||
<path d="M22.197 150.382c-4.179-3.359-10.618-9.051-15.702-13.946l-4.01-3.813.734-5.009c.396-2.732 1.13-8.083 1.582-11.839.508-3.757 1.017-7.286 1.186-7.798.226-.683 0-1.025-.621-1.025-1.073 0-1.13.285 1.807-9.107a617.602 617.602 0 0 1 2.203-7.229c.113-.398.565-.569 1.073-.398.508.227.791.683.621 1.081-.169.455.113.911.565 1.082.621.227.565.683-.395 2.333-1.525 2.562-5.422 24.419-5.648 31.477-.17 5.009-.17 5.066 1.92 7.912 2.033 2.789 6.721 7.001 13.951 12.351 2.033 1.537 4.067 3.245 4.631 3.814.848 1.024 1.243.74 8.36-6.887 4.123-4.383 8.698-8.88 10.166-10.018l2.711-2.049-2.089-4.44c-1.13-2.391-5.705-11.612-10.223-20.377-9.433-18.442-7.513-16.678-18.47-16.849l-7.117-.056-2.372-2.733c-2.485-2.903-2.824-3.984-1.638-5.805.452-.627.791-1.651.791-2.277 0-1.025.395-1.196 2.655-1.309 1.412-.057 2.711-.228 2.88-.399.17-.171.396-3.7.565-7.855l.226-7.513-3.784-8.197C2.485 39.844 0 33.583 0 31.533c0-1.081.226-1.992.452-1.992.565 0 .565.057 23.553 48.382 10.675 22.426 20.785 43.544 22.479 47.016 1.695 3.472 3.22 6.659 3.333 7.115.113.512-3.785 4.439-9.998 9.961-5.591 5.008-10.505 9.562-10.957 10.074-1.299 1.594-3.219 1.082-6.665-1.707Zm1.921-65.458c-2.599-5.066-2.712-5.123-9.828-5.464-6.27-.342-6.383-.285-6.383.911 0 .683-.226 1.593-.508 2.049-.339.512-.113 1.423.678 2.675l1.242 1.935h5.649c3.106.057 6.664.285 7.907.512 1.243.228 2.316.342 2.429.285.113-.057-.452-1.366-1.186-2.903Zm-4.745-9.107c-.452-1.195-1.638-3.7-2.598-5.578-1.581-3.188-1.751-3.301-2.146-1.992-.226.797-.396 3.13-.452 5.236-.057 4.155-.17 4.098 4.575 4.383l1.525.057-.904-2.106Z" style="fill-rule:nonzero;stroke:#000;stroke-width:2px" transform="matrix(1.01351 0 0 -1 9.088 166.517)" />
|
<rect width="1000" height="1000" rx="200" ry="200" fill="#fff" />
|
||||||
<path d="M23.892 136.835c-1.017-.74-1.299-1.48-1.299-3.358 0-2.22.169-2.562 1.694-3.188 1.525-.626 1.92-.569 3.671.626 2.316 1.594 2.373 1.992.678 4.554-1.468 2.22-2.937 2.618-4.744 1.366Zm3.219-2.049c.904-1.594.339-2.789-1.355-2.789-1.525 0-2.203 1.536-1.356 3.073.678 1.253 1.977 1.139 2.711-.284ZM59.306 124.028c0-.285-.339-.569-.735-.569-.339 0-1.299-1.594-2.033-3.529-2.259-5.92-24.852-50.943-24.908-49.52 0 .74-.339 1.252-.904 1.252-.791 0-.904-.456-.565-2.675.339-2.562.113-3.131-7.907-18.841-4.519-8.936-9.376-18.271-10.788-20.775-1.469-2.619-2.598-5.465-2.711-6.66-.17-2.049.056-2.334 4.97-6.603 2.824-2.504 6.439-5.635 8.02-7.058C28.862 2.504 32.194-.114 33.098.057c1.356.228 22.31 22.369 22.367 23.622 0 .569-1.017 9.221-2.259 19.238-2.147 17.076-4.18 37.055-3.954 38.99.169 1.196-.678 7.229-1.299 9.847-.509 2.05-.283 2.903 3.784 12.238 2.372 5.521 5.479 12.295 6.834 15.027 1.299 2.732 2.429 5.123 2.429 5.294 0 .17-.395.284-.847.284-.452 0-.847-.228-.847-.569ZM46.315 81.509c.621-3.984 1.864-13.547 2.767-21.231 1.751-14.116 3.785-29.769 4.349-33.753.339-1.993.113-2.391-3.558-6.489-6.382-7.229-13.16-14.344-15.476-16.165l-2.146-1.708-11.014 10.359C11.07 21.971 10.223 22.939 10.844 24.077c.339.626 3.22 5.92 6.383 11.725 3.163 5.806 7.342 13.547 9.263 17.19 1.977 3.7 3.784 6.887 4.123 7.058.395.228.508-5.521.395-17.759-.226-18.271-.169-18.328 1.638-17.929.226 0 .396 9.221.396 20.434v20.377l5.93 11.953c3.276 6.603 5.987 11.896 6.1 11.84.113-.058.678-3.416 1.243-7.457Z" style="fill-rule:nonzero;stroke:#000;stroke-width:2px" transform="matrix(1.01351 0 0 -1 9.088 166.517)" />
|
<svg viewBox="0 0 107 101" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2">
|
||||||
|
<path style="fill:none" d="M24 17h121v121H24z" transform="matrix(.8843 0 0 .83471 -21.223 -14.19)" />
|
||||||
|
<path d="M119.81 105.98a.549.549 0 0 0-.53-.12c-4.19-6.19-9.52-12.06-14.68-17.73l-.85-.93c0-.11-.05-.21-.12-.3a.548.548 0 0 0-.34-.2l-.17-.18-.12-.09c-.15-.32-.53-.56-.95-.35-1.58.81-3 1.97-4.4 3.04-1.87 1.43-3.7 2.92-5.42 4.52-.7.65-1.39 1.33-1.97 2.09-.28.37-.07.72.27.87-1.22 1.2-2.45 2.45-3.68 3.74-.11.12-.17.28-.16.44.01.16.09.31.22.41l2.16 1.65s.01.03.03.04c3.09 3.05 8.51 7.28 14.25 11.76.85.67 1.71 1.34 2.57 2.01.39.47.76.94 1.12 1.4.19.25.55.3.8.11.13.1.26.21.39.31a.57.57 0 0 0 .8-.1c.07-.09.1-.2.11-.31.04 0 .07.03.1.03.15 0 .31-.06.42-.18l10.18-11.12a.56.56 0 0 0-.04-.8l.01-.01Zm-29.23-3.85c.07.09.14.17.21.25 1.16.98 2.4 2.04 3.66 3.12l-5.12-3.91s-.32-.22-.52-.36c-.11-.08-.21-.16-.31-.24l-.38-.32s.07-.07.1-.11l.35-.35c1.72-1.74 4.67-4.64 6.19-6.06-1.61 1.62-4.87 6.37-4.17 7.98h-.01Zm17.53 13.81-4.22-3.22c-1.65-1.71-3.43-3.4-5.24-5.03 2.28 1.76 4.23 3.25 4.52 3.51 2.21 1.97 2.11 1.61 3.63 2.91l1.83 1.33c-.18.16-.36.33-.53.49l.01.01Zm1.06.81-.08-.06c.16-.13.33-.25.49-.38l-.4.44h-.01ZM42.24 51.45c.14.72.27 1.43.4 2.11.69 3.7 1.33 7.03 2.55 9.56l.48 1.92c.19.73.46 1.64.71 1.83 2.85 2.52 7.22 6.28 11.89 9.82.21.16.5.15.7-.01.01.02.03.03.04.04.11.1.24.15.38.15.16 0 .31-.06.42-.19 5.98-6.65 10.43-12.12 13.6-16.7.2-.25.3-.54.29-.84.2-.24.41-.48.6-.68a.558.558 0 0 0-.1-.86.578.578 0 0 0-.17-.36c-1.39-1.34-2.42-2.31-3.46-3.28-1.84-1.72-3.74-3.5-7.77-7.51-.02-.02-.05-.04-.07-.06a.555.555 0 0 0-.22-.14c-1.11-.39-3.39-.78-6.26-1.28-4.22-.72-10-1.72-15.2-3.27h-.04v-.01s-.02 0-.03.02h-.01l.04-.02s-.31.01-.37.04c-.08.04-.14.09-.19.15-.05.06-.09.12-.47.2-.38.08.08 0 .11 0h-.11v.03c.07.34.05.58.16.97-.02.1.21 1.02.24 1.11l1.83 7.26h.03Zm30.95 6.54s-.03.04-.04.05l-.64-.71c.22.21.44.42.68.66Zm-7.09 9.39s-.07.08-.1.12l-.02-.02c.04-.03.08-.07.13-.1h-.01Zm-7.07 8.47Zm3.02-28.57c.35.35 1.74 1.65 2.06 1.97-1.45-.66-5.06-2.34-6.74-2.88 1.65.29 3.93.66 4.68.91Zm-19.18-2.77c.84 1.44 1.5 6.49 2.16 11.4-.37-1.58-.69-3.12-.99-4.6-.52-2.56-1-4.85-1.67-6.88.14.01.31.03.49.05 0 .01 0 .02.02.03h-.01Zm-.29-1.21c-.23-.02-.44-.04-.62-.05-.02-.04-.03-.08-.04-.12l.66.18v-.01Zm-2.22.45v-.02.02ZM118.9 42.57c.04-.23-1.1-1.24-.74-1.26.85-.04.86-1.35 0-1.31-1.13.06-2.27.32-3.37.53-1.98.37-3.95.78-5.92 1.21-4.39.94-8.77 1.93-13.1 3.11-1.36.37-2.86.7-4.11 1.36-.42.22-.4.67-.17.95-.09.05-.18.08-.28.09-.37.07-.74.13-1.11.19a.566.566 0 0 0-.39.86c-2.32 3.1-4.96 6.44-7.82 9.95-2.81 3.21-5.73 6.63-8.72 10.14-9.41 11.06-20.08 23.6-31.9 34.64-.23.21-.24.57-.03.8.05.06.12.1.19.13-.16.15-.32.3-.48.44-.1.09-.14.2-.16.32-.08.08-.16.17-.23.25-.21.23-.2.59.03.8.23.21.59.2.8-.03.04-.04.08-.09.12-.13a.84.84 0 0 1 1.22 0c.69.74 1.34 1.44 1.95 2.09l-1.38-1.15a.57.57 0 0 0-.8.07c-.2.24-.17.6.07.8l14.82 12.43c.11.09.24.13.37.13.15 0 .29-.06.4-.17l.36-.36a.56.56 0 0 0 .63-.12c20.09-20.18 36.27-35.43 54.8-49.06.17-.12.25-.32.23-.51a.57.57 0 0 0 .48-.39c3.42-10.46 4.08-19.72 4.28-24.27 0-.03.01-.05.02-.07.02-.05.03-.1.04-.14.03-.11.05-.19.05-.19.26-.78.17-1.53-.15-2.15v.02ZM82.98 58.94c.9-1.03 1.79-2.04 2.67-3.02-5.76 7.58-15.3 19.26-28.81 33.14 9.2-10.18 18.47-20.73 26.14-30.12Zm-32.55 52.81-.03-.03c.11.02.19.04.2.04a.47.47 0 0 0-.17 0v-.01Zm6.9 6.42-.05-.04.03-.03c.02 0 .03.02.04.02 0 .02-.02.03-.03.05h.01Zm8.36-7.21 1.38-1.44c.01.01.02.03.03.05-.47.46-.94.93-1.42 1.39h.01Zm2.24-2.21c.26-.3.56-.65.87-1.02.01-.01.02-.03.04-.04 3.29-3.39 6.68-6.82 10.18-10.25.02-.02.05-.04.07-.06.86-.66 1.82-1.39 2.72-2.08-4.52 4.32-9.11 8.78-13.88 13.46v-.01Zm21.65-55.88c-1.86 2.42-3.9 5.56-5.63 8.07-5.46 7.91-23.04 27.28-23.43 27.65-2.71 2.62-10.88 10.46-16.09 15.37-.14.13-.25.24-.34.35a.794.794 0 0 1 .03-1.13c24.82-23.4 39.88-42.89 46-51.38-.13.33-.24.69-.55 1.09l.01-.02Zm16.51 7.1-.01.02c0-.02-.02-.07.01-.02Zm-.91-5.13Zm-5.89 9.45c-2.26-1.31-3.32-3.27-2.71-5.25l.19-.66c.08-.19.17-.38.28-.57.59-.98 1.49-1.85 2.52-2.36.05-.02.1-.03.15-.04a.795.795 0 0 1-.04-.43c.05-.31.25-.58.66-.58.67 0 2.75.62 3.54 1.3.24.19.47.4.68.63.3.35.74.92.96 1.33.13.06.23.62.38.91.14.46.2.93.18 1.4 0 .02 0 .02.01.03-.03.07 0 .37-.04.4-.1.72-.36 1.43-.75 2.05-.04.05-.07.11-.11.16 0 .01-.02.02-.03.04-.3.43-.65.83-1.08 1.13-1.26.89-2.73 1.16-4.2.79a6.33 6.33 0 0 1-.57-.25l-.02-.03Zm16.27-1.63c-.49 2.05-1.09 4.19-1.8 6.38-.03.08-.03.16-.03.23-.1.01-.19.05-.27.11-4.44 3.26-8.73 6.62-12.98 10.11 3.67-3.32 7.39-6.62 11.23-9.95a6.409 6.409 0 0 0 2.11-3.74l.56-3.37.03-.1c.25-.71 1.34-.4 1.17.33h-.02Z" style="fill:#6965db;fill-rule:nonzero" transform="matrix(1 0 0 1 -26.41 -29.49)" />
|
||||||
|
</svg>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 4.8 KiB |
BIN
dev-docs/static/img/og-image-2.png
Normal file
After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 76 KiB |
4
dev-docs/vercel.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"outputDirectory": "build",
|
||||||
|
"installCommand": "yarn install"
|
||||||
|
}
|
@ -145,6 +145,14 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/highlight" "^7.18.6"
|
"@babel/highlight" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/code-frame@^7.22.13":
|
||||||
|
version "7.22.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e"
|
||||||
|
integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==
|
||||||
|
dependencies:
|
||||||
|
"@babel/highlight" "^7.22.13"
|
||||||
|
chalk "^2.4.2"
|
||||||
|
|
||||||
"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8":
|
"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8":
|
||||||
version "7.18.8"
|
version "7.18.8"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d"
|
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d"
|
||||||
@ -202,6 +210,16 @@
|
|||||||
"@jridgewell/gen-mapping" "^0.3.2"
|
"@jridgewell/gen-mapping" "^0.3.2"
|
||||||
jsesc "^2.5.1"
|
jsesc "^2.5.1"
|
||||||
|
|
||||||
|
"@babel/generator@^7.23.0":
|
||||||
|
version "7.23.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420"
|
||||||
|
integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.23.0"
|
||||||
|
"@jridgewell/gen-mapping" "^0.3.2"
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.17"
|
||||||
|
jsesc "^2.5.1"
|
||||||
|
|
||||||
"@babel/helper-annotate-as-pure@^7.18.6":
|
"@babel/helper-annotate-as-pure@^7.18.6":
|
||||||
version "7.18.6"
|
version "7.18.6"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
|
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
|
||||||
@ -265,6 +283,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be"
|
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be"
|
||||||
integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
|
integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
|
||||||
|
|
||||||
|
"@babel/helper-environment-visitor@^7.22.20":
|
||||||
|
version "7.22.20"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
|
||||||
|
integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
|
||||||
|
|
||||||
"@babel/helper-explode-assignable-expression@^7.18.6":
|
"@babel/helper-explode-assignable-expression@^7.18.6":
|
||||||
version "7.18.6"
|
version "7.18.6"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096"
|
resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096"
|
||||||
@ -280,6 +303,14 @@
|
|||||||
"@babel/template" "^7.18.6"
|
"@babel/template" "^7.18.6"
|
||||||
"@babel/types" "^7.18.9"
|
"@babel/types" "^7.18.9"
|
||||||
|
|
||||||
|
"@babel/helper-function-name@^7.23.0":
|
||||||
|
version "7.23.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
|
||||||
|
integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/template" "^7.22.15"
|
||||||
|
"@babel/types" "^7.23.0"
|
||||||
|
|
||||||
"@babel/helper-hoist-variables@^7.18.6":
|
"@babel/helper-hoist-variables@^7.18.6":
|
||||||
version "7.18.6"
|
version "7.18.6"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678"
|
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678"
|
||||||
@ -287,6 +318,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.18.6"
|
"@babel/types" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/helper-hoist-variables@^7.22.5":
|
||||||
|
version "7.22.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb"
|
||||||
|
integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.22.5"
|
||||||
|
|
||||||
"@babel/helper-member-expression-to-functions@^7.18.9":
|
"@babel/helper-member-expression-to-functions@^7.18.9":
|
||||||
version "7.18.9"
|
version "7.18.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815"
|
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815"
|
||||||
@ -374,11 +412,28 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.18.6"
|
"@babel/types" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/helper-split-export-declaration@^7.22.6":
|
||||||
|
version "7.22.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
|
||||||
|
integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.22.5"
|
||||||
|
|
||||||
|
"@babel/helper-string-parser@^7.22.5":
|
||||||
|
version "7.22.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
|
||||||
|
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
|
||||||
|
|
||||||
"@babel/helper-validator-identifier@^7.18.6":
|
"@babel/helper-validator-identifier@^7.18.6":
|
||||||
version "7.18.6"
|
version "7.18.6"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076"
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076"
|
||||||
integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==
|
integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==
|
||||||
|
|
||||||
|
"@babel/helper-validator-identifier@^7.22.20":
|
||||||
|
version "7.22.20"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
|
||||||
|
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
|
||||||
|
|
||||||
"@babel/helper-validator-option@^7.18.6":
|
"@babel/helper-validator-option@^7.18.6":
|
||||||
version "7.18.6"
|
version "7.18.6"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
|
||||||
@ -412,11 +467,25 @@
|
|||||||
chalk "^2.0.0"
|
chalk "^2.0.0"
|
||||||
js-tokens "^4.0.0"
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
|
"@babel/highlight@^7.22.13":
|
||||||
|
version "7.22.20"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54"
|
||||||
|
integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-validator-identifier" "^7.22.20"
|
||||||
|
chalk "^2.4.2"
|
||||||
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
"@babel/parser@^7.12.7", "@babel/parser@^7.18.6", "@babel/parser@^7.18.8", "@babel/parser@^7.18.9":
|
"@babel/parser@^7.12.7", "@babel/parser@^7.18.6", "@babel/parser@^7.18.8", "@babel/parser@^7.18.9":
|
||||||
version "7.18.9"
|
version "7.18.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.9.tgz#f2dde0c682ccc264a9a8595efd030a5cc8fd2539"
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.9.tgz#f2dde0c682ccc264a9a8595efd030a5cc8fd2539"
|
||||||
integrity sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==
|
integrity sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==
|
||||||
|
|
||||||
|
"@babel/parser@^7.22.15", "@babel/parser@^7.23.0":
|
||||||
|
version "7.23.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
|
||||||
|
integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
|
||||||
|
|
||||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
|
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
|
||||||
version "7.18.6"
|
version "7.18.6"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2"
|
||||||
@ -1147,19 +1216,28 @@
|
|||||||
"@babel/parser" "^7.18.6"
|
"@babel/parser" "^7.18.6"
|
||||||
"@babel/types" "^7.18.6"
|
"@babel/types" "^7.18.6"
|
||||||
|
|
||||||
"@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.18.9":
|
"@babel/template@^7.22.15":
|
||||||
version "7.18.9"
|
version "7.22.15"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.9.tgz#deeff3e8f1bad9786874cb2feda7a2d77a904f98"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
|
||||||
integrity sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==
|
integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.18.6"
|
"@babel/code-frame" "^7.22.13"
|
||||||
"@babel/generator" "^7.18.9"
|
"@babel/parser" "^7.22.15"
|
||||||
"@babel/helper-environment-visitor" "^7.18.9"
|
"@babel/types" "^7.22.15"
|
||||||
"@babel/helper-function-name" "^7.18.9"
|
|
||||||
"@babel/helper-hoist-variables" "^7.18.6"
|
"@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.18.9":
|
||||||
"@babel/helper-split-export-declaration" "^7.18.6"
|
version "7.23.2"
|
||||||
"@babel/parser" "^7.18.9"
|
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
|
||||||
"@babel/types" "^7.18.9"
|
integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.22.13"
|
||||||
|
"@babel/generator" "^7.23.0"
|
||||||
|
"@babel/helper-environment-visitor" "^7.22.20"
|
||||||
|
"@babel/helper-function-name" "^7.23.0"
|
||||||
|
"@babel/helper-hoist-variables" "^7.22.5"
|
||||||
|
"@babel/helper-split-export-declaration" "^7.22.6"
|
||||||
|
"@babel/parser" "^7.23.0"
|
||||||
|
"@babel/types" "^7.23.0"
|
||||||
debug "^4.1.0"
|
debug "^4.1.0"
|
||||||
globals "^11.1.0"
|
globals "^11.1.0"
|
||||||
|
|
||||||
@ -1171,6 +1249,15 @@
|
|||||||
"@babel/helper-validator-identifier" "^7.18.6"
|
"@babel/helper-validator-identifier" "^7.18.6"
|
||||||
to-fast-properties "^2.0.0"
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
|
"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0":
|
||||||
|
version "7.23.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb"
|
||||||
|
integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-string-parser" "^7.22.5"
|
||||||
|
"@babel/helper-validator-identifier" "^7.22.20"
|
||||||
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
"@colors/colors@1.5.0":
|
"@colors/colors@1.5.0":
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
|
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
|
||||||
@ -1631,10 +1718,10 @@
|
|||||||
url-loader "^4.1.1"
|
url-loader "^4.1.1"
|
||||||
webpack "^5.73.0"
|
webpack "^5.73.0"
|
||||||
|
|
||||||
"@excalidraw/excalidraw@0.14.2":
|
"@excalidraw/excalidraw@0.17.0":
|
||||||
version "0.14.2"
|
version "0.17.0"
|
||||||
resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.14.2.tgz#150cb4b7a1bf0d11cd64295936c930e7e0db8375"
|
resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.17.0.tgz#3c64aa8e36406ac171b008cfecbdce5bb0755725"
|
||||||
integrity sha512-8LdjpTBWEK5waDWB7Bt/G9YBI4j0OxkstUhvaDGz7dwQGfzF6FW5CXBoYHNEoX0qmb+Fg/NPOlZ7FrKsrSVCqg==
|
integrity sha512-NzP22v5xMqxYW27ZtTHhiGFe7kE8NeBk45aoeM/mDSkXiOXPDH+PcvwzHRN/Ei+Vj/0sTPHxejn8bZyRWKGjXg==
|
||||||
|
|
||||||
"@hapi/hoek@^9.0.0":
|
"@hapi/hoek@^9.0.0":
|
||||||
version "9.3.0"
|
version "9.3.0"
|
||||||
@ -1670,6 +1757,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
|
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
|
||||||
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
|
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
|
||||||
|
|
||||||
|
"@jridgewell/resolve-uri@^3.1.0":
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
|
||||||
|
integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
|
||||||
|
|
||||||
"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
|
"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
|
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
|
||||||
@ -1688,6 +1780,19 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
|
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
|
||||||
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
|
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
|
||||||
|
|
||||||
|
"@jridgewell/sourcemap-codec@^1.4.14":
|
||||||
|
version "1.4.15"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
|
||||||
|
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
|
||||||
|
|
||||||
|
"@jridgewell/trace-mapping@^0.3.17":
|
||||||
|
version "0.3.20"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f"
|
||||||
|
integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/resolve-uri" "^3.1.0"
|
||||||
|
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||||
|
|
||||||
"@jridgewell/trace-mapping@^0.3.7", "@jridgewell/trace-mapping@^0.3.9":
|
"@jridgewell/trace-mapping@^0.3.7", "@jridgewell/trace-mapping@^0.3.9":
|
||||||
version "0.3.14"
|
version "0.3.14"
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed"
|
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed"
|
||||||
@ -3462,6 +3567,13 @@ docusaurus-plugin-sass@0.2.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
sass-loader "^10.1.1"
|
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:
|
dom-converter@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768"
|
resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768"
|
||||||
@ -3547,6 +3659,25 @@ dot-prop@^5.2.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-obj "^2.0.0"
|
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:
|
duplexer3@^0.1.4:
|
||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e"
|
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e"
|
||||||
@ -6611,19 +6742,19 @@ semver@7.0.0:
|
|||||||
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
|
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
|
||||||
|
|
||||||
semver@^5.4.1:
|
semver@^5.4.1:
|
||||||
version "5.7.1"
|
version "5.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
|
||||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
||||||
|
|
||||||
semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0:
|
semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0:
|
||||||
version "6.3.0"
|
version "6.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||||
|
|
||||||
semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7:
|
semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7:
|
||||||
version "7.3.7"
|
version "7.5.4"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
|
||||||
integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
|
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
||||||
dependencies:
|
dependencies:
|
||||||
lru-cache "^6.0.0"
|
lru-cache "^6.0.0"
|
||||||
|
|
||||||
@ -7159,9 +7290,9 @@ typescript@^4.7.4:
|
|||||||
integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
|
integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
|
||||||
|
|
||||||
ua-parser-js@^0.7.30:
|
ua-parser-js@^0.7.30:
|
||||||
version "0.7.31"
|
version "0.7.33"
|
||||||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6"
|
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532"
|
||||||
integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==
|
integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==
|
||||||
|
|
||||||
unescape@^1.0.1:
|
unescape@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
|
@ -15,14 +15,23 @@
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.app-title {
|
||||||
|
margin-block-start: 0.83em;
|
||||||
|
margin-block-end: 0.83em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-wrapper button {
|
.button-wrapper {
|
||||||
z-index: 1;
|
input[type="checkbox"] {
|
||||||
height: 40px;
|
margin: 5px;
|
||||||
max-width: 200px;
|
}
|
||||||
margin: 10px;
|
button {
|
||||||
padding: 5px;
|
z-index: 1;
|
||||||
|
height: 40px;
|
||||||
|
max-width: 200px;
|
||||||
|
margin: 10px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.excalidraw .App-menu_top .buttonList {
|
.excalidraw .App-menu_top .buttonList {
|
@ -1,23 +1,31 @@
|
|||||||
import { useEffect, useState, useRef, useCallback } from "react";
|
import React, {
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
useRef,
|
||||||
|
useCallback,
|
||||||
|
Children,
|
||||||
|
cloneElement,
|
||||||
|
} from "react";
|
||||||
import ExampleSidebar from "./sidebar/ExampleSidebar";
|
import ExampleSidebar from "./sidebar/ExampleSidebar";
|
||||||
|
|
||||||
import type * as TExcalidraw from "../index";
|
import type * as TExcalidraw from "@excalidraw/excalidraw";
|
||||||
|
|
||||||
import "./App.scss";
|
|
||||||
import initialData from "./initialData";
|
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
|
|
||||||
|
import type { ResolvablePromise } from "../utils";
|
||||||
import {
|
import {
|
||||||
resolvablePromise,
|
resolvablePromise,
|
||||||
ResolvablePromise,
|
distance2d,
|
||||||
|
fileOpen,
|
||||||
withBatchedUpdates,
|
withBatchedUpdates,
|
||||||
withBatchedUpdatesThrottled,
|
withBatchedUpdatesThrottled,
|
||||||
} from "../../../utils";
|
} from "../utils";
|
||||||
import { EVENT, ROUNDNESS } from "../../../constants";
|
|
||||||
import { distance2d } from "../../../math";
|
import CustomFooter from "./CustomFooter";
|
||||||
import { fileOpen } from "../../../data/filesystem";
|
import MobileFooter from "./MobileFooter";
|
||||||
import { loadSceneOrLibraryFromBlob } from "../../utils";
|
import initialData from "../initialData";
|
||||||
import {
|
|
||||||
|
import type {
|
||||||
AppState,
|
AppState,
|
||||||
BinaryFileData,
|
BinaryFileData,
|
||||||
ExcalidrawImperativeAPI,
|
ExcalidrawImperativeAPI,
|
||||||
@ -25,17 +33,14 @@ import {
|
|||||||
Gesture,
|
Gesture,
|
||||||
LibraryItems,
|
LibraryItems,
|
||||||
PointerDownState as ExcalidrawPointerDownState,
|
PointerDownState as ExcalidrawPointerDownState,
|
||||||
} from "../../../types";
|
} from "@excalidraw/excalidraw/dist/excalidraw/types";
|
||||||
import { NonDeletedExcalidrawElement } from "../../../element/types";
|
import type {
|
||||||
import { ImportedLibraryData } from "../../../data/types";
|
NonDeletedExcalidrawElement,
|
||||||
import CustomFooter from "./CustomFooter";
|
Theme,
|
||||||
import MobileFooter from "./MobileFooter";
|
} from "@excalidraw/excalidraw/dist/excalidraw/element/types";
|
||||||
|
import type { ImportedLibraryData } from "@excalidraw/excalidraw/dist/excalidraw/data/types";
|
||||||
|
|
||||||
declare global {
|
import "./App.scss";
|
||||||
interface Window {
|
|
||||||
ExcalidrawLib: typeof TExcalidraw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Comment = {
|
type Comment = {
|
||||||
x: number;
|
x: number;
|
||||||
@ -55,26 +60,6 @@ type PointerDownState = {
|
|||||||
y: number;
|
y: number;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
// This is so that we use the bundled excalidraw.development.js file instead
|
|
||||||
// of the actual source code
|
|
||||||
|
|
||||||
const {
|
|
||||||
exportToCanvas,
|
|
||||||
exportToSvg,
|
|
||||||
exportToBlob,
|
|
||||||
exportToClipboard,
|
|
||||||
Excalidraw,
|
|
||||||
useHandleLibrary,
|
|
||||||
MIME_TYPES,
|
|
||||||
sceneCoordsToViewportCoords,
|
|
||||||
viewportCoordsToSceneCoords,
|
|
||||||
restoreElements,
|
|
||||||
Sidebar,
|
|
||||||
Footer,
|
|
||||||
WelcomeScreen,
|
|
||||||
MainMenu,
|
|
||||||
LiveCollaborationTrigger,
|
|
||||||
} = window.ExcalidrawLib;
|
|
||||||
|
|
||||||
const COMMENT_ICON_DIMENSION = 32;
|
const COMMENT_ICON_DIMENSION = 32;
|
||||||
const COMMENT_INPUT_HEIGHT = 50;
|
const COMMENT_INPUT_HEIGHT = 50;
|
||||||
@ -84,9 +69,38 @@ export interface AppProps {
|
|||||||
appTitle: string;
|
appTitle: string;
|
||||||
useCustom: (api: ExcalidrawImperativeAPI | null, customArgs?: any[]) => void;
|
useCustom: (api: ExcalidrawImperativeAPI | null, customArgs?: any[]) => void;
|
||||||
customArgs?: any[];
|
customArgs?: any[];
|
||||||
|
children: React.ReactNode;
|
||||||
|
excalidrawLib: typeof TExcalidraw;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
export default function App({
|
||||||
|
appTitle,
|
||||||
|
useCustom,
|
||||||
|
customArgs,
|
||||||
|
children,
|
||||||
|
excalidrawLib,
|
||||||
|
}: AppProps) {
|
||||||
|
const {
|
||||||
|
exportToCanvas,
|
||||||
|
exportToSvg,
|
||||||
|
exportToBlob,
|
||||||
|
exportToClipboard,
|
||||||
|
useHandleLibrary,
|
||||||
|
MIME_TYPES,
|
||||||
|
sceneCoordsToViewportCoords,
|
||||||
|
viewportCoordsToSceneCoords,
|
||||||
|
restoreElements,
|
||||||
|
Sidebar,
|
||||||
|
Footer,
|
||||||
|
WelcomeScreen,
|
||||||
|
MainMenu,
|
||||||
|
LiveCollaborationTrigger,
|
||||||
|
convertToExcalidrawElements,
|
||||||
|
TTDDialog,
|
||||||
|
TTDDialogTrigger,
|
||||||
|
ROUNDNESS,
|
||||||
|
loadSceneOrLibraryFromBlob,
|
||||||
|
} = excalidrawLib;
|
||||||
const appRef = useRef<any>(null);
|
const appRef = useRef<any>(null);
|
||||||
const [viewModeEnabled, setViewModeEnabled] = useState(false);
|
const [viewModeEnabled, setViewModeEnabled] = useState(false);
|
||||||
const [zenModeEnabled, setZenModeEnabled] = useState(false);
|
const [zenModeEnabled, setZenModeEnabled] = useState(false);
|
||||||
@ -95,7 +109,8 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
|||||||
const [canvasUrl, setCanvasUrl] = useState<string>("");
|
const [canvasUrl, setCanvasUrl] = useState<string>("");
|
||||||
const [exportWithDarkMode, setExportWithDarkMode] = useState(false);
|
const [exportWithDarkMode, setExportWithDarkMode] = useState(false);
|
||||||
const [exportEmbedScene, setExportEmbedScene] = useState(false);
|
const [exportEmbedScene, setExportEmbedScene] = useState(false);
|
||||||
const [theme, setTheme] = useState("light");
|
const [theme, setTheme] = useState<Theme>("light");
|
||||||
|
const [disableImageTool, setDisableImageTool] = useState(false);
|
||||||
const [isCollaborating, setIsCollaborating] = useState(false);
|
const [isCollaborating, setIsCollaborating] = useState(false);
|
||||||
const [commentIcons, setCommentIcons] = useState<{ [id: string]: Comment }>(
|
const [commentIcons, setCommentIcons] = useState<{ [id: string]: Comment }>(
|
||||||
{},
|
{},
|
||||||
@ -139,13 +154,113 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
|||||||
];
|
];
|
||||||
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
initialStatePromiseRef.current.promise.resolve(initialData);
|
initialStatePromiseRef.current.promise.resolve({
|
||||||
|
...initialData,
|
||||||
|
elements: convertToExcalidrawElements(initialData.elements),
|
||||||
|
});
|
||||||
excalidrawAPI.addFiles(imagesArray);
|
excalidrawAPI.addFiles(imagesArray);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
fetchData();
|
fetchData();
|
||||||
}, [excalidrawAPI]);
|
}, [excalidrawAPI, convertToExcalidrawElements, MIME_TYPES]);
|
||||||
|
|
||||||
|
const renderExcalidraw = (children: React.ReactNode) => {
|
||||||
|
const Excalidraw: any = Children.toArray(children).find(
|
||||||
|
(child) =>
|
||||||
|
React.isValidElement(child) &&
|
||||||
|
typeof child.type !== "string" &&
|
||||||
|
//@ts-ignore
|
||||||
|
child.type.displayName === "Excalidraw",
|
||||||
|
);
|
||||||
|
if (!Excalidraw) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const newElement = cloneElement(
|
||||||
|
Excalidraw,
|
||||||
|
{
|
||||||
|
excalidrawAPI: (api: ExcalidrawImperativeAPI) => setExcalidrawAPI(api),
|
||||||
|
initialData: initialStatePromiseRef.current.promise,
|
||||||
|
onChange: (
|
||||||
|
elements: NonDeletedExcalidrawElement[],
|
||||||
|
state: AppState,
|
||||||
|
) => {
|
||||||
|
console.info("Elements :", elements, "State : ", state);
|
||||||
|
},
|
||||||
|
onPointerUpdate: (payload: {
|
||||||
|
pointer: { x: number; y: number };
|
||||||
|
button: "down" | "up";
|
||||||
|
pointersMap: Gesture["pointers"];
|
||||||
|
}) => setPointerData(payload),
|
||||||
|
viewModeEnabled,
|
||||||
|
zenModeEnabled,
|
||||||
|
gridModeEnabled,
|
||||||
|
theme,
|
||||||
|
name: "Custom name of drawing",
|
||||||
|
UIOptions: {
|
||||||
|
canvasActions: {
|
||||||
|
loadScene: false,
|
||||||
|
},
|
||||||
|
tools: { image: !disableImageTool },
|
||||||
|
},
|
||||||
|
renderTopRightUI,
|
||||||
|
onLinkOpen,
|
||||||
|
onPointerDown,
|
||||||
|
onScrollChange: rerenderCommentIcons,
|
||||||
|
validateEmbeddable: true,
|
||||||
|
},
|
||||||
|
<>
|
||||||
|
{excalidrawAPI && (
|
||||||
|
<Footer>
|
||||||
|
<CustomFooter
|
||||||
|
excalidrawAPI={excalidrawAPI}
|
||||||
|
excalidrawLib={excalidrawLib}
|
||||||
|
/>
|
||||||
|
</Footer>
|
||||||
|
)}
|
||||||
|
<WelcomeScreen />
|
||||||
|
<Sidebar name="custom">
|
||||||
|
<Sidebar.Tabs>
|
||||||
|
<Sidebar.Header />
|
||||||
|
<Sidebar.Tab tab="one">Tab one!</Sidebar.Tab>
|
||||||
|
<Sidebar.Tab tab="two">Tab two!</Sidebar.Tab>
|
||||||
|
<Sidebar.TabTriggers>
|
||||||
|
<Sidebar.TabTrigger tab="one">One</Sidebar.TabTrigger>
|
||||||
|
<Sidebar.TabTrigger tab="two">Two</Sidebar.TabTrigger>
|
||||||
|
</Sidebar.TabTriggers>
|
||||||
|
</Sidebar.Tabs>
|
||||||
|
</Sidebar>
|
||||||
|
<Sidebar.Trigger
|
||||||
|
name="custom"
|
||||||
|
tab="one"
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
left: "50%",
|
||||||
|
transform: "translateX(-50%)",
|
||||||
|
bottom: "20px",
|
||||||
|
zIndex: 9999999999999999,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Toggle Custom Sidebar
|
||||||
|
</Sidebar.Trigger>
|
||||||
|
{renderMenu()}
|
||||||
|
{excalidrawAPI && (
|
||||||
|
<TTDDialogTrigger icon={<span>😀</span>}>
|
||||||
|
Text to diagram
|
||||||
|
</TTDDialogTrigger>
|
||||||
|
)}
|
||||||
|
<TTDDialog
|
||||||
|
onTextSubmit={async (_) => {
|
||||||
|
console.info("submit");
|
||||||
|
// sleep for 2s
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||||
|
throw new Error("error, go away now");
|
||||||
|
// return "dummy";
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>,
|
||||||
|
);
|
||||||
|
return newElement;
|
||||||
|
};
|
||||||
const renderTopRightUI = (isMobile: boolean) => {
|
const renderTopRightUI = (isMobile: boolean) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -161,8 +276,7 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
|||||||
onClick={() => alert("This is an empty top right UI")}
|
onClick={() => alert("This is an empty top right UI")}
|
||||||
style={{ height: "2.5rem" }}
|
style={{ height: "2.5rem" }}
|
||||||
>
|
>
|
||||||
{" "}
|
Click me
|
||||||
Click me{" "}
|
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -184,37 +298,40 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
|||||||
const updateScene = () => {
|
const updateScene = () => {
|
||||||
const sceneData = {
|
const sceneData = {
|
||||||
elements: restoreElements(
|
elements: restoreElements(
|
||||||
[
|
convertToExcalidrawElements([
|
||||||
{
|
{
|
||||||
type: "rectangle",
|
type: "rectangle",
|
||||||
version: 141,
|
id: "rect-1",
|
||||||
versionNonce: 361174001,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "oDVXy8D6rom3H1-LLH2-f",
|
|
||||||
fillStyle: "hachure",
|
fillStyle: "hachure",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
roughness: 1,
|
roughness: 1,
|
||||||
opacity: 100,
|
|
||||||
angle: 0,
|
angle: 0,
|
||||||
x: 100.50390625,
|
x: 100.50390625,
|
||||||
y: 93.67578125,
|
y: 93.67578125,
|
||||||
strokeColor: "#c92a2a",
|
strokeColor: "#c92a2a",
|
||||||
backgroundColor: "transparent",
|
|
||||||
width: 186.47265625,
|
width: 186.47265625,
|
||||||
height: 141.9765625,
|
height: 141.9765625,
|
||||||
seed: 1968410350,
|
seed: 1968410350,
|
||||||
groupIds: [],
|
|
||||||
boundElements: null,
|
|
||||||
locked: false,
|
|
||||||
link: null,
|
|
||||||
updated: 1,
|
|
||||||
roundness: {
|
roundness: {
|
||||||
type: ROUNDNESS.ADAPTIVE_RADIUS,
|
type: ROUNDNESS.ADAPTIVE_RADIUS,
|
||||||
value: 32,
|
value: 32,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
{
|
||||||
|
type: "arrow",
|
||||||
|
x: 300,
|
||||||
|
y: 150,
|
||||||
|
start: { id: "rect-1" },
|
||||||
|
end: { type: "ellipse" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
x: 300,
|
||||||
|
y: 100,
|
||||||
|
text: "HELLO WORLD!",
|
||||||
|
},
|
||||||
|
]),
|
||||||
null,
|
null,
|
||||||
),
|
),
|
||||||
appState: {
|
appState: {
|
||||||
@ -327,8 +444,8 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
|||||||
pointerDownState: PointerDownState,
|
pointerDownState: PointerDownState,
|
||||||
) => {
|
) => {
|
||||||
return withBatchedUpdates((event) => {
|
return withBatchedUpdates((event) => {
|
||||||
window.removeEventListener(EVENT.POINTER_MOVE, pointerDownState.onMove);
|
window.removeEventListener("pointermove", pointerDownState.onMove);
|
||||||
window.removeEventListener(EVENT.POINTER_UP, pointerDownState.onUp);
|
window.removeEventListener("pointerup", pointerDownState.onUp);
|
||||||
excalidrawAPI?.setActiveTool({ type: "selection" });
|
excalidrawAPI?.setActiveTool({ type: "selection" });
|
||||||
const distance = distance2d(
|
const distance = distance2d(
|
||||||
pointerDownState.x,
|
pointerDownState.x,
|
||||||
@ -392,8 +509,8 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
|||||||
onPointerMoveFromPointerDownHandler(pointerDownState);
|
onPointerMoveFromPointerDownHandler(pointerDownState);
|
||||||
const onPointerUp =
|
const onPointerUp =
|
||||||
onPointerUpFromPointerDownHandler(pointerDownState);
|
onPointerUpFromPointerDownHandler(pointerDownState);
|
||||||
window.addEventListener(EVENT.POINTER_MOVE, onPointerMove);
|
window.addEventListener("pointermove", onPointerMove);
|
||||||
window.addEventListener(EVENT.POINTER_UP, onPointerUp);
|
window.addEventListener("pointerup", onPointerUp);
|
||||||
|
|
||||||
pointerDownState.onMove = onPointerMove;
|
pointerDownState.onMove = onPointerMove;
|
||||||
pointerDownState.onUp = onPointerUp;
|
pointerDownState.onUp = onPointerUp;
|
||||||
@ -494,15 +611,6 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderSidebar = () => {
|
|
||||||
return (
|
|
||||||
<Sidebar>
|
|
||||||
<Sidebar.Header>Custom header!</Sidebar.Header>
|
|
||||||
Custom sidebar!
|
|
||||||
</Sidebar>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderMenu = () => {
|
const renderMenu = () => {
|
||||||
return (
|
return (
|
||||||
<MainMenu>
|
<MainMenu>
|
||||||
@ -527,13 +635,20 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
|||||||
</MainMenu.ItemCustom>
|
</MainMenu.ItemCustom>
|
||||||
<MainMenu.DefaultItems.Help />
|
<MainMenu.DefaultItems.Help />
|
||||||
|
|
||||||
{excalidrawAPI && <MobileFooter excalidrawAPI={excalidrawAPI} />}
|
{excalidrawAPI && (
|
||||||
|
<MobileFooter
|
||||||
|
excalidrawLib={excalidrawLib}
|
||||||
|
excalidrawAPI={excalidrawAPI}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</MainMenu>
|
</MainMenu>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="App" ref={appRef}>
|
<div className="App" ref={appRef}>
|
||||||
<h1>{appTitle}</h1>
|
<h1>{appTitle}</h1>
|
||||||
|
{/* TODO fix type */}
|
||||||
<ExampleSidebar>
|
<ExampleSidebar>
|
||||||
<div className="button-wrapper">
|
<div className="button-wrapper">
|
||||||
<button onClick={loadSceneOrLibrary}>Load Scene or Library</button>
|
<button onClick={loadSceneOrLibrary}>Load Scene or Library</button>
|
||||||
@ -601,15 +716,21 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={theme === "dark"}
|
checked={theme === "dark"}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
let newTheme = "light";
|
setTheme(theme === "light" ? "dark" : "light");
|
||||||
if (theme === "light") {
|
|
||||||
newTheme = "dark";
|
|
||||||
}
|
|
||||||
setTheme(newTheme);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
Switch to Dark Theme
|
Switch to Dark Theme
|
||||||
</label>
|
</label>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={disableImageTool === true}
|
||||||
|
onChange={() => {
|
||||||
|
setDisableImageTool(!disableImageTool);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
Disable Image Tool
|
||||||
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@ -668,54 +789,7 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="excalidraw-wrapper">
|
<div className="excalidraw-wrapper">
|
||||||
<div
|
{renderExcalidraw(children)}
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
left: "50%",
|
|
||||||
bottom: "20px",
|
|
||||||
display: "flex",
|
|
||||||
zIndex: 9999999999999999,
|
|
||||||
padding: "5px 10px",
|
|
||||||
transform: "translateX(-50%)",
|
|
||||||
background: "rgba(255, 255, 255, 0.8)",
|
|
||||||
gap: "1rem",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<button onClick={() => excalidrawAPI?.toggleMenu("customSidebar")}>
|
|
||||||
Toggle Custom Sidebar
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<Excalidraw
|
|
||||||
ref={(api: ExcalidrawImperativeAPI) => setExcalidrawAPI(api)}
|
|
||||||
initialData={initialStatePromiseRef.current.promise}
|
|
||||||
onChange={(elements, state) => {
|
|
||||||
console.info("Elements :", elements, "State : ", state);
|
|
||||||
}}
|
|
||||||
onPointerUpdate={(payload: {
|
|
||||||
pointer: { x: number; y: number };
|
|
||||||
button: "down" | "up";
|
|
||||||
pointersMap: Gesture["pointers"];
|
|
||||||
}) => setPointerData(payload)}
|
|
||||||
viewModeEnabled={viewModeEnabled}
|
|
||||||
zenModeEnabled={zenModeEnabled}
|
|
||||||
gridModeEnabled={gridModeEnabled}
|
|
||||||
theme={theme}
|
|
||||||
name="Custom name of drawing"
|
|
||||||
UIOptions={{ canvasActions: { loadScene: false } }}
|
|
||||||
renderTopRightUI={renderTopRightUI}
|
|
||||||
onLinkOpen={onLinkOpen}
|
|
||||||
onPointerDown={onPointerDown}
|
|
||||||
onScrollChange={rerenderCommentIcons}
|
|
||||||
renderSidebar={renderSidebar}
|
|
||||||
>
|
|
||||||
{excalidrawAPI && (
|
|
||||||
<Footer>
|
|
||||||
<CustomFooter excalidrawAPI={excalidrawAPI} />
|
|
||||||
</Footer>
|
|
||||||
)}
|
|
||||||
<WelcomeScreen />
|
|
||||||
{renderMenu()}
|
|
||||||
</Excalidraw>
|
|
||||||
{Object.keys(commentIcons || []).length > 0 && renderCommentIcons()}
|
{Object.keys(commentIcons || []).length > 0 && renderCommentIcons()}
|
||||||
{comment && renderComment()}
|
{comment && renderComment()}
|
||||||
</div>
|
</div>
|
||||||
@ -784,7 +858,6 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
|||||||
<div className="export export-blob">
|
<div className="export export-blob">
|
||||||
<img src={blobUrl} alt="" />
|
<img src={blobUrl} alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (!excalidrawAPI) {
|
if (!excalidrawAPI) {
|
||||||
@ -806,6 +879,78 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
|||||||
>
|
>
|
||||||
Export to Canvas
|
Export to Canvas
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={async () => {
|
||||||
|
if (!excalidrawAPI) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const canvas = await exportToCanvas({
|
||||||
|
elements: excalidrawAPI.getSceneElements(),
|
||||||
|
appState: {
|
||||||
|
...initialData.appState,
|
||||||
|
exportWithDarkMode,
|
||||||
|
},
|
||||||
|
files: excalidrawAPI.getFiles(),
|
||||||
|
});
|
||||||
|
const ctx = canvas.getContext("2d")!;
|
||||||
|
ctx.font = "30px Virgil";
|
||||||
|
ctx.strokeText("My custom text", 50, 60);
|
||||||
|
setCanvasUrl(canvas.toDataURL());
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Export to Canvas
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
if (!excalidrawAPI) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const elements = excalidrawAPI.getSceneElements();
|
||||||
|
excalidrawAPI.scrollToContent(elements[0], {
|
||||||
|
fitToViewport: true,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Fit to viewport, first element
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
if (!excalidrawAPI) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const elements = excalidrawAPI.getSceneElements();
|
||||||
|
excalidrawAPI.scrollToContent(elements[0], {
|
||||||
|
fitToContent: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
excalidrawAPI.scrollToContent(elements[0], {
|
||||||
|
fitToContent: true,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Fit to content, first element
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
if (!excalidrawAPI) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const elements = excalidrawAPI.getSceneElements();
|
||||||
|
excalidrawAPI.scrollToContent(elements[0], {
|
||||||
|
fitToContent: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
excalidrawAPI.scrollToContent(elements[0]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Scroll to first element, no fitToContent, no fitToViewport
|
||||||
|
</button>
|
||||||
<div className="export export-canvas">
|
<div className="export export-canvas">
|
||||||
<img src={canvasUrl} alt="" />
|
<img src={canvasUrl} alt="" />
|
||||||
</div>
|
</div>
|
@ -1,6 +1,5 @@
|
|||||||
import { ExcalidrawImperativeAPI } from "../../../types";
|
import type * as TExcalidraw from "@excalidraw/excalidraw";
|
||||||
import { MIME_TYPES } from "../entry";
|
import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/dist/excalidraw/types";
|
||||||
import { Button } from "../../../components/Button";
|
|
||||||
|
|
||||||
const COMMENT_SVG = (
|
const COMMENT_SVG = (
|
||||||
<svg
|
<svg
|
||||||
@ -18,24 +17,28 @@ const COMMENT_SVG = (
|
|||||||
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
|
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
const CustomFooter = ({
|
const CustomFooter = ({
|
||||||
excalidrawAPI,
|
excalidrawAPI,
|
||||||
|
excalidrawLib,
|
||||||
}: {
|
}: {
|
||||||
excalidrawAPI: ExcalidrawImperativeAPI;
|
excalidrawAPI: ExcalidrawImperativeAPI;
|
||||||
|
excalidrawLib: typeof TExcalidraw;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { Button, MIME_TYPES } = excalidrawLib;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
onSelect={() => alert("General Kenobi!")}
|
onSelect={() => alert("General Kenobi!")}
|
||||||
className="you are a bold one"
|
style={{ marginLeft: "1rem", width: "auto" }}
|
||||||
style={{ marginLeft: "1rem" }}
|
|
||||||
title="Hello there!"
|
title="Hello there!"
|
||||||
>
|
>
|
||||||
{COMMENT_SVG}
|
Hit me
|
||||||
</Button>
|
</Button>
|
||||||
<button
|
<Button
|
||||||
className="custom-element"
|
className="custom-element"
|
||||||
onClick={() => {
|
onSelect={() => {
|
||||||
excalidrawAPI?.setActiveTool({
|
excalidrawAPI?.setActiveTool({
|
||||||
type: "custom",
|
type: "custom",
|
||||||
customType: "comment",
|
customType: "comment",
|
||||||
@ -58,16 +61,10 @@ const CustomFooter = ({
|
|||||||
)}`;
|
)}`;
|
||||||
excalidrawAPI?.setCursor(`url(${url}), auto`);
|
excalidrawAPI?.setCursor(`url(${url}), auto`);
|
||||||
}}
|
}}
|
||||||
|
title="Comments!"
|
||||||
>
|
>
|
||||||
{COMMENT_SVG}
|
{COMMENT_SVG}
|
||||||
</button>
|
</Button>
|
||||||
<button
|
|
||||||
className="custom-footer"
|
|
||||||
onClick={() => alert("This is dummy footer")}
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
custom footer{" "}
|
|
||||||
</button>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
27
examples/excalidraw/components/MobileFooter.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/dist/excalidraw/types";
|
||||||
|
import CustomFooter from "./CustomFooter";
|
||||||
|
import type * as TExcalidraw from "@excalidraw/excalidraw";
|
||||||
|
|
||||||
|
const MobileFooter = ({
|
||||||
|
excalidrawAPI,
|
||||||
|
excalidrawLib,
|
||||||
|
}: {
|
||||||
|
excalidrawAPI: ExcalidrawImperativeAPI;
|
||||||
|
excalidrawLib: typeof TExcalidraw;
|
||||||
|
}) => {
|
||||||
|
const { useDevice, Footer } = excalidrawLib;
|
||||||
|
|
||||||
|
const device = useDevice();
|
||||||
|
if (device.editor.isMobile) {
|
||||||
|
return (
|
||||||
|
<Footer>
|
||||||
|
<CustomFooter
|
||||||
|
excalidrawAPI={excalidrawAPI}
|
||||||
|
excalidrawLib={excalidrawLib}
|
||||||
|
/>
|
||||||
|
</Footer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
export default MobileFooter;
|
@ -1,5 +1,6 @@
|
|||||||
import React, { useState } from "react";
|
import { useState } from "react";
|
||||||
import "./ExampleSidebar.scss";
|
import "./ExampleSidebar.scss";
|
||||||
|
|
||||||
export default function Sidebar({ children }: { children: React.ReactNode }) {
|
export default function Sidebar({ children }: { children: React.ReactNode }) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ export default function Sidebar({ children }: { children: React.ReactNode }) {
|
|||||||
</button>
|
</button>
|
||||||
<div className="sidebar-links">
|
<div className="sidebar-links">
|
||||||
<button>Empty Home</button>
|
<button>Empty Home</button>
|
||||||
<button>Empty About</button>{" "}
|
<button>Empty About</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={`${open ? "sidebar-open" : ""}`}>
|
<div className={`${open ? "sidebar-open" : ""}`}>
|
@ -1,103 +1,65 @@
|
|||||||
|
import type { ExcalidrawElementSkeleton } from "@excalidraw/excalidraw/data/transform";
|
||||||
|
import type { FileId } from "@excalidraw/excalidraw/element/types";
|
||||||
|
|
||||||
|
const elements: ExcalidrawElementSkeleton[] = [
|
||||||
|
{
|
||||||
|
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: "arrow",
|
||||||
|
x: 100,
|
||||||
|
y: 200,
|
||||||
|
label: { text: "HELLO WORLD!!" },
|
||||||
|
start: { type: "rectangle" },
|
||||||
|
end: { type: "ellipse" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "image",
|
||||||
|
x: 606.1042326312408,
|
||||||
|
y: 153.57729779411773,
|
||||||
|
width: 230,
|
||||||
|
height: 230,
|
||||||
|
fileId: "rocket" as FileId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "frame",
|
||||||
|
children: ["1", "2"],
|
||||||
|
name: "My frame",
|
||||||
|
},
|
||||||
|
];
|
||||||
export default {
|
export default {
|
||||||
elements: [
|
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: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "-xMIs_0jIFqvpx-R9UnaG",
|
|
||||||
type: "ellipse",
|
|
||||||
x: 300.5703125,
|
|
||||||
y: 190.69140625,
|
|
||||||
width: 198.21875,
|
|
||||||
height: 129.51171875,
|
|
||||||
angle: 0,
|
|
||||||
strokeColor: "#000000",
|
|
||||||
backgroundColor: "transparent",
|
|
||||||
fillStyle: "hachure",
|
|
||||||
strokeWidth: 1,
|
|
||||||
strokeStyle: "solid",
|
|
||||||
roughness: 1,
|
|
||||||
opacity: 100,
|
|
||||||
groupIds: [],
|
|
||||||
seed: 957947807,
|
|
||||||
version: 47,
|
|
||||||
versionNonce: 1128618623,
|
|
||||||
isDeleted: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fileId: "rocket",
|
|
||||||
type: "image",
|
|
||||||
x: 606.1042326312408,
|
|
||||||
y: 153.57729779411773,
|
|
||||||
width: 231.30325348751828,
|
|
||||||
height: 231.64340533088227,
|
|
||||||
angle: 0,
|
|
||||||
strokeColor: "transparent",
|
|
||||||
backgroundColor: "transparent",
|
|
||||||
fillStyle: "hachure",
|
|
||||||
strokeWidth: 1,
|
|
||||||
strokeStyle: "solid",
|
|
||||||
roughness: 1,
|
|
||||||
opacity: 100,
|
|
||||||
groupIds: [],
|
|
||||||
strokeSharpness: "round",
|
|
||||||
seed: 707269846,
|
|
||||||
version: 143,
|
|
||||||
versionNonce: 2028982666,
|
|
||||||
isDeleted: false,
|
|
||||||
boundElements: null,
|
|
||||||
updated: 1644914782403,
|
|
||||||
link: null,
|
|
||||||
status: "pending",
|
|
||||||
scale: [1, 1],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
appState: { viewBackgroundColor: "#AFEEEE", currentItemFontFamily: 1 },
|
appState: { viewBackgroundColor: "#AFEEEE", currentItemFontFamily: 1 },
|
||||||
scrollToContent: true,
|
scrollToContent: true,
|
||||||
libraryItems: [
|
libraryItems: [
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
version: 1699,
|
|
||||||
versionNonce: 1813275999,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "1OMHrnYMU3LJ3w3IaXU_R",
|
|
||||||
fillStyle: "hachure",
|
|
||||||
strokeWidth: 1,
|
|
||||||
strokeStyle: "solid",
|
|
||||||
roughness: 1,
|
|
||||||
opacity: 100,
|
|
||||||
angle: 0,
|
|
||||||
x: 209.72304760646858,
|
x: 209.72304760646858,
|
||||||
y: 338.83587294718825,
|
y: 338.83587294718825,
|
||||||
strokeColor: "#881fa3",
|
strokeColor: "#881fa3",
|
||||||
backgroundColor: "#be4bdb",
|
backgroundColor: "#be4bdb",
|
||||||
width: 116.42036295658873,
|
width: 116.42036295658873,
|
||||||
height: 103.65107323746608,
|
height: 103.65107323746608,
|
||||||
seed: 1445523839,
|
|
||||||
groupIds: [],
|
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
startBinding: null,
|
|
||||||
endBinding: null,
|
|
||||||
points: [
|
points: [
|
||||||
[-92.28090097254909, 7.105427357601002e-15],
|
[-92.28090097254909, 7.105427357601002e-15],
|
||||||
[-154.72281841151394, 19.199290805487394],
|
[-154.72281841151394, 19.199290805487394],
|
||||||
@ -107,36 +69,21 @@ export default {
|
|||||||
[-39.037226329125524, 21.285677238400705],
|
[-39.037226329125524, 21.285677238400705],
|
||||||
[-92.28090097254909, 7.105427357601002e-15],
|
[-92.28090097254909, 7.105427357601002e-15],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
version: 3901,
|
|
||||||
versionNonce: 540959103,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "b-rwW8s76ztV_uTu1SHq1",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
roughness: 1,
|
|
||||||
opacity: 100,
|
|
||||||
angle: 0,
|
|
||||||
x: -249.48446738689245,
|
x: -249.48446738689245,
|
||||||
y: 374.851387389359,
|
y: 374.851387389359,
|
||||||
strokeColor: "#0a11d3",
|
strokeColor: "#0a11d3",
|
||||||
backgroundColor: "#228be6",
|
backgroundColor: "#228be6",
|
||||||
width: 88.21658171083376,
|
width: 88.21658171083376,
|
||||||
height: 113.8575037534261,
|
height: 113.8575037534261,
|
||||||
seed: 1513238033,
|
|
||||||
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
||||||
strokeSharpness: "round",
|
|
||||||
boundElementIds: [],
|
|
||||||
startBinding: null,
|
|
||||||
endBinding: null,
|
|
||||||
points: [
|
points: [
|
||||||
[-0.22814350714115691, -43.414939319563715],
|
[-0.22814350714115691, -43.414939319563715],
|
||||||
[0.06274947619197979, 42.63794490105306],
|
[0.06274947619197979, 42.63794490105306],
|
||||||
@ -158,16 +105,9 @@ export default {
|
|||||||
[-0.2758413461535838, -43.46664538034193],
|
[-0.2758413461535838, -43.46664538034193],
|
||||||
[-0.22814350714115691, -43.414939319563715],
|
[-0.22814350714115691, -43.414939319563715],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
version: 1635,
|
|
||||||
versionNonce: 1383184881,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "3CMZYj34FwjhgPB7jUC3f",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -183,9 +123,7 @@ export default {
|
|||||||
seed: 683951089,
|
seed: 683951089,
|
||||||
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
startBinding: null,
|
|
||||||
endBinding: null,
|
|
||||||
points: [
|
points: [
|
||||||
[0, -2.1538602707609424],
|
[0, -2.1538602707609424],
|
||||||
[2.326538897826852, 1.751753055375216],
|
[2.326538897826852, 1.751753055375216],
|
||||||
@ -196,16 +134,9 @@ export default {
|
|||||||
[85.2899738827162, 1.3342483900732343],
|
[85.2899738827162, 1.3342483900732343],
|
||||||
[88.30808627974527, -2.6041666666666288],
|
[88.30808627974527, -2.6041666666666288],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
version: 1722,
|
|
||||||
versionNonce: 303290783,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "DX3fUhBWtlJwYyrBDhebG",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -221,9 +152,7 @@ export default {
|
|||||||
seed: 1817746897,
|
seed: 1817746897,
|
||||||
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
startBinding: null,
|
|
||||||
endBinding: null,
|
|
||||||
points: [
|
points: [
|
||||||
[0, -2.1538602707609424],
|
[0, -2.1538602707609424],
|
||||||
[2.326538897826852, 1.751753055375216],
|
[2.326538897826852, 1.751753055375216],
|
||||||
@ -234,16 +163,9 @@ export default {
|
|||||||
[85.2899738827162, 1.3342483900732343],
|
[85.2899738827162, 1.3342483900732343],
|
||||||
[88.30808627974527, -2.6041666666666288],
|
[88.30808627974527, -2.6041666666666288],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ellipse",
|
type: "ellipse",
|
||||||
version: 4738,
|
|
||||||
versionNonce: 753357777,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "a-Snvp2FgqDYqSLylF44S",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -263,10 +185,6 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ellipse",
|
type: "ellipse",
|
||||||
version: 109,
|
|
||||||
versionNonce: 1992641983,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "7-6c-JFuB2yGoNQRgb2WM",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -282,14 +200,9 @@ export default {
|
|||||||
seed: 1073094033,
|
seed: 1073094033,
|
||||||
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ellipse",
|
type: "ellipse",
|
||||||
version: 158,
|
|
||||||
versionNonce: 1028567473,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "150XitJtlKDhTPRCyzv56",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -305,14 +218,9 @@ export default {
|
|||||||
seed: 526271345,
|
seed: 526271345,
|
||||||
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ellipse",
|
type: "ellipse",
|
||||||
version: 212,
|
|
||||||
versionNonce: 158547423,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "cmwAR3NBl1VqvSorrQN2W",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -328,16 +236,11 @@ export default {
|
|||||||
seed: 243707217,
|
seed: 243707217,
|
||||||
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
type: "diamond",
|
type: "diamond",
|
||||||
version: 659,
|
|
||||||
versionNonce: 1294871039,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "aDDArXRjZugwyEawdhCeZ",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -353,14 +256,9 @@ export default {
|
|||||||
seed: 511870335,
|
seed: 511870335,
|
||||||
groupIds: ["M6ByXuSmtHCr3RtPPKJQh"],
|
groupIds: ["M6ByXuSmtHCr3RtPPKJQh"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "diamond",
|
type: "diamond",
|
||||||
version: 700,
|
|
||||||
versionNonce: 60864881,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "Hzx8zkeyDs3YicO2Tdv6G",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -376,14 +274,9 @@ export default {
|
|||||||
seed: 1283079231,
|
seed: 1283079231,
|
||||||
groupIds: ["M6ByXuSmtHCr3RtPPKJQh"],
|
groupIds: ["M6ByXuSmtHCr3RtPPKJQh"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "diamond",
|
type: "diamond",
|
||||||
version: 780,
|
|
||||||
versionNonce: 251040287,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "PNzYhT295VNCT5EXmqvmw",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -399,14 +292,9 @@ export default {
|
|||||||
seed: 996251633,
|
seed: 996251633,
|
||||||
groupIds: ["M6ByXuSmtHCr3RtPPKJQh"],
|
groupIds: ["M6ByXuSmtHCr3RtPPKJQh"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "diamond",
|
type: "diamond",
|
||||||
version: 822,
|
|
||||||
versionNonce: 1862951761,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "jiMMAhQF3__7bF-obgXc0",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -422,16 +310,11 @@ export default {
|
|||||||
seed: 1764842481,
|
seed: 1764842481,
|
||||||
groupIds: ["M6ByXuSmtHCr3RtPPKJQh"],
|
groupIds: ["M6ByXuSmtHCr3RtPPKJQh"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
version: 4766,
|
|
||||||
versionNonce: 2003030321,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "BXfdLRoPYZ9MIumzzoA9-",
|
|
||||||
fillStyle: "hachure",
|
fillStyle: "hachure",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -447,9 +330,7 @@ export default {
|
|||||||
seed: 1424381745,
|
seed: 1424381745,
|
||||||
groupIds: ["HSrtfEf-CssQTf160Fb6R"],
|
groupIds: ["HSrtfEf-CssQTf160Fb6R"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
startBinding: null,
|
|
||||||
endBinding: null,
|
|
||||||
points: [
|
points: [
|
||||||
[-0.24755378372925183, -40.169554027464216],
|
[-0.24755378372925183, -40.169554027464216],
|
||||||
[-0.07503751055611152, 76.6515171914404],
|
[-0.07503751055611152, 76.6515171914404],
|
||||||
@ -471,9 +352,6 @@ export default {
|
|||||||
[-0.2758413461535838, -40.23974757720194],
|
[-0.2758413461535838, -40.23974757720194],
|
||||||
[-0.24755378372925183, -40.169554027464216],
|
[-0.24755378372925183, -40.169554027464216],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
@ -496,9 +374,7 @@ export default {
|
|||||||
seed: 726657713,
|
seed: 726657713,
|
||||||
groupIds: ["HSrtfEf-CssQTf160Fb6R"],
|
groupIds: ["HSrtfEf-CssQTf160Fb6R"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
startBinding: null,
|
|
||||||
endBinding: null,
|
|
||||||
points: [
|
points: [
|
||||||
[0, -2.0205717204386002],
|
[0, -2.0205717204386002],
|
||||||
[1.3361877396713384, 3.0410845646550486],
|
[1.3361877396713384, 3.0410845646550486],
|
||||||
@ -509,16 +385,9 @@ export default {
|
|||||||
[48.98410145879092, 2.500000505196364],
|
[48.98410145879092, 2.500000505196364],
|
||||||
[50.7174766392476, -2.6041666666666288],
|
[50.7174766392476, -2.6041666666666288],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
version: 2538,
|
|
||||||
versionNonce: 1913946897,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "VIuxhGjvYUBniitomEkKm",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -534,9 +403,7 @@ export default {
|
|||||||
seed: 1977326481,
|
seed: 1977326481,
|
||||||
groupIds: ["HSrtfEf-CssQTf160Fb6R"],
|
groupIds: ["HSrtfEf-CssQTf160Fb6R"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
startBinding: null,
|
|
||||||
endBinding: null,
|
|
||||||
points: [
|
points: [
|
||||||
[0, -2.136356936862347],
|
[0, -2.136356936862347],
|
||||||
[1.332367676378171, 1.9210669226078037],
|
[1.332367676378171, 1.9210669226078037],
|
||||||
@ -547,16 +414,9 @@ export default {
|
|||||||
[48.84405948536458, 1.4873339211608216],
|
[48.84405948536458, 1.4873339211608216],
|
||||||
[50.57247907260371, -2.6041666666666288],
|
[50.57247907260371, -2.6041666666666288],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ellipse",
|
type: "ellipse",
|
||||||
version: 5503,
|
|
||||||
versionNonce: 1236644479,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "1acGiqpJjntE3sr1JVnBP",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -578,10 +438,6 @@ export default {
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
type: "rectangle",
|
type: "rectangle",
|
||||||
version: 4270,
|
|
||||||
versionNonce: 309922463,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "SqGRpNqls7OV1QB2Eq-0m",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -605,10 +461,6 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "rectangle",
|
type: "rectangle",
|
||||||
version: 4319,
|
|
||||||
versionNonce: 896119505,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "fayss6b_GPh6LK1x4iX-q",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -632,10 +484,6 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "rectangle",
|
type: "rectangle",
|
||||||
version: 4417,
|
|
||||||
versionNonce: 1968987839,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "HgAnv2rwYhUpLiJiZAXv-",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -659,10 +507,6 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "draw",
|
type: "draw",
|
||||||
version: 3541,
|
|
||||||
versionNonce: 1680683185,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "12aO-Bs9HdALZN_-tuQTr",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -678,22 +522,15 @@ export default {
|
|||||||
seed: 1673003743,
|
seed: 1673003743,
|
||||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
points: [
|
points: [
|
||||||
[0, 0.6014697828497827],
|
[0, 0.6014697828497827],
|
||||||
[40.42449133807562, 0.7588628355182573],
|
[40.42449133807562, 0.7588628355182573],
|
||||||
[46.57983585730082, -2.491091008771946],
|
[46.57983585730082, -2.491091008771946],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "draw",
|
type: "draw",
|
||||||
version: 3567,
|
|
||||||
versionNonce: 620768991,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "Ck_Y0EVPh_fsY0qoRnGiD",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -709,22 +546,15 @@ export default {
|
|||||||
seed: 1821527807,
|
seed: 1821527807,
|
||||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
points: [
|
points: [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
[16.832548902953302, -2.8032978840147194],
|
[16.832548902953302, -2.8032978840147194],
|
||||||
[45.567415680676426, -0.3275477042019195],
|
[45.567415680676426, -0.3275477042019195],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "draw",
|
type: "draw",
|
||||||
version: 3592,
|
|
||||||
versionNonce: 1300624017,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "a_7IZapEuD918VW1P8Ss_",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -740,23 +570,16 @@ export default {
|
|||||||
seed: 1485707039,
|
seed: 1485707039,
|
||||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
points: [
|
points: [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
[26.41225578429045, -0.2552319773002338],
|
[26.41225578429045, -0.2552319773002338],
|
||||||
[37.62000339651456, 2.3153712935189787],
|
[37.62000339651456, 2.3153712935189787],
|
||||||
[48.33668263438425, -1.9652862252120569],
|
[48.33668263438425, -1.9652862252120569],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "draw",
|
type: "draw",
|
||||||
version: 3629,
|
|
||||||
versionNonce: 737475327,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "8io6FVNdFOLsQ266W8Lni",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -772,7 +595,7 @@ export default {
|
|||||||
seed: 1042012991,
|
seed: 1042012991,
|
||||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
points: [
|
points: [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
[10.166093050596771, -1.166642430373031],
|
[10.166093050596771, -1.166642430373031],
|
||||||
@ -780,16 +603,9 @@ export default {
|
|||||||
[46.26079588567538, 0.6125567455206506],
|
[46.26079588567538, 0.6125567455206506],
|
||||||
[54.40694982784246, -2.297087795702523],
|
[54.40694982784246, -2.297087795702523],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "draw",
|
type: "draw",
|
||||||
version: 3594,
|
|
||||||
versionNonce: 1982560369,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "LJI5kY6tg7UFAjPV3fKL-",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -805,22 +621,15 @@ export default {
|
|||||||
seed: 295443295,
|
seed: 295443295,
|
||||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
points: [
|
points: [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
[18.193786115221407, -0.5912874140789839],
|
[18.193786115221407, -0.5912874140789839],
|
||||||
[46.92865289294453, 1.884462765733816],
|
[46.92865289294453, 1.884462765733816],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "draw",
|
type: "draw",
|
||||||
version: 3609,
|
|
||||||
versionNonce: 1857766175,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "zCrZOHW-q8YWKLw6ltKxX",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -836,25 +645,18 @@ export default {
|
|||||||
seed: 1734301567,
|
seed: 1734301567,
|
||||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
points: [
|
points: [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
[8.093938105125233, 1.4279702913643746],
|
[8.093938105125233, 1.4279702913643746],
|
||||||
[18.193786115221407, -0.5912874140789839],
|
[18.193786115221407, -0.5912874140789839],
|
||||||
[46.92865289294453, 1.884462765733816],
|
[46.92865289294453, 1.884462765733816],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
type: "rectangle",
|
type: "rectangle",
|
||||||
version: 676,
|
|
||||||
versionNonce: 1841530687,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "XOD3vRhtoLWoxC9wF9Sk8",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -870,14 +672,9 @@ export default {
|
|||||||
seed: 106569279,
|
seed: 106569279,
|
||||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
version: 462,
|
|
||||||
versionNonce: 1737150513,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "WBkTga1PjKzYK-tcGjnjZ",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -893,23 +690,14 @@ export default {
|
|||||||
seed: 73916127,
|
seed: 73916127,
|
||||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
startBinding: null,
|
|
||||||
endBinding: null,
|
|
||||||
points: [
|
points: [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
[128.84193229844433, 0],
|
[128.84193229844433, 0],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ellipse",
|
type: "ellipse",
|
||||||
version: 282,
|
|
||||||
versionNonce: 1198409567,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "FHX0ZsIzUUfYPJqrZ8Lso",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -925,14 +713,9 @@ export default {
|
|||||||
seed: 387857791,
|
seed: 387857791,
|
||||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ellipse",
|
type: "ellipse",
|
||||||
version: 327,
|
|
||||||
versionNonce: 1661182481,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "ugVRR0f_uDOjrllO10yAs",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -948,14 +731,9 @@ export default {
|
|||||||
seed: 1486370207,
|
seed: 1486370207,
|
||||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ellipse",
|
type: "ellipse",
|
||||||
version: 385,
|
|
||||||
versionNonce: 2047607679,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "SBzNA0Sn-ou4QGxotj0SB",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -971,14 +749,9 @@ export default {
|
|||||||
seed: 610150847,
|
seed: 610150847,
|
||||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ellipse",
|
type: "ellipse",
|
||||||
version: 664,
|
|
||||||
versionNonce: 2135373809,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "VKcfbELTVlyJ90m0bGsj0",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -994,32 +767,20 @@ export default {
|
|||||||
seed: 144280593,
|
seed: 144280593,
|
||||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "draw",
|
type: "draw",
|
||||||
version: 1281,
|
|
||||||
versionNonce: 1708997535,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "zWrJVrKnkF5K8iXNxi9Aa",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
roughness: 0,
|
|
||||||
opacity: 100,
|
|
||||||
angle: 0,
|
|
||||||
x: -530.327851842306,
|
x: -530.327851842306,
|
||||||
y: 378.9357912947449,
|
y: 378.9357912947449,
|
||||||
strokeColor: "#087f5b",
|
strokeColor: "#087f5b",
|
||||||
backgroundColor: "#40c057",
|
backgroundColor: "#40c057",
|
||||||
width: 28.226201983883442,
|
width: 28.226201983883442,
|
||||||
height: 24.44112284281997,
|
height: 24.44112284281997,
|
||||||
seed: 29167967,
|
|
||||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
startBinding: null,
|
|
||||||
endBinding: null,
|
|
||||||
points: [
|
points: [
|
||||||
[4.907524351775825, 2.043055712211473],
|
[4.907524351775825, 2.043055712211473],
|
||||||
[3.0769604829149455, 1.6284171290602836],
|
[3.0769604829149455, 1.6284171290602836],
|
||||||
@ -1044,16 +805,9 @@ export default {
|
|||||||
[4.669824267311791, 1.1200945145694894],
|
[4.669824267311791, 1.1200945145694894],
|
||||||
[4.907524351775825, 2.043055712211473],
|
[4.907524351775825, 2.043055712211473],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
version: 701,
|
|
||||||
versionNonce: 1583157713,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "LX6kTl9A8K36ld2MEV4tI",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -1069,23 +823,14 @@ export default {
|
|||||||
seed: 1443027377,
|
seed: 1443027377,
|
||||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
startBinding: null,
|
|
||||||
endBinding: null,
|
|
||||||
points: [
|
points: [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
[42.095115772272244, 0],
|
[42.095115772272244, 0],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
version: 2908,
|
|
||||||
versionNonce: 252866495,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "SHmV_QtcwxIE-peI_QOX1",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -1098,12 +843,8 @@ export default {
|
|||||||
backgroundColor: "#99bcff",
|
backgroundColor: "#99bcff",
|
||||||
width: 29.31860660384862,
|
width: 29.31860660384862,
|
||||||
height: 5.711199931375845,
|
height: 5.711199931375845,
|
||||||
seed: 244310513,
|
|
||||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
startBinding: null,
|
|
||||||
endBinding: null,
|
|
||||||
points: [
|
points: [
|
||||||
[0, -2.341683327443203],
|
[0, -2.341683327443203],
|
||||||
[0.7724193963150375, -0.06510358900749044],
|
[0.7724193963150375, -0.06510358900749044],
|
||||||
@ -1114,16 +855,9 @@ export default {
|
|||||||
[28.316582284417855, -0.3084668090492442],
|
[28.316582284417855, -0.3084668090492442],
|
||||||
[29.31860660384862, -2.6041666666666288],
|
[29.31860660384862, -2.6041666666666288],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ellipse",
|
type: "ellipse",
|
||||||
version: 725,
|
|
||||||
versionNonce: 1969008561,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "PKRg6SqIetkWIgRqBAnDY",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -1139,20 +873,13 @@ export default {
|
|||||||
seed: 683572113,
|
seed: 683572113,
|
||||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
version: 3113,
|
|
||||||
versionNonce: 533471199,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "HrelUAgvfxi_4v8MyL_iT",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
roughness: 0,
|
|
||||||
opacity: 90,
|
opacity: 90,
|
||||||
angle: 0,
|
|
||||||
x: -544.828148539078,
|
x: -544.828148539078,
|
||||||
y: 402.0199316371545,
|
y: 402.0199316371545,
|
||||||
strokeColor: "#000000",
|
strokeColor: "#000000",
|
||||||
@ -1162,9 +889,7 @@ export default {
|
|||||||
seed: 318798801,
|
seed: 318798801,
|
||||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||||
strokeSharpness: "round",
|
strokeSharpness: "round",
|
||||||
boundElementIds: [],
|
|
||||||
startBinding: null,
|
|
||||||
endBinding: null,
|
|
||||||
points: [
|
points: [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
[4.103544916365185, -4.322122351104391],
|
[4.103544916365185, -4.322122351104391],
|
||||||
@ -1174,18 +899,11 @@ export default {
|
|||||||
[28.316582284417855, -2.0990281379671547],
|
[28.316582284417855, -2.0990281379671547],
|
||||||
[29.31860660384862, 0.2709794602754383],
|
[29.31860660384862, 0.2709794602754383],
|
||||||
],
|
],
|
||||||
lastCommittedPoint: null,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: null,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
type: "rectangle",
|
type: "rectangle",
|
||||||
version: 685,
|
|
||||||
versionNonce: 706399231,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "dba8s5bDYEnF20oGn2a8b",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -1201,14 +919,9 @@ export default {
|
|||||||
seed: 1914896753,
|
seed: 1914896753,
|
||||||
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "rectangle",
|
type: "rectangle",
|
||||||
version: 835,
|
|
||||||
versionNonce: 851916657,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "3HxCT4mFZF-jJ6m9pyOCt",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -1224,14 +937,9 @@ export default {
|
|||||||
seed: 1306468145,
|
seed: 1306468145,
|
||||||
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "ellipse",
|
type: "ellipse",
|
||||||
version: 881,
|
|
||||||
versionNonce: 704574495,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "xX9mcMHy_0Bn-D0UAMyCc",
|
|
||||||
fillStyle: "solid",
|
fillStyle: "solid",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -1247,14 +955,9 @@ export default {
|
|||||||
seed: 93422161,
|
seed: 93422161,
|
||||||
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "rectangle",
|
type: "rectangle",
|
||||||
version: 528,
|
|
||||||
versionNonce: 816914769,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "h60d2h6UPYkopTlW_XEs4",
|
|
||||||
fillStyle: "cross-hatch",
|
fillStyle: "cross-hatch",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
@ -1270,20 +973,12 @@ export default {
|
|||||||
seed: 11646495,
|
seed: 11646495,
|
||||||
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "rectangle",
|
type: "rectangle",
|
||||||
version: 570,
|
|
||||||
versionNonce: 1198069823,
|
|
||||||
isDeleted: false,
|
|
||||||
id: "bZbx28BjXM33JV1UezMcH",
|
|
||||||
fillStyle: "cross-hatch",
|
fillStyle: "cross-hatch",
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
strokeStyle: "solid",
|
strokeStyle: "solid",
|
||||||
roughness: 1,
|
|
||||||
opacity: 100,
|
|
||||||
angle: 0,
|
|
||||||
x: -698.7169501405845,
|
x: -698.7169501405845,
|
||||||
y: 384.7822247024333,
|
y: 384.7822247024333,
|
||||||
strokeColor: "#000000",
|
strokeColor: "#000000",
|
||||||
@ -1293,7 +988,6 @@ export default {
|
|||||||
seed: 291717649,
|
seed: 291717649,
|
||||||
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
||||||
strokeSharpness: "sharp",
|
strokeSharpness: "sharp",
|
||||||
boundElementIds: [],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
13
examples/excalidraw/package.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "examples",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0",
|
||||||
|
"@excalidraw/excalidraw": "*"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5"
|
||||||
|
}
|
||||||
|
}
|
3
examples/excalidraw/tsconfig.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig"
|
||||||
|
}
|
146
examples/excalidraw/utils.ts
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
import { unstable_batchedUpdates } from "react-dom";
|
||||||
|
import { fileOpen as _fileOpen } from "browser-fs-access";
|
||||||
|
import { MIME_TYPES } from "@excalidraw/excalidraw";
|
||||||
|
import { AbortError } from "../../packages/excalidraw/errors";
|
||||||
|
|
||||||
|
type FILE_EXTENSION = Exclude<keyof typeof MIME_TYPES, "binary">;
|
||||||
|
|
||||||
|
const INPUT_CHANGE_INTERVAL_MS = 500;
|
||||||
|
|
||||||
|
export type ResolvablePromise<T> = Promise<T> & {
|
||||||
|
resolve: [T] extends [undefined] ? (value?: T) => void : (value: T) => void;
|
||||||
|
reject: (error: Error) => void;
|
||||||
|
};
|
||||||
|
export const resolvablePromise = <T>() => {
|
||||||
|
let resolve!: any;
|
||||||
|
let reject!: any;
|
||||||
|
const promise = new Promise((_resolve, _reject) => {
|
||||||
|
resolve = _resolve;
|
||||||
|
reject = _reject;
|
||||||
|
});
|
||||||
|
(promise as any).resolve = resolve;
|
||||||
|
(promise as any).reject = reject;
|
||||||
|
return promise as ResolvablePromise<T>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const distance2d = (x1: number, y1: number, x2: number, y2: number) => {
|
||||||
|
const xd = x2 - x1;
|
||||||
|
const yd = y2 - y1;
|
||||||
|
return Math.hypot(xd, yd);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fileOpen = <M extends boolean | undefined = false>(opts: {
|
||||||
|
extensions?: FILE_EXTENSION[];
|
||||||
|
description: string;
|
||||||
|
multiple?: M;
|
||||||
|
}): Promise<M extends false | undefined ? File : File[]> => {
|
||||||
|
// an unsafe TS hack, alas not much we can do AFAIK
|
||||||
|
type RetType = M extends false | undefined ? File : File[];
|
||||||
|
|
||||||
|
const mimeTypes = opts.extensions?.reduce((mimeTypes, type) => {
|
||||||
|
mimeTypes.push(MIME_TYPES[type]);
|
||||||
|
|
||||||
|
return mimeTypes;
|
||||||
|
}, [] as string[]);
|
||||||
|
|
||||||
|
const extensions = opts.extensions?.reduce((acc, ext) => {
|
||||||
|
if (ext === "jpg") {
|
||||||
|
return acc.concat(".jpg", ".jpeg");
|
||||||
|
}
|
||||||
|
return acc.concat(`.${ext}`);
|
||||||
|
}, [] as string[]);
|
||||||
|
|
||||||
|
return _fileOpen({
|
||||||
|
description: opts.description,
|
||||||
|
extensions,
|
||||||
|
mimeTypes,
|
||||||
|
multiple: opts.multiple ?? false,
|
||||||
|
legacySetup: (resolve, reject, input) => {
|
||||||
|
const scheduleRejection = debounce(reject, INPUT_CHANGE_INTERVAL_MS);
|
||||||
|
const focusHandler = () => {
|
||||||
|
checkForFile();
|
||||||
|
document.addEventListener("keyup", scheduleRejection);
|
||||||
|
document.addEventListener("pointerup", scheduleRejection);
|
||||||
|
scheduleRejection();
|
||||||
|
};
|
||||||
|
const checkForFile = () => {
|
||||||
|
// this hack might not work when expecting multiple files
|
||||||
|
if (input.files?.length) {
|
||||||
|
const ret = opts.multiple ? [...input.files] : input.files[0];
|
||||||
|
resolve(ret as RetType);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
window.addEventListener("focus", focusHandler);
|
||||||
|
});
|
||||||
|
const interval = window.setInterval(() => {
|
||||||
|
checkForFile();
|
||||||
|
}, INPUT_CHANGE_INTERVAL_MS);
|
||||||
|
return (rejectPromise) => {
|
||||||
|
clearInterval(interval);
|
||||||
|
scheduleRejection.cancel();
|
||||||
|
window.removeEventListener("focus", focusHandler);
|
||||||
|
document.removeEventListener("keyup", scheduleRejection);
|
||||||
|
document.removeEventListener("pointerup", scheduleRejection);
|
||||||
|
if (rejectPromise) {
|
||||||
|
// so that something is shown in console if we need to debug this
|
||||||
|
console.warn("Opening the file was canceled (legacy-fs).");
|
||||||
|
rejectPromise(new AbortError());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}) as Promise<RetType>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const debounce = <T extends any[]>(
|
||||||
|
fn: (...args: T) => void,
|
||||||
|
timeout: number,
|
||||||
|
) => {
|
||||||
|
let handle = 0;
|
||||||
|
let lastArgs: T | null = null;
|
||||||
|
const ret = (...args: T) => {
|
||||||
|
lastArgs = args;
|
||||||
|
clearTimeout(handle);
|
||||||
|
handle = window.setTimeout(() => {
|
||||||
|
lastArgs = null;
|
||||||
|
fn(...args);
|
||||||
|
}, timeout);
|
||||||
|
};
|
||||||
|
ret.flush = () => {
|
||||||
|
clearTimeout(handle);
|
||||||
|
if (lastArgs) {
|
||||||
|
const _lastArgs = lastArgs;
|
||||||
|
lastArgs = null;
|
||||||
|
fn(..._lastArgs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ret.cancel = () => {
|
||||||
|
lastArgs = null;
|
||||||
|
clearTimeout(handle);
|
||||||
|
};
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const withBatchedUpdates = <
|
||||||
|
TFunction extends ((event: any) => void) | (() => void),
|
||||||
|
>(
|
||||||
|
func: Parameters<TFunction>["length"] extends 0 | 1 ? TFunction : never,
|
||||||
|
) =>
|
||||||
|
((event) => {
|
||||||
|
unstable_batchedUpdates(func as TFunction, event);
|
||||||
|
}) as TFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* barches React state updates and throttles the calls to a single call per
|
||||||
|
* animation frame
|
||||||
|
*/
|
||||||
|
export const withBatchedUpdatesThrottled = <
|
||||||
|
TFunction extends ((event: any) => void) | (() => void),
|
||||||
|
>(
|
||||||
|
func: Parameters<TFunction>["length"] extends 0 | 1 ? TFunction : never,
|
||||||
|
) => {
|
||||||
|
// @ts-ignore
|
||||||
|
return throttleRAF<Parameters<TFunction>>(((event) => {
|
||||||
|
unstable_batchedUpdates(func, event);
|
||||||
|
}) as TFunction);
|
||||||
|
};
|
36
examples/excalidraw/with-nextjs/.gitignore
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
.yarn/install-state.gz
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
36
examples/excalidraw/with-nextjs/README.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
First, run the development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
# or
|
||||||
|
yarn dev
|
||||||
|
# or
|
||||||
|
pnpm dev
|
||||||
|
# or
|
||||||
|
bun dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Open [http://localhost:3000](http://localhost:3005) with your browser to see the result.
|
||||||
|
|
||||||
|
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||||
|
|
||||||
|
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
To learn more about Next.js, take a look at the following resources:
|
||||||
|
|
||||||
|
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||||
|
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||||
|
|
||||||
|
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||||
|
|
||||||
|
## Deploy on Vercel
|
||||||
|
|
||||||
|
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||||
|
|
||||||
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
12
examples/excalidraw/with-nextjs/next.config.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
distDir: "build",
|
||||||
|
typescript: {
|
||||||
|
// The ts config doesn't work with `jsx: preserve" and if updated to `react-jsx` it gets ovewritten by next js throwing ts errors hence I am ignoring build errors until this is fixed.
|
||||||
|
ignoreBuildErrors: true,
|
||||||
|
},
|
||||||
|
// This is needed as in pages router the code for importing types throws error as its outside next js app
|
||||||
|
transpilePackages: ["../"],
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = nextConfig;
|
25
examples/excalidraw/with-nextjs/package.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "with-nextjs",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"build:workspace": "yarn workspace @excalidraw/excalidraw run build:esm",
|
||||||
|
"dev": "yarn build:workspace && next dev -p 3005",
|
||||||
|
"build": "yarn build:workspace && next build",
|
||||||
|
"start": "next start -p 3006",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@excalidraw/excalidraw": "*",
|
||||||
|
"next": "14.1",
|
||||||
|
"react": "^18",
|
||||||
|
"react-dom": "^18"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^20",
|
||||||
|
"@types/react": "^18",
|
||||||
|
"@types/react-dom": "^18",
|
||||||
|
"path2d-polyfill": "2.0.1",
|
||||||
|
"typescript": "^5"
|
||||||
|
}
|
||||||
|
}
|
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 197 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
BIN
examples/excalidraw/with-nextjs/src/app/favicon.ico
Normal file
After Width: | Height: | Size: 25 KiB |
11
examples/excalidraw/with-nextjs/src/app/layout.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export default function RootLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<html lang="en">
|
||||||
|
<body>{children}</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
23
examples/excalidraw/with-nextjs/src/app/page.tsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import dynamic from "next/dynamic";
|
||||||
|
import "../common.scss";
|
||||||
|
|
||||||
|
// Since client components get prerenderd on server as well hence importing the excalidraw stuff dynamically
|
||||||
|
// with ssr false
|
||||||
|
const ExcalidrawWithClientOnly = dynamic(
|
||||||
|
async () => (await import("../excalidrawWrapper")).default,
|
||||||
|
{
|
||||||
|
ssr: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<a href="/excalidraw-in-pages">Switch to Pages router</a>
|
||||||
|
<h1 className="page-title">App Router</h1>
|
||||||
|
|
||||||
|
{/* @ts-expect-error - https://github.com/vercel/next.js/issues/42292 */}
|
||||||
|
<ExcalidrawWithClientOnly />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
15
examples/excalidraw/with-nextjs/src/common.scss
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #1c7ed6;
|
||||||
|
font-size: 20px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 550;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
text-align: center;
|
||||||
|
}
|
22
examples/excalidraw/with-nextjs/src/excalidrawWrapper.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
"use client";
|
||||||
|
import * as excalidrawLib from "@excalidraw/excalidraw";
|
||||||
|
import { Excalidraw } from "@excalidraw/excalidraw";
|
||||||
|
import App from "../../components/App";
|
||||||
|
|
||||||
|
import "@excalidraw/excalidraw/index.css";
|
||||||
|
|
||||||
|
const ExcalidrawWrapper: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<App
|
||||||
|
appTitle={"Excalidraw with Nextjs Example"}
|
||||||
|
useCustom={(api: any, args?: any[]) => {}}
|
||||||
|
excalidrawLib={excalidrawLib}
|
||||||
|
>
|
||||||
|
<Excalidraw />
|
||||||
|
</App>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ExcalidrawWrapper;
|
@ -0,0 +1,22 @@
|
|||||||
|
import dynamic from "next/dynamic";
|
||||||
|
import "../common.scss";
|
||||||
|
|
||||||
|
// Since client components get prerenderd on server as well hence importing the excalidraw stuff dynamically
|
||||||
|
// with ssr false
|
||||||
|
const Excalidraw = dynamic(
|
||||||
|
async () => (await import("../excalidrawWrapper")).default,
|
||||||
|
{
|
||||||
|
ssr: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<a href="/">Switch to App router</a>
|
||||||
|
<h1 className="page-title">Pages Router</h1>
|
||||||
|
{/* @ts-expect-error - https://github.com/vercel/next.js/issues/42292 */}
|
||||||
|
<Excalidraw />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
28
examples/excalidraw/with-nextjs/tsconfig.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
},
|
||||||
|
"forceConsistentCasingInFileNames": true
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "build/types/**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
3
examples/excalidraw/with-nextjs/vercel.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"outputDirectory": "build"
|
||||||
|
}
|
252
examples/excalidraw/with-nextjs/yarn.lock
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@excalidraw/excalidraw@workspace:^":
|
||||||
|
version "0.17.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.17.2.tgz#9a636a1e6bb3c88c5883347d3a7e75e9cce8ab96"
|
||||||
|
integrity sha512-7pqUWD8+mPjDhF4XxG3gw4rvE2JGaLW3Vss5UZfTbITPxAtFaGEc1K081bncitnaYhUwN9ENJE0i87QB3poDwQ==
|
||||||
|
|
||||||
|
"@next/env@14.0.4":
|
||||||
|
version "14.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@next/env/-/env-14.0.4.tgz#d5cda0c4a862d70ae760e58c0cd96a8899a2e49a"
|
||||||
|
integrity sha512-irQnbMLbUNQpP1wcE5NstJtbuA/69kRfzBrpAD7Gsn8zm/CY6YQYc3HQBz8QPxwISG26tIm5afvvVbu508oBeQ==
|
||||||
|
|
||||||
|
"@next/swc-darwin-arm64@14.0.4":
|
||||||
|
version "14.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz#27b1854c2cd04eb1d5e75081a1a792ad91526618"
|
||||||
|
integrity sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==
|
||||||
|
|
||||||
|
"@next/swc-darwin-x64@14.0.4":
|
||||||
|
version "14.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz#9940c449e757d0ee50bb9e792d2600cc08a3eb3b"
|
||||||
|
integrity sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==
|
||||||
|
|
||||||
|
"@next/swc-linux-arm64-gnu@14.0.4":
|
||||||
|
version "14.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz#0eafd27c8587f68ace7b4fa80695711a8434de21"
|
||||||
|
integrity sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==
|
||||||
|
|
||||||
|
"@next/swc-linux-arm64-musl@14.0.4":
|
||||||
|
version "14.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz#2b0072adb213f36dada5394ea67d6e82069ae7dd"
|
||||||
|
integrity sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==
|
||||||
|
|
||||||
|
"@next/swc-linux-x64-gnu@14.0.4":
|
||||||
|
version "14.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz#68c67d20ebc8e3f6ced6ff23a4ba2a679dbcec32"
|
||||||
|
integrity sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==
|
||||||
|
|
||||||
|
"@next/swc-linux-x64-musl@14.0.4":
|
||||||
|
version "14.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz#67cd81b42fb2caf313f7992fcf6d978af55a1247"
|
||||||
|
integrity sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==
|
||||||
|
|
||||||
|
"@next/swc-win32-arm64-msvc@14.0.4":
|
||||||
|
version "14.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz#be06585906b195d755ceda28f33c633e1443f1a3"
|
||||||
|
integrity sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==
|
||||||
|
|
||||||
|
"@next/swc-win32-ia32-msvc@14.0.4":
|
||||||
|
version "14.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz#e76cabefa9f2d891599c3d85928475bd8d3f6600"
|
||||||
|
integrity sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==
|
||||||
|
|
||||||
|
"@next/swc-win32-x64-msvc@14.0.4":
|
||||||
|
version "14.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz#e74892f1a9ccf41d3bf5979ad6d3d77c07b9cba1"
|
||||||
|
integrity sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==
|
||||||
|
|
||||||
|
"@swc/helpers@0.5.2":
|
||||||
|
version "0.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.2.tgz#85ea0c76450b61ad7d10a37050289eded783c27d"
|
||||||
|
integrity sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.4.0"
|
||||||
|
|
||||||
|
"@types/node@^20":
|
||||||
|
version "20.11.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.0.tgz#8e0b99e70c0c1ade1a86c4a282f7b7ef87c9552f"
|
||||||
|
integrity sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==
|
||||||
|
dependencies:
|
||||||
|
undici-types "~5.26.4"
|
||||||
|
|
||||||
|
"@types/prop-types@*":
|
||||||
|
version "15.7.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563"
|
||||||
|
integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==
|
||||||
|
|
||||||
|
"@types/react-dom@^18":
|
||||||
|
version "18.2.18"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.18.tgz#16946e6cd43971256d874bc3d0a72074bb8571dd"
|
||||||
|
integrity sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==
|
||||||
|
dependencies:
|
||||||
|
"@types/react" "*"
|
||||||
|
|
||||||
|
"@types/react@*", "@types/react@^18":
|
||||||
|
version "18.2.47"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.47.tgz#85074b27ab563df01fbc3f68dc64bf7050b0af40"
|
||||||
|
integrity sha512-xquNkkOirwyCgoClNk85BjP+aqnIS+ckAJ8i37gAbDs14jfW/J23f2GItAf33oiUPQnqNMALiFeoM9Y5mbjpVQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/prop-types" "*"
|
||||||
|
"@types/scheduler" "*"
|
||||||
|
csstype "^3.0.2"
|
||||||
|
|
||||||
|
"@types/scheduler@*":
|
||||||
|
version "0.16.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff"
|
||||||
|
integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==
|
||||||
|
|
||||||
|
busboy@1.6.0:
|
||||||
|
version "1.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
|
||||||
|
integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
|
||||||
|
dependencies:
|
||||||
|
streamsearch "^1.1.0"
|
||||||
|
|
||||||
|
caniuse-lite@^1.0.30001406:
|
||||||
|
version "1.0.30001576"
|
||||||
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz#893be772cf8ee6056d6c1e2d07df365b9ec0a5c4"
|
||||||
|
integrity sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==
|
||||||
|
|
||||||
|
client-only@0.0.1:
|
||||||
|
version "0.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
|
||||||
|
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
|
||||||
|
|
||||||
|
csstype@^3.0.2:
|
||||||
|
version "3.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
|
||||||
|
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
||||||
|
|
||||||
|
glob-to-regexp@^0.4.1:
|
||||||
|
version "0.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
|
||||||
|
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
|
||||||
|
|
||||||
|
graceful-fs@^4.1.2, graceful-fs@^4.2.11:
|
||||||
|
version "4.2.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
||||||
|
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
|
||||||
|
|
||||||
|
"js-tokens@^3.0.0 || ^4.0.0":
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||||
|
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||||
|
|
||||||
|
loose-envify@^1.1.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||||
|
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||||
|
dependencies:
|
||||||
|
js-tokens "^3.0.0 || ^4.0.0"
|
||||||
|
|
||||||
|
nanoid@^3.3.6:
|
||||||
|
version "3.3.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
||||||
|
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
|
||||||
|
|
||||||
|
next@14.0.4:
|
||||||
|
version "14.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/next/-/next-14.0.4.tgz#bf00b6f835b20d10a5057838fa2dfced1d0d84dc"
|
||||||
|
integrity sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA==
|
||||||
|
dependencies:
|
||||||
|
"@next/env" "14.0.4"
|
||||||
|
"@swc/helpers" "0.5.2"
|
||||||
|
busboy "1.6.0"
|
||||||
|
caniuse-lite "^1.0.30001406"
|
||||||
|
graceful-fs "^4.2.11"
|
||||||
|
postcss "8.4.31"
|
||||||
|
styled-jsx "5.1.1"
|
||||||
|
watchpack "2.4.0"
|
||||||
|
optionalDependencies:
|
||||||
|
"@next/swc-darwin-arm64" "14.0.4"
|
||||||
|
"@next/swc-darwin-x64" "14.0.4"
|
||||||
|
"@next/swc-linux-arm64-gnu" "14.0.4"
|
||||||
|
"@next/swc-linux-arm64-musl" "14.0.4"
|
||||||
|
"@next/swc-linux-x64-gnu" "14.0.4"
|
||||||
|
"@next/swc-linux-x64-musl" "14.0.4"
|
||||||
|
"@next/swc-win32-arm64-msvc" "14.0.4"
|
||||||
|
"@next/swc-win32-ia32-msvc" "14.0.4"
|
||||||
|
"@next/swc-win32-x64-msvc" "14.0.4"
|
||||||
|
|
||||||
|
path2d-polyfill@2.0.1:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz#24c554a738f42700d6961992bf5f1049672f2391"
|
||||||
|
integrity sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==
|
||||||
|
|
||||||
|
picocolors@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||||
|
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||||
|
|
||||||
|
postcss@8.4.31:
|
||||||
|
version "8.4.31"
|
||||||
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
|
||||||
|
integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
|
||||||
|
dependencies:
|
||||||
|
nanoid "^3.3.6"
|
||||||
|
picocolors "^1.0.0"
|
||||||
|
source-map-js "^1.0.2"
|
||||||
|
|
||||||
|
react-dom@^18:
|
||||||
|
version "18.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
|
||||||
|
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
|
||||||
|
dependencies:
|
||||||
|
loose-envify "^1.1.0"
|
||||||
|
scheduler "^0.23.0"
|
||||||
|
|
||||||
|
react@^18:
|
||||||
|
version "18.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
||||||
|
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||||
|
dependencies:
|
||||||
|
loose-envify "^1.1.0"
|
||||||
|
|
||||||
|
scheduler@^0.23.0:
|
||||||
|
version "0.23.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
|
||||||
|
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
|
||||||
|
dependencies:
|
||||||
|
loose-envify "^1.1.0"
|
||||||
|
|
||||||
|
source-map-js@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||||
|
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||||
|
|
||||||
|
streamsearch@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
|
||||||
|
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
|
||||||
|
|
||||||
|
styled-jsx@5.1.1:
|
||||||
|
version "5.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f"
|
||||||
|
integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==
|
||||||
|
dependencies:
|
||||||
|
client-only "0.0.1"
|
||||||
|
|
||||||
|
tslib@^2.4.0:
|
||||||
|
version "2.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
|
||||||
|
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
|
||||||
|
|
||||||
|
typescript@^5:
|
||||||
|
version "5.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
|
||||||
|
integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
|
||||||
|
|
||||||
|
undici-types@~5.26.4:
|
||||||
|
version "5.26.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
||||||
|
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||||
|
|
||||||
|
watchpack@2.4.0:
|
||||||
|
version "2.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
|
||||||
|
integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
|
||||||
|
dependencies:
|
||||||
|
glob-to-regexp "^0.4.1"
|
||||||
|
graceful-fs "^4.1.2"
|
@ -12,18 +12,21 @@
|
|||||||
<script>
|
<script>
|
||||||
window.name = "codesandbox";
|
window.name = "codesandbox";
|
||||||
</script>
|
</script>
|
||||||
|
<link rel="stylesheet" href="/dist/browser/dev/index.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<noscript> You need to enable JavaScript to run this app. </noscript>
|
<noscript> You need to enable JavaScript to run this app. </noscript>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script src="https://unpkg.com/react@18.2.0/umd/react.development.js"></script>
|
|
||||||
<script src="https://unpkg.com/react-dom@18.2.0/umd/react-dom.development.js"></script>
|
|
||||||
|
|
||||||
<!-- This is so that we use the bundled excalidraw.development.js file instead
|
<!-- This is so that we use the bundled excalidraw.development.js file instead
|
||||||
of the actual source code -->
|
of the actual source code -->
|
||||||
<script src="./excalidraw.development.js"></script>
|
<script type="module">
|
||||||
|
import * as ExcalidrawLib from "@excalidraw/excalidraw";
|
||||||
|
|
||||||
<script src="./bundle.js"></script>
|
console.log(ExcalidrawLib);
|
||||||
|
window.ExcalidrawLib = ExcalidrawLib;
|
||||||
|
</script>
|
||||||
|
<script type="module" src="index.tsx"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
28
examples/excalidraw/with-script-in-browser/index.tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import App from "../components/App";
|
||||||
|
import React, { StrictMode } from "react";
|
||||||
|
import { createRoot } from "react-dom/client";
|
||||||
|
|
||||||
|
import type * as TExcalidraw from "@excalidraw/excalidraw";
|
||||||
|
|
||||||
|
import "@excalidraw/excalidraw/index.css";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
ExcalidrawLib: typeof TExcalidraw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const rootElement = document.getElementById("root")!;
|
||||||
|
const root = createRoot(rootElement);
|
||||||
|
const { Excalidraw } = window.ExcalidrawLib;
|
||||||
|
root.render(
|
||||||
|
<StrictMode>
|
||||||
|
<App
|
||||||
|
appTitle={"Excalidraw Example"}
|
||||||
|
useCustom={(api: any, args?: any[]) => {}}
|
||||||
|
excalidrawLib={window.ExcalidrawLib}
|
||||||
|
>
|
||||||
|
<Excalidraw />
|
||||||
|
</App>
|
||||||
|
</StrictMode>,
|
||||||
|
);
|
19
examples/excalidraw/with-script-in-browser/package.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "with-script-in-browser",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0",
|
||||||
|
"@excalidraw/excalidraw": "*"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"vite": "5.0.12",
|
||||||
|
"typescript": "^5"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "yarn workspace @excalidraw/excalidraw run build:esm && vite",
|
||||||
|
"build": "yarn workspace @excalidraw/excalidraw run build:esm && vite build",
|
||||||
|
"build:preview": "yarn build && vite preview --port 5002"
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 197 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 39 KiB |
4
examples/excalidraw/with-script-in-browser/vercel.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"outputDirectory": "dist",
|
||||||
|
"installCommand": "yarn install"
|
||||||
|
}
|