Compare commits

...

656 Commits

Author SHA1 Message Date
16a396a188 Merge remote-tracking branch 'origin/master' into aakansha-improve-text-wrap-ellipse 2022-09-16 13:12:31 +05:30
ec4b3d913e fix: remove no longer used code related to collab room loading (#5699)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-09-15 19:58:07 +00:00
5390617c01 test: add more specs for line editor segment midpoints (#5698)
* tests: add more specs for line editor segment midpoints

* use API to create elements

* Add specs for checking midpoint hidden when points too close
2022-09-15 19:31:55 +05:30
0d1058a596 feat: support segment midpoints in line editor (#5641)
* feat: support segment midpoints in line editor

* fix tests

* midpoints working in bezier curve

* midpoint working with non zero roughness

* calculate beizer curve control points for points >2

* unnecessary rerender

* don't show phantom points inside editor for short segments

* don't show phantom points for small curves

* improve the algo for plotting midpoints on bezier curve by taking arc lengths and doing binary search

* fix tests finally

* fix naming

* cache editor midpoints

* clear midpoint cache when undo

* fix caching

* calculate index properly when not all segments have midpoints

* make sure correct element version is fetched from cache

* chore

* fix

* direct comparison for equal points

* create arePointsEqual util

* upate name

* don't update cache except inside getter

* don't compute midpoints outside editor unless 2pointer lines

* update cache to object and burst when Zoom updated as well

* early return if midpoints not present outside editor

* don't early return

* cleanup

* Add specs

* fix
2022-09-14 19:55:54 +05:30
c5869979c8 chore: fix typo in clipboard alert (#5693)
chore: fix typo
2022-09-14 12:15:35 +05:30
6a6b9c90a7 fix: revert webpack deduping to fix @next runtime (#5695)
Revert "chore: Dedupe webpack configs. (#5449)"

This reverts commit da4fa91ffc.
2022-09-13 21:19:57 +02:00
5c17751662 fix: Move to release notes for v0.9.0 and after (#5686)
* fix: Move to release notes for v0.9.0 and after

* fix
2022-09-13 16:29:56 +05:30
898789b979 chore: update lib menu click outside callback comment (#5687) 2022-09-12 11:19:22 +05:30
7922ce129e chore: fix typo in blob.ts (#5664)
Co-authored-by: David Luzar <luzar.david@gmail.com>
2022-09-11 21:50:51 +00:00
59ec1c6cee fix: zen-mode exit button not working (#5682) 2022-09-09 13:53:38 +02:00
873bab69e0 fix: improve text weappin inside ellipse 2022-09-08 18:19:12 +05:30
933c6a2237 build: add missing dependencies: pica, lodash (#5656)
* add missing dependencies: pica, lodash

* remove lodash & fix yarn.lock

* first

* second

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-09-07 16:08:04 +05:30
cd61f31116 fix: buttons jump around on the mobile menu (#5658)
Update MobileMenu.tsx
2022-09-05 16:00:47 +05:30
b3052f0178 fix: #5622 - prevent session theme reset during collaboration (#5640)
*  fixed #5622 - prevent session theme reset

 -  prevent newly initialized state to override theme preferences.
 - 🔧 fix for #5622

* refactor

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2022-09-01 15:41:44 +05:30
a271e42af1 chore: Update translations from Crowdin (#5596)
* New translations en.json (Vietnamese)

* Auto commit: Calculate translation coverage

* New translations en.json (Lithuanian)

* Auto commit: Calculate translation coverage

* New translations en.json (Lithuanian)

* Auto commit: Calculate translation coverage

* New translations en.json (Bengali)

* Auto commit: Calculate translation coverage

* New translations en.json (Bengali)

* Auto commit: Calculate translation coverage
2022-09-01 13:36:54 +05:30
836120c14b feat: added exportPadding to PNG (blob) export in @excalidraw/utils (#5626)
* added exportPadding

* Update README.md

* Update CHANGELOG.md
2022-08-30 12:48:24 +05:30
da4fa91ffc chore: Dedupe webpack configs. (#5449)
* chore: Dedupe package dependencies and webpack configs.

* Fully dedupe `src/packages` via symlinks

* Merge https://github.com/excalidraw/excalidraw into dedupe-package-deps-configs

* fix: Link `tsc` so `build:example` works in @excalidraw/excalidraw

* @excalidraw/plugins: Revert the `yarn.lock` deduping.

* Drop yarn commands from the root `package.json`.

* Remove more unneeded `package.json` additions.

* One more change to drop in `package.json` files.

* Deduping: Move even more into common webpack configs.

* renaming

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2022-08-30 12:37:18 +05:30
553b493f37 fix: library actions inside the sidebar (#5638) 2022-08-29 19:26:03 +05:30
59a1d192d2 chore: update CodeSandbox links and add a config (#5624)
* chore: update CodeSandbox links and add a config

* Update tasks.json
2022-08-29 18:52:04 +05:30
8b7302e89e fix: don't render library menu twice for mobile (#5636) 2022-08-29 15:44:10 +05:30
f9b7cfd8aa fix: reintroduce help dialog button (#5631) 2022-08-27 23:02:17 +02:00
2b4462c941 refactor: reuse common ui dialogs and message for mobile and LayerUI (#5611)
* refactor: Move common UI dialogs to component

* refactor

* fix
2022-08-26 11:46:34 +05:30
43b13d8e3a fix: Add display name to components so it doesn't show as anonymous (#5616) 2022-08-26 11:46:19 +05:30
720f468f39 fix: improve solveQuadratic when a = 0 (#5618) 2022-08-24 14:44:59 +08:00
33300d19f6 fix: add random tiny offsets to avoid linear elements from being clipped (#5615)
Co-authored-by: Ryan Di <ryandi@Ryans-MacBook-Pro.local>
2022-08-23 15:52:15 +02:00
5aed159991 docs: fix refs table (#5614)
* docs: fix refs table

* fix

* fix

* fix

* fix
2022-08-23 13:55:43 +05:30
de1d221d1c docs: add PR link (#5613)
docs:add PR link
2022-08-23 11:51:45 +05:30
9a68dbffe2 docs: update docs for param defaultStatus in loadLibraryFromBlob (#5612) 2022-08-23 11:32:53 +05:30
32d82219b1 refactor: Stats component (#5610)
refactor: stats component
2022-08-22 17:18:25 +05:30
ba2c86fe1b refactor: Move footer to its own component (#5609) 2022-08-22 16:09:24 +05:30
f1ae37c84b fix: Crash when adding a new point in the line editor #5602 (#5606)
Update linearElementEditor.ts
2022-08-22 10:39:27 +05:30
ec350ba8b2 feat: Introduce ExcalidrawElements and ExcalidrawAppState provider (#5463)
* feat: Introduce ExcalidrawData provider so that app state and elements need not be passed to children

* fix

* fix zen mode

* Separate providers for data and elements

* pass appState and elements to layerUI

* pass appState and elements to selectedShapeActions

* pass appState and elements to MobileMenu

* pass appState to librarymenu

* rename

* rename to ExcalidrawAppState
2022-08-20 22:49:44 +05:30
46a61ad4df feat: enable midpoint inside linear element editor (#5564)
* feat: enable midpoint inside linear element editor

* fix

* fix

* hack to set pointerDownState.hit.hasHitElementInside when mid point added

* remove hacks as not needed :)

* remove newline

* fix

* add doc
2022-08-18 19:56:26 +05:30
f4b1a30bef chore: Update translations from Crowdin (#5552) 2022-08-18 15:42:40 +02:00
32aa79164b refactor: remove unused attribute hasHitElementInside from pointerDownState (#5591) 2022-08-18 19:11:18 +05:30
b5fd904808 fix: allow box selection of points when inside editor (#5594) 2022-08-18 19:07:14 +05:30
8f8dd1105f docs: changelog fixes (#5593) 2022-08-18 14:16:06 +02:00
b914ad41fc feat: support ExcalidrawElement.customData (#5592)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2022-08-18 17:32:46 +05:30
551c38f60b fix: remove unnecessary conditions in pointerup for linear elements (#5575)
* fix: remove unnecessary conditions in pointerup for linear elements

* reset editingLinearElement when clicked inside bounding box
2022-08-18 13:58:46 +05:30
38e8ae46c9 fix: check if hitting link in handleSelectionOnPointerDown (#5589)
fix: check if hitting link in handleSelectionOnPoiinterDown
2022-08-18 13:40:26 +05:30
ad0c4c4c78 fix: points not being normalized on single-elem resize (#5581) 2022-08-16 21:51:43 +02:00
27cf5ed17e fix: deselect linear element when clicked inside bounding box outside editor (#5579) 2022-08-16 23:05:38 +05:30
fd946adbae refactor: cleanup renderScene (#5573)
* refactor: cleanup renderScene

* pass object instead of individual params
2022-08-16 16:09:53 +05:30
c37977af4b docs: correct readme type typo (#5574) 2022-08-16 13:55:55 +05:30
a0d413ab4e fix: resize multiple elements from center (#5560)
Co-authored-by: Ryan Di <ryan.weihao.di@gmail.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-08-13 19:53:10 +02:00
b67a2b4f65 fix: call static methods via class instead of instance in linearElementEditor (#5561)
* fix: call getMidPoint via class instead of instance

* fix

* fix
2022-08-11 20:33:07 +05:30
5a8dbe8030 feat: show a mid point for linear elements (#5534)
* feat: Add a mid point for linear elements

* fix tests

* show mid point only on hover

* hacky fix :(

* don't add mid points if present and only add outside editor

* improve styling and always show phantom point instead of just on hover

* fix tests

* fix

* only add polyfill for test

* add hover state for phantom point

* fix tests

* fix

* Add Array.at polyfill

* reuse `centerPoint()` helper

* reuse `distance2d`

* use `Point` type

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-08-11 20:16:25 +05:30
731093f631 fix: show bounding box for 3 or more linear point elements (#5554)
* fix: show bounding box for 3+ linear point elements

* refactor

* show bounding box for 3 points as well

* fix dragging bounding box for linear elements

* Increase margin/padding for linear elements

* fix cursor and keep bounding box same but offset resize handles

* introduce slight padding for selection border

* better

* add constant for spacing
2022-08-10 21:42:28 +05:30
fe56975f19 fix: cleanup the condition for dragging elements (#5555) 2022-08-10 15:32:40 +05:30
2d800feeeb fix: shareable links being merged with current scene data (#5547) 2022-08-08 17:51:19 +02:00
93cccd596a fix: Scene lookup failing when looking up by id (#5542) 2022-08-08 17:01:17 +02:00
45b592227d fix: remove rounding to fix jitter when shift-editing (#5543)
Co-authored-by: Ryan Di <ryan.weihao.di@gmail.com>
2022-08-05 20:22:46 +05:30
b818df1098 feat: lock angle when editing linear elements with shift pressed (#5527)
Co-authored-by: Ryan <diweihao@bytedance.com>
2022-08-04 22:42:31 +00:00
4359e2935d fix: line deselected when shift-dragging point outside editor (#5540) 2022-08-05 00:01:56 +05:30
3d9d398378 fix: flip linear elements after redesign (#5538) 2022-08-04 18:41:31 +05:30
0a5da0269f docs: migrate the example to React 18 (#5533) 2022-08-04 12:24:13 +05:30
08ce7c7fc3 feat: redesign linear elements 🎉 (#5501)
* feat: redesign arrows and lines

* set selectedLinearElement on pointerup

* fix tests

* fix lint

* set selectionLinearElement to null when element is not selected

* fix

* don't set selectedElementIds to empty object when linear element selected

* don't move arrows when clicked on bounding box

* don't consider bounding box when linear element selected

* better hitbox

* show pointer when over the points in linear elements

* highlight points when hovered

* tweak design whene editing linear element points

* tweak

* fix test

* fix multi point editing

* cleanup

* fix

* fix

* remove stroke when hovered

* account for zoom when hover

* review fix

* set selectedLinearElement to null when selectedElementIds doesn't contain the linear element

* remove hover affect when moved away from linear element

* don't set selectedLinearAElement if already set

* fix selection

* render reduced in test :p

* fix box selection for single linear element

* set selectedLinearElement when deselecting selected elements and linear element is selected

* don't show linear element handles when element locked

* selected linear element when only linear present and selected with selectAll

* don't set selectedLinearElement if already set

* store selectedLinearElement in browser to persist

* remove redundant checks

* test fix

* select linear element handles when user has finished multipoint editing

* fix snap

* add comments

* show bounding box for locked linear elements

* add stroke param to fillCircle and remove stroke when linear element point hovered

* set selectedLinearElement when thats the only element left when deselcting others

* skip tests instead of removing for rotation

* (un)bind on pointerUp when moving linear element points outside editor

* render bounding box for linear elements as a fallback on state mismatch

* simplify and remove type assertion

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-08-03 20:58:17 +05:30
fe7fbff7f6 chore: Update translations from Crowdin (#5507)
* New translations en.json (Czech)

* Auto commit: Calculate translation coverage

* New translations en.json (Japanese)

* Auto commit: Calculate translation coverage
2022-08-03 11:43:00 +05:30
501397cb61 fix: disable locking aspect ratio for box-selection (#5525) 2022-08-02 19:10:17 +05:30
865d29388c feat: cursor alignment when creating linear elements with shift pressed (#5518)
* feat: cursor alignment when creating linear elements

* feat: apply cursor alignment to multi-point linear elements

* refactor: rename size helper function
2022-08-02 15:43:19 +05:30
54c7ec416a fix: Add title attribute to the modal close button (#5521)
Add `title` attribute to the modal close button
2022-08-02 11:42:47 +05:30
aca284057d fix: Context menu positioning when component has offsets (#5520)
Update Popover.tsx
2022-08-02 11:38:55 +05:30
2820cd112e feat: shift-clamp when creating multi-point lines/arrows (#5500)
Co-authored-by: Ryan <diweihao@bytedance.com>
2022-08-01 15:41:50 +02:00
426b5d9537 feat: cursor alignment when creating generic elements (#5516)
Co-authored-by: Ryan <diweihao@bytedance.com>
2022-08-01 13:24:46 +02:00
e7d34677c6 fix: resolve paths in prebuild.js script (#5498) 2022-07-30 21:56:46 +02:00
3d5356cb8e fix: use flushSync when moving line editor since we need to read previous value after setting state (#5508)
* fix: use flushSync when moving line editor since we need to read previous value after setting state

* add comment
2022-07-29 19:27:37 +05:30
46f5ce5ce0 fix: useLayout effect cleanup in dev mode for charts (#5505) 2022-07-29 17:25:26 +05:30
b00bd3d6c0 chore: Update translations from Crowdin (#5476)
* New translations en.json (French)

* New translations en.json (French)

* New translations en.json (French)

* New translations en.json (Basque)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* New translations en.json (Tamil)

* New translations en.json (Swedish)

* 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 (Bengali)

* New translations en.json (Slovak)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Kazakh)

* New translations en.json (Latvian)

* 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 (Slovenian)

* New translations en.json (Russian)

* New translations en.json (Turkish)

* New translations en.json (German)

* New translations en.json (Marathi)

* New translations en.json (Basque)

* New translations en.json (Romanian)

* 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 (Greek)

* New translations en.json (Portuguese)

* 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 (Lithuanian)

* New translations en.json (Dutch)

* New translations en.json (Punjabi)

* New translations en.json (Polish)

* New translations en.json (Kabyle)

* Auto commit: Calculate translation coverage

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-07-29 11:14:09 +05:30
91fc22182c fix: revert browser toast for high/low zoom (#5495) 2022-07-27 20:49:29 +05:30
966ca2ffa6 refactor: rename docs to dev-docs (#5487) 2022-07-26 16:55:25 +05:30
2b049b4a65 docs: Integrate docusaraus for docs (#5482)
* feat:Integrate docusaraus for docs

* Update docs for Excalidraw

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

* remove blogs

* remove blog authors

* get started docs

* typo

* add static assets

* change port number

* Add script to build docs only if docs updated

* dummy

* update script to be compatible with ignoreBuild in vercel

* remove script and dummy log

Co-authored-by: David Luzar <luzar.david@gmail.com>
2022-07-26 16:34:12 +05:30
339212e563 refactor: remove unnecessary if condition for linear element onKeyDown (#5486)
* refactor: remove unnecessary if condition for linear element onKeyDown

* fix
2022-07-26 16:33:13 +05:30
f8b4bb66b4 chore: Update peer dependencies to React 18 in @excalidraw/excalidraw (#5483)
* chore: Update peer dependencies to React 18 in `@excalidraw/excalidraw`

* Update src/packages/excalidraw/package.json

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

Co-authored-by: David Luzar <luzar.david@gmail.com>
2022-07-26 16:23:30 +05:30
f4312bba5e fix: Fixing push to DockerHub (#5468)
* fix: Fixing push to DockerHub

* Update .github/workflows/publish-docker.yml

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2022-07-26 16:13:09 +05:30
ac66665b64 fix: incorrectly rendering freedraw elements (#5481) 2022-07-22 16:18:41 +02:00
2b71a1f0bd fix: generate types when building example (#5480) 2022-07-22 18:53:21 +05:30
58845e450a fix: Use React.FC as react-dom is not able to infer types of Modal (#5479) 2022-07-22 13:09:15 +05:30
15d79f8fee chore: upgrade to React 18 (#5450)
* chore: upgrade to React 18

* better type

* use React.FC to fix type

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-07-22 11:20:36 +05:30
958ebeae61 feat: make context menu scrollable (#4030)
* Make context menu scrollable

* Fix color picker not showing up

* Fix overflow cuts shadow

* style fixes

* fix

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2022-07-21 14:34:49 +02:00
31f51ca53b chore: Update translations from Crowdin (#5428)
* New translations en.json (German)

* Auto commit: Calculate translation coverage

* New translations en.json (Galician)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* Auto commit: Calculate translation coverage

* New translations en.json (Indonesian)

* Auto commit: Calculate translation coverage

* New translations en.json (Marathi)

* Auto commit: Calculate translation coverage

* New translations en.json (Slovak)

* New translations en.json (Hindi)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* Auto commit: Calculate translation coverage

* New translations en.json (Turkish)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* New translations en.json (French)

* New translations en.json (French)

* New translations en.json (French)

* add marathi and vietnamese

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2022-07-21 13:25:30 +05:30
5abbf73050 chore(deps-dev): bump sass-loader from 12.4.0 to 13.0.2 in /src/packages/excalidraw (#5400)
chore(deps-dev): bump sass-loader in /src/packages/excalidraw

Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 12.4.0 to 13.0.2.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v12.4.0...v13.0.2)

---
updated-dependencies:
- dependency-name: sass-loader
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 12:51:57 +00:00
7cf766630d chore(deps-dev): bump rewire from 5.0.0 to 6.0.0 (#4440)
Bumps [rewire](https://github.com/jhnns/rewire) from 5.0.0 to 6.0.0.
- [Release notes](https://github.com/jhnns/rewire/releases)
- [Changelog](https://github.com/jhnns/rewire/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jhnns/rewire/compare/v5.0.0...v6.0.0)

---
updated-dependencies:
- dependency-name: rewire
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 18:20:03 +05:30
59fccafeac chore(deps-dev): bump sass-loader from 12.6.0 to 13.0.2 in /src/packages/utils (#5396)
chore(deps-dev): bump sass-loader in /src/packages/utils

Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 12.6.0 to 13.0.2.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v12.6.0...v13.0.2)

---
updated-dependencies:
- dependency-name: sass-loader
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 18:17:09 +05:30
19a6996e6b chore(deps-dev): bump typescript from 4.6.4 to 4.7.4 in /src/packages/excalidraw (#5329)
chore(deps-dev): bump typescript in /src/packages/excalidraw

Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.6.4 to 4.7.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.6.4...v4.7.4)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 18:16:09 +05:30
86c4f90910 chore(deps-dev): bump postcss-loader from 6.2.1 to 7.0.0 in /src/packages/excalidraw (#5234)
chore(deps-dev): bump postcss-loader in /src/packages/excalidraw

Bumps [postcss-loader](https://github.com/webpack-contrib/postcss-loader) from 6.2.1 to 7.0.0.
- [Release notes](https://github.com/webpack-contrib/postcss-loader/releases)
- [Changelog](https://github.com/webpack-contrib/postcss-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/postcss-loader/compare/v6.2.1...v7.0.0)

---
updated-dependencies:
- dependency-name: postcss-loader
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 18:15:50 +05:30
4d88112021 chore(deps-dev): bump @babel/plugin-transform-runtime from 7.17.10 to 7.18.6 in /src/packages/excalidraw (#5390)
chore(deps-dev): bump @babel/plugin-transform-runtime

Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.17.10 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 18:12:21 +05:30
de5c63e299 chore(deps-dev): bump @babel/plugin-transform-arrow-functions from 7.16.7 to 7.18.6 in /src/packages/excalidraw (#5392)
chore(deps-dev): bump @babel/plugin-transform-arrow-functions

Bumps [@babel/plugin-transform-arrow-functions](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-arrow-functions) from 7.16.7 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-plugin-transform-arrow-functions)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-arrow-functions"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 18:11:40 +05:30
da0853a121 chore(deps-dev): bump @babel/plugin-transform-async-to-generator from 7.16.5 to 7.18.6 in /src/packages/utils (#5391)
chore(deps-dev): bump @babel/plugin-transform-async-to-generator

Bumps [@babel/plugin-transform-async-to-generator](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-async-to-generator) from 7.16.5 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-plugin-transform-async-to-generator)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-async-to-generator"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 11:11:25 +00:00
57cc4b6a29 chore(deps-dev): bump terser-webpack-plugin from 5.3.1 to 5.3.3 in /src/packages/excalidraw (#5272)
chore(deps-dev): bump terser-webpack-plugin in /src/packages/excalidraw

Bumps [terser-webpack-plugin](https://github.com/webpack-contrib/terser-webpack-plugin) from 5.3.1 to 5.3.3.
- [Release notes](https://github.com/webpack-contrib/terser-webpack-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/terser-webpack-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/terser-webpack-plugin/compare/v5.3.1...v5.3.3)

---
updated-dependencies:
- dependency-name: terser-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 10:43:47 +00:00
e2ddd7b27a chore(deps-dev): bump @babel/plugin-transform-typescript from 7.16.1 to 7.18.6 in /src/packages/excalidraw (#5397)
chore(deps-dev): bump @babel/plugin-transform-typescript

Bumps [@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-typescript) from 7.16.1 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-plugin-transform-typescript)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 10:43:37 +00:00
693de8501e chore(deps-dev): bump webpack-cli from 4.9.2 to 4.10.0 in src/packages/excalidraw (#5327)
chore(deps-dev): bump webpack-cli in /src/packages/excalidraw

Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 4.9.2 to 4.10.0.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.9.2...webpack-cli@4.10.0)

---
updated-dependencies:
- dependency-name: webpack-cli
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 10:42:51 +00:00
c6df6d444e chore(deps-dev): bump @babel/plugin-transform-arrow-functions from 7.16.0 to 7.18.6 in /src/packages/utils (#5398)
chore(deps-dev): bump @babel/plugin-transform-arrow-functions

Bumps [@babel/plugin-transform-arrow-functions](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-arrow-functions) from 7.16.0 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-plugin-transform-arrow-functions)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-arrow-functions"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 10:39:23 +00:00
ad5692c5f8 chore(deps-dev): bump webpack-cli from 4.9.2 to 4.10.0 in /src/packages/utils (#5324)
chore(deps-dev): bump webpack-cli in /src/packages/utils

Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 4.9.2 to 4.10.0.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.9.2...webpack-cli@4.10.0)

---
updated-dependencies:
- dependency-name: webpack-cli
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 10:25:19 +00:00
60ab3337af chore(deps-dev): bump dotenv from 10.0.0 to 16.0.1 (#5197)
Bumps [dotenv](https://github.com/motdotla/dotenv) from 10.0.0 to 16.0.1.
- [Release notes](https://github.com/motdotla/dotenv/releases)
- [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md)
- [Commits](https://github.com/motdotla/dotenv/compare/v10.0.0...v16.0.1)

---
updated-dependencies:
- dependency-name: dotenv
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 15:50:17 +05:30
dd847793d2 chore(deps): bump dotenv from 10.0.0 to 16.0.1 in /src/packages/excalidraw (#5195)
chore(deps): bump dotenv in /src/packages/excalidraw

Bumps [dotenv](https://github.com/motdotla/dotenv) from 10.0.0 to 16.0.1.
- [Release notes](https://github.com/motdotla/dotenv/releases)
- [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md)
- [Commits](https://github.com/motdotla/dotenv/compare/v10.0.0...v16.0.1)

---
updated-dependencies:
- dependency-name: dotenv
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 15:48:57 +05:30
6d6e9f0dd3 chore(deps-dev): bump @babel/plugin-transform-typescript from 7.16.1 to 7.18.6 in /src/packages/utils (#5393)
chore(deps-dev): bump @babel/plugin-transform-typescript

Bumps [@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-typescript) from 7.16.1 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-plugin-transform-typescript)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 10:15:12 +00:00
0fe0d7ca6b chore(deps-dev): bump webpack from 5.72.0 to 5.73.0 in /src/packages/excalidraw (#5268)
chore(deps-dev): bump webpack in /src/packages/excalidraw

Bumps [webpack](https://github.com/webpack/webpack) from 5.72.0 to 5.73.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.72.0...v5.73.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 10:12:12 +00:00
abcf1f1bae chore(deps-dev): bump @types/lodash.throttle from 4.1.6 to 4.1.7 (#5172)
Bumps [@types/lodash.throttle](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/lodash.throttle) from 4.1.6 to 4.1.7.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/lodash.throttle)

---
updated-dependencies:
- dependency-name: "@types/lodash.throttle"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 15:41:20 +05:30
7d0b03f754 chore(deps-dev): bump ts-loader from 9.3.0 to 9.3.1 in /src/packages/utils (#5356)
chore(deps-dev): bump ts-loader in /src/packages/utils

Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 9.3.0 to 9.3.1.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v9.3.0...v9.3.1)

---
updated-dependencies:
- dependency-name: ts-loader
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 15:40:25 +05:30
bd8931d3d1 chore(deps): bump i18next-browser-languagedetector from 6.1.2 to 6.1.4 (#4977)
Bumps [i18next-browser-languagedetector](https://github.com/i18next/i18next-browser-languageDetector) from 6.1.2 to 6.1.4.
- [Release notes](https://github.com/i18next/i18next-browser-languageDetector/releases)
- [Changelog](https://github.com/i18next/i18next-browser-languageDetector/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next-browser-languageDetector/compare/v6.1.2...v6.1.4)

---
updated-dependencies:
- dependency-name: i18next-browser-languagedetector
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 15:39:41 +05:30
0d86c04939 chore(deps-dev): bump @babel/plugin-transform-async-to-generator from 7.16.0 to 7.18.6 in /src/packages/excalidraw (#5402)
chore(deps-dev): bump @babel/plugin-transform-async-to-generator

Bumps [@babel/plugin-transform-async-to-generator](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-async-to-generator) from 7.16.0 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-plugin-transform-async-to-generator)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-async-to-generator"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 15:37:40 +05:30
8436ebbf68 chore(deps-dev): bump ts-loader from 9.3.0 to 9.3.1 in /src/packages/excalidraw (#5355)
chore(deps-dev): bump ts-loader in /src/packages/excalidraw

Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 9.3.0 to 9.3.1.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v9.3.0...v9.3.1)

---
updated-dependencies:
- dependency-name: ts-loader
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 15:29:47 +05:30
824f94b3df chore(deps-dev): bump @babel/preset-typescript from 7.16.7 to 7.18.6 in /src/packages/utils (#5389)
chore(deps-dev): bump @babel/preset-typescript in /src/packages/utils

Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.16.7 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 15:29:17 +05:30
f9a8e686b2 chore(deps-dev): bump @babel/core from 7.17.2 to 7.18.6 in /src/packages/utils (#5395)
chore(deps-dev): bump @babel/core in /src/packages/utils

Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.17.2 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 15:28:54 +05:30
e442a44ba8 chore(deps-dev): bump @babel/preset-react from 7.16.7 to 7.18.6 in /src/packages/excalidraw (#5394)
chore(deps-dev): bump @babel/preset-react in /src/packages/excalidraw

Bumps [@babel/preset-react](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-react) from 7.16.7 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-preset-react)

---
updated-dependencies:
- dependency-name: "@babel/preset-react"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 15:28:34 +05:30
f1fd29571a chore(deps): bump @tldraw/vec from 1.4.3 to 1.7.1 (#5360)
Bumps [@tldraw/vec](https://github.com/tldraw/tldraw) from 1.4.3 to 1.7.1.
- [Release notes](https://github.com/tldraw/tldraw/releases)
- [Commits](https://github.com/tldraw/tldraw/commits)

---
updated-dependencies:
- dependency-name: "@tldraw/vec"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 15:04:56 +05:30
6a482a7ba2 chore(deps): bump url-parse from 1.5.7 to 1.5.10 (#4851)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.7 to 1.5.10.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.7...1.5.10)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 14:59:43 +05:30
bfea434a55 chore(deps-dev): bump @types/resize-observer-browser from 0.1.6 to 0.1.7 (#4759)
Bumps [@types/resize-observer-browser](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/resize-observer-browser) from 0.1.6 to 0.1.7.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/resize-observer-browser)

---
updated-dependencies:
- dependency-name: "@types/resize-observer-browser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 14:58:42 +05:30
acb22c5a64 chore(deps-dev): bump webpack from 5.72.1 to 5.73.0 in /src/packages/utils (#5273)
chore(deps-dev): bump webpack in /src/packages/utils

Bumps [webpack](https://github.com/webpack/webpack) from 5.72.1 to 5.73.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.72.1...v5.73.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 14:56:24 +05:30
7cd1b621d1 chore(deps-dev): bump mini-css-extract-plugin from 2.6.0 to 2.6.1 in /src/packages/excalidraw (#5331)
chore(deps-dev): bump mini-css-extract-plugin

Bumps [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) from 2.6.0 to 2.6.1.
- [Release notes](https://github.com/webpack-contrib/mini-css-extract-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/mini-css-extract-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/mini-css-extract-plugin/compare/v2.6.0...v2.6.1)

---
updated-dependencies:
- dependency-name: mini-css-extract-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 14:55:53 +05:30
9c37b25bab chore(deps-dev): bump @babel/preset-typescript from 7.16.7 to 7.18.6 in /src/packages/excalidraw (#5399)
chore(deps-dev): bump @babel/preset-typescript

Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.16.7 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 14:55:15 +05:30
a8bb9a78ef chore(deps-dev): bump @babel/preset-env from 7.16.7 to 7.18.6 in /src/packages/utils (#5401)
chore(deps-dev): bump @babel/preset-env in /src/packages/utils

Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.16.7 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 14:54:51 +05:30
e4aff04061 chore(deps-dev): bump @babel/core from 7.17.0 to 7.18.6 in /src/packages/excalidraw (#5403)
chore(deps-dev): bump @babel/core in /src/packages/excalidraw

Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.17.0 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 14:54:30 +05:30
c5cadc7de3 fix: missing translation for "Scale" to Export Dialog (#5456)
fix: missing translation for "Scale"
2022-07-20 14:52:04 +05:30
7dc0c0d96a chore(deps): bump terser from 5.7.0 to 5.14.2 in /src/packages/utils (#5469)
Bumps [terser](https://github.com/terser/terser) from 5.7.0 to 5.14.2.
- [Release notes](https://github.com/terser/terser/releases)
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 12:33:27 +05:30
2c9c8c8e05 chore(deps): bump terser from 5.9.0 to 5.14.2 in /src/packages/excalidraw (#5470)
chore(deps): bump terser in /src/packages/excalidraw

Bumps [terser](https://github.com/terser/terser) from 5.9.0 to 5.14.2.
- [Release notes](https://github.com/terser/terser/releases)
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 12:32:56 +05:30
b5d7ae57e5 chore(deps): bump terser from 4.8.0 to 4.8.1 (#5471)
Bumps [terser](https://github.com/terser/terser) from 4.8.0 to 4.8.1.
- [Release notes](https://github.com/terser/terser/releases)
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 12:32:36 +05:30
0f66ee3a41 build: move dotenv to dev deps (#5472) 2022-07-20 12:32:12 +05:30
771372c66b fix: add display name for Excalidraw component so it doesn't show as anonymous (#5464)
fix: add display name for Excalidraw component
2022-07-19 21:04:05 +05:30
a7937681e9 fix: account for safe area for floating buttons on mobile (#5420) 2022-07-19 15:44:14 +02:00
792f238d16 refactor: improve typing & check (#5415) 2022-07-19 15:44:04 +02:00
ba16416c75 fix: attribute warnings in comment svg example (#5465)
fix the attributes in comment svg example
2022-07-19 17:53:21 +05:30
6e0ac52a64 fix: check for ctrl key when wheel event triggered to only disable zooming (#5459)
* fix: check for ctrl key when wheel event triggered to only disable zooming

* remove newline
2022-07-18 14:39:55 +05:30
5bc40402a6 fix: disable render throttling by default & during resize (#5451) 2022-07-16 11:36:55 +02:00
df14c69977 refactor: don't pass zenModeEnable, viewModeEnabled and toggleZenMode props to LayerUI (#5444)
refactor: don't pass zenModeEnabled and viewModeEnabled props to LayerUI
2022-07-14 16:13:10 +05:30
1ea67ba93d fix: attach wheel event to exscalidraw container only (#5443) 2022-07-14 11:08:20 +05:30
a7153d9d1d feat: update toast api to account for duration and closable (#5427)
* feat: update toast api to account for duration and closable

* fix

* update snaps

* update docs

* male toast nullable

* fix snaps

* remove clearToast from App.tsx and replace clearToast prop in Toast comp with onClose
2022-07-11 18:11:13 +05:30
e885057a71 chore: Update translations from Crowdin (#5186)
* Auto commit: Calculate translation coverage

* New translations en.json (Persian)

* Auto commit: Calculate translation coverage

* New translations en.json (Persian)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* New translations en.json (Catalan)

* Auto commit: Calculate translation coverage

* New translations en.json (Portuguese)

* Auto commit: Calculate translation coverage

* New translations en.json (Kabyle)

* New translations en.json (Kabyle)

* New translations en.json (Vietnamese)

* Auto commit: Calculate translation coverage

* New translations en.json (Vietnamese)

* Auto commit: Calculate translation coverage

* New translations en.json (Basque)

* Auto commit: Calculate translation coverage

* New translations en.json (Catalan)

* New translations en.json (Catalan)

* New translations en.json (Bulgarian)

* New translations en.json (Hebrew)

* New translations en.json (Greek)

* New translations en.json (German)

* New translations en.json (Danish)

* New translations en.json (Czech)

* New translations en.json (Finnish)

* New translations en.json (Arabic)

* New translations en.json (French)

* New translations en.json (Romanian)

* New translations en.json (Basque)

* New translations en.json (Spanish)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Indonesian)

* New translations en.json (Persian)

* New translations en.json (Tamil)

* New translations en.json (Bengali)

* New translations en.json (Marathi)

* New translations en.json (Hindi)

* New translations en.json (Kazakh)

* New translations en.json (Latvian)

* New translations en.json (Burmese)

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

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Ukrainian)

* New translations en.json (Sinhala)

* New translations en.json (Chinese Traditional)

* New translations en.json (Polish)

* New translations en.json (Turkish)

* New translations en.json (Lithuanian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Vietnamese)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Dutch)

* New translations en.json (Swedish)

* New translations en.json (Punjabi)

* New translations en.json (Kabyle)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Slovak)

* New translations en.json (Slovenian)

* New translations en.json (Occitan)

* Auto commit: Calculate translation coverage

* New translations en.json (Slovenian)

* New translations en.json (Swedish)

* New translations en.json (Norwegian Bokmal)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* New translations en.json (Finnish)

* New translations en.json (Latvian)

* Auto commit: Calculate translation coverage

* New translations en.json (Spanish)

* New translations en.json (Russian)

* Auto commit: Calculate translation coverage

* New translations en.json (Marathi)

* New translations en.json (Hindi)

* 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 (Chinese Simplified)

* Auto commit: Calculate translation coverage

* New translations en.json (Catalan)

* New translations en.json (Greek)

* New translations en.json (Punjabi)

* New translations en.json (Dutch)

* New translations en.json (Lithuanian)

* New translations en.json (Korean)

* New translations en.json (Japanese)

* New translations en.json (Italian)

* New translations en.json (Hungarian)

* New translations en.json (Hebrew)

* New translations en.json (Finnish)

* New translations en.json (Polish)

* New translations en.json (German)

* New translations en.json (Czech)

* New translations en.json (Bulgarian)

* New translations en.json (Arabic)

* New translations en.json (Spanish)

* New translations en.json (French)

* New translations en.json (Romanian)

* New translations en.json (Basque)

* New translations en.json (Danish)

* New translations en.json (Kazakh)

* New translations en.json (Bengali)

* New translations en.json (Marathi)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Sinhala)

* New translations en.json (Latvian)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

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

* New translations en.json (Persian)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Tamil)

* New translations en.json (Turkish)

* New translations en.json (Indonesian)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Chinese Traditional)

* New translations en.json (Ukrainian)

* New translations en.json (Swedish)

* New translations en.json (Slovenian)

* New translations en.json (Slovak)

* New translations en.json (Russian)

* New translations en.json (Portuguese)

* New translations en.json (Kabyle)

* New translations en.json (Chinese Simplified)

* New translations en.json (Vietnamese)

* New translations en.json (Occitan)

* Auto commit: Calculate translation coverage

* New translations en.json (Italian)

* New translations en.json (Swedish)

* New translations en.json (Chinese Traditional)

* New translations en.json (Latvian)

* New translations en.json (Norwegian Bokmal)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Simplified)

* New translations en.json (German)

* Auto commit: Calculate translation coverage

* New translations en.json (Slovenian)

* Auto commit: Calculate translation coverage

* New translations en.json (Indonesian)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* Auto commit: Calculate translation coverage

* New translations en.json (Russian)

* Auto commit: Calculate translation coverage

* New translations en.json (Ukrainian)

* Auto commit: Calculate translation coverage

* New translations en.json (Ukrainian)

* Auto commit: Calculate translation coverage

* New translations en.json (Finnish)

* New translations en.json (Hindi)

* Auto commit: Calculate translation coverage

* New translations en.json (Marathi)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* Auto commit: Calculate translation coverage

* New translations en.json (Turkish)

* New translations en.json (Italian)

* Auto commit: Calculate translation coverage

* New translations en.json (Galician)

* Auto commit: Calculate translation coverage

* New translations en.json (Galician)

* Auto commit: Calculate translation coverage

* New translations en.json (Galician)

* New translations en.json (Galician)

* Auto commit: Calculate translation coverage

* New translations en.json (Galician)

* Auto commit: Calculate translation coverage

* New translations en.json (Galician)

* Auto commit: Calculate translation coverage

* New translations en.json (Czech)

* Auto commit: Calculate translation coverage

* New translations en.json (Galician)

* Auto commit: Calculate translation coverage

* New translations en.json (Slovak)

* Auto commit: Calculate translation coverage

* New translations en.json (Catalan)

* New translations en.json (Bengali)

* 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 Traditional)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Indonesian)

* New translations en.json (Persian)

* New translations en.json (Tamil)

* New translations en.json (Marathi)

* New translations en.json (Russian)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Kazakh)

* New translations en.json (Latvian)

* 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 (Slovak)

* New translations en.json (Portuguese)

* New translations en.json (Kabyle)

* New translations en.json (Danish)

* New translations en.json (Chinese Simplified)

* New translations en.json (Vietnamese)

* New translations en.json (Basque)

* 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 (Czech)

* New translations en.json (German)

* New translations en.json (Polish)

* New translations en.json (Greek)

* 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 (Lithuanian)

* New translations en.json (Dutch)

* New translations en.json (Punjabi)

* New translations en.json (Galician)

* Auto commit: Calculate translation coverage

* Add Slovenščina

* New translations en.json (Slovenian)

* New translations en.json (Chinese Traditional)

* New translations en.json (Norwegian Bokmal)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Simplified)

* New translations en.json (Italian)

* New translations en.json (Latvian)

* Auto commit: Calculate translation coverage

* New translations en.json (Swedish)

* Auto commit: Calculate translation coverage

* New translations en.json (Russian)

* Auto commit: Calculate translation coverage

* New translations en.json (Spanish)

* fix code for Slovenščina

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2022-07-09 11:28:09 +05:30
7efa081976 fix: show toast when browser zoom is not 100% (#5304)
* fix: show toast when browser zoom is not 100%

* update threshold for detecting zoom

* Make toast permanent for browser zoom

* check if browser zoomed on mount

* retrieve toast params from function getToastParams

* Revert "retrieve toast params from function getToastParams"

This reverts commit cfca580d74.
2022-07-08 19:19:00 +05:30
5deb93a083 fix: prevent browser zoom inside Excalidraw (#5426)
* fix: prevent browser zoom inside Excalidraw

* prevent default only for =/-
2022-07-08 17:53:40 +05:30
e3908e6fe3 fix: typo in changelog (#5425) 2022-07-07 18:45:17 +05:30
fe3d0b5e8b docs: release @excalidraw/excalidraw@0.12.0 🎉 (#5421) 2022-07-07 18:26:19 +05:30
b6bb74d08d feat: throttle scene rendering to animation framerate (#5422) 2022-07-07 11:47:37 +02:00
c725f84334 build: extract all i18n files into locales folder (#5419) 2022-07-06 15:21:05 +05:30
11a3380d83 build: automate release step fully (#5414)
* build: automate release step fully

* exit process when error

* Add npm scripts for release and prerelease

* update docs with release setps
2022-07-06 15:20:52 +05:30
76a5bb060e feat: make toast closable and allow custom duration (#5308)
* feat: make toast closable and allow custom duration

* use Infinity to keep prevent auto close

* rename to DEFAULT_TOAST_TIMEOUT and move to toast.tsx

* fix

* set closable as false by default and fix design

* tweak css

* reuse variables

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-07-05 21:43:59 +05:30
dac8dda4d4 feat: collab component state handling rewrite & fixes (#5046) 2022-07-05 16:03:40 +02:00
a1a62468a6 docs: fix command to trigger release (#5413) 2022-07-05 12:24:50 +05:30
ba3a723e99 fix: autorelease job name (#5412) 2022-07-04 22:32:22 +05:30
c5355c08cf fix: action name for autorelease (#5411) 2022-07-04 22:25:24 +05:30
6102380051 build: use next and preview tags instead of separate packages for next and preview release (#5346)
* build: use next and preview tags instead of separate packages for next and preview release

* add tag

* dummy diff

* revert dummy tweak

* don't use readme_next

* add note for latest release readme

* Add warning emoji for note

* move note to top

* remove readme next

* fix

* dummy change for release

* remove double note

* Revert "dummy change for release"

This reverts commit d3655cdee4.
2022-07-04 22:19:08 +05:30
655e59a707 chore: bye bye dependabot :) (#5409) 2022-07-04 20:11:05 +05:30
d05745070b fix: typecast file to fix the build (#5410)
* fix: typecast file to fix the build

* update type for fileOpen

* fix
2022-07-04 17:44:20 +05:30
88c313bf86 chore(deps): bump jsdom from 16.4.0 to 16.7.0 (#5350)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 16.4.0 to 16.7.0.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Changelog](https://github.com/jsdom/jsdom/blob/master/Changelog.md)
- [Commits](https://github.com/jsdom/jsdom/compare/16.4.0...16.7.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-04 14:06:27 +05:30
a7705848ec chore(deps-dev): bump webpack-dev-server from 4.9.0 to 4.9.3 in /src/packages/excalidraw (#5404)
chore(deps-dev): bump webpack-dev-server in /src/packages/excalidraw

Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.9.0 to 4.9.3.
- [Release notes](https://github.com/webpack/webpack-dev-server/releases)
- [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-server/compare/v4.9.0...v4.9.3)

---
updated-dependencies:
- dependency-name: webpack-dev-server
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-04 11:36:08 +05:30
69e1bae8dd chore(deps-dev): bump @babel/preset-env from 7.17.10 to 7.18.6 in /src/packages/excalidraw (#5405)
chore(deps-dev): bump @babel/preset-env in /src/packages/excalidraw

Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.17.10 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-04 11:35:25 +05:30
d361757e4a chore(deps-dev): bump @babel/plugin-transform-runtime from 7.17.10 to 7.18.6 in /src/packages/utils (#5388)
chore(deps-dev): bump @babel/plugin-transform-runtime

Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.17.10 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-04 11:35:06 +05:30
0ef202f2df feat: support debugging PWA in dev (#4853)
* feat: support enabling pwa in dev

* enable workbox debug

* add prebuild script

* fix lint
2022-07-02 17:59:03 +02:00
bbfd2b3cd3 fix: file handle not persisted when importing excalidraw files (#5372) 2022-06-28 14:44:59 +02:00
120c8f373c fix: library not scrollable when no published items installed (#5352)
* fix: library not scrollable when no published items installed

* show empty lib message in one case & fix i18n
2022-06-25 20:10:53 +02:00
9135ebf2e2 feat: redirect vscode.excalidraw.com to vscode marketplace (#5285) 2022-06-23 17:42:50 +02:00
af31e9dcc2 fix: focus traps inside popovers (#5317) 2022-06-23 17:33:50 +02:00
50bc7e099a fix: unable to use cmd/ctrl-delete/backspace in inputs (#5348) 2022-06-23 17:27:15 +02:00
39d17c4a3c fix: delay loading until language imported (#5344) 2022-06-22 22:06:29 +05:30
d34c2a75db fix: command to trigger release (#5347) 2022-06-22 18:10:57 +05:30
de95c68d75 fix: remove unnecessary options passed to language detector (#5336) 2022-06-22 01:33:08 +05:30
cdf352d4c3 feat: add sidebar for libraries panel (#5274)
Co-authored-by: dwelle <luzar.david@gmail.com>
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2022-06-21 17:03:23 +02:00
4712393b62 fix: stale appState.pendingImageElement (#5322)
* fix: stale `appState.pendingImageElement`

* unrelated fix for devTools race conditions

* snap fix
2022-06-19 14:13:43 +02:00
fd48c2cf79 fix: non-letter shortcuts being swallowed by color picker (#5316) 2022-06-17 12:37:11 +02:00
5feacd9a3b feat: deduplicate collab avatars based on id (#5309) 2022-06-15 15:35:57 +02:00
ec35d5db51 fix: bind text to correct container when nested (#5307)
* fix: bind text to correct container when nested

* fix tests
2022-06-15 16:09:12 +05:30
ddf088e428 chore(deps): bump eventsource from 1.1.0 to 1.1.1 (#5262)
Bumps [eventsource](https://github.com/EventSource/eventsource) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/EventSource/eventsource/releases)
- [Changelog](https://github.com/EventSource/eventsource/blob/master/HISTORY.md)
- [Commits](https://github.com/EventSource/eventsource/compare/v1.1.0...v1.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-14 22:04:35 +05:30
adc1e585ff chore(deps): bump protobufjs from 6.10.2 to 6.11.3 (#5266)
Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 6.10.2 to 6.11.3.
- [Release notes](https://github.com/protobufjs/protobuf.js/releases)
- [Changelog](https://github.com/protobufjs/protobuf.js/blob/v6.11.3/CHANGELOG.md)
- [Commits](https://github.com/protobufjs/protobuf.js/compare/v6.10.2...v6.11.3)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-14 22:04:01 +05:30
84b47a2ed5 fix: copy bound text style when copying element having bound text (#5305)
* fix: copy bound text style when copying element having bound text

* fix

* fix tests
2022-06-14 19:42:49 +05:30
6196fba286 docs: migrate example to typescript (#5243)
* docs: migrate example to typescript

* fix

* fix sidebar

* fix
2022-06-14 17:56:05 +05:30
5daff2d3cd fix: copy arrow head when using copy styles (#5303)
* fix: copy arrow head when using copy styles

* remove mutations & check against `arrow` type

* fix lint

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-06-14 16:27:41 +05:30
f1bc90e08a fix: Allow null in renderFooter prop (#5282)
* fix: Allow null in render props

* update docs
2022-06-06 20:45:06 +05:30
aabcdc20fd docs: prevent touch so that pointermove works in touch devices (#5241) 2022-05-25 11:39:16 +05:30
269fbcc2f3 docs: remove dragging threshold when interacting with custom elements (#5240) 2022-05-24 20:56:01 +05:30
d08179c215 fix: transpile browser-fs-access in package build (#5041) 2022-05-24 15:07:05 +02:00
90e739d444 docs: fix offsets in the example when dragging custom elements (#5238) 2022-05-24 16:27:23 +05:30
4a9fac2d1e fix: unsafely accessing draggingElement (#5216) 2022-05-20 17:48:26 +02:00
07ebd7c68c feat: support setting/resetting cursor from host (#5215)
* Support setting/resetting cursor type from host

* add docs

* minor
2022-05-20 18:43:38 +05:30
92f30f7ed6 test: add tests for loading library from file picker (#5206) 2022-05-19 00:37:36 +02:00
605aa554d0 fix: Library load button does not work (#5205)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-05-18 19:46:08 +00:00
bed9fca4a5 feat: go-to-excalidrawplus button (#5202)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-05-18 18:30:34 +02:00
b9968e2e72 feat: Autoredirect to Excalidraw+ if special cookie is present (#5183)
Co-authored-by: David Luzar <luzar.david@gmail.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-05-18 12:04:26 +02:00
ab1a30073c feat: expose utilitis to convert scene coords to viewport coords and vice versa (#5187)
* feat: expose utilitis to convert scene coords to viewport coords and vice versa

* add return value
2022-05-12 17:14:30 +05:30
31049d06e8 chore: Update translations from Crowdin (#5061) 2022-05-11 23:44:02 +02:00
ef8559d060 fix: do not deselect when not zooming using touchscreen pinch (#5181)
* Do not deselect when zooming

* do not deselect when trackpad zooming on Safari

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-05-11 23:30:50 +02:00
33bb23d2f3 fix: wheel zoom normalization (#5165)
Co-authored-by: David Luzar <luzar.david@gmail.com>
2022-05-11 22:01:20 +02:00
b27ac257e7 feat: support resubmitting published library items (#5174) 2022-05-11 15:56:11 +02:00
d2cc76e52e feat: support adding multiple library items on canvas (#5116) 2022-05-11 15:51:02 +02:00
cad6097d60 feat: factor out url library init & switch to updateLibrary API (#5115)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2022-05-11 15:08:54 +02:00
2537b225ac fix: hide sidebar when custom tool active (#5179) 2022-05-11 12:42:52 +00:00
4ee48d2729 fix: rename src to avatarUrl in collaborator (#5177)
* fix: rename  to  in collaborator

* update pr link

* fallback to intials on image error
2022-05-11 15:54:10 +05:30
68f23d652f feat: support custom elements in @excalidraw/excalidraw (#5164)
* feat: support custom elements in @excalidraw/excalidraw

* revert

* fix css

* fix offsets

* fix overflow of custom elements in example

* fix overflow in comments input

* make sure comment input never overflows the viewport

* remove offsetschange

* expose setActiveTool

* rename to onPointerDown

* update docs

* fix
2022-05-11 13:30:15 +05:30
a078508c05 chore(deps-dev): bump sass-loader in /src/packages/utils (#4813)
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 12.4.0 to 12.6.0.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v12.4.0...v12.6.0)

---
updated-dependencies:
- dependency-name: sass-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 13:02:20 +00:00
abf4dc9256 chore(deps-dev): bump @babel/preset-env in /src/packages/excalidraw (#5121)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.16.7 to 7.17.10.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.17.10/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 12:51:53 +00:00
ba8f12d588 chore(deps-dev): bump webpack-dev-server in /src/packages/excalidraw (#5158)
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.7.4 to 4.9.0.
- [Release notes](https://github.com/webpack/webpack-dev-server/releases)
- [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-server/compare/v4.7.4...v4.9.0)

---
updated-dependencies:
- dependency-name: webpack-dev-server
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 12:49:37 +00:00
d57560db06 chore(deps-dev): bump typescript in /src/packages/excalidraw (#5119)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.5.4 to 4.6.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.5.4...v4.6.4)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 12:48:59 +00:00
0d26049b4e chore(deps-dev): bump babel-loader in /src/packages/excalidraw (#5086)
Bumps [babel-loader](https://github.com/babel/babel-loader) from 8.2.3 to 8.2.5.
- [Release notes](https://github.com/babel/babel-loader/releases)
- [Changelog](https://github.com/babel/babel-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel-loader/compare/v8.2.3...v8.2.5)

---
updated-dependencies:
- dependency-name: babel-loader
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 12:48:27 +00:00
f72e9b6ea5 chore(deps-dev): bump ts-loader in /src/packages/utils (#5123)
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 9.2.8 to 9.3.0.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v9.2.8...v9.3.0)

---
updated-dependencies:
- dependency-name: ts-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 12:42:13 +00:00
029cfb31b0 chore(deps-dev): bump prettier from 2.5.1 to 2.6.2 (#5168)
Bumps [prettier](https://github.com/prettier/prettier) from 2.5.1 to 2.6.2.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/2.5.1...2.6.2)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 12:23:34 +00:00
3a288eb09c chore(deps-dev): bump eslint-config-prettier from 8.3.0 to 8.5.0 (#5098)
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 8.3.0 to 8.5.0.
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v8.3.0...v8.5.0)

---
updated-dependencies:
- dependency-name: eslint-config-prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 12:22:58 +00:00
803909abb6 chore(deps-dev): bump webpack in /src/packages/utils (#5167)
Bumps [webpack](https://github.com/webpack/webpack) from 5.66.0 to 5.72.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.66.0...v5.72.1)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 12:19:48 +00:00
56c75b769c chore(deps): bump sass from 1.49.7 to 1.51.0 (#5169)
Bumps [sass](https://github.com/sass/dart-sass) from 1.49.7 to 1.51.0.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.49.7...1.51.0)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 17:49:02 +05:30
eea48d94d3 chore(deps): bump @testing-library/react from 12.1.2 to 12.1.5 (#5055)
Bumps [@testing-library/react](https://github.com/testing-library/react-testing-library) from 12.1.2 to 12.1.5.
- [Release notes](https://github.com/testing-library/react-testing-library/releases)
- [Changelog](https://github.com/testing-library/react-testing-library/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/react-testing-library/compare/v12.1.2...v12.1.5)

---
updated-dependencies:
- dependency-name: "@testing-library/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 17:42:29 +05:30
e29152ab30 chore(deps-dev): bump @babel/plugin-transform-runtime (#5118)
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.17.0 to 7.17.10.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.17.10/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 17:42:13 +05:30
f4aa36b35d chore(deps-dev): bump ts-loader in /src/packages/excalidraw (#5117)
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 9.2.8 to 9.3.0.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v9.2.8...v9.3.0)

---
updated-dependencies:
- dependency-name: ts-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 17:40:30 +05:30
2903a763a7 chore(deps-dev): bump jest-canvas-mock from 2.3.1 to 2.4.0 (#5127)
Bumps [jest-canvas-mock](https://github.com/hustcc/jest-canvas-mock) from 2.3.1 to 2.4.0.
- [Release notes](https://github.com/hustcc/jest-canvas-mock/releases)
- [Changelog](https://github.com/hustcc/jest-canvas-mock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hustcc/jest-canvas-mock/commits/v2.4.0)

---
updated-dependencies:
- dependency-name: jest-canvas-mock
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 17:39:46 +05:30
4a980ed5db chore(deps-dev): bump autoprefixer in /src/packages/excalidraw (#5159)
Bumps [autoprefixer](https://github.com/postcss/autoprefixer) from 10.4.5 to 10.4.7.
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/autoprefixer/compare/10.4.5...10.4.7)

---
updated-dependencies:
- dependency-name: autoprefixer
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-10 17:39:09 +05:30
d2e687ed0a feat: make file handling more robust (#5057) 2022-05-09 15:53:04 +02:00
0d70690ec8 fix: Don't save deleted ExcalidrawElements to Firebase (#5108)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-05-09 15:38:44 +02:00
a524eeb66e fix: eraser removed deleted elements (#5155)
* fix: eraser removed deleted elements

* rename `getElements` API

* fix one more case of not including deleted elements
2022-05-07 21:01:37 +02:00
3d56ceb794 fix: Handle ColorPicker parentSelector being undefined (#5152)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-05-07 18:16:14 +00:00
65c32b3319 fix: library multiselect not accounting for published state (#5132) 2022-05-07 19:13:10 +02:00
9e8e047aae fix: Chart display fix (#5154) 2022-05-07 19:12:31 +02:00
64d330a332 feat: support customType in activeTool (#5144)
* feat: support customType in activeTool

* fix

* rewrite types and handling

* tweaks

* fix

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-05-06 18:21:22 +05:30
1ed1529f96 fix: update opacity of bound text when opacity of container updated (#5142) 2022-05-04 14:29:05 +05:30
b30066ca19 fix: jumping of text when typing single line in bound text (#5139)
* fix: jumping of text when typing single line in bound text

* add comment
2022-05-04 11:21:27 +05:30
aae8e2fa5d feat: export MIME_TYPES supported by excalidraw (#5135)
* feat: export MIME_TYPES supported by excalidraw

* Update src/packages/excalidraw/CHANGELOG.md
2022-05-02 15:47:03 +05:30
9e6d5fdbcb feat: support src collaborators (#5114)
* feat: support avatarURLfor collaborators

* fix

* better avatars :)

* use position fixed for tooltips so it renders correctly when offsets updated

* update docs

* Update src/excalidraw-app/collab/CollabWrapper.tsx

* rename avatarUrl to src
2022-05-02 15:15:24 +05:30
22b2e10ddb chore(deps-dev): bump @babel/plugin-transform-runtime (#5125)
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.16.8 to 7.17.10.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.17.10/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-02 14:47:37 +05:30
d53ac2a61e fix: library init/import race conditions (#5101) 2022-04-29 16:45:02 +02:00
6a0f800716 feat: export exportToClipboard util from package (#5103)
* feat: export copyToClipboard from package

* use promise constructor for better browser supprt

* add type to exportToClipboard

* update docs

* use json instead of text and use selected element in actionCopy

* pass `files` in example `exportToClipboard`

* fix bad access

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-04-29 18:58:44 +05:30
aee1e2451e fix: remove opacity scroll wheel interaction (#5111) 2022-04-28 19:10:08 +02:00
da94eb1284 fix: use excalidraw asset path in fonts when exporting to svg (#5065)
* fix: use excalidraw asset path in fonts when exporting

* fix

* fix

* introduce env variables and determine asset path correctly

* fix snaps

* use env vars to determine pkg name and version

* update docs

* quotes
2022-04-28 20:19:41 +05:30
ea51251fe6 fix: propagate keydown events from excalidraw-wysiwyg inputs (#5099)
* fix: allow propagation for keydown events originating from `excalidraw-wysiwyg`

* revert check on the handleKeyDown function
2022-04-27 20:28:41 +02:00
399ce1e01a fix: don't bind text to container if double clicked else instead of center (#5105) 2022-04-27 17:04:21 +05:30
7df8302ba2 chore(deps-dev): bump babel-loader in /src/packages/utils (#5088)
Bumps [babel-loader](https://github.com/babel/babel-loader) from 8.2.3 to 8.2.5.
- [Release notes](https://github.com/babel/babel-loader/releases)
- [Changelog](https://github.com/babel/babel-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel-loader/compare/v8.2.3...v8.2.5)

---
updated-dependencies:
- dependency-name: babel-loader
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-27 10:03:17 +00:00
af8c59b5bb chore(deps): bump minimist in /src/packages/excalidraw (#5039)
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-27 15:27:56 +05:30
cf0f00285b chore(deps): bump minimist from 1.2.5 to 1.2.6 in /src/packages/utils (#5040)
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-27 15:27:43 +05:30
b5c67a384c chore(deps): bump minimist from 1.2.5 to 1.2.6 (#5042)
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-27 15:27:20 +05:30
af93cedc08 EXCALIDRAW_EXPORT_SOURCE_PATH -> EXCALIDRAW_EXPORT_SOURCE (#5102) 2022-04-27 10:49:02 +02:00
b6a6f2d465 feat: Expose window.EXCALIDRAW_EXPORT_SOURCE which host can use to overwrite the source field in exports (#5095)
* Expose `window.EXCALIDRAW_EXPORT_SOURCE` which host can use to overwrite the source field in exports

* Update src/packages/excalidraw/CHANGELOG.md

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

* address review comments

* Update src/packages/excalidraw/README_NEXT.md

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>

* Update src/packages/excalidraw/README_NEXT.md

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>

* EXCALIDRAW_EXPORT_SOURCE -> EXCALIDRAW_EXPORT_SOURCE_PATH

Co-authored-by: David Luzar <luzar.david@gmail.com>
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2022-04-26 13:28:39 +02:00
6bcbf8b50a chore(deps): bump node-forge in /src/packages/excalidraw (#5071)
Bumps [node-forge](https://github.com/digitalbazaar/forge) from 1.2.1 to 1.3.1.
- [Release notes](https://github.com/digitalbazaar/forge/releases)
- [Changelog](https://github.com/digitalbazaar/forge/blob/main/CHANGELOG.md)
- [Commits](https://github.com/digitalbazaar/forge/compare/v1.2.1...v1.3.1)

---
updated-dependencies:
- dependency-name: node-forge
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-26 07:40:12 +00:00
666516d7e9 chore(deps): bump async from 2.6.3 to 2.6.4 in /src/packages/excalidraw (#5069)
Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4.
- [Release notes](https://github.com/caolan/async/releases)
- [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md)
- [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-26 07:32:29 +00:00
b941c5b661 chore(deps-dev): bump webpack in /src/packages/excalidraw (#5027)
Bumps [webpack](https://github.com/webpack/webpack) from 5.65.0 to 5.72.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.65.0...v5.72.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-26 13:01:35 +05:30
8f8c85c64e chore(deps): bump async from 2.6.3 to 2.6.4 (#5070)
Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4.
- [Release notes](https://github.com/caolan/async/releases)
- [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md)
- [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-26 12:59:37 +05:30
116b0c48da chore(deps): bump nanoid from 3.1.32 to 3.3.3 (#5073)
Bumps [nanoid](https://github.com/ai/nanoid) from 3.1.32 to 3.3.3.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.1.32...3.3.3)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-26 12:59:11 +05:30
aa2971e8c5 chore(deps-dev): bump autoprefixer in /src/packages/excalidraw (#5087)
Bumps [autoprefixer](https://github.com/postcss/autoprefixer) from 10.4.2 to 10.4.5.
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/autoprefixer/compare/10.4.2...10.4.5)

---
updated-dependencies:
- dependency-name: autoprefixer
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-26 12:58:53 +05:30
5656ac1e3e chore(deps): bump browser-fs-access from 0.24.1 to 0.29.1 (#5090)
Bumps [browser-fs-access](https://github.com/GoogleChromeLabs/browser-fs-access) from 0.24.1 to 0.29.1.
- [Release notes](https://github.com/GoogleChromeLabs/browser-fs-access/releases)
- [Commits](https://github.com/GoogleChromeLabs/browser-fs-access/commits)

---
updated-dependencies:
- dependency-name: browser-fs-access
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-26 12:58:10 +05:30
e6a9ff1b96 fix: toolIcon height not using rem (#5092) 2022-04-24 19:21:41 +02:00
832b88249c feat: stop event propagation when key handled (#5091)
* feat: stop event propagation when key handled

* don't handle s/g shortcuts if cmd/ctrl/alt pressed
2022-04-24 18:29:38 +02:00
9902092fd1 fix setting webpack public path (#5081) 2022-04-23 13:48:57 +05:30
8f0863d335 add a prefix to the extension for image embbedding sceneData (#5079) 2022-04-22 18:31:31 +02:00
9423ac3263 fix: Excalidraw named export type (#5078) 2022-04-22 15:49:36 +02:00
a66cfe2627 fix: boundElementIds when arrows bound to elements are deleted (#5077)
* fix: boundElementIds when arrows bound to elements are deleted

* fix type checks and updating unrelated elements

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-04-21 18:57:06 +05:30
86cf28f2b4 fix: don't merge libraryItems on updateScene (#5076) 2022-04-21 10:54:02 +02:00
b5a46dd671 fix: SVG metadata extraction regex on multiline elements (#5074)
* Fix SVG metadata extraction regex on multiline elements

* remove multiline flag
2022-04-20 17:07:58 +02:00
cd942c3e3b feat: rewrite library state management & related refactor (#5067)
* support libraryItems promise for `updateScene()` and use `importLibrary`

* fix typing for `getLibraryItemsFromStorage()`

* remove `libraryItemsFromStorage` hack

if there was a point to it then I'm missing it, but this part will be rewritten anyway

* rewrite state handling

(temporarily removed loading states)

* add async support

* refactor and deduplicate library importing logic

* hide hints when library open

* fix snaps

* support promise in `initialData.libraryItems`

* add default to params instead
2022-04-20 14:40:03 +02:00
55ccd5b79b feat: delay initial loading message & tweak design (#5049) 2022-04-19 19:08:13 +02:00
4348c55c31 chore: Update translations from Crowdin (#4894) 2022-04-18 00:16:43 +02:00
a3fbe40b26 fix: eraser cursor showing on theme change when not using eraser (#4990) 2022-04-17 22:47:36 +02:00
7431ca81d1 fix: update storage.rules (#5020) 2022-04-17 22:47:00 +02:00
4d13dbf625 feat: reconcile when saving to firebase (#4991)
* naming tweaks

* do not mark local element as duplicate when there's no remote counterpart

* merge instead of overwrite elements when saving to firebase & reconcile local state

* decouple syncing from persistence

* fix ts

* clarify doc

* fix reconciliation not removing duplicates
2022-04-17 22:40:39 +02:00
3840e2f4e6 feat: embed scene support for png export in npm package (#5047)
* feat: embed scene support for png export in npm package

* move logic to the callback function

* add exportEmbedScene checkbox in package example

* update readme and changelog

* add PR link in changelog

* reverse sort changelog items
2022-04-16 16:30:11 +02:00
52d10bb41e feat: hide trash button during collaboration (#5037)
* feat: hide trash button during collaboration

* visually hide the trash icon

* pointer events none

* tweak env docs

* fix typo

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-04-15 09:21:41 -07:00
96c87f920a build: export only named exports from the package (#5045)
* build: export only named exports from the package

* update docs

* Update src/packages/excalidraw/CHANGELOG.md

* fix lint
2022-04-15 18:12:57 +05:30
7d4189c624 fix: Add image button not working on iPad (#5038) 2022-04-15 12:20:51 +02:00
f3e17c90d3 fix: ensure svg image dimensions are always set (#5044) 2022-04-15 12:05:10 +02:00
70b3a9de49 feat: library restoring changes (#4995)
* restore library items in all cases & refactor

* export `restoreLibraryItems` from package

* feat: rerender library menu when updating via API

* update readme & changelog

* fix changelog
2022-04-14 16:20:35 +02:00
bf6d0eeef7 fix: Pinch zoom in view mode (#5001) 2022-04-12 12:39:28 +02:00
5359e4fec9 feat: refactor local persistence & fix race condition on SW reload (#5032) 2022-04-11 22:15:49 +02:00
58fe639b8d fix: select whole group on righclick & few lock-related fixes (#5022) 2022-04-07 17:53:55 +02:00
327ed0e2d1 feat: Element locking (#4964)
Co-authored-by: dwelle <luzar.david@gmail.com>
Co-authored-by: Zsolt Viczian <viczian.zsolt@gmail.com>
2022-04-07 13:43:29 +02:00
c2fce6d8c4 fix: export serializeLibraryAsJSON from the package (#5017) 2022-04-07 12:35:44 +05:30
cb6b7559b4 fix: support copying PNG to clipboard on Safari (#3746) 2022-04-06 14:05:09 +02:00
77d789ed8e fix: more copyText fixes (#5016) 2022-04-05 23:11:00 +02:00
89471094ce fix: Copy to clipboard all text nodes as text (#5014)
* fix: Copy to clipboard all text nodes as text

* fix: support copying text even if there are selected elements that are no text

* patch: makes paragraphs betwen texts of each element

* patch: allow copying text for bound text
2022-04-05 21:48:59 +02:00
670ceafc84 feat: Copy to clipboard all text nodes as text (#5013)
* Copy to clipboard all text nodes as text

* fix: only show the option for text elements
2022-04-05 15:31:19 +02:00
873afdacd3 feat: create and expose serializeLibraryAsJSON (#5009)
Co-authored-by: David Luzar <luzar.david@gmail.com>
2022-04-05 14:35:38 +02:00
880e4feede fix: update cursorButton once freedraw is released (#4996)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-04-01 18:25:21 +02:00
9ba7ca3845 feat: hide penMode button on reload if not enabled (#4992) 2022-03-30 10:53:22 +02:00
734bb4d2ed fix: decouple actionFinalize and actionErase (#4984)
* Update actionCanvas.tsx

* Update actionFinalize.tsx

* lint

* remove Escape trigger from actionErase

* revert to lastActiveTool only if coming from eraser tool

* unrelated: fix restoring `appState.activeTool`

* one more restoring fix

* fix tests

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-03-29 21:37:09 +02:00
f2d2f97546 fix: using stale state when switching tools (#4989) 2022-03-29 17:00:19 +02:00
2fa69ddc32 refactor: move elementLocked to activeTool.locked (#4983)
* refactor: move elementLocked to activeTool.locked

* fix

* fix snap

* update docs

* Update src/packages/excalidraw/CHANGELOG.md

* revert

* make lastActiveToolBeforeEraser required and nullable

* fix snap
2022-03-29 17:10:19 +05:30
1331cffe93 feat: Eraser toggle to switch back to the previous tool (#4981)
* add typeBeforeEraser

* ESC to switch to lastActiveToolBeforeEraser
2022-03-28 21:33:32 +02:00
f242721f3b chore: add ga for most actions (#4829) 2022-03-28 14:46:40 +02:00
e940aeb1a3 fix: updateWysiwygStyle updatedElement is undefined TypeError (#4980)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-03-28 00:14:04 +02:00
580e719580 fix: adding check for link length to prevent early return (#4982)
Co-authored-by: Connor Hanafee <connorp@Connors-MacBook-Pro.local>
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-03-27 23:50:41 +02:00
127af9db23 refactor: rename elementType to activeTool and make it an object (#4968)
* refactor: rename elementType to activeTool

* update docs

* fix snap

* update activeToll to be an object and review fixes

* fix tests

* fix
2022-03-25 20:46:01 +05:30
2209e2c1e8 fix: show link icon for bound text containers (#4960) 2022-03-23 00:45:08 +05:30
ed31980f84 feat: Save penDetected and penMode, and detect pen already on ToolButton click (#4955)
* save penMode and penDetected to browser cache

* added on pointer down

* added onPointerDown

* factor out and merge handlers

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-03-22 13:29:27 +01:00
db28595302 fix: cancel erase elements on pointer up if eraser is not active on pointer up (#4956)
* fix: erase elements on pointer up if present

* cancel erase on pointer up if eraser is not active
2022-03-22 17:14:07 +05:30
cded1cd63d fix: restore original opacities when alt pressed while erasing (#4954) 2022-03-22 16:40:28 +05:30
8e447b4c32 fix: don't bind text to container if already present (#4946)
* fix: don't bind text to container if already present

* Add specs and update condition
2022-03-22 15:32:49 +05:30
e29d3fc5e6 chore(deps-dev): bump mini-css-extract-plugin (#4872)
Bumps [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) from 2.4.6 to 2.6.0.
- [Release notes](https://github.com/webpack-contrib/mini-css-extract-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/mini-css-extract-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/mini-css-extract-plugin/compare/v2.4.6...v2.6.0)

---
updated-dependencies:
- dependency-name: mini-css-extract-plugin
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-22 13:07:14 +05:30
9da56e46f0 chore(deps-dev): bump lint-staged from 12.3.3 to 12.3.7 (#4941)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 12.3.3 to 12.3.7.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v12.3.3...v12.3.7)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-22 13:06:48 +05:30
625ecc64ed feat: Support binding text to container via context menu (#4935)
* feat: Support binding text to closest container

* Bind text to selected container

* show bind action in canvas and selected container after binding

* allow binding if container has no bound text

* fix

* move logic to show/hide bind actions to contextMenuPredicate

* don't show bind action when clicking on bounding box and not elemnts
2022-03-21 17:54:54 +05:30
ceb43ed8fb fix: erase all elements which are hit with single point click (#4934) 2022-03-17 21:03:59 +05:30
8c0a0415de update README.md to show commands in code blocks (#4932) 2022-03-16 18:49:28 +01:00
192debd829 fix: Add multiElement-edit finalize action to Desktop (currently only visible in Mobile view) (#4764)
* add finalize action to Desktop UI

* Update LayerUI.tsx

* add size to panel component

* finzalize button style

* add finalize button

* changed isMobile to DeviceInfo, added isTouchScreen

* cleanup

* rename deviceInfo to deviceType

* rename deviceInfo to deviceType

* added updateObject

* Update App.tsx
2022-03-16 15:59:30 +01:00
1cfb4dfd8b feat: Map shortcut O to ellipse and Add eraser shortcut E (#4930)
* feat: Add erase shortcut Shift+E

* map o to ellipse and E to Eraser

* fix tests

* use key

* move eraser to tools and rename shape to tools
2022-03-16 18:31:20 +05:30
fb32886355 chore(deps-dev): bump ts-loader in /src/packages/excalidraw (#4912)
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 9.2.6 to 9.2.8.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v9.2.6...v9.2.8)

---
updated-dependencies:
- dependency-name: ts-loader
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-16 13:25:36 +05:30
065df495ba fix: Hide eraser in view mode in desktop (#4929) 2022-03-16 13:09:34 +05:30
558227f744 feat: update eraser cursor (#4922)
* feat: update eraser cursor

* fix dark theme

* check before adding active class

* use custom cursor instead of DOM manipulation

* cache canvas and redraw only when theme changes

* use oc colors

* remove

* cache preview data url

* increase linwidth

* update coords for cursor

* add white 2px outline

* improvements

* use 1px line width 6px radius for outer

* improve
2022-03-15 20:56:39 +05:30
6d45430344 fix: undo when erasing elements by clicking (#4921)
* fix: undo when erasing elements by clicking

* newline remove
2022-03-14 14:59:55 +05:30
3aa0c5ebc0 chore(deps-dev): bump css-loader in /src/packages/excalidraw (#4911)
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 6.6.0 to 6.7.1.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/compare/v6.6.0...v6.7.1)

---
updated-dependencies:
- dependency-name: css-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-14 14:47:01 +05:30
e940993e0e chore(deps-dev): bump css-loader in /src/packages/utils (#4914)
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 6.5.1 to 6.7.1.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/compare/v6.5.1...v6.7.1)

---
updated-dependencies:
- dependency-name: css-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-14 14:45:33 +05:30
8f90aeb8d5 chore(deps-dev): bump ts-loader in /src/packages/utils (#4913)
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 9.2.6 to 9.2.8.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v9.2.6...v9.2.8)

---
updated-dependencies:
- dependency-name: ts-loader
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-14 14:45:02 +05:30
e92d133973 fix: undo when erasing (#4900) 2022-03-11 20:44:17 +05:30
b682d88167 fix: incorrectly erasing on mobile (#4899)
* fix: incorrectly erasing on mobile

* reintroduce fix for erasing on single-point click

* fix snaps
2022-03-11 15:45:59 +01:00
7daf1a7944 feat: Add Eraser 🎉 (#4887)
* feat: Add Eraser 🎉

* Eraser working

* remove unused state

* fix

* toggle eraser

* Support deselect with Alt/Option

* rename actionDelete -> actionErase

* Add util isEraserActive

* show eraser in mobile

* render eraser conditionally in mobile

* use selection if eraser in local storage state

* Add sampling to erase accurately

* use pointerDownState

* set eraser to false in AllowedExcalidrawElementTypes

* rename/reword fixes

* don't use updateScene

* handle bound text when erasing

* fix hover state in mobile

* consider all hitElements instead of a single

* code improvements

* revert to select if eraser active and elements selected

* show eraser in zenmode

* erase element when clicked on element while eraser active

* set groupIds to empty when eraser active

* fix test

* remove dragged distance
2022-03-11 19:53:42 +05:30
5c0eff50a0 chore: Update translations from Crowdin (#4729)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-03-09 12:21:26 +01:00
19056d635b feat: added optional REACT_APP_WS_SERVER_URL for forks usecases (#4889)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-03-09 12:13:59 +01:00
4d5f00ff08 fix: don't crash on drop highlighted text onto canvas (#4890) 2022-03-09 11:51:13 +01:00
20de06ef50 fix: paste styles shortcut (#4886)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2022-03-09 10:59:44 +01:00
1849ff6ee2 fix: freedraw element's background fill color missing from SVG when exporting with package API exportToSvg() (#4871) 2022-03-06 23:35:16 +01:00
6765fc16be fix: improve pointer syncing performance (#4883)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-03-06 22:11:14 +00:00
5ca4f5bbf4 feat: rewrite collab server connecting (#4881)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-03-06 22:43:02 +01:00
9392ec276d fix: collab room initialization (#4882) 2022-03-06 15:59:56 +01:00
b26e4fcf99 build: support runtime React Jsx in @excalidraw/utils (#4866)
* build: support runtime React Jsx

* revert version

* upgrade
2022-03-04 10:58:02 +05:30
45f3410da8 build: release @excalidraw/utils 0.1.1 (#4862) 2022-03-03 14:59:08 +01:00
94b387ef7b fix: ensure verticalAlign properties not shown when no element selected (#4860)
* fix: ensure verticalAlign properties not shown when no element selected

* show verticalAlign prop if selection contains at least one applicable element

* simplify
2022-03-02 23:56:20 +01:00
6d0716eb6b fix: binding text to non-bindable containers and not always preferring selection (#4655) 2022-03-02 17:04:09 +01:00
8e26d5b500 feat: support vertical text align for bound containers (#4852)
* feat: support vertical text align for bound containers

* update icons

* use const

* fix lint

* rename to  and show when text editor active

* don't update vertical align if not center

* fix svgs

* fix y coords when vertical align bottm

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-03-02 20:06:07 +05:30
c5a7723185 chore: fix various typos (#4857)
Found via `codespell -q 3 -S ./src/locales,./yarn.lock,./src/packages/excalidraw/yarn.lock -L afterall,doubleclick,originaly,reenable,whats,sur`
2022-03-02 11:37:12 +05:30
49172ac2d3 feat: support custom colors 🎉 (#4843)
* feat: support custom colors 🎉

* remove canvasBackground

* fix tests

* Remove custom color when elements deleted

* persist custom color across sessions

* Choose 5 latest custom colors when populating from elements

* fix tests

* styling

* don't use up/down arrow for custom colors

* Always push latest color to the begining

* don't check if valid in custom color

* calculate custom colors on color picker open

* revert unnecessary changes

* remove newlines

* simplify state

* tweak label

* fix custom color shortcuts throwing if color not exists

* fix

* early return

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-02-28 19:04:26 +05:30
618a846451 chore: remove firebase-tools (#4792) 2022-02-28 10:54:20 +01:00
d9f49ffd67 fix: Don't show align icons for single bound container element (#4846)
* fix: Don't show align icons for single bound container element

* check 2nd element as well
2022-02-28 11:08:28 +05:30
46e43baad1 feat: Support Links in Exported SVG (#4791) 2022-02-25 21:42:10 +01:00
bd35b682fa fix: redraw text bounding box when pasting styles (#4845) 2022-02-25 15:36:56 +05:30
b6f9a8005e docs: list who's integrating excalidraw (#4832)
* docs: list who's integrating excalidraw

* Update README.md
2022-02-23 23:28:17 +01:00
1acfaf6b6e feat: Scale font size when bound text containers resized with shift pressed (#4828)
* feat: Scale font size when bound text containers resized with shift pressed

* revert fontsize once shift pressed/released after resize

* make slightly more typesafe

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-02-22 18:45:59 +05:30
5cf7087754 fix: restore cursor position after bound text container value updated (#4836)
* fix: restore cursor position after bound text container value updated

* only restore cursor when the cursor is not at the end of the line

* compute diff before setting the cursor
2022-02-22 18:24:06 +05:30
b2d49155ef build:remove build packages workflow (#4835) 2022-02-22 13:50:25 +05:30
9745461db7 chore(deps): bump browser-fs-access from 0.23.0 to 0.24.1 (#4820)
Bumps [browser-fs-access](https://github.com/GoogleChromeLabs/browser-fs-access) from 0.23.0 to 0.24.1.
- [Release notes](https://github.com/GoogleChromeLabs/browser-fs-access/releases)
- [Commits](https://github.com/GoogleChromeLabs/browser-fs-access/compare/v0.23.0...v0.24.1)

---
updated-dependencies:
- dependency-name: browser-fs-access
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-22 13:26:53 +05:30
21e9fcb2f5 chore: Add tracking for hyperlinks (#4703)
* chore: Add tracking for hyperlinks

* update

* fix

* remove

* tweak

* disable ga logging in dev again

* add logging for hyperlink `edit` & support for tracking in manager

* event label tweaks

* fix tests & make more typesafe

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-02-21 17:44:28 +05:30
e203203993 refactor: don't pass array to handleBindTextResize (#4826) 2022-02-21 17:15:29 +05:30
f224e4d596 fix: support resizing multiple bound text containers (#4824) 2022-02-21 16:46:39 +05:30
e0ca689759 chore(deps): bump url-parse from 1.5.3 to 1.5.7 (#4807)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.3 to 1.5.7.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.3...1.5.7)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-19 15:16:30 +05:30
f792eb5ae7 fix: also check overflowY: overlay in detectScroll (#4806)
* fix: also check overflowY: overlay in detectScroll

* fix lint

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-02-18 19:17:43 +01:00
4604c8d823 fix: stuck resizing when resizing bound text container very fast beyond threshold (#4804)
* fix: stuck resizing when resizing bound text container very fast beyond threshold

* fix

* fix
2022-02-18 18:20:55 +05:30
0896892f8a docs: release @excalidraw/excalidraw@0.11.0 🎉 (#4799)
* docs: release @excalidraw/excalidraw@0.11.0  🎉

* Add commit link for bad commits
2022-02-17 18:52:44 +05:30
7fe225ee99 fix: rename --color-primary-chubb to --color-primary-contrast-offset and fallback to primary color if not present (#4803)
* fix: fallback to primary color if --color-primary-chubb not present

* rename to --color-primary-contrast-offset

* use contarst-offset

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

* Update src/packages/excalidraw/README_NEXT.md

* remove

* Update src/packages/excalidraw/README_NEXT.md

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

Co-authored-by: David Luzar <luzar.david@gmail.com>
2022-02-17 18:22:19 +05:30
d2fd7be457 fix: add commits directly pushed to master in changelog (#4798) 2022-02-16 21:01:59 +05:30
5c61613a2e fix: don't bump element version when adding files data (#4794)
* fix: don't bump element version when adding files data

* fix lint
2022-02-16 18:26:36 +05:30
b2767924de feat: show group/group and link action in mobile (#4795) 2022-02-16 15:41:35 +05:30
59d0a77862 chore(deps): bump @types/react from 17.0.38 to 17.0.39 (#4757)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 17.0.38 to 17.0.39.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-16 13:59:14 +05:30
987526d1e5 docs: tweak documentation for release and add examples (#4786)
* docs: tweak documentation for release

* Add image in initial data

* Add image

* remove watermark and make export work

* update readme
2022-02-15 19:13:46 +05:30
e894d41a22 chore(deps): bump vm2 from 3.9.5 to 3.9.7 (#4785)
Bumps [vm2](https://github.com/patriksimek/vm2) from 3.9.5 to 3.9.7.
- [Release notes](https://github.com/patriksimek/vm2/releases)
- [Changelog](https://github.com/patriksimek/vm2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/patriksimek/vm2/compare/3.9.5...3.9.7)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-15 16:47:23 +05:30
14d1d39e8e chore: variable naming :) (#4782) 2022-02-15 16:31:14 +05:30
69336b4832 build: rename release command to 'release package' (#4783) 2022-02-14 17:47:52 +05:30
32b677fb8a chore(deps): bump follow-redirects in /src/packages/excalidraw (#4781)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-14 14:03:04 +05:30
570f725516 chore(deps): bump follow-redirects from 1.14.7 to 1.14.8 (#4780)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-14 13:54:57 +05:30
a60860867c build: release preview package when triggered via comment (#4750)
* build: autorelease preview on every commit during pull request

* add github workflow

* update readme

* update docs

* log changed files

* remove depth

* fetch pr head

* remove console.log

* log pr number

* pull pr number

* use pull request number in release version

* dummy

* dummy

* dummy

* fix

* dummy

* fix

* Add comment and set output as version

* dummy

* fix

* fix

* set output through js toolkit

* install

* dummy

* update

* fix

* fix

* typo

* update

* condition

* typo

* testing

* wrap conditions

* echo

* hope it works

* test

* test

* yay test again

* test updated

* remove reaction

* run if comment triggered

* fix

* fix

* Update script after testing in fork

* remove

* update changelog

* update readme

* update

* remove

* append pr number then commit hash
2022-02-14 13:54:24 +05:30
7a61196462 fix: mobile link click (#4742)
* add tolerance to redirect pointerDown_Up check

* Update src/components/App.tsx

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

* Update App.tsx

* lint

* lint

* fix for ipad/mobile

* Update App.tsx

* Update App.tsx

* Update App.tsx

* testing if isIPad works on iOS15

* Update App.tsx

* Update keys.ts

* Update keys.ts

* lint

* test

* removed isTouchScreen

* isTouchScreen

* lint

* lint

* Update App.tsx

* tweak

Co-authored-by: David Luzar <luzar.david@gmail.com>
Co-authored-by: ad1992 <aakansha1216@gmail.com>
2022-02-10 14:52:33 +05:30
9653d676fe fix: contextMenu timer & pointers not correctly reset on iOS (#4765) 2022-02-09 20:42:02 +01:00
0cdd0eebf1 feat: support background fill for freedraw shapes (#4610)
* feat: support background fill for freedraw shapes

* refactor & support fill style

* make filled freedraw shapes selectable from inside

* get hit test on solid freedraw shapes to somewhat work

* fix SVG export of unclosed freedraw shapes & improve types

* fix lint

* type tweaks

* reuse `hitTestCurveInside` for collision tests

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-02-09 17:43:21 +01:00
ae8b1d8bf7 build: deploy excalidraw package example (#4762)
* build: deploy excalidraw package example

* deploy public

* install deps script

* new lines
2022-02-09 17:45:16 +05:30
92ffe8dda6 fix: use absolute coords when rendering link popover (#4753) 2022-02-09 16:33:49 +05:30
4d9dbd5a45 chore(deps-dev): bump css-loader in /src/packages/excalidraw (#4712)
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 6.5.1 to 6.6.0.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/compare/v6.5.1...v6.6.0)

---
updated-dependencies:
- dependency-name: css-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-09 07:41:07 +00:00
c66cabaefd chore(deps-dev): bump webpack-cli in /src/packages/excalidraw (#4664)
Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 4.9.1 to 4.9.2.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.9.1...webpack-cli@4.9.2)

---
updated-dependencies:
- dependency-name: webpack-cli
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-09 07:37:33 +00:00
e073128469 chore(deps-dev): bump @babel/core in /src/packages/utils (#4754)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.16.7 to 7.17.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.17.2/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-09 07:25:15 +00:00
835848d711 chore(deps): bump sass from 1.47.0 to 1.49.7 (#4723)
Bumps [sass](https://github.com/sass/dart-sass) from 1.47.0 to 1.49.7.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.47.0...1.49.7)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-09 12:52:23 +05:30
2bd1d7ef59 chore(deps-dev): bump lint-staged from 12.1.7 to 12.3.3 (#4724)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 12.1.7 to 12.3.3.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v12.1.7...v12.3.3)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-09 12:51:23 +05:30
37c8b9c2ff chore(deps-dev): bump webpack-dev-server in /src/packages/excalidraw (#4713)
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.7.3 to 4.7.4.
- [Release notes](https://github.com/webpack/webpack-dev-server/releases)
- [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-server/compare/v4.7.3...v4.7.4)

---
updated-dependencies:
- dependency-name: webpack-dev-server
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-09 12:50:10 +05:30
cf9f00f55f chore(deps-dev): bump chai from 4.3.4 to 4.3.6 (#4667)
Bumps [chai](https://github.com/chaijs/chai) from 4.3.4 to 4.3.6.
- [Release notes](https://github.com/chaijs/chai/releases)
- [Changelog](https://github.com/chaijs/chai/blob/4.x.x/History.md)
- [Commits](https://github.com/chaijs/chai/compare/v4.3.4...v4.3.6)

---
updated-dependencies:
- dependency-name: chai
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-09 12:49:53 +05:30
7ae9043221 chore(deps): bump @testing-library/jest-dom from 5.16.1 to 5.16.2 (#4745)
Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 5.16.1 to 5.16.2.
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v5.16.1...v5.16.2)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-09 12:49:33 +05:30
7c567408c5 chore(deps-dev): bump @babel/core in /src/packages/excalidraw (#4707)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.16.7 to 7.17.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.17.0/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-09 12:49:09 +05:30
54612621aa chore(deps-dev): bump terser-webpack-plugin in /src/packages/excalidraw (#4709)
Bumps [terser-webpack-plugin](https://github.com/webpack-contrib/terser-webpack-plugin) from 5.3.0 to 5.3.1.
- [Release notes](https://github.com/webpack-contrib/terser-webpack-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/terser-webpack-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/terser-webpack-plugin/compare/v5.3.0...v5.3.1)

---
updated-dependencies:
- dependency-name: terser-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-09 12:48:21 +05:30
d27b3bbebe fix: changing font size when text is not selected or edited (#4751)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-02-08 21:18:43 +00:00
e4ffc9812e docs: changelog tweaks (#4749) 2022-02-08 18:58:37 +05:30
a066317d3c feat: add onLinkOpen component prop (#4694)
Co-authored-by: ad1992 <aakansha1216@gmail.com>
2022-02-08 11:25:35 +01:00
050bc1ce2b feat: keep selected tool on canvas reset (#4728) 2022-02-07 22:30:06 +01:00
5007df6522 fix: disable contextmenu on non-secondary pen events or touch (#4675) 2022-02-07 20:01:36 +01:00
d450c36581 fix: mobile context menu won't show on long press (#4741)
* scribble fix only if not Android

* Update src/components/App.tsx

Co-authored-by: David Luzar <luzar.david@gmail.com>
2022-02-07 19:46:29 +01:00
66c92fc65a feat: Make whole element clickable in view mode when it has hyperlink (#4735)
* feat: Make whole element clickable in view mode when it has hyperlink

* redirect to link if pointerup and pointer down is exactly same point

* don't make element clickable in mobile
2022-02-07 19:54:39 +05:30
5f1cd4591a fix: do not open links twice (#4738) 2022-02-07 12:20:19 +00:00
9be6243873 fix: make link icon clickable in mobile (#4736) 2022-02-07 17:24:51 +05:30
c3f6d6d344 test: revert node v16 requirement for tests (#4737) 2022-02-07 12:27:31 +01:00
339636caab feat: allow any precision when zooming (#4730) 2022-02-06 21:58:59 +01:00
08115ef311 fix: Apple Pen missing strokes (#4705) 2022-02-06 20:07:37 +01:00
e68abdbab4 chore: Update translations from Crowdin (#4590) 2022-02-06 18:08:55 +01:00
8aff076782 feat: throttle pointermove events per framerate (#4727) 2022-02-06 17:45:37 +01:00
96de887cc8 fix: freedraw slow movement jittery lines (#4726)
Co-authored-by: David Luzar <luzar.david@gmail.com>
2022-02-06 17:45:23 +01:00
98ea46664c fix: Disable three finger pinch zoom in penMode (#4725) 2022-02-06 16:56:52 +01:00
00e30ca0e4 fix: remove click listener for opening popup (#4700)
* fix: remove click listener for oening popup

* fix
2022-02-04 20:36:21 +05:30
de6371aac4 fix: link popup position not accounting for offsets (#4695) 2022-02-03 17:00:00 +01:00
f47ddb988f feat: Support hyperlinks 🔥 (#4620)
* feat: Support hypelinks

* dont show edit when link not present

* auto submit on blur

* Add link button in sidebar and do it react way

* add key to hyperlink to remount when element selection changes

* autofocus input

* remove click handler and use pointerup/down to show /hide popup

* add keydown and support enter/escape to submit

* show extrrnal link icon when element has link

* use icons and open link in new tab

* dnt submit unless link updated

* renamed ffiles

* remove unnecessary changes

* update snap

* hide link popup once user starts interacting with element and show again only if clicked outside and clicked on element again

* render link icon outside the element

* fix hit testing

* rewrite implementation to render hyperlinks outside elements and hide when element selected

* remove

* remove

* tweak icon position and size

* rotate link icon when element rotated, handle zooming and render exactly where ne resize handle is rendered

* no need to create a new reference anymore for element when link added/updated

* rotate the link image as well when rotating element

* calculate hitbox of link icon and show pointer when hovering over link icon

* open link when clicked on link icon

* show tooltip when hovering over link icon

* show link action only when single element selected

* support other protocols

* add shortcut cmd/ctrl+k to edit/update link

* don't hide popup after submit

* renderes decreased woo

* Add context mneu label to add/edit link

* fix tests

* remove tick and show trash when in edit mode

* show edit view when element contains link

* fix snap

* horizontally center the hyperlink container with respect to elemnt

* fix padding

* remove checkcircle

* show popup on hover of selected element and dismiss when outside hitbox

* check if element has link before setting popup state

* move logic of auto hide to hyperlink and dnt hide when editing

* hide popover when drag/resize/rotate

* unmount during autohide

* autohide after 500ms

* fix regression

* prevent cmd/ctrl+k when inside link editor

* submit when input not updated

* allow custom urls

* fix centering of popup when zoomed

* fix hitbox during zoom

* fix

* tweak link normalization

* touch hyperlink tooltip DOM only if needed

* consider 0 if no offsetY

* reduce hitbox of link icon and make sure link icon doesn't show on top of higher z-index elements

* show link tooltip only if element has higher z-index

* dnt show hyperlink popup when selection changes from element with link to element with no link and also hide popover when element type changes from selection to something else

* lint: EOL

* fix link icon tooltip positioning

* open the link only when last pointer down and last pointer up hit the link hitbox

* render tooltip after 300ms delay

* ensure link popup and editor input have same height

* wip: cache the link icon canvas

* fix the image quality after caching using device pixel ratio yay

* some cleanup

* remove unused selectedElementIds from renderConfig

* Update src/renderer/renderElement.ts

* fix `opener` vulnerability

* tweak styling

* decrease padding

* open local links in the same tab

* fix caching

* code style refactor

* remove unnecessary save & restore

* show link shortcut in help dialog

* submit on cmd/ctrl+k

* merge state props

* Add title for link

* update editview if prop changes

* tweak link action logic

* make `Hyperlink` compo editor state fully controlled

* dont show popup when context menu open

* show in contextMenu only for single selection & change pos

* set button `selected` state

* set contextMenuOpen on pointerdown

* set contextMenyOpen to false when action triggered

* don't render link icons on export

* fix tests

* fix buttons wrap

* move focus states to input top-level rule

* fix elements sharing `Hyperlink` state

* fix hitbox for link icon in case of rect

* Early return if hitting link icon

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-02-03 20:34:59 +05:30
59cbf5fde5 fix: penMode darkmode style (#4692) 2022-02-03 00:09:59 +01:00
4486fbc2c6 feat: Added penMode for palm rejection (#4657)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-02-02 14:31:38 +01:00
edfbac9d7d feat: support unbinding bound text (#4686)
* feat: support unbinding text

* fix unbound text

* move the unbind option next to group action

* use boundTextElement.id when unbinding

* update original text so it takes same bounding box when unbind

* Add spec

* recompute measurements when unbinding
2022-02-01 20:11:24 +05:30
719ae7b72f fix: reset unmounted state for the component (#4682)
* Reset unmounted state for the component

* update changelog

Co-authored-by: ad1992 <aakansha1216@gmail.com>
2022-02-01 16:32:22 +05:30
631a228ca1 fix: typing _+ in wysiwyg not working (#4681) 2022-01-31 14:29:42 +01:00
4b5270ab12 fix: keyboard-zooming in wysiwyg should zoom canvas (#4676) 2022-01-31 10:43:03 +01:00
dcee594b66 remove forgotten debug statements 2022-01-29 22:07:09 +01:00
79d323fab1 refactor: simplify zoom by removing zoom.translation (#4477) 2022-01-29 21:12:44 +01:00
e4edda4555 fix: sceneCoordsToViewportCoords, jumping text when there is an offset (#4413) (#4630)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
Co-authored-by: David Luzar <luzar.david@gmail.com>
Co-authored-by: thxnder <tswwe@qq.com>
2022-01-29 14:27:03 +01:00
ca89d47d4c feat: Sync local storage state across tabs when out of sync (#4545)
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-01-27 13:21:55 +01:00
18c526d877 feat: support contextMenuLabel to be of function type to support dynmaic labels (#4654) 2022-01-27 17:47:23 +05:30
cbc6bd1ad8 chore(deps): bump nanoid in /src/packages/excalidraw (#4628)
Bumps [nanoid](https://github.com/ai/nanoid) from 3.1.23 to 3.2.0.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.1.23...3.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-26 14:46:28 +05:30
83d9282dbf chore(deps): bump nanoid from 3.1.23 to 3.2.0 in /src/packages/utils (#4629)
Bumps [nanoid](https://github.com/ai/nanoid) from 3.1.23 to 3.2.0.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.1.23...3.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-26 14:46:03 +05:30
abff780983 perf: cache approx line height in textwysiwg (#4651) 2022-01-25 17:01:12 +05:30
c009e03c8e fix: Right-click object menu displays partially off-screen (#4572) (#4631) 2022-01-23 17:28:38 +01:00
24bf4cb5fb fix: support collaboration in bound text (#4573)
* fix: support collaboration in bounded text

* align implementation irrespective of collab/submit

* don't wrap when submitted

* fix

* tests: exit editor via ESCAPE instead to remove async hacks

* simplify and remove dead comment

* remove mutating coords in submit since its taken care in updateWysiwygStyle

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-01-17 17:35:35 +05:30
0850ab0dd0 chore(deps-dev): bump @babel/plugin-transform-runtime (#4577)
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.16.4 to 7.16.8.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.8/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-17 12:36:53 +05:30
a7473169ba chore(deps-dev): bump webpack-dev-server in /src/packages/excalidraw (#4595)
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.7.2 to 4.7.3.
- [Release notes](https://github.com/webpack/webpack-dev-server/releases)
- [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-server/compare/v4.7.2...v4.7.3)

---
updated-dependencies:
- dependency-name: webpack-dev-server
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-17 12:36:40 +05:30
f6325b1e5e chore(deps-dev): bump webpack in /src/packages/utils (#4602)
Bumps [webpack](https://github.com/webpack/webpack) from 5.65.0 to 5.66.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.65.0...v5.66.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-17 12:36:26 +05:30
466220a3a8 chore(deps): bump nanoid from 3.1.30 to 3.1.32 (#4607)
Bumps [nanoid](https://github.com/ai/nanoid) from 3.1.30 to 3.1.32.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.1.30...3.1.32)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-17 12:36:07 +05:30
d9cc7d1033 chore(deps): bump follow-redirects from 1.14.6 to 1.14.7 in /src/packages/excalidraw (#4609)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-16 10:31:04 +01:00
c037e9854c chore(deps): bump follow-redirects from 1.13.3 to 1.14.7 (#4593)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-16 10:30:24 +01:00
9373961857 chore: Update translations from Crowdin (#4322)
Co-authored-by: Panayiotis Lipiridis <lipiridis@gmail.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
2022-01-13 19:06:48 +00:00
1fd2fe56ee fix: cmd/ctrl native browser behavior blocked in inputs (#4589)
* fix: cmd/ctrl native browser behavior blocked in inputs

* add basic test for fontSize increase/decrease via keyboard

* add tests for fontSize resizing via keyboard outside wysiwyg

* Update src/element/textWysiwyg.test.tsx

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>

* Update src/tests/resize.test.tsx

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>

* Update src/tests/resize.test.tsx

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2022-01-13 19:53:22 +01:00
dba71e358d fix: use cached width when calculating min width during resize (#4585) 2022-01-13 21:35:38 +05:30
1ef287027b fix: support collaboration in bounded text (#4580) 2022-01-12 23:21:45 +01:00
a51ed9ced6 feat: support decreasing/increasing fontSize via keyboard (#4553)
Co-authored-by: david <dw@dw.local>
2022-01-12 15:21:36 +01:00
4501d6d630 chore(deps-dev): bump @babel/preset-env in /src/packages/utils (#4510)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.16.4 to 7.16.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.7/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-12 15:33:05 +05:30
92a5936c7f fix: port for collab server and update docs (#4569) 2022-01-11 18:40:09 +05:30
50bd5fbae1 fix: don't mutate the bounded text if not updated when submitted (#4543)
* fix: don't mutate the bounded text if not updated when submitted

* dont update text for bounded text unless submitted

* add specs

* use node 16

* fix

* Update text when editing and cache prev text

* update prev text when props updated

* remove only

* type properly and remove unnecessary type checks

* cache original text and compare with editor value to fix alignement issue after editing and add specs

* naming tweak

Co-authored-by: dwelle <luzar.david@gmail.com>
2022-01-11 16:36:08 +05:30
62bead66d7 chore(deps-dev): bump typescript in /src/packages/excalidraw (#4432)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.5.3 to 4.5.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.5.3...v4.5.4)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-10 12:40:14 +05:30
b3073984b3 chore(deps-dev): bump @babel/core in /src/packages/excalidraw (#4513)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.16.0 to 7.16.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.7/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-10 12:40:01 +05:30
3c9ee13979 chore(deps-dev): bump autoprefixer in /src/packages/excalidraw (#4554)
Bumps [autoprefixer](https://github.com/postcss/autoprefixer) from 10.4.0 to 10.4.2.
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/autoprefixer/compare/10.4.0...10.4.2)

---
updated-dependencies:
- dependency-name: autoprefixer
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-10 12:39:42 +05:30
228c8136cf chore(deps-dev): bump mini-css-extract-plugin (#4555)
Bumps [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) from 2.4.5 to 2.4.6.
- [Release notes](https://github.com/webpack-contrib/mini-css-extract-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/mini-css-extract-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/mini-css-extract-plugin/compare/v2.4.5...v2.4.6)

---
updated-dependencies:
- dependency-name: mini-css-extract-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-10 12:39:29 +05:30
324dd460c8 chore(deps-dev): bump lint-staged from 12.1.4 to 12.1.7 (#4557)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 12.1.4 to 12.1.7.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v12.1.4...v12.1.7)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-10 12:38:48 +05:30
d8ea085a94 chore(deps): bump sass from 1.45.2 to 1.47.0 (#4561)
Bumps [sass](https://github.com/sass/dart-sass) from 1.45.2 to 1.47.0.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.45.2...1.47.0)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-10 12:38:20 +05:30
adbd486f32 chore(deps): bump @tldraw/vec from 1.4.0 to 1.4.3 (#4562)
Bumps [@tldraw/vec](https://github.com/tldraw/tldraw) from 1.4.0 to 1.4.3.
- [Release notes](https://github.com/tldraw/tldraw/releases)
- [Commits](https://github.com/tldraw/tldraw/compare/v1.4.0...v1.4.3)

---
updated-dependencies:
- dependency-name: "@tldraw/vec"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-10 12:38:08 +05:30
0a89c4b0c8 fix: prevent canvas drag while editing text (#4552) 2022-01-08 23:50:25 +01:00
c03845bac3 fix: support shift+P for freedraw (#4550)
* fix: support shift+P for freedraw

* newline

* show shift+p first
2022-01-08 18:01:22 +05:30
d5a6014076 fix: prefer spreadsheet data over image (#4533) 2022-01-07 23:18:04 +01:00
74861b1398 Fix shortcut for Draw tool in help dialog, it's not SHIFT+P anymore but just X (#4548) 2022-01-07 23:50:42 +05:30
ac71ee7278 feat: link to new LP for excalidraw plus (#4549) 2022-01-07 16:32:35 +01:00
9088df8f5a chore(deps-dev): bump @babel/preset-typescript in /src/packages/utils (#4526)
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.16.5 to 7.16.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.7/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-07 12:42:48 +05:30
c5fe0cd446 chore(deps-dev): bump webpack-dev-server in /src/packages/excalidraw (#4525)
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.7.1 to 4.7.2.
- [Release notes](https://github.com/webpack/webpack-dev-server/releases)
- [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-server/compare/v4.7.1...v4.7.2)

---
updated-dependencies:
- dependency-name: webpack-dev-server
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-07 12:00:08 +05:30
9f8783c2dd chore(deps-dev): bump @babel/plugin-transform-typescript (#4527)
Bumps [@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-typescript) from 7.16.1 to 7.16.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.7/packages/babel-plugin-transform-typescript)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-07 11:59:46 +05:30
b475412199 feat: support updating library in updateScene API (#4546)
* feat: support updating library in updateScene API

* fix

* update docs

* Update src/packages/excalidraw/CHANGELOG.md
2022-01-06 21:37:33 +05:30
5f1616f2c5 fix: show text properties button states correctly for bounded text (#4542)
* fix: show text properties button states correctly for bounded text

* rename
2022-01-05 17:58:03 +05:30
cec92c1d17 feat: update stroke color of bounded text along with container (#4541) 2022-01-05 16:27:48 +05:30
5f476e09d4 chore(deps-dev): bump @babel/core in /src/packages/utils (#4528)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.16.5 to 7.16.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.7/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-05 15:54:34 +05:30
9aa6a27252 chore(deps): bump @types/jest from 27.0.3 to 27.4.0 (#4529)
Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 27.0.3 to 27.4.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

---
updated-dependencies:
- dependency-name: "@types/jest"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-05 15:54:04 +05:30
a2e8806f57 fix: rotate bounded text when container is rotated before typing (#4535) 2022-01-04 18:03:24 +05:30
b71e702991 fix: undo should work when selecting bounded textr (#4537) 2022-01-04 18:02:16 +05:30
5c67329be6 fix: Reduce padding to 5px for bounded text (#4530)
* fix: Reduce padding to 5px

* reduce width by 50 to fix tests

* Push the word if appending space exceeds max width when breaking words

* fix spec
2022-01-03 17:59:26 +05:30
28546fbb55 fix: bound text doesn't inherit container (#4521) 2021-12-31 14:55:02 +01:00
b0cccbb9e8 chore(deps): bump @tldraw/vec from 1.2.9 to 1.4.0 (#4517)
Bumps [@tldraw/vec](https://github.com/tldraw/tldraw) from 1.2.9 to 1.4.0.
- [Release notes](https://github.com/tldraw/tldraw/releases)
- [Commits](https://github.com/tldraw/tldraw/compare/v1.2.9...v1.4.0)

---
updated-dependencies:
- dependency-name: "@tldraw/vec"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 14:44:44 +02:00
b621d065de feat: hints and shortcuts help around deep selection (#4502) 2021-12-31 11:00:20 +01:00
96580c92a5 chore(deps-dev): bump @babel/plugin-transform-arrow-functions (#4515)
Bumps [@babel/plugin-transform-arrow-functions](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-arrow-functions) from 7.16.5 to 7.16.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.7/packages/babel-plugin-transform-arrow-functions)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-arrow-functions"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 12:42:29 +05:30
975441549b chore(deps): bump sass from 1.43.5 to 1.45.2 (#4518)
Bumps [sass](https://github.com/sass/dart-sass) from 1.43.5 to 1.45.2.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.43.5...1.45.2)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 12:42:04 +05:30
4be701416a chore(deps-dev): bump @babel/preset-react in /src/packages/excalidraw (#4519)
Bumps [@babel/preset-react](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-react) from 7.16.0 to 7.16.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.7/packages/babel-preset-react)

---
updated-dependencies:
- dependency-name: "@babel/preset-react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 12:41:31 +05:30
1acb1e33f1 chore(deps-dev): bump @babel/preset-env in /src/packages/excalidraw (#4516)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.16.4 to 7.16.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.7/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 01:11:22 +00:00
986e1e40d3 chore(deps-dev): bump @babel/preset-typescript (#4514)
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.16.0 to 7.16.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.7/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 01:00:57 +00:00
fab4a0e060 chore(deps-dev): bump @babel/plugin-transform-runtime (#4508)
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.16.4 to 7.16.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.7/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:59:42 +02:00
b265ebf88f chore(deps): bump @tldraw/vec from 1.1.5 to 1.2.9 (#4479)
Bumps [@tldraw/vec](https://github.com/tldraw/tldraw) from 1.1.5 to 1.2.9.
- [Release notes](https://github.com/tldraw/tldraw/releases)
- [Commits](https://github.com/tldraw/tldraw/compare/v1.1.5...v1.2.9)

---
updated-dependencies:
- dependency-name: "@tldraw/vec"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:52:36 +02:00
351845019e chore(deps-dev): bump @types/pako from 1.0.2 to 1.0.3 (#4481)
Bumps [@types/pako](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/pako) from 1.0.2 to 1.0.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/pako)

---
updated-dependencies:
- dependency-name: "@types/pako"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:51:20 +02:00
c0fcce6f27 chore(deps): bump @testing-library/jest-dom from 5.15.1 to 5.16.1 (#4395)
Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 5.15.1 to 5.16.1.
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v5.15.1...v5.16.1)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:50:30 +02:00
b093d2d2b6 chore(deps-dev): bump prettier from 2.5.0 to 2.5.1 (#4360)
Bumps [prettier](https://github.com/prettier/prettier) from 2.5.0 to 2.5.1.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/2.5.0...2.5.1)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:49:43 +02:00
69548c5502 chore(deps): bump @types/react from 17.0.37 to 17.0.38 (#4483)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 17.0.37 to 17.0.38.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:49:15 +02:00
6ca0afa6e5 chore(deps-dev): bump @types/chai from 4.2.22 to 4.3.0 (#4394)
Bumps [@types/chai](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/chai) from 4.2.22 to 4.3.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/chai)

---
updated-dependencies:
- dependency-name: "@types/chai"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:48:59 +02:00
c50f81b829 chore(deps-dev): bump @babel/plugin-transform-arrow-functions (#4426)
Bumps [@babel/plugin-transform-arrow-functions](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-arrow-functions) from 7.16.0 to 7.16.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.5/packages/babel-plugin-transform-arrow-functions)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-arrow-functions"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:47:42 +02:00
b122c8c4eb chore(deps-dev): bump @babel/plugin-transform-async-to-generator (#4437)
Bumps [@babel/plugin-transform-async-to-generator](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-async-to-generator) from 7.16.0 to 7.16.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.5/packages/babel-plugin-transform-async-to-generator)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-async-to-generator"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:47:16 +02:00
9a7216fe94 chore(deps-dev): bump terser-webpack-plugin in /src/packages/excalidraw (#4423)
Bumps [terser-webpack-plugin](https://github.com/webpack-contrib/terser-webpack-plugin) from 5.2.5 to 5.3.0.
- [Release notes](https://github.com/webpack-contrib/terser-webpack-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/terser-webpack-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/terser-webpack-plugin/compare/v5.2.5...v5.3.0)

---
updated-dependencies:
- dependency-name: terser-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:46:52 +02:00
8eee749076 chore(deps-dev): bump @babel/preset-typescript in /src/packages/utils (#4430)
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.16.0 to 7.16.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.5/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:46:36 +02:00
2158ad0656 chore(deps-dev): bump @babel/core in /src/packages/utils (#4435)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.16.0 to 7.16.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.5/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:45:49 +02:00
74c3fea7f5 chore(deps): bump typescript from 4.5.2 to 4.5.4 (#4442)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.5.2 to 4.5.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.5.2...v4.5.4)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:45:31 +02:00
5e456e6d05 chore(deps-dev): bump lint-staged from 12.1.2 to 12.1.4 (#4478)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 12.1.2 to 12.1.4.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v12.1.2...v12.1.4)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-31 02:45:09 +02:00
477cce2ed6 fix: Text wrapping with grid (#4505) (#4506) 2021-12-30 19:10:31 +01:00
dd8e465304 feat: Support updating text properties by clicking on container (#4499) 2021-12-29 16:49:52 +05:30
11396a21de fix: check if process is defined before using so it works in browser (#4497)
* refactor: use isTestEnv() utils where applicable

* check if process is defined
2021-12-28 17:17:41 +05:30
38236bc5e0 tests: Add tests for wrapText util (#4495) 2021-12-28 16:52:57 +05:30
63ce5b82d7 fix: pending review fixes for sticky notes (#4493) 2021-12-28 16:24:44 +05:30
bae0e985b2 fix: prevent browser from scrolling when panning (#4489) 2021-12-27 14:18:11 +01:00
04f852a40a build: Added example folder for testing @excalidraw/excalidraw in local (#4488)
* build: Added example folder for testing @excalidraw/excalidraw in local

* remove unnecessary files

* use scss

* update docs

* newline

* remove index

* remove yarn

* use the bundled excalidraw.development.js for better testing and font will also be available

* remove src folder from example
2021-12-27 18:01:33 +05:30
f463c047c0 fix: pasted elements except binded text once paste action is complete (#4472) 2021-12-23 22:07:16 +05:30
1fd347cade fix: don't select binded text when ungrouping (#4470) 2021-12-23 21:36:29 +05:30
ef62390841 fix: set height correctly when text properties updated while editing in container until first submit (#4469)
* fix: set height correctly when text properties updated while editing in container

* rename PADDING to BOUND_TEXT_PADDING
2021-12-23 17:02:35 +05:30
bf2bca221e fix: align and distribute binded text in container and cleanup (#4468) 2021-12-23 17:02:13 +05:30
d0733b1960 fix: move binded text when moving container using keyboard (#4466) 2021-12-23 01:47:14 +05:30
64c2d76cfa fix: support dragging binded text in container selected in a group (#4462)
* fix: support moving binded text when container selected via group

* update coords of bounded text only when element doesn't belong to any group or element in group is selected

* dnt drag binded text when nested group selected

* Update src/element/dragElements.ts

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

Co-authored-by: David Luzar <luzar.david@gmail.com>
2021-12-22 19:16:49 +05:30
c76784b774 fix: Scope drag and drop events to Excalidraw container to prevent overriding the host drag and drop events (#4445)
* cross-env

* reverting lib

https://github.com/excalidraw/excalidraw/issues/4282

* Revert "reverting lib"

This reverts commit 840726806a.

* Update package.json

* Update App.tsx

* Update App.tsx

* lint

* updated changelog

* Update src/packages/excalidraw/CHANGELOG.md

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>

* Update src/packages/excalidraw/CHANGELOG.md

* Move fixes above build header

* Update src/packages/excalidraw/CHANGELOG.md

* lint

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
Co-authored-by: David Luzar <luzar.david@gmail.com>
2021-12-22 18:55:34 +05:30
25e54e5999 fix: vertically align single line when deleting text in bounded container (#4460) 2021-12-22 15:32:21 +05:30
55b7a7d554 fix: update height correctly when updating text properties in binded text (#4459)
* fix: update height correctly when updating text properties in binded text

* read height from editor style so its accurate

* fix
2021-12-22 12:08:51 +05:30
c1c37a6ee7 fix: align library item previews to center (#4447) 2021-12-21 19:59:36 +01:00
25b529f519 fix: vertically center align text when text deleted (#4457) 2021-12-22 00:07:55 +05:30
8e6a747873 fix: vertically center the first line as user starts typing in container (#4454)
* fix: vertically center the first line as user starts typing in container

* fix
2021-12-21 23:08:36 +05:30
089b05db1b fix: switch cursor to center of container when adding text when dimensions are too small (#4452) 2021-12-21 19:00:01 +05:30
081e097cef fix: vertically center align the bounded text correctly when zoomed (#4444)
* fix: vertically center align the bounded text correctly when zoomed

* dnt add offsets since its calculated correctly

* set editor max width better when offsets present

* Update src/element/textWysiwyg.tsx

* const

* revert
2021-12-21 17:13:11 +05:30
8b5657e1ce fix: support updating stroke color for text by typing in color picker input (#4415)
* fix: support updating stroke color for text by typing in color picker input

* restore focus when clicked on same property unless its color picker input and submit text on color picker blur

* focus editor on color picker blur

* don't focus text editor when color picker is active
2021-12-17 20:15:22 +05:30
8b2b03347c fix: bound text not atomic with container when changing z-index (#4414)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
2021-12-17 13:10:37 +00:00
c2a8712593 fix: update viewport coords correctly when editing text (#4416) 2021-12-17 11:38:18 +01:00
ff1d7728a0 fix: use word-break break-word only and update text editor height only when binded to container (#4410) 2021-12-17 15:24:23 +05:30
98b5c37e45 feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343)
* feat: Word wrap inside rect and increase height when size exceeded

* fixes for auto increase in height

* fix height

* respect newlines when wrapping text

* shift text area when height increases beyond mid rect height until it reaches to the top

* select bound text if present when rect selected

* mutate y coord after text submit

* Add padding of 30px and update dimensions acordingly

* Don't allow selecting bound text element directly

* support deletion of bound text element when rect deleted

* trim text

* Support autoshrink and improve algo

* calculate approx line height instead of hardcoding

* use textContainerId instead of storing textContainer element itself

* rename boundTextElement -> boundTextElementId

* fix text properties not getting reflected after edit inside rect

* Support resizing

* remove ts ignore

* increase height of container when text height increases while resizing

* use original text when editing/resizing so it adjusts based on original text

* fix tests

* add util isRectangleElement

* use isTextElement util everywhere

* disable selecting text inside rect when selectAll

* Bind text to circle and diamond as well

* fix tests

* vertically center align the text always

* better vertical align

* Disable binding arrows for text inside shapes

* set min width for text container when text is binded to container

* update dimensions of container if its less than min width/ min height

* Allow selecting of text container for transparent containers when clicked inside

* fix test

* preserve whitespaces between long word exceeding width and next word
Use word break instead of whitespace no wrap for better readability and support safari

* Perf improvements for measuring text width and resizing
* Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times
* Rewrite wrapText algo to break in words appropriately and for longer words
calculate the char width in order unless max width reached. This makes the
the number of runs linear (max text length times) which was earlier
textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run
* Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line

* use console.info so eslint doesnt warn :p

* cache char width and don't call resize unless min width exceeded

* update line height and height correctly when text properties inside container updated

* improve vertical centering when text properties updated, not yet perfect though

* when double clicked inside a conatiner  take the cursor to end of text same as what happens when enter is pressed

* Add hint when container selected

* Select container when escape key is pressed after submitting text

* fix copy/paste when using copy/paste action

* fix copy when dragged with alt pressed

* fix export to svg/png

* fix add to library

* Fix copy as png/svg

* Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec

* fix rotation jump

* moove all text utils to textElement.ts

* resize text element only after container resized so that width doesnt change when editing

* insert the remaining chars for long words once it goes beyond line

* fix typo, use string for character type

* renaming

* fix bugs in word wrap algo

* make grouping work

* set boundTextElementId only when text present else unset it

* rename textContainerId to containerId

* fix

* fix snap

* use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated

* use boundElementIds and also support binding text in images 🎉

* fix the sw/se ends when resizing from ne/nw

* fix y coord when resizing from north

* bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text

* bind when clicked on center of container

* use pre-wrap instead of normal so it works in ff

* use container boundTextElement when container present and trying to edit text

* review fixes

* make getBoundTextElementId type safe and check for existence when using this function

* fix

* don't duplicate boundElementIds when text submitted

* only remove last trailing space if present which we have added when joining words

* set width correctly when resizing to fix alignment issues

* make duplication work using cmd/ctrl+d

* set X coord correctly during resize

* don't allow resize to negative dimensions when text is bounded to container

* fix, check last char is space

* remove logs

* make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows

* add a util isTextBindableContainer to check if the container could bind text
2021-12-16 21:14:03 +05:30
7db63bd397 feat: redesign toolbar & tweaks (#4387) 2021-12-15 15:31:44 +01:00
390da3fd0f feat: change boundElementIdsboundElements (#4404) 2021-12-14 16:07:01 +01:00
104664cb9e feat: support selecting multiple points when editing line (#4373) 2021-12-13 13:35:07 +01:00
c822055ec8 chore(deps-dev): bump sass-loader in /src/packages/utils (#4390)
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 12.3.0 to 12.4.0.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v12.3.0...v12.4.0)

---
updated-dependencies:
- dependency-name: sass-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-13 11:42:29 +05:30
e15d73d94c chore(deps-dev): bump typescript in /src/packages/excalidraw (#4392)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.5.2 to 4.5.3.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.5.2...v4.5.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-13 11:42:18 +05:30
80ee097b85 chore(deps-dev): bump webpack in /src/packages/utils (#4391)
Bumps [webpack](https://github.com/webpack/webpack) from 5.64.4 to 5.65.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.64.4...v5.65.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-13 11:42:03 +05:30
10048b877b chore(deps-dev): bump webpack in /src/packages/excalidraw (#4389)
Bumps [webpack](https://github.com/webpack/webpack) from 5.64.4 to 5.65.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.64.4...v5.65.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-13 10:41:00 +05:30
5dd5862bb9 chore(deps-dev): bump sass-loader in /src/packages/excalidraw (#4393)
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 12.3.0 to 12.4.0.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v12.3.0...v12.4.0)

---
updated-dependencies:
- dependency-name: sass-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-13 10:40:41 +05:30
79989fedda chore: bump roughjs version (#4386)
Co-authored-by: dwelle <luzar.david@gmail.com>
2021-12-11 22:46:44 +01:00
cecabc2196 fix: husky not able to execute pre-commit on windows (#4370) 2021-12-09 15:15:54 +01:00
ed8fb40b63 fix: make firebase config parsing not fail on undefined env (#4381) 2021-12-09 12:24:41 +00:00
6e391728fe build: remove file loader and migrate to asset modules webpack for font assets (#4380)
* build: use type:javascript/auto so font file assets aren't duplicated

* update changelog

* remove file loader and use asset modules

* fix
2021-12-08 15:56:25 +05:30
dfbfbc3f11 feat: set package build target to es2017 (#4341) 2021-12-07 16:38:46 +01:00
9b8ee3cacf feat: horizontally center toolbar menu 2021-12-05 17:47:19 +01:00
4ea73d5d5b feat: Add support for rounded corners in diamond (#4369) 2021-12-05 16:56:19 +01:00
618f204ddd feat: allow zooming up to 3000% (#4358) 2021-12-04 13:51:28 +00:00
720588130c feat: stop discarding precision when rendering (#4357) 2021-12-04 13:49:57 +00:00
f354788cd0 fix: adding to library via contextmenu when no image is selected (#4356) 2021-12-04 11:59:37 +01:00
1c7ee09010 feat: support Image binding (#4347) 2021-12-03 11:42:28 +01:00
ca15b0a008 chore(deps-dev): bump postcss-loader in /src/packages/excalidraw (#4329)
Bumps [postcss-loader](https://github.com/webpack-contrib/postcss-loader) from 6.2.0 to 6.2.1.
- [Release notes](https://github.com/webpack-contrib/postcss-loader/releases)
- [Changelog](https://github.com/webpack-contrib/postcss-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/postcss-loader/compare/v6.2.0...v6.2.1)

---
updated-dependencies:
- dependency-name: postcss-loader
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-02 16:10:06 +02:00
650930c5ce chore(deps-dev): bump webpack in /src/packages/utils (#4328)
Bumps [webpack](https://github.com/webpack/webpack) from 5.64.3 to 5.64.4.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.64.3...v5.64.4)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-02 16:09:53 +02:00
79c0d59244 chore(deps-dev): bump webpack in /src/packages/excalidraw (#4327)
Bumps [webpack](https://github.com/webpack/webpack) from 5.64.3 to 5.64.4.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.64.3...v5.64.4)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-02 16:09:44 +02:00
cd50b5f7e9 chore(deps): bump @types/react from 17.0.35 to 17.0.37 (#4332)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 17.0.35 to 17.0.37.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-02 16:09:20 +02:00
c0434957ff chore(deps): bump @testing-library/jest-dom from 5.15.0 to 5.15.1 (#4333)
Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 5.15.0 to 5.15.1.
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v5.15.0...v5.15.1)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-02 16:08:59 +02:00
66aeaeb38d chore(deps): bump @tldraw/vec from 0.1.3 to 1.1.5 (#4334)
Bumps [@tldraw/vec](https://github.com/tldraw/tldraw) from 0.1.3 to 1.1.5.
- [Release notes](https://github.com/tldraw/tldraw/releases)
- [Commits](https://github.com/tldraw/tldraw/compare/v0.1.3...v1.1.5)

---
updated-dependencies:
- dependency-name: "@tldraw/vec"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-02 16:08:30 +02:00
7f545e74ab chore(deps): bump sass from 1.43.4 to 1.43.5 (#4330)
Bumps [sass](https://github.com/sass/dart-sass) from 1.43.4 to 1.43.5.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.43.4...1.43.5)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-02 15:12:01 +02:00
a776955579 chore(deps-dev): bump prettier from 2.4.1 to 2.5.0 (#4331)
Bumps [prettier](https://github.com/prettier/prettier) from 2.4.1 to 2.5.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/2.4.1...2.5.0)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-02 15:11:17 +02:00
afa7932c9b feat: set appState.exportBackground to true when exporting to jpg (#4342) 2021-11-30 22:08:55 +01:00
1ee8d7d082 chore(deps): Bump browser-fs-access to latest version (#4338)
Co-authored-by: dwelle <luzar.david@gmail.com>
2021-11-29 22:23:12 +01:00
06db702b5d feat: support selecting multiple library items via shift (#4306) 2021-11-26 12:46:23 +01:00
b53d1f6f3e feat: improve library preview image generation on publish (#4321)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2021-11-26 11:46:13 +01:00
ca1f3aa094 chore: Update translations from Crowdin (#4258) 2021-11-26 11:27:28 +01:00
8ff159e76e fix: export scale quality regression (#4316) 2021-11-25 14:05:22 +01:00
f9d2d537a2 feat: add element.updated (#4070) 2021-11-24 18:38:33 +01:00
dac970c640 chore(deps-dev): bump @babel/preset-env in /src/packages/utils (#4291)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.16.0 to 7.16.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.4/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-24 16:55:14 +00:00
78bb3b3d84 chore(deps-dev): bump @babel/plugin-transform-runtime (#4292)
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.16.0 to 7.16.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.4/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-24 18:54:33 +02:00
7d9d7ad297 chore(deps-dev): bump @babel/plugin-transform-runtime (#4288)
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.16.0 to 7.16.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.4/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-24 18:54:13 +02:00
de20a5e3ba chore(deps-dev): bump webpack in /src/packages/excalidraw (#4314)
Bumps [webpack](https://github.com/webpack/webpack) from 5.64.0 to 5.64.3.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.64.0...v5.64.3)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-24 18:52:51 +02:00
289f72e45d chore(deps-dev): bump webpack in /src/packages/utils (#4315)
Bumps [webpack](https://github.com/webpack/webpack) from 5.64.0 to 5.64.3.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.64.0...v5.64.3)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-24 18:52:36 +02:00
6dd0e6a4c5 fix: remove 100% height from tooltip container to fix layout issues (#3980) 2021-11-24 17:16:18 +01:00
96b31ecbce fix: inline ENV variables when building excalidraw package (#4311) 2021-11-24 16:25:19 +01:00
a132f154cb chore(deps-dev): bump @babel/preset-env in /src/packages/excalidraw (#4286)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.16.0 to 7.16.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.4/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-24 17:22:57 +02:00
23acd8f6d1 chore(deps-dev): bump mini-css-extract-plugin (#4289)
Bumps [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) from 2.4.4 to 2.4.5.
- [Release notes](https://github.com/webpack-contrib/mini-css-extract-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/mini-css-extract-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/mini-css-extract-plugin/compare/v2.4.4...v2.4.5)

---
updated-dependencies:
- dependency-name: mini-css-extract-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-24 17:22:34 +02:00
a60709f5ea chore(deps-dev): bump lint-staged from 12.0.1 to 12.1.2 (#4312)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 12.0.1 to 12.1.2.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v12.0.1...v12.1.2)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-24 17:21:06 +02:00
896c476716 feat: compress shareLink data when uploading to json server (#4225) 2021-11-24 14:45:13 +01:00
133ba19919 chore(deps): bump @types/jest from 27.0.2 to 27.0.3 (#4295)
Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 27.0.2 to 27.0.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

---
updated-dependencies:
- dependency-name: "@types/jest"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-24 15:40:49 +02:00
a2136bfe9d chore(deps): bump @types/react from 17.0.34 to 17.0.35 (#4297)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 17.0.34 to 17.0.35.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-24 15:39:32 +02:00
6fbd64fdaa chore(deps-dev): bump firebase-tools from 9.22.0 to 9.23.0 (#4293)
Bumps [firebase-tools](https://github.com/firebase/firebase-tools) from 9.22.0 to 9.23.0.
- [Release notes](https://github.com/firebase/firebase-tools/releases)
- [Commits](https://github.com/firebase/firebase-tools/compare/v9.22.0...v9.23.0)

---
updated-dependencies:
- dependency-name: firebase-tools
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-24 15:39:16 +02:00
cc4b0c2932 feat: supply version param when installing libraries (#4305) 2021-11-23 17:59:26 +01:00
b6ef953dc9 fix: SVG export in dark mode with embedded bitmap image (#4285)
Co-authored-by: dwelle <luzar.david@gmail.com>
2021-11-20 15:31:51 +01:00
620b662085 chore: bump typescript@4.5.2 (#4283)
* chore: bump typescript@4.5.2

* bump typescript and fix tsconfig for npm package
2021-11-19 19:51:28 +01:00
1c11df011a fix: new FS API not working on Linux (#4280) 2021-11-19 14:20:42 +01:00
59e9651547 feat: log FS abortError to console (#4279) 2021-11-19 10:54:23 +01:00
1c48d122e0 fix: url -> URL for consistency (#4277) 2021-11-19 11:21:23 +05:30
e4d02fb275 feat: Add validation for website and remove validation for library item name (#4269)
* Github->GitHub

* allow numbers

* remove validation for lib/item name
2021-11-18 10:24:26 +00:00
34a382ace9 fix: prevent adding images to library via contextMenu (#4264) 2021-11-17 20:06:26 +00:00
e60e48e67d fix: account for libraries v2 when prompting (#4263) 2021-11-17 19:54:40 +00:00
84d1d9993c feat: Allow publishing libraries from UI (#4115)
* feat: Allow publishing libraries from UI

* Add status for each library item and show publish only for unpublished libs

* Add publish library dialog

* Pass the data to publish the library

* pass lib blob

* Handle old and new libraries when importing

* Better error handling

* Show publish success when library submitted for review

* don't close library when publish success dialog open

* Support multiple libs deletion and publish

* Set status to published once library submitted for review

* Save  to LS after library published

* unique key for publish and delete

* fix layout shift when hover and also highlight selected library items

* design improvements

* migrate old library to the new one

* fix

* fix tests

* use i18n

* Support submit type in toolbutton

* Use html5 form validation, add asteriks for required fields, add twitter handle, mark github handle optional

* Add twitter handle in form state

* revert html5 validation as fetch is giving some issues :/

* clarify types around LibraryItems

* Add website optional field

* event.preventDefault to make htm5 form validationw work

* improve png generation by drawing a bounding box rect and aligining pngs to support multiple libs png

* remove ts-ignore

* add placeholders for fields

* decrease clickable area for checkbox by 0.5em

* add checkbox background color

* rename `items` to `elements`

* improve checkbox hit area

* show selected library items in publish dialog

* decrease dimensions by 3px to improve jerky experience when opening/closing library menu

* Don't close publish dialog when clicked outside

* Show selected library actions only when any library item selected and use icons instead of button

* rename library to libraryItems in excalidrawLib and added migration

* change icon and swap bg/color

* use blue brand color for hover/selected states

* prompt for confirmation when deleting library items

* separate unpublished items from published

* factor `LibraryMenu` into own file

* i18n and minor fixes for unpublished items

* fix not rendering empty cells when library empty

* don't render published section if empty and unpublished is not

* Add edit name functionality for library items

* fix

* edit lib name with onchange/blur

* bump library version

* prefer response error message

* add library urls to ENV vars

* mark lib item name as required

* Use input only for lib item name

* better error validation for lib items

* fix label styling for lib items

* design and i18n fixes

* Save publish dialog data to local storage and clear once published

* Add a note about MIT License

* Add note for guidelines

* Add tooltip for publish button

* Show spinner in submit button when submission is in progress

* assign id for older lib items when installed and set status as published for all lib when installed

* update export icon and support export library for selected items

* move LibraryMenuItems into its own component as its best to keep one comp per file

* fix spec

* Refactoring the library actions for reusablility

* show only load when items not present

* close on click outside in publish dialog

* ad dialog description and tweak copy

* vertically center input labels

* align input styles

* move author name input to other usernames

* rename param

* inline to simplify

* fix to not inline `undefined` class names

* fix version & include only latest lib schema in library export type

* await response callback

* refactor types

* refactor

* i18n

* align casing & tweaks

* move ls logic to publishLibrary

* support removal of item inside publish dialog

* fix labels for trash icon when items selected

* replace window.confirm for removal libs with confirm dialog

* fix input/textarea styling

* move library item menu scss to its own file

* use blue for load and cyan for publish

* reduce margin for submit and make submit => Submit

* Make library items header sticky

* move publish icon to left so there is no jerkiness when unpublish items selected

* update url

* fix grid gap between lib items

* Mark older items imported from initial data as unpublished

* add text to publish button on non-mobile

* add items counter

* fix test

* show personal and excal libs sections and personal goes first

* show toast on adding to library via contextMenu

* Animate plus icon and not the pending item

* fix snap

* use i18n when no item in publish dialog

* tweak style of new lib item

* show empty cells for both sections and set status as published for installed libs

* fix

* push selected item first in unpublished section

* set status as published for imported from webiste but unpublished for json

* Add items to the begining of library

* add `created` library item attr

* fix test

* use `defaultValue` instead of `value`

* fix dark theme styles

* fix toggle button not closing library

* close library menu on Escape

* tweak publish dialog item remove style

* fix remove icon in publish dialog

Co-authored-by: dwelle <luzar.david@gmail.com>
2021-11-17 23:53:43 +05:30
3ff9744b39 feat: create confirm dialog to use instead of window.confirm (#4256)
* feat: create confirm dialog to use instead of window.confirm

* move confirm to right

* add types

* less margin
2021-11-16 18:55:56 +05:30
b9abcc825a chore(deps-dev): bump webpack in /src/packages/utils (#4245)
Bumps [webpack](https://github.com/webpack/webpack) from 5.62.1 to 5.64.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.62.1...v5.64.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-14 10:47:31 +01:00
9679eaf74c chore(deps-dev): bump @types/web from 0.0.46 to 0.0.47 (#4249)
Bumps [@types/web](https://github.com/microsoft/TypeScript-DOM-Lib-Generator) from 0.0.46 to 0.0.47.
- [Release notes](https://github.com/microsoft/TypeScript-DOM-Lib-Generator/releases)
- [Commits](https://github.com/microsoft/TypeScript-DOM-Lib-Generator/compare/@types/web@0.0.46...@types/web@0.0.47)

---
updated-dependencies:
- dependency-name: "@types/web"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-14 10:46:42 +01:00
284747d742 chore(deps-dev): bump terser-webpack-plugin in /src/packages/excalidraw (#4243)
Bumps [terser-webpack-plugin](https://github.com/webpack-contrib/terser-webpack-plugin) from 5.2.4 to 5.2.5.
- [Release notes](https://github.com/webpack-contrib/terser-webpack-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/terser-webpack-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/terser-webpack-plugin/compare/v5.2.4...v5.2.5)

---
updated-dependencies:
- dependency-name: terser-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-14 10:46:18 +01:00
876f85fd7a chore(deps-dev): bump webpack in /src/packages/excalidraw (#4244)
Bumps [webpack](https://github.com/webpack/webpack) from 5.62.1 to 5.64.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.62.1...v5.64.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-14 10:45:55 +01:00
efc2bbed21 chore(deps): bump browser-fs-access from 0.21.0 to 0.21.1 (#4248)
Bumps [browser-fs-access](https://github.com/GoogleChromeLabs/browser-fs-access) from 0.21.0 to 0.21.1.
- [Release notes](https://github.com/GoogleChromeLabs/browser-fs-access/releases)
- [Commits](https://github.com/GoogleChromeLabs/browser-fs-access/compare/v0.21.0...v0.21.1)

---
updated-dependencies:
- dependency-name: browser-fs-access
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-14 10:45:29 +01:00
61d193b87b chore(deps-dev): bump lint-staged from 11.2.6 to 12.0.1 (#4250)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 11.2.6 to 12.0.1.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v11.2.6...v12.0.1)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-14 10:45:06 +01:00
3989d6a989 chore(deps): bump roughjs from 4.4.5 to 4.5.0 (#4246)
Bumps [roughjs](https://github.com/pshihn/rough) from 4.4.5 to 4.5.0.
- [Release notes](https://github.com/pshihn/rough/releases)
- [Changelog](https://github.com/rough-stuff/rough/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pshihn/rough/commits)

---
updated-dependencies:
- dependency-name: roughjs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-14 10:44:44 +01:00
f6559b65ef chore: Update translations from Crowdin (#4201) 2021-11-12 12:13:34 +01:00
bc6b066c07 Remove outdated OT info (#4232) 2021-11-09 12:16:32 +01:00
6370d517a2 chore(deps-dev): bump css-loader in /src/packages/excalidraw (#4209)
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 6.5.0 to 6.5.1.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/compare/v6.5.0...v6.5.1)

---
updated-dependencies:
- dependency-name: css-loader
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-08 17:45:06 +00:00
b8a37c42e4 chore(deps): bump @tldraw/vec from 0.0.132 to 0.1.3 (#4215)
Bumps [@tldraw/vec](https://github.com/tldraw/vec) from 0.0.132 to 0.1.3.
- [Release notes](https://github.com/tldraw/vec/releases)
- [Commits](https://github.com/tldraw/vec/commits)

---
updated-dependencies:
- dependency-name: "@tldraw/vec"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-08 18:42:21 +01:00
76763b80a9 chore(deps-dev): bump @types/web from 0.0.45 to 0.0.46 (#4214)
Bumps [@types/web](https://github.com/microsoft/TypeScript-DOM-Lib-Generator) from 0.0.45 to 0.0.46.
- [Release notes](https://github.com/microsoft/TypeScript-DOM-Lib-Generator/releases)
- [Commits](https://github.com/microsoft/TypeScript-DOM-Lib-Generator/compare/@types/web@0.0.45...@types/web@0.0.46)

---
updated-dependencies:
- dependency-name: "@types/web"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-08 18:41:59 +01:00
d2a2c9d6b5 chore(deps-dev): bump webpack in /src/packages/utils (#4211)
Bumps [webpack](https://github.com/webpack/webpack) from 5.61.0 to 5.62.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.61.0...v5.62.1)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-08 17:41:50 +00:00
3a72f347d2 chore(deps-dev): bump webpack in /src/packages/excalidraw (#4208)
Bumps [webpack](https://github.com/webpack/webpack) from 5.61.0 to 5.62.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.61.0...v5.62.1)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-08 18:41:13 +01:00
c1d9456235 chore(deps-dev): bump mini-css-extract-plugin (#4207)
Bumps [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) from 2.4.3 to 2.4.4.
- [Release notes](https://github.com/webpack-contrib/mini-css-extract-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/mini-css-extract-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/mini-css-extract-plugin/compare/v2.4.3...v2.4.4)

---
updated-dependencies:
- dependency-name: mini-css-extract-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-08 18:40:45 +01:00
c4f8b98208 chore(deps-dev): bump css-loader in /src/packages/utils (#4210)
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 6.5.0 to 6.5.1.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/compare/v6.5.0...v6.5.1)

---
updated-dependencies:
- dependency-name: css-loader
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-08 18:40:18 +01:00
b6eb57d3f1 chore(deps): bump @testing-library/jest-dom from 5.14.1 to 5.15.0 (#4212)
Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 5.14.1 to 5.15.0.
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v5.14.1...v5.15.0)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-08 18:39:52 +01:00
473b8ca0ca chore(deps): bump @types/react from 17.0.33 to 17.0.34 (#4216)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 17.0.33 to 17.0.34.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-08 18:39:24 +01:00
45206c4ef1 chore(deps-dev): bump firebase-tools from 9.21.0 to 9.22.0 (#4219)
Bumps [firebase-tools](https://github.com/firebase/firebase-tools) from 9.21.0 to 9.22.0.
- [Release notes](https://github.com/firebase/firebase-tools/releases)
- [Commits](https://github.com/firebase/firebase-tools/compare/v9.21.0...v9.22.0)

---
updated-dependencies:
- dependency-name: firebase-tools
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-08 18:38:55 +01:00
56b4a29aaa chore(deps): bump @types/react-dom from 17.0.10 to 17.0.11 (#4218)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-07 15:00:24 +01:00
bb4dda64b5 chore(deps): bump roughjs from 4.4.4 to 4.4.5 (#4221)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-07 14:57:09 +01:00
39e53b4ae7 feat: Allow letters in IDs for storing files in backend (#4224) 2021-11-07 14:37:13 +01:00
6143d5195a refactor: deduplicate encryption helpers (#4146) 2021-11-07 14:33:21 +01:00
f59e608f18 fix: Skia rendering issues (#4200) 2021-11-04 15:55:10 +01:00
6b24592e4a chore: Update translations from Crowdin (#4150) 2021-11-04 14:10:21 +02:00
7b442997dc chore: Update docker action to v2 (#4198) 2021-11-04 14:10:00 +02:00
4bfc5bbcaa chore: Update i18next-browser-languagedetector (#4196) 2021-11-03 21:07:13 +00:00
2b29b9a96d chore: Consistent case for clear canvas, change font of buttons and clean up unused strings (#4195)
* chore: Consistent case for clear canvas and font

* Remove unused

* remove
2021-11-03 21:31:27 +02:00
cc201a6d80 fix: ellipse roughness when 0 (#4194) 2021-11-03 12:50:54 +01:00
5be58b59e0 fix: Proper string for invalid SVG (#4191) 2021-11-03 10:10:58 +01:00
f1eb969565 feat: Remove support for V1 unencrypted backend (#4189) 2021-11-02 14:52:25 +02:00
8d4f455cd3 chore: Update Typescript to 4.4.4 (#4188) 2021-11-02 14:24:16 +02:00
60262cb4cc chore(deps): bump idb-keyval from 5.1.3 to 6.0.3 (#4181)
Bumps [idb-keyval](https://github.com/jakearchibald/idb-keyval) from 5.1.3 to 6.0.3.
- [Release notes](https://github.com/jakearchibald/idb-keyval/releases)
- [Changelog](https://github.com/jakearchibald/idb-keyval/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jakearchibald/idb-keyval/compare/v5.1.3...v6.0.3)

---
updated-dependencies:
- dependency-name: idb-keyval
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-02 09:44:05 +02:00
7501c24f22 feat: Use separate backend for local storage (#4187) 2021-11-02 09:33:27 +02:00
00d81aa982 chore(deps-dev): bump @babel/plugin-transform-typescript (#4160)
Bumps [@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-typescript) from 7.15.8 to 7.16.1.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.1/packages/babel-plugin-transform-typescript)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 13:36:09 +00:00
67fe156d06 chore(deps-dev): bump @babel/plugin-transform-async-to-generator (#4162)
Bumps [@babel/plugin-transform-async-to-generator](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-async-to-generator) from 7.14.5 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/packages/babel-plugin-transform-async-to-generator)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-async-to-generator"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 13:31:12 +00:00
ef433233d1 chore(deps-dev): bump @babel/preset-typescript in /src/packages/utils (#4161)
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.15.0 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 13:24:26 +00:00
1c7056bdaa chore: bump Prettier to the latest (#4185) 2021-11-01 15:24:05 +02:00
277ffaacb9 chore(deps-dev): bump css-loader in /src/packages/excalidraw (#4122)
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 5.2.6 to 6.5.0.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/compare/v5.2.6...v6.5.0)

---
updated-dependencies:
- dependency-name: css-loader
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 13:23:38 +00:00
2a3e242cfd chore(deps-dev): bump @babel/plugin-transform-runtime (#4164)
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.15.8 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 13:20:22 +00:00
b1c6051d6b chore(deps-dev): bump webpack in /src/packages/utils (#4134)
Bumps [webpack](https://github.com/webpack/webpack) from 5.50.0 to 5.61.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.50.0...v5.61.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 13:19:04 +00:00
8df9742463 chore(deps-dev): bump webpack-cli in /src/packages/excalidraw (#4132)
Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 4.7.2 to 4.9.1.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.7.2...webpack-cli@4.9.1)

---
updated-dependencies:
- dependency-name: webpack-cli
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 13:18:24 +00:00
9fdc382d71 chore(deps-dev): bump @babel/plugin-transform-arrow-functions (#4165)
Bumps [@babel/plugin-transform-arrow-functions](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-arrow-functions) from 7.14.5 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/packages/babel-plugin-transform-arrow-functions)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-arrow-functions"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 13:15:16 +00:00
f70d11c2d1 chore(deps-dev): bump @babel/plugin-transform-typescript (#4167)
Bumps [@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-typescript) from 7.15.8 to 7.16.1.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.1/packages/babel-plugin-transform-typescript)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 15:11:04 +02:00
05e54d6785 chore(deps-dev): bump mini-css-extract-plugin (#4094)
Bumps [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) from 1.6.1 to 2.4.3.
- [Release notes](https://github.com/webpack-contrib/mini-css-extract-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/mini-css-extract-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/mini-css-extract-plugin/compare/v1.6.1...v2.4.3)

---
updated-dependencies:
- dependency-name: mini-css-extract-plugin
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 13:10:36 +00:00
795a6e4546 chore(deps-dev): bump webpack-cli in /src/packages/utils (#4118)
Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 4.7.2 to 4.9.1.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.7.2...webpack-cli@4.9.1)

---
updated-dependencies:
- dependency-name: webpack-cli
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 13:09:32 +00:00
a01a4ad739 chore(deps): bump @testing-library/react from 11.2.6 to 12.1.2 (#4177)
Bumps [@testing-library/react](https://github.com/testing-library/react-testing-library) from 11.2.6 to 12.1.2.
- [Release notes](https://github.com/testing-library/react-testing-library/releases)
- [Changelog](https://github.com/testing-library/react-testing-library/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/react-testing-library/compare/v11.2.6...v12.1.2)

---
updated-dependencies:
- dependency-name: "@testing-library/react"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 13:03:24 +00:00
e09b96ac6f chore(deps-dev): bump @babel/core in /src/packages/excalidraw (#4166)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.15.8 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 12:56:22 +00:00
d48fb17718 chore(deps-dev): bump webpack in /src/packages/excalidraw (#4144)
Bumps [webpack](https://github.com/webpack/webpack) from 5.50.0 to 5.61.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.50.0...v5.61.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 18:24:40 +05:30
ede3c4af82 chore(deps-dev): bump postcss-loader in /src/packages/excalidraw (#4169)
Bumps [postcss-loader](https://github.com/webpack-contrib/postcss-loader) from 6.1.1 to 6.2.0.
- [Release notes](https://github.com/webpack-contrib/postcss-loader/releases)
- [Changelog](https://github.com/webpack-contrib/postcss-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/postcss-loader/compare/v6.1.1...v6.2.0)

---
updated-dependencies:
- dependency-name: postcss-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 14:53:43 +02:00
8bcfd97fc5 chore(deps-dev): bump css-loader in /src/packages/utils (#4119)
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 6.2.0 to 6.5.0.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/compare/v6.2.0...v6.5.0)

---
updated-dependencies:
- dependency-name: css-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 14:50:49 +02:00
5721c6dfb5 chore(deps): bump nanoid from 3.1.22 to 3.1.30 (#4176)
Bumps [nanoid](https://github.com/ai/nanoid) from 3.1.22 to 3.1.30.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.1.22...3.1.30)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 12:47:06 +00:00
9b1f77c3be chore(deps-dev): bump @babel/plugin-transform-async-to-generator (#4168)
Bumps [@babel/plugin-transform-async-to-generator](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-async-to-generator) from 7.14.5 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/packages/babel-plugin-transform-async-to-generator)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-async-to-generator"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 12:43:37 +00:00
3369035f40 feat: add hint around canvas panning (#4159) 2021-11-01 13:36:06 +01:00
dbc7a8599b chore(deps): bump @tldraw/vec from 0.0.106 to 0.0.132 (#4175)
Bumps [@tldraw/vec](https://github.com/tldraw/tldraw/tree/HEAD/packages/vec) from 0.0.106 to 0.0.132.
- [Release notes](https://github.com/tldraw/tldraw/releases)
- [Commits](https://github.com/tldraw/tldraw/commits/HEAD/packages/vec)

---
updated-dependencies:
- dependency-name: "@tldraw/vec"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 14:35:17 +02:00
09f649daf7 chore(deps-dev): bump @types/pako from 1.0.1 to 1.0.2 (#4170)
Bumps [@types/pako](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/pako) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/pako)

---
updated-dependencies:
- dependency-name: "@types/pako"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 14:33:09 +02:00
d357664850 chore(deps): bump perfect-freehand from 1.0.15 to 1.0.16 (#4178)
Bumps [perfect-freehand](https://github.com/steveruizok/perfect-freehand) from 1.0.15 to 1.0.16.
- [Release notes](https://github.com/steveruizok/perfect-freehand/releases)
- [Commits](https://github.com/steveruizok/perfect-freehand/compare/v1.0.15...v1.0.16)

---
updated-dependencies:
- dependency-name: perfect-freehand
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 14:32:37 +02:00
f973fdfa89 chore(deps): bump fake-indexeddb from 3.1.3 to 3.1.7 (#4172)
Bumps [fake-indexeddb](https://github.com/dumbmatter/fakeIndexedDB) from 3.1.3 to 3.1.7.
- [Release notes](https://github.com/dumbmatter/fakeIndexedDB/releases)
- [Changelog](https://github.com/dumbmatter/fakeIndexedDB/blob/master/CHANGELOG.md)
- [Commits](https://github.com/dumbmatter/fakeIndexedDB/compare/v3.1.3...v3.1.7)

---
updated-dependencies:
- dependency-name: fake-indexeddb
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 14:31:54 +02:00
c15bc50f17 chore(deps-dev): bump @babel/preset-env in /src/packages/excalidraw (#4163)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.15.8 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 14:31:34 +02:00
c2d0107cc5 chore(deps): bump sass from 1.32.10 to 1.43.4 (#4174)
Bumps [sass](https://github.com/sass/dart-sass) from 1.32.10 to 1.43.4.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.32.10...1.43.4)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 14:31:13 +02:00
c43fac31a1 chore(deps): bump @types/react from 17.0.3 to 17.0.33 (#4179)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 17.0.3 to 17.0.33.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 14:30:43 +02:00
9dfaf1752b chore(deps): bump open-color from 1.8.0 to 1.9.1 (#4180)
Bumps [open-color](https://github.com/yeun/open-color) from 1.8.0 to 1.9.1.
- [Release notes](https://github.com/yeun/open-color/releases)
- [Changelog](https://github.com/yeun/open-color/blob/master/build_release)
- [Commits](https://github.com/yeun/open-color/compare/v1.8.0...v1.9.1)

---
updated-dependencies:
- dependency-name: open-color
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 14:30:17 +02:00
d9a1eb2f01 chore(deps-dev): bump firebase-tools from 9.9.0 to 9.21.0 (#4184)
Bumps [firebase-tools](https://github.com/firebase/firebase-tools) from 9.9.0 to 9.21.0.
- [Release notes](https://github.com/firebase/firebase-tools/releases)
- [Commits](https://github.com/firebase/firebase-tools/compare/v9.9.0...v9.21.0)

---
updated-dependencies:
- dependency-name: firebase-tools
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 14:29:56 +02:00
f1e17a320f chore(deps-dev): bump @babel/preset-env in /src/packages/utils (#4151)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.15.8 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 10:05:36 +00:00
75ecd818b3 chore(deps-dev): bump webpack-bundle-analyzer in /src/packages/utils (#4158)
Bumps [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) from 4.4.2 to 4.5.0.
- [Release notes](https://github.com/webpack-contrib/webpack-bundle-analyzer/releases)
- [Changelog](https://github.com/webpack-contrib/webpack-bundle-analyzer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/webpack-bundle-analyzer/compare/v4.4.2...v4.5.0)

---
updated-dependencies:
- dependency-name: webpack-bundle-analyzer
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 10:05:03 +00:00
a7abc71f6a chore: Update dependabot limits (#4145) 2021-11-01 12:03:16 +02:00
6d0f0c8f21 chore(deps-dev): bump @babel/plugin-transform-runtime (#4152)
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.15.8 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 12:00:41 +02:00
790e6da500 fix: images not initialized correctly (#4157)
* fix: image not initialized correctly due to not renewing `state.pendingImageElement`

* ensure we replace elements on update

* set file as errored on >= 400 status respones
2021-11-01 10:44:57 +01:00
8df1a11535 chore(deps-dev): bump @babel/plugin-transform-arrow-functions (#4148)
Bumps [@babel/plugin-transform-arrow-functions](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-arrow-functions) from 7.14.5 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/packages/babel-plugin-transform-arrow-functions)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-arrow-functions"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-31 10:00:11 +00:00
b61ee56dc8 chore(deps-dev): bump @babel/core in /src/packages/utils (#4149)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.15.8 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-31 11:55:32 +02:00
c61f95a327 fix: image-related fixes (#4147)
* flush queues on portal close

* fix mouse broadcast race condition

* stop mutating image elements when updating status

to fix race condition when closing/opening collab room

* check `files` when resolving `LayerUI`

* fix displaying AbortError
2021-10-30 23:40:35 +02:00
d6d629f416 chore: Update translations from Crowdin (#4109) 2021-10-30 19:26:54 +03:00
65dec605f2 chore(deps-dev): bump @babel/preset-typescript (#4143)
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.15.0 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-30 16:20:16 +00:00
cacec0b5c4 chore(deps-dev): bump @babel/preset-react in /src/packages/excalidraw (#4140)
Bumps [@babel/preset-react](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-react) from 7.14.5 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/packages/babel-preset-react)

---
updated-dependencies:
- dependency-name: "@babel/preset-react"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-30 12:03:51 +03:00
87a302d7e9 chore(deps-dev): bump sass-loader in /src/packages/excalidraw (#4139)
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 12.1.0 to 12.3.0.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v12.1.0...v12.3.0)

---
updated-dependencies:
- dependency-name: sass-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-30 11:34:17 +03:00
899b36c206 chore(deps-dev): bump babel-loader in /src/packages/excalidraw (#4138)
Bumps [babel-loader](https://github.com/babel/babel-loader) from 8.2.2 to 8.2.3.
- [Release notes](https://github.com/babel/babel-loader/releases)
- [Changelog](https://github.com/babel/babel-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel-loader/compare/v8.2.2...v8.2.3)

---
updated-dependencies:
- dependency-name: babel-loader
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-30 00:41:13 +00:00
534cbef982 chore(deps-dev): bump autoprefixer in /src/packages/excalidraw (#4137)
Bumps [autoprefixer](https://github.com/postcss/autoprefixer) from 10.3.1 to 10.4.0.
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/autoprefixer/compare/10.3.1...10.4.0)

---
updated-dependencies:
- dependency-name: autoprefixer
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-30 00:01:45 +03:00
b7f118404e chore(deps-dev): bump webpack-bundle-analyzer (#4121)
Bumps [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) from 4.4.2 to 4.5.0.
- [Release notes](https://github.com/webpack-contrib/webpack-bundle-analyzer/releases)
- [Changelog](https://github.com/webpack-contrib/webpack-bundle-analyzer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/webpack-bundle-analyzer/compare/v4.4.2...v4.5.0)

---
updated-dependencies:
- dependency-name: webpack-bundle-analyzer
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 18:37:49 +03:00
aab5067718 chore(deps-dev): bump @types/resize-observer-browser from 0.1.5 to 0.1.6 (#4135)
Bumps [@types/resize-observer-browser](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/resize-observer-browser) from 0.1.5 to 0.1.6.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/resize-observer-browser)

---
updated-dependencies:
- dependency-name: "@types/resize-observer-browser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 15:36:23 +00:00
b679da02ee chore(deps-dev): bump terser-webpack-plugin in /src/packages/excalidraw (#4128)
Bumps [terser-webpack-plugin](https://github.com/webpack-contrib/terser-webpack-plugin) from 5.1.4 to 5.2.4.
- [Release notes](https://github.com/webpack-contrib/terser-webpack-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/terser-webpack-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/terser-webpack-plugin/compare/v5.1.4...v5.2.4)

---
updated-dependencies:
- dependency-name: terser-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 18:26:30 +03:00
ec652820ea chore(deps): bump @types/jest from 26.0.22 to 27.0.2 (#4131)
Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 26.0.22 to 27.0.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

---
updated-dependencies:
- dependency-name: "@types/jest"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 18:26:15 +03:00
5d941ed107 chore(deps-dev): bump @babel/preset-env in /src/packages/utils (#4129)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.15.0 to 7.15.8.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.15.8/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 18:25:59 +03:00
adc478ca34 chore(deps-dev): bump @babel/preset-env in /src/packages/excalidraw (#4130)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.14.9 to 7.15.8.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.15.8/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 18:25:47 +03:00
f1202adb15 feat: stop using production services for development (#4113) 2021-10-29 17:13:28 +02:00
fd439cf38a chore(deps-dev): bump babel-loader in /src/packages/utils (#4124)
Bumps [babel-loader](https://github.com/babel/babel-loader) from 8.2.2 to 8.2.3.
- [Release notes](https://github.com/babel/babel-loader/releases)
- [Changelog](https://github.com/babel/babel-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel-loader/compare/v8.2.2...v8.2.3)

---
updated-dependencies:
- dependency-name: babel-loader
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 11:32:52 +00:00
83c63be846 chore(deps-dev): bump @babel/preset-typescript (#4127)
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.14.5 to 7.15.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.15.0/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 11:26:28 +00:00
b59d49dd7f chore(deps-dev): bump sass-loader in /src/packages/utils (#4126)
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 12.1.0 to 12.3.0.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v12.1.0...v12.3.0)

---
updated-dependencies:
- dependency-name: sass-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 11:25:02 +00:00
0116b70edf chore(deps): bump @testing-library/jest-dom from 5.11.10 to 5.14.1 (#4125)
Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 5.11.10 to 5.14.1.
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v5.11.10...v5.14.1)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 11:24:54 +00:00
3f390d4858 chore(deps-dev): bump ts-loader in /src/packages/excalidraw (#4002)
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 9.2.4 to 9.2.6.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v9.2.4...v9.2.6)

---
updated-dependencies:
- dependency-name: ts-loader
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 11:24:16 +00:00
fdde73bff4 chore(deps-dev): bump @babel/core in /src/packages/excalidraw (#4069)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.14.8 to 7.15.8.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.15.8/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 11:21:07 +00:00
90a416e265 chore(deps): bump @types/react-dom from 17.0.3 to 17.0.10 (#4120)
Bumps [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) from 17.0.3 to 17.0.10.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

---
updated-dependencies:
- dependency-name: "@types/react-dom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 14:17:59 +03:00
a828b2e5de chore(deps-dev): bump @babel/plugin-transform-typescript (#4044)
Bumps [@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-typescript) from 7.14.6 to 7.15.8.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.15.8/packages/babel-plugin-transform-typescript)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 11:16:44 +00:00
7c51d3c24c chore(deps-dev): bump ts-loader in /src/packages/utils (#4117)
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 9.2.4 to 9.2.6.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v9.2.4...v9.2.6)

---
updated-dependencies:
- dependency-name: ts-loader
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 11:13:03 +00:00
4d2d6f181a chore(deps): bump tar from 4.4.15 to 4.4.19 (#3953)
Bumps [tar](https://github.com/npm/node-tar) from 4.4.15 to 4.4.19.
- [Release notes](https://github.com/npm/node-tar/releases)
- [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-tar/compare/v4.4.15...v4.4.19)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 11:10:33 +00:00
071416f6ef chore(deps-dev): bump @babel/plugin-transform-typescript (#4045)
Bumps [@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-typescript) from 7.14.6 to 7.15.8.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.15.8/packages/babel-plugin-transform-typescript)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 14:10:19 +03:00
d675b07089 chore(deps-dev): bump @babel/core in /src/packages/utils (#4043)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.14.8 to 7.15.8.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.15.8/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 14:09:53 +03:00
3975fd592a chore(deps-dev): bump @babel/plugin-transform-runtime (#4042)
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.14.5 to 7.15.8.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.15.8/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 14:09:37 +03:00
34a9a4dac6 chore(deps-dev): bump @babel/preset-typescript in /src/packages/utils (#3928)
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.14.5 to 7.15.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.15.0/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 14:08:37 +03:00
78e419b790 chore(deps-dev): Upgrade commit hooks to Husky 7 (#4116)
* Upgrade to Husky 7

* Husky
2021-10-29 14:06:13 +03:00
8d8769ba4e feat: add triangle arrowhead (#4024)
Co-authored-by: ad1992 <aakansha1216@gmail.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
2021-10-27 19:27:39 +02:00
d89fb3371b fix: rewrite collab element reconciliation to fix z-index issues (#4076) 2021-10-27 15:14:20 +02:00
8410972cff chore: Update translations from Crowdin (#4047)
* New translations en.json (Occitan)

* New translations en.json (Catalan)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Bengali)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Simplified)

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Occitan)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Slovak)

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Traditional)

* New translations en.json (Indonesian)

* New translations en.json (Punjabi)

* New translations en.json (Persian)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Kazakh)

* New translations en.json (Latvian)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Polish)

* New translations en.json (Dutch)

* New translations en.json (Catalan)

* New translations en.json (Bulgarian)

* New translations en.json (Tamil)

* New translations en.json (Bengali)

* New translations en.json (Chinese Simplified)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Arabic)

* New translations en.json (Czech)

* New translations en.json (Korean)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* 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 (Kabyle)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Italian)

* New translations en.json (Dutch)

* New translations en.json (Chinese Traditional)

* New translations en.json (Norwegian Bokmal)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* New translations en.json (Ukrainian)

* Auto commit: Calculate translation coverage

* New translations en.json (Slovak)

* Auto commit: Calculate translation coverage

* New translations en.json (German)

* Auto commit: Calculate translation coverage

* New translations en.json (German)

* New translations en.json (Occitan)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Slovak)

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Traditional)

* New translations en.json (Indonesian)

* New translations en.json (Punjabi)

* New translations en.json (Persian)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Kazakh)

* New translations en.json (Latvian)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Polish)

* New translations en.json (Dutch)

* New translations en.json (Catalan)

* New translations en.json (Bulgarian)

* New translations en.json (Tamil)

* New translations en.json (Bengali)

* New translations en.json (Chinese Simplified)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Arabic)

* New translations en.json (Czech)

* New translations en.json (Korean)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* 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 (Kabyle)

* Auto commit: Calculate translation coverage

* New translations en.json (Occitan)

* Auto commit: Calculate translation coverage

* New translations en.json (Occitan)

* New translations en.json (Norwegian Bokmal)

* Auto commit: Calculate translation coverage

* New translations en.json (Occitan)

* Auto commit: Calculate translation coverage

* New translations en.json (Indonesian)

* Auto commit: Calculate translation coverage

* New translations en.json (Indonesian)

* New translations en.json (Kazakh)

* Auto commit: Calculate translation coverage

* New translations en.json (Japanese)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Traditional)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Traditional)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* New translations en.json (Dutch)

* Auto commit: Calculate translation coverage

* New translations en.json (Italian)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* New translations en.json (Italian)

* Auto commit: Calculate translation coverage

* New translations en.json (Portuguese)

* Auto commit: Calculate translation coverage

* New translations en.json (Finnish)

* Auto commit: Calculate translation coverage

* New translations en.json (Sinhala)

* Auto commit: Calculate translation coverage

* New translations en.json (German)

* Auto commit: Calculate translation coverage

* New translations en.json (Portuguese, Brazilian)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Tamil)

* Auto commit: Calculate translation coverage

* New translations en.json (Slovak)

* Auto commit: Calculate translation coverage

* New translations en.json (Slovak)

* New translations en.json (Romanian)

* 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 (Chinese Traditional, Hong Kong)

* Auto commit: Calculate translation coverage

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

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

* Auto commit: Calculate translation coverage

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

* Auto commit: Calculate translation coverage

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

* Auto commit: Calculate translation coverage

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

* Auto commit: Calculate translation coverage

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

* Auto commit: Calculate translation coverage

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

* Auto commit: Calculate translation coverage

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

* Auto commit: Calculate translation coverage

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

* Auto commit: Calculate translation coverage

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

* Auto commit: Calculate translation coverage

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

* Auto commit: Calculate translation coverage

* New translations en.json (Sinhala)

* Auto commit: Calculate translation coverage

* New translations en.json (Sinhala)

* Auto commit: Calculate translation coverage

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

* New translations en.json (Chinese Simplified)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Simplified)

* New translations en.json (Kabyle)

* Auto commit: Calculate translation coverage

* New translations en.json (Kabyle)

* Auto commit: Calculate translation coverage
2021-10-27 12:41:00 +05:30
2c8d041987 Migrate the implementation back to browser-fs-access (#4106) 2021-10-27 08:57:10 +02:00
94519c8250 fix: redirect excalidraw.com/about to for-webex.excalidraw.com (#4104) 2021-10-26 17:01:05 +02:00
add8a1b1a7 fix: redirect to webex LP instead of rewrite to fix SW (#4103) 2021-10-26 16:02:30 +02:00
516e7656f3 feat: Add rewrite to webex landing page (#4102)
* feat: Add rewrite to webex landing page

* blacklist webex url

* dont cache webex

* Unregister sw for webex

* fix

* fix

* reload in callback

Co-authored-by: dwelle <luzar.david@gmail.com>
2021-10-26 18:19:41 +05:30
d7cdee37bf feat: switch collab server (#4092) 2021-10-24 11:47:45 +02:00
5c5b8c517f fix: clear image/shape cache of affected elements when adding files (#4089) 2021-10-23 14:17:04 +02:00
7dbd0c5e0a fix: clear LibraryUnit DOM on unmount (#4084) 2021-10-22 22:07:20 +02:00
ba35eb8f8c fix: pasting images on firefox (#4085) 2021-10-22 21:04:04 +02:00
163ad1f4c4 feat: image support (#4011)
Co-authored-by: Emil Atanasov <heitara@gmail.com>
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2021-10-21 22:05:48 +02:00
0f0244224d feat: Use dialog component for clear canvas instead of window confirm (#4075)
* feat: Use dialog component for clear canvas instead of window confirm

* reduce font weight

* fix specs

* update button name and use action

* export clearCanvas from actions
2021-10-21 17:35:28 +05:30
6eecadce60 feat: export isLinearElement and getNonDeletedElements (#4072)
* feat: export isLinearElement and getNonDeletedElements

* fix
2021-10-19 14:40:48 +05:30
bc88cf5002 fix: Don't show save file to disk when UIOptions.canvasActions.export.saveFileToDisk is false (#4073) 2021-10-19 14:39:47 +05:30
571be9c0fe chore(deps-dev): bump @babel/plugin-transform-runtime (#4053)
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.14.5 to 7.15.8.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.15.8/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-18 15:59:56 +05:30
5d925c7d3f build: Allow package.json changes when autoreleasing next (#4068) 2021-10-18 15:58:58 +05:30
45c520341f chore: bump @dwelle/browser-fs-access to 0.21.2 (#4067) 2021-10-18 11:08:12 +02:00
c6ffc06541 feat: support renderTopRightUI in mobile (#4065) 2021-10-17 21:44:46 +05:30
ff29780760 Refactor: convert initializeApp to func component and use JSX transform in the codebase (#4056) 2021-10-14 22:56:51 +05:30
463857ad9a feat: Export THEME from the package (#4055)
* Use Theme type everywhere
* Rename Appearance type to Theme for consistency
* Reorder headers in readme
The host don't need to pass hardcoded strings any more and instead can use the exported constant
2021-10-14 14:15:57 +05:30
be2da9539e chore(deps): bump path-parse in /src/packages/excalidraw (#3912)
Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/jbgutierrez/path-parse/releases)
- [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7)

---
updated-dependencies:
- dependency-name: path-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-13 20:18:29 +05:30
bb7829ef90 chore(deps): bump url-parse from 1.5.1 to 1.5.3 (#3927)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.1 to 1.5.3.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.1...1.5.3)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-13 20:18:09 +05:30
1104f6891e chore(deps): bump semver-regex from 3.1.2 to 3.1.3 (#3988)
Bumps [semver-regex](https://github.com/sindresorhus/semver-regex) from 3.1.2 to 3.1.3.
- [Release notes](https://github.com/sindresorhus/semver-regex/releases)
- [Commits](https://github.com/sindresorhus/semver-regex/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-13 20:17:43 +05:30
a97e172070 chore(deps): bump tmpl from 1.0.4 to 1.0.5 (#3992)
Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/daaku/nodejs-tmpl/releases)
- [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-13 20:17:24 +05:30
372 changed files with 52080 additions and 15400 deletions

43
.codesandbox/tasks.json Normal file
View File

@ -0,0 +1,43 @@
{
// 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
},
"fix": {
"name": "Fix",
"command": "yarn fix",
"runAtStart": false
},
"prettier": {
"name": "Prettify",
"command": "yarn prettier",
"runAtStart": false
},
"start": {
"name": "Start Excalidraw",
"command": "yarn start",
"runAtStart": true
},
"test": {
"name": "Run Tests",
"command": "yarn test",
"runAtStart": false
},
"install-deps": {
"name": "Install Dependencies",
"command": "yarn install",
"restartOn": { "files": ["yarn.lock"] }
}
}
}

5
.env
View File

@ -1,5 +0,0 @@
REACT_APP_BACKEND_V1_GET_URL=https://json.excalidraw.com/api/v1/
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/
REACT_APP_SOCKET_SERVER_URL=https://portal.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"}'

22
.env.development Normal file
View File

@ -0,0 +1,22 @@
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/
REACT_APP_LIBRARY_URL=https://libraries.excalidraw.com
REACT_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
# set this only if using the collaboration workflow we use on excalidraw.com
REACT_APP_PORTAL_URL=
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"}'
# 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=

View File

@ -1 +1,17 @@
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/
REACT_APP_LIBRARY_URL=https://libraries.excalidraw.com
REACT_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=
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"}'
# production-only vars
REACT_APP_GOOGLE_ANALYTICS_ID=UA-387204-13
REACT_APP_PLUS_APP=https://app.excalidraw.com

View File

@ -5,3 +5,4 @@ package-lock.json
firebase/
dist/
public/workbox
src/packages/excalidraw/types

View File

@ -1,6 +1,7 @@
{
"extends": ["@excalidraw/eslint-config", "react-app"],
"rules": {
"import/no-anonymous-default-export": "off"
"import/no-anonymous-default-export": "off",
"no-restricted-globals": "off"
}
}

View File

@ -1,34 +0,0 @@
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: sunday
time: "01:00"
reviewers:
- lipis
assignees:
- lipis
- package-ecosystem: npm
directory: /src/packages/excalidraw/
schedule:
interval: weekly
day: sunday
time: "01:00"
reviewers:
- ad1992
assignees:
- ad1992
- package-ecosystem: npm
directory: /src/packages/utils/
schedule:
interval: weekly
day: sunday
time: "01:00"
reviewers:
- ad1992
assignees:
- ad1992

View File

@ -1,4 +1,4 @@
name: Auto release @excalidraw/excalidraw-next
name: Auto release excalidraw next
on:
push:
branches:
@ -23,4 +23,5 @@ jobs:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Auto release
run: |
yarn add @actions/core
yarn autorelease

View File

@ -0,0 +1,55 @@
name: Auto release excalidraw preview
on:
issue_comment:
types: [created, edited]
jobs:
Auto-release-excalidraw-preview:
name: Auto release preview
if: github.event.comment.body == '@excalibot trigger release' && github.event.issue.pull_request
runs-on: ubuntu-latest
steps:
- name: React to release comment
uses: peter-evans/create-or-update-comment@v1
with:
token: ${{ secrets.PUSH_TRANSLATIONS_COVERAGE_PAT }}
comment-id: ${{ github.event.comment.id }}
reactions: "+1"
- name: Get PR SHA
id: sha
uses: actions/github-script@v4
with:
result-encoding: string
script: |
const { owner, repo, number } = context.issue;
const pr = await github.pulls.get({
owner,
repo,
pull_number: number,
});
return pr.data.head.sha
- uses: actions/checkout@v2
with:
ref: ${{ steps.sha.outputs.result }}
fetch-depth: 2
- name: Setup Node.js 14.x
uses: actions/setup-node@v2
with:
node-version: 14.x
- name: Set up publish access
run: |
npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Auto release preview
id: "autorelease"
run: |
yarn add @actions/core
yarn autorelease preview ${{ github.event.issue.number }}
- name: Post comment post release
if: always()
uses: peter-evans/create-or-update-comment@v1
with:
token: ${{ secrets.PUSH_TRANSLATIONS_COVERAGE_PAT }}
issue-number: ${{ github.event.issue.number }}
body: "@${{ github.event.comment.user.login }} ${{ steps.autorelease.outputs.result }}"

View File

@ -1,29 +0,0 @@
name: Build packages
on:
push:
branches:
- master
pull_request:
jobs:
packages:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js 14.x
uses: actions/setup-node@v2
with:
node-version: 14.x
- name: Install dependencies
run: |
yarn --frozen-lockfile
yarn --cwd src/packages/excalidraw
yarn --cwd src/packages/utils
- name: Build @excalidraw/excalidraw
run: |
yarn --cwd src/packages/excalidraw run pack
- name: Build @excalidraw/utils
run: |
yarn --cwd src/packages/utils run pack

View File

@ -10,11 +10,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: docker/build-push-action@v1
- name: Checkout repository
uses: actions/checkout@v3
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: excalidraw/excalidraw
tag_with_ref: true
tag_with_sha: true
- name: Build and push
uses: docker/build-push-action@v3
with:
context: .
push: true
tags: excalidraw/excalidraw:latest

5
.gitignore vendored
View File

@ -19,7 +19,10 @@ logs
node_modules
npm-debug.log*
package-lock.json
static
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

2
.husky/pre-commit Executable file
View File

@ -0,0 +1,2 @@
#!/bin/sh
yarn lint-staged

View File

@ -32,6 +32,10 @@ Last but not least, we're thankful to these companies for offering their service
[![Vercel](./.github/assets/vercel.svg)](https://vercel.com) [![Sentry](./.github/assets/sentry.svg)](https://sentry.io) [![Crowdin](./.github/assets/crowdin.svg)](https://crowdin.com)
## Who's integrating Excalidraw
[Google Cloud](https://googlecloudcheatsheet.withgoogle.com/architecture) • [Meta](https://meta.com/) • [CodeSandbox](https://codesandbox.io/) • [Obsidian Excalidraw](https://github.com/zsviczian/obsidian-excalidraw-plugin) • [Replit](https://replit.com/) • [Slite](https://slite.com/) • [Notion](https://notion.so/) • [HackerRank](https://www.hackerrank.com/) •
## Documentation
### Shortcuts
@ -84,7 +88,7 @@ Try out [`@excalidraw/excalidraw`](https://www.npmjs.com/package/@excalidraw/exc
### Code Sandbox
- Go to https://codesandbox.io/s/github/excalidraw/excalidraw
- Go to https://codesandbox.io/p/github/excalidraw/excalidraw
- You may need to sign in with GitHub and reload the page
- You can start coding instantly, and even send PRs from there!
@ -118,16 +122,47 @@ yarn start
Now you can open [http://localhost:3000](http://localhost:3000) and start coding in your favorite code editor.
#### Collaboration
For collaboration, you will need to set up [collab server](https://github.com/excalidraw/excalidraw-room) in local.
#### Commands
| Command | Description |
| ------------------ | --------------------------------- |
| `yarn` | Install the dependencies |
| `yarn start` | Run the project |
| `yarn fix` | Reformat all files with Prettier |
| `yarn test` | Run tests |
| `yarn test:update` | Update test snapshots |
| `yarn test:code` | Test for formatting with Prettier |
##### Install the dependencies
```
yarn
```
##### Run the project
```
yarn start
```
##### Reformat all files with Prettier
```
yarn fix
```
##### Run tests
```
yarn test
```
##### Update test snapshots
```
yarn test:update
```
##### Test for formatting with Prettier
```
yarn test:code
```
#### Docker Compose

20
dev-docs/.gitignore vendored Normal file
View File

@ -0,0 +1,20 @@
# Dependencies
/node_modules
# Production
/build
# Generated files
.docusaurus
.cache-loader
# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

41
dev-docs/README.md Normal file
View File

@ -0,0 +1,41 @@
# Website
This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
### Installation
```
$ yarn
```
### Local Development
```
$ yarn start
```
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
### Build
```
$ yarn build
```
This command generates static content into the `build` directory and can be served using any static contents hosting service.
### Deployment
Using SSH:
```
$ USE_SSH=true yarn deploy
```
Not using SSH:
```
$ GIT_USER=<Your GitHub username> yarn deploy
```
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.

3
dev-docs/babel.config.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
presets: [require.resolve("@docusaurus/core/lib/babel/preset")],
};

View File

@ -0,0 +1,6 @@
---
sidebar_position: 1
title: Overview
---
In development. For now, refer to [excalidraw Readme](https://github.com/excalidraw/excalidraw/blob/master/README.md).

View File

@ -0,0 +1,8 @@
---
sidebar_position: 1
title: Introduction
---
Want to integrate Excalidraw into your app? Head over to the [package docs](/docs/package/overview).
If you're looking into the Excalidraw codebase itself, start [here](/docs/codebase/overview).

View File

@ -0,0 +1,6 @@
---
sidebar_position: 1
title: Overview
---
In development. For now, refer to [excalidraw package readme](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md).

View File

@ -0,0 +1,121 @@
// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
const lightCodeTheme = require("prism-react-renderer/themes/github");
const darkCodeTheme = require("prism-react-renderer/themes/dracula");
/** @type {import('@docusaurus/types').Config} */
const config = {
title: "Excalidraw developer docs",
tagline:
"For Excalidraw contributors or those integrating the Excalidraw editor",
url: "https://docs.excalidraw.com.com",
baseUrl: "/",
onBrokenLinks: "throw",
onBrokenMarkdownLinks: "warn",
favicon: "img/favicon.ico",
organizationName: "Excalidraw", // Usually your GitHub org/user name.
projectName: "excalidraw", // Usually your repo name.
// Even if you don't use internalization, you can use this field to set useful
// metadata like html lang. For example, if your site is Chinese, you may want
// to replace "en" with "zh-Hans".
i18n: {
defaultLocale: "en",
locales: ["en"],
},
presets: [
[
"classic",
/** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
sidebarPath: require.resolve("./sidebars.js"),
// Please change this to your repo.
editUrl: "https://github.com/excalidraw/docs/tree/master/",
},
theme: {
customCss: require.resolve("./src/css/custom.css"),
},
}),
],
],
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
navbar: {
title: "Excalidraw Docs",
logo: {
alt: "Excalidraw Logo",
src: "img/logo.svg",
},
items: [
{
type: "doc",
docId: "get-started",
position: "left",
label: "Get started",
},
{
to: "https://blog.excalidraw.com",
label: "Blog",
position: "left",
},
{
to: "https://github.com/excalidraw/excalidraw",
label: "GitHub",
position: "right",
},
],
},
footer: {
style: "dark",
links: [
{
title: "Docs",
items: [
{
label: "Get Started",
to: "/docs/get-started",
},
],
},
{
title: "Community",
items: [
{
label: "Discord",
href: "https://discord.gg/UexuTaE",
},
{
label: "Twitter",
href: "https://twitter.com/excalidraw",
},
],
},
{
title: "More",
items: [
{
label: "Blog",
to: "https://blog.excalidraw.com",
},
{
label: "GitHub",
to: "https://github.com/excalidraw/excalidraw",
},
],
},
],
copyright: `Made with ❤️ Built with Docusaurus`,
},
prism: {
theme: lightCodeTheme,
darkTheme: darkCodeTheme,
},
}),
};
module.exports = config;

46
dev-docs/package.json Normal file
View File

@ -0,0 +1,46 @@
{
"name": "docs",
"version": "0.0.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start --port 3003",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "2.0.0-rc.1",
"@docusaurus/preset-classic": "2.0.0-rc.1",
"@mdx-js/react": "^1.6.22",
"clsx": "^1.2.1",
"prism-react-renderer": "^1.3.5",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "2.0.0-rc.1",
"@tsconfig/docusaurus": "^1.0.5",
"typescript": "^4.7.4"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"engines": {
"node": ">=16.14"
}
}

31
dev-docs/sidebars.js Normal file
View File

@ -0,0 +1,31 @@
/**
* Creating a sidebar enables you to:
- create an ordered group of docs
- render a sidebar for each doc of that group
- provide next/previous navigation
The sidebars can be generated from the filesystem, or explicitly defined here.
Create as many sidebars as you want.
*/
// @ts-check
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
// By default, Docusaurus generates a sidebar from the docs folder structure
tutorialSidebar: [{ type: "autogenerated", dirName: "." }],
// But you can create a sidebar manually
/*
tutorialSidebar: [
{
type: 'category',
label: 'Tutorial',
items: ['hello'],
},
],
*/
};
module.exports = sidebars;

View File

@ -0,0 +1,62 @@
import React from "react";
import clsx from "clsx";
import styles from "./styles.module.css";
const FeatureList = [
{
title: "Learn how Excalidraw works",
Svg: require("@site/static/img/undraw_innovative.svg").default,
description: (
<>Want to contribute to Excalidraw but got lost in the codebase?</>
),
},
{
title: "Integrate Excalidraw",
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
start?
</>
),
},
{
title: "Help us improve",
Svg: require("@site/static/img/undraw_add_files.svg").default,
description: (
<>
Are the docs missing something? Anything you had trouble understanding
or needs an explanation? Come contribute to the docs to make them even
better!
</>
),
},
];
function Feature({ Svg, title, description }) {
return (
<div className={clsx("col col--4")}>
<div className="text--center">
<Svg className={styles.featureSvg} role="img" />
</div>
<div className="text--center padding-horiz--md">
<h3>{title}</h3>
<p>{description}</p>
</div>
</div>
);
}
export default function HomepageFeatures() {
return (
<section className={styles.features}>
<div className="container">
<div className="row">
{FeatureList.map((props, idx) => (
<Feature key={idx} {...props} />
))}
</div>
</div>
</section>
);
}

View File

@ -0,0 +1,70 @@
import React from "react";
import clsx from "clsx";
import styles from "./styles.module.css";
type FeatureItem = {
title: string;
Svg: React.ComponentType<React.ComponentProps<"svg">>;
description: JSX.Element;
};
const FeatureList: FeatureItem[] = [
{
title: "Easy to Use",
Svg: require("@site/static/img/undraw_docusaurus_mountain.svg").default,
description: (
<>
Docusaurus was designed from the ground up to be easily installed and
used to get your website up and running quickly.
</>
),
},
{
title: "Focus on What Matters",
Svg: require("@site/static/img/undraw_docusaurus_tree.svg").default,
description: (
<>
Docusaurus lets you focus on your docs, and we&apos;ll do the chores. Go
ahead and move your docs into the <code>docs</code> directory.
</>
),
},
{
title: "Powered by React",
Svg: require("@site/static/img/undraw_docusaurus_react.svg").default,
description: (
<>
Extend or customize your website layout by reusing React. Docusaurus can
be extended while reusing the same header and footer.
</>
),
},
];
function Feature({ title, Svg, description }: FeatureItem) {
return (
<div className={clsx("col col--4")}>
<div className="text--center">
<Svg className={styles.featureSvg} role="img" />
</div>
<div className="text--center padding-horiz--md">
<h3>{title}</h3>
<p>{description}</p>
</div>
</div>
);
}
export default function HomepageFeatures(): JSX.Element {
return (
<section className={styles.features}>
<div className="container">
<div className="row">
{FeatureList.map((props, idx) => (
<Feature key={idx} {...props} />
))}
</div>
</div>
</section>
);
}

View File

@ -0,0 +1,11 @@
.features {
display: flex;
align-items: center;
padding: 2rem 0;
width: 100%;
}
.featureSvg {
height: 200px;
width: 200px;
}

View File

@ -0,0 +1,43 @@
/**
* Any CSS included here will be global. The classic template
* bundles Infima by default. Infima is a CSS framework designed to
* work well for content-centric websites.
*/
/* You can override the default Infima variables here. */
:root {
--ifm-color-primary: #6965db;
--ifm-color-primary-dark: #5b57d1;
--ifm-color-primary-darker: #5b57d1;
--ifm-color-primary-darkest: #4a47b1;
--ifm-color-primary-light: #5b57d1;
--ifm-color-primary-lighter: #5b57d1;
--ifm-color-primary-lightest: #5b57d1;
--ifm-code-font-size: 95%;
}
/* For readability concerns, you should choose a lighter palette in dark mode. */
[data-theme="dark"] {
--ifm-color-primary: #5650f0;
--ifm-color-primary-dark: #4b46d8;
--ifm-color-primary-darker: #4b46d8;
--ifm-color-primary-darkest: #3e39be;
--ifm-color-primary-light: #3f3d64;
--ifm-color-primary-lighter: #3f3d64;
--ifm-color-primary-lightest: #3f3d64;
}
.docusaurus-highlight-code-line {
background-color: rgba(0, 0, 0, 0.1);
display: block;
margin: 0 calc(-1 * var(--ifm-pre-padding));
padding: 0 var(--ifm-pre-padding);
}
[data-theme="dark"] .docusaurus-highlight-code-line {
background-color: rgba(0, 0, 0, 0.3);
}
[data-theme="dark"] .navbar__logo {
filter: invert(93%) hue-rotate(180deg);
}

View File

@ -0,0 +1,42 @@
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";
function HomepageHeader() {
const { siteConfig } = useDocusaurusContext();
return (
<header className={clsx("hero hero--primary", styles.heroBanner)}>
<div className="container">
<h1 className="hero__title">{siteConfig.title}</h1>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to="/docs/get-started"
>
Get started
</Link>
</div>
</div>
</header>
);
}
export default function Home() {
const { siteConfig } = useDocusaurusContext();
return (
<Layout
title={`Hello from ${siteConfig.title}`}
description="Description will go into a meta tag in <head />"
>
<HomepageHeader />
<main>
<HomepageFeatures />
</main>
</Layout>
);
}

View File

@ -0,0 +1,27 @@
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
*/
.heroBanner {
padding: 4rem 0;
text-align: center;
position: relative;
overflow: hidden;
}
[data-theme="dark"] .heroBanner {
color: #fff;
}
@media screen and (max-width: 996px) {
.heroBanner {
padding: 2rem;
}
}
.buttons {
display: flex;
align-items: center;
justify-content: center;
}

View File

@ -0,0 +1,42 @@
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";
function HomepageHeader() {
const { siteConfig } = useDocusaurusContext();
return (
<header className={clsx("hero hero--primary", styles.heroBanner)}>
<div className="container">
<h1 className="hero__title">{siteConfig.title}</h1>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to="/docs/get-started"
>
Get started
</Link>
</div>
</div>
</header>
);
}
export default function Home() {
const { siteConfig } = useDocusaurusContext();
return (
<Layout
title={`Hello from ${siteConfig.title}`}
description="Description will go into a meta tag in <head />"
>
<HomepageHeader />
<main>
<HomepageFeatures />
</main>
</Layout>
);
}

View File

@ -0,0 +1,7 @@
---
title: Markdown page example
---
# Markdown page example
You don't need React to write simple standalone pages.

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,4 @@
<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>

After

Width:  |  Height:  |  Size: 3.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.4 KiB

7
dev-docs/tsconfig.json Normal file
View File

@ -0,0 +1,7 @@
{
// This file is not used in compilation. It is here just for a nice editor experience.
"extends": "@tsconfig/docusaurus/tsconfig.json",
"compilerOptions": {
"baseUrl": "."
}
}

7489
dev-docs/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,11 @@
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{migrations} {
match /{scenes}/{scene} {
allow get, write: if true;
// redundant, but let's be explicit'
allow list: if false;
}
match /{files}/rooms/{room}/{file} {
allow get, write: if true;
}
match /{files}/shareLinks/{shareLink}/{file} {
allow get, write: if true;
}
}
}

View File

@ -19,65 +19,71 @@
]
},
"dependencies": {
"@dwelle/browser-fs-access": "0.21.1",
"@sentry/browser": "6.2.5",
"@sentry/integrations": "6.2.5",
"@testing-library/jest-dom": "5.11.10",
"@testing-library/react": "11.2.6",
"@tldraw/vec": "0.0.106",
"@types/jest": "26.0.22",
"@types/react": "17.0.3",
"@types/react-dom": "17.0.3",
"@testing-library/jest-dom": "5.16.2",
"@testing-library/react": "12.1.5",
"@tldraw/vec": "1.7.1",
"@types/jest": "27.4.0",
"@types/pica": "5.1.3",
"@types/react": "18.0.15",
"@types/react-dom": "18.0.6",
"@types/socket.io-client": "1.4.36",
"browser-fs-access": "0.29.1",
"clsx": "1.1.1",
"fake-indexeddb": "3.1.7",
"firebase": "8.3.3",
"i18next-browser-languagedetector": "6.1.0",
"i18next-browser-languagedetector": "6.1.4",
"idb-keyval": "6.0.3",
"image-blob-reduce": "3.0.1",
"jotai": "1.6.4",
"lodash.throttle": "4.1.1",
"nanoid": "3.1.22",
"open-color": "1.8.0",
"nanoid": "3.3.3",
"open-color": "1.9.1",
"pako": "1.0.11",
"perfect-freehand": "1.0.15",
"perfect-freehand": "1.0.16",
"pica": "7.1.1",
"png-chunk-text": "1.0.0",
"png-chunks-encode": "1.0.0",
"png-chunks-extract": "1.0.0",
"points-on-curve": "0.2.0",
"pwacompat": "2.0.17",
"react": "17.0.2",
"react-dom": "17.0.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-scripts": "4.0.3",
"roughjs": "4.4.1",
"sass": "1.32.10",
"roughjs": "4.5.2",
"sass": "1.51.0",
"socket.io-client": "2.3.1",
"typescript": "4.2.4"
"typescript": "4.5.5"
},
"devDependencies": {
"@excalidraw/eslint-config": "1.0.0",
"@excalidraw/prettier-config": "1.0.2",
"@types/lodash.throttle": "4.1.6",
"@types/pako": "1.0.1",
"@types/resize-observer-browser": "0.1.5",
"eslint-config-prettier": "8.3.0",
"@types/chai": "4.3.0",
"@types/lodash.throttle": "4.1.7",
"@types/pako": "1.0.3",
"@types/resize-observer-browser": "0.1.7",
"chai": "4.3.6",
"dotenv": "16.0.1",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-prettier": "3.3.1",
"firebase-tools": "9.9.0",
"husky": "4.3.8",
"jest-canvas-mock": "2.3.1",
"lint-staged": "10.5.4",
"husky": "7.0.4",
"jest-canvas-mock": "2.4.0",
"lint-staged": "12.3.7",
"pepjs": "0.5.3",
"prettier": "2.2.1",
"rewire": "5.0.0"
"prettier": "2.6.2",
"rewire": "6.0.0"
},
"resolutions": {
"@typescript-eslint/typescript-estree": "5.10.2"
},
"engines": {
"node": ">=14.0.0"
},
"homepage": ".",
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"jest": {
"transformIgnorePatterns": [
"node_modules/(?!(roughjs|points-on-curve|path-data-parser|points-on-path|@dwelle/browser-fs-access)/)"
"node_modules/(?!(roughjs|points-on-curve|path-data-parser|points-on-path|browser-fs-access)/)"
],
"resetMocks": false
},
@ -89,13 +95,15 @@
"build:app:docker": "REACT_APP_DISABLE_SENTRY=true react-scripts build",
"build:app": "REACT_APP_GIT_SHA=$VERCEL_GIT_COMMIT_SHA react-scripts build",
"build:version": "node ./scripts/build-version.js",
"build": "yarn build:app && yarn build:version",
"build:prebuild": "node ./scripts/prebuild.js",
"build": "yarn build:prebuild && yarn build:app && yarn build:version",
"eject": "react-scripts eject",
"fix:code": "yarn test:code --fix",
"fix:other": "yarn prettier --write",
"fix": "yarn fix:other && yarn fix:code",
"locales-coverage": "node scripts/build-locales-coverage.js",
"locales-coverage:description": "node scripts/locales-coverage-description.js",
"prepare": "husky install",
"prettier": "prettier \"**/*.{css,scss,json,md,html,yml}\" --ignore-path=.eslintignore",
"start": "react-scripts start",
"test:all": "yarn test:typecheck && yarn test:code && yarn test:other && yarn test:app --watchAll=false",
@ -106,6 +114,8 @@
"test:typecheck": "tsc",
"test:update": "yarn test:app --updateSnapshot --watchAll=false",
"test": "yarn test:app",
"autorelease": "node scripts/autorelease.js"
"autorelease": "node scripts/autorelease.js",
"prerelease": "node scripts/prerelease.js",
"release": "node scripts/release.js"
}
}

View File

@ -13,18 +13,6 @@
<meta name="theme-color" content="#000" />
<!-- Declarative Link Capturing (https://web.dev/declarative-link-capturing/) -->
<meta
http-equiv="origin-trial"
content="Ak3VyzTheARtX2CnxBZ3ZKxImB0mNyvDakmMxeAChgxrWFMZ3IGN64VP+uj36VxM5OegsbLmrP258b1xvqp7+Q8AAABbeyJvcmlnaW4iOiJodHRwczovL2V4Y2FsaWRyYXcuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJBcHBMaW5rQ2FwdHVyaW5nIiwiZXhwaXJ5IjoxNjM0MDgzMTk5fQ=="
/>
<!-- File Handling (https://web.dev/file-handling/) -->
<meta
http-equiv="origin-trial"
content="AkMQsAnFmKfRfPKQHNCv2WmZREqgwkqhyt2M7aOwQiCStB+hPYnGnv+mNbkPDAsGXrwsj/waFi76wPzTDUaEeQ0AAABUeyJvcmlnaW4iOiJodHRwczovL2V4Y2FsaWRyYXcuY29tOjQ0MyIsImZlYXR1cmUiOiJGaWxlSGFuZGxpbmciLCJleHBpcnkiOjE2MzQwODMxOTl9"
/>
<!-- General tags -->
<meta
name="description"
@ -64,6 +52,25 @@
content="Excalidraw is a whiteboard tool that lets you easily sketch diagrams that have a hand-drawn feel to them."
/>
<script>
// Redirect Excalidraw+ users which have auto-redirect enabled.
//
// Redirect only the bare root path, so link/room/library urls are not
// redirected.
//
// Putting into index.html for best performance (can't redirect on server
// due to location.hash checks).
if (
window.location.pathname === "/" &&
!window.location.hash &&
!window.location.search &&
// if its present redirect
document.cookie.includes("excplus-autoredirect=true")
) {
window.location.href = "https://app.excalidraw.com";
}
</script>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<!-- Excalidraw version -->
@ -84,12 +91,6 @@
crossorigin="anonymous"
/>
<link
href="%REACT_APP_SOCKET_SERVER_URL%/socket.io"
rel="preconnect"
crossorigin="anonymous"
/>
<link
rel="manifest"
href="manifest.json"
@ -97,6 +98,22 @@
/>
<link rel="stylesheet" href="fonts.css" type="text/css" />
<% if (process.env.REACT_APP_DEV_DISABLE_LIVE_RELOAD === "true") { %>
<script>
{
const _WebSocket = window.WebSocket;
window.WebSocket = function (url) {
if (/ws:\/\/localhost:.+?\/sockjs-node/.test(url)) {
console.info(
"[!!!] Live reload is disabled via process.env.REACT_APP_DEV_DISABLE_LIVE_RELOAD [!!!]",
);
} else {
return new _WebSocket(url);
}
};
}
</script>
<% } %>
<script>
window.EXCALIDRAW_ASSET_PATH = "/";
// setting this so that libraries installation reuses this window tab.
@ -142,26 +159,6 @@
user-select: none;
}
.LoadingMessage {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 999;
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
}
.LoadingMessage span {
background-color: var(--button-gray-1);
border-radius: 5px;
padding: 0.8em 1.2em;
color: var(--popup-text-color);
font-size: 1.3em;
}
#root {
height: 100%;
-webkit-touch-callout: none;
@ -170,8 +167,10 @@
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
@media screen and (min-width: 1200px) {
@media screen and (min-width: 1200px) {
#root {
-webkit-touch-callout: default;
-webkit-user-select: auto;
-khtml-user-select: auto;
@ -188,10 +187,6 @@
<header>
<h1 class="visually-hidden">Excalidraw</h1>
</header>
<div id="root">
<div class="LoadingMessage">
<span>Loading scene...</span>
</div>
</div>
<div id="root"></div>
</body>
</html>

View File

@ -26,7 +26,6 @@
}
}
],
"capture_links": "new-client",
"share_target": {
"action": "/web-share-target",
"method": "POST",

View File

@ -17,11 +17,23 @@
* See https://goo.gl/2aRDsh
*/
importScripts("/workbox/workbox-sw.js");
// in dev, `process` is undefined because this file is not compiled until build
const IS_DEVELOPMENT =
typeof process === "undefined" || process.env.NODE_ENV !== "production";
workbox.setConfig({
modulePathPrefix: "/workbox/",
});
if (IS_DEVELOPMENT) {
importScripts(
"https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js",
);
workbox.setConfig({
debug: true,
});
} else {
importScripts("/workbox/workbox-sw.js");
workbox.setConfig({
modulePathPrefix: "/workbox/",
});
}
self.addEventListener("message", (event) => {
if (event.data && event.data.type === "SKIP_WAITING") {
@ -30,14 +42,17 @@ self.addEventListener("message", (event) => {
});
workbox.core.clientsClaim();
workbox.precaching.precacheAndRoute(self.__WB_MANIFEST);
workbox.routing.registerNavigationRoute(
workbox.precaching.getCacheKeyForURL("./index.html"),
{
blacklist: [/^\/_/, /\/[^/?]+\.[^/]+$/],
},
);
if (!IS_DEVELOPMENT) {
workbox.precaching.precacheAndRoute(self.__WB_MANIFEST);
workbox.routing.registerNavigationRoute(
workbox.precaching.getCacheKeyForURL("./index.html"),
{
blacklist: [/^\/_/, /\/[^/?]+\.[^/]+$/],
},
);
}
// Cache relevant font files
workbox.routing.registerRoute(

View File

@ -1,51 +1,72 @@
const fs = require("fs");
const { exec, execSync } = require("child_process");
const core = require("@actions/core");
const excalidrawDir = `${__dirname}/../src/packages/excalidraw`;
const excalidrawPackage = `${excalidrawDir}/package.json`;
const pkg = require(excalidrawPackage);
const isPreview = process.argv.slice(2)[0] === "preview";
const getShortCommitHash = () => {
return execSync("git rev-parse --short HEAD").toString().trim();
};
const publish = () => {
const tag = isPreview ? "preview" : "next";
try {
execSync(`yarn --frozen-lockfile`);
execSync(`yarn --frozen-lockfile`, { cwd: excalidrawDir });
execSync(`yarn run build:umd`, { cwd: excalidrawDir });
execSync(`yarn --cwd ${excalidrawDir} publish`);
} catch (e) {
console.error(e);
execSync(`yarn --cwd ${excalidrawDir} publish --tag ${tag}`);
console.info(`Published ${pkg.name}@${tag}🎉`);
core.setOutput(
"result",
`**Preview version has been shipped** :rocket:
You can use [@excalidraw/excalidraw@${pkg.version}](https://www.npmjs.com/package/@excalidraw/excalidraw/v/${pkg.version}) for testing!`,
);
} catch (error) {
core.setOutput("result", "package couldn't be published :warning:!");
console.error(error);
process.exit(1);
}
};
// get files changed between prev and head commit
exec(`git diff --name-only HEAD^ HEAD`, async (error, stdout, stderr) => {
if (error || stderr) {
console.error(error);
core.setOutput("result", ":warning: Package couldn't be published!");
process.exit(1);
}
const changedFiles = stdout.trim().split("\n");
const filesToIgnoreRegex = /src\/excalidraw-app|packages\/utils/;
const excalidrawPackageFiles = changedFiles.filter((file) => {
return file.indexOf("src") >= 0 && !filesToIgnoreRegex.test(file);
return (
(file.indexOf("src") >= 0 || file.indexOf("package.json")) >= 0 &&
!filesToIgnoreRegex.test(file)
);
});
if (!excalidrawPackageFiles.length) {
console.info("Skipping release as no valid diff found");
core.setOutput("result", "Skipping release as no valid diff found");
process.exit(0);
}
// update package.json
pkg.version = `${pkg.version}-${getShortCommitHash()}`;
pkg.name = "@excalidraw/excalidraw-next";
fs.writeFileSync(excalidrawPackage, JSON.stringify(pkg, null, 2), "utf8");
let version = `${pkg.version}-${getShortCommitHash()}`;
// update readme
const data = fs.readFileSync(`${excalidrawDir}/README_NEXT.md`, "utf8");
fs.writeFileSync(`${excalidrawDir}/README.md`, data, "utf8");
if (isPreview) {
// use pullNumber-commithash as the version for preview
const pullRequestNumber = process.argv.slice(3)[0];
version = `${pkg.version}-${pullRequestNumber}-${getShortCommitHash()}`;
}
pkg.version = version;
fs.writeFileSync(excalidrawPackage, JSON.stringify(pkg, null, 2), "utf8");
console.info("Publish in progress...");
publish();
});

View File

@ -1,11 +1,16 @@
const { readdirSync, writeFileSync } = require("fs");
const files = readdirSync(`${__dirname}/../src/locales`);
const flatten = (object) =>
Object.keys(object).reduce(
(initial, current) => ({ ...initial, ...object[current] }),
{},
);
const flatten = (object = {}, result = {}, extraKey = "") => {
for (const key in object) {
if (typeof object[key] !== "object") {
result[extraKey + key] = object[key];
} else {
flatten(object[key], result, `${extraKey}${key}.`);
}
}
return result;
};
const locales = files.filter(
(file) => file !== "README.md" && file !== "percentages.json",
@ -19,10 +24,8 @@ for (let index = 0; index < locales.length; index++) {
const allKeys = Object.keys(data);
const translatedKeys = allKeys.filter((item) => data[item] !== "");
const percentage = (100 * translatedKeys.length) / allKeys.length;
percentages[currentLocale.replace(".json", "")] = parseInt(percentage);
const percentage = Math.floor((100 * translatedKeys.length) / allKeys.length);
percentages[currentLocale.replace(".json", "")] = percentage;
}
writeFileSync(

21
scripts/buildDocs.js Normal file
View File

@ -0,0 +1,21 @@
const { exec } = require("child_process");
// get files changed between prev and head commit
exec(`git diff --name-only HEAD^ HEAD`, async (error, stdout, stderr) => {
if (error || stderr) {
console.error(error);
process.exit(1);
}
const changedFiles = stdout.trim().split("\n");
const docFiles = changedFiles.filter((file) => {
return file.indexOf("docs") >= 0;
});
if (!docFiles.length) {
console.info("Skipping building docs as no valid diff found");
process.exit(0);
}
// Exit code 1 to build the docs in ignoredBuildStep
process.exit(1);
});

View File

@ -5,10 +5,13 @@ const THRESSHOLD = 85;
const crowdinMap = {
"ar-SA": "en-ar",
"bg-BG": "en-bg",
"bn-BD": "en-bn",
"ca-ES": "en-ca",
"da-DK": "en-da",
"de-DE": "en-de",
"el-GR": "en-el",
"es-ES": "en-es",
"eu-ES": "en-eu",
"fa-IR": "en-fa",
"fi-FI": "en-fi",
"fr-FR": "en-fr",
@ -31,21 +34,31 @@ const crowdinMap = {
"pt-PT": "en-pt",
"ro-RO": "en-ro",
"ru-RU": "en-ru",
"si-LK": "en-silk",
"sk-SK": "en-sk",
"sl-SI": "en-sl",
"sv-SE": "en-sv",
"ta-IN": "en-ta",
"tr-TR": "en-tr",
"uk-UA": "en-uk",
"zh-CN": "en-zhcn",
"zh-HK": "en-zhhk",
"zh-TW": "en-zhtw",
"lt-LT": "en-lt",
"lv-LV": "en-lv",
"cs-CZ": "en-cs",
"kk-KZ": "en-kk",
"vi-vn": "en-vi",
"mr-in": "en-mr",
};
const flags = {
"ar-SA": "🇸🇦",
"bg-BG": "🇧🇬",
"bn-BD": "🇧🇩",
"ca-ES": "🏳",
"cs-CZ": "🇨🇿",
"da-DK": "🇩🇰",
"de-DE": "🇩🇪",
"el-GR": "🇬🇷",
"es-ES": "🇪🇸",
@ -59,7 +72,10 @@ const flags = {
"it-IT": "🇮🇹",
"ja-JP": "🇯🇵",
"kab-KAB": "🏳",
"kk-KZ": "🇰🇿",
"ko-KR": "🇰🇷",
"lt-LT": "🇱🇹",
"lv-LV": "🇱🇻",
"my-MM": "🇲🇲",
"nb-NO": "🇳🇴",
"nl-NL": "🇳🇱",
@ -71,24 +87,32 @@ const flags = {
"pt-PT": "🇵🇹",
"ro-RO": "🇷🇴",
"ru-RU": "🇷🇺",
"si-LK": "🇱🇰",
"sk-SK": "🇸🇰",
"sl-SI": "🇸🇮",
"sv-SE": "🇸🇪",
"ta-IN": "🇮🇳",
"tr-TR": "🇹🇷",
"uk-UA": "🇺🇦",
"zh-CN": "🇨🇳",
"zh-HK": "🇭🇰",
"zh-TW": "🇹🇼",
"lv-LV": "🇱🇻",
"cs-CZ": "🇨🇿",
"kk-KZ": "🇰🇿",
"eu-ES": "🇪🇦",
"vi-VN": "🇻🇳",
"mr-IN": "🇮🇳",
};
const languages = {
"ar-SA": "العربية",
"bg-BG": "Български",
"bn-BD": "Bengali",
"ca-ES": "Català",
"cs-CZ": "Česky",
"da-DK": "Dansk",
"de-DE": "Deutsch",
"el-GR": "Ελληνικά",
"es-ES": "Español",
"eu-ES": "Euskara",
"fa-IR": "فارسی",
"fi-FI": "Suomi",
"fr-FR": "Français",
@ -99,7 +123,10 @@ const languages = {
"it-IT": "Italiano",
"ja-JP": "日本語",
"kab-KAB": "Taqbaylit",
"kk-KZ": "Қазақ тілі",
"ko-KR": "한국어",
"lt-LT": "Lietuvių",
"lv-LV": "Latviešu",
"my-MM": "Burmese",
"nb-NO": "Norsk bokmål",
"nl-NL": "Nederlands",
@ -111,15 +138,18 @@ const languages = {
"pt-PT": "Português",
"ro-RO": "Română",
"ru-RU": "Русский",
"si-LK": "සිංහල",
"sk-SK": "Slovenčina",
"sl-SI": "Slovenščina",
"sv-SE": "Svenska",
"ta-IN": "Tamil",
"tr-TR": "Türkçe",
"uk-UA": "Українська",
"zh-CN": "简体中文",
"zh-HK": "繁體中文 (香港)",
"zh-TW": "繁體中文",
"lv-LV": "Latviešu",
"cs-CZ": "Česky",
"kk-KZ": "Қазақ тілі",
"vi-VN": "Tiếng Việt",
"mr-IN": "मराठी",
};
const percentages = fs.readFileSync(

21
scripts/prebuild.js Normal file
View File

@ -0,0 +1,21 @@
const fs = require("fs");
const path = require("path");
// for development purposes we want to have the service-worker.js file
// accessible from the public folder. On build though, we need to compile it
// and CRA expects that file to be in src/ folder.
const moveServiceWorkerScript = () => {
const oldPath = path.resolve(__dirname, "../public/service-worker.js");
const newPath = path.resolve(__dirname, "../src/service-worker.js");
fs.rename(oldPath, newPath, (error) => {
if (error) {
throw error;
}
console.info("public/service-worker.js moved to src/");
});
};
// -----------------------------------------------------------------------------
moveServiceWorkerScript();

37
scripts/prerelease.js Normal file
View File

@ -0,0 +1,37 @@
const fs = require("fs");
const util = require("util");
const exec = util.promisify(require("child_process").exec);
const updateChangelog = require("./updateChangelog");
const excalidrawDir = `${__dirname}/../src/packages/excalidraw`;
const excalidrawPackage = `${excalidrawDir}/package.json`;
const updatePackageVersion = (nextVersion) => {
const pkg = require(excalidrawPackage);
pkg.version = nextVersion;
const content = `${JSON.stringify(pkg, null, 2)}\n`;
fs.writeFileSync(excalidrawPackage, content, "utf-8");
};
const prerelease = async (nextVersion) => {
try {
await updateChangelog(nextVersion);
updatePackageVersion(nextVersion);
await exec(`git add -u`);
await exec(
`git commit -m "docs: release @excalidraw/excalidraw@${nextVersion} 🎉"`,
);
console.info("Done!");
} catch (error) {
console.error(error);
process.exit(1);
}
};
const nextVersion = process.argv.slice(2)[0];
if (!nextVersion) {
console.error("Pass the next version to release!");
process.exit(1);
}
prerelease(nextVersion);

View File

@ -1,39 +1,44 @@
const fs = require("fs");
const util = require("util");
const exec = util.promisify(require("child_process").exec);
const updateReadme = require("./updateReadme");
const updateChangelog = require("./updateChangelog");
const { execSync } = require("child_process");
const excalidrawDir = `${__dirname}/../src/packages/excalidraw`;
const excalidrawPackage = `${excalidrawDir}/package.json`;
const pkg = require(excalidrawPackage);
const updatePackageVersion = (nextVersion) => {
const pkg = require(excalidrawPackage);
pkg.version = nextVersion;
const content = `${JSON.stringify(pkg, null, 2)}\n`;
fs.writeFileSync(excalidrawPackage, content, "utf-8");
const originalReadMe = fs.readFileSync(`${excalidrawDir}/README.md`, "utf8");
const updateReadme = () => {
const excalidrawIndex = originalReadMe.indexOf("### Excalidraw");
// remove note for stable readme
const data = originalReadMe.slice(excalidrawIndex);
// update readme
fs.writeFileSync(`${excalidrawDir}/README.md`, data, "utf8");
};
const release = async (nextVersion) => {
const publish = () => {
try {
updateReadme();
await updateChangelog(nextVersion);
updatePackageVersion(nextVersion);
await exec(`git add -u`);
await exec(
`git commit -m "docs: release @excalidraw/excalidraw@${nextVersion} 🎉"`,
);
/* eslint-disable no-console */
console.log("Done!");
} catch (e) {
console.error(e);
execSync(`yarn --frozen-lockfile`);
execSync(`yarn --frozen-lockfile`, { cwd: excalidrawDir });
execSync(`yarn run build:umd`, { cwd: excalidrawDir });
execSync(`yarn --cwd ${excalidrawDir} publish`);
} catch (error) {
console.error(error);
process.exit(1);
}
};
const nextVersion = process.argv.slice(2)[0];
if (!nextVersion) {
console.error("Pass the next version to release!");
process.exit(1);
}
release(nextVersion);
const release = () => {
updateReadme();
console.info("Note for stable readme removed");
publish();
console.info(`Published ${pkg.version}!`);
// revert readme after release
fs.writeFileSync(`${excalidrawDir}/README.md`, originalReadMe, "utf8");
console.info("Readme reverted");
};
release();

View File

@ -20,7 +20,7 @@ const headerForType = {
perf: "Performance",
build: "Build",
};
const badCommits = [];
const getCommitHashForLastVersion = async () => {
try {
const commitMessage = `"release @excalidraw/excalidraw@${lastVersion}"`;
@ -28,8 +28,8 @@ const getCommitHashForLastVersion = async () => {
`git log --format=format:"%H" --grep=${commitMessage}`,
);
return stdout;
} catch (e) {
console.error(e);
} catch (error) {
console.error(error);
}
};
@ -53,19 +53,26 @@ const getLibraryCommitsSinceLastRelease = async () => {
const messageWithoutType = commit.slice(indexOfColon + 1).trim();
const messageWithCapitalizeFirst =
messageWithoutType.charAt(0).toUpperCase() + messageWithoutType.slice(1);
const prNumber = commit.match(/\(#([0-9]*)\)/)[1];
const prMatch = commit.match(/\(#([0-9]*)\)/);
if (prMatch) {
const prNumber = prMatch[1];
// return if the changelog already contains the pr number which would happen for package updates
if (existingChangeLog.includes(prNumber)) {
return;
// return if the changelog already contains the pr number which would happen for package updates
if (existingChangeLog.includes(prNumber)) {
return;
}
const prMarkdown = `[#${prNumber}](https://github.com/excalidraw/excalidraw/pull/${prNumber})`;
const messageWithPRLink = messageWithCapitalizeFirst.replace(
/\(#[0-9]*\)/,
prMarkdown,
);
commitList[type].push(messageWithPRLink);
} else {
badCommits.push(commit);
commitList[type].push(messageWithCapitalizeFirst);
}
const prMarkdown = `[#${prNumber}](https://github.com/excalidraw/excalidraw/pull/${prNumber})`;
const messageWithPRLink = messageWithCapitalizeFirst.replace(
/\(#[0-9]*\)/,
prMarkdown,
);
commitList[type].push(messageWithPRLink);
});
console.info("Bad commits:", badCommits);
return commitList;
};

View File

@ -1,27 +0,0 @@
const fs = require("fs");
const updateReadme = () => {
const excalidrawDir = `${__dirname}/../src/packages/excalidraw`;
let data = fs.readFileSync(`${excalidrawDir}/README_NEXT.md`, "utf8");
// remove note for unstable release
data = data.replace(
/<!-- unstable-readme-start-->[\s\S]*?<!-- unstable-readme-end-->/,
"",
);
// replace "excalidraw-next" with "excalidraw"
data = data.replace(/excalidraw-next/g, "excalidraw");
data = data.trim();
const demoIndex = data.indexOf("### Demo");
const excalidrawNextNote =
"#### Note\n\n**If you don't want to wait for the next stable release and try out the unreleased changes you can use [@excalidraw/excalidraw-next](https://www.npmjs.com/package/@excalidraw/excalidraw-next).**\n\n";
// Add excalidraw next note to try out for unreleased changes
data = data.slice(0, demoIndex) + excalidrawNextNote + data.slice(demoIndex);
// update readme
fs.writeFileSync(`${excalidrawDir}/README.md`, data, "utf8");
};
module.exports = updateReadme;

View File

@ -2,22 +2,59 @@ import { register } from "./register";
import { getSelectedElements } from "../scene";
import { getNonDeletedElements } from "../element";
import { deepCopyElement } from "../element/newElement";
import { randomId } from "../random";
import { t } from "../i18n";
export const actionAddToLibrary = register({
name: "addToLibrary",
trackEvent: { category: "element" },
perform: (elements, appState, _, app) => {
const selectedElements = getSelectedElements(
getNonDeletedElements(elements),
appState,
true,
);
if (selectedElements.some((element) => element.type === "image")) {
return {
commitToHistory: false,
appState: {
...appState,
errorMessage: "Support for adding images to the library coming soon!",
},
};
}
app.library.loadLibrary().then((items) => {
app.library.saveLibrary([
...items,
selectedElements.map(deepCopyElement),
]);
});
return false;
return app.library
.getLatestLibrary()
.then((items) => {
return app.library.setLibrary([
{
id: randomId(),
status: "unpublished",
elements: selectedElements.map(deepCopyElement),
created: Date.now(),
},
...items,
]);
})
.then(() => {
return {
commitToHistory: false,
appState: {
...appState,
toast: { message: t("toast.addedToLibrary") },
},
};
})
.catch((error) => {
return {
commitToHistory: false,
appState: {
...appState,
errorMessage: error.message,
},
};
});
},
contextItemLabel: "labels.addToLibrary",
});

View File

@ -1,4 +1,3 @@
import React from "react";
import { alignElements, Alignment } from "../align";
import {
AlignBottomIcon,
@ -9,13 +8,13 @@ import {
CenterVerticallyIcon,
} from "../components/icons";
import { ToolButton } from "../components/ToolButton";
import { getElementMap, getNonDeletedElements } from "../element";
import { getNonDeletedElements } from "../element";
import { ExcalidrawElement } from "../element/types";
import { t } from "../i18n";
import { KEYS } from "../keys";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { AppState } from "../types";
import { getShortcutKey } from "../utils";
import { arrayToMap, getShortcutKey } from "../utils";
import { register } from "./register";
const enableActionGroup = (
@ -35,13 +34,16 @@ const alignSelectedElements = (
const updatedElements = alignElements(selectedElements, alignment);
const updatedElementsMap = getElementMap(updatedElements);
const updatedElementsMap = arrayToMap(updatedElements);
return elements.map((element) => updatedElementsMap[element.id] || element);
return elements.map(
(element) => updatedElementsMap.get(element.id) || element,
);
};
export const actionAlignTop = register({
name: "alignTop",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
appState,
@ -71,6 +73,7 @@ export const actionAlignTop = register({
export const actionAlignBottom = register({
name: "alignBottom",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
appState,
@ -100,6 +103,7 @@ export const actionAlignBottom = register({
export const actionAlignLeft = register({
name: "alignLeft",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
appState,
@ -129,6 +133,8 @@ export const actionAlignLeft = register({
export const actionAlignRight = register({
name: "alignRight",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
appState,
@ -158,6 +164,8 @@ export const actionAlignRight = register({
export const actionAlignVerticallyCentered = register({
name: "alignVerticallyCentered",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
appState,
@ -183,6 +191,7 @@ export const actionAlignVerticallyCentered = register({
export const actionAlignHorizontallyCentered = register({
name: "alignHorizontallyCentered",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
appState,

View File

@ -0,0 +1,136 @@
import { VERTICAL_ALIGN } from "../constants";
import { getNonDeletedElements, isTextElement } from "../element";
import { mutateElement } from "../element/mutateElement";
import {
getBoundTextElement,
measureText,
redrawTextBoundingBox,
} from "../element/textElement";
import {
hasBoundTextElement,
isTextBindableContainer,
} from "../element/typeChecks";
import {
ExcalidrawTextContainer,
ExcalidrawTextElement,
} from "../element/types";
import { getSelectedElements } from "../scene";
import { getFontString } from "../utils";
import { register } from "./register";
export const actionUnbindText = register({
name: "unbindText",
contextItemLabel: "labels.unbindText",
trackEvent: { category: "element" },
contextItemPredicate: (elements, appState) => {
const selectedElements = getSelectedElements(elements, appState);
return selectedElements.some((element) => hasBoundTextElement(element));
},
perform: (elements, appState) => {
const selectedElements = getSelectedElements(
getNonDeletedElements(elements),
appState,
);
selectedElements.forEach((element) => {
const boundTextElement = getBoundTextElement(element);
if (boundTextElement) {
const { width, height, baseline } = measureText(
boundTextElement.originalText,
getFontString(boundTextElement),
);
mutateElement(boundTextElement as ExcalidrawTextElement, {
containerId: null,
width,
height,
baseline,
text: boundTextElement.originalText,
});
mutateElement(element, {
boundElements: element.boundElements?.filter(
(ele) => ele.id !== boundTextElement.id,
),
});
}
});
return {
elements,
appState,
commitToHistory: true,
};
},
});
export const actionBindText = register({
name: "bindText",
contextItemLabel: "labels.bindText",
trackEvent: { category: "element" },
contextItemPredicate: (elements, appState) => {
const selectedElements = getSelectedElements(elements, appState);
if (selectedElements.length === 2) {
const textElement =
isTextElement(selectedElements[0]) ||
isTextElement(selectedElements[1]);
let bindingContainer;
if (isTextBindableContainer(selectedElements[0])) {
bindingContainer = selectedElements[0];
} else if (isTextBindableContainer(selectedElements[1])) {
bindingContainer = selectedElements[1];
}
if (
textElement &&
bindingContainer &&
getBoundTextElement(bindingContainer) === null
) {
return true;
}
}
return false;
},
perform: (elements, appState) => {
const selectedElements = getSelectedElements(
getNonDeletedElements(elements),
appState,
);
let textElement: ExcalidrawTextElement;
let container: ExcalidrawTextContainer;
if (
isTextElement(selectedElements[0]) &&
isTextBindableContainer(selectedElements[1])
) {
textElement = selectedElements[0];
container = selectedElements[1];
} else {
textElement = selectedElements[1] as ExcalidrawTextElement;
container = selectedElements[0] as ExcalidrawTextContainer;
}
mutateElement(textElement, {
containerId: container.id,
verticalAlign: VERTICAL_ALIGN.MIDDLE,
});
mutateElement(container, {
boundElements: (container.boundElements || []).concat({
type: "text",
id: textElement.id,
}),
});
redrawTextBoundingBox(textElement, container);
const updatedElements = elements.slice();
const textElementIndex = updatedElements.findIndex(
(ele) => ele.id === textElement.id,
);
updatedElements.splice(textElementIndex, 1);
const containerIndex = updatedElements.findIndex(
(ele) => ele.id === container.id,
);
updatedElements.splice(containerIndex + 1, 0, textElement);
return {
elements: updatedElements,
appState: { ...appState, selectedElementIds: { [container.id]: true } },
commitToHistory: true,
};
},
});

View File

@ -1,33 +1,34 @@
import React from "react";
import { getDefaultAppState } from "../appState";
import { ColorPicker } from "../components/ColorPicker";
import { trash, zoomIn, zoomOut } from "../components/icons";
import { eraser, zoomIn, zoomOut } from "../components/icons";
import { ToolButton } from "../components/ToolButton";
import { DarkModeToggle } from "../components/DarkModeToggle";
import { ZOOM_STEP } from "../constants";
import { THEME, ZOOM_STEP } from "../constants";
import { getCommonBounds, getNonDeletedElements } from "../element";
import { newElementWith } from "../element/mutateElement";
import { ExcalidrawElement } from "../element/types";
import { t } from "../i18n";
import { useIsMobile } from "../components/App";
import { CODES, KEYS } from "../keys";
import { getNormalizedZoom, getSelectedElements } from "../scene";
import { centerScrollOn } from "../scene/scroll";
import { getNewZoom } from "../scene/zoom";
import { getStateForZoom } from "../scene/zoom";
import { AppState, NormalizedZoomValue } from "../types";
import { getShortcutKey } from "../utils";
import { getShortcutKey, updateActiveTool } from "../utils";
import { register } from "./register";
import { Tooltip } from "../components/Tooltip";
import { newElementWith } from "../element/mutateElement";
import { getDefaultAppState, isEraserActive } from "../appState";
import ClearCanvas from "../components/ClearCanvas";
import clsx from "clsx";
export const actionChangeViewBackgroundColor = register({
name: "changeViewBackgroundColor",
trackEvent: false,
perform: (_, appState, value) => {
return {
appState: { ...appState, ...value },
commitToHistory: !!value.viewBackgroundColor,
};
},
PanelComponent: ({ appState, updateData }) => {
PanelComponent: ({ elements, appState, updateData }) => {
return (
<div style={{ position: "relative" }}>
<ColorPicker
@ -40,6 +41,8 @@ export const actionChangeViewBackgroundColor = register({
updateData({ openPopup: active ? "canvasColorPicker" : null })
}
data-testid="canvas-background-picker"
elements={elements}
appState={appState}
/>
</div>
);
@ -48,54 +51,51 @@ export const actionChangeViewBackgroundColor = register({
export const actionClearCanvas = register({
name: "clearCanvas",
perform: (elements, appState: AppState) => {
trackEvent: { category: "canvas" },
perform: (elements, appState, _, app) => {
app.imageCache.clear();
return {
elements: elements.map((element) =>
newElementWith(element, { isDeleted: true }),
),
appState: {
...getDefaultAppState(),
files: {},
theme: appState.theme,
elementLocked: appState.elementLocked,
penMode: appState.penMode,
penDetected: appState.penDetected,
exportBackground: appState.exportBackground,
exportEmbedScene: appState.exportEmbedScene,
gridSize: appState.gridSize,
showStats: appState.showStats,
pasteDialog: appState.pasteDialog,
activeTool:
appState.activeTool.type === "image"
? { ...appState.activeTool, type: "selection" }
: appState.activeTool,
},
commitToHistory: true,
};
},
PanelComponent: ({ updateData }) => (
<ToolButton
type="button"
icon={trash}
title={t("buttons.clearReset")}
aria-label={t("buttons.clearReset")}
showAriaLabel={useIsMobile()}
onClick={() => {
if (window.confirm(t("alerts.clearReset"))) {
updateData(null);
}
}}
data-testid="clear-canvas-button"
/>
),
PanelComponent: ({ updateData }) => <ClearCanvas onConfirm={updateData} />,
});
export const actionZoomIn = register({
name: "zoomIn",
perform: (_elements, appState) => {
const zoom = getNewZoom(
getNormalizedZoom(appState.zoom.value + ZOOM_STEP),
appState.zoom,
{ left: appState.offsetLeft, top: appState.offsetTop },
{ x: appState.width / 2, y: appState.height / 2 },
);
trackEvent: { category: "canvas" },
perform: (_elements, appState, _, app) => {
return {
appState: {
...appState,
zoom,
...getStateForZoom(
{
viewportX: appState.width / 2 + appState.offsetLeft,
viewportY: appState.height / 2 + appState.offsetTop,
nextZoom: getNormalizedZoom(appState.zoom.value + ZOOM_STEP),
},
appState,
),
},
commitToHistory: false,
};
@ -119,18 +119,19 @@ export const actionZoomIn = register({
export const actionZoomOut = register({
name: "zoomOut",
perform: (_elements, appState) => {
const zoom = getNewZoom(
getNormalizedZoom(appState.zoom.value - ZOOM_STEP),
appState.zoom,
{ left: appState.offsetLeft, top: appState.offsetTop },
{ x: appState.width / 2, y: appState.height / 2 },
);
trackEvent: { category: "canvas" },
perform: (_elements, appState, _, app) => {
return {
appState: {
...appState,
zoom,
...getStateForZoom(
{
viewportX: appState.width / 2 + appState.offsetLeft,
viewportY: appState.height / 2 + appState.offsetTop,
nextZoom: getNormalizedZoom(appState.zoom.value - ZOOM_STEP),
},
appState,
),
},
commitToHistory: false,
};
@ -154,25 +155,25 @@ export const actionZoomOut = register({
export const actionResetZoom = register({
name: "resetZoom",
perform: (_elements, appState) => {
trackEvent: { category: "canvas" },
perform: (_elements, appState, _, app) => {
return {
appState: {
...appState,
zoom: getNewZoom(
1 as NormalizedZoomValue,
appState.zoom,
{ left: appState.offsetLeft, top: appState.offsetTop },
...getStateForZoom(
{
x: appState.width / 2,
y: appState.height / 2,
viewportX: appState.width / 2 + appState.offsetLeft,
viewportY: appState.height / 2 + appState.offsetTop,
nextZoom: getNormalizedZoom(1),
},
appState,
),
},
commitToHistory: false,
};
},
PanelComponent: ({ updateData, appState }) => (
<Tooltip label={t("buttons.resetZoom")}>
<Tooltip label={t("buttons.resetZoom")} style={{ height: "100%" }}>
<ToolButton
type="button"
className="reset-zoom-button"
@ -224,14 +225,12 @@ const zoomToFitElements = (
? getCommonBounds(selectedElements)
: getCommonBounds(nonDeletedElements);
const zoomValue = zoomValueToFitBoundsOnViewport(commonBounds, {
width: appState.width,
height: appState.height,
});
const newZoom = getNewZoom(zoomValue, appState.zoom, {
left: appState.offsetLeft,
top: appState.offsetTop,
});
const newZoom = {
value: zoomValueToFitBoundsOnViewport(commonBounds, {
width: appState.width,
height: appState.height,
}),
};
const [x1, y1, x2, y2] = commonBounds;
const centerX = (x1 + x2) / 2;
@ -255,6 +254,7 @@ const zoomToFitElements = (
export const actionZoomToSelected = register({
name: "zoomToSelection",
trackEvent: { category: "canvas" },
perform: (elements, appState) => zoomToFitElements(elements, appState, true),
keyTest: (event) =>
event.code === CODES.TWO &&
@ -265,6 +265,7 @@ export const actionZoomToSelected = register({
export const actionZoomToFit = register({
name: "zoomToFit",
trackEvent: { category: "canvas" },
perform: (elements, appState) => zoomToFitElements(elements, appState, false),
keyTest: (event) =>
event.code === CODES.ONE &&
@ -275,11 +276,13 @@ export const actionZoomToFit = register({
export const actionToggleTheme = register({
name: "toggleTheme",
trackEvent: { category: "canvas" },
perform: (_, appState, value) => {
return {
appState: {
...appState,
theme: value || (appState.theme === "light" ? "dark" : "light"),
theme:
value || (appState.theme === THEME.LIGHT ? THEME.DARK : THEME.LIGHT),
},
commitToHistory: false,
};
@ -296,3 +299,49 @@ export const actionToggleTheme = register({
),
keyTest: (event) => event.altKey && event.shiftKey && event.code === CODES.D,
});
export const actionErase = register({
name: "eraser",
trackEvent: { category: "toolbar" },
perform: (elements, appState) => {
let activeTool: AppState["activeTool"];
if (isEraserActive(appState)) {
activeTool = updateActiveTool(appState, {
...(appState.activeTool.lastActiveToolBeforeEraser || {
type: "selection",
}),
lastActiveToolBeforeEraser: null,
});
} else {
activeTool = updateActiveTool(appState, {
type: "eraser",
lastActiveToolBeforeEraser: appState.activeTool,
});
}
return {
appState: {
...appState,
selectedElementIds: {},
selectedGroupIds: {},
activeTool,
},
commitToHistory: true,
};
},
keyTest: (event) => event.key === KEYS.E,
PanelComponent: ({ elements, appState, updateData, data }) => (
<ToolButton
type="button"
icon={eraser}
className={clsx("eraser", { active: isEraserActive(appState) })}
title={`${t("toolBar.eraser")}-${getShortcutKey("E")}`}
aria-label={t("toolBar.eraser")}
onClick={() => {
updateData(null);
}}
size={data?.size || "medium"}
></ToolButton>
),
});

View File

@ -1,16 +1,23 @@
import { CODES, KEYS } from "../keys";
import { register } from "./register";
import { copyToClipboard } from "../clipboard";
import {
copyTextToSystemClipboard,
copyToClipboard,
probablySupportsClipboardWriteText,
} from "../clipboard";
import { actionDeleteSelected } from "./actionDeleteSelected";
import { getSelectedElements } from "../scene/selection";
import { exportCanvas } from "../data/index";
import { getNonDeletedElements } from "../element";
import { getNonDeletedElements, isTextElement } from "../element";
import { t } from "../i18n";
export const actionCopy = register({
name: "copy",
perform: (elements, appState) => {
copyToClipboard(getNonDeletedElements(elements), appState);
trackEvent: { category: "element" },
perform: (elements, appState, _, app) => {
const selectedElements = getSelectedElements(elements, appState, true);
copyToClipboard(selectedElements, appState, app.files);
return {
commitToHistory: false,
@ -23,9 +30,10 @@ export const actionCopy = register({
export const actionCut = register({
name: "cut",
trackEvent: { category: "element" },
perform: (elements, appState, data, app) => {
actionCopy.perform(elements, appState, data, app);
return actionDeleteSelected.perform(elements, appState, data, app);
return actionDeleteSelected.perform(elements, appState);
},
contextItemLabel: "labels.cut",
keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.code === CODES.X,
@ -33,6 +41,7 @@ export const actionCut = register({
export const actionCopyAsSvg = register({
name: "copyAsSvg",
trackEvent: { category: "element" },
perform: async (elements, appState, _data, app) => {
if (!app.canvas) {
return {
@ -42,6 +51,7 @@ export const actionCopyAsSvg = register({
const selectedElements = getSelectedElements(
getNonDeletedElements(elements),
appState,
true,
);
try {
await exportCanvas(
@ -50,12 +60,13 @@ export const actionCopyAsSvg = register({
? selectedElements
: getNonDeletedElements(elements),
appState,
app.files,
appState,
);
return {
commitToHistory: false,
};
} catch (error) {
} catch (error: any) {
console.error(error);
return {
appState: {
@ -71,6 +82,7 @@ export const actionCopyAsSvg = register({
export const actionCopyAsPng = register({
name: "copyAsPng",
trackEvent: { category: "element" },
perform: async (elements, appState, _data, app) => {
if (!app.canvas) {
return {
@ -80,6 +92,7 @@ export const actionCopyAsPng = register({
const selectedElements = getSelectedElements(
getNonDeletedElements(elements),
appState,
true,
);
try {
await exportCanvas(
@ -88,23 +101,26 @@ export const actionCopyAsPng = register({
? selectedElements
: getNonDeletedElements(elements),
appState,
app.files,
appState,
);
return {
appState: {
...appState,
toastMessage: t("toast.copyToClipboardAsPng", {
exportSelection: selectedElements.length
? t("toast.selection")
: t("toast.canvas"),
exportColorScheme: appState.exportWithDarkMode
? t("buttons.darkMode")
: t("buttons.lightMode"),
}),
toast: {
message: t("toast.copyToClipboardAsPng", {
exportSelection: selectedElements.length
? t("toast.selection")
: t("toast.canvas"),
exportColorScheme: appState.exportWithDarkMode
? t("buttons.darkMode")
: t("buttons.lightMode"),
}),
},
},
commitToHistory: false,
};
} catch (error) {
} catch (error: any) {
console.error(error);
return {
appState: {
@ -118,3 +134,35 @@ export const actionCopyAsPng = register({
contextItemLabel: "labels.copyAsPng",
keyTest: (event) => event.code === CODES.C && event.altKey && event.shiftKey,
});
export const copyText = register({
name: "copyText",
trackEvent: { category: "element" },
perform: (elements, appState) => {
const selectedElements = getSelectedElements(
getNonDeletedElements(elements),
appState,
true,
);
const text = selectedElements
.reduce((acc: string[], element) => {
if (isTextElement(element)) {
acc.push(element.text);
}
return acc;
}, [])
.join("\n\n");
copyTextToSystemClipboard(text);
return {
commitToHistory: false,
};
},
contextItemPredicate: (elements, appState) => {
return (
probablySupportsClipboardWriteText &&
getSelectedElements(elements, appState, true).some(isTextElement)
);
},
contextItemLabel: "labels.copyText",
});

View File

@ -1,7 +1,6 @@
import { isSomeElementSelected } from "../scene";
import { KEYS } from "../keys";
import { ToolButton } from "../components/ToolButton";
import React from "react";
import { trash } from "../components/icons";
import { t } from "../i18n";
import { register } from "./register";
@ -12,6 +11,8 @@ import { newElementWith } from "../element/mutateElement";
import { getElementsInGroup } from "../groups";
import { LinearElementEditor } from "../element/linearElementEditor";
import { fixBindingsAfterDeletion } from "../element/binding";
import { isBoundToContainer } from "../element/typeChecks";
import { updateActiveTool } from "../utils";
const deleteSelectedElements = (
elements: readonly ExcalidrawElement[],
@ -22,6 +23,12 @@ const deleteSelectedElements = (
if (appState.selectedElementIds[el.id]) {
return newElementWith(el, { isDeleted: true });
}
if (
isBoundToContainer(el) &&
appState.selectedElementIds[el.containerId]
) {
return newElementWith(el, { isDeleted: true });
}
return el;
}),
appState: {
@ -52,11 +59,12 @@ const handleGroupEditingState = (
export const actionDeleteSelected = register({
name: "deleteSelectedElements",
trackEvent: { category: "element", action: "delete" },
perform: (elements, appState) => {
if (appState.editingLinearElement) {
const {
elementId,
activePointIndex,
selectedPointsIndices,
startBindingElement,
endBindingElement,
} = appState.editingLinearElement;
@ -66,8 +74,7 @@ export const actionDeleteSelected = register({
}
if (
// case: no point selected → delete whole element
activePointIndex == null ||
activePointIndex === -1 ||
selectedPointsIndices == null ||
// case: deleting last remaining point
element.points.length < 2
) {
@ -87,15 +94,17 @@ export const actionDeleteSelected = register({
// We cannot do this inside `movePoint` because it is also called
// when deleting the uncommitted point (which hasn't caused any binding)
const binding = {
startBindingElement:
activePointIndex === 0 ? null : startBindingElement,
endBindingElement:
activePointIndex === element.points.length - 1
? null
: endBindingElement,
startBindingElement: selectedPointsIndices?.includes(0)
? null
: startBindingElement,
endBindingElement: selectedPointsIndices?.includes(
element.points.length - 1,
)
? null
: endBindingElement,
};
LinearElementEditor.movePoint(element, activePointIndex, "delete");
LinearElementEditor.deletePoints(element, selectedPointsIndices);
return {
elements,
@ -104,17 +113,17 @@ export const actionDeleteSelected = register({
editingLinearElement: {
...appState.editingLinearElement,
...binding,
activePointIndex: activePointIndex > 0 ? activePointIndex - 1 : 0,
selectedPointsIndices:
selectedPointsIndices?.[0] > 0
? [selectedPointsIndices[0] - 1]
: [0],
},
},
commitToHistory: true,
};
}
let {
elements: nextElements,
appState: nextAppState,
} = deleteSelectedElements(elements, appState);
let { elements: nextElements, appState: nextAppState } =
deleteSelectedElements(elements, appState);
fixBindingsAfterDeletion(
nextElements,
elements.filter(({ id }) => appState.selectedElementIds[id]),
@ -126,7 +135,7 @@ export const actionDeleteSelected = register({
elements: nextElements,
appState: {
...nextAppState,
elementType: "selection",
activeTool: updateActiveTool(appState, { type: "selection" }),
multiElement: null,
},
commitToHistory: isSomeElementSelected(

View File

@ -1,17 +1,16 @@
import React from "react";
import {
DistributeHorizontallyIcon,
DistributeVerticallyIcon,
} from "../components/icons";
import { ToolButton } from "../components/ToolButton";
import { distributeElements, Distribution } from "../disitrubte";
import { getElementMap, getNonDeletedElements } from "../element";
import { distributeElements, Distribution } from "../distribute";
import { getNonDeletedElements } from "../element";
import { ExcalidrawElement } from "../element/types";
import { t } from "../i18n";
import { CODES } from "../keys";
import { CODES, KEYS } from "../keys";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { AppState } from "../types";
import { getShortcutKey } from "../utils";
import { arrayToMap, getShortcutKey } from "../utils";
import { register } from "./register";
const enableActionGroup = (
@ -31,13 +30,16 @@ const distributeSelectedElements = (
const updatedElements = distributeElements(selectedElements, distribution);
const updatedElementsMap = getElementMap(updatedElements);
const updatedElementsMap = arrayToMap(updatedElements);
return elements.map((element) => updatedElementsMap[element.id] || element);
return elements.map(
(element) => updatedElementsMap.get(element.id) || element,
);
};
export const distributeHorizontally = register({
name: "distributeHorizontally",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
appState,
@ -48,7 +50,8 @@ export const distributeHorizontally = register({
commitToHistory: true,
};
},
keyTest: (event) => event.altKey && event.code === CODES.H,
keyTest: (event) =>
!event[KEYS.CTRL_OR_CMD] && event.altKey && event.code === CODES.H,
PanelComponent: ({ elements, appState, updateData }) => (
<ToolButton
hidden={!enableActionGroup(elements, appState)}
@ -66,6 +69,7 @@ export const distributeHorizontally = register({
export const distributeVertically = register({
name: "distributeVertically",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
appState,
@ -76,7 +80,8 @@ export const distributeVertically = register({
commitToHistory: true,
};
},
keyTest: (event) => event.altKey && event.code === CODES.V,
keyTest: (event) =>
!event[KEYS.CTRL_OR_CMD] && event.altKey && event.code === CODES.V,
PanelComponent: ({ elements, appState, updateData }) => (
<ToolButton
hidden={!enableActionGroup(elements, appState)}

View File

@ -1,15 +1,13 @@
import React from "react";
import { KEYS } from "../keys";
import { register } from "./register";
import { ExcalidrawElement } from "../element/types";
import { duplicateElement, getNonDeletedElements } from "../element";
import { isSomeElementSelected } from "../scene";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { ToolButton } from "../components/ToolButton";
import { clone } from "../components/icons";
import { t } from "../i18n";
import { getShortcutKey } from "../utils";
import { arrayToMap, getShortcutKey } from "../utils";
import { LinearElementEditor } from "../element/linearElementEditor";
import { mutateElement } from "../element/mutateElement";
import {
selectGroupsForSelectedElements,
getSelectedGroupForElement,
@ -19,41 +17,24 @@ import { AppState } from "../types";
import { fixBindingsAfterDuplication } from "../element/binding";
import { ActionResult } from "./types";
import { GRID_SIZE } from "../constants";
import { bindTextToShapeAfterDuplication } from "../element/textElement";
import { isBoundToContainer } from "../element/typeChecks";
export const actionDuplicateSelection = register({
name: "duplicateSelection",
trackEvent: { category: "element" },
perform: (elements, appState) => {
// duplicate point if selected while editing multi-point element
// duplicate selected point(s) if editing a line
if (appState.editingLinearElement) {
const { activePointIndex, elementId } = appState.editingLinearElement;
const element = LinearElementEditor.getElement(elementId);
if (!element || activePointIndex === null) {
const ret = LinearElementEditor.duplicateSelectedPoints(appState);
if (!ret) {
return false;
}
const { points } = element;
const selectedPoint = points[activePointIndex];
const nextPoint = points[activePointIndex + 1];
mutateElement(element, {
points: [
...points.slice(0, activePointIndex + 1),
nextPoint
? [
(selectedPoint[0] + nextPoint[0]) / 2,
(selectedPoint[1] + nextPoint[1]) / 2,
]
: [selectedPoint[0] + 30, selectedPoint[1] + 30],
...points.slice(activePointIndex + 1),
],
});
return {
appState: {
...appState,
editingLinearElement: {
...appState.editingLinearElement,
activePointIndex: activePointIndex + 1,
},
},
elements,
appState: ret.appState,
commitToHistory: true,
};
}
@ -107,9 +88,12 @@ const duplicateElements = (
const finalElements: ExcalidrawElement[] = [];
let index = 0;
const selectedElementIds = arrayToMap(
getSelectedElements(elements, appState, true),
);
while (index < elements.length) {
const element = elements[index];
if (appState.selectedElementIds[element.id]) {
if (selectedElementIds.get(element.id)) {
if (element.groupIds.length) {
const groupId = getSelectedGroupForElement(appState, element);
// if group selected, duplicate it atomically
@ -131,7 +115,11 @@ const duplicateElements = (
}
index++;
}
bindTextToShapeAfterDuplication(
finalElements,
oldElements,
oldIdToDuplicatedId,
);
fixBindingsAfterDuplication(finalElements, oldElements, oldIdToDuplicatedId);
return {
@ -140,10 +128,15 @@ const duplicateElements = (
{
...appState,
selectedGroupIds: {},
selectedElementIds: newElements.reduce((acc, element) => {
acc[element.id] = true;
return acc;
}, {} as any),
selectedElementIds: newElements.reduce(
(acc: Record<ExcalidrawElement["id"], true>, element) => {
if (!isBoundToContainer(element)) {
acc[element.id] = true;
}
return acc;
},
{},
),
},
getNonDeletedElements(finalElements),
),

View File

@ -1,30 +1,29 @@
import React from "react";
import { trackEvent } from "../analytics";
import { load, questionCircle, saveAs } from "../components/icons";
import { ProjectName } from "../components/ProjectName";
import { ToolButton } from "../components/ToolButton";
import "../components/ToolIcon.scss";
import { Tooltip } from "../components/Tooltip";
import { DarkModeToggle, Appearence } from "../components/DarkModeToggle";
import { DarkModeToggle } from "../components/DarkModeToggle";
import { loadFromJSON, saveAsJSON } from "../data";
import { resaveAsImageWithScene } from "../data/resave";
import { t } from "../i18n";
import { useIsMobile } from "../components/App";
import { useDevice } from "../components/App";
import { KEYS } from "../keys";
import { register } from "./register";
import { CheckboxItem } from "../components/CheckboxItem";
import { getExportSize } from "../scene/export";
import { DEFAULT_EXPORT_PADDING, EXPORT_SCALES } from "../constants";
import { DEFAULT_EXPORT_PADDING, EXPORT_SCALES, THEME } from "../constants";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { getNonDeletedElements } from "../element";
import { ActiveFile } from "../components/ActiveFile";
import { isImageFileHandle } from "../data/blob";
import { nativeFileSystemSupported } from "../data/filesystem";
import { Theme } from "../element/types";
export const actionChangeProjectName = register({
name: "changeProjectName",
trackEvent: false,
perform: (_elements, appState, value) => {
trackEvent("change", "title");
return { appState: { ...appState, name: value }, commitToHistory: false };
},
PanelComponent: ({ appState, updateData, appProps }) => (
@ -41,6 +40,7 @@ export const actionChangeProjectName = register({
export const actionChangeExportScale = register({
name: "changeExportScale",
trackEvent: { category: "export", action: "scale" },
perform: (_elements, appState, value) => {
return {
appState: { ...appState, exportScale: value },
@ -89,6 +89,7 @@ export const actionChangeExportScale = register({
export const actionChangeExportBackground = register({
name: "changeExportBackground",
trackEvent: { category: "export", action: "toggleBackground" },
perform: (_elements, appState, value) => {
return {
appState: { ...appState, exportBackground: value },
@ -107,6 +108,7 @@ export const actionChangeExportBackground = register({
export const actionChangeExportEmbedScene = register({
name: "changeExportEmbedScene",
trackEvent: { category: "export", action: "embedScene" },
perform: (_elements, appState, value) => {
return {
appState: { ...appState, exportEmbedScene: value },
@ -128,32 +130,37 @@ export const actionChangeExportEmbedScene = register({
export const actionSaveToActiveFile = register({
name: "saveToActiveFile",
perform: async (elements, appState, value) => {
trackEvent: { category: "export" },
perform: async (elements, appState, value, app) => {
const fileHandleExists = !!appState.fileHandle;
try {
const { fileHandle } = isImageFileHandle(appState.fileHandle)
? await resaveAsImageWithScene(elements, appState)
: await saveAsJSON(elements, appState);
? await resaveAsImageWithScene(elements, appState, app.files)
: await saveAsJSON(elements, appState, app.files);
return {
commitToHistory: false,
appState: {
...appState,
fileHandle,
toastMessage: fileHandleExists
? fileHandle?.name
? t("toast.fileSavedToFilename").replace(
"{filename}",
`"${fileHandle.name}"`,
)
: t("toast.fileSaved")
toast: fileHandleExists
? {
message: fileHandle?.name
? t("toast.fileSavedToFilename").replace(
"{filename}",
`"${fileHandle.name}"`,
)
: t("toast.fileSaved"),
}
: null,
},
};
} catch (error) {
} catch (error: any) {
if (error?.name !== "AbortError") {
console.error(error);
} else {
console.warn(error);
}
return { commitToHistory: false };
}
@ -170,16 +177,23 @@ export const actionSaveToActiveFile = register({
export const actionSaveFileToDisk = register({
name: "saveFileToDisk",
perform: async (elements, appState, value) => {
trackEvent: { category: "export" },
perform: async (elements, appState, value, app) => {
try {
const { fileHandle } = await saveAsJSON(elements, {
...appState,
fileHandle: null,
});
const { fileHandle } = await saveAsJSON(
elements,
{
...appState,
fileHandle: null,
},
app.files,
);
return { commitToHistory: false, appState: { ...appState, fileHandle } };
} catch (error) {
} catch (error: any) {
if (error?.name !== "AbortError") {
console.error(error);
} else {
console.warn(error);
}
return { commitToHistory: false };
}
@ -192,7 +206,7 @@ export const actionSaveFileToDisk = register({
icon={saveAs}
title={t("buttons.saveAs")}
aria-label={t("buttons.saveAs")}
showAriaLabel={useIsMobile()}
showAriaLabel={useDevice().isMobile}
hidden={!nativeFileSystemSupported}
onClick={() => updateData(null)}
data-testid="save-as-button"
@ -202,36 +216,41 @@ export const actionSaveFileToDisk = register({
export const actionLoadScene = register({
name: "loadScene",
perform: async (elements, appState) => {
trackEvent: { category: "export" },
perform: async (elements, appState, _, app) => {
try {
const {
elements: loadedElements,
appState: loadedAppState,
files,
} = await loadFromJSON(appState, elements);
return {
elements: loadedElements,
appState: loadedAppState,
files,
commitToHistory: true,
};
} catch (error) {
} catch (error: any) {
if (error?.name === "AbortError") {
console.warn(error);
return false;
}
return {
elements,
appState: { ...appState, errorMessage: error.message },
files: app.files,
commitToHistory: false,
};
}
},
keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.key === KEYS.O,
PanelComponent: ({ updateData, appState }) => (
PanelComponent: ({ updateData }) => (
<ToolButton
type="button"
icon={load}
title={t("buttons.load")}
aria-label={t("buttons.load")}
showAriaLabel={useIsMobile()}
showAriaLabel={useDevice().isMobile}
onClick={updateData}
data-testid="load-button"
/>
@ -240,6 +259,7 @@ export const actionLoadScene = register({
export const actionExportWithDarkMode = register({
name: "exportWithDarkMode",
trackEvent: { category: "export", action: "toggleTheme" },
perform: (_elements, appState, value) => {
return {
appState: { ...appState, exportWithDarkMode: value },
@ -256,9 +276,9 @@ export const actionExportWithDarkMode = register({
}}
>
<DarkModeToggle
value={appState.exportWithDarkMode ? "dark" : "light"}
onChange={(theme: Appearence) => {
updateData(theme === "dark");
value={appState.exportWithDarkMode ? THEME.DARK : THEME.LIGHT}
onChange={(theme: Theme) => {
updateData(theme === THEME.DARK);
}}
title={t("labels.toggleExportColorScheme")}
/>

View File

@ -1,7 +1,6 @@
import { KEYS } from "../keys";
import { isInvisiblySmallElement } from "../element";
import { resetCursor } from "../utils";
import React from "react";
import { updateActiveTool, resetCursor } from "../utils";
import { ToolButton } from "../components/ToolButton";
import { done } from "../components/icons";
import { t } from "../i18n";
@ -14,17 +13,16 @@ import {
maybeBindLinearElement,
bindOrUnbindLinearElement,
} from "../element/binding";
import { isBindingElement } from "../element/typeChecks";
import { isBindingElement, isLinearElement } from "../element/typeChecks";
import { AppState } from "../types";
export const actionFinalize = register({
name: "finalize",
perform: (elements, appState, _, { canvas, focusContainer }) => {
trackEvent: false,
perform: (elements, appState, _, { canvas, focusContainer, scene }) => {
if (appState.editingLinearElement) {
const {
elementId,
startBindingElement,
endBindingElement,
} = appState.editingLinearElement;
const { elementId, startBindingElement, endBindingElement } =
appState.editingLinearElement;
const element = LinearElementEditor.getElement(elementId);
if (element) {
@ -42,6 +40,7 @@ export const actionFinalize = register({
: undefined,
appState: {
...appState,
cursorButton: "up",
editingLinearElement: null,
},
commitToHistory: true,
@ -50,6 +49,15 @@ export const actionFinalize = register({
}
let newElements = elements;
const pendingImageElement =
appState.pendingImageElementId &&
scene.getElement(appState.pendingImageElementId);
if (pendingImageElement) {
mutateElement(pendingImageElement, { isDeleted: true }, false);
}
if (window.document.activeElement instanceof HTMLElement) {
focusContainer();
}
@ -118,27 +126,47 @@ export const actionFinalize = register({
);
}
if (!appState.elementLocked && appState.elementType !== "freedraw") {
if (
!appState.activeTool.locked &&
appState.activeTool.type !== "freedraw"
) {
appState.selectedElementIds[multiPointElement.id] = true;
}
}
if (
(!appState.elementLocked && appState.elementType !== "freedraw") ||
(!appState.activeTool.locked &&
appState.activeTool.type !== "freedraw") ||
!multiPointElement
) {
resetCursor(canvas);
}
let activeTool: AppState["activeTool"];
if (appState.activeTool.type === "eraser") {
activeTool = updateActiveTool(appState, {
...(appState.activeTool.lastActiveToolBeforeEraser || {
type: "selection",
}),
lastActiveToolBeforeEraser: null,
});
} else {
activeTool = updateActiveTool(appState, {
type: "selection",
});
}
return {
elements: newElements,
appState: {
...appState,
elementType:
(appState.elementLocked || appState.elementType === "freedraw") &&
cursorButton: "up",
activeTool:
(appState.activeTool.locked ||
appState.activeTool.type === "freedraw") &&
multiPointElement
? appState.elementType
: "selection",
? appState.activeTool
: activeTool,
draggingElement: null,
multiElement: null,
editingElement: null,
@ -146,15 +174,21 @@ export const actionFinalize = register({
suggestedBindings: [],
selectedElementIds:
multiPointElement &&
!appState.elementLocked &&
appState.elementType !== "freedraw"
!appState.activeTool.locked &&
appState.activeTool.type !== "freedraw"
? {
...appState.selectedElementIds,
[multiPointElement.id]: true,
}
: appState.selectedElementIds,
// To select the linear element when user has finished mutipoint editing
selectedLinearElement:
multiPointElement && isLinearElement(multiPointElement)
? new LinearElementEditor(multiPointElement, scene)
: appState.selectedLinearElement,
pendingImageElementId: null,
},
commitToHistory: appState.elementType === "freedraw",
commitToHistory: appState.activeTool.type === "freedraw",
};
},
keyTest: (event, appState) =>
@ -163,7 +197,7 @@ export const actionFinalize = register({
(!appState.draggingElement && appState.multiElement === null))) ||
((event.key === KEYS.ESCAPE || event.key === KEYS.ENTER) &&
appState.multiElement !== null),
PanelComponent: ({ appState, updateData }) => (
PanelComponent: ({ appState, updateData, data }) => (
<ToolButton
type="button"
icon={done}
@ -171,6 +205,7 @@ export const actionFinalize = register({
aria-label={t("buttons.done")}
onClick={updateData}
visible={appState.multiElement != null}
size={data?.size || "medium"}
/>
),
});

View File

@ -1,6 +1,6 @@
import { register } from "./register";
import { getSelectedElements } from "../scene";
import { getElementMap, getNonDeletedElements } from "../element";
import { getNonDeletedElements } from "../element";
import { mutateElement } from "../element/mutateElement";
import { ExcalidrawElement, NonDeleted } from "../element/types";
import { normalizeAngle, resizeSingleElement } from "../element/resizeElements";
@ -9,6 +9,7 @@ import { getTransformHandles } from "../element/transformHandles";
import { isFreeDrawElement, isLinearElement } from "../element/typeChecks";
import { updateBoundElements } from "../element/binding";
import { LinearElementEditor } from "../element/linearElementEditor";
import { arrayToMap } from "../utils";
const enableActionFlipHorizontal = (
elements: readonly ExcalidrawElement[],
@ -34,6 +35,7 @@ const enableActionFlipVertical = (
export const actionFlipHorizontal = register({
name: "flipHorizontal",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
elements: flipSelectedElements(elements, appState, "horizontal"),
@ -49,6 +51,7 @@ export const actionFlipHorizontal = register({
export const actionFlipVertical = register({
name: "flipVertical",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
elements: flipSelectedElements(elements, appState, "vertical"),
@ -83,9 +86,11 @@ const flipSelectedElements = (
flipDirection,
);
const updatedElementsMap = getElementMap(updatedElements);
const updatedElementsMap = arrayToMap(updatedElements);
return elements.map((element) => updatedElementsMap[element.id] || element);
return elements.map(
(element) => updatedElementsMap.get(element.id) || element,
);
};
const flipElements = (
@ -93,13 +98,13 @@ const flipElements = (
appState: AppState,
flipDirection: "horizontal" | "vertical",
): ExcalidrawElement[] => {
for (let i = 0; i < elements.length; i++) {
flipElement(elements[i], appState);
elements.forEach((element) => {
flipElement(element, appState);
// If vertical flip, rotate an extra 180
if (flipDirection === "vertical") {
rotateElement(elements[i], Math.PI);
rotateElement(element, Math.PI);
}
}
});
return elements;
};
@ -142,10 +147,9 @@ const flipElement = (
}
if (isLinearElement(element)) {
for (let i = 1; i < element.points.length; i++) {
LinearElementEditor.movePoint(element, i, [
-element.points[i][0],
element.points[i][1],
for (let index = 1; index < element.points.length; index++) {
LinearElementEditor.movePoints(element, [
{ index, point: [-element.points[index][0], element.points[index][1]] },
]);
}
LinearElementEditor.normalizePoints(element);
@ -153,7 +157,7 @@ const flipElement = (
// calculate new x-coord for transformation
newNCoordsX = usingNWHandle ? element.x + 2 * width : element.x - 2 * width;
resizeSingleElement(
element,
new Map().set(element.id, element),
true,
element,
usingNWHandle ? "nw" : "ne",

View File

@ -1,7 +1,6 @@
import React from "react";
import { CODES, KEYS } from "../keys";
import { t } from "../i18n";
import { getShortcutKey } from "../utils";
import { arrayToMap, getShortcutKey } from "../utils";
import { register } from "./register";
import { UngroupIcon, GroupIcon } from "../components/icons";
import { newElementWith } from "../element/mutateElement";
@ -18,8 +17,9 @@ import {
import { getNonDeletedElements } from "../element";
import { randomId } from "../random";
import { ToolButton } from "../components/ToolButton";
import { ExcalidrawElement } from "../element/types";
import { ExcalidrawElement, ExcalidrawTextElement } from "../element/types";
import { AppState } from "../types";
import { isBoundToContainer } from "../element/typeChecks";
const allElementsInSameGroup = (elements: readonly ExcalidrawElement[]) => {
if (elements.length >= 2) {
@ -45,6 +45,7 @@ const enableActionGroup = (
const selectedElements = getSelectedElements(
getNonDeletedElements(elements),
appState,
true,
);
return (
selectedElements.length >= 2 && !allElementsInSameGroup(selectedElements)
@ -53,10 +54,12 @@ const enableActionGroup = (
export const actionGroup = register({
name: "group",
trackEvent: { category: "element" },
perform: (elements, appState) => {
const selectedElements = getSelectedElements(
getNonDeletedElements(elements),
appState,
true,
);
if (selectedElements.length < 2) {
// nothing to group
@ -84,8 +87,9 @@ export const actionGroup = register({
}
}
const newGroupId = randomId();
const selectElementIds = arrayToMap(selectedElements);
const updatedElements = elements.map((element) => {
if (!appState.selectedElementIds[element.id]) {
if (!selectElementIds.get(element.id)) {
return element;
}
return newElementWith(element, {
@ -100,9 +104,8 @@ export const actionGroup = register({
// to the z order of the highest element in the layer stack
const elementsInGroup = getElementsInGroup(updatedElements, newGroupId);
const lastElementInGroup = elementsInGroup[elementsInGroup.length - 1];
const lastGroupElementIndex = updatedElements.lastIndexOf(
lastElementInGroup,
);
const lastGroupElementIndex =
updatedElements.lastIndexOf(lastElementInGroup);
const elementsAfterGroup = updatedElements.slice(lastGroupElementIndex + 1);
const elementsBeforeGroup = updatedElements
.slice(0, lastGroupElementIndex)
@ -145,12 +148,18 @@ export const actionGroup = register({
export const actionUngroup = register({
name: "ungroup",
trackEvent: { category: "element" },
perform: (elements, appState) => {
const groupIds = getSelectedGroupIds(appState);
if (groupIds.length === 0) {
return { appState, elements, commitToHistory: false };
}
const boundTextElementIds: ExcalidrawTextElement["id"][] = [];
const nextElements = elements.map((element) => {
if (isBoundToContainer(element)) {
boundTextElementIds.push(element.id);
}
const nextGroupIds = removeFromSelectedGroups(
element.groupIds,
appState.selectedGroupIds,
@ -162,11 +171,19 @@ export const actionUngroup = register({
groupIds: nextGroupIds,
});
});
const updateAppState = selectGroupsForSelectedElements(
{ ...appState, selectedGroupIds: {} },
getNonDeletedElements(nextElements),
);
// remove binded text elements from selection
boundTextElementIds.forEach(
(id) => (updateAppState.selectedElementIds[id] = false),
);
return {
appState: selectGroupsForSelectedElements(
{ ...appState, selectedGroupIds: {} },
getNonDeletedElements(nextElements),
),
appState: updateAppState,
elements: nextElements,
commitToHistory: true,
};

View File

@ -1,5 +1,4 @@
import { Action, ActionResult } from "./types";
import React from "react";
import { undo, redo } from "../components/icons";
import { ToolButton } from "../components/ToolButton";
import { t } from "../i18n";
@ -7,9 +6,9 @@ import History, { HistoryEntry } from "../history";
import { ExcalidrawElement } from "../element/types";
import { AppState } from "../types";
import { isWindows, KEYS } from "../keys";
import { getElementMap } from "../element";
import { newElementWith } from "../element/mutateElement";
import { fixBindingsAfterDeletion } from "../element/binding";
import { arrayToMap } from "../utils";
const writeData = (
prevElements: readonly ExcalidrawElement[],
@ -28,17 +27,17 @@ const writeData = (
return { commitToHistory };
}
const prevElementMap = getElementMap(prevElements);
const prevElementMap = arrayToMap(prevElements);
const nextElements = data.elements;
const nextElementMap = getElementMap(nextElements);
const nextElementMap = arrayToMap(nextElements);
const deletedElements = prevElements.filter(
(prevElement) => !nextElementMap.hasOwnProperty(prevElement.id),
(prevElement) => !nextElementMap.has(prevElement.id),
);
const elements = nextElements
.map((nextElement) =>
newElementWith(
prevElementMap[nextElement.id] || nextElement,
prevElementMap.get(nextElement.id) || nextElement,
nextElement,
),
)
@ -63,6 +62,7 @@ type ActionCreator = (history: History) => Action;
export const createUndoAction: ActionCreator = (history) => ({
name: "undo",
trackEvent: { category: "history" },
perform: (elements, appState) =>
writeData(elements, appState, () => history.undoOnce()),
keyTest: (event) =>
@ -83,6 +83,7 @@ export const createUndoAction: ActionCreator = (history) => ({
export const createRedoAction: ActionCreator = (history) => ({
name: "redo",
trackEvent: { category: "history" },
perform: (elements, appState) =>
writeData(elements, appState, () => history.redoOnce()),
keyTest: (event) =>

View File

@ -1,4 +1,3 @@
import React from "react";
import { menu, palette } from "../components/icons";
import { ToolButton } from "../components/ToolButton";
import { t } from "../i18n";
@ -10,6 +9,7 @@ import { HelpIcon } from "../components/HelpIcon";
export const actionToggleCanvasMenu = register({
name: "toggleCanvasMenu",
trackEvent: { category: "menu" },
perform: (_, appState) => ({
appState: {
...appState,
@ -30,6 +30,7 @@ export const actionToggleCanvasMenu = register({
export const actionToggleEditMenu = register({
name: "toggleEditMenu",
trackEvent: { category: "menu" },
perform: (_elements, appState) => ({
appState: {
...appState,
@ -54,6 +55,7 @@ export const actionToggleEditMenu = register({
export const actionFullScreen = register({
name: "toggleFullScreen",
trackEvent: { category: "canvas", predicate: (appState) => !isFullScreen() },
perform: () => {
if (!isFullScreen()) {
allowFullScreen();
@ -70,6 +72,7 @@ export const actionFullScreen = register({
export const actionShortcuts = register({
name: "toggleShortcuts",
trackEvent: { category: "menu", action: "toggleHelpDialog" },
perform: (_elements, appState, _, { focusContainer }) => {
if (appState.showHelpDialog) {
focusContainer();

View File

@ -1,5 +1,4 @@
import React from "react";
import { getClientColors, getClientInitials } from "../clients";
import { getClientColors } from "../clients";
import { Avatar } from "../components/Avatar";
import { centerScrollOn } from "../scene/scroll";
import { Collaborator } from "../types";
@ -7,6 +6,7 @@ import { register } from "./register";
export const actionGoToCollaborator = register({
name: "goToCollaborator",
trackEvent: { category: "collab" },
perform: (_elements, appState, value) => {
const point = value as Collaborator["pointer"];
if (!point) {
@ -31,28 +31,18 @@ export const actionGoToCollaborator = register({
};
},
PanelComponent: ({ appState, updateData, data }) => {
const clientId: string | undefined = data?.id;
if (!clientId) {
return null;
}
const collaborator = appState.collaborators.get(clientId);
if (!collaborator) {
return null;
}
const [clientId, collaborator] = data as [string, Collaborator];
const { background, stroke } = getClientColors(clientId, appState);
const shortName = getClientInitials(collaborator.username);
return (
<Avatar
color={background}
border={stroke}
onClick={() => updateData(collaborator.pointer)}
>
{shortName}
</Avatar>
name={collaborator.username || ""}
src={collaborator.avatarUrl}
/>
);
},
});

View File

@ -1,4 +1,3 @@
import React from "react";
import { AppState } from "../../src/types";
import { ButtonIconSelect } from "../components/ButtonIconSelect";
import { ColorPicker } from "../components/ColorPicker";
@ -7,6 +6,7 @@ import {
ArrowheadArrowIcon,
ArrowheadBarIcon,
ArrowheadDotIcon,
ArrowheadTriangleIcon,
ArrowheadNoneIcon,
EdgeRoundIcon,
EdgeSharpIcon,
@ -30,19 +30,31 @@ import {
TextAlignCenterIcon,
TextAlignLeftIcon,
TextAlignRightIcon,
TextAlignTopIcon,
TextAlignBottomIcon,
TextAlignMiddleIcon,
} from "../components/icons";
import {
DEFAULT_FONT_FAMILY,
DEFAULT_FONT_SIZE,
FONT_FAMILY,
VERTICAL_ALIGN,
} from "../constants";
import {
getNonDeletedElements,
isTextElement,
redrawTextBoundingBox,
} from "../element";
import { newElementWith } from "../element/mutateElement";
import { isLinearElement, isLinearElementType } from "../element/typeChecks";
import { mutateElement, newElementWith } from "../element/mutateElement";
import {
getBoundTextElement,
getContainerElement,
} from "../element/textElement";
import {
isBoundToContainer,
isLinearElement,
isLinearElementType,
} from "../element/typeChecks";
import {
Arrowhead,
ExcalidrawElement,
@ -50,26 +62,37 @@ import {
ExcalidrawTextElement,
FontFamilyValues,
TextAlign,
VerticalAlign,
} from "../element/types";
import { getLanguage, t } from "../i18n";
import { KEYS } from "../keys";
import { randomInteger } from "../random";
import {
canChangeSharpness,
canHaveArrowheads,
getCommonAttributeOfSelectedElements,
getSelectedElements,
getTargetElements,
isSomeElementSelected,
} from "../scene";
import { hasStrokeColor } from "../scene/comparisons";
import { arrayToMap } from "../utils";
import { register } from "./register";
const FONT_SIZE_RELATIVE_INCREASE_STEP = 0.1;
const changeProperty = (
elements: readonly ExcalidrawElement[],
appState: AppState,
callback: (element: ExcalidrawElement) => ExcalidrawElement,
includeBoundText = false,
) => {
const selectedElementIds = arrayToMap(
getSelectedElements(elements, appState, includeBoundText),
);
return elements.map((element) => {
if (
appState.selectedElementIds[element.id] ||
selectedElementIds.get(element.id) ||
element.id === appState.editingElement?.id
) {
return callback(element);
@ -99,15 +122,93 @@ const getFormValue = function <T>(
);
};
const offsetElementAfterFontResize = (
prevElement: ExcalidrawTextElement,
nextElement: ExcalidrawTextElement,
) => {
if (isBoundToContainer(nextElement)) {
return nextElement;
}
return mutateElement(
nextElement,
{
x:
prevElement.textAlign === "left"
? prevElement.x
: prevElement.x +
(prevElement.width - nextElement.width) /
(prevElement.textAlign === "center" ? 2 : 1),
// centering vertically is non-standard, but for Excalidraw I think
// it makes sense
y: prevElement.y + (prevElement.height - nextElement.height) / 2,
},
false,
);
};
const changeFontSize = (
elements: readonly ExcalidrawElement[],
appState: AppState,
getNewFontSize: (element: ExcalidrawTextElement) => number,
fallbackValue?: ExcalidrawTextElement["fontSize"],
) => {
const newFontSizes = new Set<number>();
return {
elements: changeProperty(
elements,
appState,
(oldElement) => {
if (isTextElement(oldElement)) {
const newFontSize = getNewFontSize(oldElement);
newFontSizes.add(newFontSize);
let newElement: ExcalidrawTextElement = newElementWith(oldElement, {
fontSize: newFontSize,
});
redrawTextBoundingBox(newElement, getContainerElement(oldElement));
newElement = offsetElementAfterFontResize(oldElement, newElement);
return newElement;
}
return oldElement;
},
true,
),
appState: {
...appState,
// update state only if we've set all select text elements to
// the same font size
currentItemFontSize:
newFontSizes.size === 1
? [...newFontSizes][0]
: fallbackValue ?? appState.currentItemFontSize,
},
commitToHistory: true,
};
};
// -----------------------------------------------------------------------------
export const actionChangeStrokeColor = register({
name: "changeStrokeColor",
trackEvent: false,
perform: (elements, appState, value) => {
return {
...(value.currentItemStrokeColor && {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
strokeColor: value.currentItemStrokeColor,
}),
elements: changeProperty(
elements,
appState,
(el) => {
return hasStrokeColor(el.type)
? newElementWith(el, {
strokeColor: value.currentItemStrokeColor,
})
: el;
},
true,
),
}),
appState: {
@ -134,6 +235,8 @@ export const actionChangeStrokeColor = register({
setActive={(active) =>
updateData({ openPopup: active ? "strokeColorPicker" : null })
}
elements={elements}
appState={appState}
/>
</>
),
@ -141,6 +244,7 @@ export const actionChangeStrokeColor = register({
export const actionChangeBackgroundColor = register({
name: "changeBackgroundColor",
trackEvent: false,
perform: (elements, appState, value) => {
return {
...(value.currentItemBackgroundColor && {
@ -174,6 +278,8 @@ export const actionChangeBackgroundColor = register({
setActive={(active) =>
updateData({ openPopup: active ? "backgroundColorPicker" : null })
}
elements={elements}
appState={appState}
/>
</>
),
@ -181,6 +287,7 @@ export const actionChangeBackgroundColor = register({
export const actionChangeFillStyle = register({
name: "changeFillStyle",
trackEvent: false,
perform: (elements, appState, value) => {
return {
elements: changeProperty(elements, appState, (el) =>
@ -230,6 +337,7 @@ export const actionChangeFillStyle = register({
export const actionChangeStrokeWidth = register({
name: "changeStrokeWidth",
trackEvent: false,
perform: (elements, appState, value) => {
return {
elements: changeProperty(elements, appState, (el) =>
@ -277,6 +385,7 @@ export const actionChangeStrokeWidth = register({
export const actionChangeSloppiness = register({
name: "changeSloppiness",
trackEvent: false,
perform: (elements, appState, value) => {
return {
elements: changeProperty(elements, appState, (el) =>
@ -325,6 +434,7 @@ export const actionChangeSloppiness = register({
export const actionChangeStrokeStyle = register({
name: "changeStrokeStyle",
trackEvent: false,
perform: (elements, appState, value) => {
return {
elements: changeProperty(elements, appState, (el) =>
@ -372,12 +482,17 @@ export const actionChangeStrokeStyle = register({
export const actionChangeOpacity = register({
name: "changeOpacity",
trackEvent: false,
perform: (elements, appState, value) => {
return {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
opacity: value,
}),
elements: changeProperty(
elements,
appState,
(el) =>
newElementWith(el, {
opacity: value,
}),
true,
),
appState: { ...appState, currentItemOpacity: value },
commitToHistory: true,
@ -392,20 +507,6 @@ export const actionChangeOpacity = register({
max="100"
step="10"
onChange={(event) => updateData(+event.target.value)}
onWheel={(event) => {
event.stopPropagation();
const target = event.target as HTMLInputElement;
const STEP = 10;
const MAX = 100;
const MIN = 0;
const value = +target.value;
if (event.deltaY < 0 && value < MAX) {
updateData(value + STEP);
} else if (event.deltaY > 0 && value > MIN) {
updateData(value - STEP);
}
}}
value={
getFormValue(
elements,
@ -421,25 +522,9 @@ export const actionChangeOpacity = register({
export const actionChangeFontSize = register({
name: "changeFontSize",
trackEvent: false,
perform: (elements, appState, value) => {
return {
elements: changeProperty(elements, appState, (el) => {
if (isTextElement(el)) {
const element: ExcalidrawTextElement = newElementWith(el, {
fontSize: value,
});
redrawTextBoundingBox(element);
return element;
}
return el;
}),
appState: {
...appState,
currentItemFontSize: value,
},
commitToHistory: true,
};
return changeFontSize(elements, appState, () => value, value);
},
PanelComponent: ({ elements, appState, updateData }) => (
<fieldset>
@ -451,27 +536,40 @@ export const actionChangeFontSize = register({
value: 16,
text: t("labels.small"),
icon: <FontSizeSmallIcon theme={appState.theme} />,
testId: "fontSize-small",
},
{
value: 20,
text: t("labels.medium"),
icon: <FontSizeMediumIcon theme={appState.theme} />,
testId: "fontSize-medium",
},
{
value: 28,
text: t("labels.large"),
icon: <FontSizeLargeIcon theme={appState.theme} />,
testId: "fontSize-large",
},
{
value: 36,
text: t("labels.veryLarge"),
icon: <FontSizeExtraLargeIcon theme={appState.theme} />,
testId: "fontSize-veryLarge",
},
]}
value={getFormValue(
elements,
appState,
(element) => isTextElement(element) && element.fontSize,
(element) => {
if (isTextElement(element)) {
return element.fontSize;
}
const boundTextElement = getBoundTextElement(element);
if (boundTextElement) {
return boundTextElement.fontSize;
}
return null;
},
appState.currentItemFontSize || DEFAULT_FONT_SIZE,
)}
onChange={(value) => updateData(value)}
@ -480,21 +578,70 @@ export const actionChangeFontSize = register({
),
});
export const actionDecreaseFontSize = register({
name: "decreaseFontSize",
trackEvent: false,
perform: (elements, appState, value) => {
return changeFontSize(elements, appState, (element) =>
Math.round(
// get previous value before relative increase (doesn't work fully
// due to rounding and float precision issues)
(1 / (1 + FONT_SIZE_RELATIVE_INCREASE_STEP)) * element.fontSize,
),
);
},
keyTest: (event) => {
return (
event[KEYS.CTRL_OR_CMD] &&
event.shiftKey &&
// KEYS.COMMA needed for MacOS
(event.key === KEYS.CHEVRON_LEFT || event.key === KEYS.COMMA)
);
},
});
export const actionIncreaseFontSize = register({
name: "increaseFontSize",
trackEvent: false,
perform: (elements, appState, value) => {
return changeFontSize(elements, appState, (element) =>
Math.round(element.fontSize * (1 + FONT_SIZE_RELATIVE_INCREASE_STEP)),
);
},
keyTest: (event) => {
return (
event[KEYS.CTRL_OR_CMD] &&
event.shiftKey &&
// KEYS.PERIOD needed for MacOS
(event.key === KEYS.CHEVRON_RIGHT || event.key === KEYS.PERIOD)
);
},
});
export const actionChangeFontFamily = register({
name: "changeFontFamily",
trackEvent: false,
perform: (elements, appState, value) => {
return {
elements: changeProperty(elements, appState, (el) => {
if (isTextElement(el)) {
const element: ExcalidrawTextElement = newElementWith(el, {
fontFamily: value,
});
redrawTextBoundingBox(element);
return element;
}
elements: changeProperty(
elements,
appState,
(oldElement) => {
if (isTextElement(oldElement)) {
const newElement: ExcalidrawTextElement = newElementWith(
oldElement,
{
fontFamily: value,
},
);
redrawTextBoundingBox(newElement, getContainerElement(oldElement));
return newElement;
}
return el;
}),
return oldElement;
},
true,
),
appState: {
...appState,
currentItemFontFamily: value,
@ -534,7 +681,16 @@ export const actionChangeFontFamily = register({
value={getFormValue(
elements,
appState,
(element) => isTextElement(element) && element.fontFamily,
(element) => {
if (isTextElement(element)) {
return element.fontFamily;
}
const boundTextElement = getBoundTextElement(element);
if (boundTextElement) {
return boundTextElement.fontFamily;
}
return null;
},
appState.currentItemFontFamily || DEFAULT_FONT_FAMILY,
)}
onChange={(value) => updateData(value)}
@ -546,19 +702,26 @@ export const actionChangeFontFamily = register({
export const actionChangeTextAlign = register({
name: "changeTextAlign",
trackEvent: false,
perform: (elements, appState, value) => {
return {
elements: changeProperty(elements, appState, (el) => {
if (isTextElement(el)) {
const element: ExcalidrawTextElement = newElementWith(el, {
textAlign: value,
});
redrawTextBoundingBox(element);
return element;
}
elements: changeProperty(
elements,
appState,
(oldElement) => {
if (isTextElement(oldElement)) {
const newElement: ExcalidrawTextElement = newElementWith(
oldElement,
{ textAlign: value },
);
redrawTextBoundingBox(newElement, getContainerElement(oldElement));
return newElement;
}
return el;
}),
return oldElement;
},
true,
),
appState: {
...appState,
currentItemTextAlign: value,
@ -566,42 +729,121 @@ export const actionChangeTextAlign = register({
commitToHistory: true,
};
},
PanelComponent: ({ elements, appState, updateData }) => (
<fieldset>
<legend>{t("labels.textAlign")}</legend>
<ButtonIconSelect<TextAlign | false>
group="text-align"
options={[
{
value: "left",
text: t("labels.left"),
icon: <TextAlignLeftIcon theme={appState.theme} />,
},
{
value: "center",
text: t("labels.center"),
icon: <TextAlignCenterIcon theme={appState.theme} />,
},
{
value: "right",
text: t("labels.right"),
icon: <TextAlignRightIcon theme={appState.theme} />,
},
]}
value={getFormValue(
elements,
appState,
(element) => isTextElement(element) && element.textAlign,
appState.currentItemTextAlign,
)}
onChange={(value) => updateData(value)}
/>
</fieldset>
),
PanelComponent: ({ elements, appState, updateData }) => {
return (
<fieldset>
<legend>{t("labels.textAlign")}</legend>
<ButtonIconSelect<TextAlign | false>
group="text-align"
options={[
{
value: "left",
text: t("labels.left"),
icon: <TextAlignLeftIcon theme={appState.theme} />,
},
{
value: "center",
text: t("labels.center"),
icon: <TextAlignCenterIcon theme={appState.theme} />,
},
{
value: "right",
text: t("labels.right"),
icon: <TextAlignRightIcon theme={appState.theme} />,
},
]}
value={getFormValue(
elements,
appState,
(element) => {
if (isTextElement(element)) {
return element.textAlign;
}
const boundTextElement = getBoundTextElement(element);
if (boundTextElement) {
return boundTextElement.textAlign;
}
return null;
},
appState.currentItemTextAlign,
)}
onChange={(value) => updateData(value)}
/>
</fieldset>
);
},
});
export const actionChangeVerticalAlign = register({
name: "changeVerticalAlign",
trackEvent: { category: "element" },
perform: (elements, appState, value) => {
return {
elements: changeProperty(
elements,
appState,
(oldElement) => {
if (isTextElement(oldElement)) {
const newElement: ExcalidrawTextElement = newElementWith(
oldElement,
{ verticalAlign: value },
);
redrawTextBoundingBox(newElement, getContainerElement(oldElement));
return newElement;
}
return oldElement;
},
true,
),
appState: {
...appState,
},
commitToHistory: true,
};
},
PanelComponent: ({ elements, appState, updateData }) => {
return (
<fieldset>
<ButtonIconSelect<VerticalAlign | false>
group="text-align"
options={[
{
value: VERTICAL_ALIGN.TOP,
text: t("labels.alignTop"),
icon: <TextAlignTopIcon theme={appState.theme} />,
},
{
value: VERTICAL_ALIGN.MIDDLE,
text: t("labels.centerVertically"),
icon: <TextAlignMiddleIcon theme={appState.theme} />,
},
{
value: VERTICAL_ALIGN.BOTTOM,
text: t("labels.alignBottom"),
icon: <TextAlignBottomIcon theme={appState.theme} />,
},
]}
value={getFormValue(elements, appState, (element) => {
if (isTextElement(element) && element.containerId) {
return element.verticalAlign;
}
const boundTextElement = getBoundTextElement(element);
if (boundTextElement) {
return boundTextElement.verticalAlign;
}
return null;
})}
onChange={(value) => updateData(value)}
/>
</fieldset>
);
},
});
export const actionChangeSharpness = register({
name: "changeSharpness",
trackEvent: false,
perform: (elements, appState, value) => {
const targetElements = getTargetElements(
getNonDeletedElements(elements),
@ -609,10 +851,10 @@ export const actionChangeSharpness = register({
);
const shouldUpdateForNonLinearElements = targetElements.length
? targetElements.every((el) => !isLinearElement(el))
: !isLinearElementType(appState.elementType);
: !isLinearElementType(appState.activeTool.type);
const shouldUpdateForLinearElements = targetElements.length
? targetElements.every(isLinearElement)
: isLinearElementType(appState.elementType);
: isLinearElementType(appState.activeTool.type);
return {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
@ -652,8 +894,8 @@ export const actionChangeSharpness = register({
elements,
appState,
(element) => element.strokeSharpness,
(canChangeSharpness(appState.elementType) &&
(isLinearElementType(appState.elementType)
(canChangeSharpness(appState.activeTool.type) &&
(isLinearElementType(appState.activeTool.type)
? appState.currentItemLinearStrokeSharpness
: appState.currentItemStrokeSharpness)) ||
null,
@ -666,6 +908,7 @@ export const actionChangeSharpness = register({
export const actionChangeArrowhead = register({
name: "changeArrowhead",
trackEvent: false,
perform: (
elements,
appState,
@ -736,6 +979,14 @@ export const actionChangeArrowhead = register({
icon: <ArrowheadDotIcon theme={appState.theme} flip={!isRTL} />,
keyBinding: "r",
},
{
value: "triangle",
text: t("labels.arrowhead_triangle"),
icon: (
<ArrowheadTriangleIcon theme={appState.theme} flip={!isRTL} />
),
keyBinding: "t",
},
]}
value={getFormValue<Arrowhead | null>(
elements,
@ -778,6 +1029,14 @@ export const actionChangeArrowhead = register({
keyBinding: "r",
icon: <ArrowheadDotIcon theme={appState.theme} flip={isRTL} />,
},
{
value: "triangle",
text: t("labels.arrowhead_triangle"),
icon: (
<ArrowheadTriangleIcon theme={appState.theme} flip={isRTL} />
),
keyBinding: "t",
},
]}
value={getFormValue<Arrowhead | null>(
elements,

View File

@ -1,25 +1,44 @@
import { KEYS } from "../keys";
import { register } from "./register";
import { selectGroupsForSelectedElements } from "../groups";
import { getNonDeletedElements } from "../element";
import { getNonDeletedElements, isTextElement } from "../element";
import { ExcalidrawElement } from "../element/types";
import { isLinearElement } from "../element/typeChecks";
import { LinearElementEditor } from "../element/linearElementEditor";
export const actionSelectAll = register({
name: "selectAll",
perform: (elements, appState) => {
trackEvent: { category: "canvas" },
perform: (elements, appState, value, app) => {
if (appState.editingLinearElement) {
return false;
}
const selectedElementIds = elements.reduce(
(map: Record<ExcalidrawElement["id"], true>, element) => {
if (
!element.isDeleted &&
!(isTextElement(element) && element.containerId) &&
!element.locked
) {
map[element.id] = true;
}
return map;
},
{},
);
return {
appState: selectGroupsForSelectedElements(
{
...appState,
selectedLinearElement:
// single linear element selected
Object.keys(selectedElementIds).length === 1 &&
isLinearElement(elements[0])
? new LinearElementEditor(elements[0], app.scene)
: null,
editingGroupId: null,
selectedElementIds: elements.reduce((map, element) => {
if (!element.isDeleted) {
map[element.id] = true;
}
return map;
}, {} as any),
selectedElementIds,
},
getNonDeletedElements(elements),
),

View File

@ -0,0 +1,71 @@
import ExcalidrawApp from "../excalidraw-app";
import { t } from "../i18n";
import { CODES } from "../keys";
import { API } from "../tests/helpers/api";
import { Keyboard, Pointer, UI } from "../tests/helpers/ui";
import { fireEvent, render, screen } from "../tests/test-utils";
import { copiedStyles } from "./actionStyles";
const { h } = window;
const mouse = new Pointer("mouse");
describe("actionStyles", () => {
beforeEach(async () => {
await render(<ExcalidrawApp />);
});
it("should copy & paste styles via keyboard", () => {
UI.clickTool("rectangle");
mouse.down(10, 10);
mouse.up(20, 20);
UI.clickTool("rectangle");
mouse.down(10, 10);
mouse.up(20, 20);
// Change some styles of second rectangle
UI.clickLabeledElement("Stroke");
UI.clickLabeledElement(t("colors.c92a2a"));
UI.clickLabeledElement("Background");
UI.clickLabeledElement(t("colors.e64980"));
// Fill style
fireEvent.click(screen.getByTitle("Cross-hatch"));
// Stroke width
fireEvent.click(screen.getByTitle("Bold"));
// Stroke style
fireEvent.click(screen.getByTitle("Dotted"));
// Roughness
fireEvent.click(screen.getByTitle("Cartoonist"));
// Opacity
fireEvent.change(screen.getByLabelText("Opacity"), {
target: { value: "60" },
});
mouse.reset();
API.setSelectedElements([h.elements[1]]);
Keyboard.withModifierKeys({ ctrl: true, alt: true }, () => {
Keyboard.codeDown(CODES.C);
});
const secondRect = JSON.parse(copiedStyles)[0];
expect(secondRect.id).toBe(h.elements[1].id);
mouse.reset();
// Paste styles to first rectangle
API.setSelectedElements([h.elements[0]]);
Keyboard.withModifierKeys({ ctrl: true, alt: true }, () => {
Keyboard.codeDown(CODES.V);
});
const firstRect = API.getSelectedElement();
expect(firstRect.id).toBe(h.elements[0].id);
expect(firstRect.strokeColor).toBe("#c92a2a");
expect(firstRect.backgroundColor).toBe("#e64980");
expect(firstRect.fillStyle).toBe("cross-hatch");
expect(firstRect.strokeWidth).toBe(2); // Bold: 2
expect(firstRect.strokeStyle).toBe("dotted");
expect(firstRect.roughness).toBe(2); // Cartoonist: 2
expect(firstRect.opacity).toBe(60);
});
});

View File

@ -6,27 +6,37 @@ import {
import { CODES, KEYS } from "../keys";
import { t } from "../i18n";
import { register } from "./register";
import { mutateElement, newElementWith } from "../element/mutateElement";
import { newElementWith } from "../element/mutateElement";
import {
DEFAULT_FONT_SIZE,
DEFAULT_FONT_FAMILY,
DEFAULT_TEXT_ALIGN,
} from "../constants";
import { getBoundTextElement } from "../element/textElement";
import { hasBoundTextElement } from "../element/typeChecks";
import { getSelectedElements } from "../scene";
// `copiedStyles` is exported only for tests.
export let copiedStyles: string = "{}";
export const actionCopyStyles = register({
name: "copyStyles",
trackEvent: { category: "element" },
perform: (elements, appState) => {
const elementsCopied = [];
const element = elements.find((el) => appState.selectedElementIds[el.id]);
elementsCopied.push(element);
if (element && hasBoundTextElement(element)) {
const boundTextElement = getBoundTextElement(element);
elementsCopied.push(boundTextElement);
}
if (element) {
copiedStyles = JSON.stringify(element);
copiedStyles = JSON.stringify(elementsCopied);
}
return {
appState: {
...appState,
toastMessage: t("toast.copyStyles"),
toast: { message: t("toast.copyStyles") },
},
commitToHistory: false,
};
@ -38,31 +48,64 @@ export const actionCopyStyles = register({
export const actionPasteStyles = register({
name: "pasteStyles",
trackEvent: { category: "element" },
perform: (elements, appState) => {
const pastedElement = JSON.parse(copiedStyles);
const elementsCopied = JSON.parse(copiedStyles);
const pastedElement = elementsCopied[0];
const boundTextElement = elementsCopied[1];
if (!isExcalidrawElement(pastedElement)) {
return { elements, commitToHistory: false };
}
const selectedElements = getSelectedElements(elements, appState, true);
const selectedElementIds = selectedElements.map((element) => element.id);
return {
elements: elements.map((element) => {
if (appState.selectedElementIds[element.id]) {
const newElement = newElementWith(element, {
backgroundColor: pastedElement?.backgroundColor,
strokeWidth: pastedElement?.strokeWidth,
strokeColor: pastedElement?.strokeColor,
strokeStyle: pastedElement?.strokeStyle,
fillStyle: pastedElement?.fillStyle,
opacity: pastedElement?.opacity,
roughness: pastedElement?.roughness,
});
if (isTextElement(newElement)) {
mutateElement(newElement, {
fontSize: pastedElement?.fontSize || DEFAULT_FONT_SIZE,
fontFamily: pastedElement?.fontFamily || DEFAULT_FONT_FAMILY,
textAlign: pastedElement?.textAlign || DEFAULT_TEXT_ALIGN,
});
redrawTextBoundingBox(newElement);
if (selectedElementIds.includes(element.id)) {
let elementStylesToCopyFrom = pastedElement;
if (isTextElement(element) && element.containerId) {
elementStylesToCopyFrom = boundTextElement;
}
if (!elementStylesToCopyFrom) {
return element;
}
let newElement = newElementWith(element, {
backgroundColor: elementStylesToCopyFrom?.backgroundColor,
strokeWidth: elementStylesToCopyFrom?.strokeWidth,
strokeColor: elementStylesToCopyFrom?.strokeColor,
strokeStyle: elementStylesToCopyFrom?.strokeStyle,
fillStyle: elementStylesToCopyFrom?.fillStyle,
opacity: elementStylesToCopyFrom?.opacity,
roughness: elementStylesToCopyFrom?.roughness,
});
if (isTextElement(newElement)) {
newElement = newElementWith(newElement, {
fontSize: elementStylesToCopyFrom?.fontSize || DEFAULT_FONT_SIZE,
fontFamily:
elementStylesToCopyFrom?.fontFamily || DEFAULT_FONT_FAMILY,
textAlign:
elementStylesToCopyFrom?.textAlign || DEFAULT_TEXT_ALIGN,
});
let container = null;
if (newElement.containerId) {
container =
selectedElements.find(
(element) =>
isTextElement(newElement) &&
element.id === newElement.containerId,
) || null;
}
redrawTextBoundingBox(newElement, container);
}
if (newElement.type === "arrow") {
newElement = newElementWith(newElement, {
startArrowhead: elementStylesToCopyFrom.startArrowhead,
endArrowhead: elementStylesToCopyFrom.endArrowhead,
});
}
return newElement;
}
return element;

View File

@ -2,12 +2,14 @@ import { CODES, KEYS } from "../keys";
import { register } from "./register";
import { GRID_SIZE } from "../constants";
import { AppState } from "../types";
import { trackEvent } from "../analytics";
export const actionToggleGridMode = register({
name: "gridMode",
trackEvent: {
category: "canvas",
predicate: (appState) => !appState.gridSize,
},
perform(elements, appState) {
trackEvent("view", "mode", "grid");
return {
appState: {
...appState,

View File

@ -0,0 +1,66 @@
import { newElementWith } from "../element/mutateElement";
import { ExcalidrawElement } from "../element/types";
import { KEYS } from "../keys";
import { getSelectedElements } from "../scene";
import { arrayToMap } from "../utils";
import { register } from "./register";
export const actionToggleLock = register({
name: "toggleLock",
trackEvent: { category: "element" },
perform: (elements, appState) => {
const selectedElements = getSelectedElements(elements, appState, true);
if (!selectedElements.length) {
return false;
}
const operation = getOperation(selectedElements);
const selectedElementsMap = arrayToMap(selectedElements);
const lock = operation === "lock";
return {
elements: elements.map((element) => {
if (!selectedElementsMap.has(element.id)) {
return element;
}
return newElementWith(element, { locked: lock });
}),
appState: {
...appState,
selectedLinearElement: lock ? null : appState.selectedLinearElement,
},
commitToHistory: true,
};
},
contextItemLabel: (elements, appState) => {
const selected = getSelectedElements(elements, appState, false);
if (selected.length === 1) {
return selected[0].locked
? "labels.elementLock.unlock"
: "labels.elementLock.lock";
}
if (selected.length > 1) {
return getOperation(selected) === "lock"
? "labels.elementLock.lockAll"
: "labels.elementLock.unlockAll";
}
throw new Error(
"Unexpected zero elements to lock/unlock. This should never happen.",
);
},
keyTest: (event, appState, elements) => {
return (
event.key.toLocaleLowerCase() === KEYS.L &&
event[KEYS.CTRL_OR_CMD] &&
event.shiftKey &&
getSelectedElements(elements, appState, false).length > 0
);
},
});
const getOperation = (
elements: readonly ExcalidrawElement[],
): "lock" | "unlock" => (elements.some((el) => !el.locked) ? "lock" : "unlock");

View File

@ -3,6 +3,7 @@ import { CODES, KEYS } from "../keys";
export const actionToggleStats = register({
name: "stats",
trackEvent: { category: "menu" },
perform(elements, appState) {
return {
appState: {

View File

@ -1,11 +1,13 @@
import { CODES, KEYS } from "../keys";
import { register } from "./register";
import { trackEvent } from "../analytics";
export const actionToggleViewMode = register({
name: "viewMode",
trackEvent: {
category: "canvas",
predicate: (appState) => !appState.viewModeEnabled,
},
perform(elements, appState) {
trackEvent("view", "mode", "view");
return {
appState: {
...appState,

View File

@ -1,12 +1,13 @@
import { CODES, KEYS } from "../keys";
import { register } from "./register";
import { trackEvent } from "../analytics";
export const actionToggleZenMode = register({
name: "zenMode",
trackEvent: {
category: "canvas",
predicate: (appState) => !appState.zenModeEnabled,
},
perform(elements, appState) {
trackEvent("view", "mode", "zen");
return {
appState: {
...appState,

View File

@ -18,6 +18,7 @@ import {
export const actionSendBackward = register({
name: "sendBackward",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
elements: moveOneLeft(elements, appState),
@ -45,6 +46,7 @@ export const actionSendBackward = register({
export const actionBringForward = register({
name: "bringForward",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
elements: moveOneRight(elements, appState),
@ -72,6 +74,7 @@ export const actionBringForward = register({
export const actionSendToBack = register({
name: "sendToBack",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
elements: moveAllLeft(elements, appState),
@ -106,6 +109,8 @@ export const actionSendToBack = register({
export const actionBringToFront = register({
name: "bringToFront",
trackEvent: { category: "element" },
perform: (elements, appState) => {
return {
elements: moveAllRight(elements, appState),

View File

@ -17,6 +17,7 @@ export {
actionChangeFontSize,
actionChangeFontFamily,
actionChangeTextAlign,
actionChangeVerticalAlign,
} from "./actionProperties";
export {
@ -74,9 +75,13 @@ export {
actionCut,
actionCopyAsPng,
actionCopyAsSvg,
copyText,
} from "./actionClipboard";
export { actionToggleGridMode } from "./actionToggleGridMode";
export { actionToggleZenMode } from "./actionToggleZenMode";
export { actionToggleStats } from "./actionToggleStats";
export { actionUnbindText, actionBindText } from "./actionBoundText";
export { actionLink } from "../element/Hyperlink";
export { actionToggleLock } from "./actionToggleLock";

View File

@ -1,40 +1,59 @@
import React from "react";
import {
Action,
ActionsManagerInterface,
UpdaterFn,
ActionName,
ActionResult,
PanelComponentProps,
ActionSource,
} from "./types";
import { ExcalidrawElement } from "../element/types";
import { AppProps, AppState } from "../types";
import { AppClassProperties, AppState } from "../types";
import { MODES } from "../constants";
import Library from "../data/library";
import { trackEvent } from "../analytics";
// This is the <App> component, but for now we don't care about anything but its
// `canvas` state.
type App = {
canvas: HTMLCanvasElement | null;
focusContainer: () => void;
props: AppProps;
library: Library;
const trackAction = (
action: Action,
source: ActionSource,
appState: Readonly<AppState>,
elements: readonly ExcalidrawElement[],
app: AppClassProperties,
value: any,
) => {
if (action.trackEvent) {
try {
if (typeof action.trackEvent === "object") {
const shouldTrack = action.trackEvent.predicate
? action.trackEvent.predicate(appState, elements, value)
: true;
if (shouldTrack) {
trackEvent(
action.trackEvent.category,
action.trackEvent.action || action.name,
`${source} (${app.device.isMobile ? "mobile" : "desktop"})`,
);
}
}
} catch (error) {
console.error("error while logging action:", error);
}
}
};
export class ActionManager implements ActionsManagerInterface {
actions = {} as ActionsManagerInterface["actions"];
export class ActionManager {
actions = {} as Record<ActionName, Action>;
updater: (actionResult: ActionResult | Promise<ActionResult>) => void;
getAppState: () => Readonly<AppState>;
getElementsIncludingDeleted: () => readonly ExcalidrawElement[];
app: App;
app: AppClassProperties;
constructor(
updater: UpdaterFn,
getAppState: () => AppState,
getElementsIncludingDeleted: () => readonly ExcalidrawElement[],
app: App,
app: AppClassProperties,
) {
this.updater = (actionResult) => {
if (actionResult && "then" in actionResult) {
@ -75,9 +94,15 @@ export class ActionManager implements ActionsManagerInterface {
),
);
if (data.length === 0) {
if (data.length !== 1) {
if (data.length > 1) {
console.warn("Canceling as multiple actions match this shortcut", data);
}
return false;
}
const action = data[0];
const { viewModeEnabled } = this.getAppState();
if (viewModeEnabled) {
if (!Object.values(MODES).includes(data[0].name)) {
@ -85,27 +110,26 @@ export class ActionManager implements ActionsManagerInterface {
}
}
const elements = this.getElementsIncludingDeleted();
const appState = this.getAppState();
const value = null;
trackAction(action, "keyboard", appState, elements, this.app, null);
event.preventDefault();
this.updater(
data[0].perform(
this.getElementsIncludingDeleted(),
this.getAppState(),
null,
this.app,
),
);
event.stopPropagation();
this.updater(data[0].perform(elements, appState, value, this.app));
return true;
}
executeAction(action: Action) {
this.updater(
action.perform(
this.getElementsIncludingDeleted(),
this.getAppState(),
null,
this.app,
),
);
executeAction(action: Action, source: ActionSource = "api") {
const elements = this.getElementsIncludingDeleted();
const appState = this.getAppState();
const value = null;
trackAction(action, source, appState, elements, this.app, value);
this.updater(action.perform(elements, appState, value, this.app));
}
/**
@ -123,7 +147,12 @@ export class ActionManager implements ActionsManagerInterface {
) {
const action = this.actions[name];
const PanelComponent = action.PanelComponent!;
PanelComponent.displayName = "PanelComponent";
const elements = this.getElementsIncludingDeleted();
const appState = this.getAppState();
const updateData = (formState?: any) => {
trackAction(action, "ui", appState, elements, this.app, formState);
this.updater(
action.perform(
this.getElementsIncludingDeleted(),

View File

@ -2,7 +2,9 @@ import { Action } from "./types";
export let actions: readonly Action[] = [];
export const register = (action: Action): Action => {
export const register = <T extends Action>(action: T) => {
actions = actions.concat(action);
return action;
return action as T & {
keyTest?: unknown extends T["keyTest"] ? never : T["keyTest"];
};
};

View File

@ -1,8 +1,10 @@
import { t } from "../i18n";
import { isDarwin } from "../keys";
import { getShortcutKey } from "../utils";
import { ActionName } from "./types";
export type ShortcutName =
export type ShortcutName = SubtypeOf<
ActionName,
| "cut"
| "copy"
| "paste"
@ -25,7 +27,10 @@ export type ShortcutName =
| "addToLibrary"
| "viewMode"
| "flipHorizontal"
| "flipVertical";
| "flipVertical"
| "hyperlink"
| "toggleLock"
>;
const shortcutMap: Record<ShortcutName, string[]> = {
cut: [getShortcutKey("CtrlOrCmd+X")],
@ -62,10 +67,12 @@ const shortcutMap: Record<ShortcutName, string[]> = {
flipHorizontal: [getShortcutKey("Shift+H")],
flipVertical: [getShortcutKey("Shift+V")],
viewMode: [getShortcutKey("Alt+R")],
hyperlink: [getShortcutKey("CtrlOrCmd+K")],
toggleLock: [getShortcutKey("CtrlOrCmd+Shift+L")],
};
export const getShortcutFromShortcutName = (name: ShortcutName) => {
const shortcuts = shortcutMap[name];
// if multiple shortcuts availiable, take the first one
// if multiple shortcuts available, take the first one
return shortcuts && shortcuts.length > 0 ? shortcuts[0] : "";
};

View File

@ -1,8 +1,13 @@
import React from "react";
import { ExcalidrawElement } from "../element/types";
import { AppState, ExcalidrawProps } from "../types";
import Library from "../data/library";
import { ToolButtonSize } from "../components/ToolButton";
import {
AppClassProperties,
AppState,
ExcalidrawProps,
BinaryFiles,
} from "../types";
export type ActionSource = "ui" | "keyboard" | "contextMenu" | "api";
/** if false, the action should be prevented */
export type ActionResult =
@ -12,22 +17,18 @@ export type ActionResult =
AppState,
"offsetTop" | "offsetLeft" | "width" | "height"
> | null;
files?: BinaryFiles | null;
commitToHistory: boolean;
syncHistory?: boolean;
replaceFiles?: boolean;
}
| false;
type AppAPI = {
canvas: HTMLCanvasElement | null;
focusContainer(): void;
library: Library;
};
type ActionFn = (
elements: readonly ExcalidrawElement[],
appState: Readonly<AppState>,
formData: any,
app: AppAPI,
app: AppClassProperties,
) => ActionResult | Promise<ActionResult>;
export type UpdaterFn = (res: ActionResult) => void;
@ -39,6 +40,7 @@ export type ActionName =
| "paste"
| "copyAsPng"
| "copyAsSvg"
| "copyText"
| "sendBackward"
| "bringForward"
| "sendToBack"
@ -82,6 +84,7 @@ export type ActionName =
| "zoomToSelection"
| "changeFontFamily"
| "changeTextAlign"
| "changeVerticalAlign"
| "toggleFullScreen"
| "toggleShortcuts"
| "group"
@ -101,14 +104,21 @@ export type ActionName =
| "flipVertical"
| "viewMode"
| "exportWithDarkMode"
| "toggleTheme";
| "toggleTheme"
| "increaseFontSize"
| "decreaseFontSize"
| "unbindText"
| "hyperlink"
| "eraser"
| "bindText"
| "toggleLock";
export type PanelComponentProps = {
elements: readonly ExcalidrawElement[];
appState: AppState;
updateData: (formData?: any) => void;
appProps: ExcalidrawProps;
data?: Partial<{ id: string; size: ToolButtonSize }>;
data?: Record<string, any>;
};
export interface Action {
@ -121,18 +131,34 @@ export interface Action {
appState: AppState,
elements: readonly ExcalidrawElement[],
) => boolean;
contextItemLabel?: string;
contextItemLabel?:
| string
| ((
elements: readonly ExcalidrawElement[],
appState: Readonly<AppState>,
) => string);
contextItemPredicate?: (
elements: readonly ExcalidrawElement[],
appState: AppState,
) => boolean;
checked?: (appState: Readonly<AppState>) => boolean;
}
export interface ActionsManagerInterface {
actions: Record<ActionName, Action>;
registerAction: (action: Action) => void;
handleKeyDown: (event: React.KeyboardEvent | KeyboardEvent) => boolean;
renderAction: (name: ActionName) => React.ReactElement | null;
executeAction: (action: Action) => void;
trackEvent:
| false
| {
category:
| "toolbar"
| "element"
| "canvas"
| "export"
| "history"
| "menu"
| "collab"
| "hyperlink";
action?: string;
predicate?: (
appState: Readonly<AppState>,
elements: readonly ExcalidrawElement[],
value: any,
) => boolean;
};
}

View File

@ -1,13 +1,7 @@
import { ExcalidrawElement } from "./element/types";
import { newElementWith } from "./element/mutateElement";
import { getCommonBounds } from "./element";
interface Box {
minX: number;
minY: number;
maxX: number;
maxY: number;
}
import { Box, getCommonBoundingBox } from "./element/bounds";
import { getMaximumGroups } from "./groups";
export interface Alignment {
position: "start" | "center" | "end";
@ -37,28 +31,6 @@ export const alignElements = (
});
};
export const getMaximumGroups = (
elements: ExcalidrawElement[],
): ExcalidrawElement[][] => {
const groups: Map<String, ExcalidrawElement[]> = new Map<
String,
ExcalidrawElement[]
>();
elements.forEach((element: ExcalidrawElement) => {
const groupId =
element.groupIds.length === 0
? element.id
: element.groupIds[element.groupIds.length - 1];
const currentGroupMembers = groups.get(groupId) || [];
groups.set(groupId, [...currentGroupMembers, element]);
});
return Array.from(groups.values());
};
const calculateTranslation = (
group: ExcalidrawElement[],
selectionBoundingBox: Box,
@ -88,8 +60,3 @@ const calculateTranslation = (
(groupBoundingBox[min] + groupBoundingBox[max]) / 2,
};
};
const getCommonBoundingBox = (elements: ExcalidrawElement[]): Box => {
const [minX, minY, maxX, maxY] = getCommonBounds(elements);
return { minX, minY, maxX, maxY };
};

View File

@ -3,16 +3,20 @@ export const trackEvent =
process.env?.REACT_APP_GOOGLE_ANALYTICS_ID &&
typeof window !== "undefined" &&
window.gtag
? (category: string, name: string, label?: string, value?: number) => {
window.gtag("event", name, {
event_category: category,
event_label: label,
value,
});
? (category: string, action: string, label?: string, value?: number) => {
try {
window.gtag("event", action, {
event_category: category,
event_label: label,
value,
});
} catch (error) {
console.error("error logging to ga", error);
}
}
: typeof process !== "undefined" && process.env?.JEST_WORKER_ID
? (category: string, name: string, label?: string, value?: number) => {}
: (category: string, name: string, label?: string, value?: number) => {
? (category: string, action: string, label?: string, value?: number) => {}
: (category: string, action: string, label?: string, value?: number) => {
// Uncomment the next line to track locally
// console.info("Track Event", category, name, label, value);
// console.log("Track Event", { category, action, label, value });
};

View File

@ -4,6 +4,7 @@ import {
DEFAULT_FONT_SIZE,
DEFAULT_TEXT_ALIGN,
EXPORT_SCALES,
THEME,
} from "./constants";
import { t } from "./i18n";
import { AppState, NormalizedZoomValue } from "./types";
@ -18,7 +19,7 @@ export const getDefaultAppState = (): Omit<
"offsetTop" | "offsetLeft" | "width" | "height"
> => {
return {
theme: "light",
theme: THEME.LIGHT,
collaborators: new Map(),
currentChartType: "bar",
currentItemBackgroundColor: "transparent",
@ -40,8 +41,14 @@ export const getDefaultAppState = (): Omit<
editingElement: null,
editingGroupId: null,
editingLinearElement: null,
elementLocked: false,
elementType: "selection",
activeTool: {
type: "selection",
customType: null,
locked: false,
lastActiveToolBeforeEraser: null,
},
penMode: false,
penDetected: false,
errorMessage: null,
exportBackground: true,
exportScale: defaultExportScale,
@ -51,6 +58,7 @@ export const getDefaultAppState = (): Omit<
gridSize: null,
isBindingEnabled: true,
isLibraryOpen: false,
isLibraryMenuDocked: false,
isLoading: false,
isResizing: false,
isRotating: false,
@ -73,11 +81,16 @@ export const getDefaultAppState = (): Omit<
showStats: false,
startBoundElement: null,
suggestedBindings: [],
toastMessage: null,
toast: null,
viewBackgroundColor: oc.white,
zenModeEnabled: false,
zoom: { value: 1 as NormalizedZoomValue, translation: { x: 0, y: 0 } },
zoom: {
value: 1 as NormalizedZoomValue,
},
viewModeEnabled: false,
pendingImageElementId: null,
showHyperlinkPopup: false,
selectedLinearElement: null,
};
};
@ -91,78 +104,90 @@ const APP_STATE_STORAGE_CONF = (<
browser: boolean;
/** whether to keep when exporting to file/database */
export: boolean;
/** server (shareLink/collab/...) */
server: boolean;
},
T extends Record<keyof AppState, Values>
>(
config: { [K in keyof T]: K extends keyof AppState ? T[K] : never },
) => config)({
theme: { browser: true, export: false },
collaborators: { browser: false, export: false },
currentChartType: { browser: true, export: false },
currentItemBackgroundColor: { browser: true, export: false },
currentItemEndArrowhead: { browser: true, export: false },
currentItemFillStyle: { browser: true, export: false },
currentItemFontFamily: { browser: true, export: false },
currentItemFontSize: { browser: true, export: false },
currentItemLinearStrokeSharpness: { browser: true, export: false },
currentItemOpacity: { browser: true, export: false },
currentItemRoughness: { browser: true, export: false },
currentItemStartArrowhead: { browser: true, export: false },
currentItemStrokeColor: { browser: true, export: false },
currentItemStrokeSharpness: { browser: true, export: false },
currentItemStrokeStyle: { browser: true, export: false },
currentItemStrokeWidth: { browser: true, export: false },
currentItemTextAlign: { browser: true, export: false },
cursorButton: { browser: true, export: false },
draggingElement: { browser: false, export: false },
editingElement: { browser: false, export: false },
editingGroupId: { browser: true, export: false },
editingLinearElement: { browser: false, export: false },
elementLocked: { browser: true, export: false },
elementType: { browser: true, export: false },
errorMessage: { browser: false, export: false },
exportBackground: { browser: true, export: false },
exportEmbedScene: { browser: true, export: false },
exportScale: { browser: true, export: false },
exportWithDarkMode: { browser: true, export: false },
fileHandle: { browser: false, export: false },
gridSize: { browser: true, export: true },
height: { browser: false, export: false },
isBindingEnabled: { browser: false, export: false },
isLibraryOpen: { browser: false, export: false },
isLoading: { browser: false, export: false },
isResizing: { browser: false, export: false },
isRotating: { browser: false, export: false },
lastPointerDownWith: { browser: true, export: false },
multiElement: { browser: false, export: false },
name: { browser: true, export: false },
offsetLeft: { browser: false, export: false },
offsetTop: { browser: false, export: false },
openMenu: { browser: true, export: false },
openPopup: { browser: false, export: false },
pasteDialog: { browser: false, export: false },
previousSelectedElementIds: { browser: true, export: false },
resizingElement: { browser: false, export: false },
scrolledOutside: { browser: true, export: false },
scrollX: { browser: true, export: false },
scrollY: { browser: true, export: false },
selectedElementIds: { browser: true, export: false },
selectedGroupIds: { browser: true, export: false },
selectionElement: { browser: false, export: false },
shouldCacheIgnoreZoom: { browser: true, export: false },
showHelpDialog: { browser: false, export: false },
showStats: { browser: true, export: false },
startBoundElement: { browser: false, export: false },
suggestedBindings: { browser: false, export: false },
toastMessage: { browser: false, export: false },
viewBackgroundColor: { browser: true, export: true },
width: { browser: false, export: false },
zenModeEnabled: { browser: true, export: false },
zoom: { browser: true, export: false },
viewModeEnabled: { browser: false, export: false },
T extends Record<keyof AppState, Values>,
>(config: { [K in keyof T]: K extends keyof AppState ? T[K] : never }) =>
config)({
theme: { browser: true, export: false, server: false },
collaborators: { browser: false, export: false, server: false },
currentChartType: { browser: true, export: false, server: false },
currentItemBackgroundColor: { browser: true, export: false, server: false },
currentItemEndArrowhead: { browser: true, export: false, server: false },
currentItemFillStyle: { browser: true, export: false, server: false },
currentItemFontFamily: { browser: true, export: false, server: false },
currentItemFontSize: { browser: true, export: false, server: false },
currentItemLinearStrokeSharpness: {
browser: true,
export: false,
server: false,
},
currentItemOpacity: { browser: true, export: false, server: false },
currentItemRoughness: { browser: true, export: false, server: false },
currentItemStartArrowhead: { browser: true, export: false, server: false },
currentItemStrokeColor: { browser: true, export: false, server: false },
currentItemStrokeSharpness: { browser: true, export: false, server: false },
currentItemStrokeStyle: { browser: true, export: false, server: false },
currentItemStrokeWidth: { browser: true, export: false, server: false },
currentItemTextAlign: { browser: true, export: false, server: false },
cursorButton: { browser: true, export: false, server: false },
draggingElement: { browser: false, export: false, server: false },
editingElement: { browser: false, export: false, server: false },
editingGroupId: { browser: true, export: false, server: false },
editingLinearElement: { browser: false, export: false, server: false },
activeTool: { browser: true, export: false, server: false },
penMode: { browser: true, export: false, server: false },
penDetected: { browser: true, export: false, server: false },
errorMessage: { browser: false, export: false, server: false },
exportBackground: { browser: true, export: false, server: false },
exportEmbedScene: { browser: true, export: false, server: false },
exportScale: { browser: true, export: false, server: false },
exportWithDarkMode: { browser: true, export: false, server: false },
fileHandle: { browser: false, export: false, server: false },
gridSize: { browser: true, export: true, server: true },
height: { browser: false, export: false, server: false },
isBindingEnabled: { browser: false, export: false, server: false },
isLibraryOpen: { browser: true, export: false, server: false },
isLibraryMenuDocked: { browser: true, export: false, server: false },
isLoading: { browser: false, export: false, server: false },
isResizing: { browser: false, export: false, server: false },
isRotating: { browser: false, export: false, server: false },
lastPointerDownWith: { browser: true, export: false, server: false },
multiElement: { browser: false, export: false, server: false },
name: { browser: true, export: false, server: false },
offsetLeft: { browser: false, export: false, server: false },
offsetTop: { browser: false, export: false, server: false },
openMenu: { browser: true, export: false, server: false },
openPopup: { browser: false, export: false, server: false },
pasteDialog: { browser: false, export: false, server: false },
previousSelectedElementIds: { browser: true, export: false, server: false },
resizingElement: { browser: false, export: false, server: false },
scrolledOutside: { browser: true, export: false, server: false },
scrollX: { browser: true, export: false, server: false },
scrollY: { browser: true, export: false, server: false },
selectedElementIds: { browser: true, export: false, server: false },
selectedGroupIds: { browser: true, export: false, server: false },
selectionElement: { browser: false, export: false, server: false },
shouldCacheIgnoreZoom: { browser: true, export: false, server: false },
showHelpDialog: { browser: false, export: false, server: false },
showStats: { browser: true, export: false, server: false },
startBoundElement: { browser: false, export: false, server: false },
suggestedBindings: { browser: false, export: false, server: false },
toast: { browser: false, export: false, server: false },
viewBackgroundColor: { browser: true, export: true, server: true },
width: { browser: false, export: false, server: false },
zenModeEnabled: { browser: true, export: false, server: false },
zoom: { browser: true, export: false, server: false },
viewModeEnabled: { browser: false, export: false, server: false },
pendingImageElementId: { browser: false, export: false, server: false },
showHyperlinkPopup: { browser: false, export: false, server: false },
selectedLinearElement: { browser: true, export: false, server: false },
});
const _clearAppStateForStorage = <ExportType extends "export" | "browser">(
const _clearAppStateForStorage = <
ExportType extends "export" | "browser" | "server",
>(
appState: Partial<AppState>,
exportType: ExportType,
) => {
@ -175,8 +200,10 @@ const _clearAppStateForStorage = <ExportType extends "export" | "browser">(
for (const key of Object.keys(appState) as (keyof typeof appState)[]) {
const propConfig = APP_STATE_STORAGE_CONF[key];
if (propConfig?.[exportType]) {
// @ts-ignore see https://github.com/microsoft/TypeScript/issues/31445
stateForExport[key] = appState[key];
const nextValue = appState[key];
// https://github.com/microsoft/TypeScript/issues/31445
(stateForExport as any)[key] = nextValue;
}
}
return stateForExport;
@ -189,3 +216,13 @@ export const clearAppStateForLocalStorage = (appState: Partial<AppState>) => {
export const cleanAppStateForExport = (appState: Partial<AppState>) => {
return _clearAppStateForStorage(appState, "export");
};
export const clearAppStateForDatabase = (appState: Partial<AppState>) => {
return _clearAppStateForStorage(appState, "server");
};
export const isEraserActive = ({
activeTool,
}: {
activeTool: AppState["activeTool"];
}) => activeTool.type === "eraser";

121
src/charts.test.ts Normal file
View File

@ -0,0 +1,121 @@
import {
Spreadsheet,
tryParseCells,
tryParseNumber,
VALID_SPREADSHEET,
} from "./charts";
describe("charts", () => {
describe("tryParseNumber", () => {
it.each<[string, number]>([
["1", 1],
["0", 0],
["-1", -1],
["0.1", 0.1],
[".1", 0.1],
["1.", 1],
["424.", 424],
["$1", 1],
["-.1", -0.1],
["-$1", -1],
["$-1", -1],
])("should correctly identify %s as numbers", (given, expected) => {
expect(tryParseNumber(given)).toEqual(expected);
});
it.each<[string]>([["a"], ["$"], ["$a"], ["-$a"]])(
"should correctly identify %s as not a number",
(given) => {
expect(tryParseNumber(given)).toBeNull();
},
);
});
describe("tryParseCells", () => {
it("Successfully parses a spreadsheet", () => {
const spreadsheet = [
["time", "value"],
["01:00", "61"],
["02:00", "-60"],
["03:00", "85"],
["04:00", "-67"],
["05:00", "54"],
["06:00", "95"],
];
const result = tryParseCells(spreadsheet);
expect(result.type).toBe(VALID_SPREADSHEET);
const { title, labels, values } = (
result as { type: typeof VALID_SPREADSHEET; spreadsheet: Spreadsheet }
).spreadsheet;
expect(title).toEqual("value");
expect(labels).toEqual([
"01:00",
"02:00",
"03:00",
"04:00",
"05:00",
"06:00",
]);
expect(values).toEqual([61, -60, 85, -67, 54, 95]);
});
it("Uses the second column as the label if it is not a number", () => {
const spreadsheet = [
["time", "value"],
["01:00", "61"],
["02:00", "-60"],
["03:00", "85"],
["04:00", "-67"],
["05:00", "54"],
["06:00", "95"],
];
const result = tryParseCells(spreadsheet);
expect(result.type).toBe(VALID_SPREADSHEET);
const { title, labels, values } = (
result as { type: typeof VALID_SPREADSHEET; spreadsheet: Spreadsheet }
).spreadsheet;
expect(title).toEqual("value");
expect(labels).toEqual([
"01:00",
"02:00",
"03:00",
"04:00",
"05:00",
"06:00",
]);
expect(values).toEqual([61, -60, 85, -67, 54, 95]);
});
it("treats the first column as labels if both columns are numbers", () => {
const spreadsheet = [
["time", "value"],
["01", "61"],
["02", "-60"],
["03", "85"],
["04", "-67"],
["05", "54"],
["06", "95"],
];
const result = tryParseCells(spreadsheet);
expect(result.type).toBe(VALID_SPREADSHEET);
const { title, labels, values } = (
result as { type: typeof VALID_SPREADSHEET; spreadsheet: Spreadsheet }
).spreadsheet;
expect(title).toEqual("value");
expect(labels).toEqual(["01", "02", "03", "04", "05", "06"]);
expect(values).toEqual([61, -60, 85, -67, 54, 95]);
});
});
});

View File

@ -1,5 +1,10 @@
import colors from "./colors";
import { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, ENV } from "./constants";
import {
DEFAULT_FONT_FAMILY,
DEFAULT_FONT_SIZE,
ENV,
VERTICAL_ALIGN,
} from "./constants";
import { newElement, newLinearElement, newTextElement } from "./element";
import { NonDeletedExcalidrawElement } from "./element/types";
import { randomId } from "./random";
@ -24,18 +29,24 @@ type ParseSpreadsheetResult =
| { type: typeof NOT_SPREADSHEET; reason: string }
| { type: typeof VALID_SPREADSHEET; spreadsheet: Spreadsheet };
const tryParseNumber = (s: string): number | null => {
const match = /^[$€£¥₩]?([0-9,]+(\.[0-9]+)?)$/.exec(s);
/**
* @private exported for testing
*/
export const tryParseNumber = (s: string): number | null => {
const match = /^([-+]?)[$€£¥₩]?([-+]?)([\d.,]+)[%]?$/.exec(s);
if (!match) {
return null;
}
return parseFloat(match[1].replace(/,/g, ""));
return parseFloat(`${(match[1] || match[2]) + match[3]}`.replace(/,/g, ""));
};
const isNumericColumn = (lines: string[][], columnIndex: number) =>
lines.slice(1).every((line) => tryParseNumber(line[columnIndex]) !== null);
const tryParseCells = (cells: string[][]): ParseSpreadsheetResult => {
/**
* @private exported for testing
*/
export const tryParseCells = (cells: string[][]): ParseSpreadsheetResult => {
const numCols = cells[0].length;
if (numCols > 2) {
@ -66,13 +77,16 @@ const tryParseCells = (cells: string[][]): ParseSpreadsheetResult => {
};
}
const valueColumnIndex = isNumericColumn(cells, 0) ? 0 : 1;
const labelColumnNumeric = isNumericColumn(cells, 0);
const valueColumnNumeric = isNumericColumn(cells, 1);
if (!isNumericColumn(cells, valueColumnIndex)) {
if (!labelColumnNumeric && !valueColumnNumeric) {
return { type: NOT_SPREADSHEET, reason: "Value is not numeric" };
}
const labelColumnIndex = (valueColumnIndex + 1) % 2;
const [labelColumnIndex, valueColumnIndex] = valueColumnNumeric
? [0, 1]
: [1, 0];
const hasHeader = tryParseNumber(cells[0][valueColumnIndex]) === null;
const rows = hasHeader ? cells.slice(1) : cells;
@ -103,7 +117,7 @@ const transposeCells = (cells: string[][]) => {
};
export const tryParseSpreadsheet = (text: string): ParseSpreadsheetResult => {
// Copy/paste from excel, spreadhseets, tsv, csv.
// Copy/paste from excel, spreadsheets, tsv, csv.
// For now we only accept 2 columns with an optional header
// Check for tab separated values
@ -161,7 +175,8 @@ const commonProps = {
strokeSharpness: "sharp",
strokeStyle: "solid",
strokeWidth: 1,
verticalAlign: "middle",
verticalAlign: VERTICAL_ALIGN.MIDDLE,
locked: false,
} as const;
const getChartDimentions = (spreadsheet: Spreadsheet) => {

View File

@ -2,20 +2,23 @@ import {
ExcalidrawElement,
NonDeletedExcalidrawElement,
} from "./element/types";
import { getSelectedElements } from "./scene";
import { AppState } from "./types";
import { AppState, BinaryFiles } from "./types";
import { SVG_EXPORT_TAG } from "./scene/export";
import { tryParseSpreadsheet, Spreadsheet, VALID_SPREADSHEET } from "./charts";
import { EXPORT_DATA_TYPES } from "./constants";
import { EXPORT_DATA_TYPES, MIME_TYPES } from "./constants";
import { isInitializedImageElement } from "./element/typeChecks";
import { isPromiseLike } from "./utils";
type ElementsClipboard = {
type: typeof EXPORT_DATA_TYPES.excalidrawClipboard;
elements: ExcalidrawElement[];
elements: readonly NonDeletedExcalidrawElement[];
files: BinaryFiles | undefined;
};
export interface ClipboardData {
spreadsheet?: Spreadsheet;
elements?: readonly ExcalidrawElement[];
files?: BinaryFiles;
text?: string;
errorMessage?: string;
}
@ -37,7 +40,7 @@ export const probablySupportsClipboardBlob =
const clipboardContainsElements = (
contents: any,
): contents is { elements: ExcalidrawElement[] } => {
): contents is { elements: ExcalidrawElement[]; files?: BinaryFiles } => {
if (
[
EXPORT_DATA_TYPES.excalidraw,
@ -53,17 +56,27 @@ const clipboardContainsElements = (
export const copyToClipboard = async (
elements: readonly NonDeletedExcalidrawElement[],
appState: AppState,
files: BinaryFiles | null,
) => {
// select binded text elements when copying
const contents: ElementsClipboard = {
type: EXPORT_DATA_TYPES.excalidrawClipboard,
elements: getSelectedElements(elements, appState),
elements,
files: files
? elements.reduce((acc, element) => {
if (isInitializedImageElement(element) && files[element.fileId]) {
acc[element.fileId] = files[element.fileId];
}
return acc;
}, {} as BinaryFiles)
: undefined,
};
const json = JSON.stringify(contents);
CLIPBOARD = json;
try {
PREFER_APP_CLIPBOARD = false;
await copyTextToSystemClipboard(json);
} catch (error) {
} catch (error: any) {
PREFER_APP_CLIPBOARD = true;
console.error(error);
}
@ -76,7 +89,7 @@ const getAppClipboard = (): Partial<ElementsClipboard> => {
try {
return JSON.parse(CLIPBOARD);
} catch (error) {
} catch (error: any) {
console.error(error);
return {};
}
@ -112,7 +125,7 @@ const getSystemClipboard = async (
};
/**
* Attemps to parse clipboard. Prefers system clipboard.
* Attempts to parse clipboard. Prefers system clipboard.
*/
export const parseClipboard = async (
event: ClipboardEvent | null,
@ -138,7 +151,10 @@ export const parseClipboard = async (
try {
const systemClipboardData = JSON.parse(systemClipboard);
if (clipboardContainsElements(systemClipboardData)) {
return { elements: systemClipboardData.elements };
return {
elements: systemClipboardData.elements,
files: systemClipboardData.files,
};
}
return appClipboardData;
} catch {
@ -151,10 +167,35 @@ export const parseClipboard = async (
}
};
export const copyBlobToClipboardAsPng = async (blob: Blob) => {
await navigator.clipboard.write([
new window.ClipboardItem({ "image/png": blob }),
]);
export const copyBlobToClipboardAsPng = async (blob: Blob | Promise<Blob>) => {
let promise;
try {
// in Safari so far we need to construct the ClipboardItem synchronously
// (i.e. in the same tick) otherwise browser will complain for lack of
// user intent. Using a Promise ClipboardItem constructor solves this.
// https://bugs.webkit.org/show_bug.cgi?id=222262
//
// not await so that we can detect whether the thrown error likely relates
// to a lack of support for the Promise ClipboardItem constructor
promise = navigator.clipboard.write([
new window.ClipboardItem({
[MIME_TYPES.png]: blob,
}),
]);
} catch (error: any) {
// if we're using a Promise ClipboardItem, let's try constructing
// with resolution value instead
if (isPromiseLike(blob)) {
await navigator.clipboard.write([
new window.ClipboardItem({
[MIME_TYPES.png]: await blob,
}),
]);
} else {
throw error;
}
}
await promise;
};
export const copyTextToSystemClipboard = async (text: string | null) => {
@ -165,7 +206,7 @@ export const copyTextToSystemClipboard = async (text: string | null) => {
// not focused
await navigator.clipboard.writeText(text || "");
copied = true;
} catch (error) {
} catch (error: any) {
console.error(error);
}
}
@ -205,7 +246,7 @@ const copyTextViaExecCommand = (text: string) => {
textarea.setSelectionRange(0, textarea.value.length);
success = document.execCommand("copy");
} catch (error) {
} catch (error: any) {
console.error(error);
}

View File

@ -1,9 +1,9 @@
import React from "react";
import { ActionManager } from "../actions/manager";
import { getNonDeletedElements } from "../element";
import { ExcalidrawElement } from "../element/types";
import { ExcalidrawElement, PointerType } from "../element/types";
import { t } from "../i18n";
import { useIsMobile } from "../components/App";
import { useDevice } from "../components/App";
import {
canChangeSharpness,
canHaveArrowheads,
@ -15,54 +15,87 @@ import {
} from "../scene";
import { SHAPES } from "../shapes";
import { AppState, Zoom } from "../types";
import { capitalizeString, isTransparent, setCursorForShape } from "../utils";
import {
capitalizeString,
isTransparent,
updateActiveTool,
setCursorForShape,
} from "../utils";
import Stack from "./Stack";
import { ToolButton } from "./ToolButton";
import { hasStrokeColor } from "../scene/comparisons";
import { trackEvent } from "../analytics";
import { hasBoundTextElement, isBoundToContainer } from "../element/typeChecks";
import clsx from "clsx";
import { actionToggleZenMode } from "../actions";
export const SelectedShapeActions = ({
appState,
elements,
renderAction,
elementType,
}: {
appState: AppState;
elements: readonly ExcalidrawElement[];
renderAction: ActionManager["renderAction"];
elementType: ExcalidrawElement["type"];
}) => {
const targetElements = getTargetElements(
getNonDeletedElements(elements),
appState,
);
let isSingleElementBoundContainer = false;
if (
targetElements.length === 2 &&
(hasBoundTextElement(targetElements[0]) ||
hasBoundTextElement(targetElements[1]))
) {
isSingleElementBoundContainer = true;
}
const isEditing = Boolean(appState.editingElement);
const isMobile = useIsMobile();
const device = useDevice();
const isRTL = document.documentElement.getAttribute("dir") === "rtl";
const showFillIcons =
hasBackground(elementType) ||
hasBackground(appState.activeTool.type) ||
targetElements.some(
(element) =>
hasBackground(element.type) && !isTransparent(element.backgroundColor),
);
const showChangeBackgroundIcons =
hasBackground(elementType) ||
hasBackground(appState.activeTool.type) ||
targetElements.some((element) => hasBackground(element.type));
const showLinkIcon =
targetElements.length === 1 || isSingleElementBoundContainer;
let commonSelectedType: string | null = targetElements[0]?.type || null;
for (const element of targetElements) {
if (element.type !== commonSelectedType) {
commonSelectedType = null;
break;
}
}
return (
<div className="panelColumn">
{renderAction("changeStrokeColor")}
{((hasStrokeColor(appState.activeTool.type) &&
appState.activeTool.type !== "image" &&
commonSelectedType !== "image") ||
targetElements.some((element) => hasStrokeColor(element.type))) &&
renderAction("changeStrokeColor")}
{showChangeBackgroundIcons && renderAction("changeBackgroundColor")}
{showFillIcons && renderAction("changeFillStyle")}
{(hasStrokeWidth(elementType) ||
{(hasStrokeWidth(appState.activeTool.type) ||
targetElements.some((element) => hasStrokeWidth(element.type))) &&
renderAction("changeStrokeWidth")}
{(elementType === "freedraw" ||
{(appState.activeTool.type === "freedraw" ||
targetElements.some((element) => element.type === "freedraw")) &&
renderAction("changeStrokeShape")}
{(hasStrokeStyle(elementType) ||
{(hasStrokeStyle(appState.activeTool.type) ||
targetElements.some((element) => hasStrokeStyle(element.type))) && (
<>
{renderAction("changeStrokeStyle")}
@ -70,12 +103,12 @@ export const SelectedShapeActions = ({
</>
)}
{(canChangeSharpness(elementType) ||
{(canChangeSharpness(appState.activeTool.type) ||
targetElements.some((element) => canChangeSharpness(element.type))) && (
<>{renderAction("changeSharpness")}</>
)}
{(hasText(elementType) ||
{(hasText(appState.activeTool.type) ||
targetElements.some((element) => hasText(element.type))) && (
<>
{renderAction("changeFontSize")}
@ -86,7 +119,11 @@ export const SelectedShapeActions = ({
</>
)}
{(canHaveArrowheads(elementType) ||
{targetElements.some(
(element) =>
hasBoundTextElement(element) || isBoundToContainer(element),
) && renderAction("changeVerticalAlign")}
{(canHaveArrowheads(appState.activeTool.type) ||
targetElements.some((element) => canHaveArrowheads(element.type))) && (
<>{renderAction("changeArrowhead")}</>
)}
@ -103,7 +140,7 @@ export const SelectedShapeActions = ({
</div>
</fieldset>
{targetElements.length > 1 && (
{targetElements.length > 1 && !isSingleElementBoundContainer && (
<fieldset>
<legend>{t("labels.align")}</legend>
<div className="buttonList">
@ -136,14 +173,15 @@ export const SelectedShapeActions = ({
</div>
</fieldset>
)}
{!isMobile && !isEditing && targetElements.length > 0 && (
{!isEditing && targetElements.length > 0 && (
<fieldset>
<legend>{t("labels.actions")}</legend>
<div className="buttonList">
{renderAction("duplicateSelection")}
{renderAction("deleteSelectedElements")}
{!device.isMobile && renderAction("duplicateSelection")}
{!device.isMobile && renderAction("deleteSelectedElements")}
{renderAction("group")}
{renderAction("ungroup")}
{showLinkIcon && renderAction("hyperlink")}
</div>
</fieldset>
)}
@ -153,41 +191,64 @@ export const SelectedShapeActions = ({
export const ShapesSwitcher = ({
canvas,
elementType,
activeTool,
setAppState,
onImageAction,
appState,
}: {
canvas: HTMLCanvasElement | null;
elementType: ExcalidrawElement["type"];
activeTool: AppState["activeTool"];
setAppState: React.Component<any, AppState>["setState"];
onImageAction: (data: { pointerType: PointerType | null }) => void;
appState: AppState;
}) => (
<>
{SHAPES.map(({ value, icon, key }, index) => {
const label = t(`toolBar.${value}`);
const letter = typeof key === "string" ? key : key[0];
const shortcut = `${capitalizeString(letter)} ${t("helpDialog.or")} ${
index + 1
}`;
const letter = key && (typeof key === "string" ? key : key[0]);
const shortcut = letter
? `${capitalizeString(letter)} ${t("helpDialog.or")} ${index + 1}`
: `${index + 1}`;
return (
<ToolButton
className="Shape"
key={value}
type="radio"
icon={icon}
checked={elementType === value}
checked={activeTool.type === value}
name="editor-current-shape"
title={`${capitalizeString(label)}${shortcut}`}
keyBindingLabel={`${index + 1}`}
aria-label={capitalizeString(label)}
aria-keyshortcuts={shortcut}
data-testid={value}
onChange={() => {
onPointerDown={({ pointerType }) => {
if (!appState.penDetected && pointerType === "pen") {
setAppState({
penDetected: true,
penMode: true,
});
}
}}
onChange={({ pointerType }) => {
if (appState.activeTool.type !== value) {
trackEvent("toolbar", value, "ui");
}
const nextActiveTool = updateActiveTool(appState, {
type: value,
});
setAppState({
elementType: value,
activeTool: nextActiveTool,
multiElement: null,
selectedElementIds: {},
});
setCursorForShape(canvas, value);
setAppState({});
setCursorForShape(canvas, {
...appState,
activeTool: nextActiveTool,
});
if (value === "image") {
onImageAction({ pointerType });
}
}}
/>
);
@ -210,3 +271,45 @@ export const ZoomActions = ({
</Stack.Row>
</Stack.Col>
);
export const UndoRedoActions = ({
renderAction,
className,
}: {
renderAction: ActionManager["renderAction"];
className?: string;
}) => (
<div className={`undo-redo-buttons ${className}`}>
{renderAction("undo", { size: "small" })}
{renderAction("redo", { size: "small" })}
</div>
);
export const ExitZenModeAction = ({
actionManager,
showExitZenModeBtn,
}: {
actionManager: ActionManager;
showExitZenModeBtn: boolean;
}) => (
<button
className={clsx("disable-zen-mode", {
"disable-zen-mode--visible": showExitZenModeBtn,
})}
onClick={() => actionManager.executeAction(actionToggleZenMode)}
>
{t("buttons.exitZenMode")}
</button>
);
export const FinalizeAction = ({
renderAction,
className,
}: {
renderAction: ActionManager["renderAction"];
className?: string;
}) => (
<div className={`finalize-button ${className}`}>
{renderAction("finalize", { size: "small" })}
</div>
);

View File

@ -1,4 +1,3 @@
import React from "react";
import Stack from "../components/Stack";
import { ToolButton } from "../components/ToolButton";
import { save, file } from "../components/icons";

File diff suppressed because it is too large Load Diff

View File

@ -12,5 +12,11 @@
cursor: pointer;
font-size: 0.8rem;
font-weight: 500;
&-img {
width: 100%;
height: 100%;
border-radius: 100%;
}
}
}

View File

@ -1,20 +1,36 @@
import "./Avatar.scss";
import React from "react";
import React, { useState } from "react";
import { getClientInitials } from "../clients";
type AvatarProps = {
children: string;
onClick: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
color: string;
border: string;
name: string;
src?: string;
};
export const Avatar = ({ children, color, border, onClick }: AvatarProps) => (
<div
className="Avatar"
style={{ background: color, border: `1px solid ${border}` }}
onClick={onClick}
>
{children}
</div>
);
export const Avatar = ({ color, border, onClick, name, src }: AvatarProps) => {
const shortName = getClientInitials(name);
const [error, setError] = useState(false);
const loadImg = !error && src;
const style = loadImg
? undefined
: { background: color, border: `1px solid ${border}` };
return (
<div className="Avatar" style={style} onClick={onClick}>
{loadImg ? (
<img
className="Avatar-img"
src={src}
alt={shortName}
referrerPolicy="no-referrer"
onError={() => setError(true)}
/>
) : (
shortName
)}
</div>
);
};

View File

@ -1,4 +1,3 @@
import React from "react";
import clsx from "clsx";
// TODO: It might be "clever" to add option.icon to the existing component <ButtonSelect />
@ -8,7 +7,7 @@ export const ButtonIconSelect = <T extends Object>({
onChange,
group,
}: {
options: { value: T; text: string; icon: JSX.Element }[];
options: { value: T; text: string; icon: JSX.Element; testId?: string }[];
value: T | null;
onChange: (value: T) => void;
group: string;
@ -25,6 +24,7 @@ export const ButtonIconSelect = <T extends Object>({
name={group}
onChange={() => onChange(option.value)}
checked={value === option.value}
data-testid={option.testId}
/>
{option.icon}
</label>

View File

@ -1,4 +1,3 @@
import React from "react";
import clsx from "clsx";
export const ButtonSelect = <T extends Object>({

View File

@ -48,6 +48,10 @@
.ToolIcon__label {
color: $oc-white;
}
.Spinner {
--spinner-color: #fff;
}
}
}
}

View File

@ -3,15 +3,23 @@ import OpenColor from "open-color";
import "./Card.scss";
export const Card: React.FC<{
color: keyof OpenColor;
color: keyof OpenColor | "primary";
children?: React.ReactNode;
}> = ({ children, color }) => {
return (
<div
className="Card"
style={{
["--card-color" as any]: OpenColor[color][7],
["--card-color-darker" as any]: OpenColor[color][8],
["--card-color-darkest" as any]: OpenColor[color][9],
["--card-color" as any]:
color === "primary" ? "var(--color-primary)" : OpenColor[color][7],
["--card-color-darker" as any]:
color === "primary"
? "var(--color-primary-darker)"
: OpenColor[color][8],
["--card-color-darkest" as any]:
color === "primary"
? "var(--color-primary-darkest)"
: OpenColor[color][9],
}}
>
{children}

View File

@ -6,16 +6,20 @@ import "./CheckboxItem.scss";
export const CheckboxItem: React.FC<{
checked: boolean;
onChange: (checked: boolean) => void;
}> = ({ children, checked, onChange }) => {
onChange: (checked: boolean, event: React.MouseEvent) => void;
className?: string;
children?: React.ReactNode;
}> = ({ children, checked, onChange, className }) => {
return (
<div
className={clsx("Checkbox", { "is-checked": checked })}
className={clsx("Checkbox", className, { "is-checked": checked })}
onClick={(event) => {
onChange(!checked);
((event.currentTarget as HTMLDivElement).querySelector(
".Checkbox-box",
) as HTMLButtonElement).focus();
onChange(!checked, event);
(
(event.currentTarget as HTMLDivElement).querySelector(
".Checkbox-box",
) as HTMLButtonElement
).focus();
}}
>
<button className="Checkbox-box" role="checkbox" aria-checked={checked}>

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