Compare commits

...

90 Commits

Author SHA1 Message Date
tk338g 232412d7bc Test fixup 2021-02-19 21:17:58 +03:00
tk338g 6a8680f500 Moved minimap rendering to offscreen canvas 2021-02-19 21:07:09 +03:00
tk338g 3b0aff0ac6 Fix minimap rerendering on scroll 2021-02-19 20:12:48 +03:00
tk338g 93d0a56bdb Check for NaN before applying styles 2021-02-19 20:12:48 +03:00
tk338g 0a3675e1b9 Update test snapshots 2021-02-19 20:12:48 +03:00
tk338g cf35caaf23 Toggle minimap with "M" key 2021-02-19 20:12:48 +03:00
tk338g 4e3bf7e8d2 Use one canvas for minimap and preserve viewport borders 2021-02-19 20:12:47 +03:00
tk338g 4c3544df4a Simple minimap implementation 2021-02-19 20:12:47 +03:00
Arun 74e82d0d7c fix: Hide scrollbars on mobile (#3044)
* Hide scrollbars on mobile

* Fix package build

* Revert "Fix package build"

This reverts commit 7bf4a0aac1.

* Make requested changes
2021-02-19 12:55:58 +01:00
Lipis 9dd2257932 chore: Consistent CSS variable names and general housekeeping of styles (#2947) 2021-02-16 20:22:18 +02:00
Aakansha Doshi 9c0f832a41 fix: show user state only when passed from host (#3050) 2021-02-16 15:08:27 +05:30
Aakansha Doshi 6cafb6bb90 feat: export restore API's from Excalidraw package (#3049) 2021-02-15 14:22:04 +01:00
David Luzar e6cd97c4f2 feat: adjust line-confirm-threshold based on zoom (#2884)
Co-authored-by: Lipis <lipiridis@gmail.com>
2021-02-14 14:43:23 +01:00
Panayiotis Lipiridis ba9b65b051 chore: npm audit fix 2021-02-14 15:18:17 +02:00
Aakansha Doshi 830fb64a25 fix: Support Excalidraw inside scrollable container (#3018)
* refactor: remove position fixed from excalidraw container, modal and stats

* remove unused css

* remove position fixed from toast and scroll to content

* Make excal interactable by fixing offsets and set popover as fixed since position needs to be calculate from viewport  top

* Assign 200px less than height of Excalidraw to the selected shapes actions o UI doesn't overflow

* update changelog, readme and package.json
2021-02-14 18:18:34 +05:30
dependabot[bot] 5b343a9d46 chore(deps-dev): bump @babel/preset-env from 7.12.13 to 7.12.16 in /src/packages/utils (#3030)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.12.13 to 7.12.16.
- [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.12.16/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-02-14 11:47:25 +02:00
Ivan Kurnosov f8beb305de refactor: Removed redundant import from App.tsx (#3040)
Given it's followed by qualified import - unqualified import looks redundant, unless I'm missing some tricky edge case.
2021-02-14 11:25:57 +02:00
dependabot[bot] 4b4eecbd27 chore(deps): bump react-scripts from 4.0.1 to 4.0.2 (#2979)
Bumps [react-scripts](https://github.com/facebook/create-react-app/tree/HEAD/packages/react-scripts) from 4.0.1 to 4.0.2.
- [Release notes](https://github.com/facebook/create-react-app/releases)
- [Changelog](https://github.com/facebook/create-react-app/blob/master/CHANGELOG.md)
- [Commits](https://github.com/facebook/create-react-app/commits/react-scripts@4.0.2/packages/react-scripts)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 09:23:05 +00:00
dependabot[bot] e8bd910b9b chore(deps-dev): bump @babel/preset-env from 7.12.13 to 7.12.16 in /src/packages/excalidraw (#3019)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 08:20:30 +00:00
dependabot[bot] a9a3e1bca5 chore(deps-dev): bump ts-loader from 8.0.15 to 8.0.17 in /src/packages/utils (#3027)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 08:16:28 +00:00
dependabot[bot] 2a922dd477 chore(deps-dev): bump @babel/preset-typescript from 7.12.13 to 7.12.16 in /src/packages/excalidraw (#3025)
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.12.13 to 7.12.16.
- [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.12.16/packages/babel-preset-typescript)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 08:12:33 +00:00
dependabot[bot] 07dab85ebf chore(deps-dev): bump sass-loader from 11.0.0 to 11.0.1 in /src/packages/excalidraw (#3020)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 08:07:01 +00:00
dependabot[bot] d2ce4a7523 chore(deps-dev): bump ts-loader from 8.0.15 to 8.0.17 in /src/packages/excalidraw (#3029)
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 8.0.15 to 8.0.17.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v8.0.15...v8.0.17)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 08:01:57 +00:00
dependabot[bot] dc73f3a9eb chore(deps-dev): bump @babel/core from 7.12.13 to 7.12.16 in /src/packages/excalidraw (#3031)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 07:59:28 +00:00
dependabot[bot] d100f38750 chore(deps-dev): bump @babel/preset-typescript from 7.12.13 to 7.12.16 in /src/packages/utils (#3024)
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.12.13 to 7.12.16.
- [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.12.16/packages/babel-preset-typescript)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 07:55:41 +00:00
dependabot[bot] 503500cc74 chore(deps-dev): bump @babel/plugin-transform-typescript from 7.12.13 to 7.12.16 in /src/packages/utils (#3028)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 07:46:40 +00:00
dependabot[bot] 1a828a43d9 chore(deps): bump @types/react-dom from 17.0.0 to 17.0.1 (#3035)
Bumps [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) from 17.0.0 to 17.0.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 07:45:50 +00:00
dependabot[bot] d88884466b chore(deps-dev): bump @babel/core from 7.12.13 to 7.12.16 in /src/packages/utils (#3021)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.12.13 to 7.12.16.
- [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.12.16/packages/babel-core)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 09:44:21 +02:00
dependabot[bot] d3d470ac3d chore(deps-dev): bump jest-canvas-mock from 2.3.0 to 2.3.1 (#3037)
Bumps [jest-canvas-mock](https://github.com/hustcc/jest-canvas-mock) from 2.3.0 to 2.3.1.
- [Release notes](https://github.com/hustcc/jest-canvas-mock/releases)
- [Changelog](https://github.com/hustcc/jest-canvas-mock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hustcc/jest-canvas-mock/commits)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 09:43:49 +02:00
dependabot[bot] 54df521a78 chore(deps-dev): bump mini-css-extract-plugin from 1.3.5 to 1.3.6 in /src/packages/excalidraw (#3022)
Bumps [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) from 1.3.5 to 1.3.6.
- [Release notes](https://github.com/webpack-contrib/mini-css-extract-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/mini-css-extract-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/mini-css-extract-plugin/compare/v1.3.5...v1.3.6)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 09:43:38 +02:00
dependabot[bot] c5557b5cc1 chore(deps): bump typescript from 4.1.3 to 4.1.5 (#3034)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.1.3 to 4.1.5.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.1.3...v4.1.5)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 09:43:27 +02:00
dependabot[bot] 51875fd627 chore(deps): bump firebase from 8.2.6 to 8.2.7 (#3038)
Bumps [firebase](https://github.com/firebase/firebase-js-sdk) from 8.2.6 to 8.2.7.
- [Release notes](https://github.com/firebase/firebase-js-sdk/releases)
- [Changelog](https://github.com/firebase/firebase-js-sdk/blob/master/CHANGELOG.md)
- [Commits](https://github.com/firebase/firebase-js-sdk/compare/firebase@8.2.6...firebase@8.2.7)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 09:42:53 +02:00
dependabot[bot] b2ba61bbcf chore(deps-dev): bump webpack from 5.21.1 to 5.21.2 in /src/packages/excalidraw (#3032)
Bumps [webpack](https://github.com/webpack/webpack) from 5.21.1 to 5.21.2.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.21.1...v5.21.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 09:42:36 +02:00
dependabot[bot] 3b7f62c9a0 chore(deps-dev): bump @babel/plugin-transform-typescript from 7.12.13 to 7.12.16 in /src/packages/excalidraw (#3033)
Bumps [@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-typescript) from 7.12.13 to 7.12.16.
- [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.12.16/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-02-14 09:42:26 +02:00
dependabot[bot] aeafb81479 chore(deps-dev): bump css-loader in /src/packages/excalidraw (#3026)
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 5.0.1 to 5.0.2.
- [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.0.1...v5.0.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 09:42:13 +02:00
dependabot[bot] dfe81bf6b2 chore(deps-dev): bump webpack from 5.21.1 to 5.21.2 in /src/packages/utils (#3023)
Bumps [webpack](https://github.com/webpack/webpack) from 5.21.1 to 5.21.2.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.21.1...v5.21.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 09:42:02 +02:00
dependabot[bot] 1d332d597a chore(deps): bump @types/react from 17.0.1 to 17.0.2 (#3036)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 17.0.1 to 17.0.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-14 09:41:09 +02:00
Aakansha Doshi b5fc8757a4 fix: allow to toggle between modes when view only mode to make UI consistent (#3009) 2021-02-12 10:40:40 +02:00
Aakansha Doshi ecbd5ba55d docs: update readme, changelog and release 0.3.0 🎉 (#3003) 2021-02-11 19:55:38 +05:30
Excalidraw Bot 6967d8c985 chore: Update translations from Crowdin (#3000) 2021-02-11 14:13:32 +02:00
David Luzar 4b253c7362 fix: refresh wysiwyg position on canvas resize (#3008) 2021-02-11 12:24:26 +01:00
Aakansha Doshi 4fdddb518a docs(readme): link to @excalidraw/excalidraw npm package to give more visibility (#3002) 2021-02-10 21:58:29 +05:30
Aakansha Doshi 0b2e4dd60b build(webpack): remove publicPath so __webpack_public_path__ can be used to host assets (#2835)
* build(webpack): remove publicPath so __webpack_public_path__ can be use to host assets

* update readme and changelog

* fix

* revert version so its released in v3
2021-02-10 21:49:16 +05:30
David Luzar f162512988 docs: link to specific sponsors (#2950) 2021-02-10 10:22:49 +02:00
Lipis 2f7154cdf2 chore: Use Sentence case for Live collaboration 2021-02-09 15:55:03 +02:00
Arun 5ab0ce5a33 feat: Add the ability to clear library (#2997)
* Add the ability to clear libraries

* Update 'libraries' to 'library'

* Update en.json
2021-02-09 11:19:04 +01:00
Excalidraw Bot 073f4032f3 chore: Update translations from Crowdin (#2986) 2021-02-09 11:06:23 +02:00
Jed Fox 73cba59d2d feat: Updates to Collaboration and RTL UX (#2994) 2021-02-08 21:43:51 +01:00
José dBruxelles 4085071347 docs: Fix typo (#2996) 2021-02-08 18:39:59 +02:00
José dBruxelles 8a63187d4f Update the lang attribute with the current lang. (#2995)
Currently, when changing the app language, the `lang` attribute still in `en`.
2021-02-08 12:38:38 +02:00
David Luzar 9c51ba6067 feat: show toast when saving to existing file (#2988) 2021-02-07 22:01:22 +01:00
Excalidraw Bot bf50c9cae7 chore: Update translations from Crowdin (#2946) 2021-02-07 12:33:37 +02:00
dependabot[bot] 1801048763 chore(deps-dev): bump @babel/plugin-transform-arrow-functions from 7.12.1 to 7.12.13 in /src/packages/excalidraw (#2961)
Bumps [@babel/plugin-transform-arrow-functions](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-arrow-functions) from 7.12.1 to 7.12.13.
- [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.12.13/packages/babel-plugin-transform-arrow-functions)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 11:25:00 +02:00
dependabot[bot] 414deea084 chore(deps-dev): bump @babel/preset-typescript from 7.12.7 to 7.12.13 in /src/packages/excalidraw (#2955)
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.12.7 to 7.12.13.
- [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.12.13/packages/babel-preset-typescript)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 09:15:47 +00:00
dependabot[bot] 979d28d5c6 chore(deps-dev): bump @babel/preset-env from 7.12.11 to 7.12.13 in /src/packages/utils (#2970)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 09:14:45 +00:00
dependabot[bot] 1f8b7e417f chore(deps-dev): bump @babel/plugin-transform-async-to-generator from 7.12.1 to 7.12.13 in /src/packages/excalidraw (#2957)
Bumps [@babel/plugin-transform-async-to-generator](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-async-to-generator) from 7.12.1 to 7.12.13.
- [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.12.13/packages/babel-plugin-transform-async-to-generator)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 09:05:16 +00:00
dependabot[bot] 8c968cd13e chore(deps-dev): bump @babel/preset-typescript from 7.12.7 to 7.12.13 in /src/packages/utils (#2964)
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.12.7 to 7.12.13.
- [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.12.13/packages/babel-preset-typescript)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 08:59:54 +00:00
dependabot[bot] f798000006 chore(deps-dev): bump @babel/plugin-transform-async-to-generator from 7.12.1 to 7.12.13 in /src/packages/utils (#2972)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 08:55:43 +00:00
dependabot[bot] 7ff3a71179 chore(deps-dev): bump @babel/preset-env from 7.12.11 to 7.12.13 in /src/packages/excalidraw (#2973)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.12.11 to 7.12.13.
- [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.12.13/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-02-07 08:48:42 +00:00
dependabot[bot] 6c0804d4c3 chore(deps-dev): bump @babel/core from 7.12.10 to 7.12.13 in /src/packages/excalidraw (#2952)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.12.10 to 7.12.13.
- [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.12.13/packages/babel-core)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 08:45:04 +00:00
dependabot[bot] ae8e7aca16 chore(deps-dev): bump ts-loader from 8.0.14 to 8.0.15 in /src/packages/excalidraw (#2969)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 08:41:10 +00:00
dependabot[bot] 842b185aa6 chore(deps-dev): bump @babel/plugin-transform-runtime from 7.12.10 to 7.12.15 in /src/packages/utils (#2968)
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.12.10 to 7.12.15.
- [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.12.15/packages/babel-plugin-transform-runtime)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 08:34:00 +00:00
dependabot[bot] f59387471e chore(deps): bump firebase from 8.2.5 to 8.2.6 (#2983)
Bumps [firebase](https://github.com/firebase/firebase-js-sdk) from 8.2.5 to 8.2.6.
- [Release notes](https://github.com/firebase/firebase-js-sdk/releases)
- [Changelog](https://github.com/firebase/firebase-js-sdk/blob/master/CHANGELOG.md)
- [Commits](https://github.com/firebase/firebase-js-sdk/compare/firebase@8.2.5...firebase@8.2.6)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 08:31:32 +00:00
dependabot[bot] 60eb709eb3 chore(deps-dev): bump @babel/plugin-transform-runtime from 7.12.10 to 7.12.15 in /src/packages/excalidraw (#2967)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 08:27:00 +00:00
dependabot[bot] 02539bbb89 chore(deps): bump @testing-library/react from 11.2.3 to 11.2.5 (#2975)
Bumps [@testing-library/react](https://github.com/testing-library/react-testing-library) from 11.2.3 to 11.2.5.
- [Release notes](https://github.com/testing-library/react-testing-library/releases)
- [Changelog](https://github.com/testing-library/react-testing-library/blob/master/CHANGELOG.md)
- [Commits](https://github.com/testing-library/react-testing-library/compare/v11.2.3...v11.2.5)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 10:19:28 +02:00
Lipis 77ae5d4605 chore(deps): bump @sentry/* from 6.0.3 to 6.1.0 (#2984) 2021-02-07 10:17:05 +02:00
dependabot[bot] bdd4f69bf6 chore(deps-dev): bump @babel/preset-react from 7.12.10 to 7.12.13 in /src/packages/excalidraw (#2963)
Bumps [@babel/preset-react](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-react) from 7.12.10 to 7.12.13.
- [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.12.13/packages/babel-preset-react)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 10:16:47 +02:00
dependabot[bot] 87ca829490 chore(deps-dev): bump webpack-cli from 4.4.0 to 4.5.0 in /src/packages/excalidraw (#2953)
Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 4.4.0 to 4.5.0.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.4.0...webpack-cli@4.5.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 10:15:42 +02:00
dependabot[bot] a31a7fd766 chore(deps-dev): bump @babel/plugin-transform-typescript from 7.12.1 to 7.12.13 in /src/packages/utils (#2954)
Bumps [@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-typescript) from 7.12.1 to 7.12.13.
- [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.12.13/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-02-07 08:12:48 +00:00
dependabot[bot] e70f02063f chore(deps-dev): bump sass-loader from 10.1.1 to 11.0.0 in /src/packages/excalidraw (#2971)
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 10.1.1 to 11.0.0.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v10.1.1...v11.0.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 08:10:24 +00:00
dependabot[bot] 769f727bd4 chore(deps-dev): bump @babel/plugin-transform-arrow-functions from 7.12.1 to 7.12.13 in /src/packages/utils (#2960)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 07:58:51 +00:00
dependabot[bot] bc994fcbe2 chore(deps-dev): bump @babel/core from 7.12.10 to 7.12.13 in /src/packages/utils (#2956)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.12.10 to 7.12.13.
- [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.12.13/packages/babel-core)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 09:52:55 +02:00
dependabot[bot] ac5e058222 chore(deps-dev): bump webpack from 5.19.0 to 5.21.1 in /src/packages/utils (#2966)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 07:52:22 +00:00
dependabot[bot] d61970cdac chore(deps): bump browser-fs-access from 0.13.0 to 0.13.1 (#2980)
Bumps [browser-fs-access](https://github.com/GoogleChromeLabs/browser-fs-access) from 0.13.0 to 0.13.1.
- [Release notes](https://github.com/GoogleChromeLabs/browser-fs-access/releases)
- [Commits](https://github.com/GoogleChromeLabs/browser-fs-access/commits)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 09:43:49 +02:00
dependabot[bot] 489d4b7469 chore(deps-dev): bump webpack from 5.19.0 to 5.21.1 in /src/packages/excalidraw (#2965)
Bumps [webpack](https://github.com/webpack/webpack) from 5.19.0 to 5.21.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.19.0...v5.21.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 09:43:26 +02:00
dependabot[bot] d88de08872 chore(deps-dev): bump webpack-cli from 4.4.0 to 4.5.0 in /src/packages/utils (#2958)
Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 4.4.0 to 4.5.0.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.4.0...webpack-cli@4.5.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 09:42:51 +02:00
dependabot[bot] 42882e2a93 chore(deps-dev): bump @babel/plugin-transform-typescript (#2959)
Bumps [@babel/plugin-transform-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-typescript) from 7.12.1 to 7.12.13.
- [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.12.13/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-02-07 09:42:37 +02:00
dependabot[bot] f6374e5bde chore(deps-dev): bump ts-loader from 8.0.14 to 8.0.15 in /src/packages/utils (#2962)
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 8.0.14 to 8.0.15.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v8.0.14...v8.0.15)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 09:42:20 +02:00
dependabot[bot] aac9d4e837 chore(deps): bump @types/react from 17.0.0 to 17.0.1 (#2978)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 17.0.0 to 17.0.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 09:42:12 +02:00
dependabot[bot] d9103b8b24 chore(deps-dev): bump firebase-tools from 9.2.2 to 9.3.0 (#2974)
Bumps [firebase-tools](https://github.com/firebase/firebase-tools) from 9.2.2 to 9.3.0.
- [Release notes](https://github.com/firebase/firebase-tools/releases)
- [Changelog](https://github.com/firebase/firebase-tools/blob/master/CHANGELOG.md)
- [Commits](https://github.com/firebase/firebase-tools/compare/v9.2.2...v9.3.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 09:42:02 +02:00
dependabot[bot] 8b56346011 chore(deps-dev): bump lint-staged from 10.5.3 to 10.5.4 (#2976)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 10.5.3 to 10.5.4.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v10.5.3...v10.5.4)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-07 09:41:52 +02:00
Aakansha Doshi e63a0ec5be feat: allow host to pass color for collaborators (#2943)
* feat: allow host to pass color for collaborators

* remove user prop as its not used anywhere

* update changelog and readme

* add pr link
2021-02-06 23:33:52 +05:30
Lipis 86222662f2 docs: Add open collective in readme (#2948)
Co-authored-by: David Luzar <luzar.david@gmail.com>
2021-02-06 18:12:35 +02:00
Aakansha Doshi 066560311b feat: add props zenModeEnabled and gridModeEnabled so host can control completely (#2901)
* feat: add props zenModeEnabled and gridModeEnabled so host can control completely

* dnt show exit zenmode button when prop present

* fix

* update when props change

* Add tests

* Add tests

* update changelog and readme

* update

* Update src/tests/excalidrawPackage.test.tsx

* Update src/packages/excalidraw/README.md

Co-authored-by: Lipis <lipiridis@gmail.com>

* Update src/packages/excalidraw/README.md

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

* Apply suggestions from code review

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

* fix specs

Co-authored-by: Lipis <lipiridis@gmail.com>
Co-authored-by: David Luzar <luzar.david@gmail.com>
2021-02-06 21:22:28 +05:30
Arun d6ca981f7a fix: Rename 'Grid mode' to 'Show grid' (#2944) 2021-02-05 23:50:53 +02:00
Excalidraw Bot f7f98d9dda chore: Update translations from Crowdin (#2930) 2021-02-05 20:07:33 +02:00
Thomas Steiner 1a67642fd1 chore: [Idle detection] Deal with users on systems that don't handle emoji (#2941)
* Deal with users on systems that don't handle emoji

* Leave no trailing space

* Move function to utils, and actually call it 🤣
Chapeau, TypeScript!

* Use grinning face instead of koala

* Tweak globalAlpha
2021-02-05 18:34:35 +01:00
David Luzar 6aa22bada8 fix: mobile toolbar tooltip regression (#2939) 2021-02-05 16:09:40 +01:00
David Luzar 00209ef9c3 fix: hide collaborator list on mobile if empty (#2938)
Co-authored-by: Lipis <lipiridis@gmail.com>
2021-02-05 15:45:44 +01:00
David Luzar b79ef0d428 fix: don't prompt on empty scenes (#2937) 2021-02-05 12:04:33 +01:00
106 changed files with 33643 additions and 3541 deletions
+1 -1
View File
@@ -2,6 +2,7 @@
"extends": ["prettier", "react-app"], "extends": ["prettier", "react-app"],
"plugins": ["prettier"], "plugins": ["prettier"],
"rules": { "rules": {
"@typescript-eslint/no-unused-vars": "warn",
"curly": "warn", "curly": "warn",
"dot-notation": "warn", "dot-notation": "warn",
"import/no-anonymous-default-export": "off", "import/no-anonymous-default-export": "off",
@@ -22,7 +23,6 @@
], ],
"no-unneeded-ternary": "warn", "no-unneeded-ternary": "warn",
"no-unused-expressions": "warn", "no-unused-expressions": "warn",
"no-unused-vars": "warn",
"no-useless-return": "warn", "no-useless-return": "warn",
"no-var": "warn", "no-var": "warn",
"object-shorthand": "warn", "object-shorthand": "warn",
+1 -2
View File
@@ -19,7 +19,7 @@
### Option 2 - CodeSandbox ### Option 2 - CodeSandbox
1. Go to https://codesandbox.io/s/github/excalidraw/excalidraw 1. Go to https://codesandbox.io/s/github/excalidraw/excalidraw
1. Connect your Github account 1. Connect your GitHub account
1. Go to Git tab on left side 1. Go to Git tab on left side
1. Tap on `Fork Sandbox` 1. Tap on `Fork Sandbox`
1. Write your code 1. Write your code
@@ -35,7 +35,6 @@ Make sure the title starts with a semantic prefix:
- **feat**: A new feature - **feat**: A new feature
- **fix**: A bug fix - **fix**: A bug fix
- **improvement**: An improvement to a current feature
- **docs**: Documentation only changes - **docs**: Documentation only changes
- **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) - **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
- **refactor**: A code change that neither fixes a bug nor adds a feature - **refactor**: A code change that neither fixes a bug nor adds a feature
+21 -8
View File
@@ -2,7 +2,7 @@
<a href="https://excalidraw.com"> <a href="https://excalidraw.com">
<img width="540" src="./public/og-image-sm.png" alt="Excalidraw logo: Sketch handrawn like diagrams." /> <img width="540" src="./public/og-image-sm.png" alt="Excalidraw logo: Sketch handrawn like diagrams." />
</a> </a>
<h3>Virtual whiteboard for sketching hand-drawn like diagrams.<br>Collaborative and end to end encrypted.</h3> <h3>Virtual whiteboard for sketching hand-drawn like diagrams.<br>Collaborative and end-to-end encrypted.</h3>
<p> <p>
<a href="https://twitter.com/Excalidraw"> <a href="https://twitter.com/Excalidraw">
<img alt="Follow Excalidraw on Twitter" src="https://img.shields.io/twitter/follow/excalidraw.svg?label=follow+excalidraw&style=social&logo=twitter"> <img alt="Follow Excalidraw on Twitter" src="https://img.shields.io/twitter/follow/excalidraw.svg?label=follow+excalidraw&style=social&logo=twitter">
@@ -11,6 +11,7 @@
<img src="https://badges.crowdin.net/excalidraw/localized.svg"> <img src="https://badges.crowdin.net/excalidraw/localized.svg">
</a> </a>
</p> </p>
<p>Ask questions or hang out on our <a target="_blank" href="https://discord.gg/UexuTaE">discord.gg/UexuTaE</a>.</p>
</div> </div>
## Try it now ## Try it now
@@ -19,6 +20,14 @@ Go to [excalidraw.com](https://excalidraw.com) to start sketching.
Read the latest news and updates on our [blog](https://blog.excalidraw.com). A good start is to see all the updates of [One Year of Excalidraw](https://blog.excalidraw.com/one-year-of-excalidraw/). Read the latest news and updates on our [blog](https://blog.excalidraw.com). A good start is to see all the updates of [One Year of Excalidraw](https://blog.excalidraw.com/one-year-of-excalidraw/).
## Supporting Excalidraw
If you like the project, you can become a sponsor at [Open Collective](https://opencollective.com/excalidraw).
[<img src="https://opencollective.com/excalidraw/tiers/sponsors/0/avatar.svg?avatarHeight=120">](https://opencollective.com/excalidraw/tiers/sponsors/0/website) [<img src="https://opencollective.com/excalidraw/tiers/sponsors/1/avatar.svg?avatarHeight=120">](https://opencollective.com/excalidraw/tiers/sponsors/1/website) [<img src="https://opencollective.com/excalidraw/tiers/sponsors/2/avatar.svg?avatarHeight=120">](https://opencollective.com/excalidraw/tiers/sponsors/2/website) [<img src="https://opencollective.com/excalidraw/tiers/sponsors/3/avatar.svg?avatarHeight=120">](https://opencollective.com/excalidraw/tiers/sponsors/3/website) [<img src="https://opencollective.com/excalidraw/tiers/sponsors/4/avatar.svg?avatarHeight=120">](https://opencollective.com/excalidraw/tiers/sponsors/4/website) [<img src="https://opencollective.com/excalidraw/tiers/sponsors/5/avatar.svg?avatarHeight=120">](https://opencollective.com/excalidraw/tiers/sponsors/5/website) [<img src="https://opencollective.com/excalidraw/tiers/sponsors/6/avatar.svg?avatarHeight=120">](https://opencollective.com/excalidraw/tiers/sponsors/6/website) [<img src="https://opencollective.com/excalidraw/tiers/sponsors/7/avatar.svg?avatarHeight=120">](https://opencollective.com/excalidraw/tiers/sponsors/7/website) [<img src="https://opencollective.com/excalidraw/tiers/sponsors/8/avatar.svg?avatarHeight=120">](https://opencollective.com/excalidraw/tiers/sponsors/8/website) [<img src="https://opencollective.com/excalidraw/tiers/sponsors/9/avatar.svg?avatarHeight=120">](https://opencollective.com/excalidraw/tiers/sponsors/9/website) [<img src="https://opencollective.com/excalidraw/tiers/sponsors/10/avatar.svg?avatarHeight=120">](https://opencollective.com/excalidraw/tiers/sponsors/10/website)
<a href="https://opencollective.com/excalidraw#category-CONTRIBUTE" target="_blank"><img src="https://opencollective.com/excalidraw/tiers/backers.svg?avatarHeight=32"/></a>
## Documentation ## Documentation
### Shortcuts ### Shortcuts
@@ -41,7 +50,7 @@ Translations will be available on the app if they exceed a certain threshold of
### Create a collaboration session manually ### Create a collaboration session manually
In order to create a session manually you just need to generate a link of this form: In order to create a session manually, you just need to generate a link of this form:
``` ```
https://excalidraw.com/#room=[0-9a-f]{20},[a-zA-Z0-9_-]{22} https://excalidraw.com/#room=[0-9a-f]{20},[a-zA-Z0-9_-]{22}
@@ -61,12 +70,16 @@ The second set of digits is the encryption key. The Excalidraw server doesnt
Find a growing list of libraries containing assets for your drawings at [libraries.excalidraw.com](https://libraries.excalidraw.com). Find a growing list of libraries containing assets for your drawings at [libraries.excalidraw.com](https://libraries.excalidraw.com).
## Developement ## Embedding Excalidraw in your App?
Try out [`@excalidraw/excalidraw`](https://www.npmjs.com/package/@excalidraw/excalidraw). This package allows you to easily embed Excalidraw as a React component into your apps.
## Development
### Code Sandbox ### Code Sandbox
- Go to https://codesandbox.io/s/github/excalidraw/excalidraw - Go to https://codesandbox.io/s/github/excalidraw/excalidraw
- You may need to sign in with Github and reload the page - You may need to sign in with GitHub and reload the page
- You can start coding instantly, and even send PRs from there! - You can start coding instantly, and even send PRs from there!
### Local Installation ### Local Installation
@@ -92,15 +105,15 @@ git clone https://github.com/excalidraw/excalidraw.git
#### Docker Compose #### Docker Compose
You can use docker-compose to work on excalidraw locally if you don't want to setup a Node.js env. You can use docker-compose to work on Excalidraw locally if you don't want to setup a Node.js env.
```sh ```sh
docker-compose up --build -d docker-compose up --build -d
``` ```
### Self hosting ### Self-hosting
We publish a Docker image with the Excalidraw client at [excalidraw/excalidraw](https://hub.docker.com/r/excalidraw/excalidraw). You can use it to self host your own client under your own domain, on Kubernetes, AWS ECS, etc. We publish a Docker image with the Excalidraw client at [excalidraw/excalidraw](https://hub.docker.com/r/excalidraw/excalidraw). You can use it to self-host your own client under your own domain, on Kubernetes, AWS ECS, etc.
```sh ```sh
docker build -t excalidraw/excalidraw . docker build -t excalidraw/excalidraw .
@@ -111,7 +124,7 @@ The Docker image is free of analytics and other tracking libraries.
**At the moment, self-hosting your own instance doesn't support sharing or collaboration features.** **At the moment, self-hosting your own instance doesn't support sharing or collaboration features.**
We are working towards providing a full-fledged solution for self hosting your own Excalidraw. We are working towards providing a full-fledged solution for self-hosting your own Excalidraw.
## Contributing ## Contributing
+29588 -1513
View File
File diff suppressed because it is too large Load Diff
+18 -13
View File
@@ -19,17 +19,17 @@
] ]
}, },
"dependencies": { "dependencies": {
"@sentry/browser": "6.0.3", "@sentry/browser": "6.1.0",
"@sentry/integrations": "6.0.3", "@sentry/integrations": "6.1.0",
"@testing-library/jest-dom": "5.11.9", "@testing-library/jest-dom": "5.11.9",
"@testing-library/react": "11.2.3", "@testing-library/react": "11.2.5",
"@types/jest": "26.0.20", "@types/jest": "26.0.20",
"@types/react": "17.0.0", "@types/react": "17.0.2",
"@types/react-dom": "17.0.0", "@types/react-dom": "17.0.1",
"@types/socket.io-client": "1.4.35", "@types/socket.io-client": "1.4.35",
"browser-fs-access": "0.13.0", "browser-fs-access": "0.13.1",
"clsx": "1.1.1", "clsx": "1.1.1",
"firebase": "8.2.5", "firebase": "8.2.7",
"i18next-browser-languagedetector": "6.0.1", "i18next-browser-languagedetector": "6.0.1",
"lodash.throttle": "4.1.1", "lodash.throttle": "4.1.1",
"nanoid": "3.1.20", "nanoid": "3.1.20",
@@ -43,23 +43,25 @@
"pwacompat": "2.0.17", "pwacompat": "2.0.17",
"react": "17.0.1", "react": "17.0.1",
"react-dom": "17.0.1", "react-dom": "17.0.1",
"react-scripts": "4.0.1", "react-scripts": "4.0.2",
"roughjs": "4.3.1", "roughjs": "4.3.1",
"socket.io-client": "2.3.1", "socket.io-client": "2.3.1",
"typescript": "4.1.3" "typescript": "4.1.5"
}, },
"devDependencies": { "devDependencies": {
"@types/lodash.throttle": "4.1.6", "@types/lodash.throttle": "4.1.6",
"@types/pako": "1.0.1", "@types/pako": "1.0.1",
"@types/resize-observer-browser": "0.1.5",
"eslint-config-prettier": "7.2.0", "eslint-config-prettier": "7.2.0",
"eslint-plugin-prettier": "3.3.1", "eslint-plugin-prettier": "3.3.1",
"firebase-tools": "9.2.2", "firebase-tools": "9.3.0",
"husky": "4.3.8", "husky": "4.3.8",
"jest-canvas-mock": "2.3.0", "jest-canvas-mock": "2.3.1",
"lint-staged": "10.5.3", "lint-staged": "10.5.4",
"pepjs": "0.5.3", "pepjs": "0.5.3",
"prettier": "2.2.1", "prettier": "2.2.1",
"rewire": "5.0.0" "rewire": "5.0.0",
"worker-loader": "3.0.8"
}, },
"engines": { "engines": {
"node": ">=12.0.0" "node": ">=12.0.0"
@@ -74,6 +76,9 @@
"transformIgnorePatterns": [ "transformIgnorePatterns": [
"node_modules/(?!(roughjs|points-on-curve|path-data-parser|points-on-path|browser-fs-access)/)" "node_modules/(?!(roughjs|points-on-curve|path-data-parser|points-on-path|browser-fs-access)/)"
], ],
"moduleNameMapper": {
"^worker-loader!.+": "<rootDir>/src/__mocks__/worker-mock.js"
},
"resetMocks": false "resetMocks": false
}, },
"name": "excalidraw", "name": "excalidraw",
+4
View File
@@ -0,0 +1,4 @@
module.exports = class {
postMessage() {}
terminate() {}
};
+16 -1
View File
@@ -96,9 +96,24 @@ export const actionChangeShouldAddWatermark = register({
export const actionSaveScene = register({ export const actionSaveScene = register({
name: "saveScene", name: "saveScene",
perform: async (elements, appState, value) => { perform: async (elements, appState, value) => {
const fileHandleExists = !!appState.fileHandle;
try { try {
const { fileHandle } = await saveAsJSON(elements, appState); const { fileHandle } = await saveAsJSON(elements, appState);
return { commitToHistory: false, appState: { ...appState, fileHandle } }; return {
commitToHistory: false,
appState: {
...appState,
fileHandle,
toastMessage: fileHandleExists
? fileHandle.name
? t("toast.fileSavedToFilename").replace(
"{filename}",
`"${fileHandle.name}"`,
)
: t("toast.fileSaved")
: null,
},
};
} catch (error) { } catch (error) {
if (error?.name !== "AbortError") { if (error?.name !== "AbortError") {
console.error(error); console.error(error);
+1 -1
View File
@@ -83,7 +83,7 @@ export const actionFinalize = register({
// If the multi point line closes the loop, // If the multi point line closes the loop,
// set the last point to first point. // set the last point to first point.
// This ensures that loop remains closed at different scales. // This ensures that loop remains closed at different scales.
const isLoop = isPathALoop(multiPointElement.points); const isLoop = isPathALoop(multiPointElement.points, appState.zoom.value);
if ( if (
multiPointElement.type === "line" || multiPointElement.type === "line" ||
multiPointElement.type === "draw" multiPointElement.type === "draw"
+19
View File
@@ -7,6 +7,7 @@ import { register } from "./register";
import { allowFullScreen, exitFullScreen, isFullScreen } from "../utils"; import { allowFullScreen, exitFullScreen, isFullScreen } from "../utils";
import { CODES, KEYS } from "../keys"; import { CODES, KEYS } from "../keys";
import { HelpIcon } from "../components/HelpIcon"; import { HelpIcon } from "../components/HelpIcon";
import { MiniMap } from "../components/MiniMap";
export const actionToggleCanvasMenu = register({ export const actionToggleCanvasMenu = register({
name: "toggleCanvasMenu", name: "toggleCanvasMenu",
@@ -84,3 +85,21 @@ export const actionShortcuts = register({
), ),
keyTest: (event) => event.key === KEYS.QUESTION_MARK, keyTest: (event) => event.key === KEYS.QUESTION_MARK,
}); });
export const actionMinimap = register({
name: "toggleMinimap",
perform: (_elements, appState) => {
return {
appState: {
...appState,
isMinimapEnabled: !appState.isMinimapEnabled,
},
commitToHistory: false,
};
},
PanelComponent: ({ appState, elements }) =>
appState.isMinimapEnabled ? (
<MiniMap appState={appState} elements={elements} />
) : null,
keyTest: (event) => event.key === KEYS.M,
});
+1 -1
View File
@@ -42,7 +42,7 @@ export const actionGoToCollaborator = register({
return null; return null;
} }
const { background, stroke } = getClientColors(clientId); const { background, stroke } = getClientColors(clientId, appState);
const shortName = getClientInitials(collaborator.username); const shortName = getClientInitials(collaborator.username);
return ( return (
+1 -1
View File
@@ -17,6 +17,6 @@ export const actionToggleGridMode = register({
}; };
}, },
checked: (appState: AppState) => appState.gridSize !== null, checked: (appState: AppState) => appState.gridSize !== null,
contextItemLabel: "labels.gridMode", contextItemLabel: "labels.showGrid",
keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.code === CODES.QUOTE, keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.code === CODES.QUOTE,
}); });
+1
View File
@@ -44,6 +44,7 @@ export {
actionToggleEditMenu, actionToggleEditMenu,
actionFullScreen, actionFullScreen,
actionShortcuts, actionShortcuts,
actionMinimap,
} from "./actionMenu"; } from "./actionMenu";
export { actionGroup, actionUngroup } from "./actionGroup"; export { actionGroup, actionUngroup } from "./actionGroup";
+2 -1
View File
@@ -8,6 +8,7 @@ import {
} from "./types"; } from "./types";
import { ExcalidrawElement } from "../element/types"; import { ExcalidrawElement } from "../element/types";
import { AppState, ExcalidrawProps } from "../types"; import { AppState, ExcalidrawProps } from "../types";
import { MODES } from "../constants";
// This is the <App> component, but for now we don't care about anything but its // This is the <App> component, but for now we don't care about anything but its
// `canvas` state. // `canvas` state.
@@ -68,7 +69,7 @@ export class ActionManager implements ActionsManagerInterface {
} }
const { viewModeEnabled } = this.getAppState(); const { viewModeEnabled } = this.getAppState();
if (viewModeEnabled) { if (viewModeEnabled) {
if (data[0].name !== "viewMode") { if (!Object.values(MODES).includes(data[0].name)) {
return false; return false;
} }
} }
+2 -1
View File
@@ -85,7 +85,8 @@ export type ActionName =
| "alignHorizontallyCentered" | "alignHorizontallyCentered"
| "distributeHorizontally" | "distributeHorizontally"
| "distributeVertically" | "distributeVertically"
| "viewMode"; | "viewMode"
| "toggleMinimap";
export interface Action { export interface Action {
name: ActionName; name: ActionName;
+4 -2
View File
@@ -42,7 +42,7 @@ export const getDefaultAppState = (): Omit<
exportEmbedScene: false, exportEmbedScene: false,
fileHandle: null, fileHandle: null,
gridSize: null, gridSize: null,
height: window.innerHeight, height: globalThis.innerHeight,
isBindingEnabled: true, isBindingEnabled: true,
isLibraryOpen: false, isLibraryOpen: false,
isLoading: false, isLoading: false,
@@ -69,10 +69,11 @@ export const getDefaultAppState = (): Omit<
suggestedBindings: [], suggestedBindings: [],
toastMessage: null, toastMessage: null,
viewBackgroundColor: oc.white, viewBackgroundColor: oc.white,
width: window.innerWidth, width: globalThis.innerWidth,
zenModeEnabled: false, zenModeEnabled: false,
zoom: { value: 1 as NormalizedZoomValue, translation: { x: 0, y: 0 } }, zoom: { value: 1 as NormalizedZoomValue, translation: { x: 0, y: 0 } },
viewModeEnabled: false, viewModeEnabled: false,
isMinimapEnabled: false,
}; };
}; };
@@ -153,6 +154,7 @@ const APP_STATE_STORAGE_CONF = (<
zenModeEnabled: { browser: true, export: false }, zenModeEnabled: { browser: true, export: false },
zoom: { browser: true, export: false }, zoom: { browser: true, export: false },
viewModeEnabled: { browser: false, export: false }, viewModeEnabled: { browser: false, export: false },
isMinimapEnabled: { browser: true, export: false },
}); });
const _clearAppStateForStorage = <ExportType extends "export" | "browser">( const _clearAppStateForStorage = <ExportType extends "export" | "browser">(
+8 -1
View File
@@ -1,6 +1,13 @@
import colors from "./colors"; import colors from "./colors";
import { AppState } from "./types";
export const getClientColors = (clientId: string) => { export const getClientColors = (clientId: string, appState: AppState) => {
if (appState?.collaborators) {
const currentUser = appState.collaborators.get(clientId);
if (currentUser?.color) {
return currentUser.color;
}
}
// Naive way of getting an integer out of the clientId // Naive way of getting an integer out of the clientId
const sum = clientId.split("").reduce((a, str) => a + str.charCodeAt(0), 0); const sum = clientId.split("").reduce((a, str) => a + str.charCodeAt(0), 0);
+52 -10
View File
@@ -4,7 +4,6 @@ import { RoughCanvas } from "roughjs/bin/canvas";
import rough from "roughjs/bin/rough"; import rough from "roughjs/bin/rough";
import clsx from "clsx"; import clsx from "clsx";
import "../actions";
import { import {
actionAddToLibrary, actionAddToLibrary,
actionBringForward, actionBringForward,
@@ -48,9 +47,11 @@ import {
ELEMENT_TRANSLATE_AMOUNT, ELEMENT_TRANSLATE_AMOUNT,
ENV, ENV,
EVENT, EVENT,
GRID_SIZE,
LINE_CONFIRM_THRESHOLD, LINE_CONFIRM_THRESHOLD,
MIME_TYPES, MIME_TYPES,
POINTER_BUTTON, POINTER_BUTTON,
SCROLL_TIMEOUT,
TAP_TWICE_TIMEOUT, TAP_TWICE_TIMEOUT,
TEXT_TO_CENTER_SNAP_THRESHOLD, TEXT_TO_CENTER_SNAP_THRESHOLD,
TOUCH_CTX_MENU_TIMEOUT, TOUCH_CTX_MENU_TIMEOUT,
@@ -299,6 +300,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
offsetTop, offsetTop,
excalidrawRef, excalidrawRef,
viewModeEnabled = false, viewModeEnabled = false,
zenModeEnabled = false,
gridModeEnabled = false,
} = props; } = props;
this.state = { this.state = {
...defaultAppState, ...defaultAppState,
@@ -307,6 +310,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
height, height,
...this.getCanvasOffsets({ offsetLeft, offsetTop }), ...this.getCanvasOffsets({ offsetLeft, offsetTop }),
viewModeEnabled, viewModeEnabled,
zenModeEnabled,
gridSize: gridModeEnabled ? GRID_SIZE : null,
}; };
if (excalidrawRef) { if (excalidrawRef) {
const readyPromise = const readyPromise =
@@ -453,6 +458,9 @@ class App extends React.Component<ExcalidrawProps, AppState> {
onExportToBackend={onExportToBackend} onExportToBackend={onExportToBackend}
renderCustomFooter={renderFooter} renderCustomFooter={renderFooter}
viewModeEnabled={viewModeEnabled} viewModeEnabled={viewModeEnabled}
showExitZenModeBtn={
typeof this.props?.zenModeEnabled === "undefined" && zenModeEnabled
}
/> />
<div className="excalidraw-textEditorContainer" /> <div className="excalidraw-textEditorContainer" />
{this.state.showStats && ( {this.state.showStats && (
@@ -511,11 +519,21 @@ class App extends React.Component<ExcalidrawProps, AppState> {
} }
let viewModeEnabled = actionResult?.appState?.viewModeEnabled || false; let viewModeEnabled = actionResult?.appState?.viewModeEnabled || false;
let zenModeEnabled = actionResult?.appState?.zenModeEnabled || false;
let gridSize = actionResult?.appState?.gridSize || null;
if (typeof this.props.viewModeEnabled !== "undefined") { if (typeof this.props.viewModeEnabled !== "undefined") {
viewModeEnabled = this.props.viewModeEnabled; viewModeEnabled = this.props.viewModeEnabled;
} }
if (typeof this.props.zenModeEnabled !== "undefined") {
zenModeEnabled = this.props.zenModeEnabled;
}
if (typeof this.props.gridModeEnabled !== "undefined") {
gridSize = this.props.gridModeEnabled ? GRID_SIZE : null;
}
this.setState( this.setState(
(state) => ({ (state) => ({
...actionResult.appState, ...actionResult.appState,
@@ -526,6 +544,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
offsetTop: state.offsetTop, offsetTop: state.offsetTop,
offsetLeft: state.offsetLeft, offsetLeft: state.offsetLeft,
viewModeEnabled, viewModeEnabled,
zenModeEnabled,
gridSize,
}), }),
() => { () => {
if (actionResult.syncHistory) { if (actionResult.syncHistory) {
@@ -806,6 +826,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
document.addEventListener(EVENT.PASTE, this.pasteFromClipboard); document.addEventListener(EVENT.PASTE, this.pasteFromClipboard);
document.addEventListener(EVENT.CUT, this.onCut); document.addEventListener(EVENT.CUT, this.onCut);
document.addEventListener(EVENT.SCROLL, this.onScroll);
window.addEventListener(EVENT.RESIZE, this.onResize, false); window.addEventListener(EVENT.RESIZE, this.onResize, false);
window.addEventListener(EVENT.UNLOAD, this.onUnload, false); window.addEventListener(EVENT.UNLOAD, this.onUnload, false);
@@ -845,6 +866,15 @@ class App extends React.Component<ExcalidrawProps, AppState> {
this.addEventListeners(); this.addEventListeners();
} }
if (prevProps.zenModeEnabled !== this.props.zenModeEnabled) {
this.setState({ zenModeEnabled: !!this.props.zenModeEnabled });
}
if (prevProps.gridModeEnabled !== this.props.gridModeEnabled) {
this.setState({
gridSize: this.props.gridModeEnabled ? GRID_SIZE : null,
});
}
document document
.querySelector(".excalidraw") .querySelector(".excalidraw")
?.classList.toggle("Appearance_dark", this.state.appearance === "dark"); ?.classList.toggle("Appearance_dark", this.state.appearance === "dark");
@@ -942,6 +972,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
}, },
{ {
renderOptimizations: true, renderOptimizations: true,
renderScrollbars: !isMobile(),
}, },
); );
if (scrollBars) { if (scrollBars) {
@@ -970,6 +1001,10 @@ class App extends React.Component<ExcalidrawProps, AppState> {
} }
} }
private onScroll = debounce(() => {
this.setState({ ...this.getCanvasOffsets() });
}, SCROLL_TIMEOUT);
// Copy/paste // Copy/paste
private onCut = withBatchedUpdates((event: ClipboardEvent) => { private onCut = withBatchedUpdates((event: ClipboardEvent) => {
@@ -1522,6 +1557,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
textWysiwyg({ textWysiwyg({
id: element.id, id: element.id,
appState: this.state, appState: this.state,
canvas: this.canvas,
getViewportCoords: (x, y) => { getViewportCoords: (x, y) => {
const { x: viewportX, y: viewportY } = sceneCoordsToViewportCoords( const { x: viewportX, y: viewportY } = sceneCoordsToViewportCoords(
{ {
@@ -1928,7 +1964,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
points: points.slice(0, -1), points: points.slice(0, -1),
}); });
} else { } else {
if (isPathALoop(points)) { if (isPathALoop(points, this.state.zoom.value)) {
document.documentElement.style.cursor = CURSOR_TYPE.POINTER; document.documentElement.style.cursor = CURSOR_TYPE.POINTER;
} }
// update last uncommitted point // update last uncommitted point
@@ -2600,7 +2636,10 @@ class App extends React.Component<ExcalidrawProps, AppState> {
const { multiElement } = this.state; const { multiElement } = this.state;
// finalize if completing a loop // finalize if completing a loop
if (multiElement.type === "line" && isPathALoop(multiElement.points)) { if (
multiElement.type === "line" &&
isPathALoop(multiElement.points, this.state.zoom.value)
) {
mutateElement(multiElement, { mutateElement(multiElement, {
lastCommittedPoint: lastCommittedPoint:
multiElement.points[multiElement.points.length - 1], multiElement.points[multiElement.points.length - 1],
@@ -3671,15 +3710,16 @@ class App extends React.Component<ExcalidrawProps, AppState> {
options.push(actionCopyAsSvg); options.push(actionCopyAsSvg);
} }
if (!element) { if (!element) {
const viewModeOptions: ContextMenuOption[] = [ const viewModeOptions = [
...options, ...options,
typeof this.props.gridModeEnabled === "undefined" &&
actionToggleGridMode,
typeof this.props.zenModeEnabled === "undefined" && actionToggleZenMode,
typeof this.props.viewModeEnabled === "undefined" &&
actionToggleViewMode,
actionToggleStats, actionToggleStats,
]; ];
if (typeof this.props.viewModeEnabled === "undefined") {
viewModeOptions.push(actionToggleViewMode);
}
ContextMenu.push({ ContextMenu.push({
options: viewModeOptions, options: viewModeOptions,
top: clientY, top: clientY,
@@ -3717,8 +3757,10 @@ class App extends React.Component<ExcalidrawProps, AppState> {
separator, separator,
actionSelectAll, actionSelectAll,
separator, separator,
actionToggleGridMode, typeof this.props.gridModeEnabled === "undefined" &&
actionToggleZenMode, actionToggleGridMode,
typeof this.props.zenModeEnabled === "undefined" &&
actionToggleZenMode,
typeof this.props.viewModeEnabled === "undefined" && typeof this.props.viewModeEnabled === "undefined" &&
actionToggleViewMode, actionToggleViewMode,
actionToggleStats, actionToggleStats,
+3 -2
View File
@@ -2,9 +2,10 @@
.excalidraw { .excalidraw {
.CollabButton.is-collaborating { .CollabButton.is-collaborating {
background-color: var(--button-special-active-background-color); background-color: var(--button-special-active-bg-color);
.ToolIcon__icon svg { .ToolIcon__icon svg,
.ToolIcon__label {
color: var(--icon-green-fill-color); color: var(--icon-green-fill-color);
} }
} }
+2 -2
View File
@@ -25,8 +25,8 @@ const CollabButton = ({
onClick={onClick} onClick={onClick}
icon={users} icon={users}
type="button" type="button"
title={t("buttons.roomDialog")} title={t("labels.liveCollaboration")}
aria-label={t("buttons.roomDialog")} aria-label={t("labels.liveCollaboration")}
showAriaLabel={useIsMobile()} showAriaLabel={useIsMobile()}
> >
{collaboratorCount > 0 && ( {collaboratorCount > 0 && (
+24 -24
View File
@@ -2,9 +2,9 @@
.excalidraw { .excalidraw {
.color-picker { .color-picker {
background: var(--popup-background-color); background: var(--popup-bg-color);
border: 0px solid transparentize($oc-white, 0.75); border: 0 solid transparentize($oc-white, 0.75);
box-shadow: transparentize($oc-black, 0.75) 0px 1px 4px; box-shadow: transparentize($oc-black, 0.75) 0 1px 4px;
border-radius: 4px; border-radius: 4px;
position: absolute; position: absolute;
@@ -24,11 +24,11 @@
} }
.color-picker-triangle { .color-picker-triangle {
width: 0px; width: 0;
height: 0px; height: 0;
border-style: solid; border-style: solid;
border-width: 0px 9px 10px; border-width: 0 9px 10px;
border-color: transparent transparent var(--popup-background-color); border-color: transparent transparent var(--popup-bg-color);
position: absolute; position: absolute;
top: -10px; top: -10px;
@@ -84,12 +84,12 @@
.color-picker-transparent { .color-picker-transparent {
border-radius: 4px; border-radius: 4px;
box-shadow: transparentize($oc-black, 0.9) 0px 0px 0px 1px inset; box-shadow: transparentize($oc-black, 0.9) 0 0 0 1px inset;
position: absolute; position: absolute;
top: 0px; top: 0;
right: 0px; right: 0;
bottom: 0px; bottom: 0;
left: 0px; left: 0;
} }
.color-picker-transparent, .color-picker-transparent,
@@ -104,11 +104,11 @@
width: 1.875rem; width: 1.875rem;
:root[dir="ltr"] & { :root[dir="ltr"] & {
border-radius: 4px 0px 0px 4px; border-radius: 4px 0 0 4px;
} }
:root[dir="rtl"] & { :root[dir="rtl"] & {
border-radius: 0px 4px 4px 0px; border-radius: 0 4px 4px 0;
} }
color: var(--input-label-color); color: var(--input-label-color);
@@ -144,7 +144,7 @@
} }
.color-input-container:focus-within .color-picker-hash::after { .color-input-container:focus-within .color-picker-hash::after {
background: var(--input-background-color); background: var(--input-bg-color);
:root[dir="ltr"] & { :root[dir="ltr"] & {
right: -2px; right: -2px;
@@ -163,19 +163,19 @@
width: 12ch; /* length of `transparent` + 1 */ width: 12ch; /* length of `transparent` + 1 */
margin: 0; margin: 0;
font-size: 1rem; font-size: 1rem;
background-color: var(--input-background-color); background-color: var(--input-bg-color);
color: var(--text-color-primary); color: var(--text-primary-color);
border: 0px; border: 0;
outline: none; outline: none;
height: 1.75em; height: 1.75em;
box-shadow: var(--input-border-color) 0px 0px 0px 1px inset; box-shadow: var(--input-border-color) 0 0 0 1px inset;
:root[dir="ltr"] & { :root[dir="ltr"] & {
border-radius: 0px 4px 4px 0px; border-radius: 0 4px 4px 0;
} }
:root[dir="rtl"] & { :root[dir="rtl"] & {
border-radius: 4px 0px 0px 4px; border-radius: 4px 0 0 4px;
} }
float: left; float: left;
@@ -228,7 +228,7 @@
} }
.color-picker-type-elementBackground .color-picker-keybinding { .color-picker-type-elementBackground .color-picker-keybinding {
color: #fff; color: $oc-white;
} }
.color-picker-swatch[aria-label="transparent"] .color-picker-keybinding { .color-picker-swatch[aria-label="transparent"] .color-picker-keybinding {
@@ -241,10 +241,10 @@
&.Appearance_dark { &.Appearance_dark {
.color-picker-type-elementBackground .color-picker-keybinding { .color-picker-type-elementBackground .color-picker-keybinding {
color: #000; color: $oc-black;
} }
.color-picker-swatch[aria-label="transparent"] .color-picker-keybinding { .color-picker-swatch[aria-label="transparent"] .color-picker-keybinding {
color: #000; color: $oc-black;
} }
} }
} }
+4 -4
View File
@@ -4,13 +4,13 @@
.context-menu { .context-menu {
position: relative; position: relative;
border-radius: 4px; border-radius: 4px;
box-shadow: 0px 3px 10px transparentize($oc-black, 0.8); box-shadow: 0 3px 10px transparentize($oc-black, 0.8);
padding: 0; padding: 0;
list-style: none; list-style: none;
user-select: none; user-select: none;
margin: -0.25rem 0 0 0.125rem; margin: -0.25rem 0 0 0.125rem;
padding: 0.5rem 0; padding: 0.5rem 0;
background-color: var(--popup-secondary-background-color); background-color: var(--popup-secondary-bg-color);
border: 1px solid var(--button-gray-3); border: 1px solid var(--button-gray-3);
cursor: default; cursor: default;
} }
@@ -61,12 +61,12 @@
} }
.context-menu-option:hover { .context-menu-option:hover {
color: var(--popup-background-color); color: var(--popup-bg-color);
background-color: var(--select-highlight-color); background-color: var(--select-highlight-color);
&.dangerous { &.dangerous {
.context-menu-option__label { .context-menu-option__label {
color: var(--popup-background-color); color: var(--popup-bg-color);
} }
background-color: $oc-red-6; background-color: $oc-red-6;
} }
+1 -1
View File
@@ -45,7 +45,7 @@
position: sticky; position: sticky;
top: 0; top: 0;
padding: calc(var(--space-factor) * 2); padding: calc(var(--space-factor) * 2);
background: var(--bg-color-island); background: var(--island-bg-color);
font-size: 1.25em; font-size: 1.25em;
box-sizing: border-box; box-sizing: border-box;
+4
View File
@@ -101,6 +101,10 @@ const ExportModal = ({
shouldAddWatermark, shouldAddWatermark,
}); });
if (canvas instanceof OffscreenCanvas) {
return;
}
// if converting to blob fails, there's some problem that will // if converting to blob fails, there's some problem that will
// likely prevent preview and export (e.g. canvas too big) // likely prevent preview and export (e.g. canvas too big)
canvasToBlob(canvas) canvasToBlob(canvas)
+1 -1
View File
@@ -224,7 +224,7 @@ export const HelpDialog = ({ onClose }: { onClose?: () => void }) => {
shortcuts={[getShortcutKey("Alt+Z")]} shortcuts={[getShortcutKey("Alt+Z")]}
/> />
<Shortcut <Shortcut
label={t("labels.gridMode")} label={t("labels.showGrid")}
shortcuts={[getShortcutKey("CtrlOrCmd+'")]} shortcuts={[getShortcutKey("CtrlOrCmd+'")]}
/> />
<Shortcut <Shortcut
+1 -1
View File
@@ -26,7 +26,7 @@ $wide-viewport-width: 1000px;
> span { > span {
padding: 0.2rem 0.4rem; padding: 0.2rem 0.4rem;
background-color: var(--overlay-background-color); background-color: var(--overlay-bg-color);
border-radius: 4px; border-radius: 4px;
} }
} }
+11 -11
View File
@@ -8,9 +8,9 @@
} }
.picker { .picker {
background: var(--popup-background-color); background: var(--popup-bg-color);
border: 0px solid transparentize($oc-white, 0.75); border: 0 solid transparentize($oc-white, 0.75);
box-shadow: transparentize($oc-black, 0.75) 0px 1px 4px; box-shadow: transparentize($oc-black, 0.75) 0 1px 4px;
border-radius: 4px; border-radius: 4px;
position: absolute; position: absolute;
} }
@@ -56,8 +56,8 @@
} }
.picker-triangle { .picker-triangle {
width: 0px; width: 0;
height: 0px; height: 0;
position: relative; position: relative;
top: -10px; top: -10px;
:root[dir="ltr"] & { :root[dir="ltr"] & {
@@ -73,7 +73,7 @@
content: ""; content: "";
position: absolute; position: absolute;
border-style: solid; border-style: solid;
border-width: 0px 9px 10px; border-width: 0 9px 10px;
border-color: transparent transparent transparentize($oc-black, 0.9); border-color: transparent transparent transparentize($oc-black, 0.9);
top: -1px; top: -1px;
} }
@@ -82,8 +82,8 @@
content: ""; content: "";
position: absolute; position: absolute;
border-style: solid; border-style: solid;
border-width: 0px 9px 10px; border-width: 0 9px 10px;
border-color: transparent transparent var(--popup-background-color); border-color: transparent transparent var(--popup-bg-color);
} }
} }
@@ -121,7 +121,7 @@
} }
.picker-type-elementBackground .picker-keybinding { .picker-type-elementBackground .picker-keybinding {
color: #fff; color: $oc-white;
} }
.picker-swatch[aria-label="transparent"] .picker-keybinding { .picker-swatch[aria-label="transparent"] .picker-keybinding {
@@ -134,10 +134,10 @@
&.Appearance_dark { &.Appearance_dark {
.picker-type-elementBackground .picker-keybinding { .picker-type-elementBackground .picker-keybinding {
color: #000; color: $oc-black;
} }
.picker-swatch[aria-label="transparent"] .picker-keybinding { .picker-swatch[aria-label="transparent"] .picker-keybinding {
color: #000; color: $oc-black;
} }
} }
} }
+2 -7
View File
@@ -1,12 +1,7 @@
import React from "react"; import React from "react";
import { LoadingMessage } from "./LoadingMessage"; import { LoadingMessage } from "./LoadingMessage";
import { import { defaultLang, Language, languages, setLanguage } from "../i18n";
defaultLang,
Language,
languages,
setLanguageFirstTime,
} from "../i18n";
interface Props { interface Props {
langCode: Language["code"]; langCode: Language["code"];
@@ -23,7 +18,7 @@ export class InitializeApp extends React.Component<Props, State> {
const currentLang = const currentLang =
languages.find((lang) => lang.code === this.props.langCode) || languages.find((lang) => lang.code === this.props.langCode) ||
defaultLang; defaultLang;
await setLanguageFirstTime(currentLang); await setLanguage(currentLang);
this.setState({ this.setState({
isLoading: false, isLoading: false,
}); });
+1 -1
View File
@@ -1,7 +1,7 @@
.excalidraw { .excalidraw {
.Island { .Island {
--padding: 0; --padding: 0;
background-color: var(--bg-color-island); background-color: var(--island-bg-color);
backdrop-filter: saturate(100%) blur(10px); backdrop-filter: saturate(100%) blur(10px);
box-shadow: var(--shadow-island); box-shadow: var(--shadow-island);
border-radius: 4px; border-radius: 4px;
+4 -4
View File
@@ -19,9 +19,9 @@
} }
a { a {
margin-left: auto; margin-inline-start: auto;
// 17px for scrollbar (needed for overlay scrollbars on Big Sur?) + 1px extra // 17px for scrollbar (needed for overlay scrollbars on Big Sur?) + 1px extra
padding-right: 18px; padding-inline-end: 18px;
white-space: nowrap; white-space: nowrap;
} }
} }
@@ -73,7 +73,7 @@
&__footer { &__footer {
position: absolute; position: absolute;
z-index: 100; z-index: 100;
bottom: 0px; bottom: 0;
:root[dir="ltr"] & { :root[dir="ltr"] & {
right: 0; right: 0;
@@ -94,7 +94,7 @@
} }
:root[dir="ltr"] &.transition-right { :root[dir="ltr"] &.transition-right {
transform: translate(999px, 0px); transform: translate(999px, 0);
} }
:root[dir="rtl"] &.transition-left { :root[dir="rtl"] &.transition-left {
+54 -26
View File
@@ -27,7 +27,7 @@ import { ExportCB, ExportDialog } from "./ExportDialog";
import { FixedSideContainer } from "./FixedSideContainer"; import { FixedSideContainer } from "./FixedSideContainer";
import { GitHubCorner } from "./GitHubCorner"; import { GitHubCorner } from "./GitHubCorner";
import { HintViewer } from "./HintViewer"; import { HintViewer } from "./HintViewer";
import { exportFile, load, shield } from "./icons"; import { exportFile, load, shield, trash } from "./icons";
import { Island } from "./Island"; import { Island } from "./Island";
import "./LayerUI.scss"; import "./LayerUI.scss";
import { LibraryUnit } from "./LibraryUnit"; import { LibraryUnit } from "./LibraryUnit";
@@ -52,6 +52,7 @@ interface LayerUIProps {
onLockToggle: () => void; onLockToggle: () => void;
onInsertElements: (elements: readonly NonDeletedExcalidrawElement[]) => void; onInsertElements: (elements: readonly NonDeletedExcalidrawElement[]) => void;
zenModeEnabled: boolean; zenModeEnabled: boolean;
showExitZenModeBtn: boolean;
toggleZenMode: () => void; toggleZenMode: () => void;
langCode: Language["code"]; langCode: Language["code"];
isCollaborating: boolean; isCollaborating: boolean;
@@ -99,6 +100,7 @@ const LibraryMenuItems = ({
onInsertShape, onInsertShape,
pendingElements, pendingElements,
setAppState, setAppState,
setLibraryItems,
}: { }: {
library: LibraryItems; library: LibraryItems;
pendingElements: LibraryItem; pendingElements: LibraryItem;
@@ -106,6 +108,7 @@ const LibraryMenuItems = ({
onInsertShape: (elements: LibraryItem) => void; onInsertShape: (elements: LibraryItem) => void;
onAddToLibrary: (elements: LibraryItem) => void; onAddToLibrary: (elements: LibraryItem) => void;
setAppState: React.Component<any, AppState>["setState"]; setAppState: React.Component<any, AppState>["setState"];
setLibraryItems: (library: LibraryItems) => void;
}) => { }) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const numCells = library.length + (pendingElements.length > 0 ? 1 : 0); const numCells = library.length + (pendingElements.length > 0 ? 1 : 0);
@@ -149,6 +152,19 @@ const LibraryMenuItems = ({
}); });
}} }}
/> />
<ToolButton
key="reset"
type="button"
title={t("buttons.resetLibrary")}
aria-label={t("buttons.resetLibrary")}
icon={trash}
onClick={() => {
if (window.confirm(t("alerts.resetLibrary"))) {
Library.resetLibrary();
setLibraryItems([]);
}
}}
/>
<a href="https://libraries.excalidraw.com" target="_excalidraw_libraries"> <a href="https://libraries.excalidraw.com" target="_excalidraw_libraries">
{t("labels.libraries")} {t("labels.libraries")}
@@ -280,6 +296,7 @@ const LibraryMenu = ({
onInsertShape={onInsertShape} onInsertShape={onInsertShape}
pendingElements={pendingElements} pendingElements={pendingElements}
setAppState={setAppState} setAppState={setAppState}
setLibraryItems={setLibraryItems}
/> />
)} )}
</Island> </Island>
@@ -296,6 +313,7 @@ const LayerUI = ({
onLockToggle, onLockToggle,
onInsertElements, onInsertElements,
zenModeEnabled, zenModeEnabled,
showExitZenModeBtn,
toggleZenMode, toggleZenMode,
isCollaborating, isCollaborating,
onExportToBackend, onExportToBackend,
@@ -424,7 +442,15 @@ const LayerUI = ({
"transition-left": zenModeEnabled, "transition-left": zenModeEnabled,
})} })}
> >
<Island className={CLASSES.SHAPE_ACTIONS_MENU} padding={2}> <Island
className={CLASSES.SHAPE_ACTIONS_MENU}
padding={2}
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`,
}}
>
<SelectedShapeActions <SelectedShapeActions
appState={appState} appState={appState}
elements={elements} elements={elements}
@@ -513,17 +539,18 @@ const LayerUI = ({
"transition-right": zenModeEnabled, "transition-right": zenModeEnabled,
})} })}
> >
{Array.from(appState.collaborators) {appState.collaborators.size > 0 &&
// Collaborator is either not initialized or is actually the current user. Array.from(appState.collaborators)
.filter(([_, client]) => Object.keys(client).length !== 0) // Collaborator is either not initialized or is actually the current user.
.map(([clientId, client]) => ( .filter(([_, client]) => Object.keys(client).length !== 0)
<Tooltip .map(([clientId, client]) => (
label={client.username || "Unknown user"} <Tooltip
key={clientId} label={client.username || "Unknown user"}
> key={clientId}
{actionManager.renderAction("goToCollaborator", clientId)} >
</Tooltip> {actionManager.renderAction("goToCollaborator", clientId)}
))} </Tooltip>
))}
</UserList> </UserList>
</div> </div>
</FixedSideContainer> </FixedSideContainer>
@@ -575,27 +602,16 @@ const LayerUI = ({
> >
{renderCustomFooter?.(false)} {renderCustomFooter?.(false)}
{actionManager.renderAction("toggleShortcuts")} {actionManager.renderAction("toggleShortcuts")}
{actionManager.renderAction("toggleMinimap")}
</div> </div>
<button <button
className={clsx("disable-zen-mode", { className={clsx("disable-zen-mode", {
"disable-zen-mode--visible": zenModeEnabled, "disable-zen-mode--visible": showExitZenModeBtn,
})} })}
onClick={toggleZenMode} onClick={toggleZenMode}
> >
{t("buttons.exitZenMode")} {t("buttons.exitZenMode")}
</button> </button>
{appState.scrolledOutside && (
<button
className="scroll-back-to-content"
onClick={() => {
setAppState({
...calculateScrollCenter(elements, appState, canvas),
});
}}
>
{t("buttons.scrollBackToContent")}
</button>
)}
</footer> </footer>
); );
@@ -658,6 +674,18 @@ const LayerUI = ({
{renderBottomAppMenu()} {renderBottomAppMenu()}
{renderGitHubCorner()} {renderGitHubCorner()}
{renderFooter()} {renderFooter()}
{appState.scrolledOutside && (
<button
className="scroll-back-to-content"
onClick={() => {
setAppState({
...calculateScrollCenter(elements, appState, canvas),
});
}}
>
{t("buttons.scrollBackToContent")}
</button>
)}
</div> </div>
); );
}; };
+5
View File
@@ -0,0 +1,5 @@
.Island.MiniMap {
position: absolute;
bottom: 50px;
right: calc(var(--space-factor) * 4);
}
+151
View File
@@ -0,0 +1,151 @@
import "./MiniMap.scss";
import React, { useEffect, useRef, useMemo, useState } from "react";
import { getCommonBounds, getNonDeletedElements } from "../element";
import { ExcalidrawElement } from "../element/types";
import { AppState } from "../types";
import { distance, viewportCoordsToSceneCoords } from "../utils";
import { Island } from "./Island";
// eslint-disable-next-line import/no-webpack-loader-syntax
import MinimapWorker from "worker-loader!../renderer/minimapWorker";
const RATIO = 1.2;
const MINIMAP_HEIGHT = 150;
const MINIMAP_WIDTH = MINIMAP_HEIGHT * RATIO;
const MinimapViewport = ({
elements,
appState,
}: {
elements: readonly ExcalidrawElement[];
appState: AppState;
}) => {
const [minX, minY, maxX, maxY] = useMemo(
() => getCommonBounds(getNonDeletedElements(elements)),
[elements],
);
const minimapScale = Math.min(
MINIMAP_WIDTH / distance(minX, maxX),
MINIMAP_HEIGHT / distance(minY, maxY),
);
const leftTop = viewportCoordsToSceneCoords(
{ clientX: 0, clientY: 0 },
appState,
);
const rightBot = viewportCoordsToSceneCoords(
{ clientX: appState.width, clientY: appState.height },
appState,
);
const top = (leftTop.y - minY) * minimapScale;
const left = (leftTop.x - minX) * minimapScale;
const width = (rightBot.x - leftTop.x) * minimapScale;
const height = (rightBot.y - leftTop.y) * minimapScale;
// Set viewport boundaries
const viewportTop = Math.min(Math.max(0, top), MINIMAP_HEIGHT);
const viewportLeft = Math.min(Math.max(0, left), MINIMAP_WIDTH);
const viewportWidth = Math.min(
MINIMAP_WIDTH - viewportLeft,
width,
width + left,
);
const viewportHeight = Math.min(
MINIMAP_HEIGHT - viewportTop,
height,
height + top,
);
if (
Number.isNaN(viewportTop) ||
Number.isNaN(viewportLeft) ||
Number.isNaN(viewportWidth) ||
Number.isNaN(viewportHeight)
) {
return null;
}
return (
<div
style={{
border: "2px solid orange",
boxSizing: "border-box",
position: "absolute",
pointerEvents: "none",
top: viewportTop,
left: viewportLeft,
width: viewportWidth,
height: viewportHeight,
}}
/>
);
};
export function MiniMap({
appState,
elements,
}: {
appState: AppState;
elements: readonly ExcalidrawElement[];
}) {
const [minimapWorker] = useState(() => new MinimapWorker());
const canvasRef = useRef<HTMLCanvasElement>(null);
const elementsRef = useRef(elements);
elementsRef.current = elements;
const appStateRef = useRef(appState);
appStateRef.current = appState;
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) {
return;
}
const offscreenCanvas = canvas.transferControlToOffscreen();
minimapWorker.postMessage({ type: "INIT", canvas: offscreenCanvas }, [
offscreenCanvas,
]);
minimapWorker.postMessage({
type: "DRAW",
elements: elementsRef.current,
appState: appStateRef.current,
width: MINIMAP_WIDTH,
height: MINIMAP_HEIGHT,
});
setInterval(() => {
minimapWorker.postMessage({
type: "DRAW",
elements: elementsRef.current,
appState: appStateRef.current,
width: MINIMAP_WIDTH,
height: MINIMAP_HEIGHT,
});
}, 1000);
return () => {
minimapWorker.terminate();
};
}, [minimapWorker]);
return (
<Island padding={1} className="MiniMap">
<div
style={{
width: MINIMAP_WIDTH,
height: MINIMAP_HEIGHT,
position: "relative",
overflow: "hidden",
backgroundColor: appState.viewBackgroundColor,
}}
>
<canvas ref={canvasRef} />
<MinimapViewport elements={elements} appState={appState} />
</div>
</Island>
);
}
+20 -18
View File
@@ -152,24 +152,26 @@ export const MobileMenu = ({
<Stack.Col gap={4}> <Stack.Col gap={4}>
{renderCanvasActions()} {renderCanvasActions()}
{renderCustomFooter?.(true)} {renderCustomFooter?.(true)}
<fieldset> {appState.collaborators.size > 0 && (
<legend>{t("labels.collaborators")}</legend> <fieldset>
<UserList mobile> <legend>{t("labels.collaborators")}</legend>
{Array.from(appState.collaborators) <UserList mobile>
// Collaborator is either not initialized or is actually the current user. {Array.from(appState.collaborators)
.filter( // Collaborator is either not initialized or is actually the current user.
([_, client]) => Object.keys(client).length !== 0, .filter(
) ([_, client]) => Object.keys(client).length !== 0,
.map(([clientId, client]) => ( )
<React.Fragment key={clientId}> .map(([clientId, client]) => (
{actionManager.renderAction( <React.Fragment key={clientId}>
"goToCollaborator", {actionManager.renderAction(
clientId, "goToCollaborator",
)} clientId,
</React.Fragment> )}
))} </React.Fragment>
</UserList> ))}
</fieldset> </UserList>
</fieldset>
)}
</Stack.Col> </Stack.Col>
</div> </div>
</Section> </Section>
+10 -5
View File
@@ -1,8 +1,13 @@
@import "../css/variables.module"; @import "../css/variables.module";
.excalidraw { .excalidraw {
&.excalidraw-modal-container {
position: absolute;
z-index: 10;
}
.Modal { .Modal {
position: fixed; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
@@ -15,7 +20,7 @@
} }
.Modal__background { .Modal__background {
position: fixed; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
@@ -39,10 +44,10 @@
overflow-y: auto; overflow-y: auto;
// for modals, reset blurry bg // for modals, reset blurry bg
background: var(--bg-color-island); background: var(--island-bg-color);
backdrop-filter: none; backdrop-filter: none;
border: 1px solid var(--dialog-border); border: 1px solid var(--dialog-border-color);
box-shadow: 0 2px 10px transparentize($oc-black, 0.75); box-shadow: 0 2px 10px transparentize($oc-black, 0.75);
border-radius: 6px; border-radius: 6px;
@@ -82,7 +87,7 @@
} }
.Modal__content { .Modal__content {
position: fixed; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
+1 -1
View File
@@ -54,7 +54,7 @@ const useBodyRoot = () => {
?.classList.contains("Appearance_dark"); ?.classList.contains("Appearance_dark");
const div = document.createElement("div"); const div = document.createElement("div");
div.classList.add("excalidraw"); div.classList.add("excalidraw", "excalidraw-modal-container");
if (isDarkTheme) { if (isDarkTheme) {
div.classList.add("Appearance_dark"); div.classList.add("Appearance_dark");
+1 -9
View File
@@ -1,14 +1,6 @@
.excalidraw { .excalidraw {
.popover { .popover {
position: absolute; position: fixed;
z-index: 10; z-index: 10;
} }
.popover .cover {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
} }
+42 -40
View File
@@ -1,51 +1,53 @@
@import "../css/variables.module"; @import "../css/variables.module";
.Stats { .excalidraw {
position: fixed; .Stats {
top: 64px; position: absolute;
right: 12px; top: 64px;
font-size: 12px; right: 12px;
z-index: 999; font-size: 12px;
z-index: 999;
h3 { h3 {
margin: 0 24px 8px 0; margin: 0 24px 8px 0;
white-space: nowrap; white-space: nowrap;
} }
.close { .close {
float: right; float: right;
height: 16px; height: 16px;
width: 16px; width: 16px;
cursor: pointer; cursor: pointer;
svg { svg {
width: 100%;
height: 100%;
}
}
table {
width: 100%; width: 100%;
height: 100%; th {
border-bottom: 1px solid var(--input-border-color);
padding: 4px;
}
tr {
td:nth-child(2) {
min-width: 24px;
text-align: right;
}
}
} }
}
table { :root[dir="rtl"] & {
width: 100%; left: 12px;
th { right: initial;
border-bottom: 1px solid var(--input-border-color);
padding: 4px; h3 {
} margin: 0 0 8px 24px;
tr { }
td:nth-child(2) { .close {
min-width: 24px; float: left;
text-align: right;
} }
} }
} }
:root[dir="rtl"] & {
left: 12px;
right: initial;
h3 {
margin: 0 0 8px 24px;
}
.close {
float: left;
}
}
} }
+3 -3
View File
@@ -2,18 +2,18 @@
.excalidraw { .excalidraw {
.TextInput { .TextInput {
color: var(--text-color-primary); color: var(--text-primary-color);
display: inline-block; display: inline-block;
border: 1.5px solid var(--button-gray-1); border: 1.5px solid var(--button-gray-1);
line-height: 1; line-height: 1;
padding: 0.75rem; padding: 0.75rem;
white-space: nowrap; white-space: nowrap;
border-radius: var(--space-factor); border-radius: var(--space-factor);
background-color: var(--input-background-color); background-color: var(--input-bg-color);
&:not(:focus) { &:not(:focus) {
&:hover { &:hover {
background-color: var(--input-hover-background-color); background-color: var(--input-hover-bg-color);
} }
} }
+1 -1
View File
@@ -11,7 +11,7 @@
left: 50%; left: 50%;
margin-left: -150px; margin-left: -150px;
padding: 4px 0; padding: 4px 0;
position: fixed; position: absolute;
text-align: center; text-align: center;
width: 300px; width: 300px;
z-index: 999999; z-index: 999999;
+10 -2
View File
@@ -2,8 +2,8 @@ import { FontFamily } from "./element/types";
export const APP_NAME = "Excalidraw"; export const APP_NAME = "Excalidraw";
export const DRAGGING_THRESHOLD = 10; // 10px export const DRAGGING_THRESHOLD = 10; // px
export const LINE_CONFIRM_THRESHOLD = 10; // 10px export const LINE_CONFIRM_THRESHOLD = 8; // px
export const ELEMENT_SHIFT_TRANSLATE_AMOUNT = 5; export const ELEMENT_SHIFT_TRANSLATE_AMOUNT = 5;
export const ELEMENT_TRANSLATE_AMOUNT = 1; export const ELEMENT_TRANSLATE_AMOUNT = 1;
export const TEXT_TO_CENTER_SNAP_THRESHOLD = 30; export const TEXT_TO_CENTER_SNAP_THRESHOLD = 30;
@@ -47,6 +47,7 @@ export enum EVENT {
TOUCH_END = "touchend", TOUCH_END = "touchend",
HASHCHANGE = "hashchange", HASHCHANGE = "hashchange",
VISIBILITY_CHANGE = "visibilitychange", VISIBILITY_CHANGE = "visibilitychange",
SCROLL = "scroll",
} }
export const ENV = { export const ENV = {
@@ -92,6 +93,7 @@ export const TOUCH_CTX_MENU_TIMEOUT = 500;
export const TITLE_TIMEOUT = 10000; export const TITLE_TIMEOUT = 10000;
export const TOAST_TIMEOUT = 5000; export const TOAST_TIMEOUT = 5000;
export const VERSION_TIMEOUT = 30000; export const VERSION_TIMEOUT = 30000;
export const SCROLL_TIMEOUT = 500;
export const ZOOM_STEP = 0.1; export const ZOOM_STEP = 0.1;
@@ -99,3 +101,9 @@ export const ZOOM_STEP = 0.1;
export const IDLE_THRESHOLD = 60_000; export const IDLE_THRESHOLD = 60_000;
// Report a user active each ACTIVE_THRESHOLD milliseconds // Report a user active each ACTIVE_THRESHOLD milliseconds
export const ACTIVE_THRESHOLD = 3_000; export const ACTIVE_THRESHOLD = 3_000;
export const MODES = {
VIEW: "viewMode",
ZEN: "zenMode",
GRID: "gridMode",
};
+15 -16
View File
@@ -8,9 +8,8 @@
} }
.excalidraw { .excalidraw {
color: var(--text-color-primary); color: var(--text-primary-color);
display: flex; display: flex;
position: fixed;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
@@ -51,10 +50,10 @@
} }
.FixedSideContainer { .FixedSideContainer {
padding-top: var(--sat, 0px); padding-top: var(--sat, 0);
padding-right: var(--sar, 0px); padding-right: var(--sar, 0);
padding-bottom: var(--sab, 0px); padding-bottom: var(--sab, 0);
padding-left: var(--sal, 0px); padding-left: var(--sal, 0);
} }
.panelRow { .panelRow {
@@ -72,7 +71,7 @@
margin-top: 0.333rem; margin-top: 0.333rem;
margin-bottom: 0.333rem; margin-bottom: 0.333rem;
font-size: 0.75rem; font-size: 0.75rem;
color: var(--text-color-primary); color: var(--text-primary-color);
font-weight: bold; font-weight: bold;
display: block; display: block;
} }
@@ -227,7 +226,8 @@
.App-top-bar { .App-top-bar {
z-index: var(--zIndex-layerUI); z-index: var(--zIndex-layerUI);
display: flex; display: flex;
justify-content: center; flex-direction: column;
align-items: center;
} }
.App-bottom-bar { .App-bottom-bar {
@@ -237,10 +237,10 @@
left: 0; left: 0;
right: 0; right: 0;
--bar-padding: calc(4 * var(--space-factor)); --bar-padding: calc(4 * var(--space-factor));
padding-top: #{"max(var(--bar-padding), var(--sat, 0px))"}; padding-top: #{"max(var(--bar-padding), var(--sat,0))"};
padding-right: var(--sar, 0px); padding-right: var(--sar, 0);
padding-bottom: var(--sab, 0px); padding-bottom: var(--sab, 0);
padding-left: var(--sal, 0px); padding-left: var(--sal, 0);
z-index: 4; z-index: 4;
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
@@ -257,7 +257,7 @@
pointer-events: initial; pointer-events: initial;
.panelColumn { .panelColumn {
padding: 8px 8px 0px 8px; padding: 8px 8px 0 8px;
} }
} }
} }
@@ -361,7 +361,6 @@
.App-menu__left { .App-menu__left {
overflow-y: auto; overflow-y: auto;
max-height: calc(100vh - 236px);
} }
.dropdown-select { .dropdown-select {
@@ -433,7 +432,7 @@
.scroll-back-to-content { .scroll-back-to-content {
color: var(--popup-text-color); color: var(--popup-text-color);
position: fixed; position: absolute;
left: 50%; left: 50%;
bottom: 30px; bottom: 30px;
transform: translateX(-50%); transform: translateX(-50%);
@@ -461,7 +460,7 @@
display: none; display: none;
} }
.scroll-back-to-content { .scroll-back-to-content {
bottom: calc(80px + var(--sab, 0px)); bottom: calc(80px + var(--sab, 0));
z-index: -1; z-index: -1;
} }
} }
+42 -42
View File
@@ -1,43 +1,43 @@
@import "open-color/open-color.scss"; @import "open-color/open-color.scss";
:root { :root {
--bg-color-island: rgba(255, 255, 255, 0.9); --appearance-filter: none;
--popup-background-color: #{$oc-white}; --button-destructive-bg-color: #{$oc-red-1};
--space-factor: 0.25rem; --button-destructive-color: #{$oc-red-9};
--button-gray-1: #{$oc-gray-2}; --button-gray-1: #{$oc-gray-2};
--button-gray-2: #{$oc-gray-4}; --button-gray-2: #{$oc-gray-4};
--button-gray-3: #{$oc-gray-5}; --button-gray-3: #{$oc-gray-5};
--input-border-color: #{$oc-gray-3}; --button-special-active-bg-color: #{$oc-green-0};
--input-background-color: #{$oc-white}; --dialog-border-color: #{$oc-gray-6};
--input-hover-background-color: #{$oc-gray-1}; --dropdown-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="292.4" height="292.4" viewBox="0 0 292 292"><path d="M287 197L159 69c-4-3-8-5-13-5s-9 2-13 5L5 197c-3 4-5 8-5 13s2 9 5 13c4 4 8 5 13 5h256c5 0 9-1 13-5s5-8 5-13-1-9-5-13z"/></svg>');
--input-label-color: #{$oc-gray-7}; --focus-highlight-color: #{$oc-blue-2};
--icon-fill-color: #{$oc-black}; --icon-fill-color: #{$oc-black};
--icon-green-fill-color: #{$oc-green-9}; --icon-green-fill-color: #{$oc-green-9};
--input-bg-color: #{$oc-white};
--input-border-color: #{$oc-gray-3};
--input-hover-bg-color: #{$oc-gray-1};
--input-label-color: #{$oc-gray-7};
--island-bg-color: rgba(255, 255, 255, 0.9);
--keybinding-color: #{$oc-gray-5}; --keybinding-color: #{$oc-gray-5};
--sat: env(safe-area-inset-top); --link-color: #{$oc-blue-7};
--overlay-bg-color: #{transparentize($oc-white, 0.12)};
--popup-bg-color: #{$oc-white};
--popup-secondary-bg-color: #{$oc-gray-1};
--popup-text-color: #{$oc-black};
--popup-text-inverted-color: #{$oc-white};
--sab: env(safe-area-inset-bottom); --sab: env(safe-area-inset-bottom);
--sal: env(safe-area-inset-left); --sal: env(safe-area-inset-left);
--sar: env(safe-area-inset-right); --sar: env(safe-area-inset-right);
--text-color-primary: #{$oc-gray-8}; --sat: env(safe-area-inset-top);
--shadow-island: 0 1px 5px #{transparentize($oc-black, 0.85)};
--overlay-background-color: #{transparentize($oc-white, 0.12)};
--dropdown-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="292.4" height="292.4" viewBox="0 0 292 292"><path d="M287 197L159 69c-4-3-8-5-13-5s-9 2-13 5L5 197c-3 4-5 8-5 13s2 9 5 13c4 4 8 5 13 5h256c5 0 9-1 13-5s5-8 5-13-1-9-5-13z"/></svg>');
--focus-highlight-color: #{$oc-blue-2};
--select-highlight-color: #{$oc-blue-5}; --select-highlight-color: #{$oc-blue-5};
--appearance-filter: none; --shadow-island: 0 1px 5px #{transparentize($oc-black, 0.85)};
--button-special-active-background-color: #{$oc-green-0}; --space-factor: 0.25rem;
--button-destructive-color: #{$oc-red-9}; --text-primary-color: #{$oc-gray-8};
--button-destructive-background-color: #{$oc-red-1};
--popup-secondary-background-color: #{$oc-gray-1};
--popup-text-color: #{$oc-black};
--popup-text-inverted-color: #{$oc-white};
--dialog-border: #{$oc-gray-6};
--link-color: #{$oc-blue-7};
} }
.excalidraw { .excalidraw {
&.Appearance_dark { &.Appearance_dark {
background: #000; background: $oc-black;
&.Appearance_dark-background-none { &.Appearance_dark-background-none {
background: none; background: none;
@@ -45,31 +45,31 @@
} }
&.Appearance_dark { &.Appearance_dark {
--text-color-primary: #{$oc-gray-4}; --appearance-filter: invert(93%) hue-rotate(180deg);
--bg-color-island: #1e1e1e; --button-destructive-bg-color: #5a0000;
--popup-background-color: #2c2c2c; --button-destructive-color: #{$oc-red-3};
--button-gray-1: #363636; --button-gray-1: #363636;
--button-gray-2: #272727; --button-gray-2: #272727;
--button-gray-3: #222; --button-gray-3: #222;
--input-border-color: #2e2e2e; --button-special-active-bg-color: #204624;
--input-background-color: #121212; --dialog-border-color: #{$oc-gray-9};
--input-hover-background-color: #181818;
--input-label-color: #{$oc-gray-2};
--icon-fill-color: #{$oc-gray-4};
--icon-green-fill-color: #{$oc-green-4};
--keybinding-color: #{$oc-gray-6};
--shadow-island: 0 1px 5px #{transparentize($oc-black, 0.7)};
--overlay-background-color: rgba(30, 30, 30, 0.88);
--dropdown-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="292.4" height="292.4" viewBox="0 0 292 292"><path fill="%23ced4da" d="M287 197L159 69c-4-3-8-5-13-5s-9 2-13 5L5 197c-3 4-5 8-5 13s2 9 5 13c4 4 8 5 13 5h256c5 0 9-1 13-5s5-8 5-13-1-9-5-13z"/></svg>'); --dropdown-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="292.4" height="292.4" viewBox="0 0 292 292"><path fill="%23ced4da" d="M287 197L159 69c-4-3-8-5-13-5s-9 2-13 5L5 197c-3 4-5 8-5 13s2 9 5 13c4 4 8 5 13 5h256c5 0 9-1 13-5s5-8 5-13-1-9-5-13z"/></svg>');
--focus-highlight-color: #{$oc-blue-6}; --focus-highlight-color: #{$oc-blue-6};
--select-highlight-color: #{$oc-blue-4}; --icon-fill-color: #{$oc-gray-4};
--appearance-filter: invert(93%) hue-rotate(180deg); --icon-green-fill-color: #{$oc-green-4};
--button-special-active-background-color: #204624; --input-bg-color: #121212;
--button-destructive-color: #{$oc-red-3}; --input-border-color: #2e2e2e;
--button-destructive-background-color: #5a0000; --input-hover-bg-color: #181818;
--popup-secondary-background-color: #222; --input-label-color: #{$oc-gray-2};
--island-bg-color: #1e1e1e;
--keybinding-color: #{$oc-gray-6};
--overlay-bg-color: #{transparentize($oc-gray-8, 0.88)};
--popup-bg-color: #2c2c2c;
--popup-secondary-bg-color: #222;
--popup-text-color: #{$oc-gray-4}; --popup-text-color: #{$oc-gray-4};
--popup-text-inverted-color: #2c2c2c; --popup-text-inverted-color: #2c2c2c;
--dialog-border: #{$oc-gray-9}; --select-highlight-color: #{$oc-blue-4};
--shadow-island: 0 1px 5px #{transparentize($oc-black, 0.7)};
--text-primary-color: #{$oc-gray-4};
} }
} }
+5
View File
@@ -73,6 +73,11 @@ export const exportCanvas = async (
scale, scale,
shouldAddWatermark, shouldAddWatermark,
}); });
if (tempCanvas instanceof OffscreenCanvas) {
return;
}
tempCanvas.style.display = "none"; tempCanvas.style.display = "none";
document.body.appendChild(tempCanvas); document.body.appendChild(tempCanvas);
+1 -1
View File
@@ -141,7 +141,7 @@ export const restoreElements = (
}, [] as ExcalidrawElement[]); }, [] as ExcalidrawElement[]);
}; };
const restoreAppState = ( export const restoreAppState = (
appState: ImportedDataState["appState"], appState: ImportedDataState["appState"],
localAppState: Partial<AppState> | null, localAppState: Partial<AppState> | null,
): AppState => { ): AppState => {
+1 -1
View File
@@ -129,7 +129,7 @@ export class LinearElementEditor {
isDragging && isDragging &&
(activePointIndex === 0 || activePointIndex === element.points.length - 1) (activePointIndex === 0 || activePointIndex === element.points.length - 1)
) { ) {
if (isPathALoop(element.points)) { if (isPathALoop(element.points, appState.zoom.value)) {
LinearElementEditor.movePoint( LinearElementEditor.movePoint(
element, element,
activePointIndex, activePointIndex,
+19 -3
View File
@@ -38,6 +38,7 @@ export const textWysiwyg = ({
onSubmit, onSubmit,
getViewportCoords, getViewportCoords,
element, element,
canvas,
}: { }: {
id: ExcalidrawElement["id"]; id: ExcalidrawElement["id"];
appState: AppState; appState: AppState;
@@ -45,6 +46,7 @@ export const textWysiwyg = ({
onSubmit: (text: string) => void; onSubmit: (text: string) => void;
getViewportCoords: (x: number, y: number) => [number, number]; getViewportCoords: (x: number, y: number) => [number, number];
element: ExcalidrawElement; element: ExcalidrawElement;
canvas: HTMLCanvasElement | null;
}) => { }) => {
const updateWysiwygStyle = () => { const updateWysiwygStyle = () => {
const updatedElement = Scene.getScene(element)?.getElement(id); const updatedElement = Scene.getScene(element)?.getElement(id);
@@ -151,6 +153,10 @@ export const textWysiwyg = ({
editable.oninput = null; editable.oninput = null;
editable.onkeydown = null; editable.onkeydown = null;
if (observer) {
observer.disconnect();
}
window.removeEventListener("resize", updateWysiwygStyle); window.removeEventListener("resize", updateWysiwygStyle);
window.removeEventListener("wheel", stopEvent, true); window.removeEventListener("wheel", stopEvent, true);
window.removeEventListener("pointerdown", onPointerDown); window.removeEventListener("pointerdown", onPointerDown);
@@ -197,9 +203,19 @@ export const textWysiwyg = ({
let isDestroyed = false; let isDestroyed = false;
editable.onblur = handleSubmit; editable.onblur = handleSubmit;
// reposition wysiwyg in case of window resize. Happens on mobile when
// device keyboard is opened. // reposition wysiwyg in case of canvas is resized. Using ResizeObserver
window.addEventListener("resize", updateWysiwygStyle); // is preferred so we catch changes from host, where window may not resize.
let observer: ResizeObserver | null = null;
if (canvas && "ResizeObserver" in window) {
observer = new window.ResizeObserver(() => {
updateWysiwygStyle();
});
observer.observe(canvas);
} else {
window.addEventListener("resize", updateWysiwygStyle);
}
window.addEventListener("pointerdown", onPointerDown); window.addEventListener("pointerdown", onPointerDown);
window.addEventListener("wheel", stopEvent, { window.addEventListener("wheel", stopEvent, {
passive: false, passive: false,
+17 -3
View File
@@ -7,7 +7,7 @@
} }
.RoomDialog-link { .RoomDialog-link {
color: var(--text-color-primary); color: var(--text-primary-color);
min-width: 0; min-width: 0;
flex: 1 1 auto; flex: 1 1 auto;
margin-inline-start: 1em; margin-inline-start: 1em;
@@ -32,15 +32,29 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@media #{$is-mobile-query} {
flex-direction: column;
align-items: stretch;
}
}
@media #{$is-mobile-query} {
.RoomDialog-usernameLabel {
font-weight: bold;
}
} }
.RoomDialog-username { .RoomDialog-username {
background-color: var(--input-background-color); background-color: var(--input-bg-color);
border-color: var(--input-border-color); border-color: var(--input-border-color);
appearance: none; appearance: none;
min-width: 0; min-width: 0;
flex: 1 1 auto; flex: 1 1 auto;
margin-inline-start: 1em; margin-inline-start: 1em;
@media #{$is-mobile-query} {
margin-top: 0.5em;
margin-inline-start: 0;
}
height: 2.5rem; height: 2.5rem;
font-size: 1em; font-size: 1em;
line-height: 1.5; line-height: 1.5;
@@ -53,7 +67,7 @@
} }
.Modal .RoomDialog-stopSession { .Modal .RoomDialog-stopSession {
background-color: var(--button-destructive-background-color); background-color: var(--button-destructive-bg-color);
.ToolIcon__label, .ToolIcon__label,
.ToolIcon__icon svg { .ToolIcon__icon svg {
+5 -1
View File
@@ -119,7 +119,11 @@ const RoomDialog = ({
); );
}; };
return ( return (
<Dialog small onCloseRequest={handleClose} title={t("labels.createRoom")}> <Dialog
small
onCloseRequest={handleClose}
title={t("labels.liveCollaboration")}
>
{renderRoomDialog()} {renderRoomDialog()}
</Dialog> </Dialog>
); );
+8 -2
View File
@@ -80,7 +80,14 @@ const initializeScene = async (opts: {
let roomLinkData = getCollaborationLinkData(window.location.href); let roomLinkData = getCollaborationLinkData(window.location.href);
const isExternalScene = !!(id || jsonMatch || roomLinkData); const isExternalScene = !!(id || jsonMatch || roomLinkData);
if (isExternalScene) { if (isExternalScene) {
if (roomLinkData || window.confirm(t("alerts.loadSceneOverridePrompt"))) { if (
// don't prompt if scene is empty
!scene.elements.length ||
// don't prompt for collab scenes because we don't override local storage
roomLinkData ||
// otherwise, prompt whether user wants to override current scene
window.confirm(t("alerts.loadSceneOverridePrompt"))
) {
// Backwards compatibility with legacy url format // Backwards compatibility with legacy url format
if (id) { if (id) {
scene = await loadScene(id, null, initialData); scene = await loadScene(id, null, initialData);
@@ -274,7 +281,6 @@ function ExcalidrawWrapper() {
width={dimensions.width} width={dimensions.width}
height={dimensions.height} height={dimensions.height}
initialData={initialStatePromiseRef.current.promise} initialData={initialStatePromiseRef.current.promise}
user={{ name: collabAPI?.username }}
onCollabButtonClick={collabAPI?.onCollabButtonClick} onCollabButtonClick={collabAPI?.onCollabButtonClick}
isCollaborating={collabAPI?.isCollaborating()} isCollaborating={collabAPI?.isCollaborating()}
onPointerUpdate={collabAPI?.onPointerUpdate} onPointerUpdate={collabAPI?.onPointerUpdate}
+11
View File
@@ -88,3 +88,14 @@ interface Blob {
handle?: import("browser-fs-acces").FileSystemHandle; handle?: import("browser-fs-acces").FileSystemHandle;
name?: string; name?: string;
} }
declare module "worker-loader!*" {
// You need to change `Worker`, if you specified a different value for the `workerType` option
class WebpackWorker extends Worker {
constructor();
}
// Uncomment this if you set the `esModule` option to `false`
// export = WebpackWorker;
export default WebpackWorker;
}
+28 -12
View File
@@ -1,5 +1,6 @@
import fallbackLangData from "./locales/en.json"; import fallbackLangData from "./locales/en.json";
import percentages from "./locales/percentages.json"; import percentages from "./locales/percentages.json";
import { ENV } from "./constants";
const COMPLETION_THRESHOLD = 85; const COMPLETION_THRESHOLD = 85;
@@ -55,25 +56,33 @@ export const languages: Language[] = allLanguages
COMPLETION_THRESHOLD, COMPLETION_THRESHOLD,
); );
const TEST_LANG_CODE = "__test__";
if (process.env.NODE_ENV === ENV.DEVELOPMENT) {
languages.unshift(
{ code: TEST_LANG_CODE, label: "test language" },
{
code: `${TEST_LANG_CODE}.rtl`,
label: "\u{202a}test language (rtl)\u{202c}",
rtl: true,
},
);
}
let currentLang: Language = defaultLang; let currentLang: Language = defaultLang;
let currentLangData = {}; let currentLangData = {};
export const setLanguage = async (lang: Language) => { export const setLanguage = async (lang: Language) => {
currentLang = lang; currentLang = lang;
document.documentElement.dir = currentLang.rtl ? "rtl" : "ltr"; document.documentElement.dir = currentLang.rtl ? "rtl" : "ltr";
document.documentElement.lang = currentLang.code;
currentLangData = await import( if (lang.code.startsWith(TEST_LANG_CODE)) {
/* webpackChunkName: "i18n-[request]" */ `./locales/${currentLang.code}.json` currentLangData = {};
); } else {
}; currentLangData = await import(
/* webpackChunkName: "i18n-[request]" */ `./locales/${currentLang.code}.json`
export const setLanguageFirstTime = async (lang: Language) => { );
currentLang = lang; }
document.documentElement.dir = currentLang.rtl ? "rtl" : "ltr";
currentLangData = await import(
/* webpackChunkName: "i18n-[request]" */ `./locales/${currentLang.code}.json`
);
}; };
export const getLanguage = () => currentLang; export const getLanguage = () => currentLang;
@@ -93,6 +102,13 @@ const findPartsForData = (data: any, parts: string[]) => {
}; };
export const t = (path: string, replacement?: { [key: string]: string }) => { export const t = (path: string, replacement?: { [key: string]: string }) => {
if (currentLang.code.startsWith(TEST_LANG_CODE)) {
const name = replacement
? `${path}(${JSON.stringify(replacement).slice(1, -1)})`
: path;
return `\u{202a}[[${name}]]\u{202c}`;
}
const parts = path.split("."); const parts = path.split(".");
let translation = let translation =
findPartsForData(currentLangData, parts) || findPartsForData(currentLangData, parts) ||
+5 -2
View File
@@ -1,5 +1,7 @@
export const isDarwin = /Mac|iPod|iPhone|iPad/.test(window.navigator.platform); export const isDarwin = /Mac|iPod|iPhone|iPad/.test(
export const isWindows = /^Win/.test(window.navigator.platform); globalThis.navigator.platform,
);
export const isWindows = /^Win/.test(globalThis.navigator.platform);
export const CODES = { export const CODES = {
EQUAL: "Equal", EQUAL: "Equal",
@@ -43,6 +45,7 @@ export const KEYS = {
D: "d", D: "d",
E: "e", E: "e",
L: "l", L: "l",
M: "m",
O: "o", O: "o",
P: "p", P: "p",
Q: "q", Q: "q",
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "الطبقات", "layers": "الطبقات",
"actions": "الإجراءات", "actions": "الإجراءات",
"language": "اللغة", "language": "اللغة",
"createRoom": "مشاركة الجلسة مباشرة", "liveCollaboration": "",
"duplicateSelection": "تكرار", "duplicateSelection": "تكرار",
"untitled": "غير معنون", "untitled": "غير معنون",
"name": "الاسم", "name": "الاسم",
@@ -77,7 +77,7 @@
"group": "تحديد مجموعة", "group": "تحديد مجموعة",
"ungroup": "إلغاء تحديد مجموعة", "ungroup": "إلغاء تحديد مجموعة",
"collaborators": "المتعاونون", "collaborators": "المتعاونون",
"gridMode": "وضع الشبكة", "showGrid": "",
"addToLibrary": "أضف إلى المكتبة", "addToLibrary": "أضف إلى المكتبة",
"removeFromLibrary": "حذف من المكتبة", "removeFromLibrary": "حذف من المكتبة",
"libraryLoadingMessage": "جارٍ تحميل المكتبة…", "libraryLoadingMessage": "جارٍ تحميل المكتبة…",
@@ -117,7 +117,7 @@
"edit": "تعديل", "edit": "تعديل",
"undo": "تراجع", "undo": "تراجع",
"redo": "إعادة تنفيذ", "redo": "إعادة تنفيذ",
"roomDialog": "بدء المشاركة الحية", "resetLibrary": "",
"createNewRoom": "إنشاء غرفة جديدة", "createNewRoom": "إنشاء غرفة جديدة",
"fullScreen": "شاشة كاملة", "fullScreen": "شاشة كاملة",
"darkMode": "الوضع المظلم", "darkMode": "الوضع المظلم",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "حصل خطأ أثناء تحميل مكتبة الطرف الثالث.", "errorLoadingLibrary": "حصل خطأ أثناء تحميل مكتبة الطرف الثالث.",
"confirmAddLibrary": "هذا سيضيف {{numShapes}} شكل إلى مكتبتك. هل أنت متأكد؟", "confirmAddLibrary": "هذا سيضيف {{numShapes}} شكل إلى مكتبتك. هل أنت متأكد؟",
"imageDoesNotContainScene": "استيراد الصور غير مدعوم في الوقت الراهن.\n\nهل تريد استيراد مشهد؟ لا يبدو أن هذه الصورة تحتوي على أي بيانات مشهد. هل قمت بسماح هذا أثناء التصدير؟", "imageDoesNotContainScene": "استيراد الصور غير مدعوم في الوقت الراهن.\n\nهل تريد استيراد مشهد؟ لا يبدو أن هذه الصورة تحتوي على أي بيانات مشهد. هل قمت بسماح هذا أثناء التصدير؟",
"cannotRestoreFromImage": "تعذر استعادة المشهد من ملف الصورة" "cannotRestoreFromImage": "تعذر استعادة المشهد من ملف الصورة",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "تحديد", "selection": "تحديد",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "", "copyStyles": "",
"copyToClipboard": "", "copyToClipboard": "",
"copyToClipboardAsPng": "" "copyToClipboardAsPng": "",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+30 -27
View File
@@ -8,11 +8,11 @@
"cut": "Изрежи", "cut": "Изрежи",
"copy": "Копирай", "copy": "Копирай",
"copyAsPng": "Копиране в клипборда", "copyAsPng": "Копиране в клипборда",
"copyAsSvg": "Копиране в клипборда", "copyAsSvg": "Копирано в клипборда като SVG",
"bringForward": "Преместване на~пред", "bringForward": "Преместване напред",
"sendToBack": "Изнасяне назад", "sendToBack": "Изнасяне назад",
"bringToFront": "~Изнасяне отпред", "bringToFront": "Изнасяне отпред",
"sendBackward": "Изпрати назад", "sendBackward": "Изпрати отзад",
"delete": "Изтрий", "delete": "Изтрий",
"copyStyles": "Копирайте стилове", "copyStyles": "Копирайте стилове",
"pasteStyles": "Постави стилове", "pasteStyles": "Постави стилове",
@@ -68,7 +68,7 @@
"layers": "Слоеве", "layers": "Слоеве",
"actions": "Действия", "actions": "Действия",
"language": "Език", "language": "Език",
"createRoom": "Споделете сесия за сътрудничество на живо", "liveCollaboration": "",
"duplicateSelection": "Дублирай", "duplicateSelection": "Дублирай",
"untitled": "Неозаглавено", "untitled": "Неозаглавено",
"name": "Име", "name": "Име",
@@ -77,7 +77,7 @@
"group": "Групирай селекцията", "group": "Групирай селекцията",
"ungroup": "Спри групирането на селекцията", "ungroup": "Спри групирането на селекцията",
"collaborators": "Сътрудници", "collaborators": "Сътрудници",
"gridMode": "Решетъчен режим", "showGrid": "Показване на мрежа",
"addToLibrary": "Добавяне към библиотеката", "addToLibrary": "Добавяне към библиотеката",
"removeFromLibrary": "Премахване от библиотеката", "removeFromLibrary": "Премахване от библиотеката",
"libraryLoadingMessage": "Зареждане на библиотеката…", "libraryLoadingMessage": "Зареждане на библиотеката…",
@@ -92,7 +92,7 @@
"centerHorizontally": "Центрирай хоризонтално", "centerHorizontally": "Центрирай хоризонтално",
"distributeHorizontally": "Разпредели хоризонтално", "distributeHorizontally": "Разпредели хоризонтално",
"distributeVertically": "Разпредели вертикално", "distributeVertically": "Разпредели вертикално",
"viewMode": "" "viewMode": "Изглед"
}, },
"buttons": { "buttons": {
"clearReset": "Нулиране на платно", "clearReset": "Нулиране на платно",
@@ -117,7 +117,7 @@
"edit": "Редактиране", "edit": "Редактиране",
"undo": "Отмяна", "undo": "Отмяна",
"redo": "Повтори", "redo": "Повтори",
"roomDialog": "Започнете сътрудничество на живо", "resetLibrary": "",
"createNewRoom": "Създай нова стая", "createNewRoom": "Създай нова стая",
"fullScreen": "На цял екран", "fullScreen": "На цял екран",
"darkMode": "Тъмен режим", "darkMode": "Тъмен режим",
@@ -136,11 +136,12 @@
"decryptFailed": "Данните не можаха да се дешифрират.", "decryptFailed": "Данните не можаха да се дешифрират.",
"uploadedSecurly": "Качването е защитено с криптиране от край до край, което означава, че сървърът Excalidraw и трети страни не могат да четат съдържанието.", "uploadedSecurly": "Качването е защитено с криптиране от край до край, което означава, че сървърът Excalidraw и трети страни не могат да четат съдържанието.",
"loadSceneOverridePrompt": "Зареждането на външна рисунка ще презапише настоящото ви съдържание. Желаете ли да продължите?", "loadSceneOverridePrompt": "Зареждането на външна рисунка ще презапише настоящото ви съдържание. Желаете ли да продължите?",
"collabStopOverridePrompt": "", "collabStopOverridePrompt": "Прекратяването на сесията ще презапише предишната, локално запазена, рисунка. Сигурни ли сте?\n\n(Ако искате да продължите с локалната рисунка, просто затворете таба на браузъра.)",
"errorLoadingLibrary": "Възникна грешка при зареждането на външна библиотека.", "errorLoadingLibrary": "Възникна грешка при зареждането на външна библиотека.",
"confirmAddLibrary": "Ще се добавят {{numShapes}} фигура(и) във вашата библиотека. Сигурни ли сте?", "confirmAddLibrary": "Ще се добавят {{numShapes}} фигура(и) във вашата библиотека. Сигурни ли сте?",
"imageDoesNotContainScene": "Импортирането на картинки не се поддържва в момента.\n\nИскате да импортнете сцена? Тази картинка не съдържа данни от сцена. Разрешили ли сте последното при експортирането?", "imageDoesNotContainScene": "Импортирането на картинки не се поддържва в момента.\n\nИскате да импортнете сцена? Тази картинка не съдържа данни от сцена. Разрешили ли сте последното при експортирането?",
"cannotRestoreFromImage": "Не може да бъде възстановена сцена от този файл" "cannotRestoreFromImage": "Не може да бъде възстановена сцена от този файл",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "Селекция", "selection": "Селекция",
@@ -202,24 +203,24 @@
"title": "Грешка" "title": "Грешка"
}, },
"helpDialog": { "helpDialog": {
"blog": "", "blog": "Прочетете нашия блог",
"click": "клик", "click": "клик",
"curvedArrow": "", "curvedArrow": "Извита стрелка",
"curvedLine": "", "curvedLine": "Извита линия",
"documentation": "", "documentation": "Документация",
"drag": "плъзнете", "drag": "плъзнете",
"editor": "Редактор", "editor": "Редактор",
"github": "", "github": "Намерихте проблем? Изпратете",
"howto": "", "howto": "Следвайте нашите ръководства",
"or": "или", "or": "или",
"preventBinding": "", "preventBinding": "Спри прилепяне на стрелките",
"shapes": "Фигури", "shapes": "Фигури",
"shortcuts": "Клавиши за бърз достъп", "shortcuts": "Клавиши за бърз достъп",
"textFinish": "", "textFinish": "Завършете редактирането (текст)",
"textNewLine": "", "textNewLine": "Добавяне на нов ред (текст)",
"title": "", "title": "Помощ",
"view": "Преглед", "view": "Преглед",
"zoomToFit": "", "zoomToFit": "Приближи докато се виждат всички елементи",
"zoomToSelection": "Приближи селекцията" "zoomToSelection": "Приближи селекцията"
}, },
"encrypted": { "encrypted": {
@@ -235,14 +236,16 @@
"storage": "Съхранение на данни", "storage": "Съхранение на данни",
"title": "Статистика за хакери", "title": "Статистика за хакери",
"total": "Общо", "total": "Общо",
"version": "", "version": "Версия",
"versionCopy": "", "versionCopy": "Настисни за да копираш",
"versionNotAvailable": "", "versionNotAvailable": "Версията не е налична",
"width": "Широчина" "width": "Широчина"
}, },
"toast": { "toast": {
"copyStyles": "", "copyStyles": "Копирани стилове.",
"copyToClipboard": "", "copyToClipboard": "Копирано в клипборда.",
"copyToClipboardAsPng": "" "copyToClipboardAsPng": "Копирано в клипборда като PNG.",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "Capes", "layers": "Capes",
"actions": "Accions", "actions": "Accions",
"language": "Llengua", "language": "Llengua",
"createRoom": "Compartir una sessió de col·laboració en directe", "liveCollaboration": "",
"duplicateSelection": "Duplicar", "duplicateSelection": "Duplicar",
"untitled": "Sense títol", "untitled": "Sense títol",
"name": "Nom", "name": "Nom",
@@ -77,7 +77,7 @@
"group": "Agrupar la selecció", "group": "Agrupar la selecció",
"ungroup": "Desagrupar la selecció", "ungroup": "Desagrupar la selecció",
"collaborators": "Col·laboradors", "collaborators": "Col·laboradors",
"gridMode": "Mode quadrícula", "showGrid": "",
"addToLibrary": "Afegir a la biblioteca", "addToLibrary": "Afegir a la biblioteca",
"removeFromLibrary": "Eliminar de la biblioteca", "removeFromLibrary": "Eliminar de la biblioteca",
"libraryLoadingMessage": "Carregant la biblioteca…", "libraryLoadingMessage": "Carregant la biblioteca…",
@@ -117,7 +117,7 @@
"edit": "Editar", "edit": "Editar",
"undo": "Desfer", "undo": "Desfer",
"redo": "Refer", "redo": "Refer",
"roomDialog": "Començar col·laboració en directe", "resetLibrary": "",
"createNewRoom": "Crear sala nova", "createNewRoom": "Crear sala nova",
"fullScreen": "Pantalla completa", "fullScreen": "Pantalla completa",
"darkMode": "Mode fosc", "darkMode": "Mode fosc",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "S'ha produït un error en carregar la biblioteca de tercers.", "errorLoadingLibrary": "S'ha produït un error en carregar la biblioteca de tercers.",
"confirmAddLibrary": "Això afegirà {{numShapes}} forma(es) a la vostra biblioteca. Estàs segur?", "confirmAddLibrary": "Això afegirà {{numShapes}} forma(es) a la vostra biblioteca. Estàs segur?",
"imageDoesNotContainScene": "En aquest moment no sadmet la importació dimatges.\n\nVolies importar una escena? Sembla que aquesta imatge no conté cap dada descena. Ho has activat durant l'exportació?", "imageDoesNotContainScene": "En aquest moment no sadmet la importació dimatges.\n\nVolies importar una escena? Sembla que aquesta imatge no conté cap dada descena. Ho has activat durant l'exportació?",
"cannotRestoreFromImage": "Lescena no sha pogut restaurar des daquest fitxer dimatge" "cannotRestoreFromImage": "Lescena no sha pogut restaurar des daquest fitxer dimatge",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "Selecció", "selection": "Selecció",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "", "copyStyles": "",
"copyToClipboard": "", "copyToClipboard": "",
"copyToClipboardAsPng": "" "copyToClipboardAsPng": "",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+14 -11
View File
@@ -68,7 +68,7 @@
"layers": "Ebenen", "layers": "Ebenen",
"actions": "Aktionen", "actions": "Aktionen",
"language": "Sprache", "language": "Sprache",
"createRoom": "Live-Kollaborationssitzung teilen", "liveCollaboration": "Live-Zusammenarbeit",
"duplicateSelection": "Duplizieren", "duplicateSelection": "Duplizieren",
"untitled": "Unbenannt", "untitled": "Unbenannt",
"name": "Name", "name": "Name",
@@ -76,8 +76,8 @@
"madeWithExcalidraw": "Made with Excalidraw", "madeWithExcalidraw": "Made with Excalidraw",
"group": "Auswahl gruppieren", "group": "Auswahl gruppieren",
"ungroup": "Gruppierung aufheben", "ungroup": "Gruppierung aufheben",
"collaborators": "Mitarbeitende", "collaborators": "Kollaboratoren",
"gridMode": "Rastermodus", "showGrid": "Raster anzeigen",
"addToLibrary": "Zur Bibliothek hinzufügen", "addToLibrary": "Zur Bibliothek hinzufügen",
"removeFromLibrary": "Aus Bibliothek entfernen", "removeFromLibrary": "Aus Bibliothek entfernen",
"libraryLoadingMessage": "Lade Bibliothek…", "libraryLoadingMessage": "Lade Bibliothek…",
@@ -101,7 +101,7 @@
"exportToSvg": "Als SVG exportieren", "exportToSvg": "Als SVG exportieren",
"copyToClipboard": "In Zwischenablage kopieren", "copyToClipboard": "In Zwischenablage kopieren",
"copyPngToClipboard": "PNG in die Zwischenablage kopieren", "copyPngToClipboard": "PNG in die Zwischenablage kopieren",
"scale": "Skalieren", "scale": "Skalierung",
"save": "Speichern", "save": "Speichern",
"saveAs": "Speichern unter", "saveAs": "Speichern unter",
"load": "Laden", "load": "Laden",
@@ -117,7 +117,7 @@
"edit": "Bearbeiten", "edit": "Bearbeiten",
"undo": "Rückgängig machen", "undo": "Rückgängig machen",
"redo": "Wiederholen", "redo": "Wiederholen",
"roomDialog": "Live-Kollaborationssitzung starten", "resetLibrary": "Bibliothek zurücksetzen",
"createNewRoom": "Neuen Raum erstellen", "createNewRoom": "Neuen Raum erstellen",
"fullScreen": "Vollbildanzeige", "fullScreen": "Vollbildanzeige",
"darkMode": "Dunkles Design", "darkMode": "Dunkles Design",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Beim Laden der Drittanbieter-Bibliothek ist ein Fehler aufgetreten.", "errorLoadingLibrary": "Beim Laden der Drittanbieter-Bibliothek ist ein Fehler aufgetreten.",
"confirmAddLibrary": "Dieses fügt {{numShapes}} Form(en) zu deiner Bibliothek hinzu. Bist du sicher?", "confirmAddLibrary": "Dieses fügt {{numShapes}} Form(en) zu deiner Bibliothek hinzu. Bist du sicher?",
"imageDoesNotContainScene": "Das Importieren von Bildern wird derzeit nicht unterstützt.\n\nMöchtest du eine Szene importieren? Dieses Bild scheint keine Zeichnungsdaten zu enthalten. Hast du dies beim Exportieren aktiviert?", "imageDoesNotContainScene": "Das Importieren von Bildern wird derzeit nicht unterstützt.\n\nMöchtest du eine Szene importieren? Dieses Bild scheint keine Zeichnungsdaten zu enthalten. Hast du dies beim Exportieren aktiviert?",
"cannotRestoreFromImage": "Die Zeichnung konnte aus dieser Bilddatei nicht wiederhergestellt werden" "cannotRestoreFromImage": "Die Zeichnung konnte aus dieser Bilddatei nicht wiederhergestellt werden",
"resetLibrary": "Dieses löscht deine Bibliothek. Bist du sicher?"
}, },
"toolBar": { "toolBar": {
"selection": "Auswahl", "selection": "Auswahl",
@@ -235,14 +236,16 @@
"storage": "Speicher", "storage": "Speicher",
"title": "Statistiken für Nerds", "title": "Statistiken für Nerds",
"total": "Gesamt", "total": "Gesamt",
"version": "", "version": "Version",
"versionCopy": "", "versionCopy": "Zum Kopieren klicken",
"versionNotAvailable": "", "versionNotAvailable": "Version nicht verfügbar",
"width": "Breite" "width": "Breite"
}, },
"toast": { "toast": {
"copyStyles": "Formatierung kopiert.", "copyStyles": "Formatierung kopiert.",
"copyToClipboard": "", "copyToClipboard": "In die Zwischenablage kopiert.",
"copyToClipboardAsPng": "In die Zwischenablage als PNG kopiert." "copyToClipboardAsPng": "In die Zwischenablage als PNG kopiert.",
"fileSaved": "Datei gespeichert.",
"fileSavedToFilename": "Als {filename} gespeichert"
} }
} }
+14 -11
View File
@@ -68,7 +68,7 @@
"layers": "Στρώματα", "layers": "Στρώματα",
"actions": "Ενέργειες", "actions": "Ενέργειες",
"language": "Γλώσσα", "language": "Γλώσσα",
"createRoom": "Έναρξη ζωντανής συνεδρίας", "liveCollaboration": "Ζωντανή συνεργασία",
"duplicateSelection": "Δημιουργία αντιγράφου", "duplicateSelection": "Δημιουργία αντιγράφου",
"untitled": "Χωρίς τίτλο", "untitled": "Χωρίς τίτλο",
"name": "Όνομα", "name": "Όνομα",
@@ -77,7 +77,7 @@
"group": "Δημιουργία ομάδας από επιλογή", "group": "Δημιουργία ομάδας από επιλογή",
"ungroup": "Κατάργηση ομάδας από επιλογή", "ungroup": "Κατάργηση ομάδας από επιλογή",
"collaborators": "Συνεργάτες", "collaborators": "Συνεργάτες",
"gridMode": "Εμφάνιση σε πλέγμα", "showGrid": "Προβολή πλέγματος",
"addToLibrary": "Προσθήκη στη βιβλιοθήκη", "addToLibrary": "Προσθήκη στη βιβλιοθήκη",
"removeFromLibrary": "Αφαίρεση από τη βιβλιοθήκη", "removeFromLibrary": "Αφαίρεση από τη βιβλιοθήκη",
"libraryLoadingMessage": "Φόρτωση βιβλιοθήκης…", "libraryLoadingMessage": "Φόρτωση βιβλιοθήκης…",
@@ -117,13 +117,13 @@
"edit": "Επεξεργασία", "edit": "Επεξεργασία",
"undo": "Αναίρεση", "undo": "Αναίρεση",
"redo": "Επαναφορά", "redo": "Επαναφορά",
"roomDialog": "Έναρξη ζωντανής συνεργασίας", "resetLibrary": "Καθαρισμός βιβλιοθήκης",
"createNewRoom": "Δημιουργία νέου χώρου", "createNewRoom": "Δημιουργία νέου χώρου",
"fullScreen": "Πλήρης οθόνη", "fullScreen": "Πλήρης οθόνη",
"darkMode": "Σκοτεινή λειτουργία", "darkMode": "Σκοτεινή λειτουργία",
"lightMode": "Φωτεινή λειτουργία", "lightMode": "Φωτεινή λειτουργία",
"zenMode": "Λειτουργία Zεν", "zenMode": "Λειτουργία Zεν",
"exitZenMode": "Έξοδος απο την λειτουργία Zen" "exitZenMode": "Έξοδος από την λειτουργία Zen"
}, },
"alerts": { "alerts": {
"clearReset": "Αυτό θα σβήσει ολόκληρο τον καμβά. Είσαι σίγουρος;", "clearReset": "Αυτό θα σβήσει ολόκληρο τον καμβά. Είσαι σίγουρος;",
@@ -136,11 +136,12 @@
"decryptFailed": "Δεν ήταν δυνατή η αποκρυπτογράφηση δεδομένων.", "decryptFailed": "Δεν ήταν δυνατή η αποκρυπτογράφηση δεδομένων.",
"uploadedSecurly": "Η μεταφόρτωση έχει εξασφαλιστεί με κρυπτογράφηση από άκρο σε άκρο, πράγμα που σημαίνει ότι ο διακομιστής Excalidraw και τρίτα μέρη δεν μπορούν να διαβάσουν το περιεχόμενο.", "uploadedSecurly": "Η μεταφόρτωση έχει εξασφαλιστεί με κρυπτογράφηση από άκρο σε άκρο, πράγμα που σημαίνει ότι ο διακομιστής Excalidraw και τρίτα μέρη δεν μπορούν να διαβάσουν το περιεχόμενο.",
"loadSceneOverridePrompt": "Η φόρτωση εξωτερικού σχεδίου θα αντικαταστήσει το υπάρχον περιεχόμενο. Επιθυμείτε να συνεχίσετε;", "loadSceneOverridePrompt": "Η φόρτωση εξωτερικού σχεδίου θα αντικαταστήσει το υπάρχον περιεχόμενο. Επιθυμείτε να συνεχίσετε;",
"collabStopOverridePrompt": "", "collabStopOverridePrompt": "Η διακοπή της συνεδρίας θα αντικαταστήσει το προηγούμενο, τοπικά αποθηκευμένο σχέδιο. Είστε σίγουροι?\n\n(Αν θέλετε να διατηρήσετε το τοπικό σας σχέδιο, απλά κλείστε την καρτέλα του προγράμματος περιήγησης.)",
"errorLoadingLibrary": "Υπήρξε ένα σφάλμα κατά τη φόρτωση της βιβλιοθήκης τρίτου μέρους.", "errorLoadingLibrary": "Υπήρξε ένα σφάλμα κατά τη φόρτωση της βιβλιοθήκης τρίτου μέρους.",
"confirmAddLibrary": "Αυτό θα προσθέσει {{numShapes}} σχήμα(τα) στη βιβιλιοθήκη σας. Είστε σίγουροι;", "confirmAddLibrary": "Αυτό θα προσθέσει {{numShapes}} σχήμα(τα) στη βιβλιοθήκη σας. Είστε σίγουροι;",
"imageDoesNotContainScene": "Η εισαγωγή εικόνων δεν υποστηρίζεται αυτή τη στιγμή.\n\nΜήπως θέλετε να εισαγάγετε μια σκηνή; Αυτή η εικόνα δεν φαίνεται να περιέχει δεδομένα σκηνής. Έχετε ενεργοποιήσει αυτό κατά την εξαγωγή;", "imageDoesNotContainScene": "Η εισαγωγή εικόνων δεν υποστηρίζεται αυτή τη στιγμή.\n\nΜήπως θέλετε να εισαγάγετε μια σκηνή; Αυτή η εικόνα δεν φαίνεται να περιέχει δεδομένα σκηνής. Έχετε ενεργοποιήσει αυτό κατά την εξαγωγή;",
"cannotRestoreFromImage": "Η σκηνή δεν ήταν δυνατό να αποκατασταθεί από αυτό το αρχείο εικόνας" "cannotRestoreFromImage": "Η σκηνή δεν ήταν δυνατό να αποκατασταθεί από αυτό το αρχείο εικόνας",
"resetLibrary": "Αυτό θα καθαρίσει τη βιβλιοθήκη σας. Είστε σίγουροι;"
}, },
"toolBar": { "toolBar": {
"selection": "Επιλογή", "selection": "Επιλογή",
@@ -161,7 +162,7 @@
}, },
"hints": { "hints": {
"linearElement": "Κάνε κλικ για να ξεκινήσεις πολλαπλά σημεία, σύρε για μια γραμμή", "linearElement": "Κάνε κλικ για να ξεκινήσεις πολλαπλά σημεία, σύρε για μια γραμμή",
"freeDraw": "Κάντε κλικ και σύρατε, απελευθερώσατε όταν έχετε τελειώσει", "freeDraw": "Κάντε κλικ και σύρτε, απελευθερώσατε όταν έχετε τελειώσει",
"text": "Tip: μπορείτε επίσης να προσθέστε κείμενο με διπλό-κλικ οπουδήποτε με το εργαλείο επιλογών", "text": "Tip: μπορείτε επίσης να προσθέστε κείμενο με διπλό-κλικ οπουδήποτε με το εργαλείο επιλογών",
"linearElementMulti": "Κάνε κλικ στο τελευταίο σημείο ή πάτησε Escape ή Enter για να τελειώσεις", "linearElementMulti": "Κάνε κλικ στο τελευταίο σημείο ή πάτησε Escape ή Enter για να τελειώσεις",
"lockAngle": "Μπορείτε να περιορίσετε τη γωνία κρατώντας πατημένο το SHIFT", "lockAngle": "Μπορείτε να περιορίσετε τη γωνία κρατώντας πατημένο το SHIFT",
@@ -184,7 +185,7 @@
"clearCanvasCaveat": " Αυτό θα προκαλέσει απώλεια της δουλειάς σου ", "clearCanvasCaveat": " Αυτό θα προκαλέσει απώλεια της δουλειάς σου ",
"trackedToSentry_pre": "Το σφάλμα με αναγνωριστικό ", "trackedToSentry_pre": "Το σφάλμα με αναγνωριστικό ",
"trackedToSentry_post": " παρακολουθήθηκε στο σύστημά μας.", "trackedToSentry_post": " παρακολουθήθηκε στο σύστημά μας.",
"openIssueMessage_pre": "Ήμασταν πολύ προσεκτικοί για να μην συμπεριλάβουμε τις πληροφορίες της σκηνής σου στο σφάλμα. Αν η σκηνή σου δεν είναι ιδιωτική, παρακαλώ σκέψουν να ακολουθήσεις το δικό μας ", "openIssueMessage_pre": "Ήμασταν πολύ προσεκτικοί για να μην συμπεριλάβουμε τις πληροφορίες της σκηνής σου στο σφάλμα. Αν η σκηνή σου δεν είναι ιδιωτική, παρακαλώ σκέψου να ακολουθήσεις το δικό μας ",
"openIssueMessage_button": "ανιχνευτής σφαλμάτων.", "openIssueMessage_button": "ανιχνευτής σφαλμάτων.",
"openIssueMessage_post": " Παρακαλώ να συμπεριλάβετε τις παρακάτω πληροφορίες, αντιγράφοντας και επικολλώντας το ζήτημα στο GitHub.", "openIssueMessage_post": " Παρακαλώ να συμπεριλάβετε τις παρακάτω πληροφορίες, αντιγράφοντας και επικολλώντας το ζήτημα στο GitHub.",
"sceneContent": "Περιεχόμενο σκηνής:" "sceneContent": "Περιεχόμενο σκηνής:"
@@ -223,7 +224,7 @@
"zoomToSelection": "Ζουμ στην επιλογή" "zoomToSelection": "Ζουμ στην επιλογή"
}, },
"encrypted": { "encrypted": {
"tooltip": "Τα σχέδιά σου είναι κρυπτογραφημένα από άκρο σε άκρο, έτσι δεν θα έιναι ποτέ ορατά μέσα από τους διακομιστές του Excalidraw." "tooltip": "Τα σχέδιά σου είναι κρυπτογραφημένα από άκρο σε άκρο, έτσι δεν θα είναι ποτέ ορατά μέσα από τους διακομιστές του Excalidraw."
}, },
"stats": { "stats": {
"angle": "Γωνία", "angle": "Γωνία",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "Αντιγράφηκαν στυλ.", "copyStyles": "Αντιγράφηκαν στυλ.",
"copyToClipboard": "Αντιγράφηκε στο πρόχειρο.", "copyToClipboard": "Αντιγράφηκε στο πρόχειρο.",
"copyToClipboardAsPng": "Αντιγράφτηκε στο πρόχειρο ως PNG." "copyToClipboardAsPng": "Αντιγράφτηκε στο πρόχειρο ως PNG.",
"fileSaved": "Το αρχείο αποθηκεύτηκε.",
"fileSavedToFilename": "Αποθηκεύτηκε στο {filename}"
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "Layers", "layers": "Layers",
"actions": "Actions", "actions": "Actions",
"language": "Language", "language": "Language",
"createRoom": "Share a live-collaboration session", "liveCollaboration": "Live collaboration",
"duplicateSelection": "Duplicate", "duplicateSelection": "Duplicate",
"untitled": "Untitled", "untitled": "Untitled",
"name": "Name", "name": "Name",
@@ -77,7 +77,7 @@
"group": "Group selection", "group": "Group selection",
"ungroup": "Ungroup selection", "ungroup": "Ungroup selection",
"collaborators": "Collaborators", "collaborators": "Collaborators",
"gridMode": "Grid mode", "showGrid": "Show grid",
"addToLibrary": "Add to library", "addToLibrary": "Add to library",
"removeFromLibrary": "Remove from library", "removeFromLibrary": "Remove from library",
"libraryLoadingMessage": "Loading library…", "libraryLoadingMessage": "Loading library…",
@@ -117,7 +117,7 @@
"edit": "Edit", "edit": "Edit",
"undo": "Undo", "undo": "Undo",
"redo": "Redo", "redo": "Redo",
"roomDialog": "Start live collaboration", "resetLibrary": "Reset library",
"createNewRoom": "Create new room", "createNewRoom": "Create new room",
"fullScreen": "Full screen", "fullScreen": "Full screen",
"darkMode": "Dark mode", "darkMode": "Dark mode",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "There was an error loading the third party library.", "errorLoadingLibrary": "There was an error loading the third party library.",
"confirmAddLibrary": "This will add {{numShapes}} shape(s) to your library. Are you sure?", "confirmAddLibrary": "This will add {{numShapes}} shape(s) to your library. Are you sure?",
"imageDoesNotContainScene": "Importing images isn't supported at the moment.\n\nDid you want to import a scene? This image does not seem to contain any scene data. Have you enabled this during export?", "imageDoesNotContainScene": "Importing images isn't supported at the moment.\n\nDid you want to import a scene? This image does not seem to contain any scene data. Have you enabled this during export?",
"cannotRestoreFromImage": "Scene couldn't be restored from this image file" "cannotRestoreFromImage": "Scene couldn't be restored from this image file",
"resetLibrary": "This will clear your library. Are you sure?"
}, },
"toolBar": { "toolBar": {
"selection": "Selection", "selection": "Selection",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "Copied styles.", "copyStyles": "Copied styles.",
"copyToClipboard": "Copied to clipboard.", "copyToClipboard": "Copied to clipboard.",
"copyToClipboardAsPng": "Copied to clipboard as PNG." "copyToClipboardAsPng": "Copied to clipboard as PNG.",
"fileSaved": "File saved.",
"fileSavedToFilename": "Saved to {filename}"
} }
} }
+13 -10
View File
@@ -68,7 +68,7 @@
"layers": "Capas", "layers": "Capas",
"actions": "Acciones", "actions": "Acciones",
"language": "Idioma", "language": "Idioma",
"createRoom": "Compartir una sesión de colaboración en vivo", "liveCollaboration": "Colaboración en directo",
"duplicateSelection": "Duplicar", "duplicateSelection": "Duplicar",
"untitled": "Sin título", "untitled": "Sin título",
"name": "Nombre", "name": "Nombre",
@@ -77,10 +77,10 @@
"group": "Agrupar selección", "group": "Agrupar selección",
"ungroup": "Desagrupar selección", "ungroup": "Desagrupar selección",
"collaborators": "Colaboradores", "collaborators": "Colaboradores",
"gridMode": "Modo cuadrícula", "showGrid": "Mostrar cuadrícula",
"addToLibrary": "Añadir a la biblioteca", "addToLibrary": "Añadir a la biblioteca",
"removeFromLibrary": "Eliminar de la biblioteca", "removeFromLibrary": "Eliminar de la biblioteca",
"libraryLoadingMessage": "Cargando biblioteca…", "libraryLoadingMessage": "Cargando librería…",
"libraries": "Explorar bibliotecas", "libraries": "Explorar bibliotecas",
"loadingScene": "Cargando escena…", "loadingScene": "Cargando escena…",
"align": "Alinear", "align": "Alinear",
@@ -117,7 +117,7 @@
"edit": "Editar", "edit": "Editar",
"undo": "Deshacer", "undo": "Deshacer",
"redo": "Rehacer", "redo": "Rehacer",
"roomDialog": "Iniciar colaboración en vivo", "resetLibrary": "Resetear librería",
"createNewRoom": "Crear nueva sala", "createNewRoom": "Crear nueva sala",
"fullScreen": "Pantalla completa", "fullScreen": "Pantalla completa",
"darkMode": "Modo oscuro", "darkMode": "Modo oscuro",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Se ha producido un error al cargar la biblioteca de terceros.", "errorLoadingLibrary": "Se ha producido un error al cargar la biblioteca de terceros.",
"confirmAddLibrary": "Esto añadirá {{numShapes}} forma(s) a tu biblioteca. ¿Estás seguro?", "confirmAddLibrary": "Esto añadirá {{numShapes}} forma(s) a tu biblioteca. ¿Estás seguro?",
"imageDoesNotContainScene": "La importación de imágenes no está homologada en este momento.\n\n¿Deseas importar una escena? Esta imagen no parece contener ningún dato de escena. ¿Lo has activado durante la exportación?", "imageDoesNotContainScene": "La importación de imágenes no está homologada en este momento.\n\n¿Deseas importar una escena? Esta imagen no parece contener ningún dato de escena. ¿Lo has activado durante la exportación?",
"cannotRestoreFromImage": "No se pudo restaurar la escena desde este archivo de imagen" "cannotRestoreFromImage": "No se pudo restaurar la escena desde este archivo de imagen",
"resetLibrary": "Esto eliminará tu librería. ¿Estás seguro?"
}, },
"toolBar": { "toolBar": {
"selection": "Selección", "selection": "Selección",
@@ -235,14 +236,16 @@
"storage": "Almacenamiento", "storage": "Almacenamiento",
"title": "Estadísticas para nerds", "title": "Estadísticas para nerds",
"total": "Total", "total": "Total",
"version": "", "version": "Versión",
"versionCopy": "", "versionCopy": "Clic para copiar",
"versionNotAvailable": "", "versionNotAvailable": "Versión no disponible",
"width": "Ancho" "width": "Ancho"
}, },
"toast": { "toast": {
"copyStyles": "Estilos copiados.", "copyStyles": "Estilos copiados.",
"copyToClipboard": "", "copyToClipboard": "Copiado en el portapapeles.",
"copyToClipboardAsPng": "Copiado al portapapeles como PNG." "copyToClipboardAsPng": "Copiado al portapapeles como PNG.",
"fileSaved": "Archivo guardado.",
"fileSavedToFilename": "Guardado en {filename}"
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "لایه ها", "layers": "لایه ها",
"actions": "عملیات", "actions": "عملیات",
"language": "زبان", "language": "زبان",
"createRoom": "اشتراک گذاری جلسه همکاری زنده", "liveCollaboration": "",
"duplicateSelection": "تکرار", "duplicateSelection": "تکرار",
"untitled": "بدون عنوان", "untitled": "بدون عنوان",
"name": "نام", "name": "نام",
@@ -77,7 +77,7 @@
"group": "گروهبندی انتخابها", "group": "گروهبندی انتخابها",
"ungroup": "حذف گروهبندی انتخابها", "ungroup": "حذف گروهبندی انتخابها",
"collaborators": "همکاران", "collaborators": "همکاران",
"gridMode": "حالت شبکه ای", "showGrid": "",
"addToLibrary": "افزودن به کتابخانه", "addToLibrary": "افزودن به کتابخانه",
"removeFromLibrary": "حذف از کتابخانه", "removeFromLibrary": "حذف از کتابخانه",
"libraryLoadingMessage": "بارگذاری کتابخانه…", "libraryLoadingMessage": "بارگذاری کتابخانه…",
@@ -117,7 +117,7 @@
"edit": "ویرایش", "edit": "ویرایش",
"undo": "بازگرد", "undo": "بازگرد",
"redo": "از سر", "redo": "از سر",
"roomDialog": "همکاری آنلاین را شروع کنید", "resetLibrary": "",
"createNewRoom": "ایجاد یک اتاق جدید", "createNewRoom": "ایجاد یک اتاق جدید",
"fullScreen": "تمام‌صفحه", "fullScreen": "تمام‌صفحه",
"darkMode": "حالت تیره", "darkMode": "حالت تیره",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "خطایی در بارگذاری کتابخانه ثالث وجود داشت.", "errorLoadingLibrary": "خطایی در بارگذاری کتابخانه ثالث وجود داشت.",
"confirmAddLibrary": "{{numShapes}} از اشکال به کتابخانه شما اضافه خواهد شد. مطمئن هستید؟", "confirmAddLibrary": "{{numShapes}} از اشکال به کتابخانه شما اضافه خواهد شد. مطمئن هستید؟",
"imageDoesNotContainScene": "وارد کردن تصویر در این لحظه امکان پذیر نمی باشد.\nآیا مایل به وارد کردن یک صحنه هستید؟ این تصویر به نظر می رسد که فاقد هرگونه اطلاعاتی مربوط به صحنه باشد. آیا این گزینه را در زمان وارد کردن تصویر فعال کرده اید؟", "imageDoesNotContainScene": "وارد کردن تصویر در این لحظه امکان پذیر نمی باشد.\nآیا مایل به وارد کردن یک صحنه هستید؟ این تصویر به نظر می رسد که فاقد هرگونه اطلاعاتی مربوط به صحنه باشد. آیا این گزینه را در زمان وارد کردن تصویر فعال کرده اید؟",
"cannotRestoreFromImage": "صحنه را نمی توان از این فایل تصویری بازیابی کرد" "cannotRestoreFromImage": "صحنه را نمی توان از این فایل تصویری بازیابی کرد",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "گزینش", "selection": "گزینش",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "کپی سبک.", "copyStyles": "کپی سبک.",
"copyToClipboard": "", "copyToClipboard": "",
"copyToClipboardAsPng": "کپی در حافطه موقت به صورت PNG." "copyToClipboardAsPng": "کپی در حافطه موقت به صورت PNG.",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+12 -9
View File
@@ -68,7 +68,7 @@
"layers": "Tasot", "layers": "Tasot",
"actions": "Toiminnot", "actions": "Toiminnot",
"language": "Kieli", "language": "Kieli",
"createRoom": "Jaa yhteistyöistunto", "liveCollaboration": "Live-yhteistyö",
"duplicateSelection": "Monista", "duplicateSelection": "Monista",
"untitled": "Nimetön", "untitled": "Nimetön",
"name": "Nimi", "name": "Nimi",
@@ -77,7 +77,7 @@
"group": "Ryhmitä valinta", "group": "Ryhmitä valinta",
"ungroup": "Pura valittu ryhmä", "ungroup": "Pura valittu ryhmä",
"collaborators": "Yhteistyökumppanit", "collaborators": "Yhteistyökumppanit",
"gridMode": "Ruudukkotila", "showGrid": "Näytä ruudukko",
"addToLibrary": "Lisää kirjastoon", "addToLibrary": "Lisää kirjastoon",
"removeFromLibrary": "Poista kirjastosta", "removeFromLibrary": "Poista kirjastosta",
"libraryLoadingMessage": "Ladataan kirjastoa…", "libraryLoadingMessage": "Ladataan kirjastoa…",
@@ -117,7 +117,7 @@
"edit": "Muokkaa", "edit": "Muokkaa",
"undo": "Kumoa", "undo": "Kumoa",
"redo": "Tee uudelleen", "redo": "Tee uudelleen",
"roomDialog": "Aloita live-yhteistyö", "resetLibrary": "Tyhjennä kirjasto",
"createNewRoom": "Luo huone", "createNewRoom": "Luo huone",
"fullScreen": "Koko näyttö", "fullScreen": "Koko näyttö",
"darkMode": "Tumma tila", "darkMode": "Tumma tila",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Kolmannen osapuolen kirjastoa ladattaessa tapahtui virhe.", "errorLoadingLibrary": "Kolmannen osapuolen kirjastoa ladattaessa tapahtui virhe.",
"confirmAddLibrary": "Tämä lisää {{numShapes}} muotoa kirjastoosi. Oletko varma?", "confirmAddLibrary": "Tämä lisää {{numShapes}} muotoa kirjastoosi. Oletko varma?",
"imageDoesNotContainScene": "Kuvien lisääminen ei ole tällä hetkellä mahdollista.\n\nHaluatko tuoda piirroksen? Tämä kuva ei näytä sisältävän tarvittavia tietoja. Oletko ottanut piirrostietojen tallennuksen käyttöön viennin aikana?", "imageDoesNotContainScene": "Kuvien lisääminen ei ole tällä hetkellä mahdollista.\n\nHaluatko tuoda piirroksen? Tämä kuva ei näytä sisältävän tarvittavia tietoja. Oletko ottanut piirrostietojen tallennuksen käyttöön viennin aikana?",
"cannotRestoreFromImage": "Teosta ei voitu palauttaa tästä kuvatiedostosta" "cannotRestoreFromImage": "Teosta ei voitu palauttaa tästä kuvatiedostosta",
"resetLibrary": "Tämä tyhjentää kirjastosi. Oletko varma?"
}, },
"toolBar": { "toolBar": {
"selection": "Valinta", "selection": "Valinta",
@@ -235,14 +236,16 @@
"storage": "Tallennustila", "storage": "Tallennustila",
"title": "Nörttien tilastot", "title": "Nörttien tilastot",
"total": "Yhteensä", "total": "Yhteensä",
"version": "", "version": "Versio",
"versionCopy": "", "versionCopy": "Klikkaa kopioidaksesi",
"versionNotAvailable": "", "versionNotAvailable": "Versio ei saatavilla",
"width": "Leveys" "width": "Leveys"
}, },
"toast": { "toast": {
"copyStyles": "Tyylit kopioitu.", "copyStyles": "Tyylit kopioitu.",
"copyToClipboard": "", "copyToClipboard": "Kopioitu leikepöydälle.",
"copyToClipboardAsPng": "Kopioitu leikepöydälle PNG-tiedostona." "copyToClipboardAsPng": "Kopioitu leikepöydälle PNG-tiedostona.",
"fileSaved": "Tiedosto tallennettu.",
"fileSavedToFilename": "Tallennettu kohteeseen {filename}"
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "Calques", "layers": "Calques",
"actions": "Actions", "actions": "Actions",
"language": "Langue", "language": "Langue",
"createRoom": "Partager une session de collaboration en direct", "liveCollaboration": "Collaboration en direct",
"duplicateSelection": "Dupliquer", "duplicateSelection": "Dupliquer",
"untitled": "Sans-titre", "untitled": "Sans-titre",
"name": "Nom", "name": "Nom",
@@ -77,7 +77,7 @@
"group": "Grouper la sélection", "group": "Grouper la sélection",
"ungroup": "Dégrouper la sélection", "ungroup": "Dégrouper la sélection",
"collaborators": "Collaborateurs", "collaborators": "Collaborateurs",
"gridMode": "Mode grille", "showGrid": "Afficher la grille",
"addToLibrary": "Ajouter à la bibliothèque", "addToLibrary": "Ajouter à la bibliothèque",
"removeFromLibrary": "Supprimer de la bibliothèque", "removeFromLibrary": "Supprimer de la bibliothèque",
"libraryLoadingMessage": "Chargement de la bibliothèque…", "libraryLoadingMessage": "Chargement de la bibliothèque…",
@@ -117,7 +117,7 @@
"edit": "Modifier", "edit": "Modifier",
"undo": "Annuler", "undo": "Annuler",
"redo": "Rétablir", "redo": "Rétablir",
"roomDialog": "Démarrer la collaboration en direct", "resetLibrary": "Réinitialiser la bibliothèque",
"createNewRoom": "Créer une nouvelle salle", "createNewRoom": "Créer une nouvelle salle",
"fullScreen": "Plein écran", "fullScreen": "Plein écran",
"darkMode": "Mode sombre", "darkMode": "Mode sombre",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Une erreur s'est produite lors du chargement de la bibliothèque tierce.", "errorLoadingLibrary": "Une erreur s'est produite lors du chargement de la bibliothèque tierce.",
"confirmAddLibrary": "Cela va ajouter {{numShapes}} forme(s) à votre bibliothèque. Êtes-vous sûr·e ?", "confirmAddLibrary": "Cela va ajouter {{numShapes}} forme(s) à votre bibliothèque. Êtes-vous sûr·e ?",
"imageDoesNotContainScene": "L'importation d'images n'est pas prise en charge pour le moment.\n\nVouliez-vous importer une scène ? Cette image ne semble pas contenir de données de scène. Avez-vous activé cette option lors de l'exportation ?", "imageDoesNotContainScene": "L'importation d'images n'est pas prise en charge pour le moment.\n\nVouliez-vous importer une scène ? Cette image ne semble pas contenir de données de scène. Avez-vous activé cette option lors de l'exportation ?",
"cannotRestoreFromImage": "Impossible de restaurer la scène depuis ce fichier image" "cannotRestoreFromImage": "Impossible de restaurer la scène depuis ce fichier image",
"resetLibrary": "Cela va effacer votre bibliothèque. Êtes-vous sûr·e ?"
}, },
"toolBar": { "toolBar": {
"selection": "Sélection", "selection": "Sélection",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "Styles copiés.", "copyStyles": "Styles copiés.",
"copyToClipboard": "Copié vers le presse-papiers.", "copyToClipboard": "Copié vers le presse-papiers.",
"copyToClipboardAsPng": "Copié vers le presse-papier en PNG." "copyToClipboardAsPng": "Copié vers le presse-papier en PNG.",
"fileSaved": "Fichier enregistré.",
"fileSavedToFilename": "Enregistré sous {filename}"
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "שכבות", "layers": "שכבות",
"actions": "פעולות", "actions": "פעולות",
"language": "שפה", "language": "שפה",
"createRoom": "התחל שיתוף פעולה חי", "liveCollaboration": "",
"duplicateSelection": "שכפל", "duplicateSelection": "שכפל",
"untitled": "ללא כותרת", "untitled": "ללא כותרת",
"name": "שם", "name": "שם",
@@ -77,7 +77,7 @@
"group": "אחד לקבוצה", "group": "אחד לקבוצה",
"ungroup": "פרק קבוצה", "ungroup": "פרק קבוצה",
"collaborators": "שותפים", "collaborators": "שותפים",
"gridMode": "מצב רשת", "showGrid": "",
"addToLibrary": "הוסף לספריה", "addToLibrary": "הוסף לספריה",
"removeFromLibrary": "הסר מספריה", "removeFromLibrary": "הסר מספריה",
"libraryLoadingMessage": "טוען ספריה…", "libraryLoadingMessage": "טוען ספריה…",
@@ -117,7 +117,7 @@
"edit": "ערוך", "edit": "ערוך",
"undo": "בטל", "undo": "בטל",
"redo": "בצע מחדש", "redo": "בצע מחדש",
"roomDialog": "התחל שיתוף חי", "resetLibrary": "",
"createNewRoom": "צור חדר", "createNewRoom": "צור חדר",
"fullScreen": "מסך מלא", "fullScreen": "מסך מלא",
"darkMode": "מצב כהה", "darkMode": "מצב כהה",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "קרתה שגיאה בטעינת הספריה החיצונית.", "errorLoadingLibrary": "קרתה שגיאה בטעינת הספריה החיצונית.",
"confirmAddLibrary": "הפעולה תוסיף {{numShapes}} צורה(ות) לספריה שלך. האם אתה בטוח?", "confirmAddLibrary": "הפעולה תוסיף {{numShapes}} צורה(ות) לספריה שלך. האם אתה בטוח?",
"imageDoesNotContainScene": "אין תמיכה בייבוא תמונות כעת.\n\nהאם אתה רוצה לייבא תצוגה? התמונה הזאת אינה מכילה מידע על תצוגה. האם הפעלת את האפשרות הזאת בזמן הוצאת המידע?", "imageDoesNotContainScene": "אין תמיכה בייבוא תמונות כעת.\n\nהאם אתה רוצה לייבא תצוגה? התמונה הזאת אינה מכילה מידע על תצוגה. האם הפעלת את האפשרות הזאת בזמן הוצאת המידע?",
"cannotRestoreFromImage": "לא הצלחנו לשחזר את התצוגה מקובץ התמונה" "cannotRestoreFromImage": "לא הצלחנו לשחזר את התצוגה מקובץ התמונה",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "בחירה", "selection": "בחירה",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "", "copyStyles": "",
"copyToClipboard": "", "copyToClipboard": "",
"copyToClipboardAsPng": "" "copyToClipboardAsPng": "",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "परतें", "layers": "परतें",
"actions": "कार्रवाई", "actions": "कार्रवाई",
"language": "भाषा", "language": "भाषा",
"createRoom": "अधिवेशन", "liveCollaboration": "",
"duplicateSelection": "डुप्लिकेट", "duplicateSelection": "डुप्लिकेट",
"untitled": "अशीर्षित", "untitled": "अशीर्षित",
"name": "नाम", "name": "नाम",
@@ -77,7 +77,7 @@
"group": "समूह चयन", "group": "समूह चयन",
"ungroup": "समूह चयन असमूहीकृत करें", "ungroup": "समूह चयन असमूहीकृत करें",
"collaborators": "सहयोगी", "collaborators": "सहयोगी",
"gridMode": "ग्रिड मॉड", "showGrid": "",
"addToLibrary": "लाइब्रेरी से जोड़ें", "addToLibrary": "लाइब्रेरी से जोड़ें",
"removeFromLibrary": "लाइब्रेरी से निकालें", "removeFromLibrary": "लाइब्रेरी से निकालें",
"libraryLoadingMessage": "लाइब्रेरी खुल रही है", "libraryLoadingMessage": "लाइब्रेरी खुल रही है",
@@ -117,7 +117,7 @@
"edit": "संशोधन करें", "edit": "संशोधन करें",
"undo": "पूर्ववत् करें", "undo": "पूर्ववत् करें",
"redo": "फिर से करें", "redo": "फिर से करें",
"roomDialog": "लाइव सहयोग शुरू करें", "resetLibrary": "",
"createNewRoom": "एक नया कमरा बनाएं", "createNewRoom": "एक नया कमरा बनाएं",
"fullScreen": "पूरी स्क्रीन", "fullScreen": "पूरी स्क्रीन",
"darkMode": "डार्क मोड", "darkMode": "डार्क मोड",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "लाइब्रेरी लोड करने में त्रुटि", "errorLoadingLibrary": "लाइब्रेरी लोड करने में त्रुटि",
"confirmAddLibrary": "लाइब्रेरी जोड़ें पुष्‍टि करें आकार संख्या", "confirmAddLibrary": "लाइब्रेरी जोड़ें पुष्‍टि करें आकार संख्या",
"imageDoesNotContainScene": "दृश्य में छवि नहीं है", "imageDoesNotContainScene": "दृश्य में छवि नहीं है",
"cannotRestoreFromImage": "छवि फ़ाइल बहाल दृश्य नहीं है" "cannotRestoreFromImage": "छवि फ़ाइल बहाल दृश्य नहीं है",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "चयन", "selection": "चयन",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "काॅपी कीए स्टाइल", "copyStyles": "काॅपी कीए स्टाइल",
"copyToClipboard": "क्लिपबोर्ड में कॉपी कीए", "copyToClipboard": "क्लिपबोर्ड में कॉपी कीए",
"copyToClipboardAsPng": "क्लिपबोर्ड में PNG के रूप में कॉपी किए" "copyToClipboardAsPng": "क्लिपबोर्ड में PNG के रूप में कॉपी किए",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "Rétegek", "layers": "Rétegek",
"actions": "Műveletek", "actions": "Műveletek",
"language": "Nyelv", "language": "Nyelv",
"createRoom": "Élő együttmüködés megosztása", "liveCollaboration": "",
"duplicateSelection": "Duplikálás", "duplicateSelection": "Duplikálás",
"untitled": "Névtelen", "untitled": "Névtelen",
"name": "Név", "name": "Név",
@@ -77,7 +77,7 @@
"group": "Csoportosítás", "group": "Csoportosítás",
"ungroup": "Csoportbontás", "ungroup": "Csoportbontás",
"collaborators": "Közreműködők", "collaborators": "Közreműködők",
"gridMode": "Hálómód", "showGrid": "",
"addToLibrary": "Hozzáadás a könyvtárhoz", "addToLibrary": "Hozzáadás a könyvtárhoz",
"removeFromLibrary": "Eltávólítás a könyvtárból", "removeFromLibrary": "Eltávólítás a könyvtárból",
"libraryLoadingMessage": "Könyvtár betöltése…", "libraryLoadingMessage": "Könyvtár betöltése…",
@@ -117,7 +117,7 @@
"edit": "Szerkesztés", "edit": "Szerkesztés",
"undo": "Vissza", "undo": "Vissza",
"redo": "Újra", "redo": "Újra",
"roomDialog": "Élő együttműködés indítása", "resetLibrary": "",
"createNewRoom": "Új szoba létrehozása", "createNewRoom": "Új szoba létrehozása",
"fullScreen": "Teljes képernyő", "fullScreen": "Teljes képernyő",
"darkMode": "Sötét mód", "darkMode": "Sötét mód",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Hibába ütközött a harmarmadik féltől származó könyvtár betöltése.", "errorLoadingLibrary": "Hibába ütközött a harmarmadik féltől származó könyvtár betöltése.",
"confirmAddLibrary": "Ez a művelet {{numShapes}} formát fog hozzáadni a könyvtáradhoz. Biztos vagy benne?", "confirmAddLibrary": "Ez a művelet {{numShapes}} formát fog hozzáadni a könyvtáradhoz. Biztos vagy benne?",
"imageDoesNotContainScene": "Képek importálása egyelőre nem támogatott.\n\nEgy jelenetet szeretnél betölteni? Úgy tűnik ez a kép fájl nem tartalmazza a szükséges adatokat. Exportáláskor ezt egy külön opcióval lehet beállítani.", "imageDoesNotContainScene": "Képek importálása egyelőre nem támogatott.\n\nEgy jelenetet szeretnél betölteni? Úgy tűnik ez a kép fájl nem tartalmazza a szükséges adatokat. Exportáláskor ezt egy külön opcióval lehet beállítani.",
"cannotRestoreFromImage": "A jelenet visszaállítása nem sikerült ebből a kép fájlból" "cannotRestoreFromImage": "A jelenet visszaállítása nem sikerült ebből a kép fájlból",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "Kijelölés", "selection": "Kijelölés",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "", "copyStyles": "",
"copyToClipboard": "", "copyToClipboard": "",
"copyToClipboardAsPng": "" "copyToClipboardAsPng": "",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+13 -10
View File
@@ -68,7 +68,7 @@
"layers": "Lapisan", "layers": "Lapisan",
"actions": "Aksi", "actions": "Aksi",
"language": "Bahasa", "language": "Bahasa",
"createRoom": "Bagikan sesi kolaborasi langsung", "liveCollaboration": "",
"duplicateSelection": "Duplikat", "duplicateSelection": "Duplikat",
"untitled": "Tanpa judul", "untitled": "Tanpa judul",
"name": "Nama", "name": "Nama",
@@ -77,7 +77,7 @@
"group": "Kelompokan pilihan", "group": "Kelompokan pilihan",
"ungroup": "Pisahkan pilihan", "ungroup": "Pisahkan pilihan",
"collaborators": "Kolaborator", "collaborators": "Kolaborator",
"gridMode": "Mode grid", "showGrid": "Tampilkan grid",
"addToLibrary": "Tambahkan ke pustaka", "addToLibrary": "Tambahkan ke pustaka",
"removeFromLibrary": "Hapus dari pustaka", "removeFromLibrary": "Hapus dari pustaka",
"libraryLoadingMessage": "Memuat pustaka…", "libraryLoadingMessage": "Memuat pustaka…",
@@ -117,7 +117,7 @@
"edit": "Edit", "edit": "Edit",
"undo": "Urungkan", "undo": "Urungkan",
"redo": "Ulangi", "redo": "Ulangi",
"roomDialog": "Mulai kolaborasi langsung", "resetLibrary": "",
"createNewRoom": "Buat ruang baru", "createNewRoom": "Buat ruang baru",
"fullScreen": "Layar penuh", "fullScreen": "Layar penuh",
"darkMode": "Mode gelap", "darkMode": "Mode gelap",
@@ -136,11 +136,12 @@
"decryptFailed": "Tidak dapat mengdekripsi data.", "decryptFailed": "Tidak dapat mengdekripsi data.",
"uploadedSecurly": "Pengunggahan ini telah diamankan menggunakan enkripsi end-to-end, artinya server Excalidraw dan pihak ketiga tidak data membaca nya", "uploadedSecurly": "Pengunggahan ini telah diamankan menggunakan enkripsi end-to-end, artinya server Excalidraw dan pihak ketiga tidak data membaca nya",
"loadSceneOverridePrompt": "Memuat gambar external akan mengganti konten Anda yang ada. Apakah Anda ingin melanjutkan?", "loadSceneOverridePrompt": "Memuat gambar external akan mengganti konten Anda yang ada. Apakah Anda ingin melanjutkan?",
"collabStopOverridePrompt": "", "collabStopOverridePrompt": "Menghentikan sesi akan menimpa gambar Anda yang tersimpan secara lokal. Anda yakin?\n\n(Jika Anda ingin menyimpan gambar lokal Anda, gantinya cukup tutup tab browser.)",
"errorLoadingLibrary": "Terdapat kesalahan dalam memuat pustaka pihak ketiga.", "errorLoadingLibrary": "Terdapat kesalahan dalam memuat pustaka pihak ketiga.",
"confirmAddLibrary": "Ini akan menambahkan {{numShapes}} bentuk ke pustaka Anda. Anda yakin?", "confirmAddLibrary": "Ini akan menambahkan {{numShapes}} bentuk ke pustaka Anda. Anda yakin?",
"imageDoesNotContainScene": "Mengimpor gambar tidak didukung saat ini.\n\nApakah Anda ingin impor pemandangan? Gambar ini tidak berisi data pemandangan. Sudah ka Anda aktifkan ini ketika ekspor?", "imageDoesNotContainScene": "Mengimpor gambar tidak didukung saat ini.\n\nApakah Anda ingin impor pemandangan? Gambar ini tidak berisi data pemandangan. Sudah ka Anda aktifkan ini ketika ekspor?",
"cannotRestoreFromImage": "Pemandangan tidak dapat dipulihkan dari file gambar ini" "cannotRestoreFromImage": "Pemandangan tidak dapat dipulihkan dari file gambar ini",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "Pilihan", "selection": "Pilihan",
@@ -235,14 +236,16 @@
"storage": "Penyimpanan", "storage": "Penyimpanan",
"title": "Statistik untuk nerd", "title": "Statistik untuk nerd",
"total": "Total", "total": "Total",
"version": "", "version": "Versi",
"versionCopy": "", "versionCopy": "Klik untuk salin",
"versionNotAvailable": "", "versionNotAvailable": "Versi tidak tersedia",
"width": "Lebar" "width": "Lebar"
}, },
"toast": { "toast": {
"copyStyles": "Gaya tersalin.", "copyStyles": "Gaya tersalin.",
"copyToClipboard": "", "copyToClipboard": "Tersalin ke papan klip.",
"copyToClipboardAsPng": "Tersalin ke clipboard sebagai PNG." "copyToClipboardAsPng": "Tersalin ke clipboard sebagai PNG.",
"fileSaved": "File tersimpan.",
"fileSavedToFilename": "Disimpan ke {filename}"
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "Livelli", "layers": "Livelli",
"actions": "Azioni", "actions": "Azioni",
"language": "Lingua", "language": "Lingua",
"createRoom": "Condividi una sessione di collaborazione in diretta", "liveCollaboration": "Collaborazione live",
"duplicateSelection": "Duplica", "duplicateSelection": "Duplica",
"untitled": "Senza titolo", "untitled": "Senza titolo",
"name": "Nome", "name": "Nome",
@@ -77,7 +77,7 @@
"group": "Crea gruppo da selezione", "group": "Crea gruppo da selezione",
"ungroup": "Dividi gruppo da selezione", "ungroup": "Dividi gruppo da selezione",
"collaborators": "Collaboratori", "collaborators": "Collaboratori",
"gridMode": "Modalità griglia", "showGrid": "Visualizza griglia",
"addToLibrary": "Aggiungi alla libreria", "addToLibrary": "Aggiungi alla libreria",
"removeFromLibrary": "Rimuovi dalla libreria", "removeFromLibrary": "Rimuovi dalla libreria",
"libraryLoadingMessage": "Caricamento libreria…", "libraryLoadingMessage": "Caricamento libreria…",
@@ -117,7 +117,7 @@
"edit": "Modifica", "edit": "Modifica",
"undo": "Annulla", "undo": "Annulla",
"redo": "Ripeti", "redo": "Ripeti",
"roomDialog": "Inizia collaborazione in diretta", "resetLibrary": "Ripristina libreria",
"createNewRoom": "Crea nuova stanza", "createNewRoom": "Crea nuova stanza",
"fullScreen": "Schermo intero", "fullScreen": "Schermo intero",
"darkMode": "Tema scuro", "darkMode": "Tema scuro",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Si è verificato un errore nel caricamento della libreria di terze parti.", "errorLoadingLibrary": "Si è verificato un errore nel caricamento della libreria di terze parti.",
"confirmAddLibrary": "Questo aggiungerà {{numShapes}} forma(e) alla tua libreria. Sei sicuro?", "confirmAddLibrary": "Questo aggiungerà {{numShapes}} forma(e) alla tua libreria. Sei sicuro?",
"imageDoesNotContainScene": "L'importazione di immagini al momento non è supportata.\n\nVuoi importare una scena? Questa immagine non sembra contenere alcun dato di scena. Hai abilitato questa opzione durante l'esportazione?", "imageDoesNotContainScene": "L'importazione di immagini al momento non è supportata.\n\nVuoi importare una scena? Questa immagine non sembra contenere alcun dato di scena. Hai abilitato questa opzione durante l'esportazione?",
"cannotRestoreFromImage": "Impossibile ripristinare la scena da questo file immagine" "cannotRestoreFromImage": "Impossibile ripristinare la scena da questo file immagine",
"resetLibrary": "Questa azione cancellerà l'intera libreria. Sei sicuro?"
}, },
"toolBar": { "toolBar": {
"selection": "Selezione", "selection": "Selezione",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "Stili copiati.", "copyStyles": "Stili copiati.",
"copyToClipboard": "Copiato negli appunti.", "copyToClipboard": "Copiato negli appunti.",
"copyToClipboardAsPng": "Copiato negli appunti come PNG." "copyToClipboardAsPng": "Copiato negli appunti come PNG.",
"fileSaved": "File salvato.",
"fileSavedToFilename": "Salvato in {filename}"
} }
} }
+51 -48
View File
@@ -1,11 +1,11 @@
{ {
"labels": { "labels": {
"paste": "貼り付け", "paste": "貼り付け",
"pasteCharts": "", "pasteCharts": "チャートの貼り付け",
"selectAll": "すべて選択", "selectAll": "すべて選択",
"multiSelect": "複数選択", "multiSelect": "複数選択",
"moveCanvas": "キャンバスを移動", "moveCanvas": "キャンバスを移動",
"cut": "", "cut": "切り取り",
"copy": "コピー", "copy": "コピー",
"copyAsPng": "PNGとしてクリップボードへコピー", "copyAsPng": "PNGとしてクリップボードへコピー",
"copyAsSvg": "SVGとしてクリップボードへコピー", "copyAsSvg": "SVGとしてクリップボードへコピー",
@@ -38,7 +38,7 @@
"fontSize": "フォントの大きさ", "fontSize": "フォントの大きさ",
"fontFamily": "フォントの種類", "fontFamily": "フォントの種類",
"onlySelected": "選択中のみ", "onlySelected": "選択中のみ",
"withBackground": "", "withBackground": "背景を含める",
"exportEmbedScene": "エクスポートされたファイルにシーンを埋め込みます", "exportEmbedScene": "エクスポートされたファイルにシーンを埋め込みます",
"exportEmbedScene_details": "シーンデータはエクスポートされたPNG/SVGファイルに保存され、シーンを復元することができます。\nエクスポートされたファイルのサイズは増加します。", "exportEmbedScene_details": "シーンデータはエクスポートされたPNG/SVGファイルに保存され、シーンを復元することができます。\nエクスポートされたファイルのサイズは増加します。",
"addWatermark": "\"Made with Excalidraw\"と表示", "addWatermark": "\"Made with Excalidraw\"と表示",
@@ -68,20 +68,20 @@
"layers": "レイヤー", "layers": "レイヤー",
"actions": "操作", "actions": "操作",
"language": "言語", "language": "言語",
"createRoom": "共同編集セッションの共有", "liveCollaboration": "ライブ連携",
"duplicateSelection": "複製", "duplicateSelection": "複製",
"untitled": "", "untitled": "無題",
"name": "名前", "name": "名前",
"yourName": "あなたの名前", "yourName": "あなたの名前",
"madeWithExcalidraw": "Excalidrawで作成", "madeWithExcalidraw": "Excalidrawで作成",
"group": "図形のグループ化", "group": "図形のグループ化",
"ungroup": "グループ化を解除", "ungroup": "グループ化を解除",
"collaborators": "共同編集者", "collaborators": "共同編集者",
"gridMode": "", "showGrid": "グリッドを表示",
"addToLibrary": "ライブラリに追加", "addToLibrary": "ライブラリに追加",
"removeFromLibrary": "ライブラリから削除", "removeFromLibrary": "ライブラリから削除",
"libraryLoadingMessage": "ライブラリを読み込み中…", "libraryLoadingMessage": "ライブラリを読み込み中…",
"libraries": "", "libraries": "ライブラリを参照する",
"loadingScene": "シーンを読み込み中…", "loadingScene": "シーンを読み込み中…",
"align": "整列", "align": "整列",
"alignTop": "上揃え", "alignTop": "上揃え",
@@ -90,9 +90,9 @@
"alignRight": "右揃え", "alignRight": "右揃え",
"centerVertically": "縦方向に中央揃え", "centerVertically": "縦方向に中央揃え",
"centerHorizontally": "横方向に中央揃え", "centerHorizontally": "横方向に中央揃え",
"distributeHorizontally": "", "distributeHorizontally": "水平方向に分散配置",
"distributeVertically": "", "distributeVertically": "垂直方向に分散配置",
"viewMode": "" "viewMode": "閲覧モード"
}, },
"buttons": { "buttons": {
"clearReset": "キャンバスのリセット", "clearReset": "キャンバスのリセット",
@@ -117,12 +117,12 @@
"edit": "編集", "edit": "編集",
"undo": "元に戻す", "undo": "元に戻す",
"redo": "やり直し", "redo": "やり直し",
"roomDialog": "共同編集を開始する", "resetLibrary": "ライブラリをリセット",
"createNewRoom": "新しい部屋を作成する", "createNewRoom": "新しい部屋を作成する",
"fullScreen": "全画面表示", "fullScreen": "全画面表示",
"darkMode": "ダークモード", "darkMode": "ダークモード",
"lightMode": "ライトモード", "lightMode": "ライトモード",
"zenMode": "", "zenMode": "Zenモード",
"exitZenMode": "集中モードをやめる" "exitZenMode": "集中モードをやめる"
}, },
"alerts": { "alerts": {
@@ -136,11 +136,12 @@
"decryptFailed": "データを復号できませんでした。", "decryptFailed": "データを復号できませんでした。",
"uploadedSecurly": "データのアップロードはエンドツーエンド暗号化によって保護されています。Excalidrawサーバーと第三者はデータの内容を見ることができません。", "uploadedSecurly": "データのアップロードはエンドツーエンド暗号化によって保護されています。Excalidrawサーバーと第三者はデータの内容を見ることができません。",
"loadSceneOverridePrompt": "外部図面を読み込むと、既存のコンテンツが置き換わります。続行しますか?", "loadSceneOverridePrompt": "外部図面を読み込むと、既存のコンテンツが置き換わります。続行しますか?",
"collabStopOverridePrompt": "", "collabStopOverridePrompt": "セッションを停止すると、ローカルに保存されている図が上書きされます。 本当によろしいですか?\n\n(ローカルの図を保持したい場合は、セッションを停止せずにブラウザタブを閉じてください。)",
"errorLoadingLibrary": "サードパーティライブラリの読み込み中にエラーが発生しました。", "errorLoadingLibrary": "サードパーティライブラリの読み込み中にエラーが発生しました。",
"confirmAddLibrary": "{{numShapes}} 個の図形をライブラリに追加します。よろしいですか?", "confirmAddLibrary": "{{numShapes}} 個の図形をライブラリに追加します。よろしいですか?",
"imageDoesNotContainScene": "", "imageDoesNotContainScene": "現在、画像のインポートはサポートされていません。\n\nシーンをインポートしようとしましたか?この画像にはシーンデータが含まれていないようです。エクスポート中に有効にしていましたか?",
"cannotRestoreFromImage": "このイメージファイルからシーンを復元できませんでした" "cannotRestoreFromImage": "このイメージファイルからシーンを復元できませんでした",
"resetLibrary": "ライブラリを消去します。本当によろしいですか?"
}, },
"toolBar": { "toolBar": {
"selection": "選択", "selection": "選択",
@@ -164,7 +165,7 @@
"freeDraw": "クリックしてドラッグします。離すと終了します", "freeDraw": "クリックしてドラッグします。離すと終了します",
"text": "ヒント: 選択ツールを使用して任意の場所をダブルクリックしてテキストを追加することもできます", "text": "ヒント: 選択ツールを使用して任意の場所をダブルクリックしてテキストを追加することもできます",
"linearElementMulti": "最後のポイントをクリックするか、エスケープまたはEnterを押して終了します", "linearElementMulti": "最後のポイントをクリックするか、エスケープまたはEnterを押して終了します",
"lockAngle": "", "lockAngle": "SHIFTを押したままにすると、角度を制限することができます",
"resize": "サイズを変更中にSHIFTを押しすと比率を制御できます。Altを押すと中央からサイズを変更できます。", "resize": "サイズを変更中にSHIFTを押しすと比率を制御できます。Altを押すと中央からサイズを変更できます。",
"rotate": "回転中にSHIFT キーを押すと角度を制限することができます", "rotate": "回転中にSHIFT キーを押すと角度を制限することができます",
"lineEditor_info": "ポイントを編集するには、ダブルクリックまたはEnterキーを押します", "lineEditor_info": "ポイントを編集するには、ダブルクリックまたはEnterキーを押します",
@@ -202,47 +203,49 @@
"title": "エラー" "title": "エラー"
}, },
"helpDialog": { "helpDialog": {
"blog": "", "blog": "公式ブログを読む",
"click": "", "click": "クリック",
"curvedArrow": "", "curvedArrow": "カーブした矢印",
"curvedLine": "", "curvedLine": "曲線",
"documentation": "", "documentation": "ドキュメント",
"drag": "", "drag": "ドラッグ",
"editor": "", "editor": "エディタ",
"github": "", "github": "不具合報告はこちら",
"howto": "", "howto": "ヘルプ・マニュアル",
"or": "", "or": "または",
"preventBinding": "", "preventBinding": "矢印を結合しない",
"shapes": "", "shapes": "図形",
"shortcuts": "", "shortcuts": "キーボードショートカット",
"textFinish": "", "textFinish": "編集を終了する (テキスト)",
"textNewLine": "", "textNewLine": "新しい行を追加 (テキスト)",
"title": "", "title": "ヘルプ",
"view": "", "view": "表示",
"zoomToFit": "", "zoomToFit": "すべての要素が収まるようにズーム",
"zoomToSelection": "" "zoomToSelection": "選択要素にズーム"
}, },
"encrypted": { "encrypted": {
"tooltip": "描画内容はエンドツーエンド暗号化が施されており、Excalidrawサーバーが内容を見ることはできません。" "tooltip": "描画内容はエンドツーエンド暗号化が施されており、Excalidrawサーバーが内容を見ることはできません。"
}, },
"stats": { "stats": {
"angle": "", "angle": "角度",
"element": "", "element": "要素",
"elements": "", "elements": "要素",
"height": "高さ", "height": "高さ",
"scene": "", "scene": "シーン",
"selected": "", "selected": "選択済み",
"storage": "", "storage": "ストレージ",
"title": "", "title": "マニア向け統計情報",
"total": "合計", "total": "合計",
"version": "", "version": "バージョン",
"versionCopy": "", "versionCopy": "クリックしてコピー",
"versionNotAvailable": "", "versionNotAvailable": "利用できないバージョン",
"width": "幅" "width": "幅"
}, },
"toast": { "toast": {
"copyStyles": "", "copyStyles": "スタイルをコピー",
"copyToClipboard": "", "copyToClipboard": "クリップボードにコピー",
"copyToClipboardAsPng": "" "copyToClipboardAsPng": "PNG形式でクリップボードにコピー",
"fileSaved": "ファイルを保存しました",
"fileSavedToFilename": "{filename} に保存しました"
} }
} }
+17 -14
View File
@@ -24,7 +24,7 @@
"strokeStyle_solid": "Aččuran", "strokeStyle_solid": "Aččuran",
"strokeStyle_dashed": "S tjerriḍin", "strokeStyle_dashed": "S tjerriḍin",
"strokeStyle_dotted": "S tenqiḍin", "strokeStyle_dotted": "S tenqiḍin",
"sloppiness": "", "sloppiness": "Astehzi",
"opacity": "Tiḍullest", "opacity": "Tiḍullest",
"textAlign": "Areyyec n uḍris", "textAlign": "Areyyec n uḍris",
"edges": "Leryuf", "edges": "Leryuf",
@@ -68,7 +68,7 @@
"layers": "Tissiyin", "layers": "Tissiyin",
"actions": "Tigawin", "actions": "Tigawin",
"language": "Tutlayt", "language": "Tutlayt",
"createRoom": "Bḍu tiɣimit n umɛawen s srid", "liveCollaboration": "",
"duplicateSelection": "Sisleg", "duplicateSelection": "Sisleg",
"untitled": "War azwel", "untitled": "War azwel",
"name": "Isem", "name": "Isem",
@@ -77,7 +77,7 @@
"group": "Segrew tafrayt", "group": "Segrew tafrayt",
"ungroup": "Kkess asegrew i tefrayt", "ungroup": "Kkess asegrew i tefrayt",
"collaborators": "Imɛiwnen", "collaborators": "Imɛiwnen",
"gridMode": "Askar n uferrug", "showGrid": "Beqqeḍ aferrug",
"addToLibrary": "Rnu ɣer temkarḍit", "addToLibrary": "Rnu ɣer temkarḍit",
"removeFromLibrary": "Kkes si temkarḍit", "removeFromLibrary": "Kkes si temkarḍit",
"libraryLoadingMessage": "Asali n temkarḍit…", "libraryLoadingMessage": "Asali n temkarḍit…",
@@ -117,7 +117,7 @@
"edit": "Ẓreg", "edit": "Ẓreg",
"undo": "Sefsex", "undo": "Sefsex",
"redo": "Err-d", "redo": "Err-d",
"roomDialog": "Bdu amɛawen s srid", "resetLibrary": "",
"createNewRoom": "Snulfu-d taxxamt tamaynutt", "createNewRoom": "Snulfu-d taxxamt tamaynutt",
"fullScreen": "Agdil aččuran", "fullScreen": "Agdil aččuran",
"darkMode": "Askar imsulles", "darkMode": "Askar imsulles",
@@ -130,17 +130,18 @@
"couldNotCreateShareableLink": "D awezɣi asnulfu n useɣwen n beṭṭu.", "couldNotCreateShareableLink": "D awezɣi asnulfu n useɣwen n beṭṭu.",
"couldNotCreateShareableLinkTooBig": "D awezɣi asnulfu n useɣwen n beṭṭu. Asayes ɣezzif aṭas", "couldNotCreateShareableLinkTooBig": "D awezɣi asnulfu n useɣwen n beṭṭu. Asayes ɣezzif aṭas",
"couldNotLoadInvalidFile": "D awezɣi asali n ufaylu armeɣtu", "couldNotLoadInvalidFile": "D awezɣi asali n ufaylu armeɣtu",
"importBackendFailed": "", "importBackendFailed": "Takterḍ seg uɣawas n deffir ur teddi ara.",
"cannotExportEmptyCanvas": "D awezɣi asifeḍ n teɣzut n usuneɣ tilemt.", "cannotExportEmptyCanvas": "D awezɣi asifeḍ n teɣzut n usuneɣ tilemt.",
"couldNotCopyToClipboard": "D awezɣi anɣal ɣer tecfawit. Eɛreḍ ad tesqedceḍ iminig Chrome.", "couldNotCopyToClipboard": "D awezɣi anɣal ɣer tecfawit. Eɛreḍ ad tesqedceḍ iminig Chrome.",
"decryptFailed": "D awezɣi tukksa n uwgelhen i yisefka.", "decryptFailed": "D awezɣi tukksa n uwgelhen i yisefka.",
"uploadedSecurly": "Asili yettwasɣelles s uwgelhen ixef s ixef, ayagi yebɣa ad d-yini belli aqeddac n Excalidraw akked medden ur zmiren ara ad ɣren agbur.", "uploadedSecurly": "Asili yettwasɣelles s uwgelhen ixef s ixef, ayagi yebɣa ad d-yini belli aqeddac n Excalidraw akked medden ur zmiren ara ad ɣren agbur.",
"loadSceneOverridePrompt": "Asali n wunuɣ uffiɣ ad isemselsi agbur-inek (m) yellan. Tebɣiḍ ad tkemmeleḍ?", "loadSceneOverridePrompt": "Asali n wunuɣ uffiɣ ad isemselsi agbur-inek (m) yellan. Tebɣiḍ ad tkemmeleḍ?",
"collabStopOverridePrompt": "", "collabStopOverridePrompt": "Aḥbas n tɣimit ad yesefsex unuɣ-inek (m) yettwaḥerzen yakan s wudem adigan. Tetḥeqqeḍ?\n(Ma tebɣiḍ ad teǧǧeḍ unuɣ-inek (m) adigan, mdel iccer n yiminig, deg umḍiq.)",
"errorLoadingLibrary": "Teḍra-d tuccḍa deg usali n temkarḍit n wis kraḍ.", "errorLoadingLibrary": "Teḍra-d tuccḍa deg usali n temkarḍit n wis kraḍ.",
"confirmAddLibrary": "Ayagi adirnu talɣa (win) {{numShapes}} ɣer temkarḍit-inek (m). Tetḥeqqeḍ?", "confirmAddLibrary": "Ayagi adirnu talɣa (win) {{numShapes}} ɣer temkarḍit-inek (m). Tetḥeqqeḍ?",
"imageDoesNotContainScene": "Taktert n tugniwin ur tettwadhel ara akka tura.\nTebɣiḍ ad tketreḍ asayes? Tugna-agi tettban-d ur tegbir ara isefka n usnas. Tesremdeḍ ayagi deg usifeḍ?", "imageDoesNotContainScene": "Taktert n tugniwin ur tettwadhel ara akka tura.\nTebɣiḍ ad tketreḍ asayes? Tugna-agi tettban-d ur tegbir ara isefka n usnas. Tesremdeḍ ayagi deg usifeḍ?",
"cannotRestoreFromImage": "Asayes ulamek ara d-yettwarr seg ufaylu-agi n tugna" "cannotRestoreFromImage": "Asayes ulamek ara d-yettwarr seg ufaylu-agi n tugna",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "Tafrayt", "selection": "Tafrayt",
@@ -184,7 +185,7 @@
"clearCanvasCaveat": " Ayagi ad d-iglu s usṛuḥu n umahil ", "clearCanvasCaveat": " Ayagi ad d-iglu s usṛuḥu n umahil ",
"trackedToSentry_pre": "Tuccḍa akked umesmagi ", "trackedToSentry_pre": "Tuccḍa akked umesmagi ",
"trackedToSentry_post": " tettwasekles deg unagraw-nneɣ.", "trackedToSentry_post": " tettwasekles deg unagraw-nneɣ.",
"openIssueMessage_pre": "", "openIssueMessage_pre": "Nḥuder aṭas akken ur nseddu ara talɣut n usayes-inek (m) di tuccḍa. Ma yella asayes-inek (m) mačči d amaẓlay, ttxil-k (m) xemmem ad ḍefreḍ ",
"openIssueMessage_button": "afecku n weḍfar n yibugen.", "openIssueMessage_button": "afecku n weḍfar n yibugen.",
"openIssueMessage_post": " Ma ulac uɣilif seddu talɣut ukessar-agi s wenɣal akked usenṭeḍ di GitHub issue.", "openIssueMessage_post": " Ma ulac uɣilif seddu talɣut ukessar-agi s wenɣal akked usenṭeḍ di GitHub issue.",
"sceneContent": "Agbur n usayes:" "sceneContent": "Agbur n usayes:"
@@ -212,7 +213,7 @@
"github": "Tufiḍ-d ugur? Azen-aɣ-d", "github": "Tufiḍ-d ugur? Azen-aɣ-d",
"howto": "Ḍfer imniren-nneɣ", "howto": "Ḍfer imniren-nneɣ",
"or": "neɣ", "or": "neɣ",
"preventBinding": "", "preventBinding": "Seḥbes tuqqna n tneccabin",
"shapes": "Talɣiwin", "shapes": "Talɣiwin",
"shortcuts": "Inegzumen n unasiw", "shortcuts": "Inegzumen n unasiw",
"textFinish": "Fak asiẓreg (aḍris)", "textFinish": "Fak asiẓreg (aḍris)",
@@ -235,14 +236,16 @@
"storage": "Aḥraz", "storage": "Aḥraz",
"title": "", "title": "",
"total": "Aɣrud", "total": "Aɣrud",
"version": "", "version": "Alqem",
"versionCopy": "", "versionCopy": "Sit ad tneɣleḍ",
"versionNotAvailable": "", "versionNotAvailable": "Ur inuḥ ulqem",
"width": "Tehri" "width": "Tehri"
}, },
"toast": { "toast": {
"copyStyles": "Iɣunab yettwaneɣlen.", "copyStyles": "Iɣunab yettwaneɣlen.",
"copyToClipboard": "", "copyToClipboard": "Yettwaɣel ɣer tecfawit.",
"copyToClipboardAsPng": "Yettwanɣel ɣer tecfawit am PNG." "copyToClipboardAsPng": "Yettwanɣel ɣer tecfawit am PNG.",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+34 -31
View File
@@ -68,7 +68,7 @@
"layers": "레이어", "layers": "레이어",
"actions": "동작", "actions": "동작",
"language": "언어", "language": "언어",
"createRoom": "실시간 협업 세션 공유", "liveCollaboration": "",
"duplicateSelection": "복제", "duplicateSelection": "복제",
"untitled": "제목 없음", "untitled": "제목 없음",
"name": "이름", "name": "이름",
@@ -77,7 +77,7 @@
"group": "그룹 생성", "group": "그룹 생성",
"ungroup": "그룹 해제", "ungroup": "그룹 해제",
"collaborators": "공동 작업자", "collaborators": "공동 작업자",
"gridMode": "격자 방식", "showGrid": "",
"addToLibrary": "라이브러리에 추가", "addToLibrary": "라이브러리에 추가",
"removeFromLibrary": "라이브러리에서 제거", "removeFromLibrary": "라이브러리에서 제거",
"libraryLoadingMessage": "라이브러리 불러오는 중…", "libraryLoadingMessage": "라이브러리 불러오는 중…",
@@ -92,7 +92,7 @@
"centerHorizontally": "수평으로 중앙 정렬", "centerHorizontally": "수평으로 중앙 정렬",
"distributeHorizontally": "수평으로 분배", "distributeHorizontally": "수평으로 분배",
"distributeVertically": "수직으로 분배", "distributeVertically": "수직으로 분배",
"viewMode": "" "viewMode": "보기 모드"
}, },
"buttons": { "buttons": {
"clearReset": "캔버스 초기화", "clearReset": "캔버스 초기화",
@@ -117,7 +117,7 @@
"edit": "수정", "edit": "수정",
"undo": "실행 취소", "undo": "실행 취소",
"redo": "다시 실행", "redo": "다시 실행",
"roomDialog": "실시간 협업 시작하기", "resetLibrary": "",
"createNewRoom": "방 만들기", "createNewRoom": "방 만들기",
"fullScreen": "전체화면", "fullScreen": "전체화면",
"darkMode": "다크 모드", "darkMode": "다크 모드",
@@ -136,11 +136,12 @@
"decryptFailed": "데이터를 복호화하지 못했습니다.", "decryptFailed": "데이터를 복호화하지 못했습니다.",
"uploadedSecurly": "업로드는 종단 간 암호화로 보호되므로 Excalidraw 서버 및 타사가 콘텐츠를 읽을 수 없습니다.", "uploadedSecurly": "업로드는 종단 간 암호화로 보호되므로 Excalidraw 서버 및 타사가 콘텐츠를 읽을 수 없습니다.",
"loadSceneOverridePrompt": "외부 파일을 불러 오면 기존 콘텐츠가 대체됩니다. 계속 진행할까요?", "loadSceneOverridePrompt": "외부 파일을 불러 오면 기존 콘텐츠가 대체됩니다. 계속 진행할까요?",
"collabStopOverridePrompt": "", "collabStopOverridePrompt": "협업 세션을 종료하면 로컬 저장소에 있는 그림이 협업 세션의 그림으로 대체됩니다. 진행하겠습니까?\n\n(로컬 저장소에 있는 그림을 유지하려면 현재 브라우저 탭을 닫아주세요.)",
"errorLoadingLibrary": "외부 라이브러리를 불러오는 중에 문제가 발생했습니다.", "errorLoadingLibrary": "외부 라이브러리를 불러오는 중에 문제가 발생했습니다.",
"confirmAddLibrary": "{{numShapes}}개의 모양이 라이브러리에 추가됩니다. 계속하시겠어요?", "confirmAddLibrary": "{{numShapes}}개의 모양이 라이브러리에 추가됩니다. 계속하시겠어요?",
"imageDoesNotContainScene": "이미지에서 불러오기는 현재 지원되지 않습니다.\n\n화면을 불러오려고 하셨나요? 이미지에 화면 정보가 없는 것 같습니다. 내보낼 때 화면을 포함했나요?", "imageDoesNotContainScene": "이미지에서 불러오기는 현재 지원되지 않습니다.\n\n화면을 불러오려고 하셨나요? 이미지에 화면 정보가 없는 것 같습니다. 내보낼 때 화면을 포함했나요?",
"cannotRestoreFromImage": "이미지 파일에서 화면을 복구할 수 없었습니다" "cannotRestoreFromImage": "이미지 파일에서 화면을 복구할 수 없었습니다",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "선택", "selection": "선택",
@@ -202,25 +203,25 @@
"title": "오류" "title": "오류"
}, },
"helpDialog": { "helpDialog": {
"blog": "", "blog": "블로그 읽어보기",
"click": "", "click": "클릭",
"curvedArrow": "", "curvedArrow": "곡선 화살표",
"curvedLine": "", "curvedLine": "곡선",
"documentation": "", "documentation": "설명서",
"drag": "", "drag": "드래그",
"editor": "", "editor": "에디터",
"github": "", "github": "문제 제보하기",
"howto": "", "howto": "가이드 참고하기",
"or": "", "or": "또는",
"preventBinding": "", "preventBinding": "화살표가 붙지 않게 하기",
"shapes": "", "shapes": "도형",
"shortcuts": "", "shortcuts": "키보드 단축키",
"textFinish": "", "textFinish": "편집 완료 (텍스트)",
"textNewLine": "", "textNewLine": "줄바꿈 (텍스트)",
"title": "", "title": "도움말",
"view": "", "view": "보기",
"zoomToFit": "", "zoomToFit": "모든 요소가 보이도록 확대/축소",
"zoomToSelection": "" "zoomToSelection": "선택 영역으로 확대/축소"
}, },
"encrypted": { "encrypted": {
"tooltip": "그림은 종단 간 암호화되므로 Excalidraw의 서버는 절대로 내용을 알 수 없습니다." "tooltip": "그림은 종단 간 암호화되므로 Excalidraw의 서버는 절대로 내용을 알 수 없습니다."
@@ -235,14 +236,16 @@
"storage": "저장공간", "storage": "저장공간",
"title": "덕후들을 위한 통계", "title": "덕후들을 위한 통계",
"total": "합계", "total": "합계",
"version": "", "version": "버전",
"versionCopy": "", "versionCopy": "복사하려면 클릭",
"versionNotAvailable": "", "versionNotAvailable": "해당 버전 사용 불가능",
"width": "너비" "width": "너비"
}, },
"toast": { "toast": {
"copyStyles": "", "copyStyles": "스타일 복사.",
"copyToClipboard": "", "copyToClipboard": "클립보드로 복사.",
"copyToClipboardAsPng": "" "copyToClipboardAsPng": "클립보드로 PNG 이미지 복사.",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "အလွှာများ", "layers": "အလွှာများ",
"actions": "လုပ်ဆောင်ချက်များ", "actions": "လုပ်ဆောင်ချက်များ",
"language": "ဘာသာစကား", "language": "ဘာသာစကား",
"createRoom": "တိုက်ရိုက်ပူးပေါင်းဆောင်ရွက်ရန်အဖွဲ့ဖွဲ့", "liveCollaboration": "",
"duplicateSelection": "ပွား", "duplicateSelection": "ပွား",
"untitled": "အမည်မရှိ", "untitled": "အမည်မရှိ",
"name": "အမည်", "name": "အမည်",
@@ -77,7 +77,7 @@
"group": "အုပ်စုဖွဲ့", "group": "အုပ်စုဖွဲ့",
"ungroup": "အုပ်စုဖျက်သိမ်း", "ungroup": "အုပ်စုဖျက်သိမ်း",
"collaborators": "ပူးပေါင်းပါဝင်သူများ", "collaborators": "ပူးပေါင်းပါဝင်သူများ",
"gridMode": "", "showGrid": "",
"addToLibrary": "မှတ်တမ်းတင်", "addToLibrary": "မှတ်တမ်းတင်",
"removeFromLibrary": "မှတ်တမ်းမှထုတ်", "removeFromLibrary": "မှတ်တမ်းမှထုတ်",
"libraryLoadingMessage": "မှတ်တမ်းအား တင်သွင်းနေသည်…", "libraryLoadingMessage": "မှတ်တမ်းအား တင်သွင်းနေသည်…",
@@ -117,7 +117,7 @@
"edit": "ပြင်ဆင်", "edit": "ပြင်ဆင်",
"undo": "ပြန်ထား", "undo": "ပြန်ထား",
"redo": "ထပ်လုပ်", "redo": "ထပ်လုပ်",
"roomDialog": "တိုက်ရိုက်ပူးပေါင်းမှုစတင်", "resetLibrary": "",
"createNewRoom": "အခန်းသစ်ဖွဲ့", "createNewRoom": "အခန်းသစ်ဖွဲ့",
"fullScreen": "", "fullScreen": "",
"darkMode": "", "darkMode": "",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "ပြင်ပမှမှတ်တမ်းအားတင်သွင်းရာတွင်အမှားအယွင်းရှိနေသည်။", "errorLoadingLibrary": "ပြင်ပမှမှတ်တမ်းအားတင်သွင်းရာတွင်အမှားအယွင်းရှိနေသည်။",
"confirmAddLibrary": "{{numShapes}} ခုသောပုံသဏ္ဌာန်အားမှတ်တမ်းတင်ပါမည်။ အတည်ပြုပါ။", "confirmAddLibrary": "{{numShapes}} ခုသောပုံသဏ္ဌာန်အားမှတ်တမ်းတင်ပါမည်။ အတည်ပြုပါ။",
"imageDoesNotContainScene": "", "imageDoesNotContainScene": "",
"cannotRestoreFromImage": "ဤပုံဖြင့်မြင်ကွင်းပြန်လည်မရယူနိုင်ပါ။" "cannotRestoreFromImage": "ဤပုံဖြင့်မြင်ကွင်းပြန်လည်မရယူနိုင်ပါ။",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "ရွေးချယ်", "selection": "ရွေးချယ်",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "", "copyStyles": "",
"copyToClipboard": "", "copyToClipboard": "",
"copyToClipboardAsPng": "" "copyToClipboardAsPng": "",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "Lag", "layers": "Lag",
"actions": "Handlinger", "actions": "Handlinger",
"language": "Språk", "language": "Språk",
"createRoom": "Del en sanntids-samarbeidsøkt", "liveCollaboration": "Sanntids-samarbeid",
"duplicateSelection": "Dupliser", "duplicateSelection": "Dupliser",
"untitled": "Uten navn", "untitled": "Uten navn",
"name": "Navn", "name": "Navn",
@@ -77,7 +77,7 @@
"group": "Gruppér utvalg", "group": "Gruppér utvalg",
"ungroup": "Avgruppér utvalg", "ungroup": "Avgruppér utvalg",
"collaborators": "Samarbeidspartnere", "collaborators": "Samarbeidspartnere",
"gridMode": "Rutevisning", "showGrid": "Vis rutenett",
"addToLibrary": "Legg til i bibliotek", "addToLibrary": "Legg til i bibliotek",
"removeFromLibrary": "Fjern fra bibliotek", "removeFromLibrary": "Fjern fra bibliotek",
"libraryLoadingMessage": "Laster bibliotek…", "libraryLoadingMessage": "Laster bibliotek…",
@@ -117,7 +117,7 @@
"edit": "Rediger", "edit": "Rediger",
"undo": "Angre", "undo": "Angre",
"redo": "Gjør om", "redo": "Gjør om",
"roomDialog": "Start sanntids-samarbeid", "resetLibrary": "Nullstill bibliotek",
"createNewRoom": "Opprett et nytt rom", "createNewRoom": "Opprett et nytt rom",
"fullScreen": "Fullskjerm", "fullScreen": "Fullskjerm",
"darkMode": "Mørk modus", "darkMode": "Mørk modus",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Det oppstod en feil under lasting av tredjepartsbiblioteket.", "errorLoadingLibrary": "Det oppstod en feil under lasting av tredjepartsbiblioteket.",
"confirmAddLibrary": "Dette vil legge til {{numShapes}} figur(er) i biblioteket ditt. Er du sikker?", "confirmAddLibrary": "Dette vil legge til {{numShapes}} figur(er) i biblioteket ditt. Er du sikker?",
"imageDoesNotContainScene": "Importering av bilder støttes ikke for øyeblikket.\n\nVil du importere en scene? Dette bildet ser ikke ut til å inneholde noen scene-data. Har du aktivert dette under eksporten?", "imageDoesNotContainScene": "Importering av bilder støttes ikke for øyeblikket.\n\nVil du importere en scene? Dette bildet ser ikke ut til å inneholde noen scene-data. Har du aktivert dette under eksporten?",
"cannotRestoreFromImage": "Scenen kunne ikke gjenopprettes fra denne bildefilen" "cannotRestoreFromImage": "Scenen kunne ikke gjenopprettes fra denne bildefilen",
"resetLibrary": "Dette vil tømme biblioteket ditt. Er du sikker?"
}, },
"toolBar": { "toolBar": {
"selection": "Velg", "selection": "Velg",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "Kopierte stiler.", "copyStyles": "Kopierte stiler.",
"copyToClipboard": "Kopiert til utklippstavlen.", "copyToClipboard": "Kopiert til utklippstavlen.",
"copyToClipboardAsPng": "Kopiert til utklippstavlen som PNG." "copyToClipboardAsPng": "Kopiert til utklippstavlen som PNG.",
"fileSaved": "Fil lagret.",
"fileSavedToFilename": "Lagret til {filename}"
} }
} }
+12 -9
View File
@@ -68,7 +68,7 @@
"layers": "Lagen", "layers": "Lagen",
"actions": "Acties", "actions": "Acties",
"language": "Taal", "language": "Taal",
"createRoom": "Deel een live-samenwerkingssessie", "liveCollaboration": "Live Samenwerking",
"duplicateSelection": "Dupliceer", "duplicateSelection": "Dupliceer",
"untitled": "Naamloos", "untitled": "Naamloos",
"name": "Naam", "name": "Naam",
@@ -77,7 +77,7 @@
"group": "Groeperen", "group": "Groeperen",
"ungroup": "Groep opheffen", "ungroup": "Groep opheffen",
"collaborators": "Deelnemers", "collaborators": "Deelnemers",
"gridMode": "Rasterweergave", "showGrid": "Raster weergeven",
"addToLibrary": "Voeg toe aan bibliotheek", "addToLibrary": "Voeg toe aan bibliotheek",
"removeFromLibrary": "Verwijder uit bibliotheek", "removeFromLibrary": "Verwijder uit bibliotheek",
"libraryLoadingMessage": "Bibliotheek laden…", "libraryLoadingMessage": "Bibliotheek laden…",
@@ -117,7 +117,7 @@
"edit": "Bewerken", "edit": "Bewerken",
"undo": "Ongedaan maken", "undo": "Ongedaan maken",
"redo": "Herstel ongedaan maken", "redo": "Herstel ongedaan maken",
"roomDialog": "Live-samenwerkingssessie starten", "resetLibrary": "Bibliotheek Resetten",
"createNewRoom": "Creëer live-samenwerkingssessie", "createNewRoom": "Creëer live-samenwerkingssessie",
"fullScreen": "Volledig scherm", "fullScreen": "Volledig scherm",
"darkMode": "Donkere modus", "darkMode": "Donkere modus",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Bij het laden van de externe bibliotheek is een fout opgetreden.", "errorLoadingLibrary": "Bij het laden van de externe bibliotheek is een fout opgetreden.",
"confirmAddLibrary": "Hiermee worden {{numShapes}} vorm(n) aan uw bibliotheek toegevoegd. Ben je het zeker?", "confirmAddLibrary": "Hiermee worden {{numShapes}} vorm(n) aan uw bibliotheek toegevoegd. Ben je het zeker?",
"imageDoesNotContainScene": "Afbeeldingen importeren wordt op dit moment niet ondersteund.\n\nWil je een scène importeren? Deze afbeelding lijkt geen scène gegevens te bevatten. Heb je dit geactiveerd tijdens het exporteren?", "imageDoesNotContainScene": "Afbeeldingen importeren wordt op dit moment niet ondersteund.\n\nWil je een scène importeren? Deze afbeelding lijkt geen scène gegevens te bevatten. Heb je dit geactiveerd tijdens het exporteren?",
"cannotRestoreFromImage": "Scène kan niet worden hersteld vanuit dit afbeeldingsbestand" "cannotRestoreFromImage": "Scène kan niet worden hersteld vanuit dit afbeeldingsbestand",
"resetLibrary": "Dit zal je bibliotheek wissen. Weet je het zeker?"
}, },
"toolBar": { "toolBar": {
"selection": "Selectie", "selection": "Selectie",
@@ -235,14 +236,16 @@
"storage": "Opslag", "storage": "Opslag",
"title": "Statistieken voor nerds", "title": "Statistieken voor nerds",
"total": "Totaal", "total": "Totaal",
"version": "", "version": "Versie",
"versionCopy": "", "versionCopy": "Klik om te kopiëren",
"versionNotAvailable": "", "versionNotAvailable": "Versie niet beschikbaar",
"width": "Breedte" "width": "Breedte"
}, },
"toast": { "toast": {
"copyStyles": "Stijlen gekopieerd.", "copyStyles": "Stijlen gekopieerd.",
"copyToClipboard": "", "copyToClipboard": "Gekopieerd naar het klembord.",
"copyToClipboardAsPng": "Gekopieerd naar klembord als PNG." "copyToClipboardAsPng": "Gekopieerd naar klembord als PNG.",
"fileSaved": "Bestand opgeslagen.",
"fileSavedToFilename": "Opgeslagen als {filename}"
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "Lag", "layers": "Lag",
"actions": "Handlingar", "actions": "Handlingar",
"language": "Språk", "language": "Språk",
"createRoom": "Del ei sanntids-samarbeidsøkt", "liveCollaboration": "",
"duplicateSelection": "Dupliser", "duplicateSelection": "Dupliser",
"untitled": "Utan namn", "untitled": "Utan namn",
"name": "Namn", "name": "Namn",
@@ -77,7 +77,7 @@
"group": "Grupper utval", "group": "Grupper utval",
"ungroup": "Avgrupper utval", "ungroup": "Avgrupper utval",
"collaborators": "Samarbeidarar", "collaborators": "Samarbeidarar",
"gridMode": "Rutevisning", "showGrid": "",
"addToLibrary": "Legg til i bibliotek", "addToLibrary": "Legg til i bibliotek",
"removeFromLibrary": "Fjern frå bibliotek", "removeFromLibrary": "Fjern frå bibliotek",
"libraryLoadingMessage": "Laster bibliotek…", "libraryLoadingMessage": "Laster bibliotek…",
@@ -117,7 +117,7 @@
"edit": "Rediger", "edit": "Rediger",
"undo": "Angre", "undo": "Angre",
"redo": "Gjer om", "redo": "Gjer om",
"roomDialog": "Start sanntids-samarbeid", "resetLibrary": "",
"createNewRoom": "Lag nytt rom", "createNewRoom": "Lag nytt rom",
"fullScreen": "Fullskjerm", "fullScreen": "Fullskjerm",
"darkMode": "Mørk modus", "darkMode": "Mørk modus",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Det oppstod ein feil under lastinga av tredjepartsbibliotek.", "errorLoadingLibrary": "Det oppstod ein feil under lastinga av tredjepartsbibliotek.",
"confirmAddLibrary": "Dette vil legge til {{numShapes}} form(er) i biblioteket ditt. Er du sikker?", "confirmAddLibrary": "Dette vil legge til {{numShapes}} form(er) i biblioteket ditt. Er du sikker?",
"imageDoesNotContainScene": "Importering av bilder støttes ikkje for p. t.\n\nVil du importere ein scene? Dette bildet ser ikkje ut til å inneholde noen scene-data. Har du aktivert dette under eksporten?", "imageDoesNotContainScene": "Importering av bilder støttes ikkje for p. t.\n\nVil du importere ein scene? Dette bildet ser ikkje ut til å inneholde noen scene-data. Har du aktivert dette under eksporten?",
"cannotRestoreFromImage": "Scena kunne ikkje gjenopprettast frå denne biletfila" "cannotRestoreFromImage": "Scena kunne ikkje gjenopprettast frå denne biletfila",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "Vel", "selection": "Vel",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "", "copyStyles": "",
"copyToClipboard": "", "copyToClipboard": "",
"copyToClipboardAsPng": "" "copyToClipboardAsPng": "",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "ਪਰਤਾਂ", "layers": "ਪਰਤਾਂ",
"actions": "ਕਾਰਵਾਈਆਂ", "actions": "ਕਾਰਵਾਈਆਂ",
"language": "ਭਾਸ਼ਾ", "language": "ਭਾਸ਼ਾ",
"createRoom": "ਲਾਇਵ ਸਹਿਯੋਗ ਇਜਲਾਸ ਸਾਂਝਾ ਕਰੋ", "liveCollaboration": "",
"duplicateSelection": "ਡੁਪਲੀਕੇਟ ਬਣਾਓ", "duplicateSelection": "ਡੁਪਲੀਕੇਟ ਬਣਾਓ",
"untitled": "ਬੇ-ਸਿਰਨਾਵਾਂ", "untitled": "ਬੇ-ਸਿਰਨਾਵਾਂ",
"name": "ਨਾਂ", "name": "ਨਾਂ",
@@ -77,7 +77,7 @@
"group": "ਚੋਣ ਦਾ ਗਰੁੱਪ ਬਣਾਓ", "group": "ਚੋਣ ਦਾ ਗਰੁੱਪ ਬਣਾਓ",
"ungroup": "ਚੋਣ ਦਾ ਗਰੁੱਪ ਤੋੜੋ", "ungroup": "ਚੋਣ ਦਾ ਗਰੁੱਪ ਤੋੜੋ",
"collaborators": "ਸਹਿਯੋਗੀ", "collaborators": "ਸਹਿਯੋਗੀ",
"gridMode": "ਜਾਲੀਦਾਰ ਮੋਡ", "showGrid": "ਜਾਲੀ ਦਿਖਾਓ",
"addToLibrary": "ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚ ਜੋੜੋ", "addToLibrary": "ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚ ਜੋੜੋ",
"removeFromLibrary": "ਲਾਇਬ੍ਰੇਰੀ 'ਚੋਂ ਹਟਾਓ", "removeFromLibrary": "ਲਾਇਬ੍ਰੇਰੀ 'ਚੋਂ ਹਟਾਓ",
"libraryLoadingMessage": "ਲਾਇਬ੍ਰੇਰੀ ਲੋਡ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…", "libraryLoadingMessage": "ਲਾਇਬ੍ਰੇਰੀ ਲੋਡ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…",
@@ -117,7 +117,7 @@
"edit": "ਸੋਧੋ", "edit": "ਸੋਧੋ",
"undo": "ਅਣਕੀਤਾ ਕਰੋ", "undo": "ਅਣਕੀਤਾ ਕਰੋ",
"redo": "ਮੁੜ-ਕਰੋ", "redo": "ਮੁੜ-ਕਰੋ",
"roomDialog": "ਲਾਇਵ ਸਹਿਯੋਗ ਸ਼ੁਰੂ ਕਰੋ", "resetLibrary": "",
"createNewRoom": "ਨਵਾਂ ਕਮਰਾ ਬਣਾਓ", "createNewRoom": "ਨਵਾਂ ਕਮਰਾ ਬਣਾਓ",
"fullScreen": "ਪੂਰੀ ਸਕਰੀਨ", "fullScreen": "ਪੂਰੀ ਸਕਰੀਨ",
"darkMode": "ਡਾਰਕ ਮੋਡ", "darkMode": "ਡਾਰਕ ਮੋਡ",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "ਤੀਜੀ ਧਿਰ ਦੀ ਲਾਇਬ੍ਰੇਰੀ ਨੂੰ ਲੋਡ ਕਰਨ ਵਿੱਚ ਗਲਤੀ ਹੋਈ ਸੀ।", "errorLoadingLibrary": "ਤੀਜੀ ਧਿਰ ਦੀ ਲਾਇਬ੍ਰੇਰੀ ਨੂੰ ਲੋਡ ਕਰਨ ਵਿੱਚ ਗਲਤੀ ਹੋਈ ਸੀ।",
"confirmAddLibrary": "ਇਹ ਤੁਹਾਡੀ ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚ {{numShapes}} ਆਕ੍ਰਿਤੀ(ਆਂ) ਨੂੰ ਜੋੜ ਦੇਵੇਗਾ। ਕੀ ਤੁਸੀਂ ਪੱਕਾ ਇੰਝ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?", "confirmAddLibrary": "ਇਹ ਤੁਹਾਡੀ ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚ {{numShapes}} ਆਕ੍ਰਿਤੀ(ਆਂ) ਨੂੰ ਜੋੜ ਦੇਵੇਗਾ। ਕੀ ਤੁਸੀਂ ਪੱਕਾ ਇੰਝ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?",
"imageDoesNotContainScene": "ਫਿਲਹਾਲ ਤਸਵੀਰਾਂ ਨੂੰ ਆਯਾਤ ਕਰਨ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ।\n\nਕੀ ਤੁਸੀਂ ਦ੍ਰਿਸ਼ ਨੂੰ ਆਯਾਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਸੀ? ਇਸ ਤਸਵੀਰ ਵਿੱਚ ਦ੍ਰਿਸ਼ ਦਾ ਕੋਈ ਵੀ ਡਾਟਾ ਨਜ਼ਰ ਨਹੀਂ ਆ ਰਿਹਾ। ਕੀ ਨਿਰਯਾਤ ਦੌਰਾਨ ਤੁਸੀਂ ਇਹ ਸਮਰੱਥ ਕੀਤਾ ਸੀ?", "imageDoesNotContainScene": "ਫਿਲਹਾਲ ਤਸਵੀਰਾਂ ਨੂੰ ਆਯਾਤ ਕਰਨ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ।\n\nਕੀ ਤੁਸੀਂ ਦ੍ਰਿਸ਼ ਨੂੰ ਆਯਾਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਸੀ? ਇਸ ਤਸਵੀਰ ਵਿੱਚ ਦ੍ਰਿਸ਼ ਦਾ ਕੋਈ ਵੀ ਡਾਟਾ ਨਜ਼ਰ ਨਹੀਂ ਆ ਰਿਹਾ। ਕੀ ਨਿਰਯਾਤ ਦੌਰਾਨ ਤੁਸੀਂ ਇਹ ਸਮਰੱਥ ਕੀਤਾ ਸੀ?",
"cannotRestoreFromImage": "ਇਸ ਤਸਵੀਰ ਫਾਈਲ ਤੋਂ ਦ੍ਰਿਸ਼ ਬਹਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ" "cannotRestoreFromImage": "ਇਸ ਤਸਵੀਰ ਫਾਈਲ ਤੋਂ ਦ੍ਰਿਸ਼ ਬਹਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "ਚੋਣਕਾਰ", "selection": "ਚੋਣਕਾਰ",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "ਕਾਪੀ ਕੀਤੇ ਸਟਾਇਲ।", "copyStyles": "ਕਾਪੀ ਕੀਤੇ ਸਟਾਇਲ।",
"copyToClipboard": "ਕਲਿੱਪਬੋਰਡ 'ਤੇ ਕਾਪੀ ਕੀਤਾ।", "copyToClipboard": "ਕਲਿੱਪਬੋਰਡ 'ਤੇ ਕਾਪੀ ਕੀਤਾ।",
"copyToClipboardAsPng": "ਕਲਿੱਪਬੋਰਡ 'ਤੇ PNG ਵਜੋਂ ਕਾਪੀ ਕੀਤਾ।" "copyToClipboardAsPng": "ਕਲਿੱਪਬੋਰਡ 'ਤੇ PNG ਵਜੋਂ ਕਾਪੀ ਕੀਤਾ।",
"fileSaved": "ਫਾਈਲ ਸਾਂਭੀ ਗਈ।",
"fileSavedToFilename": "{filename} ਵਿੱਚ ਸਾਂਭੀ"
} }
} }
+26 -26
View File
@@ -1,36 +1,36 @@
{ {
"ar-SA": 87, "ar-SA": 85,
"bg-BG": 91, "bg-BG": 98,
"ca-ES": 87, "ca-ES": 85,
"de-DE": 98, "de-DE": 100,
"el-GR": 99, "el-GR": 100,
"en": 100, "en": 100,
"es-ES": 98, "es-ES": 100,
"fa-IR": 95, "fa-IR": 93,
"fi-FI": 98, "fi-FI": 100,
"fr-FR": 100, "fr-FR": 100,
"he-IL": 87, "he-IL": 85,
"hi-IN": 98, "hi-IN": 96,
"hu-HU": 87, "hu-HU": 85,
"id-ID": 97, "id-ID": 99,
"it-IT": 100, "it-IT": 100,
"ja-JP": 79, "ja-JP": 100,
"kab-KAB": 94, "kab-KAB": 97,
"ko-KR": 87, "ko-KR": 97,
"my-MM": 81, "my-MM": 79,
"nb-NO": 100, "nb-NO": 100,
"nl-NL": 97, "nl-NL": 99,
"nn-NO": 90, "nn-NO": 87,
"pa-IN": 100, "pa-IN": 99,
"pl-PL": 88, "pl-PL": 85,
"pt-BR": 100, "pt-BR": 100,
"pt-PT": 97, "pt-PT": 94,
"ro-RO": 100, "ro-RO": 100,
"ru-RU": 97, "ru-RU": 100,
"sk-SK": 100, "sk-SK": 100,
"sv-SE": 98, "sv-SE": 100,
"tr-TR": 87, "tr-TR": 85,
"uk-UA": 97, "uk-UA": 99,
"zh-CN": 98, "zh-CN": 95,
"zh-TW": 100 "zh-TW": 100
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "Warstwy", "layers": "Warstwy",
"actions": "Akcje", "actions": "Akcje",
"language": "Język", "language": "Język",
"createRoom": "Udostępnij sesję współpracy na żywo", "liveCollaboration": "",
"duplicateSelection": "Powiel", "duplicateSelection": "Powiel",
"untitled": "Bez tytułu", "untitled": "Bez tytułu",
"name": "Nazwa", "name": "Nazwa",
@@ -77,7 +77,7 @@
"group": "Zgrupuj wybrane", "group": "Zgrupuj wybrane",
"ungroup": "Rozgrupuj wybrane", "ungroup": "Rozgrupuj wybrane",
"collaborators": "Współtwórcy", "collaborators": "Współtwórcy",
"gridMode": "Tryb siatki", "showGrid": "",
"addToLibrary": "Dodaj do biblioteki", "addToLibrary": "Dodaj do biblioteki",
"removeFromLibrary": "Usuń z biblioteki", "removeFromLibrary": "Usuń z biblioteki",
"libraryLoadingMessage": "Ładowanie biblioteki…", "libraryLoadingMessage": "Ładowanie biblioteki…",
@@ -117,7 +117,7 @@
"edit": "Edytuj", "edit": "Edytuj",
"undo": "Cofnij", "undo": "Cofnij",
"redo": "Przywróć", "redo": "Przywróć",
"roomDialog": "Utwórz nową sesję współpracy na żywo", "resetLibrary": "",
"createNewRoom": "Utwórz nowy pokój", "createNewRoom": "Utwórz nowy pokój",
"fullScreen": "Pełny ekran", "fullScreen": "Pełny ekran",
"darkMode": "Ciemny motyw", "darkMode": "Ciemny motyw",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Wystąpił błąd podczas ładowania zewnętrznej biblioteki.", "errorLoadingLibrary": "Wystąpił błąd podczas ładowania zewnętrznej biblioteki.",
"confirmAddLibrary": "To doda {{numShapes}} kształtów do twojej biblioteki. Jesteś pewien?", "confirmAddLibrary": "To doda {{numShapes}} kształtów do twojej biblioteki. Jesteś pewien?",
"imageDoesNotContainScene": "Importowanie zdjęć nie jest obecnie obsługiwane.\n\nCzy chciałeś zaimportować scenę? Ten obraz nie zawiera żadnych danych sceny. Czy włączyłeś to podczas eksportowania?", "imageDoesNotContainScene": "Importowanie zdjęć nie jest obecnie obsługiwane.\n\nCzy chciałeś zaimportować scenę? Ten obraz nie zawiera żadnych danych sceny. Czy włączyłeś to podczas eksportowania?",
"cannotRestoreFromImage": "Scena nie mogła zostać przywrócona z pliku obrazu" "cannotRestoreFromImage": "Scena nie mogła zostać przywrócona z pliku obrazu",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "Zaznaczenie", "selection": "Zaznaczenie",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "", "copyStyles": "",
"copyToClipboard": "", "copyToClipboard": "",
"copyToClipboardAsPng": "" "copyToClipboardAsPng": "",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "Camadas", "layers": "Camadas",
"actions": "Ações", "actions": "Ações",
"language": "Idioma", "language": "Idioma",
"createRoom": "Compartilhar uma sessão de colaboração ao vivo", "liveCollaboration": "Colaboração ao vivo",
"duplicateSelection": "Duplicar", "duplicateSelection": "Duplicar",
"untitled": "Sem título", "untitled": "Sem título",
"name": "Nome", "name": "Nome",
@@ -77,7 +77,7 @@
"group": "Agrupar seleção", "group": "Agrupar seleção",
"ungroup": "Desagrupar seleção", "ungroup": "Desagrupar seleção",
"collaborators": "Colaboradores", "collaborators": "Colaboradores",
"gridMode": "Modo grade", "showGrid": "Mostrar grade",
"addToLibrary": "Adicionar à biblioteca", "addToLibrary": "Adicionar à biblioteca",
"removeFromLibrary": "Remover da biblioteca", "removeFromLibrary": "Remover da biblioteca",
"libraryLoadingMessage": "Carregando biblioteca…", "libraryLoadingMessage": "Carregando biblioteca…",
@@ -117,7 +117,7 @@
"edit": "Editar", "edit": "Editar",
"undo": "Desfazer", "undo": "Desfazer",
"redo": "Refazer", "redo": "Refazer",
"roomDialog": "Iniciar colaboração ao vivo", "resetLibrary": "Redefinir biblioteca",
"createNewRoom": "Criar nova sala", "createNewRoom": "Criar nova sala",
"fullScreen": "Tela cheia", "fullScreen": "Tela cheia",
"darkMode": "Modo escuro", "darkMode": "Modo escuro",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Houve um erro ao carregar a biblioteca de terceiros.", "errorLoadingLibrary": "Houve um erro ao carregar a biblioteca de terceiros.",
"confirmAddLibrary": "Isso adicionará {{numShapes}} forma(s) à sua biblioteca. Tem certeza?", "confirmAddLibrary": "Isso adicionará {{numShapes}} forma(s) à sua biblioteca. Tem certeza?",
"imageDoesNotContainScene": "A importação de imagens não é suportada no momento.\n\nVocê deseja importar uma cena? Esta imagem parece não conter dados de cena. Você ativou isto durante a exportação?", "imageDoesNotContainScene": "A importação de imagens não é suportada no momento.\n\nVocê deseja importar uma cena? Esta imagem parece não conter dados de cena. Você ativou isto durante a exportação?",
"cannotRestoreFromImage": "Não foi possível restaurar a cena deste arquivo de imagem" "cannotRestoreFromImage": "Não foi possível restaurar a cena deste arquivo de imagem",
"resetLibrary": "Isto limpará a sua biblioteca. Você tem certeza?"
}, },
"toolBar": { "toolBar": {
"selection": "Seleção", "selection": "Seleção",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "Estilos copiados.", "copyStyles": "Estilos copiados.",
"copyToClipboard": "Copiado para área de transferência.", "copyToClipboard": "Copiado para área de transferência.",
"copyToClipboardAsPng": "Copiado para a área de transferência como PNG." "copyToClipboardAsPng": "Copiado para a área de transferência como PNG.",
"fileSaved": "Arquivo salvo.",
"fileSavedToFilename": "Salvo em {filename}"
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "Camadas", "layers": "Camadas",
"actions": "Ações", "actions": "Ações",
"language": "Idioma", "language": "Idioma",
"createRoom": "Compartilhar uma sessão de colaboração ao vivo", "liveCollaboration": "",
"duplicateSelection": "Duplicar", "duplicateSelection": "Duplicar",
"untitled": "Sem título", "untitled": "Sem título",
"name": "Nome", "name": "Nome",
@@ -77,7 +77,7 @@
"group": "Agrupar seleção", "group": "Agrupar seleção",
"ungroup": "Desagrupar seleção", "ungroup": "Desagrupar seleção",
"collaborators": "Colaboradores", "collaborators": "Colaboradores",
"gridMode": "Modo grade", "showGrid": "",
"addToLibrary": "Adicionar à biblioteca", "addToLibrary": "Adicionar à biblioteca",
"removeFromLibrary": "Remover da biblioteca", "removeFromLibrary": "Remover da biblioteca",
"libraryLoadingMessage": "Carregando biblioteca…", "libraryLoadingMessage": "Carregando biblioteca…",
@@ -117,7 +117,7 @@
"edit": "Editar", "edit": "Editar",
"undo": "Desfazer", "undo": "Desfazer",
"redo": "Refazer", "redo": "Refazer",
"roomDialog": "Iniciar colaboração ao vivo", "resetLibrary": "",
"createNewRoom": "Criar nova sala", "createNewRoom": "Criar nova sala",
"fullScreen": "Tela cheia", "fullScreen": "Tela cheia",
"darkMode": "Modo escuro", "darkMode": "Modo escuro",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Houve um erro ao carregar a biblioteca de terceiros.", "errorLoadingLibrary": "Houve um erro ao carregar a biblioteca de terceiros.",
"confirmAddLibrary": "Isso adicionará {{numShapes}} forma(s) à sua biblioteca. Tem certeza?", "confirmAddLibrary": "Isso adicionará {{numShapes}} forma(s) à sua biblioteca. Tem certeza?",
"imageDoesNotContainScene": "A importação de imagens não é suportada no momento.\n\nVocê deseja importar uma cena? Esta imagem parece não conter dados de cena. Você ativou isto durante a exportação?", "imageDoesNotContainScene": "A importação de imagens não é suportada no momento.\n\nVocê deseja importar uma cena? Esta imagem parece não conter dados de cena. Você ativou isto durante a exportação?",
"cannotRestoreFromImage": "Não foi possível restaurar a cena deste arquivo de imagem" "cannotRestoreFromImage": "Não foi possível restaurar a cena deste arquivo de imagem",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "Seleção", "selection": "Seleção",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "Estilos copiados.", "copyStyles": "Estilos copiados.",
"copyToClipboard": "", "copyToClipboard": "",
"copyToClipboardAsPng": "Copiado para o clipboard como PNG." "copyToClipboardAsPng": "Copiado para o clipboard como PNG.",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "Straturi", "layers": "Straturi",
"actions": "Acțiuni", "actions": "Acțiuni",
"language": "Limbă", "language": "Limbă",
"createRoom": "Invită la o sesiune de colaborare în direct", "liveCollaboration": "Colaborare în direct",
"duplicateSelection": "Duplicare", "duplicateSelection": "Duplicare",
"untitled": "Nedenumit", "untitled": "Nedenumit",
"name": "Nume", "name": "Nume",
@@ -77,7 +77,7 @@
"group": "Grupare selecție", "group": "Grupare selecție",
"ungroup": "Degrupare selecție", "ungroup": "Degrupare selecție",
"collaborators": "Colaboratori", "collaborators": "Colaboratori",
"gridMode": "Mod grilă", "showGrid": "Afișare grilă",
"addToLibrary": "Adăugare la bibliotecă", "addToLibrary": "Adăugare la bibliotecă",
"removeFromLibrary": "Eliminare din bibliotecă", "removeFromLibrary": "Eliminare din bibliotecă",
"libraryLoadingMessage": "Se încarcă biblioteca…", "libraryLoadingMessage": "Se încarcă biblioteca…",
@@ -117,7 +117,7 @@
"edit": "Edit", "edit": "Edit",
"undo": "Anulare", "undo": "Anulare",
"redo": "Refacere", "redo": "Refacere",
"roomDialog": "Colaborare în direct", "resetLibrary": "Resetare bibliotecă",
"createNewRoom": "Creare cameră nouă", "createNewRoom": "Creare cameră nouă",
"fullScreen": "Ecran complet", "fullScreen": "Ecran complet",
"darkMode": "Mod întunecat", "darkMode": "Mod întunecat",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "A apărut o eroare la încărcarea bibliotecii terțe.", "errorLoadingLibrary": "A apărut o eroare la încărcarea bibliotecii terțe.",
"confirmAddLibrary": "Această acțiune va adăuga {{numShapes}} formă(e) la biblioteca ta. Confirmi?", "confirmAddLibrary": "Această acțiune va adăuga {{numShapes}} formă(e) la biblioteca ta. Confirmi?",
"imageDoesNotContainScene": "Importarea imaginilor nu este acceptată în acest moment.\n\nVoiai să imporți o scenă? Această imagine nu pare să conțină date de scenă. Ai activat această opțiune pe durata exportării?", "imageDoesNotContainScene": "Importarea imaginilor nu este acceptată în acest moment.\n\nVoiai să imporți o scenă? Această imagine nu pare să conțină date de scenă. Ai activat această opțiune pe durata exportării?",
"cannotRestoreFromImage": "Scena nu a putut fi restaurată din acest fișier de imagine" "cannotRestoreFromImage": "Scena nu a putut fi restaurată din acest fișier de imagine",
"resetLibrary": "Această opțiune va elimina conținutul din bibliotecă. Confirmi?"
}, },
"toolBar": { "toolBar": {
"selection": "Selecție", "selection": "Selecție",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "Stiluri copiate.", "copyStyles": "Stiluri copiate.",
"copyToClipboard": "Copiat în memoria temporară.", "copyToClipboard": "Copiat în memoria temporară.",
"copyToClipboardAsPng": "Copiat în memoria temporară ca PNG." "copyToClipboardAsPng": "Copiat în memoria temporară ca PNG.",
"fileSaved": "Fișier salvat.",
"fileSavedToFilename": "Salvat în {filename}"
} }
} }
+13 -10
View File
@@ -68,7 +68,7 @@
"layers": "Слои", "layers": "Слои",
"actions": "Действия", "actions": "Действия",
"language": "Язык", "language": "Язык",
"createRoom": "Начать сеанс совместной работы", "liveCollaboration": "Совместное взаимодействие",
"duplicateSelection": "Дубликат", "duplicateSelection": "Дубликат",
"untitled": "Безымянный", "untitled": "Безымянный",
"name": "Имя", "name": "Имя",
@@ -77,7 +77,7 @@
"group": "Сгруппировать выделение", "group": "Сгруппировать выделение",
"ungroup": "Разделить выделение", "ungroup": "Разделить выделение",
"collaborators": "Участники", "collaborators": "Участники",
"gridMode": "Сетка", "showGrid": "Показать сетку",
"addToLibrary": "Добавить в библиотеку", "addToLibrary": "Добавить в библиотеку",
"removeFromLibrary": "Удалить из библиотеки", "removeFromLibrary": "Удалить из библиотеки",
"libraryLoadingMessage": "Загрузка библиотеки…", "libraryLoadingMessage": "Загрузка библиотеки…",
@@ -117,7 +117,7 @@
"edit": "Изменить", "edit": "Изменить",
"undo": "Шаг назад", "undo": "Шаг назад",
"redo": "Шаг вперед", "redo": "Шаг вперед",
"roomDialog": "Начать совместную работу", "resetLibrary": "Сброс библиотеки",
"createNewRoom": "Создать новую комнату", "createNewRoom": "Создать новую комнату",
"fullScreen": "Полный экран", "fullScreen": "Полный экран",
"darkMode": "Темная тема", "darkMode": "Темная тема",
@@ -136,11 +136,12 @@
"decryptFailed": "Не удалось расшифровать данные.", "decryptFailed": "Не удалось расшифровать данные.",
"uploadedSecurly": "Загружаемые данные защищена сквозным шифрованием, что означает, что сервер Excalidraw и третьи стороны не могут прочитать содержимое.", "uploadedSecurly": "Загружаемые данные защищена сквозным шифрованием, что означает, что сервер Excalidraw и третьи стороны не могут прочитать содержимое.",
"loadSceneOverridePrompt": "Загрузка рисунка приведёт к замене имеющегося содержимого. Вы хотите продолжить?", "loadSceneOverridePrompt": "Загрузка рисунка приведёт к замене имеющегося содержимого. Вы хотите продолжить?",
"collabStopOverridePrompt": "", "collabStopOverridePrompt": "Остановка сессии перезапишет ваш предыдущий, локально сохранённый рисунок. Вы уверены? \n\n(Если вы хотите оставить ваш локальный рисунок, просто закройте вкладку браузера)",
"errorLoadingLibrary": "Произошла ошибка при загрузке сторонней библиотеки.", "errorLoadingLibrary": "Произошла ошибка при загрузке сторонней библиотеки.",
"confirmAddLibrary": "Будет добавлено {{numShapes}} фигур в вашу библиотеку. Продолжить?", "confirmAddLibrary": "Будет добавлено {{numShapes}} фигур в вашу библиотеку. Продолжить?",
"imageDoesNotContainScene": "Импорт изображений не поддерживается в данный момент.\n\nХотите импортировать сцену? Данное изображение не содержит данных о сцене. Было ли включено это во время экспорта?", "imageDoesNotContainScene": "Импорт изображений не поддерживается в данный момент.\n\nХотите импортировать сцену? Данное изображение не содержит данных о сцене. Было ли включено это во время экспорта?",
"cannotRestoreFromImage": "Сцена не может быть восстановлена из этого изображения" "cannotRestoreFromImage": "Сцена не может быть восстановлена из этого изображения",
"resetLibrary": "Это очистит вашу библиотеку. Вы уверены?"
}, },
"toolBar": { "toolBar": {
"selection": "Выделение области", "selection": "Выделение области",
@@ -235,14 +236,16 @@
"storage": "Хранилище", "storage": "Хранилище",
"title": "Статистика для ботаников", "title": "Статистика для ботаников",
"total": "Всего", "total": "Всего",
"version": "", "version": "Версия",
"versionCopy": "", "versionCopy": "Копировать",
"versionNotAvailable": "", "versionNotAvailable": "Версия не доступна",
"width": "Ширина" "width": "Ширина"
}, },
"toast": { "toast": {
"copyStyles": "Скопированы стили.", "copyStyles": "Скопированы стили.",
"copyToClipboard": "", "copyToClipboard": "Скопировано в буфер обмена.",
"copyToClipboardAsPng": "Скопировано в буфер обмена в формате PNG." "copyToClipboardAsPng": "Скопировано в буфер обмена в формате PNG.",
"fileSaved": "Файл сохранён.",
"fileSavedToFilename": "Сохранено в {filename}"
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "Vrstvy", "layers": "Vrstvy",
"actions": "Akcie", "actions": "Akcie",
"language": "Jazyk", "language": "Jazyk",
"createRoom": "Zdieľajte živú spoluprácu", "liveCollaboration": ivá spolupráca",
"duplicateSelection": "Duplikovať", "duplicateSelection": "Duplikovať",
"untitled": "Bez názvu", "untitled": "Bez názvu",
"name": "Meno", "name": "Meno",
@@ -77,7 +77,7 @@
"group": "Zoskupiť", "group": "Zoskupiť",
"ungroup": "Zrušiť zoskupenie", "ungroup": "Zrušiť zoskupenie",
"collaborators": "Spolupracovníci", "collaborators": "Spolupracovníci",
"gridMode": "Režim mriežky", "showGrid": "Zobraziť mriežku",
"addToLibrary": "Pridať do knižnice", "addToLibrary": "Pridať do knižnice",
"removeFromLibrary": "Odstrániť z knižnice", "removeFromLibrary": "Odstrániť z knižnice",
"libraryLoadingMessage": "Načítavanie knižnice…", "libraryLoadingMessage": "Načítavanie knižnice…",
@@ -117,7 +117,7 @@
"edit": "Upraviť", "edit": "Upraviť",
"undo": "Späť", "undo": "Späť",
"redo": "Znova", "redo": "Znova",
"roomDialog": "Začať živú spoluprácu", "resetLibrary": "Obnoviť knižnicu",
"createNewRoom": "Vytvoriť novú miestnosť", "createNewRoom": "Vytvoriť novú miestnosť",
"fullScreen": "Celá obrazovka", "fullScreen": "Celá obrazovka",
"darkMode": "Tmavý režim", "darkMode": "Tmavý režim",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Nepodarilo sa načítať externú knižnicu.", "errorLoadingLibrary": "Nepodarilo sa načítať externú knižnicu.",
"confirmAddLibrary": "Týmto sa pridá {{numShapes}} tvar(ov) do vašej knižnice. Ste si istí?", "confirmAddLibrary": "Týmto sa pridá {{numShapes}} tvar(ov) do vašej knižnice. Ste si istí?",
"imageDoesNotContainScene": "Importovanie obrázku v tomto momente nie je možné.\n\nChceli ste importovať scénu? Tento obrázok neobsahuje žiadne údaje scény. Povolili ste túto možnosť počas exportovania?", "imageDoesNotContainScene": "Importovanie obrázku v tomto momente nie je možné.\n\nChceli ste importovať scénu? Tento obrázok neobsahuje žiadne údaje scény. Povolili ste túto možnosť počas exportovania?",
"cannotRestoreFromImage": "Nepodarilo sa obnoviť scénu z tohto obrázkového súboru" "cannotRestoreFromImage": "Nepodarilo sa obnoviť scénu z tohto obrázkového súboru",
"resetLibrary": "Týmto vyprázdnite vašu knižnicu. Ste si istý?"
}, },
"toolBar": { "toolBar": {
"selection": "Výber", "selection": "Výber",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "Štýly skopírované.", "copyStyles": "Štýly skopírované.",
"copyToClipboard": "Skopírované do schránky.", "copyToClipboard": "Skopírované do schránky.",
"copyToClipboardAsPng": "Skopírované do schránky ako PNG." "copyToClipboardAsPng": "Skopírované do schránky ako PNG.",
"fileSaved": "Súbor uložený.",
"fileSavedToFilename": "Uložený ako {filename}"
} }
} }
+12 -9
View File
@@ -68,7 +68,7 @@
"layers": "Lager", "layers": "Lager",
"actions": "Åtgärder", "actions": "Åtgärder",
"language": "Språk", "language": "Språk",
"createRoom": "Dela en live-samarbetssession", "liveCollaboration": "Samarbeta live",
"duplicateSelection": "Duplicera", "duplicateSelection": "Duplicera",
"untitled": "Namnlös", "untitled": "Namnlös",
"name": "Namn", "name": "Namn",
@@ -77,7 +77,7 @@
"group": "Gruppera markering", "group": "Gruppera markering",
"ungroup": "Avgruppera markering", "ungroup": "Avgruppera markering",
"collaborators": "Medarbetare", "collaborators": "Medarbetare",
"gridMode": "Rutnätsläge", "showGrid": "Visa rutnät",
"addToLibrary": "Lägg till i biblioteket", "addToLibrary": "Lägg till i biblioteket",
"removeFromLibrary": "Ta bort från bibliotek", "removeFromLibrary": "Ta bort från bibliotek",
"libraryLoadingMessage": "Laddar bibliotek…", "libraryLoadingMessage": "Laddar bibliotek…",
@@ -117,7 +117,7 @@
"edit": "Redigera", "edit": "Redigera",
"undo": "Ångra", "undo": "Ångra",
"redo": "Gör om", "redo": "Gör om",
"roomDialog": "Starta live-samarbete", "resetLibrary": "Återställ bibliotek",
"createNewRoom": "Skapa ett nytt rum", "createNewRoom": "Skapa ett nytt rum",
"fullScreen": "Helskärm", "fullScreen": "Helskärm",
"darkMode": "Mörkt läge", "darkMode": "Mörkt läge",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Fel vid inläsning av tredjeparts bibliotek.", "errorLoadingLibrary": "Fel vid inläsning av tredjeparts bibliotek.",
"confirmAddLibrary": "Detta kommer att lägga till {{numShapes}} form(er) till ditt bibliotek. Är du säker?", "confirmAddLibrary": "Detta kommer att lägga till {{numShapes}} form(er) till ditt bibliotek. Är du säker?",
"imageDoesNotContainScene": "Importering av bilder stöds inte just nu.\n\nVill du importera en skiss? Den här bilden verkar inte innehålla någon skissdata. Har du aktiverat detta under export?", "imageDoesNotContainScene": "Importering av bilder stöds inte just nu.\n\nVill du importera en skiss? Den här bilden verkar inte innehålla någon skissdata. Har du aktiverat detta under export?",
"cannotRestoreFromImage": "Skiss kunde inte återställas från denna bildfil" "cannotRestoreFromImage": "Skiss kunde inte återställas från denna bildfil",
"resetLibrary": "Detta kommer att rensa ditt bibliotek. Är du säker?"
}, },
"toolBar": { "toolBar": {
"selection": "Markering", "selection": "Markering",
@@ -235,14 +236,16 @@
"storage": "Lagring", "storage": "Lagring",
"title": "Statistik för nördar", "title": "Statistik för nördar",
"total": "Totalt", "total": "Totalt",
"version": "", "version": "Version",
"versionCopy": "", "versionCopy": "Klicka för att kopiera",
"versionNotAvailable": "", "versionNotAvailable": "Versionen är inte tillgänglig",
"width": "Bredd" "width": "Bredd"
}, },
"toast": { "toast": {
"copyStyles": "Kopierade stilar.", "copyStyles": "Kopierade stilar.",
"copyToClipboard": "", "copyToClipboard": "Kopierad till urklipp.",
"copyToClipboardAsPng": "Kopierat till urklipp som PNG." "copyToClipboardAsPng": "Kopierat till urklipp som PNG.",
"fileSaved": "Fil sparad.",
"fileSavedToFilename": "Sparad till {filename}"
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "Katmanlar", "layers": "Katmanlar",
"actions": "Eylemler", "actions": "Eylemler",
"language": "Dil", "language": "Dil",
"createRoom": "Ortak çalışma ortamını paylaş", "liveCollaboration": "",
"duplicateSelection": "Çoğalt", "duplicateSelection": "Çoğalt",
"untitled": "Adsız", "untitled": "Adsız",
"name": "İsim", "name": "İsim",
@@ -77,7 +77,7 @@
"group": "Seçimi grup yap", "group": "Seçimi grup yap",
"ungroup": "Seçilen grubu dağıt", "ungroup": "Seçilen grubu dağıt",
"collaborators": "Ortaklar", "collaborators": "Ortaklar",
"gridMode": "Izgara modu", "showGrid": "",
"addToLibrary": "Kütüphaneye ekle", "addToLibrary": "Kütüphaneye ekle",
"removeFromLibrary": "Kütüphaneden kaldır", "removeFromLibrary": "Kütüphaneden kaldır",
"libraryLoadingMessage": "Kütüphane yükleniyor…", "libraryLoadingMessage": "Kütüphane yükleniyor…",
@@ -117,7 +117,7 @@
"edit": "Düzenle", "edit": "Düzenle",
"undo": "Geri Al", "undo": "Geri Al",
"redo": "Yeniden yap", "redo": "Yeniden yap",
"roomDialog": "Ortak çalışma ortamı yarat", "resetLibrary": "",
"createNewRoom": "Yeni oda oluştur", "createNewRoom": "Yeni oda oluştur",
"fullScreen": "Tam ekran", "fullScreen": "Tam ekran",
"darkMode": "Koyu tema", "darkMode": "Koyu tema",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "Üçüncü taraf kitaplığı yüklerken bir hata oluştu.", "errorLoadingLibrary": "Üçüncü taraf kitaplığı yüklerken bir hata oluştu.",
"confirmAddLibrary": "Bu, kitaplığınıza {{numShapes}} tane şekil ekleyecek. Emin misiniz?", "confirmAddLibrary": "Bu, kitaplığınıza {{numShapes}} tane şekil ekleyecek. Emin misiniz?",
"imageDoesNotContainScene": "Resim ekleme şuan için desteklenmiyor.\nBir sahneyi içeri aktarmak mı istediniz? Bu dosya herhangi bir sahne içeriyor gibi durmuyor. Çıktı alırken sahneyi dahil ettiniz mi?", "imageDoesNotContainScene": "Resim ekleme şuan için desteklenmiyor.\nBir sahneyi içeri aktarmak mı istediniz? Bu dosya herhangi bir sahne içeriyor gibi durmuyor. Çıktı alırken sahneyi dahil ettiniz mi?",
"cannotRestoreFromImage": "Sahne bu dosyadan oluşturulamıyor" "cannotRestoreFromImage": "Sahne bu dosyadan oluşturulamıyor",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "Seçme", "selection": "Seçme",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "", "copyStyles": "",
"copyToClipboard": "", "copyToClipboard": "",
"copyToClipboardAsPng": "" "copyToClipboardAsPng": "",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+14 -11
View File
@@ -68,7 +68,7 @@
"layers": "Шари", "layers": "Шари",
"actions": "Дії", "actions": "Дії",
"language": "Мова", "language": "Мова",
"createRoom": "Поділитися сесією для спільної роботи", "liveCollaboration": "",
"duplicateSelection": "Дублювати", "duplicateSelection": "Дублювати",
"untitled": "Без назви", "untitled": "Без назви",
"name": "Ім’я", "name": "Ім’я",
@@ -77,7 +77,7 @@
"group": "Групувати виділене", "group": "Групувати виділене",
"ungroup": "Розгрупувати виділене", "ungroup": "Розгрупувати виділене",
"collaborators": "Співавтори", "collaborators": "Співавтори",
"gridMode": "Режим сітки", "showGrid": "Показати сітку",
"addToLibrary": "Додати до бібліотеки", "addToLibrary": "Додати до бібліотеки",
"removeFromLibrary": "Видалити з бібліотеки", "removeFromLibrary": "Видалити з бібліотеки",
"libraryLoadingMessage": "Завантажити бібліотеку…", "libraryLoadingMessage": "Завантажити бібліотеку…",
@@ -92,7 +92,7 @@
"centerHorizontally": "Центрувати по горизонталі", "centerHorizontally": "Центрувати по горизонталі",
"distributeHorizontally": "Розподілити по горизонталі", "distributeHorizontally": "Розподілити по горизонталі",
"distributeVertically": "Розподілити вертикально", "distributeVertically": "Розподілити вертикально",
"viewMode": "" "viewMode": "Режим перегляду"
}, },
"buttons": { "buttons": {
"clearReset": "Очистити полотно", "clearReset": "Очистити полотно",
@@ -117,7 +117,7 @@
"edit": "Редагувати", "edit": "Редагувати",
"undo": "Відмінити", "undo": "Відмінити",
"redo": "Повторити", "redo": "Повторити",
"roomDialog": "Відкрити сесію спільної роботи", "resetLibrary": "",
"createNewRoom": "Створити нову кімнату", "createNewRoom": "Створити нову кімнату",
"fullScreen": "Повноекранний режим", "fullScreen": "Повноекранний режим",
"darkMode": "Темний режим", "darkMode": "Темний режим",
@@ -136,11 +136,12 @@
"decryptFailed": "Не вдалося розшифрувати дані.", "decryptFailed": "Не вдалося розшифрувати дані.",
"uploadedSecurly": "Це завантаження було захищене наскрізним шифруванням, а це означає що сервер Excalidraw та інші не зможуть прочитати вміст.", "uploadedSecurly": "Це завантаження було захищене наскрізним шифруванням, а це означає що сервер Excalidraw та інші не зможуть прочитати вміст.",
"loadSceneOverridePrompt": "Завантаження зовнішнього креслення замінить ваш наявний контент. Продовжити?", "loadSceneOverridePrompt": "Завантаження зовнішнього креслення замінить ваш наявний контент. Продовжити?",
"collabStopOverridePrompt": "", "collabStopOverridePrompt": "Зупинка сесії перезапише ваш попередній, локально збережений малюнок. Ви впевнені?\n\n(Якщо ви хочете зберегти локальний малюнок, просто закрийте замість нього вкладку браузера.)",
"errorLoadingLibrary": "Помилка при завантаженні сторонньої бібліотеки.", "errorLoadingLibrary": "Помилка при завантаженні сторонньої бібліотеки.",
"confirmAddLibrary": "Це призведе до додавання {{numShapes}} фігур до вашої бібліотеки. Ви впевнені?", "confirmAddLibrary": "Це призведе до додавання {{numShapes}} фігур до вашої бібліотеки. Ви впевнені?",
"imageDoesNotContainScene": "Імпортування зображень на даний момент не підтримується.\n\nЧи хочете ви імпортувати сцену? Це зображення не містить ніяких даних сцен. Ви увімкнули це під час експорту?", "imageDoesNotContainScene": "Імпортування зображень на даний момент не підтримується.\n\nЧи хочете ви імпортувати сцену? Це зображення не містить ніяких даних сцен. Ви увімкнули це під час експорту?",
"cannotRestoreFromImage": "Сцена не може бути відновлена з цього файлу зображення" "cannotRestoreFromImage": "Сцена не може бути відновлена з цього файлу зображення",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "Виділення", "selection": "Виділення",
@@ -235,14 +236,16 @@
"storage": "Сховище", "storage": "Сховище",
"title": "Статистика", "title": "Статистика",
"total": "Всього", "total": "Всього",
"version": "", "version": "Версія",
"versionCopy": "", "versionCopy": "Натисніть, щоб скопіювати",
"versionNotAvailable": "", "versionNotAvailable": "Версія недоступна",
"width": "Ширина" "width": "Ширина"
}, },
"toast": { "toast": {
"copyStyles": "Скопійовані стилі.", "copyStyles": "Скопійовані стилі.",
"copyToClipboard": "", "copyToClipboard": "Скопіювати до буферу обміну.",
"copyToClipboardAsPng": "Скопійовано в буфер обміну як PNG." "copyToClipboardAsPng": "Скопійовано в буфер обміну як PNG.",
"fileSaved": "Файл збережено.",
"fileSavedToFilename": "Збережено в {filename}"
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "图层", "layers": "图层",
"actions": "操作", "actions": "操作",
"language": "语言", "language": "语言",
"createRoom": "分享实时协作会议", "liveCollaboration": "",
"duplicateSelection": "复制", "duplicateSelection": "复制",
"untitled": "无标题", "untitled": "无标题",
"name": "名字", "name": "名字",
@@ -77,7 +77,7 @@
"group": "组选", "group": "组选",
"ungroup": "取消组选", "ungroup": "取消组选",
"collaborators": "协作者", "collaborators": "协作者",
"gridMode": "网格模式", "showGrid": "",
"addToLibrary": "添加到库中", "addToLibrary": "添加到库中",
"removeFromLibrary": "从库中移除", "removeFromLibrary": "从库中移除",
"libraryLoadingMessage": "正在加载库…", "libraryLoadingMessage": "正在加载库…",
@@ -117,7 +117,7 @@
"edit": "编辑", "edit": "编辑",
"undo": "撤销", "undo": "撤销",
"redo": "重做", "redo": "重做",
"roomDialog": "开始实时协作", "resetLibrary": "",
"createNewRoom": "新建会议室", "createNewRoom": "新建会议室",
"fullScreen": "全屏", "fullScreen": "全屏",
"darkMode": "暗色主题", "darkMode": "暗色主题",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "加载第三方库时出错。", "errorLoadingLibrary": "加载第三方库时出错。",
"confirmAddLibrary": "这将添加 {{numShapes}} 个形状到您的库。您确定吗?", "confirmAddLibrary": "这将添加 {{numShapes}} 个形状到您的库。您确定吗?",
"imageDoesNotContainScene": "当前不支持导入图片。\n\n您想要导入画布数据吗?此图像似乎不包含任何画布数据。您是否在导出过程中启用了嵌入画布的选项?", "imageDoesNotContainScene": "当前不支持导入图片。\n\n您想要导入画布数据吗?此图像似乎不包含任何画布数据。您是否在导出过程中启用了嵌入画布的选项?",
"cannotRestoreFromImage": "无法从此图像文件恢复画布" "cannotRestoreFromImage": "无法从此图像文件恢复画布",
"resetLibrary": ""
}, },
"toolBar": { "toolBar": {
"selection": "选择", "selection": "选择",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "复制样式", "copyStyles": "复制样式",
"copyToClipboard": "", "copyToClipboard": "",
"copyToClipboardAsPng": "复制为 PNG 到剪贴板" "copyToClipboardAsPng": "复制为 PNG 到剪贴板",
"fileSaved": "",
"fileSavedToFilename": ""
} }
} }
+8 -5
View File
@@ -68,7 +68,7 @@
"layers": "圖層", "layers": "圖層",
"actions": "動作", "actions": "動作",
"language": "語言", "language": "語言",
"createRoom": "建立新協作會議室", "liveCollaboration": "即時協作",
"duplicateSelection": "複製", "duplicateSelection": "複製",
"untitled": "無標題", "untitled": "無標題",
"name": "名稱", "name": "名稱",
@@ -77,7 +77,7 @@
"group": "建立群組", "group": "建立群組",
"ungroup": "取消群組", "ungroup": "取消群組",
"collaborators": "協作者", "collaborators": "協作者",
"gridMode": "網格模式", "showGrid": "顯示格線",
"addToLibrary": "加入資料庫", "addToLibrary": "加入資料庫",
"removeFromLibrary": "從資料庫中移除", "removeFromLibrary": "從資料庫中移除",
"libraryLoadingMessage": "資料庫讀取中…", "libraryLoadingMessage": "資料庫讀取中…",
@@ -117,7 +117,7 @@
"edit": "編輯", "edit": "編輯",
"undo": "復原", "undo": "復原",
"redo": "重做", "redo": "重做",
"roomDialog": "開始即時協作", "resetLibrary": "重設資料庫",
"createNewRoom": "建立新協作會議室", "createNewRoom": "建立新協作會議室",
"fullScreen": "全螢幕", "fullScreen": "全螢幕",
"darkMode": "深色模式", "darkMode": "深色模式",
@@ -140,7 +140,8 @@
"errorLoadingLibrary": "載入第三方套件時出現錯誤。", "errorLoadingLibrary": "載入第三方套件時出現錯誤。",
"confirmAddLibrary": "這將會將 {{numShapes}} 個圖形加入你的資料庫,你確定嗎?", "confirmAddLibrary": "這將會將 {{numShapes}} 個圖形加入你的資料庫,你確定嗎?",
"imageDoesNotContainScene": "目前尚不支援載入圖片。\n您是否要載入場景?此圖片中並無任何場景資料,輸出時是否有選擇包含?", "imageDoesNotContainScene": "目前尚不支援載入圖片。\n您是否要載入場景?此圖片中並無任何場景資料,輸出時是否有選擇包含?",
"cannotRestoreFromImage": "無法由此檔案回復場景。" "cannotRestoreFromImage": "無法由此檔案回復場景。",
"resetLibrary": "這會清除您的資料庫,是否確定?"
}, },
"toolBar": { "toolBar": {
"selection": "選取", "selection": "選取",
@@ -243,6 +244,8 @@
"toast": { "toast": {
"copyStyles": "已複製樣式", "copyStyles": "已複製樣式",
"copyToClipboard": "複製至剪貼簿。", "copyToClipboard": "複製至剪貼簿。",
"copyToClipboardAsPng": "已複製 PNG 至剪貼簿" "copyToClipboardAsPng": "已複製 PNG 至剪貼簿",
"fileSaved": "已儲存檔案。",
"fileSavedToFilename": "儲存為 {filename}"
} }
} }
+9 -6
View File
@@ -1,4 +1,4 @@
import { Point } from "./types"; import { NormalizedZoomValue, Point, Zoom } from "./types";
import { LINE_CONFIRM_THRESHOLD } from "./constants"; import { LINE_CONFIRM_THRESHOLD } from "./constants";
import { ExcalidrawLinearElement } from "./element/types"; import { ExcalidrawLinearElement } from "./element/types";
@@ -147,13 +147,16 @@ export const centerPoint = (a: Point, b: Point): Point => {
// to be considered a loop // to be considered a loop
export const isPathALoop = ( export const isPathALoop = (
points: ExcalidrawLinearElement["points"], points: ExcalidrawLinearElement["points"],
/** supply if you want the loop detection to account for current zoom */
zoomValue: Zoom["value"] = 1 as NormalizedZoomValue,
): boolean => { ): boolean => {
if (points.length >= 3) { if (points.length >= 3) {
const [firstPoint, lastPoint] = [points[0], points[points.length - 1]]; const [first, last] = [points[0], points[points.length - 1]];
return ( const distance = distance2d(first[0], first[1], last[0], last[1]);
distance2d(firstPoint[0], firstPoint[1], lastPoint[0], lastPoint[1]) <=
LINE_CONFIRM_THRESHOLD // Adjusting LINE_CONFIRM_THRESHOLD to current zoom so that when zoomed in
); // really close we make the threshold smaller, and vice versa.
return distance <= LINE_CONFIRM_THRESHOLD / zoomValue;
} }
return false; return false;
}; };
+75
View File
@@ -18,22 +18,97 @@ Please add the latest change on the top under the correct section.
### Features ### Features
- Export [`restore`](https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L182), [`restoreAppState`](https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L144) and [`restoreElements`](https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L128) to host
### Fixes
- Show user state only when [userState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L35) is passed on remote pointers during collaboration [#3050](https://github.com/excalidraw/excalidraw/pull/3050)
## 0.3.1
## Excalidraw API
### Fixes
- Support Excalidraw inside scrollable container [#3018](https://github.com/excalidraw/excalidraw/pull/3018)
## Excalidraw Library
### Fixes
- Allow to toggle between modes when view only mode to make UI consistent [#3009](https://github.com/excalidraw/excalidraw/pull/3009)
## 0.3.0
## Excalidraw API
### Features
- Allow host to pass [color](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L36) for [collaborator](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L27) [#2943](https://github.com/excalidraw/excalidraw/pull/2943). The unused prop `user` is now removed.
- Add `zenModeEnabled` and `gridModeEnabled` prop which enables zen mode and grid mode respectively [#2901](https://github.com/excalidraw/excalidraw/pull/2901). When this prop is used, the zen mode / grid mode will be fully controlled by the host app.
- Allow host to pass [userState](https://github.com/excalidraw/excalidraw/blob/6967d8c9851c65bb8873e2f97387749976bbe326/src/types.ts#L35) for [collaborator](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L27) to show the current user state [#2877](https://github.com/excalidraw/excalidraw/pull/2877).
- Add `viewModeEnabled` prop which enabled the view mode [#2840](https://github.com/excalidraw/excalidraw/pull/2840). When this prop is used, the view mode will not show up in context menu is so it is fully controlled by host. - Add `viewModeEnabled` prop which enabled the view mode [#2840](https://github.com/excalidraw/excalidraw/pull/2840). When this prop is used, the view mode will not show up in context menu is so it is fully controlled by host.
- Expose `getAppState` on `excalidrawRef` [#2834](https://github.com/excalidraw/excalidraw/pull/2834). - Expose `getAppState` on `excalidrawRef` [#2834](https://github.com/excalidraw/excalidraw/pull/2834).
### Build
- Remove publicPath so host can use `__webpack_public_path__` to host the assets[#2835](https://github.com/excalidraw/excalidraw/pull/2835)
## Excalidraw Library ## Excalidraw Library
### Features ### Features
- Add the ability to clear library [#2997](https://github.com/excalidraw/excalidraw/pull/2997)
- Updates to Collaboration and RTL UX [#2994](https://github.com/excalidraw/excalidraw/pull/2994)
- Show toast when saving to existing file [#2988](https://github.com/excalidraw/excalidraw/pull/2988)
- Support supplying custom scale when exporting canvas [#2904](https://github.com/excalidraw/excalidraw/pull/2904)
- Show version in the stats dialog [#2908](https://github.com/excalidraw/excalidraw/pull/2908)
- Add idle detection to collaboration feature [#2877](https://github.com/excalidraw/excalidraw/pull/2877)
- Add view mode in Excalidraw [#2840](https://github.com/excalidraw/excalidraw/pull/2840)
- Increase max zoom [#2881](https://github.com/excalidraw/excalidraw/pull/2881)
- Remove copy & paste from context menu on desktop [#2872](https://github.com/excalidraw/excalidraw/pull/2872)
- Add separators on context menu [#2659](https://github.com/excalidraw/excalidraw/pull/2659)
- Add ctrl-y to redo [#2831](https://github.com/excalidraw/excalidraw/pull/2831)
- Add view mode [#2840](https://github.com/excalidraw/excalidraw/pull/2840). - Add view mode [#2840](https://github.com/excalidraw/excalidraw/pull/2840).
- Remove `copy`, `cut`, and `paste` actions from contextmenu [#2872](https://github.com/excalidraw/excalidraw/pull/2872) - Remove `copy`, `cut`, and `paste` actions from contextmenu [#2872](https://github.com/excalidraw/excalidraw/pull/2872)
- Support `Ctrl-Y` shortcut to redo on Windows [#2831](https://github.com/excalidraw/excalidraw/pull/2831). - Support `Ctrl-Y` shortcut to redo on Windows [#2831](https://github.com/excalidraw/excalidraw/pull/2831).
### Fixes ### Fixes
- Refresh wysiwyg position on canvas resize [#3008](https://github.com/excalidraw/excalidraw/pull/3008)
- Update the `lang` attribute with the current lang. [#2995](https://github.com/excalidraw/excalidraw/pull/2995)
- Rename 'Grid mode' to 'Show grid' [#2944](https://github.com/excalidraw/excalidraw/pull/2944)
- Deal with users on systems that don't handle emoji [#2941](https://github.com/excalidraw/excalidraw/pull/2941)
- Mobile toolbar tooltip regression [#2939](https://github.com/excalidraw/excalidraw/pull/2939)
- Hide collaborator list on mobile if empty [#2938](https://github.com/excalidraw/excalidraw/pull/2938)
- Toolbar unnecessarily eats too much width [#2924](https://github.com/excalidraw/excalidraw/pull/2924)
- Mistakenly hardcoding scale [#2925](https://github.com/excalidraw/excalidraw/pull/2925)
- Text editor not visible in dark mode [#2920](https://github.com/excalidraw/excalidraw/pull/2920)
- Incorrect z-index of text editor [#2914](https://github.com/excalidraw/excalidraw/pull/2914)
- Make scrollbars draggable when offsets are set [#2916](https://github.com/excalidraw/excalidraw/pull/2916)
- Pointer-events being disabled on free-draw [#2912](https://github.com/excalidraw/excalidraw/pull/2912)
- Track zenmode and grid mode usage [#2900](https://github.com/excalidraw/excalidraw/pull/2900)
- Disable UI pointer-events on canvas drag [#2856](https://github.com/excalidraw/excalidraw/pull/2856)
- Stop flooring scroll positions [#2883](https://github.com/excalidraw/excalidraw/pull/2883)
- Apply initialData appState for zenmode and grid stats and refactor check param for actions [#2871](https://github.com/excalidraw/excalidraw/pull/2871)
- Show correct state of Nerd stats in context menu when nerd stats dialog closed [#2874](https://github.com/excalidraw/excalidraw/pull/2874)
- Remote pointers not accounting for offset [#2855](https://github.com/excalidraw/excalidraw/pull/2855)
- Toggle help dialog when "shift+?" is pressed [#2828](https://github.com/excalidraw/excalidraw/pull/2828)
- Add safe check for process so Excalidraw can be loaded via script [#2824](https://github.com/excalidraw/excalidraw/pull/2824)
- Fix UI pointer-events not disabled when dragging on canvas [#2856](https://github.com/excalidraw/excalidraw/pull/2856). - Fix UI pointer-events not disabled when dragging on canvas [#2856](https://github.com/excalidraw/excalidraw/pull/2856).
- Fix remote pointers not accounting for offset [#2855](https://github.com/excalidraw/excalidraw/pull/2855). - Fix remote pointers not accounting for offset [#2855](https://github.com/excalidraw/excalidraw/pull/2855).
### Refactor
- Remove duplicate key handling [#2878](https://github.com/excalidraw/excalidraw/pull/2878)
- Reuse scss variables in js for SSOT [#2867](https://github.com/excalidraw/excalidraw/pull/2867)
- Rename browser-nativefs to browser-fs-access [#2862](https://github.com/excalidraw/excalidraw/pull/2862)
- Rewrite collabWrapper to remove TDZs and simplify [#2834](https://github.com/excalidraw/excalidraw/pull/2834)
### Chore
- Use `Sentence case` for `Live collaboration`
## 0.2.1 ## 0.2.1
## Excalidraw API ## Excalidraw API
+249 -83
View File
@@ -18,7 +18,15 @@ yarn add react react-dom @excalidraw/excalidraw
After installation you will see a folder `excalidraw-assets` in `dist` directory which contains the assets needed for this app. After installation you will see a folder `excalidraw-assets` in `dist` directory which contains the assets needed for this app.
Move the folder `excalidraw-assets` to the path where your assets are served. In the example its served from `public/excalidraw-assets` Move the folder `excalidraw-assets` to the path where your assets are served.
By default it will try to load the files from `{rootUrl}/excalidraw-assets/`
With **Webpack**, if you want to load the files from different path you can use <pre><a href="https://webpack.js.org/guides/public-path/#on-the-fly">`__webpack_public_path__`</a></pre>.
With **create-react-app**, the assets can be served from `public/static/js/excalidraw-assets`since CRA tries to load the assets from `{rootUrl}/static/js` path by default.
You can update the value of `PUBLIC_URL` if you want to serve it from a different URL.
### Demo ### Demo
@@ -26,31 +34,43 @@ Move the folder `excalidraw-assets` to the path where your assets are served. In
### Usage ### Usage
1. If you are using a Web bundler (for instance, Webpack), you can import it as an ES6 module as shown below
```js ```js
import React, { useEffect, useState, createRef } from "react"; import React, { useEffect, useState, useRef } from "react";
import Excalidraw from "@excalidraw/excalidraw"; import Excalidraw from "@excalidraw/excalidraw";
import InitialData from "./initialData"; import InitialData from "./initialData";
import "./styles.css"; import "./styles.scss";
export default function App() { export default function App() {
const excalidrawRef = createRef(); const excalidrawRef = useRef(null);
const excalidrawWrapperRef = useRef(null);
const [dimensions, setDimensions] = useState({ const [dimensions, setDimensions] = useState({
width: window.innerWidth, width: undefined,
height: window.innerHeight, height: undefined,
}); });
const [viewModeEnabled, setViewModeEnabled] = useState(false);
const [zenModeEnabled, setZenModeEnabled] = useState(false);
const [gridModeEnabled, setGridModeEnabled] = useState(false);
useEffect(() => { useEffect(() => {
setDimensions({
width: excalidrawWrapperRef.current.getBoundingClientRect().width,
height: excalidrawWrapperRef.current.getBoundingClientRect().height,
});
const onResize = () => { const onResize = () => {
setDimensions({ setDimensions({
width: window.innerWidth, width: excalidrawWrapperRef.current.getBoundingClientRect().width,
height: window.innerHeight, height: excalidrawWrapperRef.current.getBoundingClientRect().height,
}); });
}; };
window.addEventListener("resize", onResize); window.addEventListener("resize", onResize);
return () => window.removeEventListener("resize", onResize); return () => window.removeEventListener("resize", onResize);
}, []); }, [excalidrawWrapperRef]);
const updateScene = () => { const updateScene = () => {
const sceneData = { const sceneData = {
@@ -86,31 +106,60 @@ export default function App() {
return ( return (
<div className="App"> <div className="App">
<button className="update-scene" onClick={updateScene}> <h1> Excalidraw Example</h1>
Update Scene <div className="button-wrapper">
</button> <button className="update-scene" onClick={updateScene}>
<button Update Scene
className="reset-scene" </button>
onClick={() => { <button
excalidrawRef.current.resetScene(); className="reset-scene"
}} onClick={() => {
> excalidrawRef.current.resetScene();
Reset Scene }}
</button> >
<div className="excalidraw-wrapper"> Reset Scene
</button>
<label>
<input
type="checkbox"
checked={viewModeEnabled}
onChange={() => setViewModeEnabled(!viewModeEnabled)}
/>
View mode
</label>
<label>
<input
type="checkbox"
checked={zenModeEnabled}
onChange={() => setZenModeEnabled(!zenModeEnabled)}
/>
Zen mode
</label>
<label>
<input
type="checkbox"
checked={gridModeEnabled}
onChange={() => setGridModeEnabled(!gridModeEnabled)}
/>
Grid mode
</label>
</div>
<div className="excalidraw-wrapper" ref={excalidrawWrapperRef}>
<Excalidraw <Excalidraw
ref={excalidrawRef} ref={excalidrawRef}
width={dimensions.width} width={dimensions.width}
height={dimensions.height} height={dimensions.height}
initialData={InitialData} initialData={InitialData}
onChange={(elements, state) => { onChange={(elements, state) =>
console.log("Latest elements:", elements, "Latest state:", state); console.log("Elements :", elements, "State : ", state)
}} }
user={{ name: "Excalidraw User" }} onPointerUpdate={(payload) => console.log(payload)}
onPointerUpdate={(pointerData) => console.log(pointerData)} onCollabButtonClick={() =>
onCollabButtonClick={() => { window.alert("You clicked on collab button")
window.alert("You clicked on collab button"); }
}} viewModeEnabled={viewModeEnabled}
zenModeEnabled={zenModeEnabled}
gridModeEnabled={gridModeEnabled}
/> />
</div> </div>
</div> </div>
@@ -120,6 +169,68 @@ export default function App() {
[![Edit excalidraw](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/excalidraw-ehlz3?fontsize=14&hidenavigation=1&theme=dark) [![Edit excalidraw](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/excalidraw-ehlz3?fontsize=14&hidenavigation=1&theme=dark)
2. To use it in a browser directly:
You will need to make sure `react`, `react-dom` is available as shown below.
```html
<!DOCTYPE html>
<html>
<head>
<title>Excalidraw in browser</title>
<meta charset="UTF-8" />
<script src="https://unpkg.com/react@16.14.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.13.1/umd/react-dom.development.js"></script>
<script
type="text/javascript"
src="https://unpkg.com/@excalidraw/excalidraw@0.2.2/dist/excalidraw.min.js"
></script>
</head>
<body>
<div class="container">
<h4>Excalidraw Embed Example</h4>
<div id="app"></div>
</div>
<script type="text/javascript" src="src/index.js"></script>
</body>
</html>
```
```js
import "./styles.css";
const excalidrawWrapper = document.getElementById("app");
const props = {
onChange: (data, appState) => {
console.log(data, appState);
},
};
/*eslint-disable */
ReactDOM.render(
React.createElement(Excalidraw.default, props),
excalidrawWrapper,
);
```
[![Edit excalidraw-in-browser](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/excalidraw-in-browser-tlqom?fontsize=14&hidenavigation=1&theme=dark)
Since Excalidraw doesn't support server side rendering yet so you will have to make sure the component is rendered once host is mounted.
```js
import { useState, useEffect } from "react";
export default function IndexPage() {
const [Comp, setComp] = useState(null);
useEffect(() => {
import("@excalidraw/excalidraw").then((comp) => setComp(comp.default));
});
return <>{Comp && <Comp />}</>;
}
```
### Props ### Props
| Name | Type | Default | Description | | Name | Type | Default | Description |
@@ -130,7 +241,6 @@ export default function App() {
| [`offsetTop`](#offsetTop) | Number | `0` | top position relative to which Excalidraw should render | | [`offsetTop`](#offsetTop) | Number | `0` | top position relative to which Excalidraw should render |
| [`onChange`](#onChange) | Function | | This callback is triggered whenever the component updates due to any change. This callback will receive the excalidraw elements and the current app state. | | [`onChange`](#onChange) | Function | | This callback is triggered whenever the component updates due to any change. This callback will receive the excalidraw elements and the current app state. |
| [`initialData`](#initialData) | <pre>{elements?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>, appState?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37">AppState<a> } </pre> | null | The initial data with which app loads. | | [`initialData`](#initialData) | <pre>{elements?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>, appState?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37">AppState<a> } </pre> | null | The initial data with which app loads. |
| [`user`](#user) | `{ name?: string }` | | User details. The name refers to the name of the user to be shown |
| [`excalidrawRef`](#excalidrawRef) | [`createRef`](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) or [`callbackRef`](https://reactjs.org/docs/refs-and-the-dom.html#callback-refs) or <pre>{ current: { readyPromise: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/utils.ts#L317">resolvablePromise</a> } }</pre> | | Ref to be passed to Excalidraw | | [`excalidrawRef`](#excalidrawRef) | [`createRef`](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) or [`callbackRef`](https://reactjs.org/docs/refs-and-the-dom.html#callback-refs) or <pre>{ current: { readyPromise: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/utils.ts#L317">resolvablePromise</a> } }</pre> | | Ref to be passed to Excalidraw |
| [`onCollabButtonClick`](#onCollabButtonClick) | Function | | Callback to be triggered when the collab button is clicked | | [`onCollabButtonClick`](#onCollabButtonClick) | Function | | Callback to be triggered when the collab button is clicked |
| [`isCollaborating`](#isCollaborating) | `boolean` | | This implies if the app is in collaboration mode | | [`isCollaborating`](#isCollaborating) | `boolean` | | This implies if the app is in collaboration mode |
@@ -138,52 +248,9 @@ export default function App() {
| [`onExportToBackend`](#onExportToBackend) | Function | | Callback triggered when link button is clicked on export dialog | | [`onExportToBackend`](#onExportToBackend) | Function | | Callback triggered when link button is clicked on export dialog |
| [`langCode`](#langCode) | string | `en` | Language code string | | [`langCode`](#langCode) | string | `en` | Language code string |
| [`renderFooter `](#renderFooter) | Function | | Function that renders custom UI footer | | [`renderFooter `](#renderFooter) | Function | | Function that renders custom UI footer |
| [`viewModeEnabled`](#viewModeEnabled) | boolean | false | This implies if the app is in view mode. | | [`viewModeEnabled`](#viewModeEnabled) | boolean | | This implies if the app is in view mode. |
| [`zenModeEnabled`](#zenModeEnabled) | boolean | | This implies if the zen mode is enabled |
### `Extra API's` | [`gridModeEnabled`](#gridModeEnabled) | boolean | | This implies if the grid mode is enabled |
#### `getSceneVersion`
**How to use**
<pre>
import { getSceneVersion } from "@excalidraw/excalidraw";
getSceneVersion(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>)
</pre>
This function returns the current scene version.
#### `getSyncableElements`
**_Signature_**
<pre>
getSyncableElements(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>):<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>
</pre>
**How to use**
```js
import { getSyncableElements } from "@excalidraw/excalidraw";
```
This function returns all the deleted elements of the scene.
### `getElementMap`
**_Signature_**
<pre>
getElementsMap(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>): {[id: string]: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement</a>}
</pre>
**How to use**
```js
import { getElementsMap } from "@excalidraw/excalidraw";
```
This function returns an object where each element is mapped to its id.
#### `width` #### `width`
@@ -255,10 +322,6 @@ This helps to load Excalidraw with `initialData`. It must be an object or a [pro
You might want to use this when you want to load excalidraw with some initial elements and app state. You might want to use this when you want to load excalidraw with some initial elements and app state.
#### `user`
This is the user name which shows during collaboration. Defaults to `{name: ''}`.
#### `excalidrawRef` #### `excalidrawRef`
You can pass a `ref` when you want to access some excalidraw APIs. We expose the below APIs: You can pass a `ref` when you want to access some excalidraw APIs. We expose the below APIs:
@@ -267,7 +330,7 @@ You can pass a `ref` when you want to access some excalidraw APIs. We expose the
| --- | --- | --- | | --- | --- | --- |
| ready | `boolean` | This is set to true once Excalidraw is rendered | | ready | `boolean` | This is set to true once Excalidraw is rendered |
| readyPromise | [resolvablePromise](https://github.com/excalidraw/excalidraw/blob/master/src/utils.ts#L317) | This promise will be resolved with the api once excalidraw has rendered. This will be helpful when you want do some action on the host app once this promise resolves. For this to work you will have to pass ref as shown [here](#readyPromise) | | readyPromise | [resolvablePromise](https://github.com/excalidraw/excalidraw/blob/master/src/utils.ts#L317) | This promise will be resolved with the api once excalidraw has rendered. This will be helpful when you want do some action on the host app once this promise resolves. For this to work you will have to pass ref as shown [here](#readyPromise) |
| updateScene | <pre>(<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L189">sceneData</a>)) => void </pre> | updates the scene with the sceneData | | updateScene | <pre>(<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L192">sceneData</a>)) => void </pre> | updates the scene with the sceneData |
| resetScene | `({ resetLoadingState: boolean }) => void` | Resets the scene. If `resetLoadingState` is passed as true then it will also force set the loading state to false. | | resetScene | `({ resetLoadingState: boolean }) => void` | Resets the scene. If `resetLoadingState` is passed as true then it will also force set the loading state to false. |
| getSceneElementsIncludingDeleted | <pre> () => <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a></pre> | Returns all the elements including the deleted in the scene | | getSceneElementsIncludingDeleted | <pre> () => <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a></pre> | Returns all the elements including the deleted in the scene |
| getSceneElements | <pre> () => <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a></pre> | Returns all the elements excluding the deleted in the scene | | getSceneElements | <pre> () => <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a></pre> | Returns all the elements excluding the deleted in the scene |
@@ -334,4 +397,107 @@ A function that renders (returns JSX) custom UI footer. For example, you can use
#### `viewModeEnabled` #### `viewModeEnabled`
This prop indicates if the app is in `view mode`. When this prop is used, the `view mode` will not show up in context menu is so it is fully controlled by host. Also the value of this prop if passed will be used over the value of `intialData.appState.viewModeEnabled` This prop indicates whether the app is in `view mode`. When supplied, the value takes precedence over `intialData.appState.viewModeEnabled`, the `view mode` will be fully controlled by the host app, and users won't be able to toggle it from within the app.
#### `zenModeEnabled`
This prop indicates whether the app is in `zen mode`. When supplied, the value takes precedence over `intialData.appState.zenModeEnabled`, the `zen mode` will be fully controlled by the host app, and users won't be able to toggle it from within the app.
#### `gridModeEnabled`
This prop indicates whether the shows the grid. When supplied, the value takes precedence over `intialData.appState.gridModeEnabled`, the grid will be fully controlled by the host app, and users won't be able to toggle it from within the app.
### Extra API's
#### `getSceneVersion`
**How to use**
<pre>
import { getSceneVersion } from "@excalidraw/excalidraw";
getSceneVersion(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>)
</pre>
This function returns the current scene version.
#### `getSyncableElements`
**_Signature_**
<pre>
getSyncableElements(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>):<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>
</pre>
**How to use**
```js
import { getSyncableElements } from "@excalidraw/excalidraw";
```
This function returns all the deleted elements of the scene.
#### `getElementMap`
**_Signature_**
<pre>
getElementsMap(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>): {[id: string]: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement</a>}
</pre>
**How to use**
```js
import { getElementsMap } from "@excalidraw/excalidraw";
```
This function returns an object where each element is mapped to its id.
**_The below api's will be available in [next version](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/CHANGELOG.md#unreleased)_**
#### `restoreAppState`
**_Signature_**
<pre>
restoreAppState(appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L17">ImportedDataState["appState"]</a>, localAppState: Partial<<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37">AppState</a>> | null): <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37">AppState</a>
</pre>
**_How to use_**
```js
import { restoreAppState } from "@excalidraw/excalidraw";
```
This function will make sure all the keys have appropriate values in [appState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37) and if any key is missing, it will be set to default value. If you pass `localAppState`, `localAppState` value will be preferred over the `appState` passed in params.
#### `restoreElements`
**_Signature_**
<pre>
restoreElements(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L16">ImportedDataState["elements"]</a>): <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>
</pre>
**_How to use_**
```js
import { restoreElements } from "@excalidraw/excalidraw";
```
This function will make sure all properties of element is correctly set and if any attribute is missing, it will be set to default value.
#### `restore`
**_Signature_**
<pre>
restoreElements(data: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L12">ImportedDataState</a>): <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L4">DataState</a>
</pre>
**_How to use_**
```js
import { restore } from "@excalidraw/excalidraw";
```
This function makes sure elements and state is set to appropriate values and set to default value if not present. It is combination of [restoreElements](#restoreElements) and [restoreAppState](#restoreAppState)
+7 -5
View File
@@ -18,7 +18,6 @@ const Excalidraw = (props: ExcalidrawProps) => {
offsetTop, offsetTop,
onChange, onChange,
initialData, initialData,
user,
excalidrawRef, excalidrawRef,
onCollabButtonClick, onCollabButtonClick,
isCollaborating, isCollaborating,
@@ -27,6 +26,8 @@ const Excalidraw = (props: ExcalidrawProps) => {
renderFooter, renderFooter,
langCode = defaultLang.code, langCode = defaultLang.code,
viewModeEnabled, viewModeEnabled,
zenModeEnabled,
gridModeEnabled,
} = props; } = props;
useEffect(() => { useEffect(() => {
@@ -57,7 +58,6 @@ const Excalidraw = (props: ExcalidrawProps) => {
offsetTop={offsetTop} offsetTop={offsetTop}
onChange={onChange} onChange={onChange}
initialData={initialData} initialData={initialData}
user={user}
excalidrawRef={excalidrawRef} excalidrawRef={excalidrawRef}
onCollabButtonClick={onCollabButtonClick} onCollabButtonClick={onCollabButtonClick}
isCollaborating={isCollaborating} isCollaborating={isCollaborating}
@@ -66,6 +66,8 @@ const Excalidraw = (props: ExcalidrawProps) => {
renderFooter={renderFooter} renderFooter={renderFooter}
langCode={langCode} langCode={langCode}
viewModeEnabled={viewModeEnabled} viewModeEnabled={viewModeEnabled}
zenModeEnabled={zenModeEnabled}
gridModeEnabled={gridModeEnabled}
/> />
</IsMobileProvider> </IsMobileProvider>
</InitializeApp> </InitializeApp>
@@ -78,13 +80,12 @@ const areEqual = (
prevProps: PublicExcalidrawProps, prevProps: PublicExcalidrawProps,
nextProps: PublicExcalidrawProps, nextProps: PublicExcalidrawProps,
) => { ) => {
const { initialData: prevInitialData, user: prevUser, ...prev } = prevProps; const { initialData: prevInitialData, ...prev } = prevProps;
const { initialData: nextInitialData, user: nextUser, ...next } = nextProps; const { initialData: nextInitialData, ...next } = nextProps;
const prevKeys = Object.keys(prevProps) as (keyof typeof prev)[]; const prevKeys = Object.keys(prevProps) as (keyof typeof prev)[];
const nextKeys = Object.keys(nextProps) as (keyof typeof next)[]; const nextKeys = Object.keys(nextProps) as (keyof typeof next)[];
return ( return (
prevUser?.name === nextUser?.name &&
prevKeys.length === nextKeys.length && prevKeys.length === nextKeys.length &&
prevKeys.every((key) => prev[key] === next[key]) prevKeys.every((key) => prev[key] === next[key])
); );
@@ -105,3 +106,4 @@ export {
getElementMap, getElementMap,
} from "../../element"; } from "../../element";
export { defaultLang, languages } from "../../i18n"; export { defaultLang, languages } from "../../i18n";
export { restore, restoreAppState, restoreElements } from "../../data/restore";
+1509 -653
View File
File diff suppressed because it is too large Load Diff
+15 -15
View File
@@ -1,6 +1,6 @@
{ {
"name": "@excalidraw/excalidraw", "name": "@excalidraw/excalidraw",
"version": "0.2.1", "version": "0.3.1",
"main": "dist/excalidraw.min.js", "main": "dist/excalidraw.min.js",
"files": [ "files": [
"dist/*" "dist/*"
@@ -41,26 +41,26 @@
"react-dom": "^17.0.1" "react-dom": "^17.0.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.12.10", "@babel/core": "7.12.16",
"@babel/plugin-transform-arrow-functions": "7.12.1", "@babel/plugin-transform-arrow-functions": "7.12.13",
"@babel/plugin-transform-async-to-generator": "7.12.1", "@babel/plugin-transform-async-to-generator": "7.12.13",
"@babel/plugin-transform-runtime": "7.12.10", "@babel/plugin-transform-runtime": "7.12.15",
"@babel/plugin-transform-typescript": "7.12.1", "@babel/plugin-transform-typescript": "7.12.16",
"@babel/preset-env": "7.12.11", "@babel/preset-env": "7.12.16",
"@babel/preset-react": "7.12.10", "@babel/preset-react": "7.12.13",
"@babel/preset-typescript": "7.12.7", "@babel/preset-typescript": "7.12.16",
"babel-loader": "8.2.2", "babel-loader": "8.2.2",
"babel-plugin-transform-class-properties": "6.24.1", "babel-plugin-transform-class-properties": "6.24.1",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"css-loader": "5.0.1", "css-loader": "5.0.2",
"file-loader": "6.2.0", "file-loader": "6.2.0",
"mini-css-extract-plugin": "1.3.5", "mini-css-extract-plugin": "1.3.6",
"sass-loader": "10.1.1", "sass-loader": "11.0.1",
"terser-webpack-plugin": "5.1.1", "terser-webpack-plugin": "5.1.1",
"ts-loader": "8.0.14", "ts-loader": "8.0.17",
"webpack": "5.19.0", "webpack": "5.21.2",
"webpack-bundle-analyzer": "4.4.0", "webpack-bundle-analyzer": "4.4.0",
"webpack-cli": "4.4.0" "webpack-cli": "4.5.0"
}, },
"bugs": "https://github.com/excalidraw/excalidraw/issues", "bugs": "https://github.com/excalidraw/excalidraw/issues",
"repository": "https://github.com/excalidraw/excalidraw", "repository": "https://github.com/excalidraw/excalidraw",
@@ -13,7 +13,6 @@ module.exports = {
library: "Excalidraw", library: "Excalidraw",
libraryTarget: "umd", libraryTarget: "umd",
filename: "[name].js", filename: "[name].js",
publicPath: "/",
chunkFilename: "excalidraw-assets/[name].js", chunkFilename: "excalidraw-assets/[name].js",
}, },
resolve: { resolve: {
+3
View File
@@ -48,6 +48,9 @@ export const exportToBlob = (
}, },
): Promise<Blob | null> => { ): Promise<Blob | null> => {
const canvas = exportToCanvas(opts); const canvas = exportToCanvas(opts);
if (canvas instanceof OffscreenCanvas) {
return Promise.resolve(null);
}
let { mimeType = "image/png", quality } = opts; let { mimeType = "image/png", quality } = opts;
+787 -587
View File
File diff suppressed because it is too large Load Diff
+9 -9
View File
@@ -34,21 +34,21 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.12.10", "@babel/core": "7.12.16",
"@babel/plugin-transform-arrow-functions": "7.12.1", "@babel/plugin-transform-arrow-functions": "7.12.13",
"@babel/plugin-transform-async-to-generator": "7.12.1", "@babel/plugin-transform-async-to-generator": "7.12.13",
"@babel/plugin-transform-runtime": "^7.12.10", "@babel/plugin-transform-runtime": "^7.12.10",
"@babel/plugin-transform-typescript": "7.12.1", "@babel/plugin-transform-typescript": "7.12.16",
"@babel/preset-env": "7.12.11", "@babel/preset-env": "7.12.16",
"@babel/preset-typescript": "7.12.7", "@babel/preset-typescript": "7.12.16",
"babel-loader": "8.2.2", "babel-loader": "8.2.2",
"babel-plugin-transform-class-properties": "6.24.1", "babel-plugin-transform-class-properties": "6.24.1",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"file-loader": "6.2.0", "file-loader": "6.2.0",
"ts-loader": "8.0.14", "ts-loader": "8.0.17",
"webpack": "5.19.0", "webpack": "5.21.2",
"webpack-bundle-analyzer": "4.4.0", "webpack-bundle-analyzer": "4.4.0",
"webpack-cli": "4.4.0" "webpack-cli": "4.5.0"
}, },
"bugs": "https://github.com/excalidraw/excalidraw/issues", "bugs": "https://github.com/excalidraw/excalidraw/issues",
"repository": "https://github.com/excalidraw/excalidraw", "repository": "https://github.com/excalidraw/excalidraw",
+48
View File
@@ -0,0 +1,48 @@
/* eslint-disable no-restricted-globals */
import { getNonDeletedElements } from "../element";
import { ExcalidrawElement } from "../element/types";
import { exportToCanvas } from "../scene/export";
import { AppState } from "../types";
const ctx: Worker = self as any;
let canvas: OffscreenCanvas;
ctx.addEventListener("message", (ev) => {
if (ev.data.type === "INIT") {
canvas = ev.data.canvas;
}
if (ev.data.type === "DRAW") {
const { elements, appState, width, height } = ev.data;
drawScene(canvas, elements, appState, width, height);
}
});
function drawScene(
canvas: OffscreenCanvas,
elements: readonly ExcalidrawElement[],
appState: AppState,
minimapWidth: number,
minimapHeight: number,
) {
exportToCanvas(
getNonDeletedElements(elements),
appState,
{
exportBackground: true,
viewBackgroundColor: appState.viewBackgroundColor,
shouldAddWatermark: false,
},
(width, height) => {
const scale = Math.min(minimapWidth / width, minimapHeight / height);
canvas.width = width * scale;
canvas.height = height * scale;
return {
canvas,
scale,
};
},
);
}
+16 -10
View File
@@ -115,7 +115,7 @@ const generateElementCanvas = (
const drawElementOnCanvas = ( const drawElementOnCanvas = (
element: NonDeletedExcalidrawElement, element: NonDeletedExcalidrawElement,
rc: RoughCanvas, rc: RoughCanvas,
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
) => { ) => {
context.globalAlpha = element.opacity / 100; context.globalAlpha = element.opacity / 100;
switch (element.type) { switch (element.type) {
@@ -136,13 +136,16 @@ const drawElementOnCanvas = (
default: { default: {
if (isTextElement(element)) { if (isTextElement(element)) {
const rtl = isRTL(element.text); const rtl = isRTL(element.text);
const shouldTemporarilyAttach = rtl && !context.canvas.isConnected; let shouldTemporarilyAttach = false;
if (shouldTemporarilyAttach) { if (!(context instanceof OffscreenCanvasRenderingContext2D)) {
// to correctly render RTL text mixed with LTR, we have to append it shouldTemporarilyAttach = rtl && !context.canvas.isConnected;
// to the DOM if (shouldTemporarilyAttach) {
document.body.appendChild(context.canvas); // to correctly render RTL text mixed with LTR, we have to append it
// to the DOM
document.body.appendChild(context.canvas);
}
context.canvas.setAttribute("dir", rtl ? "rtl" : "ltr");
} }
context.canvas.setAttribute("dir", rtl ? "rtl" : "ltr");
const font = context.font; const font = context.font;
context.font = getFontString(element); context.font = getFontString(element);
const fillStyle = context.fillStyle; const fillStyle = context.fillStyle;
@@ -170,7 +173,10 @@ const drawElementOnCanvas = (
context.fillStyle = fillStyle; context.fillStyle = fillStyle;
context.font = font; context.font = font;
context.textAlign = textAlign; context.textAlign = textAlign;
if (shouldTemporarilyAttach) { if (
shouldTemporarilyAttach &&
!(context instanceof OffscreenCanvasRenderingContext2D)
) {
context.canvas.remove(); context.canvas.remove();
} }
} else { } else {
@@ -451,7 +457,7 @@ const generateElementWithCanvas = (
const drawElementFromCanvas = ( const drawElementFromCanvas = (
elementWithCanvas: ExcalidrawElementWithCanvas, elementWithCanvas: ExcalidrawElementWithCanvas,
rc: RoughCanvas, rc: RoughCanvas,
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
sceneState: SceneState, sceneState: SceneState,
) => { ) => {
const element = elementWithCanvas.element; const element = elementWithCanvas.element;
@@ -482,7 +488,7 @@ const drawElementFromCanvas = (
export const renderElement = ( export const renderElement = (
element: NonDeletedExcalidrawElement, element: NonDeletedExcalidrawElement,
rc: RoughCanvas, rc: RoughCanvas,
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
renderOptimizations: boolean, renderOptimizations: boolean,
sceneState: SceneState, sceneState: SceneState,
) => { ) => {
+31 -23
View File
@@ -47,11 +47,13 @@ import {
TransformHandles, TransformHandles,
TransformHandleType, TransformHandleType,
} from "../element/transformHandles"; } from "../element/transformHandles";
import { viewportCoordsToSceneCoords } from "../utils"; import { viewportCoordsToSceneCoords, supportsEmoji } from "../utils";
import { UserIdleState } from "../excalidraw-app/collab/types"; import { UserIdleState } from "../excalidraw-app/collab/types";
const hasEmojiSupport = supportsEmoji();
const strokeRectWithRotation = ( const strokeRectWithRotation = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
x: number, x: number,
y: number, y: number,
width: number, width: number,
@@ -72,7 +74,7 @@ const strokeRectWithRotation = (
}; };
const strokeDiamondWithRotation = ( const strokeDiamondWithRotation = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
width: number, width: number,
height: number, height: number,
cx: number, cx: number,
@@ -93,7 +95,7 @@ const strokeDiamondWithRotation = (
}; };
const strokeEllipseWithRotation = ( const strokeEllipseWithRotation = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
width: number, width: number,
height: number, height: number,
cx: number, cx: number,
@@ -106,7 +108,7 @@ const strokeEllipseWithRotation = (
}; };
const fillCircle = ( const fillCircle = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
cx: number, cx: number,
cy: number, cy: number,
radius: number, radius: number,
@@ -118,7 +120,7 @@ const fillCircle = (
}; };
const strokeGrid = ( const strokeGrid = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
gridSize: number, gridSize: number,
offsetX: number, offsetX: number,
offsetY: number, offsetY: number,
@@ -141,7 +143,7 @@ const strokeGrid = (
}; };
const renderLinearPointHandles = ( const renderLinearPointHandles = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
appState: AppState, appState: AppState,
sceneState: SceneState, sceneState: SceneState,
element: NonDeleted<ExcalidrawLinearElement>, element: NonDeleted<ExcalidrawLinearElement>,
@@ -180,7 +182,7 @@ export const renderScene = (
selectionElement: NonDeletedExcalidrawElement | null, selectionElement: NonDeletedExcalidrawElement | null,
scale: number, scale: number,
rc: RoughCanvas, rc: RoughCanvas,
canvas: HTMLCanvasElement, canvas: HTMLCanvasElement | OffscreenCanvas,
sceneState: SceneState, sceneState: SceneState,
// extra options, currently passed by export helper // extra options, currently passed by export helper
{ {
@@ -311,7 +313,7 @@ export const renderScene = (
if (sceneState.remoteSelectedElementIds[element.id]) { if (sceneState.remoteSelectedElementIds[element.id]) {
selectionColors.push( selectionColors.push(
...sceneState.remoteSelectedElementIds[element.id].map((socketId) => { ...sceneState.remoteSelectedElementIds[element.id].map((socketId) => {
const { background } = getClientColors(socketId); const { background } = getClientColors(socketId, appState);
return background; return background;
}), }),
); );
@@ -439,7 +441,7 @@ export const renderScene = (
y = Math.max(y, 0); y = Math.max(y, 0);
y = Math.min(y, normalizedCanvasHeight - height); y = Math.min(y, normalizedCanvasHeight - height);
const { background, stroke } = getClientColors(clientId); const { background, stroke } = getClientColors(clientId, appState);
const strokeStyle = context.strokeStyle; const strokeStyle = context.strokeStyle;
const fillStyle = context.fillStyle; const fillStyle = context.fillStyle;
@@ -449,7 +451,7 @@ export const renderScene = (
const userState = sceneState.remotePointerUserStates[clientId]; const userState = sceneState.remotePointerUserStates[clientId];
if (isOutOfBounds || userState === UserIdleState.AWAY) { if (isOutOfBounds || userState === UserIdleState.AWAY) {
context.globalAlpha = 0.2; context.globalAlpha = 0.48;
} }
if ( if (
@@ -481,13 +483,19 @@ export const renderScene = (
context.stroke(); context.stroke();
const username = sceneState.remotePointerUsernames[clientId]; const username = sceneState.remotePointerUsernames[clientId];
const usernameAndIdleState = `${username ? `${username} ` : ""}${
userState === UserIdleState.AWAY let idleState = "";
? "⚫️" if (userState === UserIdleState.AWAY) {
: userState === UserIdleState.IDLE idleState = hasEmojiSupport ? "⚫️" : ` (${UserIdleState.AWAY})`;
? "💤" } else if (userState === UserIdleState.IDLE) {
: "🟢" idleState = hasEmojiSupport ? "💤" : ` (${UserIdleState.IDLE})`;
}`; } else if (userState === UserIdleState.ACTIVE) {
idleState = hasEmojiSupport ? "🟢" : "";
}
const usernameAndIdleState = `${
username ? `${username} ` : ""
}${idleState}`;
if (!isOutOfBounds && usernameAndIdleState) { if (!isOutOfBounds && usernameAndIdleState) {
const offsetX = x + width; const offsetX = x + width;
@@ -565,7 +573,7 @@ export const renderScene = (
}; };
const renderTransformHandles = ( const renderTransformHandles = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
sceneState: SceneState, sceneState: SceneState,
transformHandles: TransformHandles, transformHandles: TransformHandles,
angle: number, angle: number,
@@ -601,7 +609,7 @@ const renderTransformHandles = (
}; };
const renderSelectionBorder = ( const renderSelectionBorder = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
sceneState: SceneState, sceneState: SceneState,
elementProperties: { elementProperties: {
angle: number; angle: number;
@@ -663,7 +671,7 @@ const renderSelectionBorder = (
}; };
const renderBindingHighlight = ( const renderBindingHighlight = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
sceneState: SceneState, sceneState: SceneState,
suggestedBinding: SuggestedBinding, suggestedBinding: SuggestedBinding,
) => { ) => {
@@ -685,7 +693,7 @@ const renderBindingHighlight = (
}; };
const renderBindingHighlightForBindableElement = ( const renderBindingHighlightForBindableElement = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
element: ExcalidrawBindableElement, element: ExcalidrawBindableElement,
) => { ) => {
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element); const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
@@ -740,7 +748,7 @@ const renderBindingHighlightForBindableElement = (
}; };
const renderBindingHighlightForSuggestedPointBinding = ( const renderBindingHighlightForSuggestedPointBinding = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
suggestedBinding: SuggestedPointBinding, suggestedBinding: SuggestedPointBinding,
) => { ) => {
const [element, startOrEnd, bindableElement] = suggestedBinding; const [element, startOrEnd, bindableElement] = suggestedBinding;

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