Compare commits

...

54 Commits

Author SHA1 Message Date
dwelle f5f4ec7528 remove fileHandle from IDB if user rejects permission 2021-06-13 17:59:18 +02:00
dwelle ba705a099a persist fileHandle to IDB across sessions 2021-06-13 17:59:17 +02:00
Aakansha Doshi 6dee02e320 feat: expose fontfamily and refactor FONT_FAMILY (#3710)
* feat: expose fontfamily and refactor FONT_FAMILY for better readability

* fix

* fix

* fix

* docs

* fix
2021-06-13 21:26:55 +05:30
Arun 74a2f16501 feat: Show active file name when saving to current file (#3733)
* feat: Show active file name when saving to current file

* Make requested changes

* More changes
2021-06-13 21:11:07 +05:30
David Luzar fd4460be37 feat: add hint around text editing (#3708) 2021-06-12 22:58:34 +02:00
dependabot[bot] e82d0493cf chore(deps-dev): bump ts-loader in /src/packages/excalidraw (#3716)
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 8.1.0 to 9.2.3.
- [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/v8.1.0...v9.2.3)

---
updated-dependencies:
- dependency-name: ts-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-06-12 20:03:02 +00:00
dependabot[bot] 083cb4c656 chore(deps-dev): bump ts-loader in /src/packages/utils (#3712)
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 8.1.0 to 9.2.3.
- [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/v8.1.0...v9.2.3)

---
updated-dependencies:
- dependency-name: ts-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-06-13 01:27:54 +05:30
dependabot[bot] d067365c1d chore(deps-dev): bump typescript in /src/packages/excalidraw (#3671)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.2.4 to 4.3.2.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.2.4...v4.3.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-13 01:26:27 +05:30
dependabot[bot] 273cac6b60 chore(deps-dev): bump @babel/plugin-transform-typescript (#3713)
Bumps [@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-typescript) from 7.14.3 to 7.14.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.14.5/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>
2021-06-12 21:48:03 +05:30
dependabot[bot] b9337b8a36 chore(deps-dev): bump @babel/preset-env in /src/packages/utils (#3714)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.14.4 to 7.14.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.14.5/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-06-12 15:41:26 +00:00
dependabot[bot] 0e0025921b chore(deps-dev): bump @babel/plugin-transform-async-to-generator (#3715)
Bumps [@babel/plugin-transform-async-to-generator](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-async-to-generator) from 7.13.0 to 7.14.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.14.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-minor
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-12 15:36:46 +00:00
dependabot[bot] efc01ddab1 chore(deps): bump ws from 7.4.3 to 7.4.6 in /src/packages/excalidraw (#3665)
Bumps [ws](https://github.com/websockets/ws) from 7.4.3 to 7.4.6.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.4.3...7.4.6)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-12 15:34:00 +00:00
dependabot[bot] 7bce22b114 chore(deps-dev): bump webpack in /src/packages/excalidraw (#3670)
Bumps [webpack](https://github.com/webpack/webpack) from 5.37.1 to 5.38.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.37.1...v5.38.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-12 15:31:49 +00:00
dependabot[bot] aab4965bbb chore(deps): bump ws from 7.4.3 to 7.4.6 in /src/packages/utils (#3664)
Bumps [ws](https://github.com/websockets/ws) from 7.4.3 to 7.4.6.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.4.3...7.4.6)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-12 15:30:49 +00:00
dependabot[bot] 486a9a3da8 chore(deps-dev): bump autoprefixer in /src/packages/excalidraw (#3672)
Bumps [autoprefixer](https://github.com/postcss/autoprefixer) from 10.2.5 to 10.2.6.
- [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.2.5...10.2.6)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-12 20:56:01 +05:30
dependabot[bot] 2425c06082 chore(deps-dev): bump webpack in /src/packages/utils (#3673)
Bumps [webpack](https://github.com/webpack/webpack) from 5.37.1 to 5.38.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.37.1...v5.38.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-12 20:55:40 +05:30
dependabot[bot] 79ea844901 chore(deps-dev): bump @babel/preset-env in /src/packages/utils (#3675)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.14.1 to 7.14.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.14.4/packages/babel-preset-env)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-12 20:54:40 +05:30
David Luzar 6690215cd1 feat: change library icon to be more clear (#3583) 2021-06-11 23:13:05 +02:00
Excalidraw Bot 7f5e783fe8 chore: Update translations from Crowdin (#3659) 2021-06-11 19:15:44 +02:00
Aakansha Doshi 9325109836 fix: use excal id so every element has unique id (#3696)
* fix: use excal id so every element has unique id

* fix

* fix

* fix

* add docs

* fix
2021-06-10 02:46:56 +05:30
David Luzar 69b6fbb3f4 feat: pass current theme when installing libraries (#3701)
* pass current `theme` when installing libraries

* pass `theme` instead of `appState`
2021-06-08 23:14:02 +02:00
Sakito Mukai 6b6002baae refactor: Delete React SyntheticEvent persist (#3700) 2021-06-07 10:32:30 +02:00
Karl Horky 54dcb73701 docs: improve grammar and example (#3699)
* Improve grammar, render only once

* Update README_NEXT.md
2021-06-07 01:38:05 +05:30
rafaquelhodev b595d3fcba test: add unit tests for restore.ts file (#3679)
* Add unit tests for restore.ts file

* Improving describe blocks in restore tests

* Move restore.tests.ts folder and remove depedency of UI in the tests

* Adding snapshots to restore.ts tests

* Using snapshot in freedraw test

* Updating description of test for line and draw elements

* Updating description of test for arrow element

* Improving restoreAppState tests

* specs cleanup

* fix

* fix
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2021-06-06 21:53:12 +05:30
Aakansha Doshi d0867d1c3b refatcor: make ProjectName a functional component (#3695) 2021-06-04 21:22:09 +05:30
Youri Tjang 0d19e9210c feat: update virgil font (#3692)
Co-authored-by: tjangy <youri.tjang@rabobank.nl>
2021-06-02 21:41:14 +02:00
Arun 4249de41d4 feat: Add prop autoFocus to set focus on the Excalidraw component (#3691)
* feat: Add prop autofocus to set focus on Excalidraw component

* Update PR number

* Make requested changes

* Add note

* Update src/packages/excalidraw/CHANGELOG.md

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

* Update src/tests/excalidrawPackage.test.tsx

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

* Remove duplicate sentence

* Indent note

* autofocus -> autoFocus

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2021-06-02 19:54:21 +05:30
Aakansha Doshi 15f02ba191 refactor: code clean up (#3681)
* refactor: code clean up
Move types from App.tsx to types.ts
Move excalidrawPackage.test.tsx inside src/tests/package

* import type
2021-06-01 23:52:13 +05:30
David Luzar a2e1199907 feat: support exporting json to excalidraw plus (#3678)
* feat: support exporting json to excalidraw plus

* add Firebase Storage rules to codebase

* factor the onClick handler out

* move excal icon to icons.tsx

* handle export error
2021-06-01 14:05:09 +02:00
David Luzar c08e9c4172 fix: use rgba instead of shorthand alpha (#3688) 2021-05-31 14:29:40 +05:30
David Laban abfc58eb24 feat: save exportScale in AppState (#3580)
Co-authored-by: David Luzar <luzar.david@gmail.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
2021-05-30 16:31:12 +02:00
David Luzar 035c7affff fix: color pickers not opening on mobile (#3676) 2021-05-30 12:05:07 +02:00
David Luzar c819b653bf fix: on contextMenu, use selected element regardless of z-index (#3668) 2021-05-29 22:33:53 +02:00
David Luzar 60cea7a0c2 fix: selectedGroupIds not being stored in history (#3630)
thanks!
2021-05-29 21:35:03 +02:00
Aakansha Doshi d63b6a3469 feat: support custom UI rendering inside export dialog (#3666)
* feat: support custom UI rendering inside export dialog

* docs

* add

* remove assertion

Co-authored-by: dwelle <luzar.david@gmail.com>
2021-05-30 00:37:38 +05:30
Jed Fox 0912fe1c93 fix: overscroll on touch devices (#3663) 2021-05-29 11:54:36 -04:00
Aakansha Doshi 360310de31 feat: Add prop UIOptions.canvasActions.saveAsImage to show/hide save image button (#3662)
* feat: Add prop UIOptions.canvasActions.saveAsImage which implies whether the save as image dialog should be shown

* Add docs

* fix specs
2021-05-29 19:41:50 +05:30
dependabot[bot] 716c78e930 chore(deps): bump dns-packet from 1.3.1 to 1.3.4 (#3652)
Bumps [dns-packet](https://github.com/mafintosh/dns-packet) from 1.3.1 to 1.3.4.
- [Release notes](https://github.com/mafintosh/dns-packet/releases)
- [Changelog](https://github.com/mafintosh/dns-packet/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mafintosh/dns-packet/compare/v1.3.1...v1.3.4)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-29 16:06:20 +02:00
Aakansha Doshi ba48974351 feat: customise export dialog with UIOptions.canvasActions.export prop (#3658)
* refactor: update UIOptions.canvasActions.export to be a an object

* fix

* fix

* dnt show export icon when false

* fix

* inline

* memoize UIOptions

* update docs

* fix

* tweak readme

Co-authored-by: David Luzar <luzar.david@gmail.com>
2021-05-29 02:56:25 +05:30
Arun 6c3e4417e1 feat: Add shortcuts for stroke and background color picker (#3318)
* feat: Add shortcuts for opening stroke and background color picker

* Use App.tsx keydown handler

* only get selectedElements if applicable (perf)

* fix tests and snaps

* reuse `appState.openMenu`

Co-authored-by: dwelle <luzar.david@gmail.com>
2021-05-28 13:52:42 +02:00
Aakansha Doshi bc0b6e1888 refactor: rename UIOptions.canvasActions.saveScene to UIOptions.canvasActions.saveToActiveFile (#3657)
* refactor rename action saveScene to saveFileToDisk

* docs

* fix

* fix
2021-05-28 02:10:33 +05:30
Excalidraw Bot 99a22e8445 chore: Update translations from Crowdin (#3542)
* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Bulgarian)

* New translations en.json (Italian)

* New translations en.json (Catalan)

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

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* New translations en.json (Dutch)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* New translations en.json (Japanese)

* New translations en.json (Norwegian Bokmal)

* Auto commit: Calculate translation coverage

* New translations en.json (Swedish)

* Auto commit: Calculate translation coverage

* New translations en.json (Portuguese)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Traditional)

* New translations en.json (Catalan)

* Auto commit: Calculate translation coverage

* New translations en.json (Finnish)

* New translations en.json (Indonesian)

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

* New translations en.json (Chinese Simplified)

* New translations en.json (Punjabi)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Swedish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Traditional)

* New translations en.json (Korean)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Persian)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Occitan)

* New translations en.json (Dutch)

* New translations en.json (Japanese)

* New translations en.json (Turkish)

* New translations en.json (Arabic)

* New translations en.json (Indonesian)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Latvian)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Bulgarian)

* New translations en.json (Italian)

* New translations en.json (Catalan)

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

* Auto commit: Calculate translation coverage

* New translations en.json (Spanish)

* New translations en.json (German)

* New translations en.json (Norwegian Bokmal)

* Auto commit: Calculate translation coverage

* New translations en.json (Indonesian)

* New translations en.json (Romanian)

* New translations en.json (Finnish)

* New translations en.json (Italian)

* New translations en.json (Portuguese)

* Auto commit: Calculate translation coverage

* New translations en.json (Swedish)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* Auto commit: Calculate translation coverage

* New translations en.json (Turkish)

* New translations en.json (Turkish)

* Auto commit: Calculate translation coverage

* New translations en.json (Occitan)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Traditional)

* New translations en.json (Slovak)

* New translations en.json (Chinese Simplified)

* New translations en.json (Punjabi)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Swedish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Traditional)

* New translations en.json (Korean)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Persian)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Occitan)

* New translations en.json (Dutch)

* New translations en.json (Japanese)

* New translations en.json (Turkish)

* New translations en.json (Arabic)

* New translations en.json (Indonesian)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Latvian)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Bulgarian)

* New translations en.json (Italian)

* New translations en.json (Catalan)

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

* New translations en.json (Dutch)

* New translations en.json (Swedish)

* New translations en.json (Dutch)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Romanian)

* New translations en.json (Finnish)

* New translations en.json (Occitan)

* New translations en.json (Slovak)

* New translations en.json (German)

* New translations en.json (Italian)

* New translations en.json (Slovak)

* New translations en.json (French)

* New translations en.json (Portuguese)

* New translations en.json (Indonesian)

* New translations en.json (Indonesian)

* New translations en.json (French)

* New translations en.json (Chinese Traditional)

* New translations en.json (Kabyle)

* New translations en.json (Ukrainian)

* New translations en.json (Slovak)

* New translations en.json (Slovak)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Simplified)

* New translations en.json (Japanese)

* New translations en.json (Occitan)

* New translations en.json (Latvian)

* New translations en.json (Latvian)

* New translations en.json (Latvian)

* New translations en.json (Turkish)

* New translations en.json (Czech)

* Auto commit: Calculate translation coverage

* New translations en.json (Czech)

* Auto commit: Calculate translation coverage

* New translations en.json (Czech)

* Auto commit: Calculate translation coverage

* New translations en.json (Czech)

* Auto commit: Calculate translation coverage

* New translations en.json (Czech)

* Auto commit: Calculate translation coverage

* New translations en.json (Czech)

* Auto commit: Calculate translation coverage

* New translations en.json (Czech)

* Auto commit: Calculate translation coverage

* New translations en.json (Czech)

* Auto commit: Calculate translation coverage

* update language picker & coverage descriptions

* New translations en.json (Punjabi)

* Auto commit: Calculate translation coverage

* New translations en.json (Punjabi)

* Auto commit: Calculate translation coverage

* New translations en.json (Slovak)

* New translations en.json (Russian)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Korean)

* New translations en.json (Dutch)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Swedish)

* New translations en.json (Finnish)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Indonesian)

* New translations en.json (Persian)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

* New translations en.json (Hebrew)

* New translations en.json (Greek)

* New translations en.json (Turkish)

* New translations en.json (Occitan)

* New translations en.json (Latvian)

* New translations en.json (Japanese)

* New translations en.json (Punjabi)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Kabyle)

* New translations en.json (German)

* New translations en.json (Czech)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Arabic)

* New translations en.json (Bulgarian)

* New translations en.json (Catalan)

* New translations en.json (Norwegian Bokmal)

* Auto commit: Calculate translation coverage

* New translations en.json (Kabyle)

* New translations en.json (Dutch)

* New translations en.json (Norwegian Bokmal)

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

* Auto commit: Calculate translation coverage

* New translations en.json (German)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* New translations en.json (German)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* Auto commit: Calculate translation coverage

* New translations en.json (Ukrainian)

* New translations en.json (French)

* Auto commit: Calculate translation coverage

* New translations en.json (Japanese)

* Auto commit: Calculate translation coverage

* New translations en.json (Japanese)

* Auto commit: Calculate translation coverage

* New translations en.json (Italian)

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

* Auto commit: Calculate translation coverage

* New translations en.json (Arabic)

* Auto commit: Calculate translation coverage

* New translations en.json (Arabic)

* New translations en.json (Swedish)

Co-authored-by: dwelle <luzar.david@gmail.com>
2021-05-27 23:39:19 +05:30
dependabot[bot] e6d9797167 chore(deps-dev): bump @babel/core in /src/packages/excalidraw (#3620)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.14.2 to 7.14.3.
- [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.14.3/packages/babel-core)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-27 18:22:44 +05:30
dependabot[bot] a1e8fdfb1b chore(deps-dev): bump css-loader in /src/packages/excalidraw (#3653)
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 5.2.4 to 5.2.6.
- [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.4...v5.2.6)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-27 18:17:33 +05:30
dependabot[bot] 1cce63b07b chore(deps-dev): bump css-loader in /src/packages/utils (#3654)
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 5.2.4 to 5.2.6.
- [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.4...v5.2.6)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-27 18:17:15 +05:30
dependabot[bot] e9c2a09c21 chore(deps-dev): bump @babel/core in /src/packages/utils (#3619)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.14.2 to 7.14.3.
- [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.14.3/packages/babel-core)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-27 18:15:10 +05:30
dependabot[bot] 55e0812680 chore(deps-dev): bump webpack in /src/packages/excalidraw (#3618)
Bumps [webpack](https://github.com/webpack/webpack) from 5.37.0 to 5.37.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.37.0...v5.37.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-27 18:14:46 +05:30
dependabot[bot] 0f32278a7e chore(deps-dev): bump webpack-bundle-analyzer in /src/packages/utils (#3617)
Bumps [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) from 4.4.1 to 4.4.2.
- [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.1...v4.4.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-27 18:14:30 +05:30
dependabot[bot] 1bdb8da1c3 chore(deps-dev): bump @babel/plugin-transform-typescript (#3625)
Bumps [@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-typescript) from 7.13.0 to 7.14.3.
- [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.14.3/packages/babel-plugin-transform-typescript)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-27 18:13:37 +05:30
dependabot[bot] 9c9787e0a0 chore(deps-dev): bump @babel/plugin-transform-typescript (#3624)
Bumps [@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-typescript) from 7.13.0 to 7.14.3.
- [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.14.3/packages/babel-plugin-transform-typescript)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-27 18:13:12 +05:30
dependabot[bot] c2fe24c562 chore(deps): bump browserslist in /src/packages/utils (#3647)
Bumps [browserslist](https://github.com/browserslist/browserslist) from 4.16.3 to 4.16.6.
- [Release notes](https://github.com/browserslist/browserslist/releases)
- [Changelog](https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/browserslist/browserslist/compare/4.16.3...4.16.6)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-27 18:12:30 +05:30
dependabot[bot] 52faa52091 chore(deps): bump browserslist in /src/packages/excalidraw (#3648)
Bumps [browserslist](https://github.com/browserslist/browserslist) from 4.16.3 to 4.16.6.
- [Release notes](https://github.com/browserslist/browserslist/releases)
- [Changelog](https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/browserslist/browserslist/compare/4.16.3...4.16.6)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-27 18:12:08 +05:30
David Luzar dd12abc583 refactor: remove watermark code (#3639)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2021-05-26 21:44:54 +02:00
David Luzar abebf9aff8 fix: small UI issues around image export dialog (#3642) 2021-05-26 14:44:03 +02:00
126 changed files with 4983 additions and 2193 deletions
+3
View File
@@ -2,5 +2,8 @@
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"storage": {
"rules": "storage.rules"
}
}
+12
View File
@@ -0,0 +1,12 @@
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;
}
}
}
}
+1
View File
@@ -31,6 +31,7 @@
"clsx": "1.1.1",
"firebase": "8.3.3",
"i18next-browser-languagedetector": "6.1.0",
"idb-keyval": "5.0.6",
"lodash.throttle": "4.1.1",
"nanoid": "3.1.22",
"open-color": "1.8.0",
Binary file not shown.
+1
View File
@@ -117,6 +117,7 @@
width: 100%;
height: 100%;
overflow: hidden;
}
.visually-hidden {
+3
View File
@@ -38,6 +38,7 @@ const crowdinMap = {
"zh-CN": "en-zhcn",
"zh-TW": "en-zhtw",
"lv-LV": "en-lv",
"cs-CZ": "cs-cz",
};
const flags = {
@@ -76,6 +77,7 @@ const flags = {
"zh-CN": "🇨🇳",
"zh-TW": "🇹🇼",
"lv-LV": "🇱🇻",
"cs-CZ": "🇨🇿",
};
const languages = {
@@ -114,6 +116,7 @@ const languages = {
"zh-CN": "简体中文",
"zh-TW": "繁體中文",
"lv-LV": "Latviešu",
"cs-CZ": "Česky",
};
const percentages = fs.readFileSync(
+7 -4
View File
@@ -22,8 +22,8 @@ export const actionChangeViewBackgroundColor = register({
name: "changeViewBackgroundColor",
perform: (_, appState, value) => {
return {
appState: { ...appState, viewBackgroundColor: value },
commitToHistory: true,
appState: { ...appState, ...value },
commitToHistory: !!value.viewBackgroundColor,
};
},
PanelComponent: ({ appState, updateData }) => {
@@ -33,7 +33,11 @@ export const actionChangeViewBackgroundColor = register({
label={t("labels.canvasBackground")}
type="canvasBackground"
color={appState.viewBackgroundColor}
onChange={(color) => updateData(color)}
onChange={(color) => updateData({ viewBackgroundColor: color })}
isActive={appState.openPopup === "canvasColorPicker"}
setActive={(active) =>
updateData({ openPopup: active ? "canvasColorPicker" : null })
}
data-testid="canvas-background-picker"
/>
</div>
@@ -55,7 +59,6 @@ export const actionClearCanvas = register({
exportBackground: appState.exportBackground,
exportEmbedScene: appState.exportEmbedScene,
gridSize: appState.gridSize,
shouldAddWatermark: appState.shouldAddWatermark,
showStats: appState.showStats,
pasteDialog: appState.pasteDialog,
},
+86 -32
View File
@@ -1,6 +1,6 @@
import React from "react";
import { trackEvent } from "../analytics";
import { load, questionCircle, save, saveAs } from "../components/icons";
import { load, questionCircle, saveAs } from "../components/icons";
import { ProjectName } from "../components/ProjectName";
import { ToolButton } from "../components/ToolButton";
import "../components/ToolIcon.scss";
@@ -13,6 +13,12 @@ import { KEYS } from "../keys";
import { register } from "./register";
import { supported as fsSupported } from "browser-fs-access";
import { CheckboxItem } from "../components/CheckboxItem";
import { getExportSize } from "../scene/export";
import { DEFAULT_EXPORT_PADDING, EXPORT_SCALES, IDB_KEYS } from "../constants";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { getNonDeletedElements } from "../element";
import { ActiveFile } from "../components/ActiveFile";
import * as idb from "idb-keyval";
export const actionChangeProjectName = register({
name: "changeProjectName",
@@ -32,6 +38,54 @@ export const actionChangeProjectName = register({
),
});
export const actionChangeExportScale = register({
name: "changeExportScale",
perform: (_elements, appState, value) => {
return {
appState: { ...appState, exportScale: value },
commitToHistory: false,
};
},
PanelComponent: ({ elements: allElements, appState, updateData }) => {
const elements = getNonDeletedElements(allElements);
const exportSelected = isSomeElementSelected(elements, appState);
const exportedElements = exportSelected
? getSelectedElements(elements, appState)
: elements;
return (
<>
{EXPORT_SCALES.map((s) => {
const [width, height] = getExportSize(
exportedElements,
DEFAULT_EXPORT_PADDING,
s,
);
const scaleButtonTitle = `${t(
"buttons.scale",
)} ${s}x (${width}x${height})`;
return (
<ToolButton
key={s}
size="s"
type="radio"
icon={`${s}x`}
name="export-canvas-scale"
title={scaleButtonTitle}
aria-label={scaleButtonTitle}
id="export-canvas-scale"
checked={s === appState.exportScale}
onChange={() => updateData(s)}
/>
);
})}
</>
);
},
});
export const actionChangeExportBackground = register({
name: "changeExportBackground",
perform: (_elements, appState, value) => {
@@ -71,26 +125,8 @@ export const actionChangeExportEmbedScene = register({
),
});
export const actionChangeShouldAddWatermark = register({
name: "changeShouldAddWatermark",
perform: (_elements, appState, value) => {
return {
appState: { ...appState, shouldAddWatermark: value },
commitToHistory: false,
};
},
PanelComponent: ({ appState, updateData }) => (
<CheckboxItem
checked={appState.shouldAddWatermark}
onChange={(checked) => updateData(checked)}
>
{t("labels.addWatermark")}
</CheckboxItem>
),
});
export const actionSaveScene = register({
name: "saveScene",
export const actionSaveToActiveFile = register({
name: "saveToActiveFile",
perform: async (elements, appState, value) => {
const fileHandleExists = !!appState.fileHandle;
try {
@@ -114,31 +150,49 @@ export const actionSaveScene = register({
if (error?.name !== "AbortError") {
console.error(error);
}
return { commitToHistory: false };
if (fileHandleExists && error.name === "AbortError") {
try {
await idb.del(IDB_KEYS.fileHandle);
} catch (error) {
console.error(error);
}
return {
commitToHistory: false,
appState: { ...appState, fileHandle: null },
};
}
return {
commitToHistory: false,
};
}
},
keyTest: (event) =>
event.key === KEYS.S && event[KEYS.CTRL_OR_CMD] && !event.shiftKey,
PanelComponent: ({ updateData }) => (
<ToolButton
type="icon"
icon={save}
title={t("buttons.save")}
aria-label={t("buttons.save")}
onClick={() => updateData(null)}
data-testid="save-button"
PanelComponent: ({ updateData, appState }) => (
<ActiveFile
onSave={() => updateData(null)}
fileName={appState.fileHandle?.name}
/>
),
});
export const actionSaveAsScene = register({
name: "saveAsScene",
export const actionSaveFileToDisk = register({
name: "saveFileToDisk",
perform: async (elements, appState, value) => {
try {
const { fileHandle } = await saveAsJSON(elements, {
...appState,
fileHandle: null,
});
try {
if (fileHandle) {
await idb.set(IDB_KEYS.fileHandle, fileHandle);
}
} catch (error) {
console.error(error);
}
return { commitToHistory: false, appState: { ...appState, fileHandle } };
} catch (error) {
if (error?.name !== "AbortError") {
+57 -31
View File
@@ -13,6 +13,13 @@ import {
FillCrossHatchIcon,
FillHachureIcon,
FillSolidIcon,
FontFamilyCodeIcon,
FontFamilyHandDrawnIcon,
FontFamilyNormalIcon,
FontSizeExtraLargeIcon,
FontSizeLargeIcon,
FontSizeMediumIcon,
FontSizeSmallIcon,
SloppinessArchitectIcon,
SloppinessArtistIcon,
SloppinessCartoonistIcon,
@@ -20,18 +27,15 @@ import {
StrokeStyleDottedIcon,
StrokeStyleSolidIcon,
StrokeWidthIcon,
FontSizeSmallIcon,
FontSizeMediumIcon,
FontSizeLargeIcon,
FontSizeExtraLargeIcon,
FontFamilyHandDrawnIcon,
FontFamilyNormalIcon,
FontFamilyCodeIcon,
TextAlignLeftIcon,
TextAlignCenterIcon,
TextAlignLeftIcon,
TextAlignRightIcon,
} from "../components/icons";
import { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE } from "../constants";
import {
DEFAULT_FONT_FAMILY,
DEFAULT_FONT_SIZE,
FONT_FAMILY,
} from "../constants";
import {
getNonDeletedElements,
isTextElement,
@@ -44,7 +48,7 @@ import {
ExcalidrawElement,
ExcalidrawLinearElement,
ExcalidrawTextElement,
FontFamily,
FontFamilyValues,
TextAlign,
} from "../element/types";
import { getLanguage, t } from "../i18n";
@@ -99,13 +103,18 @@ export const actionChangeStrokeColor = register({
name: "changeStrokeColor",
perform: (elements, appState, value) => {
return {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
strokeColor: value,
}),
),
appState: { ...appState, currentItemStrokeColor: value },
commitToHistory: true,
...(value.currentItemStrokeColor && {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
strokeColor: value.currentItemStrokeColor,
}),
),
}),
appState: {
...appState,
...value,
},
commitToHistory: !!value.currentItemStrokeColor,
};
},
PanelComponent: ({ elements, appState, updateData }) => (
@@ -120,7 +129,11 @@ export const actionChangeStrokeColor = register({
(element) => element.strokeColor,
appState.currentItemStrokeColor,
)}
onChange={updateData}
onChange={(color) => updateData({ currentItemStrokeColor: color })}
isActive={appState.openPopup === "strokeColorPicker"}
setActive={(active) =>
updateData({ openPopup: active ? "strokeColorPicker" : null })
}
/>
</>
),
@@ -130,13 +143,18 @@ export const actionChangeBackgroundColor = register({
name: "changeBackgroundColor",
perform: (elements, appState, value) => {
return {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
backgroundColor: value,
}),
),
appState: { ...appState, currentItemBackgroundColor: value },
commitToHistory: true,
...(value.currentItemBackgroundColor && {
elements: changeProperty(elements, appState, (el) =>
newElementWith(el, {
backgroundColor: value.currentItemBackgroundColor,
}),
),
}),
appState: {
...appState,
...value,
},
commitToHistory: !!value.currentItemBackgroundColor,
};
},
PanelComponent: ({ elements, appState, updateData }) => (
@@ -151,7 +169,11 @@ export const actionChangeBackgroundColor = register({
(element) => element.backgroundColor,
appState.currentItemBackgroundColor,
)}
onChange={updateData}
onChange={(color) => updateData({ currentItemBackgroundColor: color })}
isActive={appState.openPopup === "backgroundColorPicker"}
setActive={(active) =>
updateData({ openPopup: active ? "backgroundColorPicker" : null })
}
/>
</>
),
@@ -481,19 +503,23 @@ export const actionChangeFontFamily = register({
};
},
PanelComponent: ({ elements, appState, updateData }) => {
const options: { value: FontFamily; text: string; icon: JSX.Element }[] = [
const options: {
value: FontFamilyValues;
text: string;
icon: JSX.Element;
}[] = [
{
value: 1,
value: FONT_FAMILY.Virgil,
text: t("labels.handDrawn"),
icon: <FontFamilyHandDrawnIcon theme={appState.theme} />,
},
{
value: 2,
value: FONT_FAMILY.Helvetica,
text: t("labels.normal"),
icon: <FontFamilyNormalIcon theme={appState.theme} />,
},
{
value: 3,
value: FONT_FAMILY.Cascadia,
text: t("labels.code"),
icon: <FontFamilyCodeIcon theme={appState.theme} />,
},
@@ -502,7 +528,7 @@ export const actionChangeFontFamily = register({
return (
<fieldset>
<legend>{t("labels.fontFamily")}</legend>
<ButtonIconSelect<FontFamily | false>
<ButtonIconSelect<FontFamilyValues | false>
group="font-family"
options={options}
value={getFormValue(
+2 -2
View File
@@ -34,8 +34,8 @@ export { actionFinalize } from "./actionFinalize";
export {
actionChangeProjectName,
actionChangeExportBackground,
actionSaveScene,
actionSaveAsScene,
actionSaveToActiveFile,
actionSaveFileToDisk,
actionLoadScene,
} from "./actionExport";
+3 -3
View File
@@ -66,9 +66,9 @@ export type ActionName =
| "changeProjectName"
| "changeExportBackground"
| "changeExportEmbedScene"
| "changeShouldAddWatermark"
| "saveScene"
| "saveAsScene"
| "changeExportScale"
| "saveToActiveFile"
| "saveFileToDisk"
| "loadScene"
| "duplicateSelection"
| "deleteSelectedElements"
+9 -2
View File
@@ -3,11 +3,16 @@ import {
DEFAULT_FONT_FAMILY,
DEFAULT_FONT_SIZE,
DEFAULT_TEXT_ALIGN,
EXPORT_SCALES,
} from "./constants";
import { t } from "./i18n";
import { AppState, NormalizedZoomValue } from "./types";
import { getDateTime } from "./utils";
const defaultExportScale = EXPORT_SCALES.includes(devicePixelRatio)
? devicePixelRatio
: 1;
export const getDefaultAppState = (): Omit<
AppState,
"offsetTop" | "offsetLeft" | "width" | "height"
@@ -39,6 +44,7 @@ export const getDefaultAppState = (): Omit<
elementType: "selection",
errorMessage: null,
exportBackground: true,
exportScale: defaultExportScale,
exportEmbedScene: false,
exportWithDarkMode: false,
fileHandle: null,
@@ -52,6 +58,7 @@ export const getDefaultAppState = (): Omit<
multiElement: null,
name: `${t("labels.untitled")}-${getDateTime()}`,
openMenu: null,
openPopup: null,
pasteDialog: { shown: false, data: null },
previousSelectedElementIds: {},
resizingElement: null,
@@ -61,7 +68,6 @@ export const getDefaultAppState = (): Omit<
selectedElementIds: {},
selectedGroupIds: {},
selectionElement: null,
shouldAddWatermark: false,
shouldCacheIgnoreZoom: false,
showHelpDialog: false,
showStats: false,
@@ -117,6 +123,7 @@ const APP_STATE_STORAGE_CONF = (<
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 },
@@ -132,6 +139,7 @@ const APP_STATE_STORAGE_CONF = (<
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 },
@@ -141,7 +149,6 @@ const APP_STATE_STORAGE_CONF = (<
selectedElementIds: { browser: true, export: false },
selectedGroupIds: { browser: true, export: false },
selectionElement: { browser: false, export: false },
shouldAddWatermark: { browser: true, export: false },
shouldCacheIgnoreZoom: { browser: true, export: false },
showHelpDialog: { browser: false, export: false },
showStats: { browser: true, export: false },
-22
View File
@@ -151,23 +151,14 @@ export const SelectedShapeActions = ({
);
};
const LIBRARY_ICON = (
// fa-th-large
<svg viewBox="0 0 512 512">
<path d="M296 32h192c13.255 0 24 10.745 24 24v160c0 13.255-10.745 24-24 24H296c-13.255 0-24-10.745-24-24V56c0-13.255 10.745-24 24-24zm-80 0H24C10.745 32 0 42.745 0 56v160c0 13.255 10.745 24 24 24h192c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24zM0 296v160c0 13.255 10.745 24 24 24h192c13.255 0 24-10.745 24-24V296c0-13.255-10.745-24-24-24H24c-13.255 0-24 10.745-24 24zm296 184h192c13.255 0 24-10.745 24-24V296c0-13.255-10.745-24-24-24H296c-13.255 0-24 10.745-24 24v160c0 13.255 10.745 24 24 24z" />
</svg>
);
export const ShapesSwitcher = ({
canvas,
elementType,
setAppState,
isLibraryOpen,
}: {
canvas: HTMLCanvasElement | null;
elementType: ExcalidrawElement["type"];
setAppState: React.Component<any, AppState>["setState"];
isLibraryOpen: boolean;
}) => (
<>
{SHAPES.map(({ value, icon, key }, index) => {
@@ -201,19 +192,6 @@ export const ShapesSwitcher = ({
/>
);
})}
<ToolButton
className="Shape ToolIcon_type_button__library"
type="button"
icon={LIBRARY_ICON}
name="editor-library"
keyBindingLabel="9"
aria-keyshortcuts="9"
title={`${capitalizeString(t("toolBar.library"))} — 9`}
aria-label={capitalizeString(t("toolBar.library"))}
onClick={() => {
setAppState({ isLibraryOpen: !isLibraryOpen });
}}
/>
</>
);
+21
View File
@@ -0,0 +1,21 @@
.excalidraw {
.ActiveFile {
.ActiveFile__fileName {
display: flex;
align-items: center;
span {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 9.3em;
}
svg {
width: 1.15em;
margin-inline-end: 0.3em;
transform: scaleY(0.9);
}
}
}
}
+29
View File
@@ -0,0 +1,29 @@
import React from "react";
import Stack from "../components/Stack";
import { ToolButton } from "../components/ToolButton";
import { save, file } from "../components/icons";
import { t } from "../i18n";
import "./ActiveFile.scss";
type ActiveFileProps = {
fileName?: string;
onSave: () => void;
};
export const ActiveFile = ({ fileName, onSave }: ActiveFileProps) => (
<Stack.Row className="ActiveFile" gap={1} align="center">
<span className="ActiveFile__fileName">
{file}
<span>{fileName}</span>
</span>
<ToolButton
type="icon"
icon={save}
title={t("buttons.save")}
aria-label={t("buttons.save")}
onClick={onSave}
data-testid="save-button"
/>
</Stack.Row>
);
+63 -91
View File
@@ -52,6 +52,7 @@ import {
ENV,
EVENT,
GRID_SIZE,
IDB_KEYS,
LINE_CONFIRM_THRESHOLD,
MIME_TYPES,
MQ_MAX_HEIGHT_LANDSCAPE,
@@ -111,7 +112,6 @@ import {
import { LinearElementEditor } from "../element/linearElementEditor";
import { mutateElement } from "../element/mutateElement";
import { deepCopyElement, newFreeDrawElement } from "../element/newElement";
import { MaybeTransformHandleType } from "../element/transformHandles";
import {
isBindingElement,
isBindingElementType,
@@ -167,9 +167,11 @@ import { findShapeByKey } from "../shapes";
import {
AppProps,
AppState,
ExcalidrawImperativeAPI,
Gesture,
GestureEvent,
LibraryItems,
PointerDownState,
SceneData,
} from "../types";
import {
@@ -180,7 +182,6 @@ import {
isToolIcon,
isWritableElement,
resetCursor,
ResolvablePromise,
resolvablePromise,
sceneCoordsToViewportCoords,
setCursor,
@@ -194,12 +195,14 @@ import LayerUI from "./LayerUI";
import { Stats } from "./Stats";
import { Toast } from "./Toast";
import { actionToggleViewMode } from "../actions/actionToggleViewMode";
import * as idb from "idb-keyval";
const IsMobileContext = React.createContext(false);
export const useIsMobile = () => useContext(IsMobileContext);
const ExcalidrawContainerContext = React.createContext<HTMLDivElement | null>(
null,
);
const ExcalidrawContainerContext = React.createContext<{
container: HTMLDivElement | null;
id: string | null;
}>({ container: null, id: null });
export const useExcalidrawContainer = () =>
useContext(ExcalidrawContainerContext);
@@ -222,83 +225,6 @@ const gesture: Gesture = {
initialScale: null,
};
export type PointerDownState = Readonly<{
// The first position at which pointerDown happened
origin: Readonly<{ x: number; y: number }>;
// Same as "origin" but snapped to the grid, if grid is on
originInGrid: Readonly<{ x: number; y: number }>;
// Scrollbar checks
scrollbars: ReturnType<typeof isOverScrollBars>;
// The previous pointer position
lastCoords: { x: number; y: number };
// map of original elements data
originalElements: Map<string, NonDeleted<ExcalidrawElement>>;
resize: {
// Handle when resizing, might change during the pointer interaction
handleType: MaybeTransformHandleType;
// This is determined on the initial pointer down event
isResizing: boolean;
// This is determined on the initial pointer down event
offset: { x: number; y: number };
// This is determined on the initial pointer down event
arrowDirection: "origin" | "end";
// This is a center point of selected elements determined on the initial pointer down event (for rotation only)
center: { x: number; y: number };
};
hit: {
// The element the pointer is "hitting", is determined on the initial
// pointer down event
element: NonDeleted<ExcalidrawElement> | null;
// The elements the pointer is "hitting", is determined on the initial
// pointer down event
allHitElements: NonDeleted<ExcalidrawElement>[];
// This is determined on the initial pointer down event
wasAddedToSelection: boolean;
// Whether selected element(s) were duplicated, might change during the
// pointer interaction
hasBeenDuplicated: boolean;
hasHitCommonBoundingBoxOfSelectedElements: boolean;
};
withCmdOrCtrl: boolean;
drag: {
// Might change during the pointer interation
hasOccurred: boolean;
// Might change during the pointer interation
offset: { x: number; y: number } | null;
};
// We need to have these in the state so that we can unsubscribe them
eventListeners: {
// It's defined on the initial pointer down event
onMove: null | ((event: PointerEvent) => void);
// It's defined on the initial pointer down event
onUp: null | ((event: PointerEvent) => void);
// It's defined on the initial pointer down event
onKeyDown: null | ((event: KeyboardEvent) => void);
// It's defined on the initial pointer down event
onKeyUp: null | ((event: KeyboardEvent) => void);
};
}>;
export type ExcalidrawImperativeAPI = {
updateScene: InstanceType<typeof App>["updateScene"];
resetScene: InstanceType<typeof App>["resetScene"];
getSceneElementsIncludingDeleted: InstanceType<
typeof App
>["getSceneElementsIncludingDeleted"];
history: {
clear: InstanceType<typeof App>["resetHistory"];
};
scrollToContent: InstanceType<typeof App>["scrollToContent"];
getSceneElements: InstanceType<typeof App>["getSceneElements"];
getAppState: () => InstanceType<typeof App>["state"];
refresh: InstanceType<typeof App>["refresh"];
importLibrary: InstanceType<typeof App>["importLibraryFromUrl"];
setToastMessage: InstanceType<typeof App>["setToastMessage"];
readyPromise: ResolvablePromise<ExcalidrawImperativeAPI>;
ready: true;
id: string;
};
class App extends React.Component<AppProps, AppState> {
canvas: HTMLCanvasElement | null = null;
rc: RoughCanvas | null = null;
@@ -321,6 +247,10 @@ class App extends React.Component<AppProps, AppState> {
public libraryItemsFromStorage: LibraryItems | undefined;
private id: string;
private history: History;
private excalidrawContainerValue: {
container: HTMLDivElement | null;
id: string;
};
constructor(props: AppProps) {
super(props);
@@ -377,6 +307,12 @@ class App extends React.Component<AppProps, AppState> {
}
readyPromise.resolve(api);
}
this.excalidrawContainerValue = {
container: this.excalidrawContainerRef.current,
id: this.id,
};
this.scene = new Scene();
this.library = new Library(this);
this.history = new History();
@@ -404,7 +340,7 @@ class App extends React.Component<AppProps, AppState> {
if (viewModeEnabled) {
return (
<canvas
id="canvas"
className="excalidraw__canvas"
style={{
width: canvasDOMWidth,
height: canvasDOMHeight,
@@ -426,7 +362,7 @@ class App extends React.Component<AppProps, AppState> {
}
return (
<canvas
id="canvas"
className="excalidraw__canvas"
style={{
width: canvasDOMWidth,
height: canvasDOMHeight,
@@ -452,7 +388,6 @@ class App extends React.Component<AppProps, AppState> {
const {
onCollabButtonClick,
onExportToBackend,
renderTopRightUI,
renderFooter,
renderCustomStats,
@@ -472,7 +407,7 @@ class App extends React.Component<AppProps, AppState> {
}
>
<ExcalidrawContainerContext.Provider
value={this.excalidrawContainerRef.current}
value={this.excalidrawContainerValue}
>
<IsMobileContext.Provider value={this.isMobile}>
<LayerUI
@@ -493,7 +428,6 @@ class App extends React.Component<AppProps, AppState> {
toggleZenMode={this.toggleZenMode}
langCode={getLanguage().code}
isCollaborating={this.props.isCollaborating || false}
onExportToBackend={onExportToBackend}
renderTopRightUI={renderTopRightUI}
renderCustomFooter={renderFooter}
viewModeEnabled={viewModeEnabled}
@@ -536,7 +470,9 @@ class App extends React.Component<AppProps, AppState> {
}
public focusContainer = () => {
this.excalidrawContainerRef.current?.focus();
if (this.props.autoFocus) {
this.excalidrawContainerRef.current?.focus();
}
};
public getSceneElementsIncludingDeleted = () => {
@@ -802,6 +738,8 @@ class App extends React.Component<AppProps, AppState> {
};
public async componentDidMount() {
this.excalidrawContainerValue.container = this.excalidrawContainerRef.current;
if (
process.env.NODE_ENV === ENV.TEST ||
process.env.NODE_ENV === ENV.DEVELOPMENT
@@ -871,6 +809,15 @@ class App extends React.Component<AppProps, AppState> {
} else {
this.updateDOMRect(this.initializeScene);
}
try {
const fileHandle = await idb.get(IDB_KEYS.fileHandle);
if (fileHandle) {
this.setState({ fileHandle });
}
} catch (error) {
console.error(error);
}
}
public componentWillUnmount() {
@@ -1645,6 +1592,21 @@ class App extends React.Component<AppProps, AppState> {
isHoldingSpace = true;
setCursor(this.canvas, CURSOR_TYPE.GRABBING);
}
if (event.key === KEYS.G || event.key === KEYS.S) {
const selectedElements = getSelectedElements(
this.scene.getElements(),
this.state,
);
if (selectedElements.length) {
if (event.key === KEYS.G) {
this.setState({ openPopup: "backgroundColorPicker" });
}
if (event.key === KEYS.S) {
this.setState({ openPopup: "strokeColorPicker" });
}
}
}
},
);
@@ -1845,9 +1807,21 @@ class App extends React.Component<AppProps, AppState> {
private getElementAtPosition(
x: number,
y: number,
opts?: {
/** if true, returns the first selected element (with highest z-index)
of all hit elements */
preferSelected?: boolean;
},
): NonDeleted<ExcalidrawElement> | null {
const allHitElements = this.getElementsAtPosition(x, y);
if (allHitElements.length > 1) {
if (opts?.preferSelected) {
for (let index = allHitElements.length - 1; index > -1; index--) {
if (this.state.selectedElementIds[allHitElements[index].id]) {
return allHitElements[index];
}
}
}
const elementWithHighestZIndex =
allHitElements[allHitElements.length - 1];
// If we're hitting element with highest z-index only on its bounding box
@@ -2283,8 +2257,6 @@ class App extends React.Component<AppProps, AppState> {
private handleCanvasPointerDown = (
event: React.PointerEvent<HTMLCanvasElement>,
) => {
event.persist();
// remove any active selection when we start to interact with canvas
// (mainly, we care about removing selection outside the component which
// would prevent our copy handling otherwise)
@@ -3922,7 +3894,7 @@ class App extends React.Component<AppProps, AppState> {
event.preventDefault();
const { x, y } = viewportCoordsToSceneCoords(event, this.state);
const element = this.getElementAtPosition(x, y);
const element = this.getElementAtPosition(x, y, { preferSelected: true });
const type = element ? "element" : "canvas";
@@ -16,10 +16,5 @@ export const BackgroundPickerAndDarkModeToggle = ({
<div style={{ display: "flex" }}>
{actionManager.renderAction("changeViewBackgroundColor")}
{showThemeBtn && actionManager.renderAction("toggleTheme")}
{appState.fileHandle && (
<div style={{ marginInlineStart: "0.25rem" }}>
{actionManager.renderAction("saveScene")}
</div>
)}
</div>
);
+7 -3
View File
@@ -2,16 +2,20 @@
.excalidraw {
.Checkbox {
margin: 3px 0.3em;
margin: 4px 0.3em;
display: flex;
align-items: center;
cursor: pointer;
user-select: none;
&:hover:not(.is-checked) .Checkbox-box {
box-shadow: 0 0 0 2px #{$oc-blue-4};
-webkit-tap-highlight-color: transparent;
&:hover:not(.is-checked) .Checkbox-box:not(:focus) {
box-shadow: 0 0 0 2px #{$oc-blue-4};
}
&:hover:not(.is-checked) .Checkbox-box:not(:focus) {
svg {
display: block;
opacity: 0.3;
+4 -1
View File
@@ -238,13 +238,16 @@ export const ColorPicker = ({
color,
onChange,
label,
isActive,
setActive,
}: {
type: "canvasBackground" | "elementBackground" | "elementStroke";
color: string | null;
onChange: (color: string) => void;
label: string;
isActive: boolean;
setActive: (active: boolean) => void;
}) => {
const [isActive, setActive] = React.useState(false);
const pickerButton = React.useRef<HTMLButtonElement>(null);
return (
+3 -2
View File
@@ -2,7 +2,7 @@ import clsx from "clsx";
import React, { useEffect, useState } from "react";
import { useCallbackRefState } from "../hooks/useCallbackRefState";
import { t } from "../i18n";
import { useIsMobile } from "../components/App";
import { useExcalidrawContainer, useIsMobile } from "../components/App";
import { KEYS } from "../keys";
import "./Dialog.scss";
import { back, close } from "./icons";
@@ -21,6 +21,7 @@ export const Dialog = (props: {
}) => {
const [islandNode, setIslandNode] = useCallbackRefState<HTMLDivElement>();
const [lastActiveElement] = useState(document.activeElement);
const { id } = useExcalidrawContainer();
useEffect(() => {
if (!islandNode) {
@@ -82,7 +83,7 @@ export const Dialog = (props: {
theme={props.theme}
>
<Island ref={setIslandNode}>
<h2 id="dialog-title" className="Dialog__title">
<h2 id={`${id}-dialog-title`} className="Dialog__title">
<span className="Dialog__titleContent">{props.title}</span>
<button
className="Modal__close"
+1 -1
View File
@@ -12,7 +12,7 @@ export const ErrorDialog = ({
onClose?: () => void;
}) => {
const [modalIsShown, setModalIsShown] = useState(!!message);
const excalidrawContainer = useExcalidrawContainer();
const { container: excalidrawContainer } = useExcalidrawContainer();
const handleClose = React.useCallback(() => {
setModalIsShown(false);
+3 -2
View File
@@ -97,7 +97,8 @@
border-radius: 1rem;
background-color: var(--button-color);
box-shadow: 0 3px 5px -1px rgb(0 0 0 / 28%), 0 6px 10px 0 rgb(0 0 0 / 14%);
box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.28),
0 6px 10px 0 rgba(0, 0, 0, 0.14);
font-family: Cascadia;
font-size: 1.8em;
@@ -108,7 +109,7 @@
}
&:active {
background-color: var(--button-color-darkest);
box-shadow: 0 3px 5px -1px rgb(0 0 0 / 20%), 0 6px 10px 0 rgb(0 0 0 / 14%);
box-shadow: none;
}
svg {
+15
View File
@@ -157,6 +157,13 @@ export const HelpDialog = ({ onClose }: { onClose?: () => void }) => {
shortcuts={["Shift+P", "7"]}
/>
<Shortcut label={t("toolBar.text")} shortcuts={["T", "8"]} />
<Shortcut
label={t("helpDialog.editSelectedShape")}
shortcuts={[
getShortcutKey("Enter"),
t("helpDialog.doubleClick"),
]}
/>
<Shortcut
label={t("helpDialog.textNewLine")}
shortcuts={[
@@ -365,6 +372,14 @@ export const HelpDialog = ({ onClose }: { onClose?: () => void }) => {
label={t("labels.flipVertical")}
shortcuts={[getShortcutKey("Shift+V")]}
/>
<Shortcut
label={t("labels.showStroke")}
shortcuts={[getShortcutKey("S")]}
/>
<Shortcut
label={t("labels.showBackground")}
shortcuts={[getShortcutKey("G")]}
/>
</ShortcutIsland>
</Column>
</Columns>
+9 -1
View File
@@ -5,7 +5,7 @@ import { getSelectedElements } from "../scene";
import "./HintViewer.scss";
import { AppState } from "../types";
import { isLinearElement } from "../element/typeChecks";
import { isLinearElement, isTextElement } from "../element/typeChecks";
import { getShortcutKey } from "../utils";
interface Hint {
@@ -57,6 +57,14 @@ const getHints = ({ appState, elements }: Hint) => {
return t("hints.lineEditor_info");
}
if (selectedElements.length === 1 && isTextElement(selectedElements[0])) {
return t("hints.text_selected");
}
if (appState.editingElement && isTextElement(appState.editingElement)) {
return t("hints.text_editing");
}
return null;
};
+10 -48
View File
@@ -8,20 +8,17 @@ import { CanvasError } from "../errors";
import { t } from "../i18n";
import { useIsMobile } from "./App";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { exportToCanvas, getExportSize } from "../scene/export";
import { exportToCanvas } from "../scene/export";
import { AppState } from "../types";
import { Dialog } from "./Dialog";
import { clipboard, exportImage } from "./icons";
import Stack from "./Stack";
import { ToolButton } from "./ToolButton";
import "./ExportDialog.scss";
import { supported as fsSupported } from "browser-fs-access";
import OpenColor from "open-color";
import { CheckboxItem } from "./CheckboxItem";
const scales = [1, 2, 3];
const defaultScale = scales.includes(devicePixelRatio) ? devicePixelRatio : 1;
import { DEFAULT_EXPORT_PADDING } from "../constants";
const supportsContextFilters =
"filter" in document.createElement("canvas").getContext("2d")!;
@@ -82,7 +79,7 @@ const ExportButton: React.FC<{
const ImageExportModal = ({
elements,
appState,
exportPadding = 10,
exportPadding = DEFAULT_EXPORT_PADDING,
actionManager,
onExportToPng,
onExportToSvg,
@@ -98,14 +95,9 @@ const ImageExportModal = ({
onCloseRequest: () => void;
}) => {
const someElementIsSelected = isSomeElementSelected(elements, appState);
const [scale, setScale] = useState(defaultScale);
const [exportSelected, setExportSelected] = useState(someElementIsSelected);
const previewRef = useRef<HTMLDivElement>(null);
const {
exportBackground,
viewBackgroundColor,
shouldAddWatermark,
} = appState;
const { exportBackground, viewBackgroundColor } = appState;
const exportedElements = exportSelected
? getSelectedElements(elements, appState)
@@ -125,8 +117,6 @@ const ImageExportModal = ({
exportBackground,
viewBackgroundColor,
exportPadding,
scale,
shouldAddWatermark,
});
// if converting to blob fails, there's some problem that will
@@ -149,8 +139,6 @@ const ImageExportModal = ({
exportBackground,
exportPadding,
viewBackgroundColor,
scale,
shouldAddWatermark,
]);
return (
@@ -181,34 +169,8 @@ const ImageExportModal = ({
</div>
</div>
<div style={{ display: "flex", alignItems: "center", marginTop: ".6em" }}>
<Stack.Row gap={2} justifyContent={"center"}>
{scales.map((_scale) => {
const [width, height] = getExportSize(
exportedElements,
exportPadding,
shouldAddWatermark,
_scale,
);
const scaleButtonTitle = `${t(
"buttons.scale",
)} ${_scale}x (${width}x${height})`;
return (
<ToolButton
key={_scale}
size="s"
type="radio"
icon={`${_scale}x`}
name="export-canvas-scale"
title={scaleButtonTitle}
aria-label={scaleButtonTitle}
id="export-canvas-scale"
checked={_scale === scale}
onChange={() => setScale(_scale)}
/>
);
})}
<Stack.Row gap={2}>
{actionManager.renderAction("changeExportScale")}
</Stack.Row>
<p style={{ marginLeft: "1em", userSelect: "none" }}>Scale</p>
</div>
@@ -227,7 +189,7 @@ const ImageExportModal = ({
color="indigo"
title={t("buttons.exportToPng")}
aria-label={t("buttons.exportToPng")}
onClick={() => onExportToPng(exportedElements, scale)}
onClick={() => onExportToPng(exportedElements)}
>
PNG
</ExportButton>
@@ -235,14 +197,14 @@ const ImageExportModal = ({
color="red"
title={t("buttons.exportToSvg")}
aria-label={t("buttons.exportToSvg")}
onClick={() => onExportToSvg(exportedElements, scale)}
onClick={() => onExportToSvg(exportedElements)}
>
SVG
</ExportButton>
{probablySupportsClipboardBlob && (
<ExportButton
title={t("buttons.copyPngToClipboard")}
onClick={() => onExportToClipboard(exportedElements, scale)}
onClick={() => onExportToClipboard(exportedElements)}
color="gray"
shade={7}
>
@@ -257,7 +219,7 @@ const ImageExportModal = ({
export const ImageExportDialog = ({
elements,
appState,
exportPadding = 10,
exportPadding = DEFAULT_EXPORT_PADDING,
actionManager,
onExportToPng,
onExportToSvg,
+36 -26
View File
@@ -3,11 +3,11 @@ import { ActionsManagerInterface } from "../actions/types";
import { NonDeletedExcalidrawElement } from "../element/types";
import { t } from "../i18n";
import { useIsMobile } from "./App";
import { AppState } from "../types";
import { AppState, ExportOpts } from "../types";
import { Dialog } from "./Dialog";
import { exportFile, exportToFileIcon, link } from "./icons";
import { ToolButton } from "./ToolButton";
import { actionSaveAsScene } from "../actions/actionExport";
import { actionSaveFileToDisk } from "../actions/actionExport";
import { Card } from "./Card";
import "./ExportDialog.scss";
@@ -22,35 +22,40 @@ const JSONExportModal = ({
elements,
appState,
actionManager,
onExportToBackend,
exportOpts,
canvas,
}: {
appState: AppState;
elements: readonly NonDeletedExcalidrawElement[];
actionManager: ActionsManagerInterface;
onExportToBackend?: ExportCB;
onCloseRequest: () => void;
exportOpts: ExportOpts;
canvas: HTMLCanvasElement | null;
}) => {
const { onExportToBackend } = exportOpts;
return (
<div className="ExportDialog ExportDialog--json">
<div className="ExportDialog-cards">
<Card color="lime">
<div className="Card-icon">{exportToFileIcon}</div>
<h2>{t("exportDialog.disk_title")}</h2>
<div className="Card-details">
{t("exportDialog.disk_details")}
{!fsSupported && actionManager.renderAction("changeProjectName")}
</div>
<ToolButton
className="Card-button"
type="button"
title={t("exportDialog.disk_button")}
aria-label={t("exportDialog.disk_button")}
showAriaLabel={true}
onClick={() => {
actionManager.executeAction(actionSaveAsScene);
}}
/>
</Card>
{exportOpts.saveFileToDisk && (
<Card color="lime">
<div className="Card-icon">{exportToFileIcon}</div>
<h2>{t("exportDialog.disk_title")}</h2>
<div className="Card-details">
{t("exportDialog.disk_details")}
{!fsSupported && actionManager.renderAction("changeProjectName")}
</div>
<ToolButton
className="Card-button"
type="button"
title={t("exportDialog.disk_button")}
aria-label={t("exportDialog.disk_button")}
showAriaLabel={true}
onClick={() => {
actionManager.executeAction(actionSaveFileToDisk);
}}
/>
</Card>
)}
{onExportToBackend && (
<Card color="pink">
<div className="Card-icon">{link}</div>
@@ -62,10 +67,12 @@ const JSONExportModal = ({
title={t("exportDialog.link_button")}
aria-label={t("exportDialog.link_button")}
showAriaLabel={true}
onClick={() => onExportToBackend(elements)}
onClick={() => onExportToBackend(elements, appState, canvas)}
/>
</Card>
)}
{exportOpts.renderCustomUI &&
exportOpts.renderCustomUI(elements, appState, canvas)}
</div>
</div>
);
@@ -75,12 +82,14 @@ export const JSONExportDialog = ({
elements,
appState,
actionManager,
onExportToBackend,
exportOpts,
canvas,
}: {
appState: AppState;
elements: readonly NonDeletedExcalidrawElement[];
actionManager: ActionsManagerInterface;
onExportToBackend?: ExportCB;
exportOpts: ExportOpts;
canvas: HTMLCanvasElement | null;
}) => {
const [modalIsShown, setModalIsShown] = useState(false);
@@ -107,8 +116,9 @@ export const JSONExportDialog = ({
elements={elements}
appState={appState}
actionManager={actionManager}
onExportToBackend={onExportToBackend}
onCloseRequest={handleClose}
exportOpts={exportOpts}
canvas={canvas}
/>
</Dialog>
)}
+26 -27
View File
@@ -36,7 +36,7 @@ import { Island } from "./Island";
import "./LayerUI.scss";
import { LibraryUnit } from "./LibraryUnit";
import { LoadingMessage } from "./LoadingMessage";
import { LockIcon } from "./LockIcon";
import { LockButton } from "./LockButton";
import { MobileMenu } from "./MobileMenu";
import { PasteChartDialog } from "./PasteChartDialog";
import { Section } from "./Section";
@@ -47,6 +47,7 @@ import { Tooltip } from "./Tooltip";
import { UserList } from "./UserList";
import Library from "../data/library";
import { JSONExportDialog } from "./JSONExportDialog";
import { LibraryButton } from "./LibraryButton";
interface LayerUIProps {
actionManager: ActionManager;
@@ -63,11 +64,6 @@ interface LayerUIProps {
toggleZenMode: () => void;
langCode: Language["code"];
isCollaborating: boolean;
onExportToBackend?: (
exportedElements: readonly NonDeletedExcalidrawElement[],
appState: AppState,
canvas: HTMLCanvasElement | null,
) => void;
renderTopRightUI?: (isMobile: boolean, appState: AppState) => JSX.Element;
renderCustomFooter?: (isMobile: boolean, appState: AppState) => JSX.Element;
viewModeEnabled: boolean;
@@ -112,6 +108,7 @@ const LibraryMenuItems = ({
onAddToLibrary,
onInsertShape,
pendingElements,
theme,
setAppState,
setLibraryItems,
libraryReturnUrl,
@@ -124,6 +121,7 @@ const LibraryMenuItems = ({
onRemoveFromLibrary: (index: number) => void;
onInsertShape: (elements: LibraryItem) => void;
onAddToLibrary: (elements: LibraryItem) => void;
theme: AppState["theme"];
setAppState: React.Component<any, AppState>["setState"];
setLibraryItems: (library: LibraryItems) => void;
libraryReturnUrl: ExcalidrawProps["libraryReturnUrl"];
@@ -197,7 +195,7 @@ const LibraryMenuItems = ({
<a
href={`https://libraries.excalidraw.com?target=${
window.name || "_blank"
}&referrer=${referrer}&useHash=true&token=${id}`}
}&referrer=${referrer}&useHash=true&token=${id}&theme=${theme}`}
target="_excalidraw_libraries"
>
{t("labels.libraries")}
@@ -251,6 +249,7 @@ const LibraryMenu = ({
onInsertShape,
pendingElements,
onAddToLibrary,
theme,
setAppState,
libraryReturnUrl,
focusContainer,
@@ -261,6 +260,7 @@ const LibraryMenu = ({
onClickOutside: (event: MouseEvent) => void;
onInsertShape: (elements: LibraryItem) => void;
onAddToLibrary: () => void;
theme: AppState["theme"];
setAppState: React.Component<any, AppState>["setState"];
libraryReturnUrl: ExcalidrawProps["libraryReturnUrl"];
focusContainer: () => void;
@@ -350,6 +350,7 @@ const LibraryMenu = ({
libraryReturnUrl={libraryReturnUrl}
focusContainer={focusContainer}
library={library}
theme={theme}
id={id}
/>
)}
@@ -371,7 +372,6 @@ const LayerUI = ({
showThemeBtn,
toggleZenMode,
isCollaborating,
onExportToBackend,
renderTopRightUI,
renderCustomFooter,
viewModeEnabled,
@@ -393,33 +393,24 @@ const LayerUI = ({
elements={elements}
appState={appState}
actionManager={actionManager}
onExportToBackend={
onExportToBackend
? (elements) => {
onExportToBackend &&
onExportToBackend(elements, appState, canvas);
}
: undefined
}
exportOpts={UIOptions.canvasActions.export}
canvas={canvas}
/>
);
};
const renderImageExportDialog = () => {
if (!UIOptions.canvasActions.export) {
if (!UIOptions.canvasActions.saveAsImage) {
return null;
}
const createExporter = (type: ExportType): ExportCB => async (
exportedElements,
scale,
) => {
await exportCanvas(type, exportedElements, appState, {
exportBackground: appState.exportBackground,
name: appState.name,
viewBackgroundColor: appState.viewBackgroundColor,
scale,
shouldAddWatermark: appState.shouldAddWatermark,
})
.catch(muteFSAbortError)
.catch((error) => {
@@ -497,6 +488,9 @@ const LayerUI = ({
setAppState={setAppState}
showThemeBtn={showThemeBtn}
/>
{appState.fileHandle && (
<>{actionManager.renderAction("saveToActiveFile")}</>
)}
</Stack.Col>
</Island>
</Section>
@@ -515,7 +509,8 @@ const LayerUI = ({
style={{
// we want to make sure this doesn't overflow so substracting 200
// which is approximately height of zoom footer and top left menu items with some buffer
maxHeight: `${appState.height - 200}px`,
// if active file name is displayed, subtracting 248 to account for its height
maxHeight: `${appState.height - (appState.fileHandle ? 248 : 200)}px`,
}}
>
<SelectedShapeActions
@@ -552,6 +547,7 @@ const LayerUI = ({
libraryReturnUrl={libraryReturnUrl}
focusContainer={focusContainer}
library={library}
theme={appState.theme}
id={id}
/>
) : null;
@@ -579,6 +575,12 @@ const LayerUI = ({
{(heading) => (
<Stack.Col gap={4} align="start">
<Stack.Row gap={1}>
<LockButton
zenModeEnabled={zenModeEnabled}
checked={appState.elementLocked}
onChange={onLockToggle}
title={t("toolBar.lock")}
/>
<Island
padding={1}
className={clsx({ "zen-mode": zenModeEnabled })}
@@ -590,15 +592,12 @@ const LayerUI = ({
canvas={canvas}
elementType={appState.elementType}
setAppState={setAppState}
isLibraryOpen={appState.isLibraryOpen}
/>
</Stack.Row>
</Island>
<LockIcon
zenModeEnabled={zenModeEnabled}
checked={appState.elementLocked}
onChange={onLockToggle}
title={t("toolBar.lock")}
<LibraryButton
appState={appState}
setAppState={setAppState}
/>
</Stack.Row>
{libraryMenu}
+45
View File
@@ -0,0 +1,45 @@
import clsx from "clsx";
import { t } from "../i18n";
import { AppState } from "../types";
import { capitalizeString } from "../utils";
const LIBRARY_ICON = (
<svg viewBox="0 0 576 512">
<path
fill="currentColor"
d="M542.22 32.05c-54.8 3.11-163.72 14.43-230.96 55.59-4.64 2.84-7.27 7.89-7.27 13.17v363.87c0 11.55 12.63 18.85 23.28 13.49 69.18-34.82 169.23-44.32 218.7-46.92 16.89-.89 30.02-14.43 30.02-30.66V62.75c.01-17.71-15.35-31.74-33.77-30.7zM264.73 87.64C197.5 46.48 88.58 35.17 33.78 32.05 15.36 31.01 0 45.04 0 62.75V400.6c0 16.24 13.13 29.78 30.02 30.66 49.49 2.6 149.59 12.11 218.77 46.95 10.62 5.35 23.21-1.94 23.21-13.46V100.63c0-5.29-2.62-10.14-7.27-12.99z"
></path>
</svg>
);
export const LibraryButton: React.FC<{
appState: AppState;
setAppState: React.Component<any, AppState>["setState"];
}> = ({ appState, setAppState }) => {
return (
<label
className={clsx(
"ToolIcon ToolIcon_type_floating ToolIcon__library zen-mode-visibility",
`ToolIcon_size_m`,
{
"zen-mode-visibility--hidden": appState.zenModeEnabled,
},
)}
title={`${capitalizeString(t("toolBar.library"))} — 9`}
style={{ marginInlineStart: "var(--space-factor)" }}
>
<input
className="ToolIcon_type_checkbox"
type="checkbox"
name="editor-library"
onChange={(event) => {
setAppState({ isLibraryOpen: event.target.checked });
}}
checked={appState.isLibraryOpen}
aria-label={capitalizeString(t("toolBar.library"))}
aria-keyshortcuts="9"
/>
<div className="ToolIcon__icon">{LIBRARY_ICON}</div>
</label>
);
};
-1
View File
@@ -39,7 +39,6 @@ export const LibraryUnit = ({
const svg = exportToSvg(elementsToRender, {
exportBackground: false,
viewBackgroundColor: oc.white,
shouldAddWatermark: false,
});
for (const child of ref.current!.children) {
if (child.tagName !== "svg") {
@@ -8,10 +8,8 @@ type LockIconSize = "s" | "m";
type LockIconProps = {
title?: string;
name?: string;
id?: string;
checked: boolean;
onChange?(): void;
size?: LockIconSize;
zenModeEnabled?: boolean;
};
@@ -41,12 +39,12 @@ const ICONS = {
),
};
export const LockIcon = (props: LockIconProps) => {
export const LockButton = (props: LockIconProps) => {
return (
<label
className={clsx(
"ToolIcon ToolIcon__lock ToolIcon_type_floating zen-mode-visibility",
`ToolIcon_size_${props.size || DEFAULT_SIZE}`,
`ToolIcon_size_${DEFAULT_SIZE}`,
{
"zen-mode-visibility--hidden": props.zenModeEnabled,
},
@@ -57,7 +55,6 @@ export const LockIcon = (props: LockIconProps) => {
className="ToolIcon_type_checkbox"
type="checkbox"
name={props.name}
id={props.id}
onChange={props.onChange}
checked={props.checked}
aria-label={props.title}
+4 -3
View File
@@ -13,9 +13,10 @@ import { SelectedShapeActions, ShapesSwitcher } from "./Actions";
import { Section } from "./Section";
import CollabButton from "./CollabButton";
import { SCROLLBAR_WIDTH, SCROLLBAR_MARGIN } from "../scene/scrollbars";
import { LockIcon } from "./LockIcon";
import { LockButton } from "./LockButton";
import { UserList } from "./UserList";
import { BackgroundPickerAndDarkModeToggle } from "./BackgroundPickerAndDarkModeToggle";
import { LibraryButton } from "./LibraryButton";
type MobileMenuProps = {
appState: AppState;
@@ -64,15 +65,15 @@ export const MobileMenu = ({
canvas={canvas}
elementType={appState.elementType}
setAppState={setAppState}
isLibraryOpen={appState.isLibraryOpen}
/>
</Stack.Row>
</Island>
<LockIcon
<LockButton
checked={appState.elementLocked}
onChange={onLockToggle}
title={t("toolBar.lock")}
/>
<LibraryButton appState={appState} setAppState={setAppState} />
</Stack.Row>
{libraryMenu}
</Stack.Col>
+1 -1
View File
@@ -58,7 +58,7 @@ const useBodyRoot = (theme: AppState["theme"]) => {
const isMobileRef = useRef(isMobile);
isMobileRef.current = isMobile;
const excalidrawContainer = useExcalidrawContainer();
const { container: excalidrawContainer } = useExcalidrawContainer();
useLayoutEffect(() => {
if (div) {
-1
View File
@@ -38,7 +38,6 @@ const ChartPreviewBtn = (props: {
const svg = exportToSvg(elements, {
exportBackground: false,
viewBackgroundColor: oc.white,
shouldAddWatermark: false,
});
const previewNode = previewRef.current!;
+32 -38
View File
@@ -1,9 +1,10 @@
import "./TextInput.scss";
import React, { Component } from "react";
import React, { useState } from "react";
import { focusNearestParent } from "../utils";
import "./ProjectName.scss";
import { useExcalidrawContainer } from "./App";
type Props = {
value: string;
@@ -12,22 +13,19 @@ type Props = {
isNameEditable: boolean;
};
type State = {
fileName: string;
};
export class ProjectName extends Component<Props, State> {
state = {
fileName: this.props.value,
};
private handleBlur = (event: any) => {
export const ProjectName = (props: Props) => {
const { id } = useExcalidrawContainer();
const [fileName, setFileName] = useState<string>(props.value);
const handleBlur = (event: any) => {
focusNearestParent(event.target);
const value = event.target.value;
if (value !== this.props.value) {
this.props.onChange(value);
if (value !== props.value) {
props.onChange(value);
}
};
private handleKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {
const handleKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {
if (event.key === "Enter") {
event.preventDefault();
if (event.nativeEvent.isComposing || event.keyCode === 229) {
@@ -37,29 +35,25 @@ export class ProjectName extends Component<Props, State> {
}
};
public render() {
return (
<div className="ProjectName">
<label className="ProjectName-label" htmlFor="filename">
{`${this.props.label}${this.props.isNameEditable ? "" : ":"}`}
</label>
{this.props.isNameEditable ? (
<input
className="TextInput"
onBlur={this.handleBlur}
onKeyDown={this.handleKeyDown}
id="filename"
value={this.state.fileName}
onChange={(event) =>
this.setState({ fileName: event.target.value })
}
/>
) : (
<span className="TextInput TextInput--readonly" id="filename">
{this.props.value}
</span>
)}
</div>
);
}
}
return (
<div className="ProjectName">
<label className="ProjectName-label" htmlFor="filename">
{`${props.label}${props.isNameEditable ? "" : ":"}`}
</label>
{props.isNameEditable ? (
<input
className="TextInput"
onBlur={handleBlur}
onKeyDown={handleKeyDown}
id={`${id}-filename`}
value={fileName}
onChange={(event) => setFileName(event.target.value)}
/>
) : (
<span className="TextInput TextInput--readonly" id={`${id}-filename`}>
{props.value}
</span>
)}
</div>
);
};
+4 -2
View File
@@ -1,5 +1,6 @@
import React from "react";
import { t } from "../i18n";
import { useExcalidrawContainer } from "./App";
interface SectionProps extends React.HTMLProps<HTMLElement> {
heading: string;
@@ -7,13 +8,14 @@ interface SectionProps extends React.HTMLProps<HTMLElement> {
}
export const Section = ({ heading, children, ...props }: SectionProps) => {
const { id } = useExcalidrawContainer();
const header = (
<h2 className="visually-hidden" id={`${heading}-title`}>
<h2 className="visually-hidden" id={`${id}-${heading}-title`}>
{t(`headings.${heading}`)}
</h2>
);
return (
<section {...props} aria-labelledby={`${heading}-title`}>
<section {...props} aria-labelledby={`${id}-${heading}-title`}>
{typeof children === "function" ? (
children(header)
) : (
+3 -1
View File
@@ -2,6 +2,7 @@ import "./ToolIcon.scss";
import React from "react";
import clsx from "clsx";
import { useExcalidrawContainer } from "./App";
type ToolIconSize = "s" | "m";
@@ -43,6 +44,7 @@ type ToolButtonProps =
const DEFAULT_SIZE: ToolIconSize = "m";
export const ToolButton = React.forwardRef((props: ToolButtonProps, ref) => {
const { id: excalId } = useExcalidrawContainer();
const innerRef = React.useRef(null);
React.useImperativeHandle(ref, () => innerRef.current);
const sizeCn = `ToolIcon_size_${props.size || DEFAULT_SIZE}`;
@@ -98,7 +100,7 @@ export const ToolButton = React.forwardRef((props: ToolButtonProps, ref) => {
aria-label={props["aria-label"]}
aria-keyshortcuts={props["aria-keyshortcuts"]}
data-testid={props["data-testid"]}
id={props.id}
id={`${excalId}-${props.id}`}
onChange={props.onChange}
checked={props.checked}
ref={innerRef}
+38 -11
View File
@@ -8,10 +8,18 @@
position: relative;
font-family: Cascadia;
cursor: pointer;
background-color: var(--button-gray-1);
-webkit-tap-highlight-color: transparent;
border-radius: var(--space-factor);
user-select: none;
background-color: var(--button-gray-1);
&:hover {
background-color: var(--button-gray-2);
}
&:active {
background-color: var(--button-gray-3);
}
}
.ToolIcon--plain {
@@ -66,14 +74,6 @@
margin: 0;
font-size: inherit;
&:hover {
background-color: var(--button-gray-1);
}
&:active {
background-color: var(--button-gray-2);
}
&:focus {
box-shadow: 0 0 0 2px var(--focus-highlight-color);
}
@@ -86,6 +86,14 @@
}
}
&:hover {
background-color: var(--button-gray-2);
}
&:active {
background-color: var(--button-gray-3);
}
&--show {
visibility: visible;
}
@@ -103,6 +111,9 @@
&:not(.ToolIcon_toggle_opaque):checked + .ToolIcon__icon {
background-color: var(--button-gray-2);
&:active {
background-color: var(--button-gray-3);
}
}
&:focus + .ToolIcon__icon {
@@ -130,12 +141,21 @@
}
.ToolIcon__icon {
background-color: var(--button-gray-1);
&:hover {
background-color: var(--button-gray-2);
}
&:active {
background-color: var(--button-gray-3);
}
width: 2rem;
height: 2em;
}
}
.ToolIcon.ToolIcon__lock {
margin-inline-end: var(--space-factor);
&.ToolIcon_type_floating {
margin-left: 0.1rem;
}
@@ -166,10 +186,9 @@
// move the lock button out of the way on small viewports
// it begins to collide with the GitHub icon before we switch to mobile mode
@media (max-width: 760px) {
.ToolIcon.ToolIcon__lock {
.ToolIcon.ToolIcon_type_floating {
display: inline-block;
position: absolute;
top: 60px;
right: -8px;
margin-left: 0;
@@ -194,6 +213,14 @@
position: static;
}
}
.ToolIcon.ToolIcon__library {
top: 100px;
}
.ToolIcon.ToolIcon__lock {
margin-inline-end: 0;
top: 60px;
}
}
.unlocked-icon {
+11 -9
View File
@@ -24,7 +24,10 @@ type Opts = {
mirror?: true;
} & React.SVGProps<SVGSVGElement>;
const createIcon = (d: string | React.ReactNode, opts: number | Opts = 512) => {
export const createIcon = (
d: string | React.ReactNode,
opts: number | Opts = 512,
) => {
const { width = 512, height = width, mirror, style } =
typeof opts === "number" ? ({ width: opts } as Opts) : opts;
return (
@@ -90,14 +93,8 @@ export const exportFile = createIcon(
export const exportImage = createIcon(
<>
<path
d="M571 308l-95.7-96.4c-10.1-10.1-27.4-3-27.4 11.3V288h-64v64h64v65.2c0 14.3 17.3 21.4 27.4 11.3L571 332c6.6-6.6 6.6-17.4 0-24zm-187 44v-64 64z"
fill-rule="nonzero"
/>
<path
d="M384 121.941V128H256V0h6.059c6.362 0 12.471 2.53 16.97 7.029l97.941 97.941a24.01 24.01 0 017.03 16.971zM248 160c-13.2 0-24-10.8-24-24V0H24C10.745 0 0 10.745 0 24v464c0 13.255 10.745 24 24 24h336c13.255 0 24-10.745 24-24V160H248zm-135.455 16c26.51 0 48 21.49 48 48s-21.49 48-48 48-48-21.49-48-48 21.491-48 48-48zm208 240h-256l.485-48.485L104.545 328c4.686-4.686 11.799-4.201 16.485.485L160.545 368 264.06 264.485c4.686-4.686 12.284-4.686 16.971 0L320.545 304v112z"
fill-rule="nonzero"
/>
<path d="M571 308l-95.7-96.4c-10.1-10.1-27.4-3-27.4 11.3V288h-64v64h64v65.2c0 14.3 17.3 21.4 27.4 11.3L571 332c6.6-6.6 6.6-17.4 0-24zm-187 44v-64 64z" />
<path d="M384 121.941V128H256V0h6.059c6.362 0 12.471 2.53 16.97 7.029l97.941 97.941a24.01 24.01 0 017.03 16.971zM248 160c-13.2 0-24-10.8-24-24V0H24C10.745 0 0 10.745 0 24v464c0 13.255 10.745 24 24 24h336c13.255 0 24-10.745 24-24V160H248zm-135.455 16c26.51 0 48 21.49 48 48s-21.49 48-48 48-48-21.49-48-48 21.491-48 48-48zm208 240h-256l.485-48.485L104.545 328c4.686-4.686 11.799-4.201 16.485.485L160.545 368 264.06 264.485c4.686-4.686 12.284-4.686 16.971 0L320.545 304v112z" />
</>,
{ width: 576, height: 512, mirror: true },
);
@@ -480,6 +477,11 @@ export const shield = createIcon(
{ width: 24 },
);
export const file = createIcon(
"M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48zm32-48h224V288l-23.5-23.5c-4.7-4.7-12.3-4.7-17 0L176 352l-39.5-39.5c-4.7-4.7-12.3-4.7-17 0L80 352v64zm48-240c-26.5 0-48 21.5-48 48s21.5 48 48 48 48-21.5 48-48-21.5-48-48-48z",
{ width: 384, height: 512 },
);
export const GroupIcon = React.memo(({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<>
+16 -9
View File
@@ -1,6 +1,6 @@
import { FontFamily } from "./element/types";
import cssVariables from "./css/variables.module.scss";
import { AppProps } from "./types";
import { FontFamilyValues } from "./element/types";
export const APP_NAME = "Excalidraw";
@@ -63,15 +63,15 @@ export const CLASSES = {
// 1-based in case we ever do `if(element.fontFamily)`
export const FONT_FAMILY = {
1: "Virgil",
2: "Helvetica",
3: "Cascadia",
} as const;
Virgil: 1,
Helvetica: 2,
Cascadia: 3,
};
export const WINDOWS_EMOJI_FALLBACK_FONT = "Segoe UI Emoji";
export const DEFAULT_FONT_SIZE = 20;
export const DEFAULT_FONT_FAMILY: FontFamily = 1;
export const DEFAULT_FONT_FAMILY: FontFamilyValues = FONT_FAMILY.Virgil;
export const DEFAULT_TEXT_ALIGN = "left";
export const DEFAULT_VERTICAL_ALIGN = "top";
export const DEFAULT_VERSION = "{version}";
@@ -97,6 +97,10 @@ export const STORAGE_KEYS = {
LOCAL_STORAGE_LIBRARY: "excalidraw-library",
} as const;
export const IDB_KEYS = {
fileHandle: "fileHandle",
} as const;
// time in milliseconds
export const TAP_TWICE_TIMEOUT = 300;
export const TOUCH_CTX_MENU_TIMEOUT = 500;
@@ -131,11 +135,11 @@ export const DEFAULT_UI_OPTIONS: AppProps["UIOptions"] = {
canvasActions: {
changeViewBackgroundColor: true,
clearCanvas: true,
export: true,
export: { saveFileToDisk: true },
loadScene: true,
saveAsScene: true,
saveScene: true,
saveToActiveFile: true,
theme: true,
saveAsImage: true,
},
};
@@ -144,3 +148,6 @@ export const MQ_MAX_WIDTH_LANDSCAPE = 1000;
export const MQ_MAX_HEIGHT_LANDSCAPE = 500;
export const MAX_DECIMALS_FOR_SVG_EXPORT = 2;
export const EXPORT_SCALES = [1, 2, 3];
export const DEFAULT_EXPORT_PADDING = 10; // px
+3 -2
View File
@@ -51,11 +51,12 @@
image-rendering: -moz-crisp-edges; // FF
z-index: var(--zIndex-canvas);
}
#canvas {
// Remove the main canvas from document flow to avoid resizeObserver
// feedback loop (see https://github.com/excalidraw/excalidraw/pull/3379)
}
&__canvas {
position: absolute;
}
+3 -9
View File
@@ -3,6 +3,7 @@ import {
copyBlobToClipboardAsPng,
copyTextToSystemClipboard,
} from "../clipboard";
import { DEFAULT_EXPORT_PADDING } from "../constants";
import { NonDeletedExcalidrawElement } from "../element/types";
import { t } from "../i18n";
import { exportToCanvas, exportToSvg } from "../scene/export";
@@ -20,18 +21,14 @@ export const exportCanvas = async (
appState: AppState,
{
exportBackground,
exportPadding = 10,
exportPadding = DEFAULT_EXPORT_PADDING,
viewBackgroundColor,
name,
scale = 1,
shouldAddWatermark,
}: {
exportBackground: boolean;
exportPadding?: number;
viewBackgroundColor: string;
name: string;
scale?: number;
shouldAddWatermark: boolean;
},
) => {
if (elements.length === 0) {
@@ -43,8 +40,7 @@ export const exportCanvas = async (
exportWithDarkMode: appState.exportWithDarkMode,
viewBackgroundColor,
exportPadding,
scale,
shouldAddWatermark,
exportScale: appState.exportScale,
metadata:
appState.exportEmbedScene && type === "svg"
? await (
@@ -70,8 +66,6 @@ export const exportCanvas = async (
exportBackground,
viewBackgroundColor,
exportPadding,
scale,
shouldAddWatermark,
});
tempCanvas.style.display = "none";
document.body.appendChild(tempCanvas);
+28 -1
View File
@@ -1,4 +1,4 @@
import { fileOpen, fileSave } from "browser-fs-access";
import { fileOpen, fileSave, FileSystemHandle } from "browser-fs-access";
import { cleanAppStateForExport } from "../appState";
import { EXPORT_DATA_TYPES, EXPORT_SOURCE, MIME_TYPES } from "../constants";
import { clearElementsForExport } from "../element";
@@ -12,6 +12,7 @@ import {
ExportedLibraryData,
} from "./types";
import Library from "./library";
import { AbortError } from "../errors";
export const serializeAsJSON = (
elements: readonly ExcalidrawElement[],
@@ -28,6 +29,26 @@ export const serializeAsJSON = (
return JSON.stringify(data, null, 2);
};
// adapted from https://web.dev/file-system-access
const verifyPermission = async (fileHandle: FileSystemHandle) => {
try {
const options = { mode: "readwrite" } as any;
// Check if permission was already granted. If so, return true.
if ((await fileHandle.queryPermission(options)) === "granted") {
return true;
}
// Request permission. If the user grants permission, return true.
if ((await fileHandle.requestPermission(options)) === "granted") {
return true;
}
// The user didn't grant permission, so return false.
return false;
} catch (error) {
console.error(error);
return false;
}
};
export const saveAsJSON = async (
elements: readonly ExcalidrawElement[],
appState: AppState,
@@ -37,6 +58,12 @@ export const saveAsJSON = async (
type: MIME_TYPES.excalidraw,
});
if (appState.fileHandle) {
if (!(await verifyPermission(appState.fileHandle))) {
throw new AbortError();
}
}
const fileHandle = await fileSave(
blob,
{
+1 -1
View File
@@ -2,7 +2,7 @@ import { loadLibraryFromBlob } from "./blob";
import { LibraryItems, LibraryItem } from "../types";
import { restoreElements } from "./restore";
import { getNonDeletedElements } from "../element";
import App from "../components/App";
import type App from "../components/App";
class Library {
private libraryCache: LibraryItems | null = null;
+8 -8
View File
@@ -1,18 +1,18 @@
import {
ExcalidrawElement,
FontFamily,
ExcalidrawSelectionElement,
FontFamilyValues,
} from "../element/types";
import { AppState, NormalizedZoomValue } from "../types";
import { ImportedDataState } from "./types";
import { isInvisiblySmallElement, getNormalizedDimensions } from "../element";
import { getNormalizedDimensions, isInvisiblySmallElement } from "../element";
import { isLinearElementType } from "../element/typeChecks";
import { randomId } from "../random";
import {
FONT_FAMILY,
DEFAULT_FONT_FAMILY,
DEFAULT_TEXT_ALIGN,
DEFAULT_VERTICAL_ALIGN,
FONT_FAMILY,
} from "../constants";
import { getDefaultAppState } from "../appState";
import { LinearElementEditor } from "../element/linearElementEditor";
@@ -41,11 +41,11 @@ export type RestoredDataState = {
appState: RestoredAppState;
};
const getFontFamilyByName = (fontFamilyName: string): FontFamily => {
for (const [id, fontFamilyString] of Object.entries(FONT_FAMILY)) {
if (fontFamilyString.includes(fontFamilyName)) {
return parseInt(id) as FontFamily;
}
const getFontFamilyByName = (fontFamilyName: string): FontFamilyValues => {
if (Object.keys(FONT_FAMILY).includes(fontFamilyName)) {
return FONT_FAMILY[
fontFamilyName as keyof typeof FONT_FAMILY
] as FontFamilyValues;
}
return DEFAULT_FONT_FAMILY;
};
+1 -1
View File
@@ -5,7 +5,7 @@ import { mutateElement } from "./mutateElement";
import { getPerfectElementSize } from "./sizeHelpers";
import Scene from "../scene/Scene";
import { NonDeletedExcalidrawElement } from "./types";
import { PointerDownState } from "../components/App";
import { PointerDownState } from "../types";
export const dragSelectedElements = (
pointerDownState: PointerDownState,
+2 -1
View File
@@ -1,6 +1,7 @@
import { duplicateElement } from "./newElement";
import { mutateElement } from "./mutateElement";
import { API } from "../tests/helpers/api";
import { FONT_FAMILY } from "../constants";
const isPrimitive = (val: any) => {
const type = typeof val;
@@ -79,7 +80,7 @@ it("clones text element", () => {
opacity: 100,
text: "hello",
fontSize: 20,
fontFamily: 1,
fontFamily: FONT_FAMILY.Virgil,
textAlign: "left",
verticalAlign: "top",
});
+15 -3
View File
@@ -5,11 +5,11 @@ import {
ExcalidrawGenericElement,
NonDeleted,
TextAlign,
FontFamily,
GroupId,
VerticalAlign,
Arrowhead,
ExcalidrawFreeDrawElement,
FontFamilyValues,
} from "../element/types";
import { measureText, getFontString } from "../utils";
import { randomInteger, randomId } from "../random";
@@ -109,7 +109,7 @@ export const newTextElement = (
opts: {
text: string;
fontSize: number;
fontFamily: FontFamily;
fontFamily: FontFamilyValues;
textAlign: TextAlign;
verticalAlign: VerticalAlign;
} & ElementConstructorOpts,
@@ -307,7 +307,19 @@ export const duplicateElement = <TElement extends Mutable<ExcalidrawElement>>(
overrides?: Partial<TElement>,
): TElement => {
let copy: TElement = deepCopyElement(element);
copy.id = process.env.NODE_ENV === "test" ? `${copy.id}_copy` : randomId();
if (process.env.NODE_ENV === "test") {
copy.id = `${copy.id}_copy`;
// `window.h` may not be defined in some unit tests
if (
window.h?.app
?.getSceneElementsIncludingDeleted()
.find((el) => el.id === copy.id)
) {
copy.id += "_copy";
}
} else {
copy.id = randomId();
}
copy.seed = randomInteger();
copy.groupIds = getNewGroupIdsForDuplication(
copy.groupIds,
+1 -2
View File
@@ -32,8 +32,7 @@ import {
MaybeTransformHandleType,
TransformHandleDirection,
} from "./transformHandles";
import { PointerDownState } from "../components/App";
import { Point } from "../types";
import { Point, PointerDownState } from "../types";
export const normalizeAngle = (angle: number): number => {
if (angle >= 2 * Math.PI) {
+3 -2
View File
@@ -3,7 +3,8 @@ import { FONT_FAMILY } from "../constants";
export type ChartType = "bar" | "line";
export type FillStyle = "hachure" | "cross-hatch" | "solid";
export type FontFamily = keyof typeof FONT_FAMILY;
export type FontFamilyKeys = keyof typeof FONT_FAMILY;
export type FontFamilyValues = typeof FONT_FAMILY[FontFamilyKeys];
export type FontString = string & { _brand: "fontString" };
export type GroupId = string;
export type PointerType = "mouse" | "pen" | "touch";
@@ -91,7 +92,7 @@ export type ExcalidrawTextElement = _ExcalidrawElementBase &
Readonly<{
type: "text";
fontSize: number;
fontFamily: FontFamily;
fontFamily: FontFamilyValues;
text: string;
baseline: number;
textAlign: TextAlign;
+9
View File
@@ -1,4 +1,5 @@
type CANVAS_ERROR_NAMES = "CANVAS_ERROR" | "CANVAS_POSSIBLY_TOO_BIG";
export class CanvasError extends Error {
constructor(
message: string = "Couldn't export canvas.",
@@ -9,3 +10,11 @@ export class CanvasError extends Error {
this.message = message;
}
}
export class AbortError extends Error {
constructor(message: string = "Request aborted") {
super();
this.name = "AbortError";
this.message = message;
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
import throttle from "lodash.throttle";
import React, { PureComponent } from "react";
import { ExcalidrawImperativeAPI } from "../../components/App";
import { ExcalidrawImperativeAPI } from "../../types";
import { ErrorDialog } from "../../components/ErrorDialog";
import { APP_NAME, ENV, EVENT } from "../../constants";
import { ImportedDataState } from "../../data/types";
@@ -0,0 +1,92 @@
import React from "react";
import { Card } from "../../components/Card";
import { ToolButton } from "../../components/ToolButton";
import { serializeAsJSON } from "../../data/json";
import { getImportedKey, createIV, generateEncryptionKey } from "../data";
import { loadFirebaseStorage } from "../data/firebase";
import { NonDeletedExcalidrawElement } from "../../element/types";
import { AppState } from "../../types";
import { nanoid } from "nanoid";
import { t } from "../../i18n";
import { excalidrawPlusIcon } from "./icons";
const encryptData = async (
key: string,
json: string,
): Promise<{ blob: Blob; iv: Uint8Array }> => {
const importedKey = await getImportedKey(key, "encrypt");
const iv = createIV();
const encoded = new TextEncoder().encode(json);
const ciphertext = await window.crypto.subtle.encrypt(
{
name: "AES-GCM",
iv,
},
importedKey,
encoded,
);
return { blob: new Blob([new Uint8Array(ciphertext)]), iv };
};
const exportToExcalidrawPlus = async (
elements: readonly NonDeletedExcalidrawElement[],
appState: AppState,
) => {
const firebase = await loadFirebaseStorage();
const id = `${nanoid(12)}`;
const key = (await generateEncryptionKey())!;
const encryptedData = await encryptData(
key,
serializeAsJSON(elements, appState),
);
const blob = new Blob([encryptedData.iv, encryptedData.blob], {
type: "application/octet-stream",
});
await firebase
.storage()
.ref(`/migrations/scenes/${id}`)
.put(blob, {
customMetadata: {
data: JSON.stringify({ version: 1, name: appState.name }),
created: Date.now().toString(),
},
});
window.open(`https://plus.excalidraw.com/import?excalidraw=${id},${key}`);
};
export const ExportToExcalidrawPlus: React.FC<{
elements: readonly NonDeletedExcalidrawElement[];
appState: AppState;
onError: (error: Error) => void;
}> = ({ elements, appState, onError }) => {
return (
<Card color="indigo">
<div className="Card-icon">{excalidrawPlusIcon}</div>
<h2>Excalidraw+</h2>
<div className="Card-details">
{t("exportDialog.excalidrawplus_description")}
</div>
<ToolButton
className="Card-button"
type="button"
title={t("exportDialog.excalidrawplus_button")}
aria-label={t("exportDialog.excalidrawplus_button")}
showAriaLabel={true}
onClick={async () => {
try {
await exportToExcalidrawPlus(elements, appState);
} catch (error) {
console.error(error);
onError(new Error(t("exportDialog.excalidrawplus_exportError")));
}
}}
/>
</Card>
);
};
File diff suppressed because one or more lines are too long
+35 -7
View File
@@ -5,15 +5,19 @@ import { getSceneVersion } from "../../element";
import Portal from "../collab/Portal";
import { restoreElements } from "../../data/restore";
// private
// -----------------------------------------------------------------------------
let firebasePromise: Promise<
typeof import("firebase/app").default
> | null = null;
let firestorePromise: Promise<any> | null = null;
let firebseStoragePromise: Promise<any> | null = null;
const loadFirebase = async () => {
const _loadFirebase = async () => {
const firebase = (
await import(/* webpackChunkName: "firebase" */ "firebase/app")
).default;
await import(/* webpackChunkName: "firestore" */ "firebase/firestore");
const firebaseConfig = JSON.parse(process.env.REACT_APP_FIREBASE_CONFIG);
firebase.initializeApp(firebaseConfig);
@@ -21,13 +25,37 @@ const loadFirebase = async () => {
return firebase;
};
const getFirebase = async (): Promise<
const _getFirebase = async (): Promise<
typeof import("firebase/app").default
> => {
if (!firebasePromise) {
firebasePromise = loadFirebase();
firebasePromise = _loadFirebase();
}
return await firebasePromise!;
return firebasePromise;
};
// -----------------------------------------------------------------------------
const loadFirestore = async () => {
const firebase = await _getFirebase();
if (!firestorePromise) {
firestorePromise = import(
/* webpackChunkName: "firestore" */ "firebase/firestore"
);
await firestorePromise;
}
return firebase;
};
export const loadFirebaseStorage = async () => {
const firebase = await _getFirebase();
if (!firebseStoragePromise) {
firebseStoragePromise = import(
/* webpackChunkName: "storage" */ "firebase/storage"
);
await firebseStoragePromise;
}
return firebase;
};
interface FirebaseStoredScene {
@@ -108,7 +136,7 @@ export const saveToFirebase = async (
return true;
}
const firebase = await getFirebase();
const firebase = await loadFirestore();
const sceneVersion = getSceneVersion(elements);
const { ciphertext, iv } = await encryptElements(roomKey, elements);
@@ -150,7 +178,7 @@ export const loadFromFirebase = async (
roomKey: string,
socket: SocketIOClient.Socket | null,
): Promise<readonly ExcalidrawElement[] | null> => {
const firebase = await getFirebase();
const firebase = await loadFirestore();
const db = firebase.firestore();
const docRef = db.collection("scenes").doc(roomId);
+2 -2
View File
@@ -17,7 +17,7 @@ const generateRandomID = async () => {
return Array.from(arr, byteToHex).join("");
};
const generateEncryptionKey = async () => {
export const generateEncryptionKey = async () => {
const key = await window.crypto.subtle.generateKey(
{
name: "AES-GCM",
@@ -176,7 +176,7 @@ export const getImportedKey = (key: string, usage: KeyUsage) =>
[usage],
);
const decryptImported = async (
export const decryptImported = async (
iv: ArrayBuffer,
encrypted: ArrayBuffer,
privateKey: string,
+25 -3
View File
@@ -8,7 +8,6 @@ import React, {
} from "react";
import { trackEvent } from "../analytics";
import { getDefaultAppState } from "../appState";
import { ExcalidrawImperativeAPI } from "../components/App";
import { ErrorDialog } from "../components/ErrorDialog";
import { TopErrorBoundary } from "../components/TopErrorBoundary";
import {
@@ -31,7 +30,7 @@ import Excalidraw, {
defaultLang,
languages,
} from "../packages/excalidraw/index";
import { AppState, LibraryItems } from "../types";
import { AppState, LibraryItems, ExcalidrawImperativeAPI } from "../types";
import {
debounce,
getVersion,
@@ -56,6 +55,7 @@ import { Tooltip } from "../components/Tooltip";
import { shield } from "../components/icons";
import "./index.scss";
import { ExportToExcalidrawPlus } from "./components/ExportToExcalidrawPlus";
const languageDetector = new LanguageDetector();
languageDetector.init({
@@ -424,7 +424,28 @@ const ExcalidrawWrapper = () => {
onCollabButtonClick={collabAPI?.onCollabButtonClick}
isCollaborating={collabAPI?.isCollaborating()}
onPointerUpdate={collabAPI?.onPointerUpdate}
onExportToBackend={onExportToBackend}
UIOptions={{
canvasActions: {
export: {
onExportToBackend,
renderCustomUI: (elements, appState) => {
return (
<ExportToExcalidrawPlus
elements={elements}
appState={appState}
onError={(error) => {
excalidrawAPI?.updateScene({
appState: {
errorMessage: error.message,
},
});
}}
/>
);
},
},
},
}}
renderTopRightUI={renderTopRightUI}
renderFooter={renderFooter}
langCode={langCode}
@@ -432,6 +453,7 @@ const ExcalidrawWrapper = () => {
detectScroll={false}
handleKeyboardGlobally={true}
onLibraryChange={onLibraryChange}
autoFocus={true}
/>
{excalidrawAPI && <CollabWrapper excalidrawAPI={excalidrawAPI} />}
{errorMessage && (
+2 -1
View File
@@ -21,6 +21,7 @@ interface DehydratedHistoryEntry {
const clearAppStatePropertiesForHistory = (appState: AppState) => {
return {
selectedElementIds: appState.selectedElementIds,
selectedGroupIds: appState.selectedGroupIds,
viewBackgroundColor: appState.viewBackgroundColor,
editingLinearElement: appState.editingLinearElement,
editingGroupId: appState.editingGroupId,
@@ -169,7 +170,7 @@ class History {
continue;
}
}
if (key === "selectedElementIds") {
if (key === "selectedElementIds" || key === "selectedGroupIds") {
continue;
}
if (nextEntry.appState[key] !== lastEntry.appState[key]) {
+1
View File
@@ -48,6 +48,7 @@ const allLanguages: Language[] = [
{ code: "zh-CN", label: "简体中文" },
{ code: "zh-TW", label: "繁體中文" },
{ code: "lv-LV", label: "Latviešu" },
{ code: "cs-CZ", label: "Česky" },
].concat([defaultLang]);
export const languages: Language[] = allLanguages
-2
View File
@@ -69,8 +69,6 @@ const canvas = exportToCanvas(
{
exportBackground: true,
viewBackgroundColor: "#ffffff",
shouldAddWatermark: false,
scale: 1,
},
createCanvas,
);
+1
View File
@@ -44,6 +44,7 @@ export const KEYS = {
A: "a",
D: "d",
E: "e",
G: "g",
L: "l",
O: "o",
P: "p",
+55 -35
View File
@@ -20,6 +20,10 @@
"background": "الخلفية",
"fill": "التعبئة",
"strokeWidth": "حجم الحدود",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "نمط الحدود",
"strokeStyle_solid": "صلبة",
"strokeStyle_dashed": "متقطع",
@@ -38,8 +42,8 @@
"fontSize": "حجم الخط",
"fontFamily": "نوع الخط",
"onlySelected": "المحدد فقط",
"withBackground": "مع الخلفية",
"exportEmbedScene": "تضمين المشهد في ملف التصدير",
"withBackground": "الخلفية",
"exportEmbedScene": "",
"exportEmbedScene_details": "سيتم حفظ بيانات المشهد في ملف PNG/SVG المصدّر بحيث يمكن استعادة المشهد منه.\nسيزيد حجم الملف المصدر.",
"addWatermark": "إضافة \"مصنوعة بواسطة Excalidraw\"",
"handDrawn": "رسم باليد",
@@ -61,7 +65,7 @@
"architect": "معماري",
"artist": "رسام",
"cartoonist": "كرتوني",
"fileTitle": "",
"fileTitle": "إسم الملف",
"colorPicker": "اختيار الألوان",
"canvasBackground": "خلفية اللوحة",
"drawingCanvas": "لوحة الرسم",
@@ -92,21 +96,26 @@
"centerHorizontally": "توسيط أفقي",
"distributeHorizontally": "التوزيع الأفقي",
"distributeVertically": "التوزيع عمودياً",
"flipHorizontal": "",
"flipVertical": "",
"flipHorizontal": "قلب عامودي",
"flipVertical": "قلب أفقي",
"viewMode": "نمط العرض",
"toggleExportColorScheme": "",
"share": "مشاركة"
"share": "مشاركة",
"showStroke": "",
"showBackground": "",
"toggleTheme": "غير النمط"
},
"buttons": {
"clearReset": "إعادة تعيين اللوحة",
"exportJSON": "صدر الملف",
"exportImage": "إحفظ كصورة",
"export": "تصدير",
"exportToPng": "تصدير بصيغة PNG",
"exportToSvg": "تصدير بصيغة SVG",
"copyToClipboard": "نسخ إلى الحافظة",
"copyPngToClipboard": "نسخ الـ PNG إلى الحافظة",
"scale": "مقاس",
"save": "حفظ",
"save": "احفظ للملف الحالي",
"saveAs": "حفظ كـ",
"load": "تحميل",
"getShareableLink": "احصل على رابط المشاركة",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "تحديد",
"freedraw": "الكتابة الحرة",
"rectangle": "مستطيل",
"diamond": "مضلع",
"ellipse": "دائرة",
"arrow": "سهم",
"line": "خط",
"freedraw": "",
"text": "نص",
"library": "مكتبة",
"lock": "الحفاظ على أداة التحديد نشطة بعد الرسم"
@@ -210,30 +219,41 @@
"errorDialog": {
"title": "خطأ"
},
"exportDialog": {
"disk_title": "حفظ الملف للجهاز",
"disk_details": "",
"disk_button": "إحفظ لملف",
"link_title": "رابط قابل للمشاركة",
"link_details": "صدر الملف للمشاهدة فقط.",
"link_button": "التصدير كرابط",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "",
"click": "",
"curvedArrow": "",
"curvedLine": "",
"documentation": "",
"blog": "اقرأ مدونتنا",
"click": "انقر",
"curvedArrow": "سهم مائل",
"curvedLine": "خط مائل",
"documentation": "دليل الاستخدام",
"drag": "اسحب",
"editor": "المحرر",
"github": "عثرت على مشكلة؟ إرسال",
"howto": "",
"or": "",
"preventBinding": "",
"shapes": "",
"shortcuts": "",
"textFinish": "",
"textNewLine": "",
"title": "",
"view": "",
"zoomToFit": "",
"zoomToSelection": ""
"howto": "اتبع التعليمات",
"or": "أو",
"preventBinding": "منع ارتبط السهم",
"shapes": "أشكال",
"shortcuts": "اختصارات لوحة المفاتيح",
"textFinish": "الانتهاء من التحرير (نص)",
"textNewLine": "اضف سطر جديد (نص)",
"title": "المساعدة",
"view": "عرض",
"zoomToFit": "تكبير للملائمة",
"zoomToSelection": "تكبير للعنصر المحدد"
},
"encrypted": {
"tooltip": "رسوماتك مشفرة من النهاية إلى النهاية حتى أن خوادم Excalidraw لن تراها أبدا.",
"link": ""
"link": "مشاركة المدونة في التشفير من النهاية إلى النهاية في Excalidraw"
},
"stats": {
"angle": "الزاوية",
@@ -245,18 +265,18 @@
"storage": "التخزين",
"title": "إحصائيات للمهووسين",
"total": "المجموع",
"version": "",
"versionCopy": "",
"versionNotAvailable": "",
"version": "الإصدار",
"versionCopy": "انقر للنسخ",
"versionNotAvailable": "الإصدار غير متوفر",
"width": "العرض"
},
"toast": {
"copyStyles": "",
"copyToClipboard": "",
"copyToClipboardAsPng": "",
"fileSaved": "",
"fileSavedToFilename": "",
"canvas": "",
"selection": ""
"copyStyles": "نسخ النمط.",
"copyToClipboard": "نسخ إلى الحافظة.",
"copyToClipboardAsPng": "تم نسخ {{exportSelection}} إلى الحافظة بصيغةPNG\n({{exportColorScheme}})",
"fileSaved": "تم حفظ الملف.",
"fileSavedToFilename": "حفظ باسم {filename}",
"canvas": "لوحة الرسم",
"selection": "العنصر المحدد"
}
}
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Фон",
"fill": "Наситеност",
"strokeWidth": "Ширина на щриха",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "Стил на линия",
"strokeStyle_solid": "Плътен",
"strokeStyle_dashed": "Пунктир",
@@ -38,8 +42,8 @@
"fontSize": "Размер на шрифта",
"fontFamily": "Семейство шрифтове",
"onlySelected": "Само избраното",
"withBackground": "С фон",
"exportEmbedScene": "Вгради сцената във файл",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "Данните от сцената ще бъдат екпортирани в PNG/SVG файл, за да може сцената да бъде възстановена от него.\nТова ще увеличи размера на файла.",
"addWatermark": "Добави \"Направено с Excalidraw\"",
"handDrawn": "Нарисувано на ръка",
@@ -96,17 +100,22 @@
"flipVertical": "",
"viewMode": "Изглед",
"toggleExportColorScheme": "",
"share": ""
"share": "",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "Нулиране на платно",
"exportJSON": "",
"exportImage": "",
"export": "Експортиране",
"exportToPng": "Изнасяне в PNG",
"exportToSvg": "Изнасяне в SVG",
"copyToClipboard": "Копиране в клипборда",
"copyPngToClipboard": "Копирай PNG в клипборда",
"scale": "Мащаб",
"save": "Запази",
"save": "",
"saveAs": "Запиши като",
"load": "Зареждане",
"getShareableLink": "Получаване на връзка за споделяне",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Селекция",
"freedraw": "Рисуване",
"rectangle": "Правоъгълник",
"diamond": "Диамант",
"ellipse": "Елипс",
"arrow": "Стрелка",
"line": "Линия",
"freedraw": "",
"text": "Текст",
"library": "Библиотека",
"lock": "Поддържайте избрания инструмент активен след рисуване"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Грешка"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "Прочетете нашия блог",
"click": "клик",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Color del fons",
"fill": "Estil del fons",
"strokeWidth": "Amplada del traç",
"strokeShape": "Estil del traç",
"strokeShape_gel": "Bolígraf de gel",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "Estil del traç",
"strokeStyle_solid": "Sòlid",
"strokeStyle_dashed": "Guions",
@@ -38,8 +42,8 @@
"fontSize": "Mida de lletra",
"fontFamily": "Tipus de lletra",
"onlySelected": "Només seleccionats",
"withBackground": "Amb fons",
"exportEmbedScene": "Incrustar escena al fitxer exportat",
"withBackground": "Fons",
"exportEmbedScene": "",
"exportEmbedScene_details": "Les dades de lescena es desaran al fitxer PNG/SVG de manera que es pugui restaurar lescena.\nAugmentarà la mida del fitxer exportat.",
"addWatermark": "Afegir \"Fet amb Excalidraw\"",
"handDrawn": "Dibuixat a mà",
@@ -96,17 +100,22 @@
"flipVertical": "Capgira verticalment",
"viewMode": "Mode de visualització",
"toggleExportColorScheme": "Canvia l'esquema de colors de l'exportació",
"share": "Compartir"
"share": "Compartir",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "Netejar el llenç",
"exportJSON": "Exporta a un fitxer",
"exportImage": "Desa com a imatge",
"export": "Exportar",
"exportToPng": "Exportar a PNG",
"exportToSvg": "Exportar a SNG",
"copyToClipboard": "Copiar al porta-retalls",
"copyPngToClipboard": "Copiar PNG al porta-retalls",
"scale": "Escala",
"save": "Desar",
"save": "Desa al fitxer actual",
"saveAs": "Desar com",
"load": "Carregar",
"getShareableLink": "Obtenir enllaç per compartir",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Selecció",
"freedraw": "Dibuix lliure",
"rectangle": "Rectangle",
"diamond": "Rombe",
"ellipse": "El·lipse",
"arrow": "Fletxa",
"line": "Línia",
"freedraw": "Dibuix",
"text": "Text",
"library": "Biblioteca",
"lock": "Mantenir activa l'eina seleccionada desprès de dibuixar"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Error"
},
"exportDialog": {
"disk_title": "Desa la disc",
"disk_details": "",
"disk_button": "Desa en un fitxer",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "Exporta",
"excalidrawplus_exportError": "No és possible exportar a Excalidraw+ ara mateix..."
},
"helpDialog": {
"blog": "Llegiu el nostre blog",
"click": "clic",
+282
View File
@@ -0,0 +1,282 @@
{
"labels": {
"paste": "Vložit",
"pasteCharts": "Vložit grafy",
"selectAll": "Vybrat vše",
"multiSelect": "Přidat prvek do výběru",
"moveCanvas": "Posunout plátno",
"cut": "Vyjmout",
"copy": "Kopírovat",
"copyAsPng": "Zkopírovat do schránky jako PNG",
"copyAsSvg": "Zkopírovat do schránky jako SVG",
"bringForward": "Přenést blíž",
"sendToBack": "Přenést do pozadí",
"bringToFront": "Přenést do popředí",
"sendBackward": "Přenést dál",
"delete": "Smazat",
"copyStyles": "Kopírovat styly",
"pasteStyles": "Vložit styly",
"stroke": "Obrys",
"background": "Pozadí",
"fill": "Výplň",
"strokeWidth": "Šířka obrysu",
"strokeShape": "Tvar tahu",
"strokeShape_gel": "Gelové pero",
"strokeShape_fountain": "Plnicí pero",
"strokeShape_brush": "Fixa",
"strokeStyle": "Styl tahu",
"strokeStyle_solid": "Plný",
"strokeStyle_dashed": "Čárkovaný",
"strokeStyle_dotted": "Tečkovaný",
"sloppiness": "Stylizace",
"opacity": "Průhlednost",
"textAlign": "Zarovnání textu",
"edges": "Hrany",
"sharp": "Ostré",
"round": "Zaoblené",
"arrowheads": "Styl šipky",
"arrowhead_none": "Žádný",
"arrowhead_arrow": "Šipka",
"arrowhead_bar": "Kóta",
"arrowhead_dot": "Tečka",
"fontSize": "Velikost písma",
"fontFamily": "Písmo",
"onlySelected": "Pouze vybrané",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "",
"addWatermark": "",
"handDrawn": "Od ruky",
"normal": "Normální",
"code": "Kód",
"small": "Malé",
"medium": "Střední",
"large": "Velké",
"veryLarge": "Velmi velké",
"solid": "",
"hachure": "",
"crossHatch": "",
"thin": "",
"bold": "",
"left": "",
"center": "",
"right": "",
"extraBold": "",
"architect": "",
"artist": "",
"cartoonist": "",
"fileTitle": "",
"colorPicker": "",
"canvasBackground": "Pozadí plátna",
"drawingCanvas": "",
"layers": "",
"actions": "",
"language": "",
"liveCollaboration": "",
"duplicateSelection": "",
"untitled": "",
"name": "",
"yourName": "",
"madeWithExcalidraw": "",
"group": "",
"ungroup": "",
"collaborators": "",
"showGrid": "",
"addToLibrary": "",
"removeFromLibrary": "",
"libraryLoadingMessage": "",
"libraries": "",
"loadingScene": "",
"align": "",
"alignTop": "",
"alignBottom": "",
"alignLeft": "",
"alignRight": "",
"centerVertically": "",
"centerHorizontally": "",
"distributeHorizontally": "",
"distributeVertically": "",
"flipHorizontal": "",
"flipVertical": "",
"viewMode": "Náhled",
"toggleExportColorScheme": "",
"share": "Sdílet",
"showStroke": "",
"showBackground": "",
"toggleTheme": "Přepnout tmavý řežim"
},
"buttons": {
"clearReset": "",
"exportJSON": "",
"exportImage": "",
"export": "Exportovat",
"exportToPng": "Exportovat do PNG",
"exportToSvg": "Exportovat do SVG",
"copyToClipboard": "Kopírovat do schránky",
"copyPngToClipboard": "Kopírovat PNG do schránky",
"scale": "Měřítko",
"save": "",
"saveAs": "Uložit jako",
"load": "Nahrát",
"getShareableLink": "Získat odkaz pro sdílení",
"close": "Zavřít",
"selectLanguage": "Zvolit jazyk",
"scrollBackToContent": "",
"zoomIn": "Přiblížit",
"zoomOut": "Oddálit",
"resetZoom": "Resetovat přiblížení",
"menu": "Menu",
"done": "Hotovo",
"edit": "Upravit",
"undo": "Zpět",
"redo": "Znovu",
"resetLibrary": "",
"createNewRoom": "Vytvořit novou místnost",
"fullScreen": "Celá obrazovka",
"darkMode": "Tmavý režim",
"lightMode": "Světlý režim",
"zenMode": "Zen mód",
"exitZenMode": "Opustit zen mód"
},
"alerts": {
"clearReset": "",
"couldNotCreateShareableLink": "",
"couldNotCreateShareableLinkTooBig": "",
"couldNotLoadInvalidFile": "",
"importBackendFailed": "",
"cannotExportEmptyCanvas": "",
"couldNotCopyToClipboard": "",
"decryptFailed": "",
"uploadedSecurly": "",
"loadSceneOverridePrompt": "",
"collabStopOverridePrompt": "",
"errorLoadingLibrary": "",
"errorAddingToLibrary": "",
"errorRemovingFromLibrary": "",
"confirmAddLibrary": "",
"imageDoesNotContainScene": "",
"cannotRestoreFromImage": "",
"invalidSceneUrl": "",
"resetLibrary": ""
},
"toolBar": {
"selection": "Výběr",
"rectangle": "Obdélník",
"diamond": "Diamant",
"ellipse": "Elipsa",
"arrow": "Šipka",
"line": "Čára",
"freedraw": "Kreslení",
"text": "Text",
"library": "",
"lock": ""
},
"headings": {
"canvasActions": "",
"selectedShapeActions": "",
"shapes": "Tvary"
},
"hints": {
"linearElement": "",
"freeDraw": "",
"text": "",
"linearElementMulti": "",
"lockAngle": "",
"resize": "",
"rotate": "",
"lineEditor_info": "",
"lineEditor_pointSelected": "",
"lineEditor_nothingSelected": ""
},
"canvasError": {
"cannotShowPreview": "",
"canvasTooBig": "",
"canvasTooBigTip": ""
},
"errorSplash": {
"headingMain_pre": "",
"headingMain_button": "",
"clearCanvasMessage": "",
"clearCanvasMessage_button": "",
"clearCanvasCaveat": "",
"trackedToSentry_pre": "",
"trackedToSentry_post": "",
"openIssueMessage_pre": "",
"openIssueMessage_button": "",
"openIssueMessage_post": "",
"sceneContent": ""
},
"roomDialog": {
"desc_intro": "",
"desc_privacy": "",
"button_startSession": "",
"button_stopSession": "",
"desc_inProgressIntro": "",
"desc_shareLink": "",
"desc_exitSession": "",
"shareTitle": ""
},
"errorDialog": {
"title": ""
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "",
"click": "kliknutí",
"curvedArrow": "",
"curvedLine": "",
"documentation": "",
"drag": "tažení",
"editor": "",
"github": "",
"howto": "",
"or": "nebo",
"preventBinding": "",
"shapes": "",
"shortcuts": "",
"textFinish": "",
"textNewLine": "",
"title": "",
"view": "",
"zoomToFit": "",
"zoomToSelection": ""
},
"encrypted": {
"tooltip": "",
"link": ""
},
"stats": {
"angle": "",
"element": "",
"elements": "",
"height": "",
"scene": "",
"selected": "",
"storage": "",
"title": "",
"total": "",
"version": "",
"versionCopy": "",
"versionNotAvailable": "",
"width": ""
},
"toast": {
"copyStyles": "",
"copyToClipboard": "",
"copyToClipboardAsPng": "",
"fileSaved": "",
"fileSavedToFilename": "",
"canvas": "plátno",
"selection": "výběr"
}
}
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Hintergrund",
"fill": "Füllung",
"strokeWidth": "Strichstärke",
"strokeShape": "Strichform",
"strokeShape_gel": "Gelschreiber",
"strokeShape_fountain": "Füllfederhalter",
"strokeShape_brush": "Pinselstift",
"strokeStyle": "Konturstil",
"strokeStyle_solid": "Durchgezogen",
"strokeStyle_dashed": "Gestrichelt",
@@ -38,8 +42,8 @@
"fontSize": "Schriftgröße",
"fontFamily": "Schriftfamilie",
"onlySelected": "Nur ausgewählte",
"withBackground": "Mit Hintergrund",
"exportEmbedScene": "Zeichnung in exportierte Datei einbetten",
"withBackground": "Hintergrund",
"exportEmbedScene": "Szene einbetten",
"exportEmbedScene_details": "Die Zeichnungsdaten werden in der exportierten PNG/SVG-Datei gespeichert, sodass das Dokument später weiter bearbeitet werden kann. \nDieses wird die exportierte Datei vergrößern.",
"addWatermark": "\"Made with Excalidraw\" hinzufügen",
"handDrawn": "Handgezeichnet",
@@ -96,17 +100,22 @@
"flipVertical": "Vertikal spiegeln",
"viewMode": "Ansichtsmodus",
"toggleExportColorScheme": "Exportfarbschema umschalten",
"share": "Teilen"
"share": "Teilen",
"showStroke": "Auswahl für Strichfarbe anzeigen",
"showBackground": "Auswahl für Hintergrundfarbe anzeigen",
"toggleTheme": "Design umschalten"
},
"buttons": {
"clearReset": "Zeichenfläche löschen & Hintergrundfarbe zurücksetzen",
"exportJSON": "In Datei exportieren",
"exportImage": "Als Bild speichern",
"export": "Exportieren",
"exportToPng": "Als PNG exportieren",
"exportToSvg": "Als SVG exportieren",
"copyToClipboard": "In Zwischenablage kopieren",
"copyPngToClipboard": "PNG in die Zwischenablage kopieren",
"scale": "Skalierung",
"save": "Speichern",
"save": "In aktueller Datei speichern",
"saveAs": "Speichern unter",
"load": "Laden",
"getShareableLink": "Teilbaren Link erhalten",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Auswahl",
"freedraw": "Freies Zeichnen",
"rectangle": "Rechteck",
"diamond": "Raute",
"ellipse": "Ellipse",
"arrow": "Pfeil",
"line": "Linie",
"freedraw": "Zeichnen",
"text": "Text",
"library": "Bibliothek",
"lock": "Ausgewähltes Werkzeug nach Zeichnen aktiv lassen"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Fehler"
},
"exportDialog": {
"disk_title": "Auf Festplatte speichern",
"disk_details": "Exportiere die Zeichnungsdaten in eine Datei, die Du später importieren kannst.",
"disk_button": "In Datei speichern",
"link_title": "Teilbarer Link",
"link_details": "Als schreibgeschützten Link exportieren.",
"link_button": "Als Link exportieren",
"excalidrawplus_description": "Speichere die Szene in deinem Excalidraw+ Arbeitsbereich.",
"excalidrawplus_button": "Exportieren",
"excalidrawplus_exportError": "Konnte nicht nach Excalidraw+ exportieren..."
},
"helpDialog": {
"blog": "Lies unseren Blog",
"click": "klicken",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Φόντο",
"fill": "Γέμισμα",
"strokeWidth": "Πάχος μολυβιάς",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "Στυλ περιγράμματος",
"strokeStyle_solid": "Συμπαγής",
"strokeStyle_dashed": "Διακεκομμένη με παύλες",
@@ -38,8 +42,8 @@
"fontSize": "Μέγεθος γραμματοσειράς",
"fontFamily": "Γραμματοσειρά",
"onlySelected": "Μόνο τα Επιλεγμένα",
"withBackground": "Με φόντο",
"exportEmbedScene": "Ενσωμάτωση της σκηνής στο αρχείο προς εξαγωγή",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "Τα δεδομένα σκηνής θα αποθηκευτούν στο αρχείο PNG/SVG προς εξαγωγή ώστε η σκηνή να είναι δυνατό να αποκατασταθεί από αυτό.\nΘα αυξήσει το μέγεθος του αρχείου προς εξαγωγή.",
"addWatermark": "Προσθήκη \"Φτιαγμένο με Excalidraw\"",
"handDrawn": "Σχεδιασμένο στο χέρι",
@@ -96,17 +100,22 @@
"flipVertical": "Κατακόρυφη αναστροφή",
"viewMode": "Λειτουργία προβολής",
"toggleExportColorScheme": "Εναλλαγή εξαγωγής θέματος χρωμάτων",
"share": "Κοινοποίηση"
"share": "Κοινοποίηση",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "Επαναφορά του καμβά",
"exportJSON": "",
"exportImage": "",
"export": "Εξαγωγή",
"exportToPng": "Εξαγωγή σε PNG",
"exportToSvg": "Εξαγωγή σε SVG",
"copyToClipboard": "Αντιγραφή στο πρόχειρο",
"copyPngToClipboard": "Αντιγραφή PNG στο πρόχειρο",
"scale": "Κλίμακα",
"save": "Αποθήκευση",
"save": "",
"saveAs": "Αποθήκευση ως",
"load": "Άνοιγμα",
"getShareableLink": "Δημόσιος σύνδεσμος",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Επιλογή",
"freedraw": "Ελεύθερο σχέδιο",
"rectangle": "Ορθογώνιο",
"diamond": "Ρόμβος",
"ellipse": "Έλλειψη",
"arrow": "Βέλος",
"line": "Γραμμή",
"freedraw": "",
"text": "Κείμενο",
"library": "Βιβλιοθήκη",
"lock": "Κράτησε επιλεγμένο το εργαλείο μετά το σχέδιο"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Σφάλμα"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "Διαβάστε το Blog μας",
"click": "κλικ",
+12 -3
View File
@@ -101,6 +101,8 @@
"viewMode": "View mode",
"toggleExportColorScheme": "Toggle export color scheme",
"share": "Share",
"showStroke": "Show stroke color picker",
"showBackground": "Show background color picker",
"toggleTheme": "Toggle theme"
},
"buttons": {
@@ -178,6 +180,8 @@
"linearElement": "Click to start multiple points, drag for single line",
"freeDraw": "Click and drag, release when you're finished",
"text": "Tip: you can also add text by double-clicking anywhere with the selection tool",
"text_selected": "Double-click or press ENTER to edit text",
"text_editing": "Press Escape or CtrlOrCmd+ENTER to finish editing",
"linearElementMulti": "Click on last point or press Escape or Enter to finish",
"lockAngle": "You can constrain angle by holding SHIFT",
"resize": "You can constrain proportions by holding SHIFT while resizing,\nhold ALT to resize from the center",
@@ -223,7 +227,10 @@
"disk_button": "Save to file",
"link_title": "Shareable link",
"link_details": "Export as a read-only link.",
"link_button": "Export to Link"
"link_button": "Export to Link",
"excalidrawplus_description": "Save the scene to your Excalidraw+ workspace.",
"excalidrawplus_button": "Export",
"excalidrawplus_exportError": "Couldn't export to Excalidraw+ at this moment..."
},
"helpDialog": {
"blog": "Read our blog",
@@ -231,16 +238,18 @@
"curvedArrow": "Curved arrow",
"curvedLine": "Curved line",
"documentation": "Documentation",
"doubleClick": "double-click",
"drag": "drag",
"editor": "Editor",
"editSelectedShape": "Edit selected shape (text/arrow/line)",
"github": "Found an issue? Submit",
"howto": "Follow our guides",
"or": "or",
"preventBinding": "Prevent arrow binding",
"shapes": "Shapes",
"shortcuts": "Keyboard shortcuts",
"textFinish": "Finish editing (text)",
"textNewLine": "Add new line (text)",
"textFinish": "Finish editing (text editor)",
"textNewLine": "Add new line (text editor)",
"title": "Help",
"view": "View",
"zoomToFit": "Zoom to fit all elements",
+27 -7
View File
@@ -20,6 +20,10 @@
"background": "Fondo",
"fill": "Rellenar",
"strokeWidth": "Grosor del trazo",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "Estilo del trazo",
"strokeStyle_solid": "Sólido",
"strokeStyle_dashed": "Discontinua",
@@ -38,8 +42,8 @@
"fontSize": "Tamaño de la fuente",
"fontFamily": "Tipo de fuente",
"onlySelected": "Sólo seleccionados",
"withBackground": "Con fondo",
"exportEmbedScene": "Insertar escena en el archivo exportado",
"withBackground": "Fondo",
"exportEmbedScene": "Embeber escena",
"exportEmbedScene_details": "Los datos de escena se guardarán en el archivo PNG/SVG exportado, así la escena puede ser restaurada de la misma.\nEsto aumentará el tamaño del archivo exportado.",
"addWatermark": "Agregar \"Hecho con Excalidraw\"",
"handDrawn": "Dibujado a mano",
@@ -96,17 +100,22 @@
"flipVertical": "Girar verticalmente",
"viewMode": "Modo presentación",
"toggleExportColorScheme": "Cambiar el esquema de colores de exportación",
"share": "Compartir"
"share": "Compartir",
"showStroke": "Mostrar el selector de color del trazo",
"showBackground": "Mostrar el selector de color de fondo",
"toggleTheme": "Alternar tema"
},
"buttons": {
"clearReset": "Limpiar lienzo y reiniciar el color de fondo",
"exportJSON": "Exportar como archivo",
"exportImage": "Guardar como imagen",
"export": "Exportar",
"exportToPng": "Exportar a PNG",
"exportToSvg": "Exportar a SVG",
"copyToClipboard": "Copiar al portapapeles",
"copyPngToClipboard": "Copiar PNG al portapapeles",
"scale": "Escalar",
"save": "Guardar",
"save": "Guardal al archivo actual",
"saveAs": "Guardar como",
"load": "Cargar",
"getShareableLink": "Obtener enlace para compartir",
@@ -115,7 +124,7 @@
"scrollBackToContent": "Volver al contenido",
"zoomIn": "Acercarse",
"zoomOut": "Alejarse",
"resetZoom": "Restablecer acercamiento",
"resetZoom": "Restablecer zoom",
"menu": "Menú",
"done": "Hecho",
"edit": "Editar",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Selección",
"freedraw": "Dibujo libre",
"rectangle": "Rectángulo",
"diamond": "Diamante",
"ellipse": "Elipse",
"arrow": "Flecha",
"line": "Línea",
"freedraw": "Dibujar",
"text": "Texto",
"library": "Biblioteca",
"lock": "Mantener la herramienta seleccionada activa después de dibujar"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Error"
},
"exportDialog": {
"disk_title": "Guardar en el disco",
"disk_details": "Exportar los datos de la escena a un archivo desde el cual se puede importar más tarde.",
"disk_button": "Guardar en el archivo",
"link_title": "Enlace para compartir",
"link_details": "Exportar como enlace de sólo lectura.",
"link_button": "Exportar al link",
"excalidrawplus_description": "Guarda la escena en tu espacio de trabajo de Excalidraw+.",
"excalidrawplus_button": "Exportar",
"excalidrawplus_exportError": "No se pudo exportar a Excalidraw+ en este momento..."
},
"helpDialog": {
"blog": "Lee nuestro blog",
"click": "click",
@@ -233,7 +253,7 @@
},
"encrypted": {
"tooltip": "Tus dibujos están cifrados de punto a punto, por lo que los servidores de Excalidraw nunca los verán.",
"link": ""
"link": "Entrada en el blog sobre cifrado de extremo a extremo"
},
"stats": {
"angle": "Ángulo",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "پس زمینه",
"fill": "رنگ آمیزی",
"strokeWidth": "ضخامت خط",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "استایل خط",
"strokeStyle_solid": "یکدست",
"strokeStyle_dashed": "خط چین",
@@ -38,8 +42,8 @@
"fontSize": "اندازه قلم",
"fontFamily": "نوع قلم",
"onlySelected": "فقط انتخاب شده ها",
"withBackground": "با پس زمینه",
"exportEmbedScene": "قرار دادن صحنه در فایل خروجی",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "متحوای صحنه به فایل خروجی SVG/PNG اضافه خواهد شد برای بازیابی صحنه به آن اضافه خواهد شد.\nباعث افزایش حجم فایل خروجی میشود.",
"addWatermark": "\"ساخته شده با Excalidraw\" را اضافه کن",
"handDrawn": "دست نویس",
@@ -96,17 +100,22 @@
"flipVertical": "",
"viewMode": "",
"toggleExportColorScheme": "",
"share": ""
"share": "",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "پاکسازی بوم نقاشی",
"exportJSON": "",
"exportImage": "",
"export": "تبدیل",
"exportToPng": "تبدیل به PNG",
"exportToSvg": "تبدیل به SVG",
"copyToClipboard": "کپی در حافظه موقت",
"copyPngToClipboard": "کپی PNG در حافظه موقت",
"scale": "مقیاس",
"save": "ذخیره",
"save": "",
"saveAs": "ذخیره با نام",
"load": "بارگذاری",
"getShareableLink": "دریافت لینک قابل اشتراک",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "گزینش",
"freedraw": "طراحی آزاد",
"rectangle": "مستطیل",
"diamond": "لوزی",
"ellipse": "بیضی",
"arrow": "پیکان",
"line": "خط",
"freedraw": "",
"text": "متن",
"library": "کتابخانه",
"lock": "ابزار انتخاب شده را بعد از کشیدن نگه دار"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "خطا"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "بلاگ ما را بخوانید",
"click": "",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Tausta",
"fill": "Täyttö",
"strokeWidth": "Viivan leveys",
"strokeShape": "Viivan muoto",
"strokeShape_gel": "Geelikynä",
"strokeShape_fountain": "Sulkakynä",
"strokeShape_brush": "Sivellinkynä",
"strokeStyle": "Viivan tyyli",
"strokeStyle_solid": "Yhtenäinen",
"strokeStyle_dashed": "Katkoviiva",
@@ -38,8 +42,8 @@
"fontSize": "Kirjasinkoko",
"fontFamily": "Kirjasintyyppi",
"onlySelected": "Vain valitut",
"withBackground": "Sisällytä tausta",
"exportEmbedScene": "Upota teos tiedostoon",
"withBackground": "Taustalla",
"exportEmbedScene": "Upota t",
"exportEmbedScene_details": "Teoksen tiedot tallennetaan PNG/SVG-tiedostoon, jolloin teoksen voi palauttaa siitä. Kasvattaa tallennetun tiedoston kokoa.",
"addWatermark": "Lisää \"Tehty Excalidrawilla\"",
"handDrawn": "Käsinkirjoitettu",
@@ -96,17 +100,22 @@
"flipVertical": "Käännä pystysuunnassa",
"viewMode": "Katselutila",
"toggleExportColorScheme": "Vaihda viennin väriteema",
"share": "Jaa"
"share": "Jaa",
"showStroke": "Näytä viivan värin valitsin",
"showBackground": "Näytä taustavärin valitsin",
"toggleTheme": "Vaihda teema"
},
"buttons": {
"clearReset": "Tyhjennä piirtoalue",
"exportJSON": "Vie tiedostoon",
"exportImage": "Tallenna kuvana",
"export": "Vie",
"exportToPng": "Vie PNG-tiedostona",
"exportToSvg": "Vie SVG-tiedostona",
"copyToClipboard": "Kopioi leikepöydälle",
"copyPngToClipboard": "Kopioi PNG-tiedosto leikepöydälle",
"scale": "Koko",
"save": "Tallenna",
"save": "Tallenna nykyiseen tiedostoon",
"saveAs": "Tallenna nimellä",
"load": "Avaa",
"getShareableLink": "Hae jaettava linkki",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Valinta",
"freedraw": "Vapaa piirto",
"rectangle": "Suorakulmio",
"diamond": "Vinoneliö",
"ellipse": "Soikio",
"arrow": "Nuoli",
"line": "Viiva",
"freedraw": "Piirrä",
"text": "Teksti",
"library": "Kirjasto",
"lock": "Pidä valittu työkalu aktiivisena piirron jälkeen"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Virhe"
},
"exportDialog": {
"disk_title": "Tallenna levylle",
"disk_details": "Vie työn tiedot tiedostoon, josta sen voi tuoda myöhemmin.",
"disk_button": "Tallenna tiedostoon",
"link_title": "Jaettava linkki",
"link_details": "Vie vain luku -linkkinä.",
"link_button": "Vie linkkinä",
"excalidrawplus_description": "Tallenna teos Excalidraw+ tilaan.",
"excalidrawplus_button": "Vie",
"excalidrawplus_exportError": "Ei voitu viedä Excalidraw+-palveluun tällä hetkellä..."
},
"helpDialog": {
"blog": "Lue blogiamme",
"click": "klikkaa",
+31 -11
View File
@@ -16,10 +16,14 @@
"delete": "Supprimer",
"copyStyles": "Copier les styles",
"pasteStyles": "Coller les styles",
"stroke": "Contour",
"stroke": "Trait",
"background": "Arrière-plan",
"fill": "Remplissage",
"strokeWidth": "Largeur du trait",
"strokeShape": "Forme du trait",
"strokeShape_gel": "Stylo à bille",
"strokeShape_fountain": "Stylo-plume",
"strokeShape_brush": "Pinceau",
"strokeStyle": "Style du trait",
"strokeStyle_solid": "Plein",
"strokeStyle_dashed": "Tirets",
@@ -38,8 +42,8 @@
"fontSize": "Taille de la police",
"fontFamily": "Police",
"onlySelected": "Uniquement la sélection",
"withBackground": "Avec arrière-plan",
"exportEmbedScene": "Intégrer la scène au fichier exporté",
"withBackground": "Arrière-plan",
"exportEmbedScene": "Intégrer la scène",
"exportEmbedScene_details": "Les données de scène seront enregistrées dans le fichier PNG/SVG exporté, afin que la scène puisse être restaurée à partir de celui-ci.\nCela augmentera la taille du fichier exporté.",
"addWatermark": "Ajouter \"Fait avec Excalidraw\"",
"handDrawn": "À main levée",
@@ -96,17 +100,22 @@
"flipVertical": "Retourner verticalement",
"viewMode": "Mode présentation",
"toggleExportColorScheme": "Activer/Désactiver l'export du thème de couleur",
"share": "Partager"
"share": "Partager",
"showStroke": "Afficher le sélecteur de couleur de trait",
"showBackground": "Afficher le sélecteur de couleur d'arrière-plan",
"toggleTheme": "Changer le thème"
},
"buttons": {
"clearReset": "Réinitialiser le canevas",
"exportJSON": "Exporter comme fichier",
"exportImage": "Enregistrer comme image",
"export": "Exporter",
"exportToPng": "Exporter en PNG",
"exportToSvg": "Exporter en SVG",
"exportToPng": "Enregistrer en PNG",
"exportToSvg": "Enregistrer en SVG",
"copyToClipboard": "Copier dans le presse-papier",
"copyPngToClipboard": "Copier le PNG vers le presse-papier",
"copyPngToClipboard": "Copier le PNG dans le presse-papier",
"scale": "Échelle",
"save": "Sauvegarder",
"save": "Enregistrer dans le fichier actuel",
"saveAs": "Enregistrer sous",
"load": "Ouvrir",
"getShareableLink": "Obtenir un lien de partage",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Sélection",
"freedraw": "Dessin libre",
"rectangle": "Rectangle",
"diamond": "Losange",
"ellipse": "Ellipse",
"arrow": "Flèche",
"line": "Ligne",
"freedraw": "Dessiner",
"text": "Texte",
"library": "Bibliothèque",
"lock": "Garder l'outil sélectionné actif après le dessin"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Erreur"
},
"exportDialog": {
"disk_title": "Enregistrer sur le disque",
"disk_details": "Exporter les données de la scène comme un fichier que vous pourrez importer ultérieurement.",
"disk_button": "Enregistrer comme fichier",
"link_title": "Lien partageable",
"link_details": "Exporter comme un lien en lecture seule.",
"link_button": "Exporter comme lien",
"excalidrawplus_description": "Enregistrer la scène dans votre espace de travail Excalidraw+.",
"excalidrawplus_button": "Exporter",
"excalidrawplus_exportError": "Impossible d'exporter vers Excalidraw+ pour le moment..."
},
"helpDialog": {
"blog": "Lire notre blog",
"click": "clic",
@@ -252,8 +272,8 @@
},
"toast": {
"copyStyles": "Styles copiés.",
"copyToClipboard": "Copié vers le presse-papiers.",
"copyToClipboardAsPng": "{{exportSelection}} copié dans le presse-papiers en PNG\n({{exportColorScheme}})",
"copyToClipboard": "Copié dans le presse-papier.",
"copyToClipboardAsPng": "{{exportSelection}} copié dans le presse-papier en PNG\n({{exportColorScheme}})",
"fileSaved": "Fichier enregistré.",
"fileSavedToFilename": "Enregistré sous {filename}",
"canvas": "canevas",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "רקע",
"fill": "מילוי",
"strokeWidth": "עובי קו מתאר",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "סגנון קו המתאר",
"strokeStyle_solid": "מלא",
"strokeStyle_dashed": "מקווקו",
@@ -38,8 +42,8 @@
"fontSize": "גודל גופן",
"fontFamily": "סוג הגופן",
"onlySelected": "רק מה שנבחר",
"withBackground": "עם רקע",
"exportEmbedScene": "שלב את התצוגה בקובץ המיוצא",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "מידע התצוגה יישמר לקובץ המיוצא מסוג PNG/SVG כך שיהיה ניתן לשחזרה ממנו.\nהפעולה תגדיל את גודל הקובץ המיוצא.",
"addWatermark": "הוסף \"נוצר באמצעות Excalidraw\"",
"handDrawn": "כתב יד",
@@ -96,17 +100,22 @@
"flipVertical": "",
"viewMode": "מצב תצוגה",
"toggleExportColorScheme": "",
"share": ""
"share": "",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "אפס את הלוח",
"exportJSON": "",
"exportImage": "",
"export": "ייצא",
"exportToPng": "יצא ל PNG",
"exportToSvg": "יצא ל SVG",
"copyToClipboard": "העתק ללוח",
"copyPngToClipboard": "העתק PNG ללוח",
"scale": "קנה מידה",
"save": "שמור",
"save": "",
"saveAs": "שמירה בשם",
"load": "טען",
"getShareableLink": "קבל קישור לשיתוף",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "בחירה",
"freedraw": "ציור חופשי",
"rectangle": "מרובע",
"diamond": "מעוין",
"ellipse": "אליפסה",
"arrow": "חץ",
"line": "קו",
"freedraw": "",
"text": "טקסט",
"library": "ספריה",
"lock": "השאר את הכלי הנבחר פעיל גם לאחר סיום הציור"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "שגיאה"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "קרא את הבלוג שלנו",
"click": "קליק",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "पृष्ठभूमि",
"fill": "भरें",
"strokeWidth": "रेखा की चौड़ाई",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "स्ट्रोक का आकार",
"strokeStyle_solid": "ठोस",
"strokeStyle_dashed": "डैश",
@@ -38,8 +42,8 @@
"fontSize": "फ़ॉन्ट का आकार",
"fontFamily": "फ़ॉन्ट का परिवार",
"onlySelected": "केवल चयनित",
"withBackground": "बैकग्राउंड के साथ",
"exportEmbedScene": "निर्यात एम्बेड दृश्य",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "निर्यात एम्बेड दृश्य विवरण",
"addWatermark": "ऐड \"मेड विथ एक्सकैलिडराव\"",
"handDrawn": "हाथ से बनाया हुआ",
@@ -96,17 +100,22 @@
"flipVertical": "",
"viewMode": "",
"toggleExportColorScheme": "",
"share": ""
"share": "",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "कैनवास रीसेट करें",
"exportJSON": "",
"exportImage": "",
"export": "निर्यात",
"exportToPng": "पीएनजी के रूप में निर्यात करे",
"exportToSvg": "Svg के रूप में निर्यात करे",
"copyToClipboard": "क्लिपबोर्ड पर प्रतिलिपि बनाएँ",
"copyPngToClipboard": "क्लिपबोर्ड पर कॉपी करें,पीएनजी के रूप में",
"scale": "पैमाना",
"save": "सहेजें",
"save": "",
"saveAs": "सेव करे इस तरह",
"load": "लोड करें",
"getShareableLink": "साझा करने योग्य लिंक प्राप्त करें",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "चयन",
"freedraw": "मुफ्त ड्रा",
"rectangle": "आयात",
"diamond": "तिर्यग्वर्ग",
"ellipse": "दीर्घवृत्त",
"arrow": "तीर",
"line": "रेखा",
"freedraw": "",
"text": "पाठ",
"library": "लाइब्रेरी",
"lock": "ड्राइंग के बाद चयनित टूल को सक्रिय रखें"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "गलती"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "हमारा ब्लॉग पढे",
"click": "क्लिक करें",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Háttér",
"fill": "Kitöltés",
"strokeWidth": "Körvonal vastagsága",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "Körvonal stílusa",
"strokeStyle_solid": "Kitöltött",
"strokeStyle_dashed": "Szaggatott",
@@ -38,8 +42,8 @@
"fontSize": "Betűméret",
"fontFamily": "Betűkészlet család",
"onlySelected": "Csak a kijelölt",
"withBackground": "Háttérrel",
"exportEmbedScene": "Jelenet beágyazása az exportált fájlba",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "A jelenetet leíró adatok hozzá lesznek adva a PNG/SVG fájlhoz, így a jelenetet vissza lehet majd tölteni belőle. Ez megnöveli a fájl méretét.",
"addWatermark": "Add hozzá, hogy \"Excalidraw-val készült\"",
"handDrawn": "Kézzel rajzolt",
@@ -96,17 +100,22 @@
"flipVertical": "",
"viewMode": "",
"toggleExportColorScheme": "",
"share": ""
"share": "",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "Vászon törlése",
"exportJSON": "",
"exportImage": "",
"export": "Exportálás",
"exportToPng": "Exportálás PNG-be",
"exportToSvg": "Exportálás SVG-be",
"copyToClipboard": "Vágólapra másolás",
"copyPngToClipboard": "PNG másolása a vágólapra",
"scale": "Nagyítás",
"save": "Mentés",
"save": "",
"saveAs": "Mentés másként",
"load": "Betöltés",
"getShareableLink": "Megosztható link létrehozása",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Kijelölés",
"freedraw": "Szabadkézi rajz",
"rectangle": "Téglalap",
"diamond": "Rombusz",
"ellipse": "Ellipszis",
"arrow": "Nyíl",
"line": "Vonal",
"freedraw": "",
"text": "Szöveg",
"library": "Könyvtár",
"lock": "Rajzolás után az aktív eszközt tartsa kijelölve"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Hiba"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "",
"click": "",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Latar",
"fill": "Isian",
"strokeWidth": "Lebar guratan",
"strokeShape": "Bentuk guratan",
"strokeShape_gel": "Pena gel",
"strokeShape_fountain": "Pena gunung",
"strokeShape_brush": "Kuas",
"strokeStyle": "Gaya guratan",
"strokeStyle_solid": "Padat",
"strokeStyle_dashed": "Putus-putus",
@@ -38,8 +42,8 @@
"fontSize": "Ukuran font",
"fontFamily": "Jenis font",
"onlySelected": "Hanya yang Dipilih",
"withBackground": "Dengan latar",
"exportEmbedScene": "Sematkan pemandangan ke dalam file yang diekspor",
"withBackground": "Latar",
"exportEmbedScene": "Sematkan pemandangan",
"exportEmbedScene_details": "Data pemandangan akan disimpan dalam file PNG/SVG yang diekspor, sehingga pemandangan itu dapat dipulihkan darinya.\nAkan membesarkan ukuran file yang diekspor.",
"addWatermark": "Tambahkan \"Dibuat dengan Excalidraw\"",
"handDrawn": "Tulisan tangan",
@@ -96,17 +100,22 @@
"flipVertical": "Balikkan vertikal",
"viewMode": "Mode tampilan",
"toggleExportColorScheme": "Ubah skema warna ekspor",
"share": "Bagikan"
"share": "Bagikan",
"showStroke": "Tampilkan garis pengambil warna",
"showBackground": "Tampilkan latar pengambil warna",
"toggleTheme": "Ubah tema"
},
"buttons": {
"clearReset": "Setel Ulang Kanvas",
"exportJSON": "Ekspor ke file",
"exportImage": "Simpan gambar",
"export": "Ekspor",
"exportToPng": "Ekspor ke PNG",
"exportToSvg": "Ekspor ke SVG",
"copyToClipboard": "Salin ke Papan Klip",
"copyPngToClipboard": "Salin PNG ke papan klip",
"scale": "Skala",
"save": "Simpan",
"save": "Simpan ke file sekarang",
"saveAs": "Simpan sebagai",
"load": "Muat",
"getShareableLink": "Buat Tautan yang Bisa Dibagian",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Pilihan",
"freedraw": "Menggambar bebas",
"rectangle": "Persegi",
"diamond": "Berlian",
"ellipse": "Elips",
"arrow": "Panah",
"line": "Garis",
"freedraw": "Gambar",
"text": "Teks",
"library": "Pustaka",
"lock": "Biarkan alat yang dipilih aktif setelah menggambar"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Kesalahan"
},
"exportDialog": {
"disk_title": "Simpan ke disk",
"disk_details": "Ekspor data pemandangan ke file yang mana Anda dapat impor nanti.",
"disk_button": "Simpan ke file",
"link_title": "Tautan",
"link_details": "Ekspor sebagai tautan yang hanya dibaca.",
"link_button": "Ekspor ke tautan",
"excalidrawplus_description": "Simpan pemandangan ke ruang kerja Excalidraw+ Anda.",
"excalidrawplus_button": "Ekspor",
"excalidrawplus_exportError": "Tidak dapat ekspor ke Excalidraw+ saat ini..."
},
"helpDialog": {
"blog": "Baca blog kami",
"click": "klik",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Sfondo",
"fill": "Riempimento",
"strokeWidth": "Spessore del tratto",
"strokeShape": "Forma del tratto",
"strokeShape_gel": "Penna gel",
"strokeShape_fountain": "Penna stilografica",
"strokeShape_brush": "Pennello",
"strokeStyle": "Stile del tratto",
"strokeStyle_solid": "Pieno",
"strokeStyle_dashed": "Tratteggiato",
@@ -38,8 +42,8 @@
"fontSize": "Dimensione carattere",
"fontFamily": "Carattere",
"onlySelected": "Solo selezionati",
"withBackground": "Con sfondo",
"exportEmbedScene": "Incorpora la scena nel file esportato",
"withBackground": "Sfondo",
"exportEmbedScene": "Includi scena",
"exportEmbedScene_details": "I dati della scena saranno salvati nel file PNG/SVG esportato in modo che la scena possa essere ripristinata da esso.\nQuesto aumenterà la dimensione del file esportato.",
"addWatermark": "Aggiungi \"Creato con Excalidraw\"",
"handDrawn": "A mano libera",
@@ -96,17 +100,22 @@
"flipVertical": "Capovolgi verticalmente",
"viewMode": "Modalità visualizzazione",
"toggleExportColorScheme": "Cambia lo schema di colori in esportazione",
"share": "Condividi"
"share": "Condividi",
"showStroke": "Mostra selettore colore del tratto",
"showBackground": "Mostra selettore colore di sfondo",
"toggleTheme": "Cambia tema"
},
"buttons": {
"clearReset": "Svuota la tela",
"exportJSON": "Esporta su file",
"exportImage": "Salva come immagine",
"export": "Esporta",
"exportToPng": "Esporta come PNG",
"exportToSvg": "Esporta come SVG",
"copyToClipboard": "Copia negli appunti",
"copyPngToClipboard": "Copia PNG negli appunti",
"scale": "Scala",
"save": "Salva",
"save": "Salva sul file corrente",
"saveAs": "Salva con nome",
"load": "Carica",
"getShareableLink": "Ottieni link condivisibile",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Selezione",
"freedraw": "Disegno libero",
"rectangle": "Rettangolo",
"diamond": "Rombo",
"ellipse": "Ellisse",
"arrow": "Freccia",
"line": "Linea",
"freedraw": "",
"text": "Testo",
"library": "Libreria",
"lock": "Mantieni lo strumento selezionato attivo dopo aver disegnato"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Errore"
},
"exportDialog": {
"disk_title": "Salva su disco",
"disk_details": "Esporta i dati della scena su file, dal quale potrai importare in seguito.",
"disk_button": "Salva su file",
"link_title": "Link condivisibile",
"link_details": "Esporta come link di sola lettura.",
"link_button": "Esporta come Link",
"excalidrawplus_description": "Salva la scena nel tuo spazio di lavoro Excalidraw+.",
"excalidrawplus_button": "Esporta",
"excalidrawplus_exportError": "Non è stato possibile esportare su Excalidraw+ al questo momento..."
},
"helpDialog": {
"blog": "Leggi il nostro blog",
"click": "click",
+30 -10
View File
@@ -20,6 +20,10 @@
"background": "背景の色",
"fill": "塗りつぶし",
"strokeWidth": "線の幅",
"strokeShape": "ストロークの形状",
"strokeShape_gel": "ジェルペン",
"strokeShape_fountain": "噴水ペン",
"strokeShape_brush": "ブラシペン",
"strokeStyle": "線の種類",
"strokeStyle_solid": "実線",
"strokeStyle_dashed": "破線",
@@ -38,8 +42,8 @@
"fontSize": "フォントの大きさ",
"fontFamily": "フォントの種類",
"onlySelected": "選択中のみ",
"withBackground": "背景を含める",
"exportEmbedScene": "エクスポートされたファイルにシーンを埋め込みます",
"withBackground": "背景",
"exportEmbedScene": "",
"exportEmbedScene_details": "シーンデータはエクスポートされたPNG/SVGファイルに保存され、シーンを復元することができます。\nエクスポートされたファイルのサイズは増加します。",
"addWatermark": "\"Made with Excalidraw\"と表示",
"handDrawn": "手描き風",
@@ -96,17 +100,22 @@
"flipVertical": "垂直方向に反転",
"viewMode": "閲覧モード",
"toggleExportColorScheme": "",
"share": ""
"share": "共有",
"showStroke": "",
"showBackground": "",
"toggleTheme": "テーマの切り替え"
},
"buttons": {
"clearReset": "キャンバスのリセット",
"exportJSON": "ファイルへエクスポート",
"exportImage": "画像として保存",
"export": "エクスポート",
"exportToPng": "PNG にエクスポート",
"exportToSvg": "SVG にエクスポート",
"copyToClipboard": "クリップボードにコピー",
"copyPngToClipboard": "クリップボードにPNGをコピー",
"scale": "スケール",
"save": "保存",
"save": "現在のファイルに保存",
"saveAs": "名前を付けて保存",
"load": "読み込み...",
"getShareableLink": "共有URLの取得",
@@ -142,22 +151,22 @@
"loadSceneOverridePrompt": "外部図面を読み込むと、既存のコンテンツが置き換わります。続行しますか?",
"collabStopOverridePrompt": "セッションを停止すると、ローカルに保存されている図が上書きされます。 本当によろしいですか?\n\n(ローカルの図を保持したい場合は、セッションを停止せずにブラウザタブを閉じてください。)",
"errorLoadingLibrary": "サードパーティライブラリの読み込み中にエラーが発生しました。",
"errorAddingToLibrary": "",
"errorRemovingFromLibrary": "",
"errorAddingToLibrary": "アイテムをライブラリに追加できませんでした",
"errorRemovingFromLibrary": "ライブラリからアイテムを削除できませんでした",
"confirmAddLibrary": "{{numShapes}} 個の図形をライブラリに追加します。よろしいですか?",
"imageDoesNotContainScene": "現在、画像のインポートはサポートされていません。\n\nシーンをインポートしようとしましたか?この画像にはシーンデータが含まれていないようです。エクスポート中に有効にしていましたか?",
"cannotRestoreFromImage": "このイメージファイルからシーンを復元できませんでした",
"invalidSceneUrl": "",
"invalidSceneUrl": "指定された URL からシーンをインポートできませんでした。不正な形式であるか、有効な Excalidraw JSON データが含まれていません。",
"resetLibrary": "ライブラリを消去します。本当によろしいですか?"
},
"toolBar": {
"selection": "選択",
"freedraw": "手書き",
"rectangle": "矩形",
"diamond": "ひし形",
"ellipse": "楕円",
"arrow": "矢印",
"line": "直線",
"freedraw": "描画",
"text": "テキスト",
"library": "ライブラリ",
"lock": "描画後も使用中のツールを選択したままにする"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "エラー"
},
"exportDialog": {
"disk_title": "ディスクに保存",
"disk_details": "シーンデータを後からインポートできるファイルにエクスポートします。",
"disk_button": "ファイルへ保存",
"link_title": "共有可能なリンク",
"link_details": "読み取り専用リンクとしてエクスポート",
"link_button": "リンクとしてエクスポート",
"excalidrawplus_description": "Excalidraw+ ワークスペースにシーンを保存します。",
"excalidrawplus_button": "エクスポート",
"excalidrawplus_exportError": "Excalidraw+ にエクスポートできませんでした..."
},
"helpDialog": {
"blog": "公式ブログを読む",
"click": "クリック",
@@ -253,10 +273,10 @@
"toast": {
"copyStyles": "スタイルをコピー",
"copyToClipboard": "クリップボードにコピー",
"copyToClipboardAsPng": "",
"copyToClipboardAsPng": "{{exportSelection}} を PNG 形式でクリップボードにコピーしました\n({{exportColorScheme}})",
"fileSaved": "ファイルを保存しました",
"fileSavedToFilename": "{filename} に保存しました",
"canvas": "キャンバス",
"selection": ""
"selection": "選択"
}
}
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Agilal",
"fill": "Taččart",
"strokeWidth": "Tehri n yizirig",
"strokeShape": "Talɣa n yizirig",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "Amfezzu",
"strokeStyle": "Aɣanib n tizirig",
"strokeStyle_solid": "Aččuran",
"strokeStyle_dashed": "S tjerriḍin",
@@ -38,8 +42,8 @@
"fontSize": "Tiddi n tsefsit",
"fontFamily": "Tawacult n tsefsiyin",
"onlySelected": "Tafrayt kan",
"withBackground": "S ugilal",
"exportEmbedScene": "Seddu asayes deg ufaylu yettwasifḍen",
"withBackground": "Agilal",
"exportEmbedScene": "Sleɣ asayes",
"exportEmbedScene_details": "Asayes ad yettwasekles deg ufaylu n usifeḍ PNG/SVG akken akken ad yili wamek ara d-yettwarr seg-s usayes. Ayagi ad isimɣur tiddi n ufaylu n usifeḍ.",
"addWatermark": "Seddu \"Yettwaxdem s Excalidraw\"",
"handDrawn": "Asuneɣ s ufus",
@@ -96,17 +100,22 @@
"flipVertical": "Tuttya tubdidt",
"viewMode": "Askar n tmuɣli",
"toggleExportColorScheme": "Sermed/sens asifeḍ usentel n yini",
"share": "Bḍu"
"share": "Bḍu",
"showStroke": "Beqqeḍ amelqaḍ n yini n yizirig",
"showBackground": "Beqqeḍ amelqaḍ n yini n ugilal",
"toggleTheme": "Snifel asentel"
},
"buttons": {
"clearReset": "Ales awennez n teɣzut n usuneɣ",
"exportJSON": "Sifeḍ afaylu",
"exportImage": "Sekles am tugna",
"export": "Sifeḍ",
"exportToPng": "Sifeḍ ɣer PNG",
"exportToSvg": "Sifeḍ ɣer SVG",
"copyToClipboard": "Nɣel ɣer tecfawit",
"copyPngToClipboard": "Nɣel PNG ɣer tecfawit",
"scale": "Taskala",
"save": "Sekles",
"save": "Sekles deg ufaylu amiran",
"saveAs": "Sekles am",
"load": "Sali-d",
"getShareableLink": "Awi-d aseɣwen n beṭṭu",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Tafrayt",
"freedraw": "Unuɣ ilelli",
"rectangle": "Asrem",
"diamond": "Ameɣṛun",
"ellipse": "Taglayt",
"arrow": "Taneccabt",
"line": "Izirig",
"freedraw": "Suneɣ",
"text": "Aḍris",
"library": "Tamkarḍit",
"lock": "Eǧǧ afecku n tefrayt yermed mbaɛd asuneɣ"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Tuccḍa"
},
"exportDialog": {
"disk_title": "Sekles deg uḍebsi",
"disk_details": "Sekles isefka n usayes deg ufaylu ansi ara tizmireḍ ad d-tketreḍ areḍqal.",
"disk_button": "Sekles deg ufaylu",
"link_title": "Aseɣwen n beṭṭu",
"link_details": "Sifeḍ am useɣwen n tɣuri kan.",
"link_button": "Sifeḍ deg useɣwen",
"excalidrawplus_description": "Sekles asayes-inek•inem di tallunt n umahil Excalidraw+.",
"excalidrawplus_button": "Sifeḍ",
"excalidrawplus_exportError": "Ulamek asifeḍ ɣer Excalidraw+ akka tura..."
},
"helpDialog": {
"blog": "Ɣeṛ ablug-nneɣ",
"click": "ssit",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "배경색",
"fill": "채우기",
"strokeWidth": "선 굵기",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "선",
"strokeStyle_solid": "실선",
"strokeStyle_dashed": "파선",
@@ -38,8 +42,8 @@
"fontSize": "글자 크기",
"fontFamily": "글꼴",
"onlySelected": "선택한 항목만",
"withBackground": "배경 포함",
"exportEmbedScene": "화면을 내보낸 파일에 담기",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "화면 정보가 내보내는 PNG/SVG 파일에 저장되어 이후에 파일에서 화면을 복구할 수 있습니다. 파일 크기가 증가합니다.",
"addWatermark": "\"Made with Excalidraw\" 추가",
"handDrawn": "손글씨",
@@ -96,17 +100,22 @@
"flipVertical": "",
"viewMode": "보기 모드",
"toggleExportColorScheme": "",
"share": ""
"share": "",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "캔버스 초기화",
"exportJSON": "",
"exportImage": "",
"export": "내보내기",
"exportToPng": "PNG로 내보내기",
"exportToSvg": "SVG로 내보내기",
"copyToClipboard": "클립보드로 복사",
"copyPngToClipboard": "클립보드로 PNG 이미지 복사",
"scale": "크기",
"save": "저장",
"save": "",
"saveAs": "다른 이름으로 저장",
"load": "불러오기",
"getShareableLink": "공유 가능한 링크 생성",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "선택",
"freedraw": "자유롭게 그리기",
"rectangle": "사각형",
"diamond": "다이아몬드",
"ellipse": "타원",
"arrow": "화살표",
"line": "선",
"freedraw": "",
"text": "텍스트",
"library": "라이브러리",
"lock": "선택된 도구 유지하기"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "오류"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "블로그 읽어보기",
"click": "클릭",
+60 -40
View File
@@ -1,43 +1,47 @@
{
"labels": {
"paste": "",
"pasteCharts": "",
"selectAll": "",
"multiSelect": "",
"moveCanvas": "",
"cut": "",
"copy": "",
"copyAsPng": "",
"copyAsSvg": "",
"bringForward": "",
"sendToBack": "",
"bringToFront": "",
"sendBackward": "",
"delete": "",
"copyStyles": "",
"pasteStyles": "",
"stroke": "",
"background": "",
"fill": "",
"strokeWidth": "",
"strokeStyle": "",
"strokeStyle_solid": "",
"strokeStyle_dashed": "",
"strokeStyle_dotted": "",
"sloppiness": "",
"opacity": "",
"textAlign": "",
"edges": "",
"sharp": "",
"round": "",
"arrowheads": "",
"arrowhead_none": "",
"arrowhead_arrow": "",
"arrowhead_bar": "",
"arrowhead_dot": "",
"fontSize": "",
"fontFamily": "",
"onlySelected": "",
"paste": "Ielīmēt",
"pasteCharts": "Ielīmēt grafikus",
"selectAll": "Iezīmēt visu",
"multiSelect": "Pievienot elementu iezīmētajam",
"moveCanvas": "Pārvietot darba laukumu",
"cut": "Izgriezt",
"copy": "Kopēt",
"copyAsPng": "Kopēt starpliktuvē kā PNG",
"copyAsSvg": "Kopēt starpliktuvē kā SVG",
"bringForward": "Pārvietot vienu slāni augstāk",
"sendToBack": "Pārvietot uz zemāko slāni",
"bringToFront": "Pārvietot uz virsējo slāni",
"sendBackward": "Pārvietot par vienu slāni zemāk",
"delete": "Dzēst",
"copyStyles": "Kopēt stilus",
"pasteStyles": "Ielīmēt stilus",
"stroke": "Līnija",
"background": "Fons",
"fill": "Aizpildījums",
"strokeWidth": "Līnijas platums",
"strokeShape": "Līnijas forma",
"strokeShape_gel": "Gēla pildspalva",
"strokeShape_fountain": "Lodīšu pildspalva",
"strokeShape_brush": "Flomāsters - ota",
"strokeStyle": "Līnijas forma",
"strokeStyle_solid": "Vienlaidu",
"strokeStyle_dashed": "Raustīta līnija",
"strokeStyle_dotted": "Punktota līnija",
"sloppiness": "Precizitāte",
"opacity": "Necaurspīdīgums",
"textAlign": "Teksta izkārtojums",
"edges": "Malas",
"sharp": "Asas",
"round": "Apaļas",
"arrowheads": "Bultas",
"arrowhead_none": "Nekādas",
"arrowhead_arrow": "Bulta",
"arrowhead_bar": "Svītra",
"arrowhead_dot": "Punkts",
"fontSize": "Teksta lielums",
"fontFamily": "Fontu saime",
"onlySelected": "Tikai iezīmētais",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "",
@@ -96,10 +100,15 @@
"flipVertical": "",
"viewMode": "",
"toggleExportColorScheme": "",
"share": ""
"share": "",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "",
"exportJSON": "",
"exportImage": "",
"export": "",
"exportToPng": "",
"exportToSvg": "",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "",
"draw": "",
"rectangle": "",
"diamond": "",
"ellipse": "",
"arrow": "",
"line": "",
"freedraw": "",
"text": "",
"library": "",
"lock": ""
@@ -210,6 +219,17 @@
"errorDialog": {
"title": ""
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "",
"click": "",
+24 -4
View File
@@ -20,6 +20,10 @@
"background": "နောက်ခံ",
"fill": "ဖြည့်",
"strokeWidth": "မျဉ်းအထူ",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "မျဉ်းပုံစံ",
"strokeStyle_solid": "အပြည့်",
"strokeStyle_dashed": "မျဉ်းပြတ်",
@@ -39,7 +43,7 @@
"fontFamily": "စာလုံးပုံစံ",
"onlySelected": "ရွေးထားသလောက်",
"withBackground": "",
"exportEmbedScene": "မြင်ကွင်းပါမြှုပ်နှံ၍ထုတ်ပါ",
"exportEmbedScene": "",
"exportEmbedScene_details": "ထုတ်ယူလိုက်သော PNG/SVG ထဲမြင်ကွင်းအချက်အလက်များပါဝင်သဖြင့် ပြန်လည်ရယူနိုင်သော်လည်း ဖိုင်အရွယ်အစားကြီးပါမည်။",
"addWatermark": "\"Excalidraw ဖြင့်ဖန်တီးသည်။\" စာသားထည့်",
"handDrawn": "လက်ရေး",
@@ -96,17 +100,22 @@
"flipVertical": "",
"viewMode": "",
"toggleExportColorScheme": "",
"share": ""
"share": "",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "ကားချပ်ရှင်းလင်း",
"exportJSON": "",
"exportImage": "",
"export": "ထုတ်",
"exportToPng": "PNG ထုတ်",
"exportToSvg": "SVG ထုတ်",
"copyToClipboard": "ကူးယူ",
"copyPngToClipboard": "PNG ကူးယူ",
"scale": "စကေး",
"save": "သိမ်း",
"save": "",
"saveAs": "ပြောင်းသိမ်း",
"load": "တင်သွင်း",
"getShareableLink": "မျှဝေရန် လင့်ခ်ရယူ",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "ရွေးချယ်",
"freedraw": "အလွတ်ရေးဆွဲ",
"rectangle": "စတုဂံ",
"diamond": "စိန်",
"ellipse": "အဝိုင်း",
"arrow": "မြှား",
"line": "မျဉ်း",
"freedraw": "",
"text": "စာသား",
"library": "မှတ်တမ်း",
"lock": "ရွေးချယ်ထားသောကိရိယာကိုသာဆက်သုံး"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "ချို့ယွင်းချက်"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "",
"click": "",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Bakgrunn",
"fill": "Fyll",
"strokeWidth": "Strektykkelse",
"strokeShape": "Strekstil",
"strokeShape_gel": "Gelepenn",
"strokeShape_fountain": "Fyllepenn",
"strokeShape_brush": "Pensel",
"strokeStyle": "Strekstil",
"strokeStyle_solid": "Heltrukket",
"strokeStyle_dashed": "Stiplet",
@@ -38,8 +42,8 @@
"fontSize": "Skriftstørrelse",
"fontFamily": "Fontfamilie",
"onlySelected": "Kun valgte",
"withBackground": "Med bakgrunn",
"exportEmbedScene": "Bygg inn scenen i den eksporterte filen",
"withBackground": "Bakgrunn",
"exportEmbedScene": "Bygg inn scene",
"exportEmbedScene_details": "Scenedata vil bli lagret i den eksporterte PNG/SVG-filen, slik at scenen kan gjenopprettes fra den.\nDet vil øke den eksporterte filstørrelsen.",
"addWatermark": "Legg til \"Laget med Excalidraw\"",
"handDrawn": "Håndtegnet",
@@ -96,17 +100,22 @@
"flipVertical": "Snu vertikalt",
"viewMode": "Visningsmodus",
"toggleExportColorScheme": "Veksle eksport av fargepalett",
"share": "Del"
"share": "Del",
"showStroke": "Vis fargevelger for kantfarge",
"showBackground": "Vis fargevelger for bakgrunnsfarge",
"toggleTheme": "Veksle tema"
},
"buttons": {
"clearReset": "Tøm lerretet og tilbakestill bakgrunnsfargen",
"exportJSON": "Eksporter til fil",
"exportImage": "Lagre som bilde",
"export": "Eksporter",
"exportToPng": "Eksporter til PNG",
"exportToSvg": "Eksporter til SVG",
"copyToClipboard": "Kopier til utklippstavle",
"copyPngToClipboard": "Kopier PNG til utklippstavlen",
"scale": "Skalering",
"save": "Lagre",
"save": "Lagre til aktiv fil",
"saveAs": "Lagre som",
"load": "Åpne",
"getShareableLink": "Få delingslenke",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Velg",
"freedraw": "Frihåndstegning",
"rectangle": "Rektangel",
"diamond": "Diamant",
"ellipse": "Ellipse",
"arrow": "Pil",
"line": "Linje",
"freedraw": "Tegn",
"text": "Tekst",
"library": "Bibliotek",
"lock": "Behold merket verktøy som aktivt"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Feil"
},
"exportDialog": {
"disk_title": "Lagre til disk",
"disk_details": "Eksporter scene-dataene til en fil som du kan importere fra senere.",
"disk_button": "Lagre til fil",
"link_title": "Delbar lenke",
"link_details": "Eksporter som en skrivebeskyttet lenke.",
"link_button": "Eksporter til lenke",
"excalidrawplus_description": "Lagre scenen til ditt Excalidraw+ arbeidsområde.",
"excalidrawplus_button": "Eksporter",
"excalidrawplus_exportError": "Kunne ikke eksportere til Excalidraw+ for øyeblikket..."
},
"helpDialog": {
"blog": "Les bloggen vår",
"click": "klikk",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Achtergrond",
"fill": "Invulling",
"strokeWidth": "Lijnbreedte",
"strokeShape": "Lijnstijl",
"strokeShape_gel": "Gel pen",
"strokeShape_fountain": "Vulpen",
"strokeShape_brush": "Penseel",
"strokeStyle": "Lijnstijl",
"strokeStyle_solid": "Ononderbroken",
"strokeStyle_dashed": "Gestreept",
@@ -38,8 +42,8 @@
"fontSize": "Tekstgrootte",
"fontFamily": "Lettertype",
"onlySelected": "Enkel geselecteerde",
"withBackground": "Met achtergrond",
"exportEmbedScene": "Scène in geëxporteerd bestand invoegen",
"withBackground": "Achtergrond",
"exportEmbedScene": "Scène insluiten",
"exportEmbedScene_details": "Scènegegevens worden in het geëxporteerde PNG/SVG-bestand opgeslagen zodat de scène kan worden hersteld.\nDe grootte van de geëxporteerde bestanden zal toenemen.",
"addWatermark": "Voeg \"Gemaakt met Excalidraw\" toe",
"handDrawn": "Handgetekend",
@@ -96,17 +100,22 @@
"flipVertical": "Verticaal spiegelen",
"viewMode": "Weergavemodus",
"toggleExportColorScheme": "Kleurenschema exporteren aan/uit",
"share": "Deel"
"share": "Deel",
"showStroke": "Toon lijn kleur kiezer",
"showBackground": "Toon achtergrondkleur kiezer",
"toggleTheme": "Thema aan/uit"
},
"buttons": {
"clearReset": "Canvas opnieuw instellen",
"exportJSON": "Exporteren naar bestand",
"exportImage": "Als afbeelding opslaan",
"export": "Exporteren",
"exportToPng": "Exporteren naar PNG",
"exportToSvg": "Exporteren naar SVG",
"copyToClipboard": "Kopieer",
"copyPngToClipboard": "Kopieer als PNG",
"scale": "Schaal",
"save": "Opslaan",
"save": "Opslaan naar huidige bestand",
"saveAs": "Opslaan als",
"load": "Open",
"getShareableLink": "Maak een deelbare link",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Selectie",
"freedraw": "Vrij tekenen",
"rectangle": "Rechthoek",
"diamond": "Ruit",
"ellipse": "Ovaal",
"arrow": "Pijl",
"line": "Lijn",
"freedraw": "Tekenen",
"text": "Tekst",
"library": "Bibliotheek",
"lock": "Geselecteerde tool actief houden na tekenen"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Fout"
},
"exportDialog": {
"disk_title": "Opslaan op schijf",
"disk_details": "De scènegegevens exporteren naar een bestand waaruit u later kunt importeren.",
"disk_button": "Opslaan naar bestand",
"link_title": "Deelbare link",
"link_details": "Exporteren als een alleen-lezen link.",
"link_button": "Exporteer naar link",
"excalidrawplus_description": "Sla de scène op in je Excalidraw+ werkruimte.",
"excalidrawplus_button": "Exporteren",
"excalidrawplus_exportError": "Kan op dit moment niet exporteren naar Excalidraw+..."
},
"helpDialog": {
"blog": "Lees onze blog",
"click": "klik",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Bakgrunn",
"fill": "Fyll",
"strokeWidth": "Strekbreidd",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "Strekstil",
"strokeStyle_solid": "Solid",
"strokeStyle_dashed": "Stipla",
@@ -38,8 +42,8 @@
"fontSize": "Skriftstorleik",
"fontFamily": "Skrifttype",
"onlySelected": "Kun valde",
"withBackground": "Med bakgrunn",
"exportEmbedScene": "Bygg scena inn i eksportert fil",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "Scenedata vert lagra i den eksporterte PNG- eller SVG-fila slik at scena kan bli gjenopprettast frå den. Dette vil auke eksportert filstorleik.",
"addWatermark": "Legg til «Laga med Excalidraw»",
"handDrawn": "Handteikna",
@@ -96,17 +100,22 @@
"flipVertical": "Vipp loddrett",
"viewMode": "Visningsmodus",
"toggleExportColorScheme": "Veksle eksport av fargepalett",
"share": "Del"
"share": "Del",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "Tilbakestill lerretet",
"exportJSON": "",
"exportImage": "",
"export": "Eksporter",
"exportToPng": "Eksporter til PNG",
"exportToSvg": "Eksporter til SVG",
"copyToClipboard": "Kopier til utklippstavla",
"copyPngToClipboard": "Kopier PNG til utklippstavla",
"scale": "Skaler",
"save": "Lagre",
"save": "",
"saveAs": "Lagre som",
"load": "Opne",
"getShareableLink": "Hent delingslenke",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Vel",
"freedraw": "Frihandsteikning",
"rectangle": "Rektangel",
"diamond": "Diamant",
"ellipse": "Ellipse",
"arrow": "Pil",
"line": "Linje",
"freedraw": "",
"text": "Tekst",
"library": "Bibliotek",
"lock": "Hald fram med valt verktøy"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Feil"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "Les bloggen vår",
"click": "klikk",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Rèireplan",
"fill": "Empliment",
"strokeWidth": "Largor de contorn",
"strokeShape": "Fòrma del trach",
"strokeShape_gel": "Estilo gèl",
"strokeShape_fountain": "Calam",
"strokeShape_brush": "Pincèl",
"strokeStyle": "Estil de contorn",
"strokeStyle_solid": "Solide",
"strokeStyle_dashed": "Tiret",
@@ -38,8 +42,8 @@
"fontSize": "Talha poliça",
"fontFamily": "Familha de poliça",
"onlySelected": "Seleccion sonque",
"withBackground": "Inclure lo rèireplan",
"exportEmbedScene": "Integrar la scèna al fichièr dexpo",
"withBackground": "Rèireplan",
"exportEmbedScene": "Scèna embarcada",
"exportEmbedScene_details": "Las donadas de scèna seràn enregistradas dins lo fichièr PNG/SVG exportat, per que la scèna pòsca èsser restaurada a partir daqueste fichièr.\nAumentarà la talha del fichièr exportat.",
"addWatermark": "Apondre « Fabricat amb Excalidraw »",
"handDrawn": "A la man levada",
@@ -96,17 +100,22 @@
"flipVertical": "Virar verticalament",
"viewMode": "Mòde de vista",
"toggleExportColorScheme": "Alternar lesquèma de color dexpòrt",
"share": "Partejar"
"share": "Partejar",
"showStroke": "Mostrar lo selector de color de contorn",
"showBackground": "Mostrar lo selector de color de fons",
"toggleTheme": "Alternar tèma"
},
"buttons": {
"clearReset": "Reïnicializar lo canabàs",
"exportJSON": "Exportar en fichièr",
"exportImage": "Salvar coma imatge",
"export": "Exportar",
"exportToPng": "Exportar en PNG",
"exportToSvg": "Exportar en SVG",
"copyToClipboard": "Copiar al quichapapièrs",
"copyPngToClipboard": "Copiar PNG al quichapapièrs",
"scale": "Escala",
"save": "Enregistrar",
"save": "Salvar al fichièr actual",
"saveAs": "Enregistrar jos",
"load": "Cargar",
"getShareableLink": "Obténer lo ligam de partatge",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Seleccion",
"freedraw": "Dessenh liure",
"rectangle": "Rectangle",
"diamond": "Lausange",
"ellipse": "Ellipsa",
"arrow": "Sageta",
"line": "Linha",
"freedraw": "Dessenhar",
"text": "Tèxt",
"library": "Bibliotèca",
"lock": "Mantenir activa laisina aprèp dessenhar"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Error"
},
"exportDialog": {
"disk_title": "Salvar al disc",
"disk_details": "Exportar las donadas de la scèna cap a un fichièr que podètz importar mai tard.",
"disk_button": "Salvar al fichièr",
"link_title": "Ligam de partejar",
"link_details": "Exportar coma un ligam de lectura sola.",
"link_button": "Exportar en ligam",
"excalidrawplus_description": "Enregistrar la scèna dins vòstre espaci de trabalh Excalidraw+.",
"excalidrawplus_button": "Exportar",
"excalidrawplus_exportError": "Export impossibla cap a Excalidraw+ pel moment..."
},
"helpDialog": {
"blog": "Legir nòstre blog",
"click": "clic",
+33 -13
View File
@@ -20,6 +20,10 @@
"background": "ਬੈਕਗਰਾਉਂਡ",
"fill": "ਭਰਨਾ",
"strokeWidth": "ਰੇਖਾ ਦੀ ਚੌੜਾਈ",
"strokeShape": "",
"strokeShape_gel": "ਜੈੱਲ ਪੈੱਨ",
"strokeShape_fountain": "ਫਾਉਨਟੇਨ ਪੈੱਨ",
"strokeShape_brush": "ਬੁਰਸ਼ ਪੈੱਨ",
"strokeStyle": "ਰੇਖਾ ਦਾ ਸਟਾਇਲ",
"strokeStyle_solid": "ਠੋਸ",
"strokeStyle_dashed": "ਡੈਸ਼ ਵਾਲੀ",
@@ -38,8 +42,8 @@
"fontSize": "ਫੌਂਟ ਅਕਾਰ",
"fontFamily": "ਫੌਂਟ ਪਰਿਵਾਰ",
"onlySelected": "ਸਿਰਫ ਚੁਣੇ ਹੋਏ ਹੀ",
"withBackground": "ਬੈਕਗਰਾਉਂਂਡ ਨਾਲ",
"exportEmbedScene": "ਦ੍ਰਿਸ਼ ਨੂੰ ਨਿਰਯਾਤ ਕੀਤੀ ਫਾਈਲ ਵਿੱਚ ਮੜ੍ਹੋ",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "ਦ੍ਰਿਸ਼ ਦਾ ਡਾਟਾ ਨਿਰਯਾਤ ਕੀਤੀ PNG/SVG ਫਾਈਲ ਵਿੱਚ ਸਾਂਭ ਦਿੱਤਾ ਜਾਵੇਗਾ ਤਾਂ ਜੋ ਇਸ ਵਿੱਚੋਂ ਦ੍ਰਿਸ਼ ਨੂੰ ਬਹਾਲ ਕੀਤਾ ਜਾ ਸਕੇ। ਇਹ ਨਿਰਯਾਤ ਕੀਤੀ ਜਾਣ ਵਾਲੀ ਫਾਈਲ ਦਾ ਅਕਾਰ ਵਧਾ ਦੇਵੇਗਾ।",
"addWatermark": "\"Excalidraw ਨਾਲ ਬਣਾਇਆ\" ਜੋੜੋ",
"handDrawn": "ਹੱਥਲਿਖਤ",
@@ -61,14 +65,14 @@
"architect": "ਭਵਨ ਨਿਰਮਾਣਕਾਰੀ",
"artist": "ਕਲਾਕਾਰ",
"cartoonist": "ਕਾਰਟੂਨਿਸਟ",
"fileTitle": "",
"fileTitle": "ਫਾਈਲ ਦਾ ਨਾਂ",
"colorPicker": "ਰੰਗ ਚੋਣਕਾਰ",
"canvasBackground": "ਕੈਨਵਸ ਦਾ ਬੈਕਗਰਾਉਂਡ",
"drawingCanvas": "ਡਰਾਇੰਗ ਕੈਨਵਸ",
"layers": "ਪਰਤਾਂ",
"actions": "ਕਾਰਵਾਈਆਂ",
"language": "ਭਾਸ਼ਾ",
"liveCollaboration": "",
"liveCollaboration": "ਲਾਇਵ ਸਹਿਯੋਗ",
"duplicateSelection": "ਡੁਪਲੀਕੇਟ ਬਣਾਓ",
"untitled": "ਬੇ-ਸਿਰਨਾਵਾਂ",
"name": "ਨਾਂ",
@@ -96,17 +100,22 @@
"flipVertical": "",
"viewMode": "ਦੇਖੋ ਮੋਡ",
"toggleExportColorScheme": "",
"share": ""
"share": "ਸਾਂਝਾ ਕਰੋ",
"showStroke": "",
"showBackground": "",
"toggleTheme": "ਥੀਮ ਬਦਲੋ"
},
"buttons": {
"clearReset": "ਕੈਨਵਸ ਰੀਸੈੱਟ ਕਰੋ",
"exportJSON": "",
"exportImage": "",
"export": "ਨਿਰਯਾਤ",
"exportToPng": "PNG ਵਿੱਚ ਨਿਰਯਾਤ ਕਰੋ",
"exportToSvg": "SVG ਵਿੱਚ ਨਿਰਯਾਤ ਕਰੋ",
"copyToClipboard": "ਕਲਿੱਪਬੋਰਡ 'ਤੇ ਕਾਪੀ ਕਰੋ",
"copyPngToClipboard": "PNG ਨੂੰ ਕਲਿੱਪਬੋਰਡ 'ਤੇ ਕਾਪੀ ਕਰੋ",
"scale": "ਪੈਮਾਇਸ਼",
"save": "ਸਾਂਭੋ",
"save": "",
"saveAs": "ਇਸ ਵਜੋਂ ਸਾਂਭੋ",
"load": "ਲੋਡ ਕਰੋ",
"getShareableLink": "ਸਾਂਝੀ ਕਰਨ ਵਾਲੀ ਲਿੰਕ ਲਵੋ",
@@ -121,7 +130,7 @@
"edit": "ਸੋਧੋ",
"undo": "ਅਣਕੀਤਾ ਕਰੋ",
"redo": "ਮੁੜ-ਕਰੋ",
"resetLibrary": "",
"resetLibrary": "ਲਾਇਬ੍ਰੇਰੀ ਰੀਸੈੱਟ ਕਰੋ",
"createNewRoom": "ਨਵਾਂ ਕਮਰਾ ਬਣਾਓ",
"fullScreen": "ਪੂਰੀ ਸਕਰੀਨ",
"darkMode": "ਡਾਰਕ ਮੋਡ",
@@ -142,22 +151,22 @@
"loadSceneOverridePrompt": "ਬਾਹਰੀ ਡਰਾਇੰਗ ਨੂੰ ਲੋਡ ਕਰਨਾ ਤੁਹਾਡੀ ਮੌਜੂਦਾ ਸਮੱਗਰੀ ਦੀ ਥਾਂ ਲੈ ਲਵੇਗਾ। ਕੀ ਤੁਸੀਂ ਜਾਰੀ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ?",
"collabStopOverridePrompt": "ਇਜਲਾਸ ਨੂੰ ਰੋਕਣਾ ਪਿਛਲੀ ਲੋਕਲ ਸਾਂਭੀ ਡਰਾਇੰਗ ਦੀ ਥਾਂ ਲੈ ਲਵੇਗਾ। ਪੱਕਾ ਇੰਝ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?\n\n(ਜੇ ਤੁਸੀਂ ਆਪਣੀ ਲੋਕਲ ਡਰਾਇੰਗ ਨੂੰ ਬਰਕਰਾਰ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ ਤਾਂ ਇਹ ਕਰਨ ਦੀ ਬਜਾਏ ਬੱਸ ਆਪਣਾ ਟੈਬ ਬੰਦ ਕਰ ਦਿਉ।)",
"errorLoadingLibrary": "ਤੀਜੀ ਧਿਰ ਦੀ ਲਾਇਬ੍ਰੇਰੀ ਨੂੰ ਲੋਡ ਕਰਨ ਵਿੱਚ ਗਲਤੀ ਹੋਈ ਸੀ।",
"errorAddingToLibrary": "",
"errorRemovingFromLibrary": "",
"errorAddingToLibrary": "ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚ ਸਮੱਗਰੀ ਨਹੀਂ ਜੋੜ ਸਕੇ",
"errorRemovingFromLibrary": "ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚੋਂ ਸਮੱਗਰੀ ਨਹੀਂ ਹਟਾ ਸਕੇ",
"confirmAddLibrary": "ਇਹ ਤੁਹਾਡੀ ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚ {{numShapes}} ਆਕ੍ਰਿਤੀ(ਆਂ) ਨੂੰ ਜੋੜ ਦੇਵੇਗਾ। ਕੀ ਤੁਸੀਂ ਪੱਕਾ ਇੰਝ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?",
"imageDoesNotContainScene": "ਫਿਲਹਾਲ ਤਸਵੀਰਾਂ ਨੂੰ ਆਯਾਤ ਕਰਨ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ।\n\nਕੀ ਤੁਸੀਂ ਦ੍ਰਿਸ਼ ਨੂੰ ਆਯਾਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਸੀ? ਇਸ ਤਸਵੀਰ ਵਿੱਚ ਦ੍ਰਿਸ਼ ਦਾ ਕੋਈ ਵੀ ਡਾਟਾ ਨਜ਼ਰ ਨਹੀਂ ਆ ਰਿਹਾ। ਕੀ ਨਿਰਯਾਤ ਦੌਰਾਨ ਤੁਸੀਂ ਇਹ ਸਮਰੱਥ ਕੀਤਾ ਸੀ?",
"cannotRestoreFromImage": "ਇਸ ਤਸਵੀਰ ਫਾਈਲ ਤੋਂ ਦ੍ਰਿਸ਼ ਬਹਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ",
"invalidSceneUrl": "",
"resetLibrary": ""
"resetLibrary": "ਇਹ ਤੁਹਾਡੀ ਲਾਇਬ੍ਰੇਰੀ ਨੂੰ ਸਾਫ ਕਰ ਦੇਵੇਗਾ। ਕੀ ਤੁਸੀਂ ਪੱਕਾ ਇੰਝ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"
},
"toolBar": {
"selection": "ਚੋਣਕਾਰ",
"freedraw": "ਖੁੱਲ੍ਹੀ ਵਾਹੀ",
"rectangle": "ਆਇਤ",
"diamond": "ਹੀਰਾ",
"ellipse": "ਅੰਡਾਕਾਰ",
"arrow": "ਤੀਰ",
"line": "ਲਕੀਰ",
"freedraw": "",
"text": "ਪਾਠ",
"library": "ਲਾਇਬ੍ਰੇਰੀ",
"lock": "ਡਰਾਇੰਗ ਤੋਂ ਬਾਅਦ ਵੀ ਚੁਣੇ ਹੋਏ ਸੰਦ ਨੂੰ ਸਰਗਰਮ ਰੱਖੋ "
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "ਗਲਤੀ"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "ਸਾਡਾ ਬਲੌਗ ਪੜ੍ਹੋ",
"click": "ਕਲਿੱਕ",
@@ -256,7 +276,7 @@
"copyToClipboardAsPng": "",
"fileSaved": "ਫਾਈਲ ਸਾਂਭੀ ਗਈ।",
"fileSavedToFilename": "{filename} ਵਿੱਚ ਸਾਂਭੀ",
"canvas": "",
"selection": ""
"canvas": "ਕੈਨਵਸ",
"selection": "ਚੋਣ"
}
}
+24 -23
View File
@@ -1,38 +1,39 @@
{
"ar-SA": 84,
"bg-BG": 92,
"ca-ES": 99,
"ar-SA": 92,
"bg-BG": 83,
"ca-ES": 94,
"cs-CZ": 36,
"de-DE": 100,
"el-GR": 97,
"el-GR": 88,
"en": 100,
"es-ES": 99,
"fa-IR": 87,
"es-ES": 98,
"fa-IR": 79,
"fi-FI": 99,
"fr-FR": 100,
"he-IL": 88,
"hi-IN": 91,
"hu-HU": 80,
"he-IL": 80,
"hi-IN": 82,
"hu-HU": 73,
"id-ID": 100,
"it-IT": 100,
"ja-JP": 96,
"kab-KAB": 99,
"ko-KR": 91,
"lv-LV": 0,
"my-MM": 75,
"it-IT": 99,
"ja-JP": 98,
"kab-KAB": 98,
"ko-KR": 83,
"lv-LV": 17,
"my-MM": 68,
"nb-NO": 100,
"nl-NL": 100,
"nn-NO": 100,
"nn-NO": 90,
"oc-FR": 100,
"pa-IN": 93,
"pl-PL": 94,
"pt-BR": 100,
"pt-PT": 99,
"pa-IN": 89,
"pl-PL": 85,
"pt-BR": 90,
"pt-PT": 92,
"ro-RO": 100,
"ru-RU": 97,
"sk-SK": 100,
"sv-SE": 100,
"tr-TR": 100,
"uk-UA": 100,
"zh-CN": 100,
"tr-TR": 91,
"uk-UA": 97,
"zh-CN": 98,
"zh-TW": 99
}
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Kolor wypełnienia",
"fill": "Wypełnienie",
"strokeWidth": "Grubość obramowania",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "Styl obrysu",
"strokeStyle_solid": "Pełny",
"strokeStyle_dashed": "Kreskowany",
@@ -38,8 +42,8 @@
"fontSize": "Rozmiar tekstu",
"fontFamily": "Krój pisma",
"onlySelected": "Tylko wybrane",
"withBackground": "Z tłem",
"exportEmbedScene": "Osadź scenę w eksportowanym pliku",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "Dane sceny zostaną zapisane w eksportowanym pliku PNG/SVG tak, aby scena mogła zostać z niego przywrócona.\nZwiększy to rozmiar eksportowanego pliku.",
"addWatermark": "Dodaj \"Zrobione w Excalidraw\"",
"handDrawn": "Odręczny",
@@ -96,17 +100,22 @@
"flipVertical": "",
"viewMode": "Tryb widoku",
"toggleExportColorScheme": "",
"share": ""
"share": "",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "Wyczyść dokument i zresetuj kolor dokumentu",
"exportJSON": "",
"exportImage": "",
"export": "Zapisz jako",
"exportToPng": "Zapisz jako PNG",
"exportToSvg": "Zapisz jako SVG",
"copyToClipboard": "Skopiuj do schowka",
"copyPngToClipboard": "Skopiuj do schowka jako plik PNG",
"scale": "Skala",
"save": "Zapisz",
"save": "",
"saveAs": "Zapisz jako",
"load": "Otwórz",
"getShareableLink": "Udostępnij",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Zaznaczenie",
"freedraw": "Swobodne rysowanie",
"rectangle": "Prostokąt",
"diamond": "Romb",
"ellipse": "Elipsa",
"arrow": "Strzałka",
"line": "Linia",
"freedraw": "",
"text": "Tekst",
"library": "Biblioteka",
"lock": "Zablokuj wybrane narzędzie"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Wystąpił błąd"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "Przeczytaj na naszym blogu",
"click": "kliknięcie",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Fundo",
"fill": "Preenchimento",
"strokeWidth": "Espessura do traço",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "Estilo de traço",
"strokeStyle_solid": "Sólido",
"strokeStyle_dashed": "Tracejado",
@@ -38,8 +42,8 @@
"fontSize": "Tamanho da fonte",
"fontFamily": "Família da fonte",
"onlySelected": "Somente a seleção",
"withBackground": "Com fundo",
"exportEmbedScene": "Incorporar a cena no arquivo exportado",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "Os dados da cena serão salvos no arquivo PNG/SVG exportado para que a cena possa ser restaurada.\nIrá aumentar o tamanho do arquivo exportado.",
"addWatermark": "Adicionar \"Feito com Excalidraw\"",
"handDrawn": "Manuscrito",
@@ -96,17 +100,22 @@
"flipVertical": "Inverter verticalmente",
"viewMode": "Modo de visualização",
"toggleExportColorScheme": "Alternar esquema de cores de exportação",
"share": "Compartilhar"
"share": "Compartilhar",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "Limpar o canvas e redefinir a cor de fundo",
"exportJSON": "",
"exportImage": "",
"export": "Exportar",
"exportToPng": "Exportar em PNG",
"exportToSvg": "Exportar em SVG",
"copyToClipboard": "Copiar para o clipboard",
"copyPngToClipboard": "Copiar PNG para área de transferência",
"scale": "Escala",
"save": "Salvar",
"save": "",
"saveAs": "Salvar como",
"load": "Carregar",
"getShareableLink": "Obter um link de compartilhamento",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Seleção",
"freedraw": "Desenho livre",
"rectangle": "Retângulo",
"diamond": "Losango",
"ellipse": "Elipse",
"arrow": "Flecha",
"line": "Linha",
"freedraw": "",
"text": "Texto",
"library": "Biblioteca",
"lock": "Manter ativa a ferramenta selecionada após desenhar"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Erro"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "Leia o nosso blog",
"click": "clicar",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Fundo",
"fill": "Preenchimento",
"strokeWidth": "Espessura do traço",
"strokeShape": "Forma do traço",
"strokeShape_gel": "Caneta de gel",
"strokeShape_fountain": "Caneta de fonte",
"strokeShape_brush": "Caneta de pincel",
"strokeStyle": "Estilo de traço",
"strokeStyle_solid": "Sólido",
"strokeStyle_dashed": "Tracejado",
@@ -38,8 +42,8 @@
"fontSize": "Tamanho da fonte",
"fontFamily": "Família da fontes",
"onlySelected": "Somente a seleção",
"withBackground": "Com fundo",
"exportEmbedScene": "Incorporar a cena no arquivo exportado",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "Os dados da cena serão salvos no arquivo PNG/SVG exportado para que a cena possa ser restaurada.\nIrá aumentar o tamanho do arquivo exportado.",
"addWatermark": "Adicionar \"Feito com Excalidraw\"",
"handDrawn": "Manuscrito",
@@ -96,17 +100,22 @@
"flipVertical": "Inverter verticalmente",
"viewMode": "Modo de visualização",
"toggleExportColorScheme": "Alternar esquema de cores de exportação",
"share": "Partilhar"
"share": "Partilhar",
"showStroke": "",
"showBackground": "",
"toggleTheme": "Alternar tema"
},
"buttons": {
"clearReset": "Limpar o canvas e redefinir a cor de fundo",
"exportJSON": "",
"exportImage": "",
"export": "Exportar",
"exportToPng": "Exportar em PNG",
"exportToSvg": "Exportar em SVG",
"copyToClipboard": "Copiar para o clipboard",
"copyPngToClipboard": "Copiar PNG para área de transferência",
"scale": "Escala",
"save": "Guardar",
"save": "",
"saveAs": "Salvar como",
"load": "Carregar",
"getShareableLink": "Obter um link de partilha",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Seleção",
"freedraw": "Desenho livre",
"rectangle": "Retângulo",
"diamond": "Losango",
"ellipse": "Elipse",
"arrow": "Flecha",
"line": "Linha",
"freedraw": "Desenhar",
"text": "Texto",
"library": "Biblioteca",
"lock": "Manter a ferramenta selecionada ativa após desenhar"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Erro"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "Leia o nosso blog",
"click": "clicar",
+29 -9
View File
@@ -20,6 +20,10 @@
"background": "Fundal",
"fill": "Umplere",
"strokeWidth": "Lățimea conturului",
"strokeShape": "Forma conturului",
"strokeShape_gel": "Pix cu gel",
"strokeShape_fountain": "Stilou",
"strokeShape_brush": "Pensulă tip stilou",
"strokeStyle": "Stilul conturului",
"strokeStyle_solid": "Neîntrerupt",
"strokeStyle_dashed": "Liniuțe",
@@ -38,8 +42,8 @@
"fontSize": "Dimensiune font",
"fontFamily": "Familia de fonturi",
"onlySelected": "Numai selecția",
"withBackground": "Cu fundal",
"exportEmbedScene": "Încorporează scena în fișierul exportat",
"withBackground": "Fundal",
"exportEmbedScene": "Încorporare scenă",
"exportEmbedScene_details": "Datele scenei vor fi salvate în fișierul PNG/SVG exportat, astfel că scena va putea fi restaurată din acesta.\nVa crește dimensiunea fișierului exportat.",
"addWatermark": "Adaugă „Realizat cu Excalidraw”",
"handDrawn": "Scris de mână",
@@ -96,20 +100,25 @@
"flipVertical": "Răsturnare verticală",
"viewMode": "Mod de vizualizare",
"toggleExportColorScheme": "Comutare schemă de culori de export",
"share": "Distribuie"
"share": "Distribuie",
"showStroke": "Afișare selector culoare contur",
"showBackground": "Afișare selector culoare fundal",
"toggleTheme": "Comutare temă"
},
"buttons": {
"clearReset": "Resetare pânză",
"exportJSON": "Exportare la fișiere",
"exportImage": "Salvare ca imagine",
"export": "Exportare",
"exportToPng": "Exportare ca PNG",
"exportToSvg": "Exportare ca SVG",
"copyToClipboard": "Copiere în memoria temporară",
"copyPngToClipboard": "Copiere PNG în memoria temporară",
"scale": "Scală",
"save": "Salvare",
"save": "Salvare în fișierul curent",
"saveAs": "Salvare ca",
"load": "Încărcare",
"getShareableLink": "Legătură partajabilă",
"getShareableLink": "Obține URL partajabil",
"close": "Închidere",
"selectLanguage": "Selectare limbă",
"scrollBackToContent": "Derulare înapoi la conținut",
@@ -131,8 +140,8 @@
},
"alerts": {
"clearReset": "Această opțiune va șterge întreaga pânză. Confirmi?",
"couldNotCreateShareableLink": "Legătura partajabilă nu a putut fi crea.",
"couldNotCreateShareableLinkTooBig": "Nu s-a putut crea o legătură partajabilă: scena este prea mare",
"couldNotCreateShareableLink": "Nu s-a putut crea un URL partajabil.",
"couldNotCreateShareableLinkTooBig": "Nu s-a putut crea un URL partajabil: scena este prea mare",
"couldNotLoadInvalidFile": "Fișierul invalid nu a putut fi încărcat",
"importBackendFailed": "Importarea de la nivel de server a eșuat.",
"cannotExportEmptyCanvas": "Nu se poate exporta pânza goală.",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Selecție",
"freedraw": "Desenare liberă",
"rectangle": "Dreptunghi",
"diamond": "Romb",
"ellipse": "Elipsă",
"arrow": "Săgeată",
"line": "Linie",
"freedraw": "Desenare",
"text": "Text",
"library": "Bibliotecă",
"lock": "Menține activ instrumentul selectat după desenare"
@@ -203,13 +212,24 @@
"button_startSession": "Pornire sesiune",
"button_stopSession": "Oprire sesiune",
"desc_inProgressIntro": "Sesiunea de colaborare în direct este în curs de desfășurare.",
"desc_shareLink": "Distribuie această legătură persoanelor cu care dorești să colaborezi:",
"desc_shareLink": "Distribuie acest URL persoanelor cu care dorești să colaborezi:",
"desc_exitSession": "Oprirea sesiunii te va deconecta de la sală, însă vei putea lucra în continuare, pe plan local, cu scena. Reține că această opțiune nu va afecta alte persoane, iar acestea vor putea să colaboreze în continuare pe versiunea lor.",
"shareTitle": "Alătură-te unei sesiuni de colaborare în direct pe Excalidraw"
},
"errorDialog": {
"title": "Eroare"
},
"exportDialog": {
"disk_title": "Salvare pe disc",
"disk_details": "Exportă datele scenei pe un fișier din care poți importa mai târziu.",
"disk_button": "Salvare în fișier",
"link_title": "URL partajabil",
"link_details": "Exportă ca URL doar în citire.",
"link_button": "Exportare în URL",
"excalidrawplus_description": "Salvează scena în spațiul de lucru Excalidraw+.",
"excalidrawplus_button": "Exportare",
"excalidrawplus_exportError": "Excalidraw+ nu a putut fi exportat în acest moment..."
},
"helpDialog": {
"blog": "Citește blogul nostru",
"click": "clic",
+28 -8
View File
@@ -20,6 +20,10 @@
"background": "Фон",
"fill": "Заливка",
"strokeWidth": "Толщина штриха",
"strokeShape": "Стиль обводки",
"strokeShape_gel": "Гелевая ручка",
"strokeShape_fountain": "Фонтанная ручка",
"strokeShape_brush": "Кисть",
"strokeStyle": "Стиль обводки",
"strokeStyle_solid": "Сплошная",
"strokeStyle_dashed": "Пунктирная",
@@ -38,8 +42,8 @@
"fontSize": "Размер шрифта",
"fontFamily": "Семейство шрифтов",
"onlySelected": "Только выбранные",
"withBackground": "С фоном",
"exportEmbedScene": "Встроить информацию о сцене в экспортируемый файл",
"withBackground": "Фон",
"exportEmbedScene": "Встроить сцену",
"exportEmbedScene_details": "Сцена будет сохранена в PNG/SVG файл так, чтобы всю сцену можно будет восстановить из этого файла. Это увеличит размер файла.",
"addWatermark": "Добавить «Создано в Excalidraw»",
"handDrawn": "От руки",
@@ -92,21 +96,26 @@
"centerHorizontally": "Центрировать по горизонтали",
"distributeHorizontally": "Распределить по горизонтали",
"distributeVertically": "Распределить по вертикали",
"flipHorizontal": "",
"flipVertical": "",
"flipHorizontal": "Переворот по горизонтали",
"flipVertical": "Переворот по вертикали",
"viewMode": "Вид",
"toggleExportColorScheme": "Экспортировать цветовую схему",
"share": "Поделиться"
"share": "Поделиться",
"showStroke": "",
"showBackground": "",
"toggleTheme": ""
},
"buttons": {
"clearReset": "Очистить холст и сбросить цвет фона",
"exportJSON": "Сохранить в",
"exportImage": "Сохранить как изображение",
"export": "Экспортировать",
"exportToPng": "Экспорт в PNG",
"exportToSvg": "Экспорт в SVG",
"copyToClipboard": "Скопировать в буфер обмена",
"copyPngToClipboard": "Скопировать PNG в буфер обмена",
"scale": "Масштаб",
"save": "Сохранить",
"save": "Сохранить в текущий файл",
"saveAs": "Сохранить как",
"load": "Загрузить",
"getShareableLink": "Получить доступ по ссылке",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Выделение области",
"freedraw": "Свободное рисование",
"rectangle": "Прямоугольник",
"diamond": "Ромб",
"ellipse": "Эллипс",
"arrow": "Cтрелка",
"line": "Линия",
"freedraw": "",
"text": "Текст",
"library": "Библиотека",
"lock": "Сохранять выбранный инструмент активным после рисования"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Ошибка"
},
"exportDialog": {
"disk_title": "Сохранить на диск",
"disk_details": "Экспортировать данные сцены в файл, из которого можно импортировать позже.",
"disk_button": "Сохранить в файл",
"link_title": "Поделитесь ссылкой",
"link_details": "Экспорт ссылки только для чтения.",
"link_button": "Экспорт в ссылку",
"excalidrawplus_description": "",
"excalidrawplus_button": "Экспорт",
"excalidrawplus_exportError": "Не удалось экспортировать в Excalidraw+ на данный момент..."
},
"helpDialog": {
"blog": "Прочитайте наш блог",
"click": "нажать",
@@ -233,7 +253,7 @@
},
"encrypted": {
"tooltip": "Ваши данные защищены сквозным (End-to-end) шифрованием. Серверы Excalidraw никогда не получат доступ к ним.",
"link": ""
"link": "Запись блога о сквозном шифровании в Excalidraw"
},
"stats": {
"angle": "Угол",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Pozadie",
"fill": "Výplň",
"strokeWidth": "Hrúbka obrysu",
"strokeShape": "Tvar obrysu",
"strokeShape_gel": "Gélové pero",
"strokeShape_fountain": "Plniace pero",
"strokeShape_brush": "Fixka",
"strokeStyle": "Štýl obrysu",
"strokeStyle_solid": "Plný",
"strokeStyle_dashed": "Čiarkovaný",
@@ -38,8 +42,8 @@
"fontSize": "Veľkosť písma",
"fontFamily": "Písmo",
"onlySelected": "Iba vybrané",
"withBackground": "S pozadím",
"exportEmbedScene": "Uložiť scénu do exportovaného súboru",
"withBackground": "Pozadie",
"exportEmbedScene": "Zahrnúť scénu",
"exportEmbedScene_details": "Údaje scény budú uložené do exportovaného PNG/SVG súboru, takže scéna z neho môže byť opäť obnovená.\nBude to mať za následok zvýšenie veľkosti súboru.",
"addWatermark": "Pridať \"Vytvorené s Excalidraw\"",
"handDrawn": "Ručne písané",
@@ -96,17 +100,22 @@
"flipVertical": "Prevrátiť zvislo",
"viewMode": "Režim zobrazenia",
"toggleExportColorScheme": "Prepnúť exportovanie farebnej schémy",
"share": "Zdieľať"
"share": "Zdieľať",
"showStroke": "Zobraziť výber farby pre obrys",
"showBackground": "Zobraziť výber farby pre pozadie",
"toggleTheme": "Prepnúť tému"
},
"buttons": {
"clearReset": "Obnoviť plátno",
"exportJSON": "Exportovať do súboru",
"exportImage": "Uložiť ako obrázok",
"export": "Exportovať",
"exportToPng": "Exportovať do PNG",
"exportToSvg": "Exportovať do SVG",
"copyToClipboard": "Kopírovať do schránky",
"copyPngToClipboard": "Kopírovať PNG do schránky",
"scale": "Mierka",
"save": "Uložiť",
"save": "Uložiť do aktuálneho súboru",
"saveAs": "Uložiť ako",
"load": "Nahrať",
"getShareableLink": "Získať odkaz na zdieľanie",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Výber",
"freedraw": "Voľné kreslenie",
"rectangle": "Obdĺžnik",
"diamond": "Diamant",
"ellipse": "Elipsa",
"arrow": "Šípka",
"line": "Čiara",
"freedraw": "Kresliť",
"text": "Text",
"library": "Knižnica",
"lock": "Nechať zvolený nástroj aktívny po skončení kreslenia"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Chyba"
},
"exportDialog": {
"disk_title": "Uložiť na disk",
"disk_details": "Exportovať údaje scény do súboru, z ktorého môžu byť neskôr importované.",
"disk_button": "Uložiť do súboru",
"link_title": "Odkaz na zdieľanie",
"link_details": "Exportovať ako odkaz iba na čítanie.",
"link_button": "Exportovať ako odkaz",
"excalidrawplus_description": "Uložiť scénu do vášho Excalidraw+ pracovného priestoru.",
"excalidrawplus_button": "Exportovať",
"excalidrawplus_exportError": "Nepodarilo sa vykonať export do Excalidraw+..."
},
"helpDialog": {
"blog": "Prečítajte si náš blog",
"click": "kliknutie",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Bakgrund",
"fill": "Fyllnad",
"strokeWidth": "Linjebredd",
"strokeShape": "Linjeform",
"strokeShape_gel": "Gelépenna",
"strokeShape_fountain": "Reservoarpenna",
"strokeShape_brush": "Penselpenna",
"strokeStyle": "Linjestil",
"strokeStyle_solid": "Solid",
"strokeStyle_dashed": "Streckad",
@@ -38,8 +42,8 @@
"fontSize": "Teckenstorlek",
"fontFamily": "Teckensnitt",
"onlySelected": "Endast markering",
"withBackground": "Med bakgrund",
"exportEmbedScene": "Bädda in skiss i exporterad fil",
"withBackground": "Bakgrund",
"exportEmbedScene": "Bädda in skiss",
"exportEmbedScene_details": "Skissdata kommer att sparas i den exporterade PNG/SVG-filen så att skissen kan återställas från den.\nKommer att öka exporterad filstorlek.",
"addWatermark": "Lägg till \"Skapad med Excalidraw\"",
"handDrawn": "Handritad",
@@ -96,17 +100,22 @@
"flipVertical": "Vänd vertikalt",
"viewMode": "Visningsläge",
"toggleExportColorScheme": "Växla färgschema för export",
"share": "Dela"
"share": "Dela",
"showStroke": "Visa färgväljare för linjefärg",
"showBackground": "Visa färgväljare för bakgrundsfärg",
"toggleTheme": "Växla tema"
},
"buttons": {
"clearReset": "Återställ canvasen",
"exportJSON": "Exportera till fil",
"exportImage": "Spara som bild",
"export": "Exportera",
"exportToPng": "Exportera till PNG",
"exportToSvg": "Exportera till SVG",
"copyToClipboard": "Kopiera till urklipp",
"copyPngToClipboard": "Kopiera PNG till urklipp",
"scale": "Skala",
"save": "Spara",
"save": "Spara till aktuell fil",
"saveAs": "Spara som",
"load": "Öppna",
"getShareableLink": "Hämta delbar länk",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Markering",
"freedraw": "Frihand",
"rectangle": "Rektangel",
"diamond": "Diamant",
"ellipse": "Ellips",
"arrow": "Pil",
"line": "Linje",
"freedraw": "Rita",
"text": "Text",
"library": "Bibliotek",
"lock": "Håll valt verktyg aktivt efter ritande"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Fel"
},
"exportDialog": {
"disk_title": "Spara till disk",
"disk_details": "Exportera skissdata till en fil som du kan importera från senare.",
"disk_button": "Spara till fil",
"link_title": "Delbar länk",
"link_details": "Exportera som en skrivskyddad länk.",
"link_button": "Exportera till länk",
"excalidrawplus_description": "Spara skissen till din Excalidraw+ arbetsyta.",
"excalidrawplus_button": "Exportera",
"excalidrawplus_exportError": "Det gick inte att exportera till Excalidraw+ just nu..."
},
"helpDialog": {
"blog": "Läs vår blogg",
"click": "klicka",
+26 -6
View File
@@ -20,6 +20,10 @@
"background": "Arka plan",
"fill": "Doldur",
"strokeWidth": "Kontur genişliği",
"strokeShape": "",
"strokeShape_gel": "",
"strokeShape_fountain": "",
"strokeShape_brush": "",
"strokeStyle": "Kontur stili",
"strokeStyle_solid": "Dolu",
"strokeStyle_dashed": "Kesik çizgili",
@@ -30,7 +34,7 @@
"edges": "Kenarlar",
"sharp": "Keskin",
"round": "Yuvarlak",
"arrowheads": "Ok başları",
"arrowheads": "Ok ları",
"arrowhead_none": "Yok",
"arrowhead_arrow": "Ok",
"arrowhead_bar": "Çizgi",
@@ -38,8 +42,8 @@
"fontSize": "Yazı tipi boyutu",
"fontFamily": "Yazı tipi ailesi",
"onlySelected": "Sadece seçilen",
"withBackground": "Arka planla beraber",
"exportEmbedScene": "Sahneyi çıktı dosyasına dahil et",
"withBackground": "",
"exportEmbedScene": "",
"exportEmbedScene_details": "Sahne datası, daha sonra geri kullanılabilmesi için çıktı alınan PNG/SVG dosyasına dahil edicelek. Bu işlem dosya boyutunu arttıracaktır.",
"addWatermark": "\"Excalidraw ile yapıldı\" yazısını ekle",
"handDrawn": "El-yazısı",
@@ -96,17 +100,22 @@
"flipVertical": "Dikey döndür",
"viewMode": "Görünüm modu",
"toggleExportColorScheme": "Renk şemasını dışa aktar/aktarma",
"share": "Paylaş"
"share": "Paylaş",
"showStroke": "",
"showBackground": "",
"toggleTheme": "Temayı etkinleştir/devre dışı bırak"
},
"buttons": {
"clearReset": "Tuvali sıfırla",
"exportJSON": "",
"exportImage": "",
"export": "Dışa aktar",
"exportToPng": "PNG olarak dışa aktar",
"exportToSvg": "SVG olarak dışa aktar",
"copyToClipboard": "Panoya kopyala",
"copyPngToClipboard": "PNG'yi panoya kopyala",
"scale": "Ölçek",
"save": "Kaydet",
"save": "",
"saveAs": "Farklı kaydet",
"load": "Yükle",
"getShareableLink": "Paylaşılabilir bağlantı al",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Seçme",
"freedraw": "Serbest çizim",
"rectangle": "Dikdörtgen",
"diamond": "Elmas",
"ellipse": "Elips",
"arrow": "Ok",
"line": "Çizgi",
"freedraw": "Çiz",
"text": "Yazı",
"library": "Kütüphane",
"lock": "Seçilen aracı çizimden sonra aktif tut"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Hata"
},
"exportDialog": {
"disk_title": "",
"disk_details": "",
"disk_button": "",
"link_title": "",
"link_details": "",
"link_button": "",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "Blog'umuzu okuyun",
"click": "tıkla",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "Тло",
"fill": "Заповнити",
"strokeWidth": "Товщина контуру",
"strokeShape": "Форма обведення",
"strokeShape_gel": "Гельручка",
"strokeShape_fountain": "Перо",
"strokeShape_brush": "Пензель",
"strokeStyle": "Стиль контуру",
"strokeStyle_solid": "Суцільний",
"strokeStyle_dashed": "Пунктир",
@@ -38,8 +42,8 @@
"fontSize": "Розмір шрифту",
"fontFamily": "Шрифт",
"onlySelected": "Тільки вибране",
"withBackground": "З фоном",
"exportEmbedScene": "Вставити сцену в експортований файл",
"withBackground": "Фон",
"exportEmbedScene": "Вбудована сцена",
"exportEmbedScene_details": "Дані сцени будуть збережені в експортований файл PNG/SVG. Ця сцена може бути відновленна з нього, однак це збільшить розмір експортованого файлу.",
"addWatermark": "Додати «Накреслене в Excalidraw»",
"handDrawn": "Рукописний",
@@ -96,17 +100,22 @@
"flipVertical": "Віддзеркалити вертикально",
"viewMode": "Режим перегляду",
"toggleExportColorScheme": "Переключити колірну схему експорту",
"share": "Поділитися"
"share": "Поділитися",
"showStroke": "",
"showBackground": "",
"toggleTheme": "Перемкнути тему"
},
"buttons": {
"clearReset": "Очистити полотно",
"exportJSON": "Експорт у файл",
"exportImage": "Зберегти як зображення",
"export": "Експортувати",
"exportToPng": "Експортувати в PNG",
"exportToSvg": "Експортувати в SVG",
"copyToClipboard": "Скопіювати до буферу обміну",
"copyPngToClipboard": "Скопіювати PNG до буферу обміну",
"scale": "Масштаб",
"save": "Зберегти",
"save": "Зберегти до поточного файлу",
"saveAs": "Зберегти як",
"load": "Завантажити",
"getShareableLink": "Отримати посилання",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "Виділення",
"freedraw": "Вільне креслення",
"rectangle": "Прямокутник",
"diamond": "Ромб",
"ellipse": "Еліпс",
"arrow": "Стрілка",
"line": "Лінія",
"freedraw": "Малювати",
"text": "Текст",
"library": "Бібліотека",
"lock": "Залишити обраний інструмент після креслення"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "Помилка"
},
"exportDialog": {
"disk_title": "Зберегти на диск",
"disk_details": "Експорт даних сцени в файл, з якого можна імпортувати пізніше.",
"disk_button": "Зберегти до файлу",
"link_title": "Доступ за посиланням",
"link_details": "Експортувати як посилання тільки для читання.",
"link_button": "Експортувати у посилання",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "Наш блог",
"click": "натиснути",
+26 -6
View File
@@ -20,6 +20,10 @@
"background": "背景",
"fill": "填充",
"strokeWidth": "描边宽度",
"strokeShape": "描边形状",
"strokeShape_gel": "中性笔",
"strokeShape_fountain": "钢笔",
"strokeShape_brush": "墨笔",
"strokeStyle": "描边 (样式)",
"strokeStyle_solid": "实线",
"strokeStyle_dashed": "虚线",
@@ -38,8 +42,8 @@
"fontSize": "字体大小",
"fontFamily": "字体",
"onlySelected": "仅被选中",
"withBackground": "包括背景",
"exportEmbedScene": "画布数据嵌入到导出的文件",
"withBackground": "背景",
"exportEmbedScene": "包含画布数据",
"exportEmbedScene_details": "画布数据将被保存到导出的 PNG/SVG 文件,以便恢复。\n将会增加导出的文件大小。",
"addWatermark": "添加 “使用 Excalidraw 创建” 水印",
"handDrawn": "手写",
@@ -96,17 +100,22 @@
"flipVertical": "垂直翻转",
"viewMode": "查看模式",
"toggleExportColorScheme": "切换导出配色方案",
"share": "分享"
"share": "分享",
"showStroke": "显示描边颜色选择器",
"showBackground": "显示背景颜色选择器",
"toggleTheme": "切换主题"
},
"buttons": {
"clearReset": "重置画布",
"exportJSON": "导出为文件",
"exportImage": "保存为图像",
"export": "导出",
"exportToPng": "导出为 PNG",
"exportToSvg": "导出为 SVG",
"copyToClipboard": "复制到剪贴板",
"copyPngToClipboard": "复制 PNG 到剪切板",
"scale": "缩放",
"save": "保存",
"save": "保存至当前文件",
"saveAs": "保存为",
"load": "载入文件",
"getShareableLink": "获取共享链接",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "选择",
"freedraw": "自由书写",
"rectangle": "矩形",
"diamond": "菱形",
"ellipse": "椭圆",
"arrow": "箭头",
"line": "线条",
"freedraw": "自由书写",
"text": "文字",
"library": "库",
"lock": "绘制后保持所选的工具栏状态"
@@ -169,7 +178,7 @@
},
"hints": {
"linearElement": "点击创建多个点 拖动创建直线",
"freeDraw": "点击并拖动,完成后发布",
"freeDraw": "点击并拖动,完成时松开",
"text": "提示:您也可以使用选择工具双击任意位置来添加文字",
"linearElementMulti": "点击最后一个点或按下 Esc/Enter 来完成",
"lockAngle": "可以按住 Shift 来约束角度",
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "错误"
},
"exportDialog": {
"disk_title": "保存到本地",
"disk_details": "将画布数据导出为文件,以便以后导入",
"disk_button": "保存为文件",
"link_title": "分享链接",
"link_details": "导出为只读链接。",
"link_button": "导出链接",
"excalidrawplus_description": "",
"excalidrawplus_button": "",
"excalidrawplus_exportError": ""
},
"helpDialog": {
"blog": "浏览我们的博客",
"click": "单击",
+25 -5
View File
@@ -20,6 +20,10 @@
"background": "背景",
"fill": "填充",
"strokeWidth": "筆劃寬度",
"strokeShape": "筆畫形狀",
"strokeShape_gel": "中性筆",
"strokeShape_fountain": "鋼筆",
"strokeShape_brush": "毛筆",
"strokeStyle": "筆畫樣式",
"strokeStyle_solid": "實線",
"strokeStyle_dashed": "虛線",
@@ -38,8 +42,8 @@
"fontSize": "字型大小",
"fontFamily": "字體",
"onlySelected": "僅選取物件",
"withBackground": "包含背景",
"exportEmbedScene": "在輸出的檔案中嵌入場景",
"withBackground": "背景",
"exportEmbedScene": "嵌入場景",
"exportEmbedScene_details": "用於回復場景的場景資料會被包含在輸出的 PNG/SVG 檔案中。\n會增加輸出的檔案大小。",
"addWatermark": "加上 \"Made with Excalidraw\"",
"handDrawn": "手寫",
@@ -96,17 +100,22 @@
"flipVertical": "垂直翻轉",
"viewMode": "檢視模式",
"toggleExportColorScheme": "切換輸出配色",
"share": "共享"
"share": "共享",
"showStroke": "顯示線條檢色器",
"showBackground": "顯示背景檢色器",
"toggleTheme": "切換主題"
},
"buttons": {
"clearReset": "重置 canvas",
"exportJSON": "匯出至檔案",
"exportImage": "另存為圖片",
"export": "輸出",
"exportToPng": "輸出成 PNG",
"exportToSvg": "輸出成 SVG",
"copyToClipboard": "複製至剪貼簿",
"copyPngToClipboard": "複製 PNG 至剪貼簿",
"scale": "縮放比例",
"save": "儲存",
"save": "儲存目前檔案",
"saveAs": "儲存為",
"load": "載入",
"getShareableLink": "取得共享連結",
@@ -152,12 +161,12 @@
},
"toolBar": {
"selection": "選取",
"freedraw": "繪圖",
"rectangle": "長方形",
"diamond": "菱形",
"ellipse": "橢圓",
"arrow": "箭頭",
"line": "線條",
"freedraw": "繪圖",
"text": "文字",
"library": "資料庫",
"lock": "可連續使用選取的工具"
@@ -210,6 +219,17 @@
"errorDialog": {
"title": "錯誤"
},
"exportDialog": {
"disk_title": "儲存至硬碟",
"disk_details": "將場景匯出為可供匯入之檔案",
"disk_button": "儲存至檔案",
"link_title": "可共享連結",
"link_details": "匯出為唯讀連結",
"link_button": "匯出為連結",
"excalidrawplus_description": "將此場景儲存至你的 Excalidraw+ 工作區",
"excalidrawplus_button": "輸出",
"excalidrawplus_exportError": "目前無法輸出至 Excalidraw+"
},
"helpDialog": {
"blog": "閱讀部落格",
"click": "點擊",
+39
View File
@@ -11,6 +11,45 @@ The change should be grouped under one of the below section and must contain PR
Please add the latest change on the top under the correct section.
-->
## Unreleased
**This changes are not yet released but you can still try it out in [@excalidraw/excalidraw-next](https://www.npmjs.com/package/@excalidraw/excalidraw-next).**
## Excalidraw API
### Features
- Expose [`FONT_FAMILY`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#FONT_FAMILY) so that consumer can use when passing `initialData.appState.currentItemFontFamily`.
- Added prop [`autoFocus`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#autoFocus) to focus the excalidraw component on page load when enabled, defaults to false [#3691](https://github.com/excalidraw/excalidraw/pull/3691).
Note: Earlier Excalidraw component was focussed by default on page load, you need to enable `autoFocus` prop to retain the same behaviour.
- Added prop `UIOptions.canvasActions.export.renderCustomUI` to support Custom UI rendering inside export dialog [#3666](https://github.com/excalidraw/excalidraw/pull/3666).
- Added prop `UIOptions.canvasActions.saveAsImage` to show/hide the **Save as image** button in the canvas actions. Defauls to `true` hence the **Save as Image** button is rendered [#3662](https://github.com/excalidraw/excalidraw/pull/3662).
- Export dialog can be customised with [`UiOptions.canvasActions.export`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#exportOpts) [#3658](https://github.com/excalidraw/excalidraw/pull/3658).
Also, [`UIOptions`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#UIOptions) is now memoized to avoid unnecessary rerenders.
#### BREAKING CHANGE
- `UIOptions.canvasActions.saveAsScene` is now renamed to `UiOptions.canvasActions.export.saveFileToDisk`. Defaults to `true` hence the **save file to disk** button is rendered inside the export dialog.
- `exportToBackend` is now renamed to `UIOptions.canvasActions.export.exportToBackend`. If this prop is not passed, the **shareable-link** button will not be rendered, same as before.
### Fixes
- Use excalidraw Id in elements so every element has unique id [#3696](https://github.com/excalidraw/excalidraw/pull/3696).
### Refactor
- #### BREAKING CHANGE
- Rename `UIOptions.canvasActions.saveScene` to `UIOptions.canvasActions.saveToActiveFile`[#3657](https://github.com/excalidraw/excalidraw/pull/3657).
- Removed `shouldAddWatermark: boolean` attribute from options for [export](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#export-utilities) APIs [#3639](https://github.com/excalidraw/excalidraw/pull/3639).
- Removed `appState.shouldAddWatermark` so in case you were passing `shouldAddWatermark` in [initialData.AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L42) it will not work anymore.
---
## 0.8.0 (2021-05-15)
## Excalidraw API
+2 -3
View File
@@ -153,7 +153,7 @@ To view the full example visit :point_down:
</details>
Since Excalidraw doesn't support server side rendering yet so you will have to make sure the component is rendered once host is mounted.
Since Excalidraw doesn't support server side rendering yet, you should render the component once the host is mounted.
```js
import { useState, useEffect } from "react";
@@ -161,7 +161,7 @@ export default function IndexPage() {
const [Comp, setComp] = useState(null);
useEffect(() => {
import("@excalidraw/excalidraw").then((comp) => setComp(comp.default));
});
}, []);
return <>{Comp && <Comp />}</>;
}
```
@@ -823,5 +823,4 @@ This function returns a svg with the exported elements.
| --- | --- | --- | --- |
| exportBackground | boolean | true | Indicates whether background should be exported |
| viewBackgroundColor | string | #fff | The default background color |
| shouldAddWatermark | boolean | false | Indicates whether watermark should be exported |
| exportWithDarkMode | boolean | false | Indicates whether to export with dark mode |

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