Compare commits

...

672 Commits

Author SHA1 Message Date
f6ced89c3c prefer props.viewModeEnabled 2025-05-12 21:37:41 +02:00
6eb0596638 fix debug 2025-05-12 20:27:22 +02:00
0607003903 limit zoom 2025-05-12 21:29:07 +10:00
4e2026e47d tweak debounce timeout 2025-05-12 21:07:21 +10:00
67260915cb improve zoom in/out animation 2025-05-12 19:09:21 +10:00
c84fad4436 experiment with zooming 2025-05-12 16:24:00 +10:00
2e9c8851b3 simplify code 2025-05-12 16:23:35 +10:00
19608b712f improve debug 2025-05-12 16:23:18 +10:00
3a566a292c rename and restrict constraint mode 2025-05-09 18:46:54 +10:00
62c800c21a refactor code 2025-05-09 18:07:58 +10:00
f9723e2d19 do not include constraints in tests 2025-05-09 16:40:35 +10:00
ffbd4a5dc8 lint 2025-05-09 16:21:02 +10:00
5dded6112c rename func 2025-05-09 15:44:39 +10:00
84c396aec2 fix jumping/flashing when zooming in or out too quickly 2025-05-09 13:00:56 +10:00
bc6cc83b1e update encoding & decoding 2025-05-08 15:58:39 +10:00
baa7b3293a bringing back scroll constraints debug 2025-05-08 12:21:42 +10:00
4208c97b62 configurable allowance 2025-05-02 17:52:14 +10:00
2d0c0afa34 encode and decode constraints 2025-05-02 17:32:44 +10:00
df26487936 call api to update when debug inputs change 2025-04-14 17:22:23 +10:00
782772cec5 fix debug inputs 2025-04-14 17:16:15 +10:00
39f79927ae merge with master 2025-04-14 16:18:11 +10:00
01304aac49 feat: Keep text label horizontal (#9364)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2025-04-13 21:21:49 +02:00
dff69e9191 chore: Element center point util (#9298) 2025-04-09 17:04:51 +02:00
6fc85022ae fix: lasso selection issues (#9353)
* revert stroke slicing hack for knot

* fix incorrect closing of path

* nonzero enclosure

* lint
2025-04-08 00:50:52 +10:00
e48b63a0ae fix: Rounded diamond edge elbow arrow U route (#9349) 2025-04-07 10:43:07 +02:00
c2caf78e95 fix: deselected hit element being duplicated + incorrect re-seeding (#9333)
* fix: deselected hit element being duplicated + incorrect re-seeding

* snapshots

* Fix alt-drag binding

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* Add alt-drag bound arrow test

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

---------

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
Co-authored-by: Mark Tolmacs <mark@lazycat.hu>
2025-04-07 10:41:31 +02:00
ce267aa0d3 feat: lasso selection (#9169)
* lasso without 'real' shape detection

* select a single linear el

* improve ux

* feed segments to worker

* simplify path threshold adaptive to zoom

* add a tiny threshold for checks

* refactor code

* lasso tests

* fix: ts

* do not capture lasso tool

* try worker-loader in next config

* update config

* refactor

* lint

* feat: show active tool when using "more tools"

* keep lasso if selected from toolbar

* fix incorrect checks for resetting to selection

* shift for additive selection

* bound text related fixes

* lint

* keep alt toggled lasso selection if shift pressed

* fix regression

* fix 'dead' lassos

* lint

* use workerpool and polyfill

* fix worker bundled with window related code

* refactor

* add file extension for worker constructor error

* another attempt at constructor error

* attempt at build issue

* attempt with dynamic import

* test not importing from math

* narrow down imports

* Reusing existing workers infrastructure (fallback to the main thread, type-safety)

* Points on curve inside the shared chunk

* Give up on experimental code splitting

* Remove potentially unnecessary optimisation

* Removing workers as the complexit is much worse, while perf. does not seem to be much better

* fix selecting text containers and containing frames together

* render fill directly from animated trail

* do not re-render static when setting selected element ids in lasso

* remove unnecessary property

* tweak trail animation

* slice points to remove notch

* always start alt-lasso from initial point

* revert build & worker changes (unused)

* remove `lasso` from `hasStrokeColor`

* label change

* remove unused props

* remove unsafe optimization

* snaps

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
Co-authored-by: Marcel Mraz <marcel@excalidraw.com>
2025-04-07 16:44:25 +10:00
6e47fadb59 feat: add container to multiple text elements (#9348) 2025-04-07 00:57:27 +02:00
b3d5ba0567 fix: Linear element is not normalized (#9347)
* Fix #9292
2025-04-06 13:41:11 +02:00
c79e892e55 chore: bump @radix-ui/react-tabs version to 1.1.3 (#9329)
* chore: bump @radix-ui/react-tabs version to 1.1.3

bumped the version to latest stable that includes
react ^19 as peerDepenecy.
This fixes peerDependency issues, as reported in #9253

* redeploy

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2025-04-02 16:23:15 +02:00
57a9e301d4 feat: tweak color swatch, and button bgs (#9330)
* feat: tweak color swatch, and button bgs

* snapshots
2025-04-02 14:36:13 +02:00
7c58477382 feat: tweak properties panel styling (#9322) 2025-03-30 19:20:13 +02:00
83fac6d0db feat: tweak stats panel input styles (#9321) 2025-03-30 19:00:31 +02:00
f2e8404c7b feat: allow to disable preventUnload in dev (#9319)
* feat: allow to disable preventUnload in dev

* add template
2025-03-29 19:42:33 +01:00
d797c2e210 fix: strip legacy attrs on element restore (#9318) 2025-03-29 19:31:16 +01:00
0cd5a259ae fix: incorrect type imports (#9308) 2025-03-27 12:00:12 +01:00
432a46ef9e refactor: separate elements logic into a standalone package (#9285) 2025-03-26 15:24:59 +01:00
a18f059188 fix: Reduce allocations in collision detection (#9299)
Reduce allocations
2025-03-26 15:10:43 +01:00
ab89d4c16f feat: add keyboard shortcut to save file in text (#9295)
Co-authored-by: Aviral Sharma <aviralsharma954@gmail.com>
2025-03-25 22:18:55 +01:00
6c3a434f2a docs: Fix table rendering and broken links in Props page (#9293)
* Fix table rendering and broken links

---------

Co-authored-by: Marcel Mraz <marcel@excalidraw.com>
2025-03-25 14:32:15 +01:00
e1bb59fb8f chore: Use isDevEnv() and isTestEnv() (#9264)
Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
Co-authored-by: Mark Tolmacs <mark@lazycat.hu>
2025-03-24 19:44:00 +01:00
77aca48c84 fix: Refactor and merge duplication and binding (#9246) 2025-03-23 18:39:33 +01:00
58990b41ae fix: 'Rotate' spell error (#9288) 2025-03-22 09:06:23 +00:00
99d8bff175 fix: elements offset incorrectly when action-duplicated during drag (#9275)
* fix: elements offset incorrectly when action-duplicated during drag

* prevent duplicate action during drag altogether
2025-03-15 20:05:42 +01:00
30983d801a fix: Arrow conversion regression (#9241)
Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
2025-03-15 12:31:25 +01:00
21ffaf4d76 refactor: auto ordered imports (#9163) 2025-03-12 15:23:31 +01:00
82b9a6b464 docs: CHANGELOG typos 🙏 (#9250) 2025-03-11 23:18:15 +01:00
817d8c553c docs: update CHANGELOG (#9243) 2025-03-11 13:44:10 +01:00
69bc5bdaab chore: post publish docs & examples changes (#9217) 2025-03-11 13:02:59 +01:00
d587b8a3de fix: Do not rebind undragged elbow arrow endpoint (#9191) 2025-03-10 16:25:33 +01:00
4ec812bc18 fix: Bound elbow arrow on duplication does not route correctly (#9236) 2025-03-08 12:39:54 +01:00
a9e2d2348b chore: Logging and fixing extremely large scenes (#9225) 2025-03-05 23:06:01 +01:00
70c3e921bb fix: package env vars (#9221) 2025-03-04 21:45:48 +01:00
d92384b77d revert: vite@6 -> vite@5 (#9220) 2025-03-04 17:45:52 +00:00
c5d3bb0b6a fix: #8475 Arrow updated on both sides (#8593) 2025-03-04 17:24:39 +01:00
d21c6a1bc6 chore: bump vite@6.x (#9210) 2025-03-04 14:00:13 +01:00
d1112bbf4f fix: docked sidebar width (#9213) 2025-03-02 18:24:20 +01:00
2523624f15 fix: React 18 element.ref was accessed error (#9208)
Bump @radix-ui/react-popover to fix element.ref React 19 error

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
2025-03-02 14:24:50 +01:00
68578556ff fix: cleanup legacy element.rawText (obsidian) (#9203) 2025-03-01 11:03:02 +01:00
ecef5d12f4 chore: release @excalidraw/excalidraw@18.0.0 🎉 (#9127) 2025-02-28 16:49:09 +01:00
392118bf26 fix: Fix elbow arrow fixed binding on restore (#9197) 2025-02-28 15:36:41 +01:00
0ffeaeaecf feat: Remove GA code from binding (#9042)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2025-02-25 22:52:06 +01:00
31e8476c78 chore: upgrade to react@19 (#9182) 2025-02-25 19:18:42 +01:00
9ee0b8ffcb Enhancement: grouped together Undo and Redo buttons on mobile (#9109)
* bugfix: put the redo and undo button under the same div so that they look grouped together

* fixed the position of the redo and undo buttons to the right
2025-02-13 13:07:44 +00:00
16b86d7d16 chore: update firebase@8 to @11 (#9136) 2025-02-13 13:57:14 +01:00
f12b92ce9d chore: Upgrade Sentry to latest and update debug messages (#9134)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2025-02-13 12:47:27 +01:00
77dc055d81 chore: Revert aspect ratio fix with element size limits and chk (#9131) 2025-02-12 15:02:35 +01:00
26f02bebea fix: stop using structuredClone (#9128)
fix: stop using `structuredClone`
2025-02-12 13:02:53 +01:00
e3060dfb8f feat: custom text metrics provider (#9121) 2025-02-11 14:23:08 +01:00
c329470b73 fix: Fix inconsistency in resizing while maintaining aspect ratio (#9116) 2025-02-10 15:24:08 +01:00
c8f4a4cb41 feat: add props.onDuplicate (#9117)
* feat: add `props.onDuplicate`

* docs

* clarify docs

* fix docs
2025-02-10 14:20:18 +00:00
9e49c9254b fix: IFrame and elbow arrow interaction fix (#9101) 2025-02-06 14:45:49 +01:00
b0c8c5f7a7 feat: change empty arrowhead icon (#9100) 2025-02-06 10:52:03 +01:00
4f64372506 perf: Improved pointer events related performance when the sidebar is docked with a large library open (#9086)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2025-02-04 22:05:56 +01:00
424e94a403 fix: duplicating/removing frame while children selected (#9079) 2025-02-04 19:23:47 +01:00
302664e500 fix: Elbow arrow z-index binding (#9067) 2025-02-01 19:21:03 +01:00
86c67bd37f fix: library item checkbox style regression (#9080) 2025-02-01 12:27:41 +01:00
511433988c feat: tweak slider colors to be more muted (#9076) 2025-01-31 16:52:50 +01:00
9b6edc767a fix: Elbow arrow orthogonality (#9073) 2025-01-31 14:19:07 +01:00
6cdb683410 fix: button bg CSS variable leaking into other styles (#9075) 2025-01-31 12:33:54 +01:00
84bab403ff Fix: issue #8818 Xiaolai font has been set as a fallback for Excalifont (#9055)
Co-authored-by: David Luzar <5153846+dwelle@users.noreply.github.com>
2025-01-30 13:41:41 +00:00
Are
61e0bb83d0 feat: improve library sidebar performance (#9060)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2025-01-30 14:41:08 +01:00
bd1590fc74 feat: implement custom Range component for opacity control (#9009)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2025-01-29 21:46:40 +00:00
d29c3db7f6 fix: fonts not loading on export (again) (#9064) 2025-01-29 22:24:26 +01:00
a58822c1c1 fix: merge server-side fonts with liberation sans (#9052) 2025-01-29 22:04:49 +01:00
a3e1619635 fix: hyperlinks html entities (#9063) 2025-01-29 19:02:54 +01:00
52eaf64591 feat: box select frame & children to allow resizing at the same time (#9031)
* box select frame & children

* avoid selecting children twice to avoid double their moving

* do not show ele stats if frame and children selected together

* do not update frame membership if selected together

* do not group frame and its children

* comment and refactor code

* hide align altogether

* include frame children when selecting all

* simplify

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2025-01-28 22:10:16 +01:00
7028daa44a fix: remove flushSync to fix flickering (#9057) 2025-01-28 19:23:35 +01:00
65f218b100 fix: excalidraw issue #9045 flowcharts: align attributes of new node (#9047)
* fix: excalidraw#9045 by modifying the stroke style, opacity, and fill style for the new node and next nodes.

* fix: added roughness and opacity to the arrowbindings
2025-01-25 17:05:50 +01:00
807b3c59f2 fix: align arrows bound to elements excalidraw#8833 (#8998) 2025-01-25 17:00:39 +01:00
b8da5065fd fix: update elbow arrow on font size change #8798 (#9002) 2025-01-25 17:00:26 +01:00
49f1276ef2 fix: Undo for elbow arrows create incorrect routing (#9046) 2025-01-24 20:18:08 +01:00
8f20b29b73 fix: #8575 , Flowchart clones the current arrowhead (#8581)
* fix: #8575, Flowchart clones the current arrowhead

* fix: #8575, changed stroke color, style and width to startBindingElement
2025-01-24 16:50:07 +01:00
f87c2cde09 feat: allow installing libs from excal github (#9041) 2025-01-23 16:50:47 +01:00
0bf234fcc9 fix: adding partial group to frame (#9014)
* prevent new frame from including partial groups

* separate wrapped partial group
2025-01-23 07:26:12 +08:00
dd1b45a25a perf: reduce unnecessary frame clippings (#8980)
* reduce unnecessary frame clippings

* further optim
2025-01-23 07:25:46 +08:00
ec06fbc1fc fix: do not refocus element link input on unrelated updates (#9037) 2025-01-22 21:30:15 +01:00
fa05ae1230 refactor: remove defaultProps (#9035) 2025-01-22 12:43:02 +01:00
91ebf8b0ea feat: Elbow arrow segment fixing & positioning (#8952)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
Co-authored-by: David Luzar <5153846+dwelle@users.noreply.github.com>
2025-01-17 18:07:03 +01:00
8551823da9 feat: update jotai (#9015)
* feat: update jotai in excalidraw package

* feat: update jotai in excalidraw-app

* fix: exports from excalidraw/jotai

* fix: use isolated react hooks

* test: use jotai provider in <Trans /> test

* remove unused package

* refactor & make safer

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2025-01-16 16:59:11 +01:00
ae6bee3403 feat: do not delete frame children on frame delete (#9011) 2025-01-14 21:08:25 +01:00
46f42ef8d7 fix: arrow binding behaving unexpectedly on pointerup (#9010)
* fix: arrow binding behaving unexpectedly on pointerup

* update snaps
2025-01-14 19:36:47 +01:00
00b5b0a0ca feat: add action to wrap selected items in a frame (#9005)
* feat: add action to wrap selected items in a frame

* fix type

* select frame on wrap & refactor

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2025-01-13 15:03:56 +00:00
c92f3bebf5 fix: change cursor by tool change immediately (#8212) 2025-01-09 14:26:12 +01:00
2ac55067cd fix: package build fails on worker chunks (#8990) 2025-01-07 11:22:36 +00:00
78ab12c7e6 fix: z-index clash in mobile UI (#8985) 2025-01-06 21:21:11 +01:00
f2f8219917 feat: reintroduce .excalidraw.png default when embedding scene (#8979) 2025-01-05 22:21:39 +01:00
12c39d1034 feat: add mimeTypes on file save (#8946) 2025-01-05 21:12:07 +00:00
d33e42e3a1 feat: add crowfoot to arrowheads (#8942)
* crowfoot many

* crowfoot one

* one or many

* add icons for crowfoot

* add crowfoot icons

* adjust arrowhead selection popover

* make options collapsible

* swap triangle and bar

* switch to radix popover

* put triangle outline in the first row

* align shadow with new design spec

* remove unused flag

* swap order

* tweak labels

* handle shift+tab

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
Co-authored-by: Jakub Królak <108676707+j-krolak@users.noreply.github.com>
2025-01-05 21:50:24 +01:00
3b9ffd9586 fix: elbow arrows do not work within frames (issue: #8964) (#8969)
check for !isFrameLikeElement
2025-01-05 21:47:20 +01:00
b63689c230 feat: make HTML attribute sanitization stricter (#8977)
* feat: make HTML attribute sanitization stricter

* fix double escape
2025-01-05 21:45:04 +01:00
c84babf574 feat: validate library install urls (#8976) 2025-01-05 17:10:55 +01:00
36274f1f3e feat: cleanup svg export and move payload to <metadata> (#8975) 2025-01-05 16:53:05 +01:00
798c795405 docs: add demo link for browser integration (#8956) 2024-12-27 14:39:08 +09:00
107eae3916 refactor: separate resizing logic from pointer (#8155)
* separate resizing logic for a single element

* replace resize logic in stats

* do not recompute width and height from points when they're already given

* correctly update linear elements' position when resized

* update snapshots

* lint

* simplify linear resizing logic

* fix initial scale for aspect ratio

* update tests for linear elements

* test typo

* separate pointer from resizing for multiple elements

* lint and simplify

* fix tests

* lint

* provide scene in param instead

* type

* refactor code

* fix floating in tests

* remove restrictions/checks on width & height

* update pointer to dimension to prevent regression

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-12-23 11:10:35 +01:00
56fca30bd0 fix: normalizeSVG width and height from viewbox when size includes decimal points (#8939)
Update image.ts
2024-12-22 23:10:11 +01:00
1e3399eac8 fix: make arrow binding area adapt to zoom levels (#8927)
* make binding area adapt to zoom

* revert stroke color

* normalize binding gap

* reduce normalized gap
2024-12-22 22:55:50 +01:00
873698a1a2 fix: robust state.editingFrame teardown (#8941) 2024-12-22 22:47:39 +01:00
606ac6c743 fix: regression on dragging a selected frame by its name (#8924)
fix hit element check for a selected frame's name
2024-12-22 22:47:21 +01:00
d99e4a23ca feat: use stats panel to crop (#8848)
* feat: use stats panel to crop

* fix: test flake

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-12-17 13:15:30 +01:00
551bae07a7 feat: snap when cropping as well (#8831)
* crop with snap

* make crop snap work with cmd as well

* turn off grid with cmd as well in crop
2024-12-16 18:31:33 +08:00
2af3221974 fix: right-click paste for images in clipboard (Issue #8826) (#8845)
* Fix right-click paste command for images (Issue #8826)

* Fix clipboard logic for multiple paste types

* fix: remove unused code

* refactor & robustness

* fix: creating paste event with image files

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-12-10 20:10:34 +00:00
9b401f6ea3 fix: fixed image transparency by adding alpha option to preserve image alpha channel (#8895)
added alpha option to preserve image alpha channel
2024-12-10 13:41:10 +01:00
8a1152ce36 fix: Flush pending DOM updates before .focus() (#8901) 2024-12-09 21:57:37 +01:00
b5652b8e36 fix: normalize svg using only absolute sizing (#8854) 2024-11-27 13:09:44 +01:00
31e2a0cb4a fix: element link selector dialog z-index & positioning (#8853) 2024-11-26 23:18:20 +01:00
c0b80a03bd feat: in canvas links between shapes (#8812)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-11-26 18:53:25 +01:00
a758aaf8f6 fix: update old blog links & add canonical url (#8846) 2024-11-26 17:42:25 +01:00
b2a6a87b10 chore: Remove @tldraw/vec (#8762)
Not needed.
2024-11-21 15:19:20 +01:00
ab8b3537b3 fix: Optimize frameToHighlight state change and snapLines state change (#8763)
Fix case when frame interactions recursively call setState() without any change.
2024-11-21 15:19:00 +01:00
d21e0008dd fix: Make some events expllicitly active to avoid console warnings (#8757)
Avoid chrome/edge reporting of by-default blocking event handlers
2024-11-21 15:18:18 +01:00
840f1428c4 chore: bump @excalidraw/mermaid-to-excalidraw@1.1.2 (#8830) 2024-11-20 13:10:07 +01:00
2db5bbcb29 fix: Unify binding update options for updateBoundElements() (#8832)
Fix insonsistent naming for option newSize/oldSize for updateBoundElements()
2024-11-20 11:46:45 +01:00
0927431d0d chore: bump @excalidraw/mermaid-to-excalidraw (#8829) 2024-11-19 20:46:55 +01:00
98c0a67333 build(deps): bump cross-spawn from 7.0.3 to 7.0.6 (#8824)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-19 20:34:35 +01:00
57cf577376 fix: cleanup scripts and support upto node 22 (#8794) 2024-11-11 23:56:00 +05:30
6e0ee89ee4 fix: usage of node12 which is deprecated (#8791) 2024-11-11 12:05:55 +01:00
35f778a734 build: set PWA flag in dev to false (#8788) 2024-11-09 21:04:50 +01:00
ee091d0dbd build: add a flag VITE_APP_ENABLE_PWA for enabling pwa in dev environment (#8784)
* build: add a flag VITE_APP_ENABLE_PWA for enabling pwa in dev environment

* fix

* set VITE_ENABLE_PWA to false in .env.development
2024-11-09 21:45:37 +05:30
ef9ea14a75 fix: remove manifest.json (#8783)
* fix: remove manifest.json

* disable pwa in dev
2024-11-09 13:42:11 +05:30
df168a6883 fix: load env vars correctly and set debug and linter flags to false explicitly in prod mode (#8770)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-11-07 21:14:49 +00:00
798f5f4dfb feat: update blog url (#8767) 2024-11-06 16:41:41 +00:00
d9ad7c039b feat: export scene to e+ on workspace creation/redemption (#8514)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-11-04 22:35:45 +00:00
7c0239e693 fix: Console error in dev mode due to missing font path in non-prod (#8756)
Fix console error due to missing font path in dev mode reported by Firefox.
2024-11-04 17:54:00 +01:00
da33481fa3 chore: support upto node 22.x.x (#8755) 2024-11-04 18:57:40 +05:30
70e0e8dc29 fix: text pushes UI due to padding (#8745) 2024-11-01 23:43:48 +02:00
2734e646ca chore: simplify line-break regexes, separate text wrapping (#8715) 2024-10-30 14:24:12 +01:00
dfaaff4432 fix: fix trailing line whitespaces layout shift (#8714) 2024-10-30 14:11:13 +01:00
03028eaa8c fix: load font faces in Safari manually (#8693) 2024-10-30 12:40:24 +01:00
79b181bcdc fix: restore svg image DataURL dimensions (#8730) 2024-10-29 22:40:24 +01:00
f9815b8b4f fix: image cropping svg + compat mode (#8710)
Co-authored-by: Ryan Di <ryan.weihao.di@gmail.com>
2024-10-28 10:08:05 +01:00
96ed8a4331 chore: remove duplicated meta tag (#8718)
Co-authored-by: David Luzar <5153846+dwelle@users.noreply.github.com>
2024-10-25 16:29:48 +00:00
33b01d4e80 fix: usage of node12 which is deprecated (#8709) 2024-10-25 10:39:44 +05:30
7d52176fea feat: added sitemap & fixed robot txt (#8699) 2024-10-24 12:49:33 +02:00
958e03fcc6 fix: image render perf (#8697) 2024-10-23 11:58:43 +02:00
4cedf3d966 feat: do not strip unknown element properties on restore (#8682) 2024-10-21 22:56:22 +02:00
e957c8e9ee feat: image cropping (#8613)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-10-21 22:26:52 +02:00
eb09b48ae6 fix: undo/redo action for international keyboard layouts (#8649)
Co-authored-by: Marcel Mraz <marcel@excalidraw.com>
2024-10-21 17:08:39 +02:00
61623bbeba fix: Comic Shanns issues, new fonts structure (#8641) 2024-10-21 00:11:53 +02:00
15ca182333 fix: remove export-to-clip-as-svg shortcut for now (#8660) 2024-10-17 20:47:05 +02:00
b479f3bd65 feat: add first-class support for CJK (#8530) 2024-10-17 20:14:17 +02:00
21815fb930 fix: text disappearing on edit (#8558) (#8624) 2024-10-17 13:11:48 +02:00
47ee8a0094 refactor: point() -> pointFrom() to fix compiler issue (#8578) 2024-10-01 21:27:17 +02:00
a977dd1bf5 feat: Added reddit links as embeddable (#8099)
feat: #8063 Added reddit links as embeddable

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2024-09-28 11:49:18 +05:30
3fe1883f3f feat: prefer user defined coords and dimensions over calculated for for frame (#8517)
* feat: prefer user defined coords and dimensions over calculated for frame

* update changelog

* lint

* show the info only in dev mode and when children present
2024-09-24 21:09:15 +05:30
a80cb5896a feat: self-hosting existing google fonts (#8540) 2024-09-24 17:30:21 +02:00
6dfa18414a test: decrease min coverage thresholds (#8541) 2024-09-24 12:01:28 +00:00
8ca4cf3260 feat: flip arrowheads if only arrow(s) selected (#8525)
Co-authored-by: Mark Tolmacs <mark@lazycat.hu>
2024-09-19 15:46:36 +02:00
f3f0ab7c83 fix: Elbow arrow fixedpoint flipping now properly flips on inverted resize and flip action (#8324)
* Flipping action now properly mirrors selections with elbow arrows
* Flipping action now re-centers the selection to the original center to avoid "walking" selections on repeated flipping
2024-09-19 08:47:23 +02:00
44a1c8d857 fix: svg and png frame clipping cases (#8515) 2024-09-18 00:20:22 +02:00
e0a22edfbd fix: Re-route elbow arrows when pasted (#8448)
Re-route elbow arrows when pasted
2024-09-17 12:20:40 +02:00
c07f5a0c80 feat: Common elbow mid segments (#8440)
Common start or end segment length for elbow arrows regardless of arrowhead is present
2024-09-17 10:11:07 +02:00
508f16dc04 refactor: rename example App.tsx -> ExampleApp.tsx (#8501) 2024-09-13 16:56:32 +02:00
c1b310c56b fix: Buffer dependency (#8474)
* fix Buffer dependency

* moved to encode.ts

* move base64 parsing out

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-09-12 15:48:47 +02:00
d4900e8f19 fix: Linear element complete button disabled (#8492) 2024-09-12 14:59:38 +02:00
caf2db934c fix: aspect ratio of distorted images are not preserved in SVG exports (#8061) 2024-09-12 14:11:08 +02:00
60e3801691 fix: WYSIWYG editor padding is not normalized with zoom.value (#8481) 2024-09-12 13:42:39 +02:00
80f3b75d42 chore: revert vite 5.4.2 -> 5.0.12 (#8499) 2024-09-12 12:56:45 +02:00
dc812bee19 docs: replace dead link (#8494)
* docs update dead link on main-menu page

* doc: fix dead link
2024-09-12 13:20:18 +05:30
01e83cc9a5 fix: default sidebar triggers & behavior (#8498) 2024-09-11 20:19:14 +02:00
813f9b702e feat: merge search sidebar back to default sidebar (#8497) 2024-09-11 19:26:01 +02:00
fd39712ba6 fix: improve canvas search scroll behavior further (#8491) 2024-09-11 18:01:18 +02:00
b46ca0192b fix: addFiles clears the whole image cache when each file is added - regression from #8471 (#8490)
Update App.tsx
2024-09-11 07:57:41 +02:00
72b7c937b1 feat: smarter zooming when scrolling to match & only match on search/switch (#8488) 2024-09-10 21:26:01 +02:00
d107215564 fix: select instead of focus search input (#8483) 2024-09-09 19:57:22 +02:00
6959a363f0 feat: canvas search (#8438)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-09-09 17:12:07 +02:00
5a11c70714 fix: image rendering issue when passed in initialData (#8471) 2024-09-08 23:56:00 +02:00
6ff56c36e3 fix: add partial mocking (#8473)
* fix: add partial mocking

* lint

* Update packages/utils/export.test.ts
2024-09-06 16:41:37 +05:30
51ea184938 build: upgrade vite to 5.4.x, vitest to 2.x and related vite packages (#8459)
* build: upgrade vite to 5.x, vitest to 2.x and related vite packages

* upgrade vitest-ui and coverage

* pass empty set to fix type error and update snap

* set ignoreEmptyLines to false

* update threshold

* update coverage threshold

* downgrade vite-plugin-pwa as its better to push separately with testing

* add package resolutions for strip-ansi, string-width and wrap-ansi

* disable pwa

* only add resolution for strip-ansi
2024-09-05 18:35:36 +05:30
21fff26d31 build(deps): bump micromatch from 4.0.5 to 4.0.8 in /dev-docs (#8458)
Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.5 to 4.0.8.
- [Release notes](https://github.com/micromatch/micromatch/releases)
- [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/micromatch/compare/4.0.5...4.0.8)

---
updated-dependencies:
- dependency-name: micromatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-04 15:46:37 +05:30
f4dd23fc31 chore: Unify math types, utils and functions (#8389)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-09-02 22:23:38 +00:00
e3d1dee9d0 build(deps): bump micromatch from 4.0.7 to 4.0.8 (#8450)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 00:37:49 +02:00
e3f31df747 docs : update dead link on main-menu page (#8454) 2024-09-01 22:31:13 +00:00
60e75406e0 refactor: remove unused env variable (#8457) 2024-09-02 00:25:12 +02:00
b396e07b90 fix: PropertiesPopover maxWidth changing fixed units to relative units (#8456) 2024-09-01 18:18:37 +02:00
2d1d84a47b fix: View mode wheel zooming does not work (#8452)
* Update App.tsx

* fix: prevent zooming browser over DOM

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-08-31 12:06:38 +02:00
ee30225062 feat: subset font glyphs for SVG export (#8384)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-08-30 22:26:06 +02:00
16cae4fc07 feat: reset copyStatus on export dialog settings change (#8443) 2024-08-29 15:10:08 +02:00
576bc0dbe5 feat: tweak copy button success animation (#8441) 2024-08-29 00:43:01 +02:00
00af35c692 feat: enable panning/zoom while in wysiwyg (#8437) 2024-08-29 00:42:46 +02:00
ea7c702cfc feat: Visual debugger (#8344)
Add visual debugger to the Excalidraw app (only).
2024-08-27 19:46:00 +02:00
26d2296578 fix: fixed copy to clipboard button (#8426)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-08-27 00:27:44 +02:00
afb68a6467 feat: improve elbow arrow keyboard move (#8392) 2024-08-26 15:58:54 +02:00
b459e5cfd2 fix: context menu does not work after after dragging on StatsDragInput (#8386)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-08-26 15:58:46 +02:00
5facc0d6da fix: perf regression in getCommonBounds (#8429) 2024-08-26 15:57:28 +02:00
824ad603e1 docs: Update function call in @excalidraw/mermaid-to-excalidraw (#8420) 2024-08-26 13:20:29 +02:00
5e1ff7cafe perf: improve new element drawing (#8340)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-08-23 20:27:57 +02:00
b5d7f5b4ba feat: rewrite d2c to not require token (#8269) 2024-08-20 18:06:22 +02:00
fb4bb29aa5 fix: object snapping not working (#8381) 2024-08-15 18:48:25 +02:00
3cfcc7b489 feat: split gridSize from enabled state & support custom gridStep (#8364) 2024-08-14 14:59:14 +02:00
4320a3cf41 feat: improve zoom-to-content when creating flowchart (#8368) 2024-08-12 20:42:08 +02:00
8420e1aa13 fix: Reimplement rectangle intersection (#8367) 2024-08-12 19:19:16 +02:00
5daf1a1b4e fix: Round coordinates and sizes for rectangle intersection (#8366)
Round coordinates and sizes for rectangle intersection
2024-08-12 11:07:58 +02:00
97981804d7 feat: Stats popup style tweaks (#8361) 2024-08-11 19:33:44 +02:00
f7b3befd0a fix: text content with tab characters act different in view/edit (#8336)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-08-09 20:20:36 +00:00
7b2bee9746 chore: remove unused parameter (#8355) 2024-08-09 21:39:40 +02:00
88014ace4a fix: drawing from 0-dimension canvas (#8356) 2024-08-09 21:36:04 +02:00
87a9430809 fix: disable flowchart keybindings inside inputs (#8353) 2024-08-09 18:44:17 +02:00
99b91c46f7 fix: Yet more patching of intersect code (#8352)
* Yet more patching of intersect code
2024-08-09 17:33:12 +02:00
1ea5b26f25 fix: missing act() in flowchart tests (#8354) 2024-08-09 17:27:02 +02:00
d5f4ee7b3f fix: z-index change by one causes app to freeze (#8314) 2024-08-09 15:26:08 +02:00
261304c1a4 fix: Patch over intersection calculation issue (#8350)
* Patch over intersection calculation issue
2024-08-09 14:40:57 +02:00
84398a7e5c fix: Point duplication in LEE on ALT+click (#8347) 2024-08-09 12:01:32 +02:00
54491d13d4 feat: create flowcharts from a generic element using elbow arrows (#8329)
Co-authored-by: Mark Tolmacs <mark@lazycat.hu>
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-08-08 21:43:15 +02:00
dd1370381d chore: Refactor and remove scene from elbow arrow generation (#8342)
* Refactor and remove scene from elbow arrow generation
2024-08-08 14:06:26 +02:00
72d6ee48fc fix: Do not allow resizing unbound elbow arrows either (#8333)
* Fix resizing of unbound elbow arrows
2024-08-06 17:33:34 +02:00
232242d2e9 test: skip test.yml in PRs (#8330) 2024-08-06 16:04:04 +02:00
f19ce30dfe chore: bump @testing-library/react 12.1.5 -> 16.0.0 (#8322) 2024-08-06 15:17:42 +02:00
3cf14c73a3 refactor: rename draggingElement -> newElement (#8294)
* add newElement to appState

* freedraw should not be an editing element

* do not set editing element for freedraw and generic

* remove ununsed `appState.draggingElement`

* remove setting dragged for new linear element

* decouple selection element from new element

* fix hint for text bindables

* update snapshot

* fixes

* fix frame regressions

* add comments to types

* document `editingElement`

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-08-06 19:26:06 +08:00
8d530cf102 fix: Docker build in CI (#8312)
* Fix Docker build CI
* Bump nginx-alpine version to 1.27
2024-08-06 13:21:20 +02:00
b87925d253 build: add example apps public and vite dev-dist to eslintignore (#8326) 2024-08-05 23:43:48 +02:00
a6684b09f2 docs: fix typos in props.mdx (#8325) 2024-08-05 21:41:19 +00:00
b427617f66 build: add rm:build, rm:node_modules & clean-install scripts (#8323) 2024-08-05 23:37:33 +02:00
2907fbe34b build(deps): bump @excalidraw/excalidraw from 0.17.0 to 0.17.6 in /dev-docs (#7908)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-05 09:49:57 +02:00
c67815f7b0 fix: Duplicating arrow without bound elements throws error (#8316)
Co-authored-by: David Luzar <5153846+dwelle@users.noreply.github.com>
2024-08-03 16:37:36 +00:00
c641860cb1 fix: CVE-2023-45133 (#7988)
* Upgrade @babel/* versions to 7.24 to ensure non-vulnerable Babel versions
* Pinning React version to 18.2.0 exactly, avoiding test-utils type version clashes
* Fix warning message on yarn start
* Moving react to peer dependencies
* Moving app dependencies from workspace into app
* Bump vitest to 1.6.0 to fix history.test.tsx breaking

---------

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
2024-08-02 14:44:38 +02:00
84d89b9a8a fix: throttle fractional indices validation (#8306) 2024-08-02 11:55:15 +02:00
e63dd025c9 fix: allow binding elbow arrows to frame children (#8309) 2024-08-01 19:40:54 +02:00
15e019706d feat: Orthogonal (elbow) arrows for diagramming (#8299)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-08-01 18:39:03 +02:00
a133a70e87 build: update release script to build esm (#8308) 2024-08-01 20:19:37 +05:30
80ea7ca23f fix: skip registering font faces for local fonts (#8303) 2024-08-01 11:32:16 +02:00
e844580b14 feat: remove automatic frame naming (#8302) 2024-07-31 13:56:11 +02:00
5a0771ad9c fix: load fonts for exportToCanvas (#8298) 2024-07-30 17:23:35 +02:00
adcdbe2907 fix: re-add Cascadia Code with ligatures (#8291) 2024-07-30 11:15:11 +02:00
230d0edc44 feat: multiple fonts fallbacks (#8286) 2024-07-30 10:34:40 +02:00
d0a380758e feat: ability to debug the state of fractional indices (#8235) 2024-07-30 10:03:27 +02:00
7b36de0476 fix: linear elements not selected on pointer up from hitting its bound text (#8285)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-07-27 13:02:00 +00:00
2427e622b0 feat: improve mermaid detection on paste (#8287) 2024-07-27 12:36:54 +02:00
62228e0bbb feat: introduce font picker (#8012)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-07-25 18:55:55 +02:00
4c5408263c chore: Correct Typos in Code Comments (#8268)
chore: correct typos

Co-authored-by: wuzhiqing <wuzhiqing@linklogis.com>
2024-07-23 14:26:55 +05:30
bd7b778f41 perf: cache the temp canvas created for labeled arrows (#8267)
* perf: cache the temp canvas created for labeled arrows

* use allEleemntsMap so bound text element can be retrieved when editing

* remove logs

* fix rotation

* pass isRotating

* feat: cache `element.angle` instead of relying on `appState.isRotating`

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-07-23 11:17:32 +05:30
43b2476dfe fix: revert default element canvas padding change (#8266) 2024-07-22 11:47:16 +02:00
df8875a497 fix: freedraw jittering (#8238) 2024-07-14 08:44:47 +00:00
6fbc44fd1f fix: messed up env variable (#8231) 2024-07-11 14:33:35 +02:00
d25a7d365b feat: upgrade mermaid-to-excalidraw to v1.1.0 (#8226)
* feat: upgrade mermaid-to-excalidraw to v1.1.0

* fixes

* upgrade and remove config as its redundant

* lint

* upgrade to v1.1.0
2024-07-10 20:57:43 +05:30
e52c2cd0b6 fix: log allowed events (#8224) 2024-07-09 12:16:14 +02:00
96eeec5119 feat: bump max file size (#8220) 2024-07-08 18:35:13 +02:00
f5221d521b ci: upgrade gh actions checkout and setup-node to v4 (#8168)
fix: usage of `node12 which is deprecated`
2024-07-08 14:26:25 +05:30
db2c235cd4 Fix : exportToCanvas() doc example (#8127) 2024-07-08 08:52:05 +00:00
148b895f46 feat: smarter preferred lang detection (#8205) 2024-07-04 17:55:35 +02:00
d9258a736b chore: Consolidate i18n import in LanguageList component (#8201) 2024-07-04 17:34:16 +02:00
2e1f08c796 fix: memory leak - scene.destroy() and window.launchQueue (#8198) 2024-07-02 22:08:02 +02:00
1d5b41dabb fix: stop updating text versions on init (#8191) 2024-07-01 14:04:58 +02:00
66a2f24296 fix: Add binding update to manual stat changes (#8183)
Manual stats changes now respect previous element bindings.
2024-07-01 09:45:31 +02:00
04668d8263 fix: Binding after duplicating is now applied for both the old and duplicate shapes (#8185)
Using ALT/OPT + drag to clone does not transfer the bindings (or leaves the duplicates in place of the old one , which are also not bound).

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
2024-06-28 15:28:48 +02:00
abbeed3d5f feat: support Stats bound text fontSize editing (#8187) 2024-06-28 13:52:29 +02:00
ba8c09d529 fix: Incorrect point offsetting in LinearElementEditor.movePoints() (#8145)
The LinearElementEditor.movePoints() function incorrectly calculates the offset for local linear element points when multiple targetPoints are provided, one of those target points is index === 0 AND the other points are moved in the negative direction, and ending up with negative local coordinates.

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
2024-06-28 12:23:10 +02:00
744b3e5d09 fix: stats state leaking & race conds (#8177) 2024-06-26 23:31:08 +02:00
6ba9bd60e8 feat: allow props.initialData to be a function (#8135) 2024-06-24 11:36:49 +02:00
a1ffa064df fix: only bind arrow (#8152)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-06-19 10:55:35 +02:00
4dc4590f24 fix: repair invalid binding on restore & fix type check (#8133) 2024-06-13 19:42:08 +02:00
d2f67e619f feat: editable element stats (#6382)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-06-12 19:49:46 +02:00
22b39277f5 feat: paste as mermaid if applicable (#8116) 2024-06-11 19:19:22 +02:00
63dee03ef0 docs: remove extra braces in callback JSX (#8087)
Fix: Syantax error
2024-05-31 10:48:31 +00:00
08b13f971d fix: wysiwyg blur-submit on mobile (#8075) 2024-05-28 16:18:02 +02:00
69f4cc70cb feat: stop autoselecting text on text edit on mobile (#8076) 2024-05-28 16:17:52 +02:00
860308eb27 feat: create new text with width (#8038)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-05-28 15:53:52 +02:00
4eb9463f26 fix: restore linear dimensions from points (#8062) 2024-05-27 10:36:58 +02:00
6ed6131169 build: run tests on master branch (#8072)
* build: run tests on master branch

* lint
2024-05-27 12:44:20 +05:30
1ed98f9c93 fix: lp plus url (#8056) 2024-05-24 09:10:14 +00:00
a71bb63d1f fix: fix twitter og image (#8050) 2024-05-23 11:52:37 +02:00
661d6a4a75 fix: flaky snapshot tests with floating point precision issues (#8049) 2024-05-23 11:51:01 +02:00
defd34923a docs: fix updateScene storeAction default tsdoc & document types (#8048) 2024-05-22 13:40:23 +02:00
c540bd68aa feat: wrap long text when pasting (#8026)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-05-21 16:56:09 +02:00
eddbe55f50 fix: always re-generate index of defined moved elements (#8040) 2024-05-20 23:23:42 +02:00
2f9526da24 feat: upgrade to mermaid-to-excalidraw v1 🚀 (#8022)
* feat: upgrade to mermaid-to-excalidraw v1 🚀

* upgrade to v1
2024-05-20 11:19:38 +05:30
1b6e3fe05b feat: rerender canvas on focus (#8035) 2024-05-19 22:20:40 +02:00
afe52c89a7 fix: undo/redo when exiting view mode (#8024)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-05-19 15:54:52 +02:00
be4e127f6c fix: Two finger panning is slow (#7849)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-05-19 14:23:43 +02:00
ff0b4394b1 feat: add missing type="button" (#8030) 2024-05-18 08:36:08 +00:00
Hey
7d8b7fc14d fix: compatible safari layers button svg (#8020)
Co-authored-by: ysen <ysen.ge@hairobotics.com>
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-05-15 15:22:05 +02:00
971b4d4ae6 feat: text wrapping (#7999)
* resize single elements from the side

* fix lint

* do not resize texts from the sides (for we want to wrap/unwrap)

* omit side handles for frames too

* upgrade types

* enable resizing from the sides for multiple elements as well

* fix lint

* maintain aspect ratio when elements are not of the same angle

* lint

* always resize proportionally for multiple elements

* increase side resizing padding

* code cleanup

* adaptive handles

* do not resize for linear elements with only two points

* prioritize point dragging over edge resizing

* lint

* allow free resizing for multiple elements at degree 0

* always resize from the sides

* reduce hit threshold

* make small multiple elements movable

* lint

* show side handles on touch screen and mobile devices

* differentiate touchscreens

* keep proportional with text in multi-element resizing

* update snapshot

* update multi elements resizing logic

* lint

* reduce side resizing padding

* bound texts do not scale in normal cases

* lint

* test sides for texts

* wrap text

* do not update text size when changing its alignment

* keep text wrapped/unwrapped when editing

* change wrapped size to auto size from context menu

* fix test

* lint

* increase min width for wrapped texts

* wrap wrapped text in container

* unwrap when binding text to container

* rename `wrapped` to `autoResize`

* fix lint

* revert: use `center` align when wrapping text in container

* update snaps

* fix lint

* simplify logic on autoResize

* lint and test

* snapshots

* remove unnecessary code

* snapshots

* fix: defaults not set correctly

* tests for wrapping texts when resized

* tests for text wrapping when edited

* fix autoResize refactor

* include autoResize flag check

* refactor

* feat: rename action label & change contextmenu position

* fix: update version on `autoResize` action

* fix infinite loop when editing text in a container

* simplify

* always maintain `width` if `!autoResize`

* maintain `x` if `!autoResize`

* maintain `y` pos after fontSize change if `!autoResize`

* refactor

* when editing, do not wrap text in textWysiwyg

* simplify text editor

* make test more readable

* comment

* rename action to match file name

* revert function signature change

* only update  in app

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-05-15 21:04:53 +08:00
cc4c51996c build: specify packageManager field (#8010) 2024-05-14 10:45:27 +02:00
79257a1923 fix: correctly resolve the package version (#8016)
The property name is `VITE_PKG_VERSION` (not `PKG_VERSION`)

Resolves #7984
2024-05-14 13:31:02 +05:30
dc66261c19 fix: re-introduce wysiwyg width offset (#8014) 2024-05-13 17:38:21 +02:00
273ba803d9 fix: font not rendered correctly on init (#8002) 2024-05-10 16:37:46 +02:00
301e83805d feat: add install-PWA to command palette (#7935) 2024-05-08 22:02:28 +02:00
ed5ce8d3de fix: command palette filter (#7981) 2024-05-08 17:56:05 +02:00
1ed53b153c build: enable consistent type imports eslint rule (#7992)
* build: enable consistent type imports eslint rule

* change to warn

* fix the warning in example and excalidraw-app

* fix packages

* enable type annotations and throw error for the rule
2024-05-08 14:21:50 +05:30
c1926f33bb fix: remove unused param from drawImagePlaceholder (#7991) 2024-05-07 20:22:51 +05:30
6539029d2a fix: docker build of Excalidraw app (#7430)
* fix: docker build of Excalidraw app

Fixes #7403.

* deps: update (container) Nginx to 1.24

---------

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2024-05-07 18:00:58 +05:30
d1f37cc64f feat: tweak a few icons & add line editor button to side panel (#7990) 2024-05-07 13:18:39 +02:00
f0d25e34c3 chore: Add lcov coverage output to vitest (#7987)
chore: Add lcov coverage output to vitest so VSCode coverage gutters extension works

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
2024-05-06 17:35:23 +02:00
d9bbf1eda6 feat: Allow binding only via linear element ends (#7946)
Arrows now only bind to new shapes if their start or end point is dragged close to them. Arrows previously bound to shapes remain bound on move and drag if at the end of the drag/move the points remain in the original shapes' binding area.

---------

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
Co-authored-by: Sammy Lee <sammy.joe.lee@gmail.com>
2024-05-02 08:32:12 +02:00
f79fb9aae2 chore: Bump vitest to 1.5.3 to support VSCode vitest Extension (#7968)
Bump vitest to 1.5.3 to support VSCode vitest Extension

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
2024-05-01 20:47:52 +02:00
275f6fbe24 fix: typo in doc api (#7466) 2024-04-30 16:52:42 +00:00
88812e0386 feat: resize elements from the sides (#7855)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-04-30 18:05:00 +02:00
6e5aeb112d feat: record freedraw tool selection to history (#7949) 2024-04-25 17:24:05 +00:00
4d83d1c91e fix: use Reflect API instead of Object.hasOwn (#7958) 2024-04-25 15:36:26 +02:00
a04676d423 fix: CTRL/CMD & arrow point drag unbinds both sides (#6459) (#7877) 2024-04-23 00:01:05 +02:00
c851aaaf7b fix: z-index for laser pointer to be able to draw on embeds and such (#7918) 2024-04-22 23:53:55 +02:00
1bd2b1fe55 feat: export reconciliation (#7917) 2024-04-22 17:27:57 +02:00
015b46ab23 feat: expose StoreAction in relation to multiplayer history (#7898)
Improved Store API and improved handling of actions to eliminate potential concurrency issues
2024-04-22 09:22:25 +00:00
530617be90 feat: multiplayer undo / redo (#7348) 2024-04-17 14:01:24 +02:00
5211b003b8 fix: double text rendering on edit (#7904) 2024-04-17 13:48:04 +02:00
bbcca06b94 fix: collision regressions from vector geometry rewrite (#7902) 2024-04-17 13:31:12 +02:00
f92f04c13c fix: Correct unit from 'eg' to 'deg' (#7891) 2024-04-15 11:11:27 +02:00
890ed9f31f feat: add "toggle grid" to command palette (#7887) 2024-04-13 19:12:29 +02:00
da2e507298 fix: allow same origin for all necessary domains (#7889) 2024-04-13 18:51:30 +02:00
f59b4f6af4 fix: always make sure we render bound text above containers (#7880) 2024-04-12 21:50:02 +02:00
afcde542f9 fix: parse embeddable srcdoc urls strictly (#7884) 2024-04-12 20:51:17 +02:00
4689a6b300 fix: hit test for closed sharp curves (#7881) 2024-04-12 12:58:51 +02:00
0ae9b383d6 fix: Gist embed allowing unsafe html (#7883) 2024-04-12 12:57:43 +02:00
f597bd3e01 fix: command palette tweaks and fixes (#7876) 2024-04-11 11:39:19 +02:00
4987cc53d0 fix: include borders when testing insides of a shape (#7865) 2024-04-09 16:07:36 +02:00
d917db438e fix: external link not opening (#7859) 2024-04-09 16:06:49 +02:00
a33a400f01 fix: add safe check for arrow points length in tranformToExcalidrawElements (#7863)
* fix: add safe check for arrow points length in tranformToExcalidrawElements

* add spec

* throw error only for dev mode

* fix lint
2024-04-09 09:56:21 +05:30
8a162a4cb4 fix: import (#7869) 2024-04-08 16:59:03 +02:00
c6a045d092 fix: theme toggle shortcut event.code (#7868) 2024-04-08 16:55:33 +02:00
cd50aa719f feat: add system mode to the theme selector (#7853)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-04-08 16:46:24 +02:00
92bc08207c fix: remove incorrect check from index.html (#7867) 2024-04-08 16:42:00 +02:00
32df5502ae feat: fractional indexing (#7359)
* Introducing fractional indices as part of `element.index`

* Ensuring invalid fractional indices are always synchronized with the array order

* Simplifying reconciliation based on the fractional indices

* Moving reconciliation inside the `@excalidraw/excalidraw` package

---------

Co-authored-by: Marcel Mraz <marcel@excalidraw.com>
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-04-04 13:51:11 +01:00
bbdcd30a73 refactor: update collision from ga to vector geometry (#7636)
* new collision api

* isPointOnShape

* removed redundant code

* new collision methods in app

* curve shape takes starting point

* clean up geometry

* curve rotation

* freedraw

* inside curve

* improve ellipse inside check

* ellipse distance func

* curve inside

* include frame name bounds

* replace previous private methods for getting elements at x,y

* arrow bound text hit detection

* keep iframes on top

* remove dependence on old collision methods from app

* remove old collision functions

* move some hit functions outside of app

* code refactor

* type

* text collision from inside

* fix context menu test

* highest z-index collision

* fix 1px away binding test

* strictly less

* remove unused imports

* lint

* 'ignore' resize flipping test

* more lint fix

* skip 'flips while resizing' test

* more test

* fix merge errors

* fix selection in resize test

* added a bit more comment

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-04-04 16:31:23 +08:00
3e334a67ed feat: show firefox-compatible command palette shortcut alias (#7825) 2024-03-28 18:12:54 +01:00
1d71f84515 fix: stop using lookbehind for backwards compat (#7824) 2024-03-28 17:32:38 +01:00
550a388b2b feat: command palette (#7804)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-03-28 16:16:32 +00:00
6b523563d8 fix: ejs support in html files (#7822) 2024-03-28 14:58:47 +01:00
65bc500598 fix: excalidrawAPI.toggleSidebar not switching between tabs correctly (#7821) 2024-03-28 14:52:23 +01:00
7949aa1f1c feat: upgrade mermaid-to-excalidraw to 0.3.0 (#7819) 2024-03-28 16:44:29 +05:30
15bfa626b4 feat: support to not render remote cursor & username (#7130) 2024-03-18 10:41:06 +01:00
068895db0e feat: expose more collaborator status icons (#7777) 2024-03-18 10:20:07 +01:00
b7babe554b feat: load old library if migration fails 2024-03-11 09:57:01 +01:00
6a385d6663 feat: change LibraryPersistenceAdapter load() source -> priority
to clarify the semantics
2024-03-11 09:40:51 +01:00
2382fad4f6 feat: store library to IndexedDB & support storage adapters (#7655) 2024-03-08 22:29:19 +01:00
480572f893 fix: correcting Assistant metrics (#7758)
* Changed Assistant metrics to the corrrect ones from OS/2 table

* Adding more information about font metrics

* Adding branded types to avoid future mistakes
2024-03-07 16:54:36 +01:00
68b1fdb20e fix: add missing font metrics for Assistant (#7752) 2024-03-06 10:53:37 +01:00
a38e82f999 feat: close dropdown on escape (#7750) 2024-03-05 23:22:34 +01:00
a07f6e9e3a feat: show ai badge for discovery (#7749) 2024-03-05 23:22:25 +01:00
7e471b55eb feat: text measurements based on font metrics (#7693)
* Introduced vertical offset based on harcoded font metrics 

* Unified usage of alphabetic baseline for both canvas & svg export

* Removed baseline property

* Removed font-size rounding on Safari

* Removed artificial width offset
2024-03-05 19:33:27 +00:00
160440b860 feat: improve collab error notification (#7741)
* identify cause

* toast after dialog for error messages in collab

* remove comment

* shake tooltip instead for repeating collab errors

* clear collab error

* empty commit

* simplify & fix reset race condition

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-03-04 20:43:44 +08:00
f207bd0a1c build: export types for @excalidraw/utils (#7736)
* build: export types for @excalidraw/utils

* fix

* add types
2024-02-29 15:43:04 +05:30
99601baffc build: create ESM build for utils package 🥳 (#7500)
* build: create ESM build for utils package

* add deps, exports and import.meta
2024-02-28 19:33:47 +05:30
af1a3d5b76 fix: export utils from excalidraw package in excalidraw library (#7731)
* fix: export utils from excalidraw package in excalidraw library

* don't export utils utilities

* fix import path

* fix export

* don't export export utilites

* fix export paths

* reexport utils from excalidraw package

* add exports from withinBounds

* fix path
2024-02-28 11:14:57 +05:30
36e56267c9 docs: add missing closing angle bracket in integration.mdx (#7729)
Update integration.mdx: Fix missing closing angle bracket in code sample

 A closing angle bracket was missing in a code sample.

Original code:
<div style={{height:"500px", width:"500px"}}
    <Excalidraw />
</div>

Changes:

<div style={{height:"500px", width:"500px"}}>
    <Excalidraw />
</div>
2024-02-27 07:19:20 +00:00
b09b5cb5f4 fix: split renderScene so that locales aren't imported unnecessarily (#7718)
* fix: split renderScene so that locales aren't imported unnecessarily

* lint

* split export code

* rename renderScene to helpers.ts

* add helpers

* fix typo

* fixes

* move renderElementToSvg to export

* lint

* rename export to staticSvgScene

* fix
2024-02-27 10:37:44 +05:30
dd8529743a docs: type mistake in integration of excalidraw (#7723) 2024-02-26 10:24:27 +01:00
f639d44a95 fix: remove dependency of t in blob.ts (#7717)
* remove dependency of t in blob.ts

* fix
2024-02-23 15:05:46 +05:30
f5ab3e4e12 fix: remove dependency of t from clipboard and image (#7712)
* fix: remove dependency of t from clipboard and image

* pass errorMessage to copyTextToSystemClipboard where needed

* wrap copyTextToSystemClipboard and rethrow translated error in caller

* review fix

* typo
2024-02-21 19:45:33 +05:30
361a9449bb fix: remove scene hack from export.ts & remove pass elementsMap to getContainingFrame (#7713)
* fix: remove scene hack from export.ts as its not needed anymore

* remove

* pass elementsMap to getContainingFrame

* remove unused `mapElementIds` param

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-02-21 16:34:20 +05:30
2e719ff671 fix: decouple pure functions from hyperlink to prevent mermaid bundling (#7710)
* move hyperlink code into its folder

* move pure js functions to hyperlink/helpers and move actionLink to actions

* fix tests

* fix
2024-02-20 20:59:01 +05:30
79d9dc2f8f fix: make bounds independent of scene (#7679)
* fix: make bounds independent of scene

* pass only elements to getCommonBounds

* lint

* pass elementsMap to getVisibleAndNonSelectedElements
2024-02-19 19:39:14 +05:30
9013c84524 fix: make LinearElementEditor independent of scene (#7670)
* fix: make LinearElementEditor independent of scene

* more fixes

* pass elements and elementsMap to maybeBindBindableElement,getHoveredElementForBinding,bindingBorderTest,getElligibleElementsForBindableElementAndWhere,isLinearElementEligibleForNewBindingByBindable

* replace `ElementsMap` with `NonDeletedSceneElementsMap` & remove unused params

* fix lint

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-02-19 11:49:01 +05:30
47f87f4ecb fix: remove scene from getElementAbsoluteCoords and dependent functions and use elementsMap (#7663)
* fix: remove scene from getElementAbsoluteCoords and dependent functions and use elementsMap

* lint

* fix

* use non deleted elements where possible

* use non deleted elements map in actions

* pass elementsMap instead of array to elementOverlapsWithFrame

* lint

* fix

* pass elementsMap to getElementsCorners

* pass elementsMap to getEligibleElementsForBinding

* pass elementsMap in bindOrUnbindSelectedElements and unbindLinearElements

* pass elementsMap in elementsAreInFrameBounds,elementOverlapsWithFrame,isCursorInFrame,getElementsInResizingFrame

* pass elementsMap in getElementsWithinSelection, getElementsCompletelyInFrame, isElementContainingFrame, getElementsInNewFrame

* pass elementsMap to getElementWithTransformHandleType

* pass elementsMap to getVisibleGaps, getMaximumGroups,getReferenceSnapPoints,snapDraggedElements

* lint

* pass elementsMap to bindTextToShapeAfterDuplication,bindLinearElementToElement,getTextBindableContainerAtPosition

* revert changes for bindTextToShapeAfterDuplication
2024-02-16 11:35:01 +05:30
73bf50e8a8 fix: remove t from getDefaultAppState and allow name to be nullable (#7666)
* fix: remove t and allow name to be nullable

* pass name as required prop

* remove Unnamed

* pass name to excalidrawPlus as well for better type safe

* render once we have excalidrawAPI to avoid defaulting

* rename `getAppName` -> `getName` (temporary)

* stop preventing editing filenames when `props.name` supplied

* keep `name` as optional param for export functions

* keep `appState.name` on `props.name` state separate

* fix lint

* assertive first

* fix lint

* Add TODO

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-02-15 11:11:18 +05:30
1316d884fe feat: update constraints on window resize 2024-02-09 21:18:05 +01:00
d6710ded04 feat: disable animations during zooms out of translate canvas 2024-02-09 20:57:18 +01:00
78d2a6ecc0 feat: add constraints on canvas actions 2024-02-09 20:09:00 +01:00
213134bbca fix: disable overscroll on pinch-to-zoom 2024-02-09 16:17:58 +01:00
b5bf346229 fix: prevent jumping when trying to zoom out the zoomFactor 2024-02-09 16:10:58 +01:00
4c62eef7da fix: add scroll constraints to pinch-to-zoom in safari 2024-02-09 15:47:18 +01:00
82aa1cf19d fix: fixed detecting viewport outside of constraints 2024-02-09 15:31:51 +01:00
48c3465b19 docs: release patch v0.17.3 (#7673)
* docs: release patch v0.17.3

* update cl
2024-02-09 19:29:50 +05:30
adc4c9f484 fix: prevent panning to trigger history on macos chrome (#7671) 2024-02-08 19:50:50 +01:00
9bc874a61e fix: adjust the scroll constraints to align with inverted scrollX/Y 2024-02-08 18:40:42 +01:00
def1df2c68 fix: keep customData when converting to ExcalidrawElement (#7656)
* feat: keep customData when converting to ExcalidrawElement (#7654)

* docs: add changelog for keeping customData when converting to ExcalidrawElement
2024-02-08 17:23:10 +05:30
d5f55aba44 [debug] 2 2024-02-07 17:09:49 +01:00
72de65e482 Merge branch 'master' into arnost/scroll-in-read-only-links 2024-02-07 16:07:57 +01:00
0513b647ec feat: change collab trigger & add share dialog (#7647) 2024-02-03 14:04:23 +00:00
a289c42830 feat: add loading state to FilledButton (#7650) 2024-02-03 14:53:31 +01:00
d67eaa8710 fix: file save timing out with big file sizes (#7649) 2024-02-03 11:53:35 +01:00
0c3dffb082 fix: make getEmbedLink independent of t function (#7643)
* fix: make getEmbedLink independent of t function

* rename warning to error and make it type safe
2024-02-01 21:12:10 +05:30
0e0f34edd8 fix: follow mode border for hosts apps (#7642) 2024-02-01 15:03:15 +01:00
4888d9d355 chore: change default port of collab server (#7641) 2024-02-01 14:41:38 +01:00
1c39bd5781 fix: don't bundle react and jotai when importing from scene (#7640)
* don't bundle react and jotai when importing from scene

* fix
2024-02-01 18:24:17 +05:30
90ad885446 feat: support onPointerUp prop (#7638)
* feat: support onPointerUp prop

* update changelog

* Update packages/excalidraw/CHANGELOG.md

Co-authored-by: David Luzar <5153846+dwelle@users.noreply.github.com>

---------

Co-authored-by: David Luzar <5153846+dwelle@users.noreply.github.com>
2024-02-01 12:26:55 +00:00
1741c234a6 fix: decouple container cache logic to containerCache. (#7637) 2024-01-31 21:17:41 +05:30
63b50b3586 fix: don't bundle react-dom when importing from transformHandles (#7634)
* fix: don't bundle react when importing from transfromHandles

* rename to DEFAULT_TRANSFORM_HANDLE_SPACING
2024-01-31 16:50:35 +05:30
e0fefa8025 fix: don't bundle react-dom when importing from element (#7635) 2024-01-31 16:43:37 +05:30
d426cc968d refactor: remove portal as it is no longer needed (#7623)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-01-29 16:37:09 +01:00
2409c091ff feat: support roundness for images (#7558)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-01-29 15:27:07 +01:00
626fe252ab fix: frame name field (#7457)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-01-29 10:57:22 +01:00
10bd08ef19 fix: make getBoundTextElement and related helpers pure (#7601)
* fix: make getBoundTextElement pure

* updating args

* fix

* pass boundTextElement to getBoundTextMaxWidth

* fix labelled arrows

* lint

* pass elementsMap to removeElementsFromFrame

* pass elementsMap to getMaximumGroups, alignElements and distributeElements

* lint

* pass allElementsMap to renderElement

* lint

* feat: make more typesafe

* fix: remove unnecessary assertion

* fix: remove unused params

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-01-26 11:29:07 +05:30
2789d08154 docs: update the docs for next js integration (#7605)
* docs: update the docs for next js integration

* update

* update

* update docs with tabbed examples

* fix
2024-01-25 20:26:48 +05:30
678bb2b819 build(deps-dev): bump vite from 5.0.6 to 5.0.12 (#7586)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.0.6 to 5.0.12.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.0.12/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.0.12/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-24 19:29:50 +05:30
966f9aead9 build(deps-dev): bump vite from 5.0.6 to 5.0.12 in /examples/excalidraw/with-script-in-browser (#7603)
build(deps-dev): bump vite

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.0.6 to 5.0.12.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.0.12/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.0.12/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-24 19:28:11 +05:30
4f0a2a9593 docs: add next js with app router example (#7552)
* move the existing example to with-script-in-browser

* Add example with next js app router

* disable ssr for excalidraw client comp

* typo

* update output dir

* don't include nextjs example in tsconfig

* remove meta.json

* lint

* remove example.ts

* port

* move the examples outside packages and use the deps as workspaces in examples

* update gitignore

* fix example

* update path of build dir

* fix

* fix scripts

* try local path

* fix

* update commands

* fix

* fix

* fix script

* skip ts

* disable ts

* add vercel.json

* install

* update tsconfig

* fix lint

* remove console.log

* lets see if this works

* revert

* remove ts nocheck

* add types and some utils in nextjs example

* fix types

* updatw example and remove nextjs dynamic syntax so we don't import excal twice

* move both examples to workspaces and create generic example to be used by browser and next js both

* copy the static assets to nextjs

* fix ts config

* render custom menu items

* fix custom footer

* fix types in browser example

* use regular imports for importing excal and import it using dynamic next js in app router instead

* Add example for pages router

* fix css discrepancies

* fix css

* configure output dir

* fix

* fix css

* rename to with-nextjs

* move components to examples/excalidraw/components
2024-01-24 17:07:54 +05:30
f3f8217125 docs: toggleSidebar api fix (#7575) 2024-01-23 14:50:51 +00:00
89bd6181f2 fix: revert mapElementIds flag removal (#7594) 2024-01-22 17:23:00 +01:00
c6fdac131b ci: add the workspace ignore check to install actions as dependency for auto release (#7593) 2024-01-22 17:01:00 +05:30
0415c616b1 refactor: decoupling global Scene state part-1 (#7577) 2024-01-22 00:23:02 +01:00
740a165452 fix: filter out elements not overlapping frame on paste (#7591) 2024-01-21 20:55:57 +01:00
4997624a3a fix: frame name editing inconvenience (#7437) 2024-01-21 20:55:28 +01:00
b66daae1f3 fix: Truncate collaborator name in dropdown. (#7576) 2024-01-21 20:36:09 +01:00
1e7df58b5b feat: add pasted elements to frame under cursor (#7590) 2024-01-21 14:01:43 +01:00
46da032626 fix: exporting frame-overlapping elements belonging to other frames (#7584) 2024-01-19 14:41:22 +01:00
3b0593baa7 fix: Prevent the library label from being collapsed (#7579) 2024-01-19 14:41:08 +01:00
dd530737a2 docs: fix "canvas actions" link in Props page (#7536)
fix "canvas actions" link in Props page
2024-01-17 16:19:42 +05:30
0f99e823f4 Merge branch 'master' into arnost/scroll-in-read-only-links
# Conflicts:
#	packages/excalidraw/appState.ts
#	packages/excalidraw/components/App.tsx
#	packages/excalidraw/element/textWysiwyg.test.tsx
#	packages/excalidraw/scene/scrollConstraints.ts
#	packages/excalidraw/scene/types.ts
#	packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap
#	packages/excalidraw/tests/__snapshots__/dragCreate.test.tsx.snap
#	packages/excalidraw/tests/__snapshots__/move.test.tsx.snap
#	packages/excalidraw/tests/__snapshots__/multiPointCreate.test.tsx.snap
#	packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap
#	packages/excalidraw/tests/__snapshots__/selection.test.tsx.snap
#	packages/excalidraw/tests/linearElementEditor.test.tsx
#	packages/excalidraw/types.ts
#	packages/utils/export.ts
2024-01-15 10:37:52 +01:00
a4e5e46dd1 fix: move default to last so its compatible with nextjs (#7561) 2024-01-15 14:52:04 +05:30
0fa5f5de4c fix: translating frames containing grouped text containers (#7557) 2024-01-13 21:28:54 +01:00
41cc746885 fix: host font assets from root (#7548) 2024-01-11 21:29:29 +01:00
8ead8559e0 feat: redirect font requests to cdn (#7549) 2024-01-11 21:08:17 +01:00
5245276409 feat: erase groups atomically (#7545) 2024-01-11 17:43:04 +01:00
0c24a7042f feat: remove ExcalidrawEmbeddableElement.validated flag (#7539) 2024-01-11 17:42:51 +01:00
Are
86cfeb714c feat: add eraser tool trail (#7511)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-01-11 16:10:15 +00:00
872973f145 fix: do not modify elements while erasing (#7531) 2024-01-11 16:00:07 +01:00
3ecf72a507 docs: add changelog for ESM build (#7542)
* docs: add changelog for ESM build

* move to breaking change
2024-01-11 16:40:45 +05:30
1aaa400876 docs: fix extra space in UIOptions/tools (#7537)
fix typo in UIOptions/tools
2024-01-11 11:09:33 +00:00
65047cc2cb fix: decouple react and react-dom imports from utils and make it treeshakeable (#7527)
fix: decouple react and react-dom imports from utils and make it tree-shakeable
2024-01-08 21:01:47 +05:30
8b993d409e feat: render embeds lazily (#7519) 2024-01-04 19:03:04 +01:00
1cb350b2aa feat: update X brand logo & tweak labels (#7518) 2024-01-04 14:57:31 +01:00
43ccc875fb feat: support multi-embed pasting & x.com domain (#7516) 2024-01-04 13:27:52 +01:00
4249b7dec8 chore: add version for excalidraw-app workspace (#7514) 2024-01-04 13:53:19 +05:30
49f15c736b chore: remove unused files (#7509)
chore remove unused files
2024-01-03 16:25:36 +05:30
a8064ba3ee build: Welcome ESM and Bye Bye UMD (#7441)
* build: Welcome ESM and Bye Bye UMD

* remove package

* create unbundled esm build

* update script for example

* fix typo

* dummy commit

* update autorelease script to build esm

* revert dummy commit

* move react, react-dom and testing library to dev dependencies

* remove entry.js, publicPath and yarn install:deps script

* fix

* upgrade esbuild to fix glob import error for locales

* remove webpack chunk names as thats not needed anymore

* marking the code sideeffects free

* make the library tree-shakeable and move fonts to fonts directory

* allow side effects for css, scss files

* remove tree-shaking

* comment code for tree shaking

* move to vite for example

* bye bye webpack

* ignore ts

* separate build and output dir

* use esbuild for creating bundle for example

* update output dir

* lint

* create browser dev build with source maps and prod with minification

* add dev and prod builds for bundler

* lint

* update script

* remove await

* load prod build

* create minified build in dist

* prod and dev builds using export field

* remove import.meta

* dummy

* define import.meta prod and dev

* fix

* export types

* add types field

* typo

* lint

* Update scripts/buildPackage.js

* move types inside export

* newline
2024-01-01 20:18:44 +05:30
e6c3c06c2e feat: support pen erasing (#7496) 2024-01-01 13:27:03 +01:00
d19b51d4f8 fix: drawing-tablet stylus touch events being prevented (#7494) 2023-12-30 15:00:12 +01:00
c72e853c85 refactor: editor events sub/unsub refactor (#7483) 2023-12-30 11:12:38 +01:00
5f40a4cad4 fix: missing cross-env from build:umd in package.json (#7460) 2023-12-19 00:02:03 +01:00
d91c98b82e fix: incorrect types in ActionNavigate (#7462) 2023-12-18 21:14:30 +01:00
57ea4e61d1 fix: mixing clientId & socketId in UserList (#7461) 2023-12-18 18:21:57 +01:00
0808532b49 fix: follow mode collaborator status indicator (#7459) 2023-12-18 16:14:25 +01:00
2a0fe2584e fix: empty snapLines arrays would cause re-render (#7454)
Co-authored-by: Lynda Lin <lynda.lin@optoma.com>
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2023-12-18 12:42:17 +00:00
7bd6496854 refactor: Fix Typo (#7445) 2023-12-16 18:23:11 +00:00
537f6e7f68 docs: add steps for local development (#7449)
* docs: add steps for local development #7434

* docs: minor tweaks

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2023-12-16 19:18:35 +01:00
6dfa89e846 fix: emitted visible scene bounds not accounting for offsets (#7450) 2023-12-16 17:32:54 +01:00
561e919a2e fix: import Socket as type (#7446) 2023-12-16 11:15:04 +01:00
20e3acf7a6 feat: bump socket.io-client & collab tweaks (#7444) 2023-12-16 00:23:59 +01:00
2c0929e537 fix: follow-mode tweaks (#7443) 2023-12-15 15:16:25 +01:00
aad8ab0123 feat: follow mode (#6848)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2023-12-15 00:07:11 +01:00
88a2b286c7 feat: move utils to utils package and make @excalidraw/utils a workspace (#7432)
* feat: move utils to utils package and make @excalidraw/utils a workspace

* remove esm and update types path

* remove esm script

* fix package.json and yarn.lock

* update path

* fix

* fix lint and test
2023-12-13 21:51:27 +05:30
b635b10b59 chore: Update translations from Crowdin (#7176)
* New translations en.json (Azerbaijani)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

* New translations en.json (Chinese Traditional, Hong Kong)

* New translations en.json (Sinhala)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Occitan)

* New translations en.json (Kabyle)

* New translations en.json (Karakalpak)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Simplified)

* Auto commit: Calculate translation coverage

* New translations en.json (Marathi)

* New translations en.json (Hindi)

* Auto commit: Calculate translation coverage

* New translations en.json (Marathi)

* New translations en.json (Hindi)

* Auto commit: Calculate translation coverage

* New translations en.json (German)

* New translations en.json (Slovenian)

* Auto commit: Calculate translation coverage

* New translations en.json (Korean)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Traditional)

* Auto commit: Calculate translation coverage

* New translations en.json (Russian)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* New translations en.json (Spanish)

* Auto commit: Calculate translation coverage

* New translations en.json (Arabic)

* New translations en.json (Thai)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Bulgarian)

* New translations en.json (Catalan)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Basque)

* New translations en.json (Finnish)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Kurdish)

* New translations en.json (Lithuanian)

* New translations en.json (Dutch)

* New translations en.json (Punjabi)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Slovak)

* New translations en.json (Slovenian)

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Vietnamese)

* New translations en.json (Galician)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Indonesian)

* New translations en.json (Persian)

* New translations en.json (Khmer)

* New translations en.json (Tamil)

* New translations en.json (Bengali)

* New translations en.json (Marathi)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Kazakh)

* New translations en.json (Latvian)

* New translations en.json (Azerbaijani)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

* New translations en.json (Chinese Traditional, Hong Kong)

* New translations en.json (Sinhala)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Occitan)

* New translations en.json (Kabyle)

* New translations en.json (Karakalpak)

* Auto commit: Calculate translation coverage

* New translations en.json (Slovenian)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Simplified)

* Auto commit: Calculate translation coverage

* New translations en.json (German)

* Auto commit: Calculate translation coverage

* New translations en.json (Russian)

* Auto commit: Calculate translation coverage

* New translations en.json (Polish)

* New translations en.json (Korean)

* Auto commit: Calculate translation coverage

* New translations en.json (Swedish)

* Auto commit: Calculate translation coverage

* New translations en.json (Swedish)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Simplified)

* New translations en.json (Catalan)

* Auto commit: Calculate translation coverage

* New translations en.json (Basque)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Traditional)

* Auto commit: Calculate translation coverage

* New translations en.json (Spanish)

* Auto commit: Calculate translation coverage

* New translations en.json (Arabic)

* New translations en.json (Thai)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Bulgarian)

* New translations en.json (Catalan)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Basque)

* New translations en.json (Finnish)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Kurdish)

* New translations en.json (Lithuanian)

* New translations en.json (Dutch)

* New translations en.json (Punjabi)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Slovak)

* New translations en.json (Slovenian)

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Vietnamese)

* New translations en.json (Galician)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Indonesian)

* New translations en.json (Persian)

* New translations en.json (Khmer)

* New translations en.json (Tamil)

* New translations en.json (Bengali)

* New translations en.json (Marathi)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Kazakh)

* New translations en.json (Latvian)

* New translations en.json (Azerbaijani)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

* New translations en.json (Chinese Traditional, Hong Kong)

* New translations en.json (Sinhala)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Occitan)

* New translations en.json (Kabyle)

* New translations en.json (Karakalpak)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* New translations en.json (Spanish)

* Auto commit: Calculate translation coverage

* New translations en.json (Slovenian)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Traditional)

* Auto commit: Calculate translation coverage

* New translations en.json (Swedish)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* Auto commit: Calculate translation coverage

* New translations en.json (German)

* Auto commit: Calculate translation coverage

* New translations en.json (Danish)

* Auto commit: Calculate translation coverage

* New translations en.json (Italian)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Simplified)

* Auto commit: Calculate translation coverage

* New translations en.json (Korean)

* Auto commit: Calculate translation coverage

* New translations en.json (Polish)

* New translations en.json (Slovak)

* Auto commit: Calculate translation coverage

* New translations en.json (Karakalpak)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Arabic)

* New translations en.json (Bulgarian)

* New translations en.json (Catalan)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Basque)

* New translations en.json (Finnish)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Kurdish)

* New translations en.json (Lithuanian)

* New translations en.json (Dutch)

* New translations en.json (Punjabi)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Slovak)

* New translations en.json (Slovenian)

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Vietnamese)

* New translations en.json (Galician)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Indonesian)

* New translations en.json (Persian)

* New translations en.json (Khmer)

* New translations en.json (Tamil)

* New translations en.json (Bengali)

* New translations en.json (Marathi)

* New translations en.json (Thai)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Kazakh)

* New translations en.json (Latvian)

* New translations en.json (Azerbaijani)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

* New translations en.json (Chinese Traditional, Hong Kong)

* New translations en.json (Sinhala)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Occitan)

* New translations en.json (Kabyle)

* New translations en.json (Karakalpak)

* New translations en.json (Swedish)

* New translations en.json (Romanian)

* remove packages

---------

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2023-12-12 16:56:22 +05:30
7ebda02b81 fix: update path of files in docs (#7428)
* fix: update path of files in docs

* remove root yarn install in size limit

* add vercel.json in dev-docs

* update config

* fix lint

* indent

* revert changelog and readme
2023-12-12 14:28:34 +05:30
d6cd8b78f1 build: decouple package deps and introduce yarn workspaces (#7415)
* feat: decouple package deps and introduce yarn workspaces

* update root directory

* fix

* fix scripts

* fix lint

* update path in scripts

* remove yarn.lock files from packages

* ignore workspace

* dummy

* dummy

* remove comment check

* revert workflow changes

* ignore ws when installing gh actions

* remove log

* update path

* fix

* fix typo
2023-12-12 11:32:51 +05:30
b7d7ccc929 fix: env variable for text-to-diagram and use frozen lock file when install deps in excalidraw-app (#7409) 2023-12-07 19:32:19 +05:30
f14ad61bd0 build: move build process and excalidraw-app dependencies in its own package.json (#7021)
* build: move build process and excalidraw-app dependencies in its own package.json

* fix

* fix public path

* move bug-issue-template to excalidraw-app

* make env vars accessible in excalidraw app

* update build script

* install when building

* add ts ignore

* fix build-version script

* update config in vercel.json

* add vercel config for example

* fix vercel config

* update install script in vercel

* update install script in lint.yml

* update install script in test workflows

* push locales to locales folder pwa

* add favicons to manifest

* move react to peer deps in editor

* fix ts

* Enable vite intellisense

* add global.d.ts for excalidraw-app

* remove console.log

* remove react, react-dom and vite from excalidraw-app deps

* increase size limit
2023-12-07 16:39:11 +05:30
8963baf5ad chore: upgrade to vite 5.x and vitest 1.x (#7407)
* chore: upgrade to vite 5.x and vitest 1.x

* fix coverage

* move to ESM for vite config

* use ESM for vitest
2023-12-07 15:30:08 +05:30
557add5bf7 feat: Support Mermaid Class diagrams 🥳 (#7381)
* feat: support mermaid class diagrams

* upgrade mermaid-to-excalidraw

* upgrade mermaid-to-excalidraw

* add sequence diagrams in supported chart types

* upgrade mermaid-to-excalidraw

* update i18n
2023-12-06 21:31:54 +05:30
b9cfbc2077 feat: add support for more UML arrowheads (#7391) 2023-12-06 16:00:00 +01:00
a04cc707c3 build(deps-dev): bump vite from 4.4.2 to 4.4.12 (#7393)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.4.2 to 4.4.12.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v4.4.12/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.4.12/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-06 15:31:44 +05:30
72ea8022bf docs: changelog instruction removed from docs (#7395)
changelog instruction removed from docs
2023-12-06 11:36:39 +05:30
4bdeaf999b feat: TTD dialog UI tweaks (#7384) 2023-12-04 17:50:30 +01:00
42d8c5a040 chore: update changelog and package.json for v0.17.1 (#7351) 2023-11-28 19:12:39 +05:30
f299514e44 fix: umd build so it can be used in browser (#7349)
* fix: umd build so it can be used in browser

* fix lint

* increase size limit

* update changelog

* use json.stringify for env preact variable so its accessible as string

* update changelog
2023-11-28 18:11:16 +05:30
dd220bcaea feat: TTD dialog tweaks (#7346)
* tweaks to TTD dialog ~ prepping for settings dialog

* tweaks to ttd parsing & error logging
2023-11-27 16:03:03 +01:00
fe75f29c15 fix: disable caching bounds for arrow labels (#7343) 2023-11-25 23:32:05 +01:00
14845a343b feat: text-to-diagram (#7325)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2023-11-25 21:11:03 +00:00
dd8a7d41e2 fix: bounds cached prematurely resulting in incorrectly rendered labels (#7339) 2023-11-24 19:55:56 +01:00
fda5c6fdf7 fix: t2c settings dialog spacing for apps that use CSS resets (#7337) 2023-11-24 16:32:00 +01:00
3d1631f375 feat: d2c tweaks (#7336) 2023-11-24 14:02:11 +01:00
c7ee46e7f8 feat: wireframe-to-code (#7334) 2023-11-23 23:07:53 +01:00
d1e4421823 feat: Expose ActionManager.registerAction through ExcalidrawImperativeAPI (#6995)
* feat: Expose `ActionManager` through `ExcalidrawImperativeAPI`

* Only expose `registerAction` instead of `ActionManager`
2023-11-22 15:22:49 -06:00
7c9cf30909 fix: make zoomToFit fitToViewport account for sidebar (#7298) 2023-11-17 15:56:19 +01:00
1e37dbd60e feat: change frame resizing behavior (#7307) 2023-11-17 14:37:43 +01:00
f8d5c2a1b6 build: allow a range of major node versions (#7306) 2023-11-17 14:23:19 +01:00
23b24ea5c3 build: use caret for specifying node version to avoid major upgrades automatically (#7297) 2023-11-16 16:18:38 +05:30
a528769b68 docs: upgrade to @excalidraw/excalidraw@0.17.0 (#7285) 2023-11-14 20:10:19 +05:30
ddb7585057 docs: Docs for v0.17.0 🚀 (#7248)
* feat: add docs for getCommonBounds

* docs: add docs for frames api support

* docs: update docs for regenerateIds opts in convertToExcalidrawElements

* add docs for ref removal

* add docs for lock support and insertOnCanvasDirectly in setActiveTool

* fix broken links

* update docs for next js support

* update docs for Preact

* add faq

* docs: add `onChange`, `onPointerDown`, `onPointerUp` docs

* docs: update `useDevice` docs

* update docs for disabling image tool

* add docs for withinBounds helpers

* fix lint

* upgrade excal

* add docusaurus2-dotenv for expose env vars

* fix env variable and upgrade excal

* Update dev-docs/docs/@excalidraw/excalidraw/api/excalidraw-element-skeleton.mdx

Co-authored-by: David Luzar <5153846+dwelle@users.noreply.github.com>

* update docs

Co-authored-by: David Luzar <5153846+dwelle@users.noreply.github.com>

* update docs for process.env

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2023-11-14 19:54:34 +05:30
111a48ffb1 docs: release @excalidraw/excalidraw@0.17.0 🎉 (#7284) 2023-11-14 19:53:59 +05:30
54153629c0 chore: update release scripts (#7282)
* chore: update release scripts

* update docs
2023-11-14 16:37:57 +05:30
9c425224c7 feat: support disabling image tool (#6320)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2023-11-14 10:25:41 +01:00
9d1d45a8ea chore: update changelog (#7279)
* chore: update changelog

* fix

* Update CHANGELOG.md
2023-11-14 13:11:05 +05:30
029c3c48ba fix: image insertion bugs (#7278) 2023-11-13 15:34:59 +01:00
adfd95be33 build: support preact 🥳 (#7255)
* build: support preact

* add log

* Simplify the config and generate prod and dev builds for preact

* update changelog

* remove logs

* use env variable so its available during build time

* update cl

* fix
2023-11-13 16:18:36 +05:30
ceb255e8ee fix: exportToSvg to honor frameRendering also for name not only for frame itself (#7270)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2023-11-12 22:34:05 +00:00
ae5b9a4ffd fix: not cloning elements on export polluting Scene mapping (#7276) 2023-11-12 23:32:12 +01:00
3d4ff59f40 fix: Can't toggle penMode off due to missing typecheck in togglePenMode (#7273)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2023-11-12 13:24:13 +01:00
7b00089314 chore: bump @excalidraw/random-username (#7272) 2023-11-11 19:23:22 +01:00
af6b81df40 fix: Replace hard coded font family with const value in addFrameLabelsAsTextElements (#7269) 2023-11-11 10:04:02 +01:00
02cc8440c4 feat: allow D&D dice app domain for embeds (#7263)
Co-authored-by: David Luzar <5153846+dwelle@users.noreply.github.com>
2023-11-10 15:29:19 +00:00
6363492cee fix: perf issue when ungrouping elements within frame (#7265)
Co-authored-by: Ryan Di <ryan.weihao.di@gmail.com>
2023-11-10 16:13:08 +01:00
900b317bf3 feat: remove full screen shortcut (#7222) 2023-11-10 14:44:02 +00:00
68179356e6 fix: Fixes the shortcut collision between "toggleHandTool" and "distributeHorizontally" (#7189)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2023-11-10 15:33:02 +01:00
3ed15e95da Small typo fix frames.mdx (#7216) 2023-11-10 15:23:43 +01:00
798e1fd858 fix: allow pointer events when editing a linear element (#7238) 2023-11-10 15:21:59 +01:00
f66c93633c feat: make adaptive-roughness less aggressive (#7250) 2023-11-10 13:32:34 +01:00
cee00767df feat: support excalidrawAPI and remove refs support (#7251)
* feat: support excalidrawAPI and remove refs support

* update changelog

* remove ready and readyPromise

* update changelog

* update changelog
2023-11-10 15:33:43 +05:30
864c0b3ea8 feat: render frames on export (#7210) 2023-11-09 17:00:21 +01:00
a9a6f8eafb docs: update the docs with next js dynamic import support (#7252) 2023-11-09 16:03:35 +05:30
3c96943db3 test: fix mermaid test flake (#7249) 2023-11-07 18:06:15 +01:00
9006caff39 fix: make modal use viewport breakpoints (#7246) 2023-11-07 10:10:12 +01:00
ce7a847668 feat: export getCommonBounds util (#7247)
* feat: export getCommonBounds util

* add pr link

* fix
2023-11-07 14:19:13 +05:30
b1037b342d feat: make device breakpoints more specific (#7243) 2023-11-06 16:29:00 +01:00
18a7b97515 chore: Fix typo in comment in LocalData file (#7235) 2023-11-04 18:15:09 +01:00
e8def8da8d feat: Support mermaid flowchart and sequence diagrams to excalidraw diagrams 🥳 (#6920)
* feat: integrate mermaidToExcalidraw

* create mermaid to excal dialog

* allow mermaid syntax and export in preview

* fix

* fix webpack config

* fix markdown error by using named export

* center preview

* set elements as selected when inserted onto canvas

* persist mermaid data to storage

* store canvas data in refs

* load mermaid lazily

* tweak design

* compute width, height correctly for arrows

* fix undefined vertex issue

* add mermaid icon in dropdown

* add a note in dialog

* reset preview when error

* show error in preview when error

* show mermaid error messgae react way

* design tweaks

* add example and docs link

* fix

* tweak design to remove scroll bar

* show a spinner unless mermaid loaded

* regenerate ids when needed via programmatic api, this makes sure for mermaid diagrams ids are regenerated

* tweak

* add option to transform viewport to scene coords in transform api

* make opts optional and use 100% zoom when inserting to canvas

* fix arrow bindings in safari and firefox

* fix elements insert position and viewport centering

* fix: Update start/end points by 0.5 so bindings don't overlap with start/end bound element coordinates.

* defer rendering the preview

* tweak text

* fix tests

* remove only

* make design responsive

* fix: show extra tools dropdown in mobile

* fix mobile css

* width auto

* upgrade mermaid-to-excalidraw

* don't pass appState in deps as its not used

* upgrade mermaid-to-excalidraw to fix firefox issue

* use types from mermaid-to-excalidraw

* upgrade mermaid-to-excalidraw

* use stable version of mermaid-to-excalidraw

* upgrade mermaid-to-excalidraw

* fix width of shapes toolbar for smaller screen size and also fix regression of mobile menu

* use i18n

* better api

* enable test coverage in ui

* Add tests

* use common utils to update and get text editor

* updgrade mermaid-to-excalidraw to support sequence diagrams

* fix test

* don't update arrow container height anytime in when redrawing text bounding box

* increase size limit

* increase size limit of vendor to 900kb

* use openDialog for mermaid

* upgrade mermaid-to-excalidraw

* update frame id post generation

* upgrade mermaid-to-excalidraw to add entity codes support

* update size limit

* upgrade mermaid-to-excalidraw package with frame api changes

* upgrade mermaid-to-excalidraw to remove directive and use config

* don't highlight mermaid tool and remove unused api setSelection

* stop using loading state to update text area

* move some styling to scss

* review fixes

* use modifiedTableIcon props and remove stale snap

* css

* dialog css

* fix snap

* use dialog border

* change mermaidToExcalidrawLib to state

* better styling of errors

* make modal bigger

* fix mobile

* update snaps

* fix icon color

* fix dark mode insert button color

* horizontally center spinner

* render canvas conditionally on loaded state

* rd tweaks

* tweak class names

* remove max height

* typo in example

* upgrade mermaid-to-excalidraw

* simplify error state

* fix height & overflow on vertical breakpoint

* fix lint

* show errors in overlay

* set textarea font family

* reduce opacity

* update snap

* upgrade to mermaid  0.1.2

---------

Co-authored-by: dwelle <luzar.david@gmail.com>
2023-11-03 17:41:34 +05:30
a7db41c5ba fix: align input :hover/:focus with spec (#7225) 2023-11-02 16:06:26 +01:00
d8166d9e1d fix: dialog remounting on className updates (#7224) 2023-11-02 16:06:15 +01:00
81c0259041 docs: add npm downloads rate badge to README.md file (#7127) 2023-11-01 13:27:57 +01:00
f5c91c3a0f feat: support frames via programmatic API (#7205)
* update frame id post generation

* support frames via programmatic API

* fix types

* add test for frames

* throw error when element doesn't exist

* naming tweaks

* update the api to use children

* consider max of frame dimensions and calculated bounds of elements

* consider bound elements in frame api
2023-11-01 17:14:04 +05:30
9b8de8a12e test: disable flaky test (#7213) 2023-10-31 12:05:08 +01:00
ea677d4581 feat: make clipboard more robust and reintroduce contextmenu actions (#7198) 2023-10-28 19:29:28 +00:00
ec2de7205f fix: don't update label position when dragging labelled arrows (#6891)
* fix: don't update label position when dragging labelled arrows

* lint

* add test

* don't update coords for label when labelled arrow inside frame

* increase locales bundle size limit
2023-10-27 12:06:11 +05:30
Are
d5e3f436dc feat: add approximate elements in bbox detection (#6727)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-26 23:33:00 +02:00
dcf4592e79 feat: regenerate ids by default when using transform api and also update bindings by 0.5px to avoid possible overlapping (#7195)
* feat: regenerate ids by default when using transform api and also update bindings by 0.5px to avoid possible overlapping

* type

* increase limit as some past PR(s) increased the bundle size

* review fixes

* update changelog
2023-10-27 00:43:48 +05:30
d1f8eec174 feat: support giphy.com embed domain (#7192) 2023-10-26 00:00:50 +02:00
0f81c30276 fix: frame add/remove/z-index ordering changes (#7194) 2023-10-25 23:16:02 +02:00
f098789d16 fix: element relative position when dragging multiple elements on grid (#7107)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-25 22:48:03 +02:00
f794b0bb90 fix: freedraw non-solid bg hitbox not working (#7193) 2023-10-25 17:21:01 +02:00
104f64f1dc revert: remove bound-arrows from frames (#7190) 2023-10-25 10:39:19 +02:00
71ad3c5356 fix: Actions panel ux improvement (#6850)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-24 18:36:13 +00:00
afea0df141 feat: renderer tweaks (#6698) 2023-10-20 17:45:37 +02:00
d2a508104e fix: Better fill rendering with latest RoughJS (#7031)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-20 15:08:24 +02:00
3697618266 feat: support props.locked for setActiveTool (#7153)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2023-10-20 13:16:23 +02:00
e7cc2337ea feat: add onChange, onPointerDown, onPointerUp api subs (#7154) 2023-10-20 13:08:22 +02:00
9eb89f9960 build(deps): bump @babel/traverse from 7.18.9 to 7.23.2 in /dev-docs (#7165)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-20 11:31:27 +02:00
ab1bcc7615 chore: Update translations from Crowdin (#6695) 2023-10-20 11:29:28 +02:00
b1cac35269 feat: Closing of "Save to.." Dialog on Save To Disk (#7168)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-19 17:51:50 +00:00
83f86e2b86 fix: Fix for Strange Symbol Appearing on Canvas after Deleting Grouped Graphics (Issue #7116) (#7170)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-19 12:59:39 +02:00
7e38cab76e build(deps): bump @babel/traverse from 7.21.4 to 7.23.2 (#7171)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-19 12:33:16 +02:00
2cabb1f1f4 fix: attempt to fix flake in wysiwyg tests (#7173) 2023-10-19 12:32:31 +02:00
63650f82d1 feat: Added Copy/Paste from Google Docs (#7136)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-19 12:14:23 +02:00
dde3dac931 feat: remove bound-arrows from frames (#7157) 2023-10-17 18:18:20 +02:00
5b94cffc74 fix: ensure ClipboardItem created in the same tick to fix safari (#7066) 2023-10-16 11:38:57 +02:00
aaf73c8ff3 fix: double image dialog shown on insert (#7152) 2023-10-16 00:19:46 +02:00
44d9d5fcac fix: wysiwyg left in undefined state on reload (#7123) 2023-10-13 14:29:54 +02:00
89a3bbddb7 test: add more resizing tests (#7028)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-12 20:59:02 +02:00
b86184a849 fix: ensure relative z-index of elements added to frame is retained (#7134) 2023-10-12 15:00:23 +02:00
b552166924 feat: new dark mode theme & light theme tweaks (#7104)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-12 14:58:33 +02:00
26ff3993bb feat: better laser cursor for dark mode (#7132) 2023-10-11 11:17:27 +02:00
7ad02c359a fix: memoize static canvas on props.renderConfig (#7131) 2023-10-10 23:31:23 +02:00
2523fe82e3 feat: laser pointer improvements (#7128) 2023-10-10 13:55:55 +02:00
4ea079eb85 fix: regression from #6739 preventing redirect link in view mode (#7120)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-09 12:26:49 +02:00
f20ba90ffa perf: improve element in frame check (#7124) 2023-10-09 16:32:27 +08:00
03da9112cf fix: update links to excalidraw-app (#7072) 2023-10-08 19:37:17 -05:00
a249f332a2 fix: ensure we do not stop laser update prematurely (#7100) 2023-10-06 12:00:35 +02:00
Are
2e61926a6b feat: initial Laser Pointer MVP (#6739)
* feat: initial Laser pointer mvp

* feat: add laser-pointer package and integrate it with collab

* chore: fix yarn.lock

* feat: update laser-pointer package, prevent panning from showing

* feat: add laser pointer tool button when collaborating, migrate to official package

* feat: reduce laser tool button size

* update icon

* fix icon & rotate

* fix: lock zoom level

* fix icon

* add `selected` state, simplify and reduce api

* set up pointer callbacks in viewMode if laser tool active

* highlight extra-tools button if one of the nested tools active

* add shortcut to laser pointer

* feat: don't update paths if nothing changed

* ensure we reset flag if no rAF scheduled

* move `lastUpdate` to instance to optimize

* return early

* factor out into constants and add doc

* skip iteration instead of exit

* fix naming

* feat: remove testing variable on window

* destroy on editor unmount

* fix incorrectly resetting `lastUpdate` in `stop()`

---------

Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-05 17:05:16 +02:00
e921bfb1ae feat: Export iconFillColor() (#6996) 2023-10-04 18:17:22 -05:00
e6f74350ac refactor: DRY out tool typing (#7086) 2023-10-04 23:39:00 +02:00
fa33aa08ab refactor: refactor event globals to differentiate from lastPointerUp (#7084) 2023-10-04 16:18:22 +02:00
8b838049df fix: remove invisible elements safely (#7083) 2023-10-04 16:09:59 +02:00
1f4f5e11ae refactor: DRY out and simplify setting active tool from toolbar (#7079) 2023-10-04 00:16:54 +02:00
12420592ef feat: support menu / dropdown items to have selected state (#7078) 2023-10-03 23:35:47 +02:00
bfd318e765 docs: Update the excalidraw-app source-code link in README.md (#7035)
chore: Update the `excalidraw-app` source-code link in README.md
2023-10-03 08:41:13 -05:00
6a821f3b76 fix: Icon size in manifest (#7073) 2023-10-03 11:07:02 +02:00
84fd13e872 docs: fix minor grammar and spellings (#7039) 2023-10-02 10:11:02 +02:00
7d2b6f3374 docs: fix typo on homepage of developer docs (#7047) 2023-09-29 20:52:53 -05:00
ceb637f5ea fix: elements being dropped/duplicated when added to frame (#7057) 2023-09-29 15:40:14 +02:00
4c35eba72d feat: element alignments - snapping (#6256)
Co-authored-by: Ryan Di <ryan.weihao.di@gmail.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-09-28 16:28:08 +02:00
4765f5536e fix: frame name not editable on dbl-click (#7037) 2023-09-25 16:54:23 +02:00
556175558a fix: polyfill Element.replaceChildren (#7034) 2023-09-24 19:07:35 +02:00
4db73a7f95 docs: release @excalidraw/excalidraw@0.16.1 🎉 (#7020) 2023-09-21 10:28:21 +05:30
f8b3692262 fix: more eye-droper fixes (#7019) 2023-09-21 09:54:03 +05:30
741d5f1a18 refactor: move excalidraw-app outside src (#6987)
* refactor: move excalidraw-app outside src

* move some tests to excal app and fix some

* fix tests

* fix

* port remaining tests

* fix

* update snap

* move tests inside test folder

* fix

* fix
2023-09-21 09:28:48 +05:30
3ec09988fa Merge branch 'master' of github.com:excalidraw/excalidraw into arnost/scroll-in-read-only-links 2023-09-20 15:38:30 +02:00
0a588a880b docs: release @excalidraw/excalidraw@0.16.0 🎉 (#6993) 2023-09-19 19:59:53 +05:30
3d617958cc fix: improperly disabling UI pointer-events on canvas interaction (#7005)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2023-09-19 16:01:40 +02:00
99dbc0acb9 docs: Add docs for Excalidraw Element Skeleton (#6879)
* docs: Add docs for Excalidraw Element Skeleton

* fix

* upgrade package

* tweaks

* fix

* tweak

* Update dev-docs/docs/@excalidraw/excalidraw/api/excalidraw-element-skeleton.mdx

Co-authored-by: David Luzar <luzar.david@gmail.com>

* fix

---------

Co-authored-by: David Luzar <luzar.david@gmail.com>
2023-09-19 18:28:53 +05:30
4b11f43117 feat: zen-mode/go-to-plus button style tweaks (#7006) 2023-09-19 14:20:59 +02:00
e3f4f567b8 feat: holding down CMD/CTRL will disable snap to grid when grid is active (#6983)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-09-18 17:10:28 +02:00
b40fd65404 feat: fix overscroll animation trigger when zoomed in 2023-09-18 15:00:52 +02:00
eb020d0410 fix: generic element's labels not flipping with them (#6967) 2023-09-17 13:26:02 +02:00
c1952fd6cc fix: several eyeDropper fixes (#7002) 2023-09-17 13:24:50 +02:00
1f94f204dd fix: isBindableElement to affirm frames (#6900)
fix isBindableElement to affirm frames
2023-09-15 16:15:06 -05:00
a34216f9fc docs: new Sidebar API (#6976)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2023-09-15 13:03:23 +00:00
c9efb12e5b fix: use device.isMobile for sidebar trigger label breakpoint (#6994) 2023-09-15 12:08:51 +00:00
266069ae05 test: update snapshots 2023-09-14 23:26:16 +02:00
c33fb846ab chore: cleanup 2023-09-14 23:15:57 +02:00
94e9b20951 fix: prevent jitter animation on pinch to zoom and on scroll event 2023-09-14 12:07:30 +02:00
d73cd14dfb docs: add mermaid docs (#6971)
* docs: add mermaid docs

* fix link

* add development.mdx

* add codebase

* add parseEdge

* add subgraph

* convertors

* tweaks

* structure the codebase

* add docs for new diagram type

* decouple docs for flowchart parser

* fix broken links

* use diagram instead of chart

* revert package.json

* tweaks

* point root folder of mermaid-to-excalidraw to installation

* remove installation from sidebar children

* fix link

* update flowchart parser diagram

* update parser overview diagram

* update more diagrams

* remove note about change in element stroke

* update diagram

* increase size limit for excalidraw production bundle

* tweaks

* add link

* move codebase after introduction

* dummy

---------

Co-authored-by: dwelle <luzar.david@gmail.com>
2023-09-13 21:01:34 +05:30
186ed43671 feat: animate to constrained area on setting constrains 2023-09-13 16:41:10 +02:00
d1e3ea431b chore: renaming 2023-09-13 16:40:39 +02:00
ddb08ce732 feat: use single function for animating canvas translation 2023-09-13 16:20:12 +02:00
edf54d1543 fix: scale constrained area based on zoom 2023-09-13 15:58:38 +02:00
b4e80b602d feat: add memoization 2023-09-13 15:57:50 +02:00
dd9bde5ee7 feat: animation depending on timeout 2023-09-13 14:54:39 +02:00
b99bf74c3d feat: hide scroll back to content button 2023-09-12 12:23:13 +02:00
6abf194281 fix: export to plus url (#6980) 2023-09-11 21:13:16 +00:00
5302490372 feat: update logo (#6979) 2023-09-11 17:47:41 +02:00
84b19a77d7 feat: make constrained scroll working with split canvases 2023-09-11 17:07:07 +02:00
4a9adc703a feat: export changeProperty() and getFormValue(). (#6957) 2023-09-09 08:13:15 -05:00
53a88d4c7a Merge branch 'master' of github.com:excalidraw/excalidraw into arnost/scroll-in-read-only-links 2023-09-07 13:52:29 +02:00
56c21529db docs: Adding the json Schema to the documentation (#6817)
Co-authored-by: Rajni2002 <rajnikant.dash@everlytics.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-09-07 12:43:37 +02:00
a13aed92f2 fix: z-index inconsistencies during addition / deletion in frames (#6914)
Co-authored-by: Marcel Mraz <marcel.mraz@adacta-fintech.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-09-06 22:41:44 +00:00
134df7bfbb fix: update size-limit so react is not installed as dependency (#6964) 2023-09-06 10:39:04 +05:30
5191cdbe26 fix: stale labeled arrow bounds cache after editing the label (#6893)
* fix stale labeled arrow bounds cache after editing the label

* add arrow bounds test

* fix test to check the arrow version

* fix

* fix test - remove unused import

* Update src/element/textWysiwyg.test.tsx

---------

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2023-09-05 21:20:27 +05:30
10900f39ee fix: allow to scroll on one axis when other is fully in view 2023-09-05 17:32:51 +02:00
27fd150a20 fix: canvas flickering due to resetting canvas on skipped frames (#6960) 2023-09-05 12:06:48 +02:00
ebbd72e792 feat: use single overscrollAllowance for both axis 2023-09-04 11:55:14 +02:00
f8ba862774 feat: set initial zoom to viewportZoomFactor when lockZoom is false 2023-09-03 23:47:48 +02:00
806b1e9705 fix: prevent viewport jumping when panning by mouse wheel 2023-09-03 16:54:04 +02:00
188921c247 fix: grid jittery after partition PR (#6935) 2023-08-27 19:30:47 +02:00
de1ebad755 fix: regression in indexing when adding elements to frame (#6904) 2023-08-18 16:34:01 +02:00
9cd5e15917 fix: stabilize selectedElementIds when box selecting (#6912) 2023-08-18 16:14:57 +02:00
8101a351db fix: resetting deleted elements on duplication (#6906) 2023-08-18 00:28:26 +02:00
49e9a2ab33 build(deps): bump @excalidraw/excalidraw from 0.15.2 to 0.15.3 in /dev-docs (#6896)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-17 13:47:32 +02:00
d140d1b8b3 fix: make canvas compos memoize appState on props they declare (#6897) 2023-08-17 13:39:15 +02:00
1bd416002c fix: scope --color-selection retrieval to given instance (#6886)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-08-16 21:59:37 +00:00
991f5570ce build(deps): bump word-wrap from 1.2.3 to 1.2.5 (#6892)
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.5.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.5)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-16 16:11:43 +05:30
3cf8259e71 build(deps): bump semver from 6.3.0 to 6.3.1 in /src/packages/utils (#6755)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-16 11:38:36 +02:00
9b727025fd build(deps): bump semver from 6.3.0 to 6.3.1 in /src/packages/excalidraw (#6754)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-16 11:38:16 +02:00
59b53eb9cb build(deps): bump protobufjs from 6.11.3 to 6.11.4 (#6890)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-16 11:25:31 +02:00
9e0bfd178e refactor: factor out shape generation from renderElement.ts pt 2 (#6878) 2023-08-14 13:52:25 +02:00
c29f19a88b perf: Limiting the suggested binding to fix performance issue (#6877) 2023-08-14 13:11:08 +02:00
2b14a5c233 build: increase limit for bundle by 1kb (#6880) 2023-08-14 15:47:18 +05:30
a376bd9495 feat: partition main canvas vertically (#6759)
Co-authored-by: Marcel Mraz <marcel.mraz@adacta-fintech.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-08-12 22:56:59 +02:00
3ea07076ad feat: support creating containers, linear elements, text containers, labelled arrows and arrow bindings programatically (#6546)
* feat: support creating text containers programatically

* fix

* fix

* fix

* fix

* update api to use label

* fix api and support individual shapes and text element

* update test case in package example

* support creating arrows and line

* support labelled arrows

* add in package example

* fix alignment

* better types

* fix

* keep element as is unless we support prog api

* fix tests

* fix lint

* ignore

* support arrow bindings via start and end in api

* fix lint

* fix coords

* support id as well for elements

* preserve bindings if present and fix testcases

* preserve bindings for labelled arrows

* support ids, clean up code and move the api related stuff to transform.ts

* allow multiple arrows to bind to single element

* fix singular elements

* fix single text element, unique id and tests

* fix lint

* fix

* support binding arrow to text element

* fix creation of regular text

* use same stroke color as parent for text containers and height 0 for linear element by default

* fix types

* fix

* remove more ts ignore

* remove ts ignore

* remove

* Add coverage script

* Add tests

* fix tests

* make type optional when id present

* remove type when id provided in tests

* Add more tests

* tweak

* let host call convertToExcalidrawElements when using programmatic API

* remove convertToExcalidrawElements call from restore

* lint

* update snaps

* Add new type excalidraw-api/clipboard for programmatic api

* cleanup

* rename tweak

* tweak

* make image attributes optional and better ts check

* support image via programmatic API

* fix lint

* more types

* make fileId mandatory for image and export convertToExcalidrawElements

* fix

* small tweaks

* update snaps

* fix

* use Object.assign instead of mutateElement

* lint

* preserve z-index by pushing all elements first and then add bindings

* instantiate instead of closure for storing elements

* use element API to create regular text, diamond, ellipse and rectangle

* fix snaps

* udpdate api

* ts fixes

* make `convertToExcalidrawElements` more typesafe

* update snaps

* refactor the approach so that order of elements doesn't matter

* Revert "update snaps"

This reverts commit 621dfadccf.

* review fixes

* rename ExcalidrawProgrammaticElement -> ExcalidrawELementSkeleton

* Add tests

* give preference to first element when duplicate ids found

* use console.error

---------

Co-authored-by: dwelle <luzar.david@gmail.com>
2023-08-09 16:41:15 +05:30
ded0222e8d docs: add note for tests that have requisites (#6856)
Co-authored-by: David Luzar <luzar.david@gmail.com>
2023-08-05 09:51:50 +00:00
e7983bc493 fix: webpack config exclude statement to system agnostic (#6857) 2023-08-05 11:49:57 +02:00
083bcf802c fix: remove embeddable from generic elements (#6853) 2023-08-04 15:16:55 +02:00
b0cdd00c2a [debug] 2023-08-02 17:54:04 +02:00
6711735b27 Merge branch 'master' into arnost/scroll-in-read-only-links 2023-08-02 17:53:30 +02:00
803e14ada1 Revert "[debug]"
This reverts commit 71eb3023b2.
2023-08-02 17:41:32 +02:00
bb985eba3a fix: resizing arrow labels (#6789)
* fix arrow labels resizing

- min arrow labels width based on font size
- labels width and padding in % of container's width
- resize labels simply multiplying by scale

* remove no longer needed getContainerDims

* fix arrow labels font size not updated on change font size action

* fix bound arrows not updated right after resize

* fix test

* fix 3+ point arrow label resizing with shift

* fix bound text not scaling when resizing with shift & n or s handle

* fix arrow labels width not updating when moving a 2-point arrow point with shift

---------

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2023-08-02 15:34:21 +05:30
4469c02191 chore: move this.scene.getElementsIncludingDeleted() result into const 2023-08-01 16:52:59 +02:00
04e23e1d29 fix: do not animate empty scene 2023-08-01 16:30:45 +02:00
23c88a38d0 build(deps): bump semver from 5.7.1 to 5.7.2 in /dev-docs (#6757)
Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-01 16:14:08 +05:30
b85d5fa12b test: add coverage report for PR (#6840)
* test: add coverage report for PR

* gh token

* fix

* fix

* add reporter

* fix

* enable v8 for coverage

* no watch

* test

* add threshold

* fix

* change name so the action isn't required

* change job name

* rename job so it doesn't collid with test required check

* remove log
2023-08-01 16:13:04 +05:30
9391a09e54 build(deps): bump word-wrap from 1.2.3 to 1.2.5 (#6811)
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.5.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.5)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-01 11:07:16 +05:30
50450a7dab chore: update required node version to 18 (#6837) 2023-07-31 23:47:41 +02:00
d24a032dbb feat: set scroll constraints on initial scene state 2023-07-31 18:33:39 +02:00
fc9a9a2571 fix: eye-dropper not working with app offset correctly on non-1 dPR (#6835) 2023-07-31 16:36:30 +02:00
6126c34dc0 fix: add self destroying service-worker.js to migrate everyone from CRA to Vite (#6833)
* fix: add self destroying service-worker.js to migrate everyone from CRA to VITE

* add comment

* don't add service-worker.js to app pre-cache
2023-07-31 19:56:50 +05:30
12e37e3dd2 fix: forgotten REACT_APP env variables (#6834) 2023-07-31 15:29:24 +02:00
76d3930983 fix: typo 2023-07-31 09:50:47 +02:00
af6e64ffc2 Merge branch 'master' into arnost/scroll-in-read-only-links 2023-07-31 09:26:14 +02:00
9ca27c62c7 feat: add support for simplePDF in Web-Embeds (#6810) 2023-07-29 10:02:15 +02:00
1acc646534 feat: add support for val.town embeds (#6821) 2023-07-28 16:55:40 +02:00
66bac50de3 fix: refresh sw when browser refreshed (#6824)
* fix: refresh sw when browser refreshed

* dummy test

* enable immediate reload

* test

* fix

* autoupdate

* don't immediate

* test

* testing testing

* test

* test

* its same

* revert logs

* fix types

---------
2023-07-28 20:17:24 +05:30
5dd1efde8a build: update to node 18 in docker (#6822) 2023-07-28 12:06:33 +05:30
a7c590d459 feat: render bold lines in grid (#6779)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-07-27 22:41:44 +00:00
48924688c7 build: migrate to Vite 🚀 (#6818)
* init

* add: vite dev build working

* fix: href serving from public

* feat: add ejs plugin

* feat: migrated env files and ejs templating

* chore: add types related to envs

* chore: add vite-env types

* feat: support vite pwa

* chore: upgrade vite pwa

* chore: pin node version to 16.18.1

* chore: preserve use of nodejs 14

* refactor: preserve REACT_APP as env prefix

* chore: support esm environment variables

* fix ts config

* use VITE prefix and remove vite-plugin-env-compatible

* introduce import-meta-loader for building pacakge as webpack isn't compatible with import.meta syntax

* lint

* remove import.meta.env in main.js

* set debug flag to false

* migrate to vitest and use jest-canvas-mock 2.4.0 so its comp
atible with vite

* integrate vitest-ui

* fix most of teh test

* snaps

* Add script for testing with vite ui

* fix all tests related to mocking

* fix more test

* fix more

* fix flip.test.tsx

* fix contentxmenu snaps

* fix regression snaps

* fix excalidraw.test.tsx and this makes all tests finally pass :)

* use node 16

* specify node version

* use node 16 in lint as well

* fix mobile.test.tsx

* use node 16

* add style-loader

* upgrade to node 18

* fix lint package.json

* support eslint with vite

* fix lint

* fix lint

* fix ts

* remove pwa/sw stuff

* use env vars in EJS the vite way

* fix lint

* move remainig jest mock/spy to vite

* don't cache locales

* fix regex

* add fonts cache

* tweak

* add custom service worker

* upgrade vite and create font cache again

* cache fonts.css and locales

* tweak

* use manifestTransforms for filtering locales

* use assets js pattern for locales

* add font.css to globIgnore so its pushed to fonts cache

* create a separate chunk for locales with rollup

* remove manifestTransforms and fix glob pattern for locales to filter from workbox pre-cache

* push sourcemaps in production

* add comments in config

* lint

* use node 18

* disable pwa in dev

* fix

* fix

* increase limit of bundle

* upgrade vite-pwa to latest

* remove public/workbox so workbox assets are not precached

* fon't club en.json and percentages.json with manual locales chunk to fix first load+offline mode

* tweak regex

* remove happy-dom as its not used

* add comment

* use any instead of ts-ignore

* cleanup

* remove jest-canvas-mock resolution as vite-canvas-mock was patched locking deps at 2.4.0

* use same theme color present in entry point

* remove vite-plugin-eslint as it improves DX significantly

* integrate vite-plugin-checker for ts errors

* add nabla/vite-plugin-eslint

* use eslint from checker only

* add env variable VITE_APP_COLLAPSE_OVERLAY for collapsing the checker overlay

* tweak vite checker overlay badge position

* Enable eslint behind flag as its not working well with windows with non WSL

* make port configurable

* open the browser when server ready

* enable eslint by default

---------

Co-authored-by: Weslley Braga <weslley@bambee.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-07-27 23:50:11 +05:30
8af9ea3cf3 fix: adding to selection via shift box-select (#6815) 2023-07-27 12:50:08 +02:00
cbd908097f chore: typo - Collab.ts (#6812) 2023-07-26 23:30:25 +02:00
c1247742ea fix: prevent binding focus NaN value (#6803)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2023-07-26 23:28:11 +02:00
8104068bd5 revert: "build: Migrate to Vite 🚀" (#6814)
Revert "build: Migrate to Vite 🚀 (#6713)"

This reverts commit e93bbc5776.
2023-07-26 22:34:06 +05:30
dcc75ed007 feat: adds support for stackblitz.com embeds (#6813)
feat: adds stackblitz.com embeds
2023-07-26 21:01:18 +05:30
e93bbc5776 build: Migrate to Vite 🚀 (#6713)
* init

* add: vite dev build working

* fix: href serving from public

* feat: add ejs plugin

* feat: migrated env files and ejs templating

* chore: add types related to envs

* chore: add vite-env types

* feat: support vite pwa

* chore: upgrade vite pwa

* chore: pin node version to 16.18.1

* chore: preserve use of nodejs 14

* refactor: preserve REACT_APP as env prefix

* chore: support esm environment variables

* fix ts config

* use VITE prefix and remove vite-plugin-env-compatible

* introduce import-meta-loader for building pacakge as webpack isn't compatible with import.meta syntax

* lint

* remove import.meta.env in main.js

* set debug flag to false

* migrate to vitest and use jest-canvas-mock 2.4.0 so its comp
atible with vite

* integrate vitest-ui

* fix most of teh test

* snaps

* Add script for testing with vite ui

* fix all tests related to mocking

* fix more test

* fix more

* fix flip.test.tsx

* fix contentxmenu snaps

* fix regression snaps

* fix excalidraw.test.tsx and this makes all tests finally pass :)

* use node 16

* specify node version

* use node 16 in lint as well

* fix mobile.test.tsx

* use node 16

* add style-loader

* upgrade to node 18

* fix lint package.json

* support eslint with vite

* fix lint

* fix lint

* fix ts

* remove pwa/sw stuff

* use env vars in EJS the vite way

* fix lint

* move remainig jest mock/spy to vite

* don't cache locales

* fix regex

* add fonts cache

* tweak

* add custom service worker

* upgrade vite and create font cache again

* cache fonts.css and locales

* tweak

* use manifestTransforms for filtering locales

* use assets js pattern for locales

* add font.css to globIgnore so its pushed to fonts cache

* create a separate chunk for locales with rollup

* remove manifestTransforms and fix glob pattern for locales to filter from workbox pre-cache

* push sourcemaps in production

* add comments in config

* lint

* use node 18

* disable pwa in dev

* fix

* fix

* increase limit of bundle

* upgrade vite-pwa to latest

* remove public/workbox so workbox assets are not precached

* fon't club en.json and percentages.json with manual locales chunk to fix first load+offline mode

* tweak regex

* remove happy-dom as its not used

* add comment

* use any instead of ts-ignore

* cleanup

* remove jest-canvas-mock resolution as vite-canvas-mock was patched locking deps at 2.4.0

* use same theme color present in entry point

---------

Co-authored-by: Weslley Braga <weslley@bambee.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-07-26 15:55:20 +05:30
2a2495175b build: increase limit to 290 kB for prod bundle (#6809) 2023-07-26 08:49:39 +05:30
b57b3b573d feat: introducing Web-Embeds (alias iframe element) (#6691)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-07-24 16:51:53 +02:00
744e5b2ab3 fix: use pull request in semantic workflow for better security (#6799)
* fix: use pull request in semantic workflow for security

* add types
2023-07-24 13:01:42 +05:30
d36c72c435 fix: don't show canvasBackground label when UIOptions.canvasActions.changeViewBackgroundColor is false (#6781)
* fix(components/main-menu): not show canvasBackground

* chore(components/main-menu): add data-testid attr to canvasBackground label

* test(tests/packages/excalidraw): check whether canvasbackground label is rendered when changeviewbackground is false

* test: update snapshots

* fix(tests/packages/excalidraw): change to lowercase canvas background test id

* change to pull request target for size-limit

* Revert "change to pull request target for size-limit"

This reverts commit baf1ca2677.

* Add test

---------

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2023-07-24 12:33:54 +05:30
e57dc405fa chore: add style-loader as deps instead of using from react-scripts (#6791) 2023-07-21 13:48:48 +05:30
41ed019bc2 chore: remove size-limit deps from root package.json (#6790)
* chore: remove size-limit deps from root package.json

* add size limit preset
2023-07-21 13:35:20 +05:30
f7c3644342 refactor: add typeScript support to enforce valid translation keys (#6776) 2023-07-20 18:15:32 +02:00
5e3550fc14 ci: structured build output from size-limit (#6788)
* ci: better build output from size-limit

* add size-limit.json

* try with pull request target

* fix

* revert pull request target
2023-07-20 13:54:13 +05:30
70888327a3 fix: use subdirectory for @excalidraw/excalidraw size limit (#6787)
* fix: use subdirectory for @excalidraw/excalidraw size limit

* fix

* update yml

* update path

* fix

* fix

* better
2023-07-19 22:07:18 +05:30
9fc15d81a0 ci: introduce bundle size for package @excalidraw/excalidraw (#6785)
* ci: update bundle size limit

* change the size script to track bundle size on the package excalidraw

* fix build command

* fix

* remove

* fix

* update script

* fix
2023-07-19 21:19:10 +05:30
a80ac4c748 ci: add bundle size limit action (#6783)
* ci: add bundle size limit action

* chore: fix lint

* ci: fix

* ci: fix workflow

* ci: fix workflow

* add size limit deps

* use node 18

---------

Co-authored-by: Nitin Kumar <nitin.kumar@razorpay.com>
2023-07-19 13:55:50 +05:30
4e9039e850 feat: simplify memoization logic 2023-07-15 12:44:34 +02:00
132750f753 feat: splitting logic, memoization 2023-07-15 12:44:33 +02:00
71eb3023b2 [debug] 2023-07-15 12:44:32 +02:00
6d165971fc feat: set view mode when constrains set via props 2023-07-15 12:44:31 +02:00
9562e4309f feat: add zoom lock and viewportZoomFactor 2023-07-15 12:44:30 +02:00
e8e391e465 refactor: split constrainScroll into smaller functions 2023-07-15 12:44:29 +02:00
92be92071a feat: disable animation on zooming 2023-07-15 12:44:28 +02:00
71918e57a8 feat: cleanup 2023-07-15 12:44:27 +02:00
c0bd9027cb feat: animate the scroll to constrained area 2023-07-15 12:44:26 +02:00
7336b1c276 test: update snapshot 2023-07-15 12:44:25 +02:00
7fb6c23715 fix: remove forgotten console.log 2023-07-15 12:44:24 +02:00
82014fe670 chore: comments and variable renaming 2023-07-15 12:44:23 +02:00
bc44c3f947 feat: add overscroll when constrained area is smaller than viewport 2023-07-15 12:44:21 +02:00
19ba107041 feat: pass scrollConstraints via props 2023-07-15 12:44:18 +02:00
381ef93956 feat: remove zoom limit 2023-07-15 12:42:46 +02:00
f82363aae9 feat: enforce constrains on setting constrains 2023-07-15 12:42:45 +02:00
485c57fd59 chore: remove console.log 2023-07-15 12:42:44 +02:00
35b43c14d8 feat: allow scroll over constraints while mouse down 2023-07-15 12:42:43 +02:00
f7e8056abe feat: update constraints on window resize 2023-07-15 12:42:42 +02:00
71f7960606 test: fix test snapshots 2023-07-15 12:42:41 +02:00
2998573e79 feat: limit scroll in componentDidUpdate 2023-07-15 12:42:40 +02:00
209934c90a feat: center constrained area on zoom out 2023-07-15 12:42:39 +02:00
a8158691b7 feat: limit zoom by translateCanvas 2023-07-15 12:42:38 +02:00
75f8e904cc feat: add possibility to limit scroll area 2023-07-15 12:42:37 +02:00
1224 changed files with 185510 additions and 77401 deletions

5
.codesandbox/Dockerfile Normal file
View 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

View File

@ -27,7 +27,10 @@
"start": {
"name": "Start Excalidraw",
"command": "yarn start",
"runAtStart": true
"runAtStart": true,
"preview": {
"port": 3000
}
},
"test": {
"name": "Run Tests",
@ -37,7 +40,11 @@
"install-deps": {
"name": "Install Dependencies",
"command": "yarn install",
"restartOn": { "files": ["yarn.lock"] }
"restartOn": {
"files": ["yarn.lock"],
"branch": false,
"resume": false
}
}
}
}

View File

@ -4,8 +4,16 @@
!.eslintrc.json
!.npmrc
!.prettierrc
!excalidraw-app/
!package.json
!public/
!src/
!packages/
!scripts/
!tsconfig.json
!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

View File

@ -1,30 +1,53 @@
REACT_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_GET_URL=https://json-dev.excalidraw.com/api/v2/
VITE_APP_BACKEND_V2_POST_URL=https://json-dev.excalidraw.com/api/v2/post/
REACT_APP_LIBRARY_URL=https://libraries.excalidraw.com
REACT_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
VITE_APP_LIBRARY_URL=https://libraries.excalidraw.com
VITE_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
# 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
REACT_APP_PORTAL_URL=
VITE_APP_PLUS_LP=https://plus.excalidraw.com
VITE_APP_PLUS_APP=http://localhost:3000
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!
# must be lowercase `true` when turned on
#
# whether to enable Service Workers in development
REACT_APP_DEV_ENABLE_SW=
# whether to disable live reload / HMR. Usuaully what you want to do when
# debugging Service Workers.
REACT_APP_DEV_DISABLE_LIVE_RELOAD=
REACT_APP_DISABLE_TRACKING=true
VITE_APP_DEV_DISABLE_LIVE_RELOAD=
VITE_APP_ENABLE_TRACKING=true
FAST_REFRESH=false
# The port the run the dev server
VITE_APP_PORT=3000
#Debug flags
# 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
# Enable PWA in dev server
VITE_APP_ENABLE_PWA=false
VITE_APP_PLUS_EXPORT_PUBLIC_KEY='MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm2g5T+Rub6Kbf1Mf57t0
7r2zeHuVg4dla3r5ryXMswtzz6x767octl6oLThn33mQsPSy3GKglFZoCTXJR4ij
ba8SxB04sL/N8eRrKja7TFWjCVtRwTTfyy771NYYNFVJclkxHyE5qw4m27crHF1y
UNWEjuqNMi/lwAErS9fFa2oJlWyT8U7zzv/5kQREkxZI6y9v0AF3qcbsy2731FnD
s9ChJvOUW9toIab2gsIdrKW8ZNpu084ZFVKb6LNjvIXI1Se4oMTHeszXzNptzlot
kdxxjOoaQMAyfljFSot1F1FlU6MQlag7UnFGvFjRHN1JI5q4K+n3a67DX+TMyRqS
HQIDAQAB'
# set to true in .env.development.local to disable the prevent unload dialog
VITE_APP_DISABLE_PREVENT_UNLOAD=

View File

@ -1,15 +1,32 @@
REACT_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_GET_URL=https://json.excalidraw.com/api/v2/
VITE_APP_BACKEND_V2_POST_URL=https://json.excalidraw.com/api/v2/post/
REACT_APP_LIBRARY_URL=https://libraries.excalidraw.com
REACT_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
VITE_APP_LIBRARY_URL=https://libraries.excalidraw.com
VITE_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
REACT_APP_PORTAL_URL=https://portal.excalidraw.com
# Fill to set socket server URL used for collaboration.
# Meant for forks only: excalidraw.com uses custom REACT_APP_PORTAL_URL flow
REACT_APP_WS_SERVER_URL=
VITE_APP_PLUS_LP=https://plus.excalidraw.com
VITE_APP_PLUS_APP=https://app.excalidraw.com
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
# socket server URL used for collaboration
VITE_APP_WS_SERVER_URL=https://oss-collab.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_ENABLE_TRACKING=false
VITE_APP_PLUS_EXPORT_PUBLIC_KEY='MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApQ0jM9Qz8TdFLzcuAZZX
/WvuKSOJxiw6AR/ZcE3eFQWM/mbFdhQgyK8eHGkKQifKzH1xUZjCxyXcxW6ZO02t
kPOPxhz+nxUrIoWCD/V4NGmUA1lxwHuO21HN1gzKrN3xHg5EGjyouR9vibT9VDGF
gq6+4Ic/kJX+AD2MM7Yre2+FsOdysrmuW2Fu3ahuC1uQE7pOe1j0k7auNP0y1q53
PrB8Ts2LUpepWC1l7zIXFm4ViDULuyWXTEpUcHSsEH8vpd1tckjypxCwkipfZsXx
iPszy0o0Dx2iArPfWMXlFAI9mvyFCyFC3+nSvfyAUb2C4uZgCwAuyFh/ydPF4DEE
PQIDAQAB'
# Set the below flags explicitly to false in production mode since vite loads and merges .env.local vars when running the build command
VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX=false
VITE_APP_COLLAPSE_OVERLAY=false
# Enable eslint in dev server
VITE_APP_ENABLE_ESLINT=false
REACT_APP_PLUS_APP=https://app.excalidraw.com
REACT_APP_DISABLE_TRACKING=

View File

@ -5,4 +5,7 @@ package-lock.json
firebase/
dist/
public/workbox
src/packages/excalidraw/types
packages/excalidraw/types
examples/**/public
dev-dist
coverage

View File

@ -1,7 +1,37 @@
{
"extends": ["@excalidraw/eslint-config", "react-app"],
"rules": {
"import/order": [
"warn",
{
"groups": ["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"],
"pathGroups": [
{
"pattern": "@excalidraw/**",
"group": "external",
"position": "after"
}
],
"newlines-between": "always-and-inside-groups",
"warnOnUnassignedImports": true
}
],
"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"
}
],
"no-restricted-imports": [
"error",
{
"name": "jotai",
"message": "Do not import from \"jotai\" directly. Use our app-specific modules (\"editor-jotai\" or \"app-jotai\")."
}
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -12,10 +12,10 @@ jobs:
- uses: actions/checkout@v2
with:
fetch-depth: 2
- name: Setup Node.js 14.x
- name: Setup Node.js 18.x
uses: actions/setup-node@v2
with:
node-version: 14.x
node-version: 18.x
- name: Set up publish access
run: |
npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
@ -23,5 +23,5 @@ jobs:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Auto release
run: |
yarn add @actions/core
yarn add @actions/core -W
yarn autorelease

View File

@ -32,10 +32,10 @@ jobs:
with:
ref: ${{ steps.sha.outputs.result }}
fetch-depth: 2
- name: Setup Node.js 14.x
- name: Setup Node.js 18.x
uses: actions/setup-node@v2
with:
node-version: 14.x
node-version: 18.x
- name: Set up publish access
run: |
npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
@ -44,7 +44,7 @@ jobs:
- name: Auto release preview
id: "autorelease"
run: |
yarn add @actions/core
yarn add @actions/core -W
yarn autorelease preview ${{ github.event.issue.number }}
- name: Post comment post release
if: always()

View File

@ -9,14 +9,14 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Setup Node.js 14.x
- name: Setup Node.js 18.x
uses: actions/setup-node@v2
with:
node-version: 14.x
node-version: 18.x
- name: Install and lint
run: |
yarn --frozen-lockfile
yarn install
yarn test:other
yarn test:code
yarn test:typecheck

View File

@ -10,23 +10,23 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
token: ${{ secrets.PUSH_TRANSLATIONS_COVERAGE_PAT }}
- name: Setup Node.js 14.x
- name: Setup Node.js 18.x
uses: actions/setup-node@v2
with:
node-version: 14.x
node-version: 18.x
- name: Create report file
run: |
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
git config --global user.name 'Excalidraw Bot'
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 push
fi

View File

@ -1,7 +1,7 @@
name: Semantic PR title
on:
pull_request_target:
pull_request:
types:
- opened
- edited
@ -11,6 +11,6 @@ jobs:
semantic:
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v3.0.0
- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -10,10 +10,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js 14.x
- name: Setup Node.js 18.x
uses: actions/setup-node@v2
with:
node-version: 14.x
node-version: 18.x
- name: Install and build
run: |
yarn --frozen-lockfile

28
.github/workflows/size-limit.yml vendored Normal file
View 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
View 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 }}

View File

@ -1,17 +1,19 @@
name: Tests
on: pull_request
on:
push:
branches: master
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js 14.x
uses: actions/setup-node@v2
- uses: actions/checkout@v4
- name: Setup Node.js 18.x
uses: actions/setup-node@v4
with:
node-version: 14.x
node-version: 18.x
- name: Install and test
run: |
yarn --frozen-lockfile
yarn install
yarn test:app

8
.gitignore vendored
View File

@ -21,8 +21,8 @@ npm-debug.log*
package-lock.json
yarn-debug.log*
yarn-error.log*
src/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
packages/excalidraw/types
coverage
dev-dist
html
meta*.json

2
.nvmrc
View File

@ -1 +1 @@
14
18

View File

@ -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

View File

@ -1,17 +1,19 @@
FROM node:14-alpine AS build
FROM node:18 AS build
WORKDIR /opt/node_app
COPY package.json yarn.lock ./
RUN yarn --ignore-optional --network-timeout 600000
COPY . .
# do not ignore optional dependencies:
# Error: Cannot find module @rollup/rollup-linux-x64-gnu
RUN yarn --network-timeout 600000
ARG NODE_ENV=production
COPY . .
RUN yarn build:app:docker
FROM nginx:1.21-alpine
FROM nginx:1.27-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

View File

@ -1,13 +1,13 @@
<a href="https://excalidraw.com/" target="_blank" rel="noopener">
<picture>
<source media="(prefers-color-scheme: dark)" alt="Excalidraw" srcset="https://excalidraw.nyc3.cdn.digitaloceanspaces.com/github%2FExcalidraw_Github_cover_dark.png" />
<img alt="Excalidraw" src="https://excalidraw.nyc3.cdn.digitaloceanspaces.com/github%2FExcalidraw_Github_cover.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/excalidraw_github_cover_2.png" />
</picture>
</a>
<h4 align="center">
<a href="https://excalidraw.com">Excalidraw Editor</a> |
<a href="https://blog.excalidraw.com">Blog</a> |
<a href="https://plus.excalidraw.com/blog">Blog</a> |
<a href="https://docs.excalidraw.com">Documentation</a> |
<a href="https://plus.excalidraw.com">Excalidraw+</a>
</h4>
@ -25,6 +25,9 @@
<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" />
</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">
<img alt="PRs welcome!" src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" />
</a>
@ -70,7 +73,7 @@ The Excalidraw editor (npm package) supports:
## 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:
- 📡&nbsp;PWA support (works offline).
- 🤼&nbsp;Real-time collaboration.
@ -82,19 +85,17 @@ We'll be adding these features as drop-in plugins for the npm package in the fut
## 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).
```
Use `npm` or `yarn` to install the package.
```bash
npm install react react-dom @excalidraw/excalidraw
```
or via yarn
```
# or
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

View File

@ -1,3 +1,3 @@
files:
- source: /src/locales/en.json
translation: /src/locales/%locale%.json
- source: /packages/excalidraw/locales/en.json
translation: /packages/excalidraw/locales/%locale%.json

View File

@ -17,5 +17,6 @@ Below are the currently supported components:
- [MainMenu](/docs/@excalidraw/excalidraw/api/children-components/main-menu)
- [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)
- [LiveCollaborationTrigger](/docs/@excalidraw/excalidraw/api/children-components/live-collaboration-trigger)

View File

@ -34,7 +34,7 @@ Open the `Menu` in the below playground and you will see the `custom footer` ren
```jsx live noInline
const MobileFooter = ({}) => {
const device = useDevice();
if (device.isMobile) {
if (device.editor.isMobile) {
return (
<Footer>
<button

View File

@ -38,6 +38,7 @@ To render an item, its recommended to use `MainMenu.Item`.
| Prop | Type | Required | Default | Description |
| --- | --- | :-: | :-: | --- |
| `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 |
| `icon` | `JSX.Element` | No | - | The icon used in the menu item |
| `shortcut` | `string` | No | - | The shortcut to be shown for the menu item |
@ -70,6 +71,7 @@ function App() {
| Prop | Type | Required | Default | Description |
| --- | --- | :-: | :-: | --- |
| `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. |
| `children` | `React.ReactNode` | Yes | - | The content of the menu item |
| `icon` | `JSX.Element` | No | - | The icon used in the menu item |
@ -131,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/main-menu/DefaultItems.tsx) of the default items.
### MainMenu.Group

View File

@ -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>
);
}
```

View File

@ -31,7 +31,7 @@ The welcome screen consists of two main groups of subcomponents:
<img
src={require("@site/static/img/welcome-screen-overview.png").default}
alt="Excalidraw logo: Sketch handrawn like diagrams."
alt="Excalidraw logo: Sketch hand-drawn like diagrams."
/>
### Center

View File

@ -8,15 +8,15 @@
import { FONT_FAMILY } from "@excalidraw/excalidraw";
```
`FONT_FAMILY` contains all the font families used in `Excalidraw` as explained below
`FONT_FAMILY` contains all the font families used in `Excalidraw`. The default families are the following:
| Font Family | Description |
| ----------- | ---------------------- |
| `Virgil` | The `handwritten` font |
| `Helvetica` | The `Normal` Font |
| `Cascadia` | The `Code` Font |
| `Excalifont` | The `Hand-drawn` font |
| `Nunito` | The `Normal` Font |
| `Comic Shanns` | The `Code` Font |
Defaults to `FONT_FAMILY.Virgil` unless passed in `initialData.appState.currentItemFontFamily`.
Pre-selected family is `FONT_FAMILY.Excalifont`, unless it's overriden with `initialData.appState.currentItemFontFamily`.
### THEME
@ -37,7 +37,7 @@ Defaults to `THEME.LIGHT` unless passed in `initialData.appState.theme`
### 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 **

View File

@ -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,
},
]);
```
![image](https://github.com/excalidraw/excalidraw/assets/11256141/70ca7063-88fb-434c-838a-cd466e1bc3c2)
### 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",
},
]);
```
![image](https://github.com/excalidraw/excalidraw/assets/11256141/085c7ac3-7952-4f22-b9c3-6beb51438526)
### 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,
},
]);
```
![image](https://github.com/excalidraw/excalidraw/assets/11256141/0c22a06b-b568-4ab5-9848-a5f0160f66a6)
#### 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",
},
]);
```
![image](https://github.com/excalidraw/excalidraw/assets/11256141/14f1bf3f-ad81-4096-8c1c-f35235084ec5)
### 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",
},
},
]);
```
![image](https://github.com/excalidraw/excalidraw/assets/11256141/1e2c7b5d-fcb4-4f86-946d-0bfb0e97d532)
#### 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",
},
},
]);
```
![image](https://github.com/excalidraw/excalidraw/assets/11256141/f8123cd1-c9aa-452d-b96b-05c846c5030d)
### 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",
},
},
]);
```
![image](https://github.com/excalidraw/excalidraw/assets/11256141/70635e9b-f1c8-4839-89e1-73b813abeb93)
### 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.
![image](https://github.com/excalidraw/excalidraw/assets/11256141/5aff09fd-b7e8-4c63-98be-da40b0698704)
```js
convertToExcalidrawElements([
{
type: "arrow",
x: 255,
y: 239,
label: {
text: "HELLO WORLD!!",
},
start: {
type: "text",
text: "HEYYYYY",
},
end: {
type: "text",
text: "WHATS UP ?",
},
},
]);
```
![image](https://github.com/excalidraw/excalidraw/assets/11256141/2a9f03ac-e45c-4fbd-9be0-5d9f8c8e0343)
#### 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",
},
},
]);
```
![image](https://github.com/excalidraw/excalidraw/assets/11256141/a8b047c8-2eed-4aea-82a2-e1e6bbddb8d4)
### Frames
To create a frame, you need to pass `type`, `children` (list of Excalidraw element ids). The rest of the attributes are optional.
```ts
{
type: "frame";
children: readonly ExcalidrawElement["id"][];
name?: string;
} & Partial<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"
}]
}
```

View File

@ -1,29 +1,28 @@
# ref
# excalidrawAPI
<pre>
<a href="https://reactjs.org/docs/refs-and-the-dom.html#creating-refs">
createRef
</a>{" "}
&#124;{" "}
<a href="https://reactjs.org/docs/hooks-reference.html#useref">useRef</a>{" "}
&#124;{" "}
<a href="https://reactjs.org/docs/refs-and-the-dom.html#callback-refs">
callbackRef
</a>{" "}
&#124; <br />
&#123; current: &#123; 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>
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 |
| --- | --- | --- |
| ready | `boolean` | This is set to true once Excalidraw is rendered |
| [readyPromise](#readypromise) | `function` | This promise will be resolved with the api once excalidraw has rendered. This will be helpful when you want do some action on the host app once this promise resolves. For this to work you will have to pass ref as shown [here](#readypromise) |
| [updateScene](#updatescene) | `function` | updates the scene with the sceneData |
| [updateLibrary](#updatelibrary) | `function` | updates the scene with the sceneData |
| [updateLibrary](#updatelibrary) | `function` | updates the library |
| [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. |
| [getSceneElementsIncludingDeleted](#getsceneelementsincludingdeleted) | `function` | Returns all the elements including the deleted in the scene |
@ -38,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 |
| [setCursor](#setcursor) | `function` | This API can be used to set customise the mouse cursor on the canvas |
| [resetCursor](#resetcursor) | `function` | This API can be used to reset to default mouse cursor on the canvas |
| [toggleMenu](#togglemenu) | `function` | Toggles specific menus on/off |
| [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>
const excalidrawRef = &#123; current:&#123; readyPromise:
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/utils.ts#L460">
&nbsp;resolvablePromise
</a>
&nbsp;&#125; &#125;
</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.
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
<pre>
(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
</a>
) => void
@ -102,10 +62,10 @@ You can use this function to update the scene with the sceneData. It accepts the
| 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 |
| `appState` | [`ImportedDataState["appState"]`](https://github.com/excalidraw/excalidraw/blob/master/src/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. |
| `commitToHistory` | `boolean` | Implies if the `history (undo/redo)` should be recorded. Defaults to `false`. |
| `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/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/packages/excalidraw/types.ts#L37">Collaborator></a></code> | The list of collaborators to be updated in the scene. |
| `captureUpdate` | [`CaptureUpdateAction`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/store.ts#L40) | Controls which updates should be captured by the `Store`. Captured updates are emmitted and listened to by other components, such as `History` for undo / redo purposes. |
```jsx live
function App() {
@ -145,6 +105,7 @@ function App() {
appState: {
viewBackgroundColor: "#edf2ff",
},
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
};
excalidrawAPI.updateScene(sceneData);
};
@ -155,23 +116,35 @@ function App() {
<button className="custom-button" onClick={updateScene}>
Update Scene
</button>
<Excalidraw ref={(api) => setExcalidrawAPI(api)} />
<Excalidraw excalidrawAPI={(api) => setExcalidrawAPI(api)} />
</div>
);
}
```
#### captureUpdate
You can use the `captureUpdate` to influence undo / redo behaviour.
> **NOTE**: Some updates are not observed by the store / history - i.e. updates to `collaborators` object or parts of `AppState` which are not observed (not `ObservedAppState`). Such updates will never make it to the undo / redo stacks, regardless of the passed `captureUpdate` value.
| | `captureUpdate` value | Notes |
| --- | --- | --- |
| _Immediately undoable_ | `CaptureUpdateAction.IMMEDIATELY` | Use for updates which should be captured. Should be used for most of the local updates. These updates will _immediately_ make it to the local undo / redo stacks. |
| _Eventually undoable_ | `CaptureUpdateAction.EVENTUALLY` | Use for updates which should not be captured immediately - likely exceptions which are part of some async multi-step process. Otherwise, all such updates would end up being captured with the next `CaptureUpdateAction.IMMEDIATELY` - triggered either by the next `updateScene` or internally by the editor. These updates will _eventually_ make it to the local undo / redo stacks. |
| _Never undoable_ | `CaptureUpdateAction.NEVER` | Use for updates which should never be recorded, such as remote updates or scene initialization. These updates will _never_ make it to the local undo / redo stacks. |
### updateLibrary
<pre>
(opts: &#123; <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
</a>
;<br /> merge?: boolean; <br /> prompt?: boolean;
<br /> openLibraryMenu?: boolean;
<br /> defaultStatus?: "unpublished" | "published"; <br /> &#125;) => Promise&lt;
<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
</a>
&gt;
@ -181,7 +154,7 @@ You can use this function to update the library. It accepts the below attributes
| 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. |
| `prompt` | boolean | `false` | Whether to prompt user for confirmation. |
| `openLibraryMenu` | boolean | `false` | Keep the library menu open after library is updated. |
@ -228,8 +201,8 @@ function App() {
Update Library
</button>
<Excalidraw
ref={(api) => setExcalidrawAPI(api)}
// initial data retrieved from https://github.com/excalidraw/excalidraw/blob/master/dev-docs/src/initialData.js
excalidrawAPI={(api) => setExcalidrawAPI(api)}
// initial data retrieved from https://github.com/excalidraw/excalidraw/blob/master/dev-docs/packages/excalidraw/initialData.js
initialData={{
libraryItems: initialData.libraryItems,
appState: { openSidebar: "library" },
@ -244,7 +217,7 @@ function App() {
<pre>
(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
</a>
) => void
@ -264,7 +237,7 @@ Resets the scene. If `resetLoadingState` is passed as true then it will also for
<pre>
() =>{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L115">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L115">
ExcalidrawElement[]
</a>
</pre>
@ -275,7 +248,7 @@ Returns all the elements including the deleted in the scene.
<pre>
() => NonDeleted&#60;
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L115">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L115">
ExcalidrawElement
</a>
[]&#62;
@ -287,7 +260,7 @@ Returns all the elements excluding the deleted in the scene
<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
</a>
</pre>
@ -328,7 +301,7 @@ Scroll the nearest element out of the elements supplied to the center of the vie
| Attribute | type | default | Description |
| --- | --- | --- | --- |
| target | [ExcalidrawElement](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L115) &#124; [ExcalidrawElement[]](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L115) | All scene elements | The element(s) to scroll to. |
| target | [ExcalidrawElement](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L115) &#124; [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%) |
@ -376,7 +349,7 @@ The unique id of the excalidraw component. This can be used to identify the exca
<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
</a>
</pre>
@ -387,14 +360,25 @@ This API can be used to get the files present in the scene. It may contain files
This API has the below signature. It sets the `tool` passed in param as the active tool.
<pre>
(tool: <br /> &#123; type:{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/shapes.tsx#L15">
SHAPES
</a>
[number]["value"]&#124; "eraser" &#125; &#124;
<br /> &#123; type: "custom"; customType: string &#125;) => void
</pre>
```ts
(
tool: (
| (
| { type: Exclude<ToolType, "image"> }
| {
type: Extract<ToolType, "image">;
insertOnCanvasDirectly?: boolean;
}
)
| { type: "custom"; customType: string }
) & { locked?: boolean },
) => {};
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `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
@ -404,15 +388,15 @@ This API can be used to customise the mouse cursor on the canvas and has the bel
(cursor: string) => void
```
## toggleMenu
## toggleSidebar
```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
@ -421,3 +405,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.
## 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.

View File

@ -1,18 +1,18 @@
# initialData
<pre>
&#123; 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> &#125;
&#123; 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> &#125;
</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.
| 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. |
| `appState` | [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95) | The `AppState` 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/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 |
| `libraryItems` | [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L247) &#124; Promise&lt;[LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200)&gt; | 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. |
| `libraryItems` | [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L247) &#124; Promise&lt;[LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L200)&gt; | This library items with which `Excalidraw` should be mounted. |
| `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.

View File

@ -1,42 +1,44 @@
# Props
All `props` are *optional*.
All `props` are _optional_.
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| [`initialData`](/docs/@excalidraw/excalidraw/api/props/initialdata) | `object` &#124; `null` &#124; <code>Promise<object &#124; null></code> | `null` | The initial data with which app loads. |
| [`ref`](/docs/@excalidraw/excalidraw/api/props/ref) | `object` | _ | `Ref` to be passed to Excalidraw |
| [`isCollaborating`](#iscollaborating) | `boolean` | _ | This indicates if the app is in `collaboration` mode |
| [`onChange`](#onchange) | `function` | _ | This callback is triggered whenever the component updates due to any change. This callback will receive the excalidraw `elements` and the current `app state`. |
| [`onPointerUpdate`](#onpointerupdate) | `function` | _ | Callback triggered when mouse pointer is updated. |
| [`onPointerDown`](#onpointerdown) | `function` | _ | This prop if passed gets triggered on pointer down evenets |
| [`onScrollChange`](#onscrollchange) | `function` | _ | This prop if passed gets triggered when scrolling the canvas. |
| [`onPaste`](#onpaste) | `function` | _ | Callback to be triggered if passed when the something is pasted in to the scene |
| [`onLibraryChange`](#onlibrarychange) | `function` | _ | The callback if supplied is triggered when the library is updated and receives the library items. |
| [`onLinkOpen`](#onlinkopen) | `function` | _ | The callback if supplied is triggered when any link is opened. |
| [`initialData`](/docs/@excalidraw/excalidraw/api/props/initialdata) | `object` &#124; `null` &#124; <code>Promise<object &#124; null></code> | `null` | The initial data with which app loads. |
| [`excalidrawAPI`](/docs/@excalidraw/excalidraw/api/props/excalidraw-api) | `function` | \_ | Callback triggered with the excalidraw api once rendered |
| [`isCollaborating`](#iscollaborating) | `boolean` | \_ | This indicates if the app is in `collaboration` mode |
| [`onChange`](#onchange) | `function` | \_ | This callback is triggered whenever the component updates due to any change. This callback will receive the excalidraw `elements` and the current `app state`. |
| [`onPointerUpdate`](#onpointerupdate) | `function` | \_ | Callback triggered when mouse pointer is updated. |
| [`onPointerDown`](#onpointerdown) | `function` | \_ | This prop if passed gets triggered on pointer down events |
| [`onScrollChange`](#onscrollchange) | `function` | \_ | This prop if passed gets triggered when scrolling the canvas. |
| [`onPaste`](#onpaste) | `function` | \_ | Callback to be triggered if passed when something is pasted into the scene |
| [`onLibraryChange`](#onlibrarychange) | `function` | \_ | The callback if supplied is triggered when the library is updated and receives the library items. |
| [`generateLinkForSelection`](#generatelinkforselection) | `function` | \_ | Allows you to override `url` generation when linking to Excalidraw elements. |
| [`onLinkOpen`](#onlinkopen) | `function` | \_ | The callback if supplied is triggered when any link is opened. |
| [`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 |
| [`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. |
| [`zenModeEnabled`](#zenmodeenabled) | `boolean` | _ | This indicates if the `zen` 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 |
| [`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. |
| [`viewModeEnabled`](#viewmodeenabled) | `boolean` | \_ | This indicates if the app is in `view` mode. |
| [`zenModeEnabled`](#zenmodeenabled) | `boolean` | \_ | This indicates if the `zen` 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 |
| [`theme`](#theme) | `"light"` &#124; `"dark"` | `"light"` | The theme of the Excalidraw component |
| [`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. |
| [`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 |
| [`generateIdForFile`](#generateidforfile) | `function` | _ | Allows you to override `id` generation for files added on canvas |
| [`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 |
| [`validateEmbeddable`](#validateembeddable) | `string[]` \| `boolean` \| `RegExp` \| `RegExp[]` \| <code>((link: string) => boolean &#124; undefined)</code> | \_ | 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
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 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
{
@ -58,11 +60,11 @@ Every time component updates, this callback if passed will get triggered and has
(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.
@ -78,14 +80,14 @@ This callback is triggered when mouse pointer is updated.
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
(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.
2. `appState`: [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95) of the scene.
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/packages/excalidraw/types.ts#L95) of the scene.
3. `canvas`: The `HTMLCanvasElement` of the scene.
### onPointerDown
@ -93,7 +95,14 @@ This callback is triggered when mouse pointer is updated.
This prop if passed will be triggered on pointer down events and has the below signature.
<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>
### 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.
<pre>
(data: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/clipboard.ts#L18">ClipboardData</a>, event: ClipboardEvent &#124; null) => boolean
(data:{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/clipboard.ts#L18">
ClipboardData
</a>
, event: ClipboardEvent &#124; null) => boolean
</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.
@ -122,7 +135,7 @@ This callback if supplied will get triggered when the library is updated and has
<pre>
(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
</a>
) => void | Promise&lt;any&gt;
@ -130,13 +143,24 @@ This callback if supplied will get triggered when the library is updated and has
It is invoked with empty items when user clears the library. You can use this callback when you want to do something additional when library is updated for example persisting it to local storage.
### generateLinkForSelection
This prop if passed will be used to replace the default link generation function. The idea is that the host app can take over the creation of element links, which can be used to navigate to a particular element or a group. If the host app chooses a different key for element link id, then the host app should also take care of the handling and the navigation in `onLinkOpen`.
```tsx
(id: string, type: "element" | "group") => string;
```
### onLinkOpen
This prop if passed will be triggered when clicked on `link`. To handle the redirect yourself (such as when using your own router for internal links), you must call `event.preventDefault()`.
<pre>
(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement</a>,
event: CustomEvent&lt;&#123; nativeEvent: MouseEvent }&gt;) => void
(element:{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">
ExcalidrawElement
</a>
, event: CustomEvent&lt;&#123; nativeEvent: MouseEvent }&gt;) => void
</pre>
Example:
@ -166,7 +190,7 @@ const onLinkOpen: ExcalidrawProps["onLinkOpen"] = useCallback(
### 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
import { defaultLang, languages } from "@excalidraw/excalidraw";
@ -175,35 +199,33 @@ import { defaultLang, languages } from "@excalidraw/excalidraw";
| name | type |
| --- | --- |
| `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
This prop indicates whether the app is in `view mode`. When supplied, the value takes precedence over *intialData.appState.viewModeEnabled*, the `view mode` will be fully controlled by the host app, and users won't be able to toggle it from within the app.
This prop indicates whether the app is in `view mode`. When supplied, the value takes precedence over _intialData.appState.viewModeEnabled_, the `view mode` will be fully controlled by the host app, and users won't be able to toggle it from within the app.
### zenModeEnabled
This prop indicates whether the app is in `zen mode`. When supplied, the value takes precedence over *intialData.appState.zenModeEnabled*, the `zen mode` will be fully controlled by the host app, and users won't be able to toggle it from within the app.
This prop indicates whether the app is in `zen mode`. When supplied, the value takes precedence over _intialData.appState.zenModeEnabled_, the `zen mode` will be fully controlled by the host app, and users won't be able to toggle it from within the app.
### gridModeEnabled
This prop indicates whether the shows the grid. When supplied, the value takes precedence over *intialData.appState.gridModeEnabled*, the grid will be fully controlled by the host app, and users won't be able to toggle it from within the app.
This prop indicates whether the shows the grid. When supplied, the value takes precedence over _intialData.appState.gridModeEnabled_, the grid will be fully controlled by the host app, and users won't be able to toggle it from within the app.
### libraryReturnUrl
If supplied, this URL will be used when user tries to install a library from [libraries.excalidraw.com](https://libraries.excalidraw.com).
Defaults to *window.location.origin + window.location.pathname*. To install the libraries in the same tab from which it was opened, you need to set `window.name` (to any alphanumeric string) — if it's not set it will open in a new tab.
If supplied, this URL will be used when user tries to install a library from [libraries.excalidraw.com](https://libraries.excalidraw.com). Defaults to _window.location.origin + window.location.pathname_. To install the libraries in the same tab from which it was opened, you need to set `window.name` (to any alphanumeric string) — if it's not set it will open in a new tab.
### theme
This prop controls Excalidraw's theme. When supplied, the value takes precedence over *intialData.appState.theme*, the theme will be fully controlled by the host app, and users won't be able to toggle it from within the app unless *UIOptions.canvasActions.toggleTheme* is set to `true`, in which case the `theme` prop will control Excalidraw's default theme with ability to allow theme switching (you must take care of updating the `theme` prop when you detect a change to `appState.theme` from the [onChange](#onchange) callback).
This prop controls Excalidraw's theme. When supplied, the value takes precedence over _intialData.appState.theme_, the theme will be fully controlled by the host app, and users won't be able to toggle it from within the app unless _UIOptions.canvasActions.toggleTheme_ is set to `true`, in which case the `theme` prop will control Excalidraw's default theme with ability to allow theme switching (you must take care of updating the `theme` prop when you detect a change to `appState.theme` from the [onChange](#onchange) callback).
You can use [`THEME`](/docs/@excalidraw/excalidraw/api/utils#theme) to specify the theme.
### name
This prop sets the `name` of the drawing which will be used when exporting the drawing. When supplied, the value takes precedence over *intialData.appState.name*, the `name` will be fully controlled by host app and the users won't be able to edit from within Excalidraw.
This prop sets the `name` of the drawing which will be used when exporting the drawing. When supplied, the value takes precedence over _intialData.appState.name_, the `name` will be fully controlled by host app and the users won't be able to edit from within Excalidraw.
### detectScroll
@ -215,7 +237,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).
### autoFocus
This prop indicates whether to `focus` the Excalidraw component on page load. Defaults to false.
@ -228,3 +249,12 @@ Allows you to override `id` generation for files added on canvas (images). By de
(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.

View File

@ -4,10 +4,9 @@
<pre>
(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
</a>
) => JSX | null
</a>) => JSX | null
</pre>
A function returning `JSX` to render `custom` UI in the top right corner of the app.
@ -63,61 +62,19 @@ function App() {
}
```
## renderSidebar
## renderEmbeddable
```tsx
() => JSX | null;
```
<pre>
(element: NonDeleted&lt;ExcalidrawEmbeddableElement&gt;, 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.
### Sidebar
The `<Sidebar>` component takes these props (all are optional except `children`):
| Prop | Type | Description |
| Parameter | Type | Description |
| --- | --- | --- |
| `children` | `React.ReactNode` | Content you want to render inside the `sidebar`. |
| `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. |
| `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>
);
}
```
| `element` | `NonDeleted<ExcalidrawEmbeddableElement>` | The embeddable element to be rendered. |
| `appState` | `AppState` | The current state of the UI. |

View File

@ -1,10 +1,10 @@
# 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>
&#123;
<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
</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
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 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.

View File

@ -20,16 +20,16 @@ exportToCanvas(&#123;<br/>&nbsp;
getDimensions,<br/>&nbsp;
files,<br/>&nbsp;
exportPadding?: number;<br/>
&#125;: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L21">ExportOpts</a>
&#125;: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/utils/export.ts#L24">ExportOpts</a>
</pre>
| 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. |
| `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. |
| `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/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. |
| `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. |
@ -90,7 +90,7 @@ function App() {
<img src={canvasUrl} alt="" />
</div>
<div style={{ height: "400px" }}>
<Excalidraw ref={(api) => setExcalidrawAPI(api)}
<Excalidraw excalidrawAPI={(api) => setExcalidrawAPI(api)}
/>
</div>
</>
@ -105,7 +105,7 @@ function App() {
<pre>
exportToBlob(<br/>&nbsp;
opts: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L14">ExportOpts</a> & &#123;<br/>&nbsp;
opts: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/utils.ts#L14">ExportOpts</a> & &#123;<br/>&nbsp;
mimeType?: string,<br/>&nbsp;
quality?: number,<br/>&nbsp;
exportPadding?: number;<br/>
@ -134,16 +134,16 @@ Returns a promise which resolves with a [blob](https://developer.mozilla.org/en-
<pre>
exportToSvg(&#123;<br/>&nbsp;
elements:&nbsp;
<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[]
</a>,<br/>&nbsp;
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/>&nbsp;
exportPadding: number,<br/>&nbsp;
metadata: string,<br/>&nbsp;
files:&nbsp;
<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
</a>,<br/>
&#125;);
@ -151,10 +151,10 @@ exportToSvg(&#123;<br/>&nbsp;
| 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 `|
| 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 |
| 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/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 |
| 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.
@ -164,7 +164,7 @@ This function returns a promise which resolves to `svg` of the exported drawing.
<pre>
exportToClipboard(<br/>&nbsp;
opts: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L21">ExportOpts</a> & &#123;<br/>&nbsp;
opts: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/utils.ts#L21">ExportOpts</a> & &#123;<br/>&nbsp;
mimeType?: string,<br/>&nbsp;
quality?: number;<br/>&nbsp;
type: 'png' | 'svg' |'json'<br/>

View File

@ -8,7 +8,7 @@ id: "restore"
**_Signature_**
<pre>
restoreAppState(appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L34">ImportedDataState["appState"]</a>,<br/>&nbsp; localAppState: Partial&lt;<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/>&nbsp; localAppState: Partial&lt;<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>
**_How to use_**
@ -17,7 +17,7 @@ restoreAppState(appState: <a href="https://github.com/excalidraw/excalidraw/blob
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.
Use this as a way to not override user's defaults if you persist them.
@ -29,16 +29,16 @@ You can pass `null` / `undefined` if not applicable.
<pre>
restoreElements(
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ImportedDataState["elements"]</a>,<br/>&nbsp;
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/>&nbsp;
opts: &#123; refreshDimensions?: boolean, repairBindings?: boolean }<br/>
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ImportedDataState["elements"]</a>,<br/>&nbsp;
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/>&nbsp;
opts: &#123; refreshDimensions?: boolean, repairBindings?: boolean, normalizeIndices?: boolean }<br/>
)
</pre>
| Prop | Type | Description |
| ---- | ---- | ---- |
| `elements` | <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ImportedDataState["elements"]</a> | The `elements` to be restored |
| [`localElements`](#localelements) | <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a> &#124; null &#124; undefined | When `localElements` are supplied, they are used to ensure that existing restored elements reuse `version` (and increment it), and regenerate `versionNonce`. |
| `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> &#124; null &#124; 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
@ -51,8 +51,9 @@ The extra optional parameter to configure restored elements. It has the followin
| 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. |
| `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. |
| `normalizeIndices` |`boolean` | Indicates whether _fractional indices_ for the elements should be normalized. This is to prevent possible issues caused by using stale (too old, too long) indices. |
**_How to use_**
@ -70,15 +71,15 @@ Parameter `refreshDimensions` indicates whether we should also `recalculate` tex
<pre>
restore(
data: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L34">ImportedDataState</a>,<br/>&nbsp;
localAppState: Partial&lt;<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a>> | null | undefined,<br/>&nbsp;
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><br/>
opts: &#123; refreshDimensions?: boolean, repairBindings?: boolean }<br/>
data: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L34">ImportedDataState</a>,<br/>&nbsp;
localAppState: Partial&lt;<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a>> | null | undefined,<br/>&nbsp;
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: &#123; refreshDimensions?: boolean, repairBindings?: boolean, normalizeIndices?: boolean }<br/>
)
</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_**
@ -93,7 +94,7 @@ This function makes sure elements and state is set to appropriate values and set
**_Signature_**
<pre>
restoreLibraryItems(libraryItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L34">ImportedDataState["libraryItems"]</a>,<br/>&nbsp;
restoreLibraryItems(libraryItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L34">ImportedDataState["libraryItems"]</a>,<br/>&nbsp;
defaultStatus: "published" | "unpublished")
</pre>

View File

@ -8,7 +8,7 @@ These are pure Javascript functions exported from the @excalidraw/excalidraw [`@
### 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.
@ -16,8 +16,8 @@ If you want to overwrite the `source` field in the `JSON` string, you can set `w
<pre>
serializeAsJSON(&#123;<br/>&nbsp;
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a>,<br/>&nbsp;
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a>,<br/>
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a>,<br/>&nbsp;
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a>,<br/>
}): string
</pre>
@ -37,7 +37,7 @@ If you want to overwrite the source field in the JSON string, you can set `windo
<pre>
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>
**How to use**
@ -53,7 +53,7 @@ Returns `true` if element is invisibly small (e.g. width & height are zero).
**_Signature_**
<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>
**How to use**
@ -80,10 +80,10 @@ excalidrawAPI.updateScene(scene);
<pre>
loadFromBlob(<br/>&nbsp;
blob: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>,<br/>&nbsp;
localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a> | null,<br/>&nbsp;
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a> | null,<br/>&nbsp;
localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a> | null,<br/>&nbsp;
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a> | null,<br/>&nbsp;
fileHandle?: FileSystemHandle | null <br/>
) => Promise&lt;<a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L61">RestoredDataState</a>>
) => Promise&lt;<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/restore.ts#L61">RestoredDataState</a>>
</pre>
### loadLibraryFromBlob
@ -129,11 +129,11 @@ if (contents.type === MIME_TYPES.excalidraw) {
<pre>
loadSceneOrLibraryFromBlob(<br/>&nbsp;
blob: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>,
localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a> | null,<br/>&nbsp;
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a> | null,<br/>&nbsp;
blob: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>,<br/>&nbsp;
localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a> | null,<br/>&nbsp;
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a> | null,<br/>&nbsp;
fileHandle?: FileSystemHandle | null<br/>
) => Promise&lt;&#123; 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&lt;&#123; 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>
### getFreeDrawSvgPath
@ -149,7 +149,7 @@ import { getFreeDrawSvgPath } from "@excalidraw/excalidraw";
**Signature**
<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>
### isLinearElement
@ -164,9 +164,9 @@ import { isLinearElement } from "@excalidraw/excalidraw";
**Signature**
```tsx
isLinearElement(elementType?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L80">ExcalidrawElement</a>): boolean
```
<pre>
isLinearElement(elementType?: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L80">ExcalidrawElement</a>): boolean
</pre>
### getNonDeletedElements
@ -181,7 +181,7 @@ import { getNonDeletedElements } from "@excalidraw/excalidraw";
**Signature**
<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>
### mergeLibraryItems
@ -195,8 +195,10 @@ import { mergeLibraryItems } from "@excalidraw/excalidraw";
**_Signature_**
<pre>
mergeLibraryItems(localItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L250">LibraryItems</a>,<br/>&nbsp;
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>
mergeLibraryItems(<br/>&nbsp;
localItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L250">LibraryItems</a>,<br/>&nbsp;
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>
### parseLibraryTokensFromUrl
@ -237,8 +239,8 @@ export const App = () => {
<pre>
useHandleLibrary(opts: &#123;<br/>&nbsp;
excalidrawAPI: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L494">ExcalidrawAPI</a>,<br/>&nbsp;
getInitialLibraryItems?: () => <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L253">LibraryItemsSource</a><br/>
excalidrawAPI: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L494">ExcalidrawAPI</a>,<br/>&nbsp;
getInitialLibraryItems?: () => <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L253">LibraryItemsSource</a><br/>
});
</pre>
@ -251,7 +253,7 @@ This function returns the current `scene` version.
**_Signature_**
<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>
**How to use**
@ -272,7 +274,7 @@ import { sceneCoordsToViewportCoords } from "@excalidraw/excalidraw";
<pre>
sceneCoordsToViewportCoords(&#123; sceneX: number, sceneY: number },<br/>&nbsp;
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a><br/>): &#123; x: number, y: number }
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a><br/>): &#123; x: number, y: number }
</pre>
### viewportCoordsToSceneCoords
@ -287,7 +289,7 @@ import { viewportCoordsToSceneCoords } from "@excalidraw/excalidraw";
<pre>
viewportCoordsToSceneCoords(&#123; clientX: number, clientY: number },<br/>&nbsp;
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a><br/>): &#123;x: number, y: number}
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a><br/>): &#123;x: number, y: number}
</pre>
### useDevice
@ -299,7 +301,7 @@ Open the `main menu` in the below example to view the footer.
```jsx live noInline
const MobileFooter = ({}) => {
const device = useDevice();
if (device.isMobile) {
if (device.editor.isMobile) {
return (
<Footer>
<button
@ -331,14 +333,15 @@ const 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 |
| --- | --- | --- |
| `isSmScreen` | `boolean` | Set to `true` when the device small screen is small (Width < `640px` ) |
| `isMobile` | `boolean` | Set to `true` when the device is `mobile` |
| `isTouchScreen` | `boolean` | Set to `true` for `touch` devices |
| `canDeviceFitSidebar` | `boolean` | Implies whether there is enough space to fit the `sidebar` |
| `viewport.isMobile` | `boolean` | Set to `true` when viewport is in `mobile` breakpoint |
| `viewport.isLandscape` | `boolean` | Set to `true` when the viewport is in `landscape` mode |
| `editor.canFitSidebar` | `boolean` | Set to `true` if there's enough space to fit the `sidebar` |
| `editor.isMobile` | `boolean` | Set to `true` when editor container is in `mobile` breakpoint |
| `isTouchScreen` | `boolean` | Set to `true` for `touch` when touch event detected |
### i18n
@ -347,8 +350,8 @@ To help with localization, we export the following.
| name | type |
| --- | --- |
| `defaultLang` | `string` |
| `languages` | [`Language[]`](https://github.com/excalidraw/excalidraw/blob/master/src/i18n.ts#L15) |
| `useI18n` | [`() => { langCode, t }`](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) |
| `useI18n` | [`() => { langCode, t }`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/i18n.ts#L15) |
```js
import { defaultLang, languages, useI18n } from "@excalidraw/excalidraw";
@ -383,3 +386,94 @@ function App() {
);
}
```
### getCommonBounds
This util can be used to get the common bounds of the passed elements.
**_Signature_**
```ts
getCommonBounds(
elements: readonly ExcalidrawElement[]
): readonly [
minX: number,
minY: number,
maxX: number,
maxY: number,
]
```
**_How to use_**
```js
import { getCommonBounds } from "@excalidraw/excalidraw";
```
### elementsOverlappingBBox
To filter `elements` that are inside, overlap, or contain the `bounds` rectangle.
The bounds check is approximate and does not precisely follow the element's shape. You can also supply `errorMargin` which effectively makes the `bounds` larger by that amount.
This API has 3 `type`s of operation: `overlap`, `contain`, and `inside`:
- `overlap` - filters elements that are overlapping or inside bounds.
- `contain` - filters elements that are inside bounds or bounds inside elements.
- `inside` - filters elements that are inside bounds.
**_Signature_**
<pre>
elementsOverlappingBBox(<br/>&nbsp;
elements: readonly NonDeletedExcalidrawElement[];<br/>&nbsp;
bounds: <a href="https://github.com/excalidraw/excalidraw/blob/9c425224c789d083bf16e0597ce4a429b9ee008e/src/element/bounds.ts#L37-L42">Bounds</a> | ExcalidrawElement;<br/>&nbsp;
errorMargin?: number;<br/>&nbsp;
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/>&nbsp;
element: NonDeletedExcalidrawElement,<br/>&nbsp;
bounds: <a href="https://github.com/excalidraw/excalidraw/blob/9c425224c789d083bf16e0597ce4a429b9ee008e/src/element/bounds.ts#L37-L42">Bounds</a>,<br/>&nbsp;
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/>&nbsp;
element: NonDeletedExcalidrawElement,<br/>&nbsp;
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";
```

View File

@ -1,6 +1,6 @@
# 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:
@ -21,7 +21,7 @@ Most notably, you can customize the primary colors, by overriding these variable
- `--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.
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
.custom-styles .excalidraw {

View File

@ -13,18 +13,18 @@ To start the example app using the `@excalidraw/excalidraw` package, follow the
1. Install the dependencies
```bash
cd src/packages/excalidraw && yarn
yarn
```
2. Start the example app
```bash
yarn start
yarn start:example
```
[http://localhost:3001](http://localhost:3001) will open in your default browser.
The example is same as the [codesandbox example](https://ehlz3.csb.app/)
This is the same example as the [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/master/examples/with-script-in-browser) example.
## Releasing
@ -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:
```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.
@ -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:
```bash
yarn release
yarn release:excalidraw
```
This will publish the package.

View File

@ -2,7 +2,7 @@
### 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
@ -17,11 +17,9 @@ We strongly recommend turning it off. You can follow the steps below on how to d
<div style={{width:'30rem'}}>
2. Once opened, look for **Aggressively Block Fingerprinting**
![Aggresive block fingerprinting](../../assets/aggressive-block-fingerprint.png)
![Aggressive block fingerprinting](../../assets/aggressive-block-fingerprint.png)
3. Switch to **Block Fingerprinting**
![Block filtering](../../assets/block-fingerprint.png)
4. Thats all. All text elements should be fixed now 🎉
@ -31,6 +29,17 @@ We strongly recommend turning it off. You can follow the steps below on how to d
If disabling this setting doesn't fix the display of text elements, please consider opening an [issue](https://github.com/excalidraw/excalidraw/issues/new) on our GitHub, or message us on [Discord](https://discord.gg/UexuTaE).
### ReferenceError: process is not defined
When using `vite` or any build tools, you will have to make sure the `process` is accessible as we are accessing `process.env.IS_PREACT` to decide whether to use `preact` build.
Since Vite removes env variables by default, you can update the vite config to ensure its available :point_down:
```
define: {
"process.env.IS_PREACT": JSON.stringify("true"),
},
```
## Need help?

View File

@ -1,16 +1,12 @@
# Installation
**Excalidraw** is published to npm as a component you can directly embed in your projects.
**Excalidraw** is exported as a component to be directly embedded in your project.
Using `npm`:
Use `npm` or `yarn` to install the package.
```bash
npm install react react-dom @excalidraw/excalidraw
```
or `yarn`:
```bash
# or
yarn add react react-dom @excalidraw/excalidraw
```
@ -20,24 +16,40 @@ yarn add react react-dom @excalidraw/excalidraw
:::
### Static assets
### Self-hosting fonts
Excalidraw depends on assets such as localization files (if you opt to use them), fonts, and others.
By default, Excalidraw will try to download all the used fonts from the [CDN](https://esm.run/@excalidraw/excalidraw/dist/prod).
By default these assets are loaded from a public CDN [`https://unpkg.com/@excalidraw/excalidraw/dist/`](https://unpkg.com/@excalidraw/excalidraw/dist), so you don't need to do anything on your end.
However, if you want to host these files yourself, you can find them in your `node_modules/@excalidraw/excalidraw/dist` directory, in folders `excalidraw-assets` (for production) and `excalidraw-assets-dev` (for development).
Copy these folders to your static assets directory, and add a `window.EXCALIDRAW_ASSET_PATH` variable in your `index.html` or `index.js` entry file pointing to your public assets path (relative). For example, if you serve your assets from the root of your hostname, you would do:
For self-hosting purposes, you'll have to copy the content of the folder `node_modules/@excalidraw/excalidraw/dist/prod/fonts` to the path where your assets should be served from (i.e. `public/` directory in your project). In that case, you should also set `window.EXCALIDRAW_ASSET_PATH` to the very same path, i.e. `/` in case it's in the root:
```js
window.EXCALIDRAW_ASSET_PATH = "/";
```
or, if you serve your assets from the root of your CDN, you would do:
```js
// Vanilla
<head>
<script>
window.EXCALIDRAW_ASSET_PATH = "https://my.cdn.com/assets/";
</script>
</head>
```
or, if you prefer the path to be dynamicly set based on the `location.origin`, you could do the following:
```jsx
// Next.js
<Script id="load-env-variables" strategy="beforeInteractive" >
{ `window["EXCALIDRAW_ASSET_PATH"] = location.origin;` } // or use just "/"!
</Script>
```
### Dimensions of Excalidraw
Excalidraw takes _100%_ of `width` and `height` of the containing block so make sure the container in which you render Excalidraw has non zero dimensions.
### Demo
## Demo
[Try here](https://codesandbox.io/s/excalidraw-ehlz3).
Go to [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/master/examples/with-script-in-browser) example.

View File

@ -12,7 +12,7 @@ import { Excalidraw } from "@excalidraw/excalidraw";
Throughout the documentation we use live, editable Excalidraw examples like the one shown below.
While we aim for the examples to closely reflect what you'd get if you rendered it yourself, we actually initialize it with some props behind the scenes.
While we aim for the examples to closely reflect what you'd get if you rendered it yourself, we actually initialize it with some props behind the scenes.
For example, we're passing a `theme` prop to it based on the current color theme of the docs you're just reading.
:::
@ -30,48 +30,135 @@ 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
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() {
const [Excalidraw, setExcalidraw] = useState(null);
useEffect(() => {
import("@excalidraw/excalidraw").then((comp) => setExcalidraw(comp.Excalidraw));
}, []);
return <>{Excalidraw && <Excalidraw />}</>;
return <Excalidraw />;
}
```
The `types` are available at `@excalidraw/excalidraw/types`, you can view [example for typescript](https://codesandbox.io/s/excalidraw-types-9h2dm)
However the above component only works for named component exports. If you want to import some util / constant or something else apart from Excalidraw, then this approach will not work. Instead you can write a wrapper over Excalidraw and import the wrapper dynamically.
If you are using `pages router` then importing the wrapper dynamically would work, where as if you are using `app router` then you will have to also add `useClient` directive on top of the file in addition to dynamically importing the wrapper as shown :point_down:
<Tabs>
<TabItem value="Excalidraw Wrapper" label="Excalidraw Wrapper" >
```jsx showLineNumbers
"use client";
import { Excalidraw, convertToExcalidrawElements } from "@excalidraw/excalidraw";
import "@excalidraw/excalidraw/index.css";
const ExcalidrawWrapper: React.FC = () => {
console.info(convertToExcalidrawElements([{
type: "rectangle",
id: "rect-1",
width: 186.47265625,
height: 141.9765625,
},]));
return (
<div style={{height:"500px", width:"500px"}}>
<Excalidraw />
</div>
);
};
export default ExcalidrawWrapper;
```
</TabItem>
<TabItem value="pages" label="Pages router">
```jsx showLineNumbers
import dynamic from "next/dynamic";
// Since client components get prerenderd on server as well hence importing
// the excalidraw stuff dynamically with ssr false
const ExcalidrawWrapper = dynamic(
async () => (await import("../excalidrawWrapper")).default,
{
ssr: false,
},
);
export default function Page() {
return (
<ExcalidrawWrapper />
);
}
```
</TabItem>
<TabItem value="app" label="App router">
```jsx showLineNumbers
import dynamic from "next/dynamic";
// Since client components get prerenderd on server as well hence importing
// the excalidraw stuff dynamically with ssr false
const ExcalidrawWrapper = dynamic(
async () => (await import("../excalidrawWrapper")).default,
{
ssr: false,
},
);
export default function Page() {
return (
<ExcalidrawWrapper />
);
}
```
</TabItem>
</Tabs>
{/* Link should be updated to point to the latest! */}
Here is a [source code](https://github.com/excalidraw/excalidraw/tree/master/examples/with-nextjs) for the example with app and pages router. You you can try it out [here](https://excalidraw-package-example-with-nextjs.vercel.app/).
The `types` are available at `@excalidraw/excalidraw/types`, check [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/master/examples/with-script-in-browser) example for details.
### Preact
Since we support `umd` build ships with `react/jsx-runtime` and `react-dom/client` inlined with the package. This conflicts with `Preact` and hence the build doesn't work directly with `Preact`.
However we have shipped a separate build for `Preact` so if you are using `Preact` you need to set `process.env.IS_PREACT` to `true` to use the `Preact` build.
Once the above `env` variable is set, you will be able to use the package in `Preact` as well.
:::info
When using `vite` or any build tools, you will have to make sure the `process` is accessible as we are accessing `process.env.IS_PREACT` to decide whether to use `preact` build.
Since Vite removes env variables by default, you can update the vite config to ensure its available :point_down:
```
define: {
"process.env.IS_PREACT": JSON.stringify("true"),
},
```
:::
## Browser
To use it in a browser directly:
To use it Excalidraw in a browser directly, use the following setup :point_down:
For development use :point_down:
```js
<script
type="text/javascript"
src="https://unpkg.com/@excalidraw/excalidraw/dist/excalidraw.development.js"
></script>
```
For production use :point_down:
```js
<script
type="text/javascript"
src="https://unpkg.com/@excalidraw/excalidraw/dist/excalidraw.production.min.js"
></script>
```
You will need to make sure `react`, `react-dom` is available as shown in the below example. For prod please use the production versions of `react`, `react-dom`.
> **Note**: We rely on import maps to de-duplicate `react`, `react-dom` and `react/jsx-runtime` versions.
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
@ -85,13 +172,23 @@ import TabItem from "@theme/TabItem";
<head>
<title>Excalidraw in browser</title>
<meta charset="UTF-8" />
<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>
<script
type="text/javascript"
src="https://unpkg.com/@excalidraw/excalidraw/dist/excalidraw.development.js"
></script>
<link
rel="stylesheet"
href="https://esm.sh/@excalidraw/excalidraw@0.18.0/dist/dev/index.css"
/>
<link rel="stylesheet" href="./index.css" />
<script>
window.EXCALIDRAW_ASSET_PATH = "https://esm.sh/@excalidraw/excalidraw@0.18.0/dist/prod/";
</script>
<script type="importmap">
{
"imports": {
"react": "https://esm.sh/react@19.0.0",
"react/jsx-runtime": "https://esm.sh/react@19.0.0/jsx-runtime",
"react-dom": "https://esm.sh/react-dom@19.0.0"
}
}
</script>
</head>
<body>
@ -99,7 +196,7 @@ import TabItem from "@theme/TabItem";
<h1>Excalidraw Embed Example</h1>
<div id="app"></div>
</div>
<script type="text/javascript" src="src/index.js"></script>
<script type="text/javascript" src="packages/excalidraw/index.js"></script>
</body>
</html>
```
@ -108,6 +205,14 @@ import TabItem from "@theme/TabItem";
<TabItem value="js" label="Javascript">
```js showLineNumbers
// See https://www.npmjs.com/package/@excalidraw/excalidraw documentation.
import * as ExcalidrawLib from 'https://esm.sh/@excalidraw/excalidraw@0.18.0/dist/dev/index.js?external=react,react-dom';
import React from "https://esm.sh/react@19.0.0";
import ReactDOM from "https://esm.sh/react-dom@19.0.0"
window.ExcalidrawLib = ExcalidrawLib;
console.log("Excalidraw library", ExcalidrawLib);
const App = () => {
return React.createElement(
React.Fragment,
@ -129,3 +234,5 @@ root.render(React.createElement(App));
</TabItem>
</Tabs>
You can try it out [here](https://jsfiddle.net/vfn6dm14/3/).

View 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 parseMermaidToExcalidraw(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"/>

View File

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

View File

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

View File

@ -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.
![image](https://github.com/excalidraw/excalidraw/assets/11256141/2a097bbb-64bf-49d6-bf7f-21172bdb538d)
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
![image](https://github.com/excalidraw/excalidraw/assets/11256141/d7013305-0b90-4fa0-a66e-b4f4604ad0b2)
## 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:
![image](https://github.com/excalidraw/excalidraw/assets/11256141/5243ce4c-beaa-43d2-812a-0577b0a574d7)
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"
}
]
```

View File

@ -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:
![image](https://github.com/excalidraw/excalidraw/assets/11256141/8e060de7-b867-44ad-864b-0c1b24466b67)
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
![image](https://github.com/excalidraw/excalidraw/assets/11256141/2c24cf7b-f096-4c12-88db-55520de27558)
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).
![image](https://github.com/excalidraw/excalidraw/assets/11256141/3a4825d8-9704-468c-a02f-7e507f4d5b7a)
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).
![image](https://github.com/excalidraw/excalidraw/assets/11256141/00226e9d-043d-4a08-989a-3ad9d2a574f1)

View File

@ -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 🎉

View File

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

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

View 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": 20,
"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 |

View File

@ -15,7 +15,7 @@ In case you want to pick up something from the roadmap, comment on that issue an
1. Run `yarn` to install dependencies
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
> git remote add upstream https://github.com/excalidraw/excalidraw.git
@ -52,15 +52,6 @@ Make sure the title starts with a semantic prefix:
- **chore**: Other changes that don't modify src or test files
- **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
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.
@ -69,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.
:::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

View File

@ -14,3 +14,4 @@ These docs are focused on developers, and structured in the following way:
- [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.
- 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

View File

@ -1,6 +1,11 @@
// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
// Set the env variable to false so the excalidraw npm package doesn't throw
// process undefined as docusaurus doesn't expose env variables by default
process.env.IS_PREACT = "false";
/** @type {import('@docusaurus/types').Config} */
const config = {
title: "Excalidraw developer docs",
@ -10,7 +15,7 @@ const config = {
baseUrl: "/",
onBrokenLinks: "throw",
onBrokenMarkdownLinks: "warn",
favicon: "img/favicon.ico",
favicon: "img/favicon.png",
organizationName: "Excalidraw", // Usually your GitHub org/user name.
projectName: "excalidraw", // Usually your repo name.
@ -36,10 +41,7 @@ const config = {
showLastUpdateTime: true,
},
theme: {
customCss: [
require.resolve("./src/css/custom.scss"),
require.resolve("../src/packages/excalidraw/example/App.scss"),
],
customCss: [require.resolve("./src/css/custom.scss")],
},
}),
],
@ -64,7 +66,7 @@ const config = {
label: "Docs",
},
{
to: "https://blog.excalidraw.com",
to: "https://plus.excalidraw.com/blog",
label: "Blog",
position: "left",
},
@ -109,7 +111,7 @@ const config = {
items: [
{
label: "Blog",
to: "https://blog.excalidraw.com",
to: "https://plus.excalidraw.com/blog",
},
{
label: "GitHub",
@ -123,7 +125,7 @@ const config = {
prism: {
theme: require("prism-react-renderer/themes/dracula"),
},
image: "img/og-image.png",
image: "img/og-image-2.png",
docs: {
sidebar: {
hideable: true,
@ -139,7 +141,38 @@ const config = {
},
}),
themes: ["@docusaurus/theme-live-codeblock"],
plugins: ["docusaurus-plugin-sass"],
plugins: [
"docusaurus-plugin-sass",
[
"docusaurus2-dotenv",
{
systemvars: true,
},
],
function () {
return {
name: "disable-fully-specified-error",
configureWebpack() {
return {
module: {
rules: [
{
test: /\.m?js$/,
resolve: {
fullySpecified: false,
},
},
],
},
optimization: {
// disable terser minification
minimize: false,
},
};
},
};
},
],
};
module.exports = config;

View File

@ -18,18 +18,19 @@
"@docusaurus/core": "2.2.0",
"@docusaurus/preset-classic": "2.2.0",
"@docusaurus/theme-live-codeblock": "2.2.0",
"@excalidraw/excalidraw": "0.15.2",
"@excalidraw/excalidraw": "0.18.0",
"@mdx-js/react": "^1.6.22",
"clsx": "^1.2.1",
"docusaurus-plugin-sass": "0.2.3",
"prism-react-renderer": "^1.3.5",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"sass": "1.57.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "2.0.0-rc.1",
"@tsconfig/docusaurus": "^1.0.5",
"docusaurus2-dotenv": "1.4.0",
"typescript": "^4.7.4"
},
"browserslist": {

View File

@ -23,7 +23,11 @@ const sidebars = {
},
items: ["introduction/development", "introduction/contributing"],
},
{
type: "category",
label: "Codebase",
items: ["codebase/json-schema", "codebase/frames"],
},
{
type: "category",
label: "@excalidraw/excalidraw",
@ -49,7 +53,7 @@ const sidebars = {
},
items: [
"@excalidraw/excalidraw/api/props/initialdata",
"@excalidraw/excalidraw/api/props/ref",
"@excalidraw/excalidraw/api/props/excalidraw-api",
"@excalidraw/excalidraw/api/props/render-props",
"@excalidraw/excalidraw/api/props/ui-options",
],
@ -64,6 +68,7 @@ const sidebars = {
items: [
"@excalidraw/excalidraw/api/children-components/main-menu",
"@excalidraw/excalidraw/api/children-components/welcome-screen",
"@excalidraw/excalidraw/api/children-components/sidebar",
"@excalidraw/excalidraw/api/children-components/footer",
"@excalidraw/excalidraw/api/children-components/live-collaboration-trigger",
],
@ -80,18 +85,48 @@ const sidebars = {
"@excalidraw/excalidraw/api/utils/restore",
],
},
{
type: "category",
label: "Constants",
link: { type: "doc", id: "@excalidraw/excalidraw/api/constants" },
items: [],
},
"@excalidraw/excalidraw/api/constants",
"@excalidraw/excalidraw/api/excalidraw-element-skeleton",
],
},
"@excalidraw/excalidraw/faq",
"@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",
],
},
],
},
],
};

View File

@ -1,5 +1,6 @@
import React from "react";
import clsx from "clsx";
import React from "react";
import styles from "./styles.module.css";
const FeatureList = [
@ -15,7 +16,7 @@ const FeatureList = [
Svg: require("@site/static/img/undraw_blank_canvas.svg").default,
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?
</>
),

View File

@ -1,5 +1,6 @@
import React from "react";
import clsx from "clsx";
import React from "react";
import styles from "./styles.module.css";
type FeatureItem = {

View File

@ -59,7 +59,7 @@ pre a {
padding: 5px;
background: #70b1ec;
color: white;
font-weight: bold;
font-weight: 700;
border: none;
}

View File

@ -1,10 +1,11 @@
import React from "react";
import clsx from "clsx";
import Layout from "@theme/Layout";
import Link from "@docusaurus/Link";
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import styles from "./index.module.css";
import HomepageFeatures from "@site/src/components/Homepage";
import Layout from "@theme/Layout";
import clsx from "clsx";
import React from "react";
import styles from "./index.module.css";
function HomepageHeader() {
const { siteConfig } = useDocusaurusContext();

View File

@ -1,6 +1,6 @@
// Import the original mapper
import MDXComponents from "@theme-original/MDXComponents";
import Highlight from "@site/src/components/Highlight";
import MDXComponents from "@theme-original/MDXComponents";
export default {
// Re-use the default mapping

View File

@ -3,11 +3,18 @@ import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
import initialData from "@site/src/initialData";
import { useColorMode } from "@docusaurus/theme-common";
import "@excalidraw/excalidraw/index.css";
let ExcalidrawComp = {};
if (ExecutionEnvironment.canUseDOM) {
ExcalidrawComp = require("@excalidraw/excalidraw");
}
const Excalidraw = React.forwardRef((props, ref) => {
if (!window.EXCALIDRAW_ASSET_PATH) {
window.EXCALIDRAW_ASSET_PATH =
"https://esm.sh/@excalidraw/excalidraw@0.18.0/dist/prod/";
}
const { colorMode } = useColorMode();
return <ExcalidrawComp.Excalidraw theme={colorMode} {...props} ref={ref} />;
});
@ -25,6 +32,7 @@ const ExcalidrawScope = {
exportToCanvas: ExcalidrawComp.exportToCanvas,
initialData,
useI18n: ExcalidrawComp.useI18n,
convertToExcalidrawElements: ExcalidrawComp.convertToExcalidrawElements,
};
export default ExcalidrawScope;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -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">
<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)" />
<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 xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
<rect width="1000" height="1000" rx="200" ry="200" fill="#fff" />
<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>

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

4
dev-docs/vercel.json Normal file
View File

@ -0,0 +1,4 @@
{
"outputDirectory": "build",
"installCommand": "yarn install"
}

File diff suppressed because it is too large Load Diff

39
examples/with-nextjs/.gitignore vendored Normal file
View File

@ -0,0 +1,39 @@
# 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
# copied assets
public/**/*.woff2

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

View 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;

View File

@ -0,0 +1,25 @@
{
"name": "with-nextjs",
"version": "0.1.0",
"private": true,
"scripts": {
"build:workspace": "yarn workspace @excalidraw/excalidraw run build:esm && yarn copy:assets",
"copy:assets": "cp -r ../../packages/excalidraw/dist/prod/fonts ./public",
"dev": "yarn build:workspace && next dev -p 3005",
"build": "yarn build:workspace && next build",
"start": "next start -p 3006",
"lint": "next lint"
},
"dependencies": {
"next": "14.1",
"react": "19.0.0",
"react-dom": "19.0.0"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "19.0.10",
"@types/react-dom": "19.0.4",
"path2d-polyfill": "2.0.1",
"typescript": "^5"
}
}

View File

Before

Width:  |  Height:  |  Size: 197 KiB

After

Width:  |  Height:  |  Size: 197 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,11 @@
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}

View File

@ -0,0 +1,27 @@
import dynamic from "next/dynamic";
import Script from "next/script";
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>
<Script id="load-env-variables" strategy="beforeInteractive">
{`window["EXCALIDRAW_ASSET_PATH"] = window.origin;`}
</Script>
{/* @ts-expect-error - https://github.com/vercel/next.js/issues/42292 */}
<ExcalidrawWithClientOnly />
</>
);
}

View File

@ -0,0 +1,15 @@
* {
box-sizing: border-box;
font-family: sans-serif;
}
a {
color: #1c7ed6;
font-size: 20px;
text-decoration: none;
font-weight: 500;
}
.page-title {
text-align: center;
}

View File

@ -0,0 +1,23 @@
"use client";
import * as excalidrawLib from "@excalidraw/excalidraw";
import { Excalidraw } from "@excalidraw/excalidraw";
import "@excalidraw/excalidraw/index.css";
import App from "../../with-script-in-browser/components/ExampleApp";
const ExcalidrawWrapper: React.FC = () => {
return (
<>
<App
appTitle={"Excalidraw with Nextjs Example"}
useCustom={(api: any, args?: any[]) => {}}
excalidrawLib={excalidrawLib}
>
<Excalidraw />
</App>
</>
);
};
export default ExcalidrawWrapper;

View 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 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 />
</>
);
}

View 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"]
}

View File

@ -0,0 +1,3 @@
{
"outputDirectory": "build"
}

View 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"

View 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

View File

@ -0,0 +1,35 @@
{
// These tasks will run in order when initializing your CodeSandbox project.
"setupTasks": [
{
"name": "Install Dependencies",
"command": "yarn install"
}
],
// These tasks can be run from CodeSandbox. Running one will open a log in the app.
"tasks": {
"build": {
"name": "Build",
"command": "yarn build",
"runAtStart": false
},
"start": {
"name": "Start Example",
"command": "yarn start",
"runAtStart": true,
"preview": {
"port": 3001
}
},
"install-deps": {
"name": "Install Dependencies",
"command": "yarn install",
"restartOn": {
"files": ["yarn.lock"],
"branch": false,
"resume": false
}
}
}
}

View File

@ -0,0 +1,2 @@
# copied assets
public/**/*.woff2

View File

@ -1,6 +1,7 @@
import { ExcalidrawImperativeAPI } from "../../../types";
import { MIME_TYPES } from "../entry";
import { Button } from "../../../components/Button";
import React from "react";
import type * as TExcalidraw from "@excalidraw/excalidraw";
import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types";
const COMMENT_SVG = (
<svg
@ -18,24 +19,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>
</svg>
);
const CustomFooter = ({
excalidrawAPI,
excalidrawLib,
}: {
excalidrawAPI: ExcalidrawImperativeAPI;
excalidrawLib: typeof TExcalidraw;
}) => {
const { Button, MIME_TYPES } = excalidrawLib;
return (
<>
<Button
onSelect={() => alert("General Kenobi!")}
className="you are a bold one"
style={{ marginLeft: "1rem" }}
style={{ marginLeft: "1rem", width: "auto" }}
title="Hello there!"
>
{COMMENT_SVG}
Hit me
</Button>
<button
<Button
className="custom-element"
onClick={() => {
onSelect={() => {
excalidrawAPI?.setActiveTool({
type: "custom",
customType: "comment",
@ -58,15 +63,10 @@ const CustomFooter = ({
)}`;
excalidrawAPI?.setCursor(`url(${url}), auto`);
}}
title="Comments!"
>
{COMMENT_SVG}
</button>
<button
className="custom-footer"
onClick={() => alert("This is dummy footer")}
>
custom footer
</button>
</Button>
</>
);
};

View File

@ -15,14 +15,23 @@
border-radius: 50%;
}
}
.app-title {
margin-block-start: 0.83em;
margin-block-end: 0.83em;
}
}
.button-wrapper button {
z-index: 1;
height: 40px;
max-width: 200px;
margin: 10px;
padding: 5px;
.button-wrapper {
input[type="checkbox"] {
margin: 5px;
}
button {
z-index: 1;
height: 40px;
max-width: 200px;
margin: 10px;
padding: 5px;
}
}
.excalidraw .App-menu_top .buttonList {

View File

@ -1,23 +1,20 @@
import { useEffect, useState, useRef, useCallback } from "react";
import ExampleSidebar from "./sidebar/ExampleSidebar";
import type * as TExcalidraw from "../index";
import "./App.scss";
import initialData from "./initialData";
import { nanoid } from "nanoid";
import {
resolvablePromise,
ResolvablePromise,
withBatchedUpdates,
withBatchedUpdatesThrottled,
} from "../../../utils";
import { EVENT, ROUNDNESS } from "../../../constants";
import { distance2d } from "../../../math";
import { fileOpen } from "../../../data/filesystem";
import { loadSceneOrLibraryFromBlob } from "../../utils";
import {
import React, {
useEffect,
useState,
useRef,
useCallback,
Children,
cloneElement,
} from "react";
import type * as TExcalidraw from "@excalidraw/excalidraw";
import type { ImportedLibraryData } from "@excalidraw/excalidraw/data/types";
import type {
NonDeletedExcalidrawElement,
Theme,
} from "@excalidraw/excalidraw/element/types";
import type {
AppState,
BinaryFileData,
ExcalidrawImperativeAPI,
@ -25,18 +22,24 @@ import {
Gesture,
LibraryItems,
PointerDownState as ExcalidrawPointerDownState,
} from "../../../types";
import { NonDeletedExcalidrawElement } from "../../../element/types";
import { ImportedLibraryData } from "../../../data/types";
} from "@excalidraw/excalidraw/types";
import initialData from "../initialData";
import {
resolvablePromise,
distance2d,
fileOpen,
withBatchedUpdates,
withBatchedUpdatesThrottled,
} from "../utils";
import CustomFooter from "./CustomFooter";
import MobileFooter from "./MobileFooter";
import { KEYS } from "../../../keys";
import ExampleSidebar from "./sidebar/ExampleSidebar";
declare global {
interface Window {
ExcalidrawLib: typeof TExcalidraw;
}
}
import "./ExampleApp.scss";
import type { ResolvablePromise } from "../utils";
type Comment = {
x: number;
@ -57,26 +60,6 @@ type PointerDownState = {
};
};
// 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_INPUT_HEIGHT = 50;
const COMMENT_INPUT_WIDTH = 150;
@ -85,9 +68,38 @@ export interface AppProps {
appTitle: string;
useCustom: (api: ExcalidrawImperativeAPI | null, customArgs?: any[]) => void;
customArgs?: any[];
children: React.ReactNode;
excalidrawLib: typeof TExcalidraw;
}
export default function App({ appTitle, useCustom, customArgs }: AppProps) {
export default function ExampleApp({
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 [viewModeEnabled, setViewModeEnabled] = useState(false);
const [zenModeEnabled, setZenModeEnabled] = useState(false);
@ -96,7 +108,8 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
const [canvasUrl, setCanvasUrl] = useState<string>("");
const [exportWithDarkMode, setExportWithDarkMode] = 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 [commentIcons, setCommentIcons] = useState<{ [id: string]: Comment }>(
{},
@ -140,13 +153,113 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
];
//@ts-ignore
initialStatePromiseRef.current.promise.resolve(initialData);
initialStatePromiseRef.current.promise.resolve({
...initialData,
elements: convertToExcalidrawElements(initialData.elements),
});
excalidrawAPI.addFiles(imagesArray);
};
};
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) => {
return (
<>
@ -184,38 +297,40 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
const updateScene = () => {
const sceneData = {
elements: restoreElements(
[
convertToExcalidrawElements([
{
type: "rectangle",
version: 141,
versionNonce: 361174001,
isDeleted: false,
id: "oDVXy8D6rom3H1-LLH2-f",
id: "rect-1",
fillStyle: "hachure",
strokeWidth: 1,
strokeStyle: "solid",
roughness: 1,
opacity: 100,
angle: 0,
x: 100.50390625,
y: 93.67578125,
strokeColor: "#c92a2a",
backgroundColor: "transparent",
width: 186.47265625,
height: 141.9765625,
seed: 1968410350,
groupIds: [],
frameId: null,
boundElements: null,
locked: false,
link: null,
updated: 1,
roundness: {
type: ROUNDNESS.ADAPTIVE_RADIUS,
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,
),
appState: {
@ -328,8 +443,8 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
pointerDownState: PointerDownState,
) => {
return withBatchedUpdates((event) => {
window.removeEventListener(EVENT.POINTER_MOVE, pointerDownState.onMove);
window.removeEventListener(EVENT.POINTER_UP, pointerDownState.onUp);
window.removeEventListener("pointermove", pointerDownState.onMove);
window.removeEventListener("pointerup", pointerDownState.onUp);
excalidrawAPI?.setActiveTool({ type: "selection" });
const distance = distance2d(
pointerDownState.x,
@ -393,8 +508,8 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
onPointerMoveFromPointerDownHandler(pointerDownState);
const onPointerUp =
onPointerUpFromPointerDownHandler(pointerDownState);
window.addEventListener(EVENT.POINTER_MOVE, onPointerMove);
window.addEventListener(EVENT.POINTER_UP, onPointerUp);
window.addEventListener("pointermove", onPointerMove);
window.addEventListener("pointerup", onPointerUp);
pointerDownState.onMove = onPointerMove;
pointerDownState.onUp = onPointerUp;
@ -486,7 +601,7 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
}}
onBlur={saveComment}
onKeyDown={(event) => {
if (!event.shiftKey && event.key === KEYS.ENTER) {
if (!event.shiftKey && event.key === "Enter") {
event.preventDefault();
saveComment();
}
@ -519,7 +634,12 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
</MainMenu.ItemCustom>
<MainMenu.DefaultItems.Help />
{excalidrawAPI && <MobileFooter excalidrawAPI={excalidrawAPI} />}
{excalidrawAPI && (
<MobileFooter
excalidrawLib={excalidrawLib}
excalidrawAPI={excalidrawAPI}
/>
)}
</MainMenu>
);
};
@ -595,15 +715,21 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
type="checkbox"
checked={theme === "dark"}
onChange={() => {
let newTheme = "light";
if (theme === "light") {
newTheme = "dark";
}
setTheme(newTheme);
setTheme(theme === "light" ? "dark" : "light");
}}
/>
Switch to Dark Theme
</label>
<label>
<input
type="checkbox"
checked={disableImageTool === true}
onChange={() => {
setDisableImageTool(!disableImageTool);
}}
/>
Disable Image Tool
</label>
<label>
<input
type="checkbox"
@ -662,60 +788,7 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
</div>
</div>
<div className="excalidraw-wrapper">
<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}
>
{excalidrawAPI && (
<Footer>
<CustomFooter excalidrawAPI={excalidrawAPI} />
</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()}
</Excalidraw>
{renderExcalidraw(children)}
{Object.keys(commentIcons || []).length > 0 && renderCommentIcons()}
{comment && renderComment()}
</div>
@ -798,7 +871,7 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
files: excalidrawAPI.getFiles(),
});
const ctx = canvas.getContext("2d")!;
ctx.font = "30px Virgil";
ctx.font = "30px Excalifont";
ctx.strokeText("My custom text", 50, 60);
setCanvasUrl(canvas.toDataURL());
}}
@ -819,7 +892,7 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
files: excalidrawAPI.getFiles(),
});
const ctx = canvas.getContext("2d")!;
ctx.font = "30px Virgil";
ctx.font = "30px Excalifont";
ctx.strokeText("My custom text", 50, 60);
setCanvasUrl(canvas.toDataURL());
}}

View File

@ -0,0 +1,30 @@
import React from "react";
import type * as TExcalidraw from "@excalidraw/excalidraw";
import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types";
import CustomFooter from "./CustomFooter";
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;

View File

@ -1,5 +1,7 @@
import React, { useState } from "react";
import "./ExampleSidebar.scss";
export default function Sidebar({ children }: { children: React.ReactNode }) {
const [open, setOpen] = useState(false);

View File

@ -11,19 +11,21 @@
<title>React App</title>
<script>
window.name = "codesandbox";
window.EXCALIDRAW_ASSET_PATH =
"https://esm.sh/@excalidraw/excalidraw@0.18.0/dist/prod/";
</script>
</head>
<body>
<noscript> You need to enable JavaScript to run this app. </noscript>
<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
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>
</html>

View File

@ -0,0 +1,29 @@
import React, { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "@excalidraw/excalidraw/index.css";
import type * as TExcalidraw from "@excalidraw/excalidraw";
import App from "./components/ExampleApp";
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>,
);

View File

@ -0,0 +1,22 @@
{
"name": "with-script-in-browser",
"version": "1.0.0",
"private": true,
"dependencies": {
"react": "19.0.0",
"react-dom": "19.0.0",
"@excalidraw/excalidraw": "*",
"browser-fs-access": "0.29.1"
},
"devDependencies": {
"vite": "5.0.12",
"typescript": "^5"
},
"scripts": {
"start": "vite",
"build": "vite build",
"preview": "vite preview --port 5002",
"build:preview": "yarn build && yarn preview",
"build:package": "yarn workspace @excalidraw/excalidraw run build:esm"
}
}

Some files were not shown because too many files have changed in this diff Show More