From 9423ac3263a7b3203045d246a938abb920164e42 Mon Sep 17 00:00:00 2001 From: David Luzar Date: Fri, 22 Apr 2022 15:49:36 +0200 Subject: [PATCH 01/28] fix: Excalidraw named export type (#5078) --- src/excalidraw-app/index.tsx | 3 ++- src/packages/excalidraw/entry.js | 3 --- src/packages/excalidraw/index.tsx | 8 +++++--- src/tests/packages/excalidraw.test.tsx | 2 +- src/tests/scroll.test.tsx | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/excalidraw-app/index.tsx b/src/excalidraw-app/index.tsx index 5451a9c82..75f5ae149 100644 --- a/src/excalidraw-app/index.tsx +++ b/src/excalidraw-app/index.tsx @@ -19,7 +19,8 @@ import { } from "../element/types"; import { useCallbackRefState } from "../hooks/useCallbackRefState"; import { Language, t } from "../i18n"; -import Excalidraw, { +import { + Excalidraw, defaultLang, languages, } from "../packages/excalidraw/index"; diff --git a/src/packages/excalidraw/entry.js b/src/packages/excalidraw/entry.js index 8915a1255..e5d4a20a2 100644 --- a/src/packages/excalidraw/entry.js +++ b/src/packages/excalidraw/entry.js @@ -1,6 +1,3 @@ -import Excalidraw from "./index"; - import "../../../public/fonts.css"; -export { Excalidraw }; export * from "./index"; diff --git a/src/packages/excalidraw/index.tsx b/src/packages/excalidraw/index.tsx index 05bb3a34b..a3937bbb4 100644 --- a/src/packages/excalidraw/index.tsx +++ b/src/packages/excalidraw/index.tsx @@ -13,7 +13,7 @@ import { DEFAULT_UI_OPTIONS } from "../../constants"; import { Provider } from "jotai"; import { jotaiScope, jotaiStore } from "../../jotai"; -const Excalidraw = (props: ExcalidrawProps) => { +const ExcalidrawBase = (props: ExcalidrawProps) => { const { onChange, initialData, @@ -173,8 +173,10 @@ const areEqual = ( const forwardedRefComp = forwardRef< ExcalidrawAPIRefValue, PublicExcalidrawProps ->((props, ref) => ); -export default React.memo(forwardedRefComp, areEqual); +>((props, ref) => ); + +export const Excalidraw = React.memo(forwardedRefComp, areEqual); + export { getSceneVersion, isInvisiblySmallElement, diff --git a/src/tests/packages/excalidraw.test.tsx b/src/tests/packages/excalidraw.test.tsx index d0e22c6dc..1007fd88b 100644 --- a/src/tests/packages/excalidraw.test.tsx +++ b/src/tests/packages/excalidraw.test.tsx @@ -1,5 +1,5 @@ import { fireEvent, GlobalTestState, render } from "../test-utils"; -import Excalidraw from "../../packages/excalidraw/index"; +import { Excalidraw } from "../../packages/excalidraw/index"; import { queryByText, queryByTestId } from "@testing-library/react"; import { GRID_SIZE, THEME } from "../../constants"; import { t } from "../../i18n"; diff --git a/src/tests/scroll.test.tsx b/src/tests/scroll.test.tsx index 70a115a50..1105352d0 100644 --- a/src/tests/scroll.test.tsx +++ b/src/tests/scroll.test.tsx @@ -4,7 +4,7 @@ import { restoreOriginalGetBoundingClientRect, waitFor, } from "./test-utils"; -import Excalidraw from "../packages/excalidraw/index"; +import { Excalidraw } from "../packages/excalidraw/index"; import { API } from "./helpers/api"; const { h } = window; From 8f0863d33532c1b3a9f727d90d1d1526e8254a24 Mon Sep 17 00:00:00 2001 From: Achille Lacoin Date: Fri, 22 Apr 2022 18:31:31 +0200 Subject: [PATCH 02/28] add a prefix to the extension for image embbedding sceneData (#5079) --- src/constants.ts | 2 ++ src/data/filesystem.ts | 2 ++ src/data/index.ts | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 78e70f656..8d2ae3468 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -94,7 +94,9 @@ export const MIME_TYPES = { excalidrawlib: "application/vnd.excalidrawlib+json", json: "application/json", svg: "image/svg+xml", + "excalidraw.svg": "image/svg+xml", png: "image/png", + "excalidraw.png": "image/png", jpg: "image/jpeg", gif: "image/gif", binary: "application/octet-stream", diff --git a/src/data/filesystem.ts b/src/data/filesystem.ts index 55f41171b..8db365c67 100644 --- a/src/data/filesystem.ts +++ b/src/data/filesystem.ts @@ -13,7 +13,9 @@ type FILE_EXTENSION = | "gif" | "jpg" | "png" + | "excalidraw.png" | "svg" + | "excalidraw.svg" | "json" | "excalidraw" | "excalidrawlib"; diff --git a/src/data/index.ts b/src/data/index.ts index 5cfaaa978..8ea90adf6 100644 --- a/src/data/index.ts +++ b/src/data/index.ts @@ -56,7 +56,7 @@ export const exportCanvas = async ( { description: "Export to SVG", name, - extension: "svg", + extension: appState.exportEmbedScene ? "excalidraw.svg" : "svg", fileHandle, }, ); @@ -89,7 +89,7 @@ export const exportCanvas = async ( return await fileSave(blob, { description: "Export to PNG", name, - extension: "png", + extension: appState.exportEmbedScene ? "excalidraw.png" : "png", fileHandle, }); } else if (type === "clipboard") { From 9902092fd19386c1528b5202f151d94166f0b1ec Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Sat, 23 Apr 2022 13:48:57 +0530 Subject: [PATCH 03/28] fix setting webpack public path (#5081) --- src/packages/excalidraw/entry.js | 2 ++ src/packages/excalidraw/index.tsx | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packages/excalidraw/entry.js b/src/packages/excalidraw/entry.js index e5d4a20a2..02c14fdb1 100644 --- a/src/packages/excalidraw/entry.js +++ b/src/packages/excalidraw/entry.js @@ -1,3 +1,5 @@ +import "./publicPath"; + import "../../../public/fonts.css"; export * from "./index"; diff --git a/src/packages/excalidraw/index.tsx b/src/packages/excalidraw/index.tsx index a3937bbb4..213c823b0 100644 --- a/src/packages/excalidraw/index.tsx +++ b/src/packages/excalidraw/index.tsx @@ -1,5 +1,4 @@ import React, { useEffect, forwardRef } from "react"; -import "./publicPath"; import { InitializeApp } from "../../components/InitializeApp"; import App from "../../components/App"; From 832b88249c6afc59416304dceeb573865f79249a Mon Sep 17 00:00:00 2001 From: David Luzar Date: Sun, 24 Apr 2022 18:29:38 +0200 Subject: [PATCH 04/28] feat: stop event propagation when key handled (#5091) * feat: stop event propagation when key handled * don't handle s/g shortcuts if cmd/ctrl/alt pressed --- src/actions/manager.tsx | 1 + src/components/App.tsx | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/actions/manager.tsx b/src/actions/manager.tsx index 434a38490..7481d56a3 100644 --- a/src/actions/manager.tsx +++ b/src/actions/manager.tsx @@ -117,6 +117,7 @@ export class ActionManager { trackAction(action, "keyboard", appState, elements, this.app, null); event.preventDefault(); + event.stopPropagation(); this.updater(data[0].perform(elements, appState, value, this.app)); return true; } diff --git a/src/components/App.tsx b/src/components/App.tsx index 38520fc45..a5c6ddff7 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -1272,6 +1272,7 @@ class App extends React.Component { } this.cutAll(); event.preventDefault(); + event.stopPropagation(); }); private onCopy = withBatchedUpdates((event: ClipboardEvent) => { @@ -1283,6 +1284,7 @@ class App extends React.Component { } this.copyAll(); event.preventDefault(); + event.stopPropagation(); }); private cutAll = () => { @@ -1874,8 +1876,10 @@ class App extends React.Component { ); } this.setActiveTool({ ...this.state.activeTool, type: shape }); + event.stopPropagation(); } else if (event.key === KEYS.Q) { this.toggleLock("keyboard"); + event.stopPropagation(); } } if (event.key === KEYS.SPACE && gesture.pointers.size === 0) { @@ -1884,7 +1888,11 @@ class App extends React.Component { event.preventDefault(); } - if (event.key === KEYS.G || event.key === KEYS.S) { + if ( + (event.key === KEYS.G || event.key === KEYS.S) && + !event.altKey && + !event[KEYS.CTRL_OR_CMD] + ) { const selectedElements = getSelectedElements( this.scene.getElements(), this.state, @@ -1902,9 +1910,11 @@ class App extends React.Component { selectedElements.some((element) => hasBackground(element.type))) ) { this.setState({ openPopup: "backgroundColorPicker" }); + event.stopPropagation(); } if (event.key === KEYS.S) { this.setState({ openPopup: "strokeColorPicker" }); + event.stopPropagation(); } } }, From e6a9ff1b9659dfbf6698a58e68520a3729f0f1b6 Mon Sep 17 00:00:00 2001 From: David Luzar Date: Sun, 24 Apr 2022 19:21:41 +0200 Subject: [PATCH 05/28] fix: toolIcon height not using rem (#5092) --- src/components/ToolIcon.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ToolIcon.scss b/src/components/ToolIcon.scss index 172ebc273..7057110c9 100644 --- a/src/components/ToolIcon.scss +++ b/src/components/ToolIcon.scss @@ -155,7 +155,7 @@ } width: 2rem; - height: 2em; + height: 2rem; } } From 5656ac1e3e12b9a032c4d579d9a4196cf302becb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Apr 2022 12:58:10 +0530 Subject: [PATCH 06/28] chore(deps): bump browser-fs-access from 0.24.1 to 0.29.1 (#5090) Bumps [browser-fs-access](https://github.com/GoogleChromeLabs/browser-fs-access) from 0.24.1 to 0.29.1. - [Release notes](https://github.com/GoogleChromeLabs/browser-fs-access/releases) - [Commits](https://github.com/GoogleChromeLabs/browser-fs-access/commits) --- updated-dependencies: - dependency-name: browser-fs-access dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9d0d3178e..c03c2f636 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@types/react": "17.0.39", "@types/react-dom": "17.0.11", "@types/socket.io-client": "1.4.36", - "browser-fs-access": "0.24.1", + "browser-fs-access": "0.29.1", "clsx": "1.1.1", "fake-indexeddb": "3.1.7", "firebase": "8.3.3", diff --git a/yarn.lock b/yarn.lock index c34301cc9..df12a2d51 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3394,10 +3394,10 @@ brorand@^1.0.1, brorand@^1.1.0: resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= -browser-fs-access@0.24.1: - version "0.24.1" - resolved "https://registry.yarnpkg.com/browser-fs-access/-/browser-fs-access-0.24.1.tgz#29b915fdcd2ef0972ebabc2b7685c6893d288a72" - integrity sha512-fRcwhfNej0h2Jy+Uodxjbc5PQvNkZyG9fXu3S6Mcv0kigKath5sL54GXfMtOay/A/ULMa956eQZ9lMWVPiLtMA== +browser-fs-access@0.29.1: + version "0.29.1" + resolved "https://registry.yarnpkg.com/browser-fs-access/-/browser-fs-access-0.29.1.tgz#8a9794c73cf86b9aec74201829999c597128379c" + integrity sha512-LSvVX5e21LRrXqVMhqtAwj5xPgDb+fXAIH80NsnCQ9xuZPs2xWsOREi24RKgZa1XOiQRbcmVrv87+ulOKsgjxw== browser-process-hrtime@^1.0.0: version "1.0.0" From aa2971e8c59ee6253d5aac9173ef7bd446b038c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Apr 2022 12:58:53 +0530 Subject: [PATCH 07/28] chore(deps-dev): bump autoprefixer in /src/packages/excalidraw (#5087) Bumps [autoprefixer](https://github.com/postcss/autoprefixer) from 10.4.2 to 10.4.5. - [Release notes](https://github.com/postcss/autoprefixer/releases) - [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md) - [Commits](https://github.com/postcss/autoprefixer/compare/10.4.2...10.4.5) --- updated-dependencies: - dependency-name: autoprefixer dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/packages/excalidraw/package.json | 2 +- src/packages/excalidraw/yarn.lock | 60 ++++++++++++++-------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/packages/excalidraw/package.json b/src/packages/excalidraw/package.json index f4b9aa779..e970be61a 100644 --- a/src/packages/excalidraw/package.json +++ b/src/packages/excalidraw/package.json @@ -52,7 +52,7 @@ "@babel/preset-env": "7.16.7", "@babel/preset-react": "7.16.7", "@babel/preset-typescript": "7.16.7", - "autoprefixer": "10.4.2", + "autoprefixer": "10.4.5", "babel-loader": "8.2.3", "babel-plugin-transform-class-properties": "6.24.1", "cross-env": "7.0.3", diff --git a/src/packages/excalidraw/yarn.lock b/src/packages/excalidraw/yarn.lock index 3bbda4369..26097f04d 100644 --- a/src/packages/excalidraw/yarn.lock +++ b/src/packages/excalidraw/yarn.lock @@ -1577,14 +1577,14 @@ async@^2.6.2: dependencies: lodash "^4.17.14" -autoprefixer@10.4.2: - version "10.4.2" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b" - integrity sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ== +autoprefixer@10.4.5: + version "10.4.5" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.5.tgz#662193c744094b53d3637f39be477e07bd904998" + integrity sha512-Fvd8yCoA7lNX/OUllvS+aS1I7WRBclGXsepbvT8ZaPgrH24rgXpZzF0/6Hh3ZEkwg+0AES/Osd196VZmYoEFtw== dependencies: - browserslist "^4.19.1" - caniuse-lite "^1.0.30001297" - fraction.js "^4.1.2" + browserslist "^4.20.2" + caniuse-lite "^1.0.30001332" + fraction.js "^4.2.0" normalize-range "^0.1.2" picocolors "^1.0.0" postcss-value-parser "^4.2.0" @@ -1800,15 +1800,15 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.14.5, browserslist@^4.17.5, browserslist@^4.17.6, browserslist@^4.19.1: - version "4.19.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" - integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== +browserslist@^4.14.5, browserslist@^4.17.5, browserslist@^4.17.6, browserslist@^4.19.1, browserslist@^4.20.2: + version "4.20.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.2.tgz#567b41508757ecd904dab4d1c646c612cd3d4f88" + integrity sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA== dependencies: - caniuse-lite "^1.0.30001286" - electron-to-chromium "^1.4.17" + caniuse-lite "^1.0.30001317" + electron-to-chromium "^1.4.84" escalade "^3.1.1" - node-releases "^2.0.1" + node-releases "^2.0.2" picocolors "^1.0.0" buffer-from@^1.0.0: @@ -1844,10 +1844,10 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297: - version "1.0.30001298" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001298.tgz#0e690039f62e91c3ea581673d716890512e7ec52" - integrity sha512-AcKqikjMLlvghZL/vfTHorlQsLDhGRalYf1+GmWCf5SCMziSGjRYQW/JEksj14NaYHIR6KIhrFAy0HV5C25UzQ== +caniuse-lite@^1.0.30001317, caniuse-lite@^1.0.30001332: + version "1.0.30001332" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001332.tgz#39476d3aa8d83ea76359c70302eafdd4a1d727dd" + integrity sha512-10T30NYOEQtN6C11YGg411yebhvpnC6Z102+B95eAsN0oB6KUs01ivE8u+G6FMIRtIrVlYXhL+LUwQ3/hXwDWw== chalk@^1.1.3: version "1.1.3" @@ -2211,10 +2211,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.4.17: - version "1.4.38" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.38.tgz#10ea58d73d36b13e78d5024f3b74a352d3958d01" - integrity sha512-WhHt3sZazKj0KK/UpgsbGQnUUoFeAHVishzHFExMxagpZgjiGYSC9S0ZlbhCfSH2L2i+2A1yyqOIliTctMx7KQ== +electron-to-chromium@^1.4.84: + version "1.4.118" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.118.tgz#2d917c71712dac9652cc01af46c7d0bd51552974" + integrity sha512-maZIKjnYDvF7Fs35nvVcyr44UcKNwybr93Oba2n3HkKDFAtk0svERkLN/HyczJDS3Fo4wU9th9fUQd09ZLtj1w== emojis-list@^3.0.0: version "3.0.0" @@ -2449,10 +2449,10 @@ forwarded@0.2.0: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fraction.js@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.2.tgz#13e420a92422b6cf244dff8690ed89401029fbe8" - integrity sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA== +fraction.js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" + integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== fresh@0.5.2: version "0.5.2" @@ -3162,10 +3162,10 @@ node-forge@^1.2.0: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.1.tgz#82794919071ef2eb5c509293325cec8afd0fd53c" integrity sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w== -node-releases@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" - integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== +node-releases@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.3.tgz#225ee7488e4a5e636da8da52854844f9d716ca96" + integrity sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw== normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" From 116b0c48da2f5c793f4413a801319e3fa2291720 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Apr 2022 12:59:11 +0530 Subject: [PATCH 08/28] chore(deps): bump nanoid from 3.1.32 to 3.3.3 (#5073) Bumps [nanoid](https://github.com/ai/nanoid) from 3.1.32 to 3.3.3. - [Release notes](https://github.com/ai/nanoid/releases) - [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md) - [Commits](https://github.com/ai/nanoid/compare/3.1.32...3.3.3) --- updated-dependencies: - dependency-name: nanoid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index c03c2f636..9f218af9d 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "image-blob-reduce": "3.0.1", "jotai": "1.6.4", "lodash.throttle": "4.1.1", - "nanoid": "3.1.32", + "nanoid": "3.3.3", "open-color": "1.9.1", "pako": "1.0.11", "perfect-freehand": "1.0.16", diff --git a/yarn.lock b/yarn.lock index df12a2d51..ec0d50954 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8510,10 +8510,10 @@ nan@^2.12.1: resolved "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== -nanoid@3.1.32, nanoid@^3.1.20: - version "3.1.32" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.32.tgz#8f96069e6239cc0a9ae8c0d3b41a3b4933a88c0a" - integrity sha512-F8mf7R3iT9bvThBoW4tGXhXFHCctyCiUUPrWF8WaTqa3h96d9QybkSeba43XVOOE3oiLfkVDe4bT8MeGmkrTxw== +nanoid@3.3.3, nanoid@^3.1.20: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== nanomatch@^1.2.9: version "1.2.13" From 8f8c85c64e61a5b01b0b070448880717c5ce617c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Apr 2022 12:59:37 +0530 Subject: [PATCH 09/28] chore(deps): bump async from 2.6.3 to 2.6.4 (#5070) Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4. - [Release notes](https://github.com/caolan/async/releases) - [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md) - [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4) --- updated-dependencies: - dependency-name: async dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index ec0d50954..77a26537d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2971,9 +2971,9 @@ async-limiter@~1.0.0: integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== async@^2.6.2: - version "2.6.3" - resolved "https://registry.npmjs.org/async/-/async-2.6.3.tgz" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== dependencies: lodash "^4.17.14" From b941c5b661e32aa869c7dc7217d232a5120ff576 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Apr 2022 13:01:35 +0530 Subject: [PATCH 10/28] chore(deps-dev): bump webpack in /src/packages/excalidraw (#5027) Bumps [webpack](https://github.com/webpack/webpack) from 5.65.0 to 5.72.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v5.65.0...v5.72.0) --- updated-dependencies: - dependency-name: webpack dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/packages/excalidraw/package.json | 2 +- src/packages/excalidraw/yarn.lock | 72 ++++++++++++---------------- 2 files changed, 31 insertions(+), 43 deletions(-) diff --git a/src/packages/excalidraw/package.json b/src/packages/excalidraw/package.json index e970be61a..8ec742f72 100644 --- a/src/packages/excalidraw/package.json +++ b/src/packages/excalidraw/package.json @@ -63,7 +63,7 @@ "terser-webpack-plugin": "5.3.1", "ts-loader": "9.2.8", "typescript": "4.5.4", - "webpack": "5.65.0", + "webpack": "5.72.0", "webpack-bundle-analyzer": "4.5.0", "webpack-cli": "4.9.2", "webpack-dev-server": "4.7.4", diff --git a/src/packages/excalidraw/yarn.lock b/src/packages/excalidraw/yarn.lock index 26097f04d..f1cd5cd95 100644 --- a/src/packages/excalidraw/yarn.lock +++ b/src/packages/excalidraw/yarn.lock @@ -1174,10 +1174,10 @@ dependencies: "@types/node" "*" -"@types/eslint-scope@^3.7.0": - version "3.7.0" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.0.tgz#4792816e31119ebd506902a482caec4951fabd86" - integrity sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw== +"@types/eslint-scope@^3.7.3": + version "3.7.3" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" + integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== dependencies: "@types/eslint" "*" "@types/estree" "*" @@ -1190,10 +1190,10 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^0.0.50": - version "0.0.50" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" - integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== +"@types/estree@*", "@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": version "4.17.27" @@ -2226,10 +2226,10 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -enhanced-resolve@^5.0.0, enhanced-resolve@^5.8.3: - version "5.8.3" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" - integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== +enhanced-resolve@^5.0.0, enhanced-resolve@^5.9.2: + version "5.9.2" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz#0224dcd6a43389ebfb2d55efee517e5466772dd9" + integrity sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -2544,10 +2544,10 @@ globby@^11.0.1: merge2 "^1.3.0" slash "^3.0.0" -graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== +graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== gzip-size@^6.0.0: version "6.0.0" @@ -3044,24 +3044,12 @@ micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4: braces "^3.0.1" picomatch "^2.2.3" -mime-db@1.45.0: - version "1.45.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" - integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== - mime-db@1.51.0, "mime-db@>= 1.43.0 < 2": version "1.51.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== -mime-types@^2.1.27: - version "2.1.28" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" - integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== - dependencies: - mime-db "1.45.0" - -mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24: +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24: version "2.1.34" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== @@ -4180,18 +4168,18 @@ webpack-merge@5.8.0, webpack-merge@^5.7.3: clone-deep "^4.0.1" wildcard "^2.0.0" -webpack-sources@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.2.tgz#d88e3741833efec57c4c789b6010db9977545260" - integrity sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw== +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@5.65.0: - version "5.65.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.65.0.tgz#ed2891d9145ba1f0d318e4ea4f89c3fa18e6f9be" - integrity sha512-Q5or2o6EKs7+oKmJo7LaqZaMOlDWQse9Tm5l1WAfU/ujLGN5Pb0SqGeVkN/4bpPmEqEP5RnVhiqsOtWtUVwGRw== +webpack@5.72.0: + version "5.72.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.72.0.tgz#f8bc40d9c6bb489a4b7a8a685101d6022b8b6e28" + integrity sha512-qmSmbspI0Qo5ld49htys8GY9XhS9CGqFoHTsOVAnjBdg0Zn79y135R+k4IR4rKK6+eKaabMhJwiVB7xw0SJu5w== dependencies: - "@types/eslint-scope" "^3.7.0" - "@types/estree" "^0.0.50" + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/wasm-edit" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" @@ -4199,12 +4187,12 @@ webpack@5.65.0: acorn-import-assertions "^1.7.6" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.8.3" + enhanced-resolve "^5.9.2" es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" json-parse-better-errors "^1.0.2" loader-runner "^4.2.0" mime-types "^2.1.27" @@ -4213,7 +4201,7 @@ webpack@5.65.0: tapable "^2.1.1" terser-webpack-plugin "^5.1.3" watchpack "^2.3.1" - webpack-sources "^3.2.2" + webpack-sources "^3.2.3" websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" From 666516d7e9b4d34eb4abc32bdf291a61bb15987a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Apr 2022 07:32:29 +0000 Subject: [PATCH 11/28] chore(deps): bump async from 2.6.3 to 2.6.4 in /src/packages/excalidraw (#5069) Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4. - [Release notes](https://github.com/caolan/async/releases) - [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md) - [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4) --- updated-dependencies: - dependency-name: async dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/packages/excalidraw/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packages/excalidraw/yarn.lock b/src/packages/excalidraw/yarn.lock index f1cd5cd95..63491c465 100644 --- a/src/packages/excalidraw/yarn.lock +++ b/src/packages/excalidraw/yarn.lock @@ -1571,9 +1571,9 @@ array-union@^2.1.0: integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== async@^2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== dependencies: lodash "^4.17.14" From 6bcbf8b50ab491507c74992e7fbc6068cdfadae0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Apr 2022 07:40:12 +0000 Subject: [PATCH 12/28] chore(deps): bump node-forge in /src/packages/excalidraw (#5071) Bumps [node-forge](https://github.com/digitalbazaar/forge) from 1.2.1 to 1.3.1. - [Release notes](https://github.com/digitalbazaar/forge/releases) - [Changelog](https://github.com/digitalbazaar/forge/blob/main/CHANGELOG.md) - [Commits](https://github.com/digitalbazaar/forge/compare/v1.2.1...v1.3.1) --- updated-dependencies: - dependency-name: node-forge dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/packages/excalidraw/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packages/excalidraw/yarn.lock b/src/packages/excalidraw/yarn.lock index 63491c465..f9edd3b30 100644 --- a/src/packages/excalidraw/yarn.lock +++ b/src/packages/excalidraw/yarn.lock @@ -3146,9 +3146,9 @@ neo-async@^2.6.2: integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== node-forge@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.1.tgz#82794919071ef2eb5c509293325cec8afd0fd53c" - integrity sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w== + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== node-releases@^2.0.2: version "2.0.3" From b6a6f2d465d25c4c0bed247924fdf4ac324179f0 Mon Sep 17 00:00:00 2001 From: Achille Lacoin Date: Tue, 26 Apr 2022 13:28:39 +0200 Subject: [PATCH 13/28] feat: Expose `window.EXCALIDRAW_EXPORT_SOURCE` which host can use to overwrite the source field in exports (#5095) * Expose `window.EXCALIDRAW_EXPORT_SOURCE` which host can use to overwrite the source field in exports * Update src/packages/excalidraw/CHANGELOG.md Co-authored-by: David Luzar * address review comments * Update src/packages/excalidraw/README_NEXT.md Co-authored-by: Aakansha Doshi * Update src/packages/excalidraw/README_NEXT.md Co-authored-by: Aakansha Doshi * EXCALIDRAW_EXPORT_SOURCE -> EXCALIDRAW_EXPORT_SOURCE_PATH Co-authored-by: David Luzar Co-authored-by: Aakansha Doshi --- src/constants.ts | 3 ++- src/global.d.ts | 1 + src/packages/excalidraw/CHANGELOG.md | 1 + src/packages/excalidraw/README_NEXT.md | 4 ++++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/constants.ts b/src/constants.ts index 8d2ae3468..83c70cb69 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -108,7 +108,8 @@ export const EXPORT_DATA_TYPES = { excalidrawLibrary: "excalidrawlib", } as const; -export const EXPORT_SOURCE = window.location.origin; +export const EXPORT_SOURCE = + window.EXCALIDRAW_EXPORT_SOURCE_PATH || window.location.origin; // time in milliseconds export const IMAGE_RENDER_TIMEOUT = 500; diff --git a/src/global.d.ts b/src/global.d.ts index 4d607b9a7..a5cc0de5a 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -13,6 +13,7 @@ interface Window { ClipboardItem: any; __EXCALIDRAW_SHA__: string | undefined; EXCALIDRAW_ASSET_PATH: string | undefined; + EXCALIDRAW_EXPORT_SOURCE_PATH: string; gtag: Function; } diff --git a/src/packages/excalidraw/CHANGELOG.md b/src/packages/excalidraw/CHANGELOG.md index e3aa056d8..02bdebcc6 100644 --- a/src/packages/excalidraw/CHANGELOG.md +++ b/src/packages/excalidraw/CHANGELOG.md @@ -17,6 +17,7 @@ Please add the latest change on the top under the correct section. #### Features +- Expose `window.EXCALIDRAW_EXPORT_SOURCE_PATH` which you can use to overwrite the `source` field in exported data [#5095](https://github.com/excalidraw/excalidraw/pull/5095). - The `exportToBlob` utility now supports the `exportEmbedScene` option when generating a png image [#5047](https://github.com/excalidraw/excalidraw/pull/5047). - Exported [`restoreLibraryItems`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#restoreLibraryItems) API [#4995](https://github.com/excalidraw/excalidraw/pull/4995). diff --git a/src/packages/excalidraw/README_NEXT.md b/src/packages/excalidraw/README_NEXT.md index c20b29151..d67c8f9ee 100644 --- a/src/packages/excalidraw/README_NEXT.md +++ b/src/packages/excalidraw/README_NEXT.md @@ -924,6 +924,8 @@ serializeAsJSON({ Takes the scene elements and state and returns a JSON string. Deleted `elements`as well as most properties from `AppState` are removed from the resulting JSON. (see [`serializeAsJSON()`](https://github.com/excalidraw/excalidraw/blob/master/src/data/json.ts#L16) source for details). +If you want to overwrite the source field in the JSON string, you can set `window.EXCALIDRAW_EXPORT_SOURCE_PATH` to the desired value. + #### `serializeLibraryAsJSON` **_Signature_** @@ -935,6 +937,8 @@ serializeLibraryAsJSON({ Takes the library items and returns a JSON string. +If you want to overwrite the source field in the JSON string, you can set `window.EXCALIDRAW_EXPORT_SOURCE_PATH` to the desired value. + #### `getSceneVersion` **How to use** From af93cedc0883155759372a43887101889105305a Mon Sep 17 00:00:00 2001 From: Achille Lacoin Date: Wed, 27 Apr 2022 10:49:02 +0200 Subject: [PATCH 14/28] EXCALIDRAW_EXPORT_SOURCE_PATH -> EXCALIDRAW_EXPORT_SOURCE (#5102) --- src/constants.ts | 2 +- src/global.d.ts | 2 +- src/packages/excalidraw/CHANGELOG.md | 2 +- src/packages/excalidraw/README_NEXT.md | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 83c70cb69..47bbc8aed 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -109,7 +109,7 @@ export const EXPORT_DATA_TYPES = { } as const; export const EXPORT_SOURCE = - window.EXCALIDRAW_EXPORT_SOURCE_PATH || window.location.origin; + window.EXCALIDRAW_EXPORT_SOURCE || window.location.origin; // time in milliseconds export const IMAGE_RENDER_TIMEOUT = 500; diff --git a/src/global.d.ts b/src/global.d.ts index a5cc0de5a..dbaf3922e 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -13,7 +13,7 @@ interface Window { ClipboardItem: any; __EXCALIDRAW_SHA__: string | undefined; EXCALIDRAW_ASSET_PATH: string | undefined; - EXCALIDRAW_EXPORT_SOURCE_PATH: string; + EXCALIDRAW_EXPORT_SOURCE: string; gtag: Function; } diff --git a/src/packages/excalidraw/CHANGELOG.md b/src/packages/excalidraw/CHANGELOG.md index 02bdebcc6..b4ed48cba 100644 --- a/src/packages/excalidraw/CHANGELOG.md +++ b/src/packages/excalidraw/CHANGELOG.md @@ -17,7 +17,7 @@ Please add the latest change on the top under the correct section. #### Features -- Expose `window.EXCALIDRAW_EXPORT_SOURCE_PATH` which you can use to overwrite the `source` field in exported data [#5095](https://github.com/excalidraw/excalidraw/pull/5095). +- Expose `window.EXCALIDRAW_EXPORT_SOURCE` which you can use to overwrite the `source` field in exported data [#5095](https://github.com/excalidraw/excalidraw/pull/5095). - The `exportToBlob` utility now supports the `exportEmbedScene` option when generating a png image [#5047](https://github.com/excalidraw/excalidraw/pull/5047). - Exported [`restoreLibraryItems`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#restoreLibraryItems) API [#4995](https://github.com/excalidraw/excalidraw/pull/4995). diff --git a/src/packages/excalidraw/README_NEXT.md b/src/packages/excalidraw/README_NEXT.md index d67c8f9ee..f3da869c7 100644 --- a/src/packages/excalidraw/README_NEXT.md +++ b/src/packages/excalidraw/README_NEXT.md @@ -924,7 +924,7 @@ serializeAsJSON({ Takes the scene elements and state and returns a JSON string. Deleted `elements`as well as most properties from `AppState` are removed from the resulting JSON. (see [`serializeAsJSON()`](https://github.com/excalidraw/excalidraw/blob/master/src/data/json.ts#L16) source for details). -If you want to overwrite the source field in the JSON string, you can set `window.EXCALIDRAW_EXPORT_SOURCE_PATH` to the desired value. +If you want to overwrite the source field in the JSON string, you can set `window.EXCALIDRAW_EXPORT_SOURCE` to the desired value. #### `serializeLibraryAsJSON` @@ -937,7 +937,7 @@ serializeLibraryAsJSON({ Takes the library items and returns a JSON string. -If you want to overwrite the source field in the JSON string, you can set `window.EXCALIDRAW_EXPORT_SOURCE_PATH` to the desired value. +If you want to overwrite the source field in the JSON string, you can set `window.EXCALIDRAW_EXPORT_SOURCE` to the desired value. #### `getSceneVersion` From b5c67a384c53f16aa083e9ccdc4fc85272deb1c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Apr 2022 15:27:20 +0530 Subject: [PATCH 15/28] chore(deps): bump minimist from 1.2.5 to 1.2.6 (#5042) Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6) --- updated-dependencies: - dependency-name: minimist dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 77a26537d..1cb204eb9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8369,9 +8369,9 @@ minimatch@3.0.4, minimatch@^3.0.4: brace-expansion "^1.1.7" minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== minipass-collect@^1.0.2: version "1.0.2" From cf0f00285b2554dd76d0748e715fd409b9b57262 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Apr 2022 15:27:43 +0530 Subject: [PATCH 16/28] chore(deps): bump minimist from 1.2.5 to 1.2.6 in /src/packages/utils (#5040) Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6) --- updated-dependencies: - dependency-name: minimist dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/packages/utils/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packages/utils/yarn.lock b/src/packages/utils/yarn.lock index ebe9c89d8..bb117cf7f 100644 --- a/src/packages/utils/yarn.lock +++ b/src/packages/utils/yarn.lock @@ -2123,9 +2123,9 @@ mimic-fn@^2.1.0: integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== ms@2.0.0: version "2.0.0" From af8c59b5bb06e0a3001682062b169d35508cb9fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Apr 2022 15:27:56 +0530 Subject: [PATCH 17/28] chore(deps): bump minimist in /src/packages/excalidraw (#5039) Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6) --- updated-dependencies: - dependency-name: minimist dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/packages/excalidraw/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packages/excalidraw/yarn.lock b/src/packages/excalidraw/yarn.lock index f9edd3b30..070712f8c 100644 --- a/src/packages/excalidraw/yarn.lock +++ b/src/packages/excalidraw/yarn.lock @@ -3091,9 +3091,9 @@ minimatch@^3.0.4: brace-expansion "^1.1.7" minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== mkdirp@^0.5.5: version "0.5.5" From 7df8302ba2050cc7d4f701a8d77da99909c4be7f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Apr 2022 10:03:17 +0000 Subject: [PATCH 18/28] chore(deps-dev): bump babel-loader in /src/packages/utils (#5088) Bumps [babel-loader](https://github.com/babel/babel-loader) from 8.2.3 to 8.2.5. - [Release notes](https://github.com/babel/babel-loader/releases) - [Changelog](https://github.com/babel/babel-loader/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel-loader/compare/v8.2.3...v8.2.5) --- updated-dependencies: - dependency-name: babel-loader dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/packages/utils/package.json | 2 +- src/packages/utils/yarn.lock | 28 ++++++---------------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/src/packages/utils/package.json b/src/packages/utils/package.json index bf06ed494..26c82fb71 100644 --- a/src/packages/utils/package.json +++ b/src/packages/utils/package.json @@ -41,7 +41,7 @@ "@babel/plugin-transform-typescript": "7.16.1", "@babel/preset-env": "7.16.7", "@babel/preset-typescript": "7.16.7", - "babel-loader": "8.2.3", + "babel-loader": "8.2.5", "babel-plugin-transform-class-properties": "6.24.1", "cross-env": "7.0.3", "css-loader": "6.7.1", diff --git a/src/packages/utils/yarn.lock b/src/packages/utils/yarn.lock index bb117cf7f..0efdd1b70 100644 --- a/src/packages/utils/yarn.lock +++ b/src/packages/utils/yarn.lock @@ -1320,13 +1320,13 @@ babel-helper-get-function-arity@^6.24.1: babel-runtime "^6.22.0" babel-types "^6.24.1" -babel-loader@8.2.3: - version "8.2.3" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" - integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== +babel-loader@8.2.5: + version "8.2.5" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e" + integrity sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ== dependencies: find-cache-dir "^3.3.1" - loader-utils "^1.4.0" + loader-utils "^2.0.0" make-dir "^3.1.0" schema-utils "^2.6.5" @@ -2002,13 +2002,6 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - json5@^2.1.2: version "2.2.0" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" @@ -2031,15 +2024,6 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== -loader-utils@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^1.0.1" - loader-utils@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" @@ -2122,7 +2106,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimist@^1.2.0, minimist@^1.2.5: +minimist@^1.2.5: version "1.2.6" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== From 399ce1e01a20c1b5933f21d8ac3961d84c6839aa Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Wed, 27 Apr 2022 17:04:21 +0530 Subject: [PATCH 19/28] fix: don't bind text to container if double clicked else instead of center (#5105) --- src/components/App.tsx | 3 +-- src/element/textWysiwyg.test.tsx | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index a5c6ddff7..b82db477c 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -2239,8 +2239,7 @@ class App extends React.Component { if (isTextElement(selectedElements[0])) { existingTextElement = selectedElements[0]; } else if (isTextBindableContainer(selectedElements[0], false)) { - container = selectedElements[0]; - existingTextElement = getBoundTextElement(container); + existingTextElement = getBoundTextElement(selectedElements[0]); } } diff --git a/src/element/textWysiwyg.test.tsx b/src/element/textWysiwyg.test.tsx index d9753c89b..ae7f1341c 100644 --- a/src/element/textWysiwyg.test.tsx +++ b/src/element/textWysiwyg.test.tsx @@ -544,6 +544,29 @@ describe("textWysiwyg", () => { expect((h.elements[1] as ExcalidrawTextElement).containerId).toBe(null); }); + it("should'nt bind text to container when not double clicked on center", async () => { + expect(h.elements.length).toBe(1); + expect(h.elements[0].id).toBe(rectangle.id); + + // clicking somewhere on top left + mouse.doubleClickAt(rectangle.x + 20, rectangle.y + 20); + expect(h.elements.length).toBe(2); + + const text = h.elements[1] as ExcalidrawTextElementWithContainer; + expect(text.type).toBe("text"); + expect(text.containerId).toBe(null); + mouse.down(); + const editor = document.querySelector( + ".excalidraw-textEditorContainer > textarea", + ) as HTMLTextAreaElement; + + fireEvent.change(editor, { target: { value: "Hello World!" } }); + + await new Promise((r) => setTimeout(r, 0)); + editor.blur(); + expect(rectangle.boundElements).toBe(null); + }); + it("should update font family correctly on undo/redo by selecting bounded text when font family was updated", async () => { expect(h.elements.length).toBe(1); From ea51251fe6a0aa00061958487f6a8888dbf97b0c Mon Sep 17 00:00:00 2001 From: Achille Lacoin Date: Wed, 27 Apr 2022 20:28:41 +0200 Subject: [PATCH 20/28] fix: propagate keydown events from excalidraw-wysiwyg inputs (#5099) * fix: allow propagation for keydown events originating from `excalidraw-wysiwyg` * revert check on the handleKeyDown function --- src/element/textWysiwyg.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/element/textWysiwyg.tsx b/src/element/textWysiwyg.tsx index 4edea15db..5242d13df 100644 --- a/src/element/textWysiwyg.tsx +++ b/src/element/textWysiwyg.tsx @@ -316,8 +316,6 @@ export const textWysiwyg = ({ } editable.onkeydown = (event) => { - event.stopPropagation(); - if (!event.shiftKey && actionZoomIn.keyTest(event)) { event.preventDefault(); app.actionManager.executeAction(actionZoomIn); From da94eb1284b9f49835ef0a4e9cd8a34177d2a378 Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Thu, 28 Apr 2022 20:19:41 +0530 Subject: [PATCH 21/28] fix: use excalidraw asset path in fonts when exporting to svg (#5065) * fix: use excalidraw asset path in fonts when exporting * fix * fix * introduce env variables and determine asset path correctly * fix snaps * use env vars to determine pkg name and version * update docs * quotes --- src/packages/excalidraw/CHANGELOG.md | 1 + src/packages/excalidraw/env.js | 8 ++++++-- src/packages/excalidraw/publicPath.js | 3 +-- src/scene/export.ts | 18 +++++++++++++++--- src/tests/scene/export.test.ts | 1 + src/utils.ts | 3 +++ 6 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/packages/excalidraw/CHANGELOG.md b/src/packages/excalidraw/CHANGELOG.md index b4ed48cba..450239eff 100644 --- a/src/packages/excalidraw/CHANGELOG.md +++ b/src/packages/excalidraw/CHANGELOG.md @@ -23,6 +23,7 @@ Please add the latest change on the top under the correct section. #### Fixes +- Use `window.EXCALIDRAW_ASSET_PATH` for fonts when exporting to svg [#5065](https://github.com/excalidraw/excalidraw/pull/5065). - Library menu now properly rerenders if open when library is updated using `updateScene({ libraryItems })` [#4995](https://github.com/excalidraw/excalidraw/pull/4995). #### Refactor diff --git a/src/packages/excalidraw/env.js b/src/packages/excalidraw/env.js index 7ca6283e2..6c5fd56e5 100644 --- a/src/packages/excalidraw/env.js +++ b/src/packages/excalidraw/env.js @@ -1,14 +1,18 @@ const dotenv = require("dotenv"); const { readFileSync } = require("fs"); - +const pkg = require("./package.json"); const parseEnvVariables = (filepath) => { - return Object.entries(dotenv.parse(readFileSync(filepath))).reduce( + const envVars = Object.entries(dotenv.parse(readFileSync(filepath))).reduce( (env, [key, value]) => { env[key] = JSON.stringify(value); return env; }, {}, ); + envVars.PKG_NAME = JSON.stringify(pkg.name); + envVars.PKG_VERSION = JSON.stringify(pkg.version); + envVars.IS_EXCALIDRAW_NPM_PACKAGE = JSON.stringify(true); + return envVars; }; module.exports = { parseEnvVariables }; diff --git a/src/packages/excalidraw/publicPath.js b/src/packages/excalidraw/publicPath.js index 93660ee66..0e1f8c3db 100644 --- a/src/packages/excalidraw/publicPath.js +++ b/src/packages/excalidraw/publicPath.js @@ -1,9 +1,8 @@ import { ENV } from "../../constants"; -import pkg from "./package.json"; if (process.env.NODE_ENV !== ENV.TEST) { /* eslint-disable */ /* global __webpack_public_path__:writable */ __webpack_public_path__ = window.EXCALIDRAW_ASSET_PATH || - `https://unpkg.com/${pkg.name}@${pkg.version}/dist/`; + `https://unpkg.com/${process.env.PKG_NAME}@${process.env.PKG_VERSION}/dist/`; } diff --git a/src/scene/export.ts b/src/scene/export.ts index d404e822b..9dacc755b 100644 --- a/src/scene/export.ts +++ b/src/scene/export.ts @@ -115,6 +115,19 @@ export const exportToSvg = async ( svgRoot.setAttribute("filter", THEME_FILTER); } + let assetPath = "https://excalidraw.com/"; + + // Asset path needs to be determined only when using package + if (process.env.IS_EXCALIDRAW_NPM_PACKAGE) { + assetPath = + window.EXCALIDRAW_ASSET_PATH || + `https://unpkg.com/${process.env.PKG_NAME}@${process.env.PKG_VERSION}`; + + if (assetPath?.startsWith("/")) { + assetPath = assetPath.replace("/", `${window.location.origin}/`); + } + assetPath = `${assetPath}/dist/excalidraw-assets/`; + } svgRoot.innerHTML = ` ${SVG_EXPORT_TAG} ${metadata} @@ -122,16 +135,15 @@ export const exportToSvg = async ( `; - // render background rect if (appState.exportBackground && viewBackgroundColor) { const rect = svgRoot.ownerDocument!.createElementNS(SVG_NS, "rect"); diff --git a/src/tests/scene/export.test.ts b/src/tests/scene/export.test.ts index 1b6f72113..bab87a15c 100644 --- a/src/tests/scene/export.test.ts +++ b/src/tests/scene/export.test.ts @@ -7,6 +7,7 @@ import { } from "../fixtures/elementFixture"; describe("exportToSvg", () => { + window.EXCALIDRAW_ASSET_PATH = "/"; const ELEMENT_HEIGHT = 100; const ELEMENT_WIDTH = 100; const ELEMENTS = [ diff --git a/src/utils.ts b/src/utils.ts index 91b67fd2b..fd20f7535 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -575,6 +575,9 @@ export const arrayToMap = ( export const isTestEnv = () => typeof process !== "undefined" && process.env?.NODE_ENV === "test"; +export const isProdEnv = () => + typeof process !== "undefined" && process.env?.NODE_ENV === "production"; + export const wrapEvent = (name: EVENT, nativeEvent: T) => { return new CustomEvent(name, { detail: { From aee1e2451e9d977c822a590c2961ba4aaf2f3e07 Mon Sep 17 00:00:00 2001 From: Johannes Date: Thu, 28 Apr 2022 18:10:08 +0100 Subject: [PATCH 22/28] fix: remove opacity scroll wheel interaction (#5111) --- src/actions/actionProperties.tsx | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/actions/actionProperties.tsx b/src/actions/actionProperties.tsx index 53801a220..49efbe45f 100644 --- a/src/actions/actionProperties.tsx +++ b/src/actions/actionProperties.tsx @@ -503,20 +503,6 @@ export const actionChangeOpacity = register({ max="100" step="10" onChange={(event) => updateData(+event.target.value)} - onWheel={(event) => { - event.stopPropagation(); - const target = event.target as HTMLInputElement; - const STEP = 10; - const MAX = 100; - const MIN = 0; - const value = +target.value; - - if (event.deltaY < 0 && value < MAX) { - updateData(value + STEP); - } else if (event.deltaY > 0 && value > MIN) { - updateData(value - STEP); - } - }} value={ getFormValue( elements, From 6a0f80071628190b4fc3dbfb6cfc611af3ede2b9 Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Fri, 29 Apr 2022 18:58:44 +0530 Subject: [PATCH 23/28] feat: export exportToClipboard util from package (#5103) * feat: export copyToClipboard from package * use promise constructor for better browser supprt * add type to exportToClipboard * update docs * use json instead of text and use selected element in actionCopy * pass `files` in example `exportToClipboard` * fix bad access Co-authored-by: dwelle --- src/actions/actionClipboard.tsx | 4 ++- src/clipboard.ts | 22 +++++++------- src/packages/excalidraw/CHANGELOG.md | 1 + src/packages/excalidraw/README_NEXT.md | 30 ++++++++++++++++++- src/packages/excalidraw/example/App.js | 30 +++++++++++++++++-- src/packages/excalidraw/index.tsx | 1 + src/packages/utils.ts | 41 ++++++++++++++++++++++++-- 7 files changed, 111 insertions(+), 18 deletions(-) diff --git a/src/actions/actionClipboard.tsx b/src/actions/actionClipboard.tsx index 5d92290e2..8a25e1810 100644 --- a/src/actions/actionClipboard.tsx +++ b/src/actions/actionClipboard.tsx @@ -15,7 +15,9 @@ export const actionCopy = register({ name: "copy", trackEvent: { category: "element" }, perform: (elements, appState, _, app) => { - copyToClipboard(getNonDeletedElements(elements), appState, app.files); + const selectedElements = getSelectedElements(elements, appState, true); + + copyToClipboard(selectedElements, appState, app.files); return { commitToHistory: false, diff --git a/src/clipboard.ts b/src/clipboard.ts index 5b61dae25..bc4d3d3b4 100644 --- a/src/clipboard.ts +++ b/src/clipboard.ts @@ -2,7 +2,6 @@ import { ExcalidrawElement, NonDeletedExcalidrawElement, } from "./element/types"; -import { getSelectedElements } from "./scene"; import { AppState, BinaryFiles } from "./types"; import { SVG_EXPORT_TAG } from "./scene/export"; import { tryParseSpreadsheet, Spreadsheet, VALID_SPREADSHEET } from "./charts"; @@ -12,7 +11,7 @@ import { isPromiseLike } from "./utils"; type ElementsClipboard = { type: typeof EXPORT_DATA_TYPES.excalidrawClipboard; - elements: ExcalidrawElement[]; + elements: readonly NonDeletedExcalidrawElement[]; files: BinaryFiles | undefined; }; @@ -57,19 +56,20 @@ const clipboardContainsElements = ( export const copyToClipboard = async ( elements: readonly NonDeletedExcalidrawElement[], appState: AppState, - files: BinaryFiles, + files: BinaryFiles | null, ) => { // select binded text elements when copying - const selectedElements = getSelectedElements(elements, appState, true); const contents: ElementsClipboard = { type: EXPORT_DATA_TYPES.excalidrawClipboard, - elements: selectedElements, - files: selectedElements.reduce((acc, element) => { - if (isInitializedImageElement(element) && files[element.fileId]) { - acc[element.fileId] = files[element.fileId]; - } - return acc; - }, {} as BinaryFiles), + elements, + files: files + ? elements.reduce((acc, element) => { + if (isInitializedImageElement(element) && files[element.fileId]) { + acc[element.fileId] = files[element.fileId]; + } + return acc; + }, {} as BinaryFiles) + : undefined, }; const json = JSON.stringify(contents); CLIPBOARD = json; diff --git a/src/packages/excalidraw/CHANGELOG.md b/src/packages/excalidraw/CHANGELOG.md index 450239eff..ccd3ad86a 100644 --- a/src/packages/excalidraw/CHANGELOG.md +++ b/src/packages/excalidraw/CHANGELOG.md @@ -17,6 +17,7 @@ Please add the latest change on the top under the correct section. #### Features +- Expose util `exportToClipboard`[https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#exportToClipboard] which allows to copy the scene contents to clipboard as `svg`, `png` or `json` [#5103](https://github.com/excalidraw/excalidraw/pull/5103). - Expose `window.EXCALIDRAW_EXPORT_SOURCE` which you can use to overwrite the `source` field in exported data [#5095](https://github.com/excalidraw/excalidraw/pull/5095). - The `exportToBlob` utility now supports the `exportEmbedScene` option when generating a png image [#5047](https://github.com/excalidraw/excalidraw/pull/5047). - Exported [`restoreLibraryItems`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#restoreLibraryItems) API [#4995](https://github.com/excalidraw/excalidraw/pull/4995). diff --git a/src/packages/excalidraw/README_NEXT.md b/src/packages/excalidraw/README_NEXT.md index f3da869c7..ee7c85c2f 100644 --- a/src/packages/excalidraw/README_NEXT.md +++ b/src/packages/excalidraw/README_NEXT.md @@ -857,7 +857,7 @@ This function returns the canvas with the exported elements, appState and dimens
 exportToBlob(
-  opts: ExportOpts & {
+  opts: ExportOpts & {
   mimeType?: string,
   quality?: number;
 })
@@ -900,6 +900,34 @@ exportToSvg({
 
 This function returns a promise which resolves to svg of the exported drawing.
 
+#### `exportToClipboard`
+
+**_Signature_**
+
+
+exportToClipboard(
+  opts: ExportOpts & {
+  mimeType?: string,
+  quality?: number;
+  type: 'png' | 'svg' |'json'
+})
+
+ +| Name | Type | Default | Description | +| --- | --- | --- | --- | --- | --- | +| opts | | | This param is same as the params passed to `exportToCanvas`. You can refer to [`exportToCanvas`](#exportToCanvas). | +| mimeType | string | "image/png" | Indicates the image format, this will be used when exporting as `png`. | +| quality | number | 0.92 | A value between 0 and 1 indicating the [image quality](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#parameters). Applies only to `image/jpeg`/`image/webp` MIME types. This will be used when exporting as `png`. | +| type | 'png' | 'svg' | 'json' | | This determines the format to which the scene data should be exported. | + +**How to use** + +```js +import { exportToClipboard } from "@excalidraw/excalidraw-next"; +``` + +Copies the scene data in the specified format (determined by `type`) to clipboard. + ##### Additional attributes of appState for `export\*` APIs | Name | Type | Default | Description | diff --git a/src/packages/excalidraw/example/App.js b/src/packages/excalidraw/example/App.js index 4182cd3bb..49af956c8 100644 --- a/src/packages/excalidraw/example/App.js +++ b/src/packages/excalidraw/example/App.js @@ -10,8 +10,13 @@ import { MIME_TYPES } from "../../../constants"; // This is so that we use the bundled excalidraw.development.js file instead // of the actual source code -const { exportToCanvas, exportToSvg, exportToBlob, Excalidraw } = - window.ExcalidrawLib; +const { + exportToCanvas, + exportToSvg, + exportToBlob, + exportToClipboard, + Excalidraw, +} = window.ExcalidrawLib; const resolvablePromise = () => { let resolve; let reject; @@ -141,6 +146,15 @@ export default function App() { } }, []); + const onCopy = async (type) => { + await exportToClipboard({ + elements: excalidrawRef.current.getSceneElements(), + appState: excalidrawRef.current.getAppState(), + files: excalidrawRef.current.getFiles(), + type, + }); + window.alert(`Copied to clipboard as ${type} sucessfully`); + }; return (

Excalidraw Example

@@ -175,6 +189,7 @@ export default function App() { > Update Library + +
+ + + +
[]; @@ -81,7 +86,7 @@ export const exportToBlob = async ( mimeType?: string; quality?: number; }, -): Promise => { +): Promise => { let { mimeType = MIME_TYPES.png, quality } = opts; if (mimeType === MIME_TYPES.png && typeof quality === "number") { @@ -107,9 +112,12 @@ export const exportToBlob = async ( quality = quality ? quality : /image\/jpe?g/.test(mimeType) ? 0.92 : 0.8; - return new Promise((resolve) => { + return new Promise((resolve, reject) => { canvas.toBlob( - async (blob: Blob | null) => { + async (blob) => { + if (!blob) { + return reject(new Error("couldn't export to blob")); + } if ( blob && mimeType === MIME_TYPES.png && @@ -156,6 +164,33 @@ export const exportToSvg = async ({ ); }; +export const exportToClipboard = async ( + opts: ExportOpts & { + mimeType?: string; + quality?: number; + type: "png" | "svg" | "json"; + }, +) => { + if (opts.type === "svg") { + const svg = await exportToSvg(opts); + await copyTextToSystemClipboard(svg.outerHTML); + } else if (opts.type === "png") { + await copyBlobToClipboardAsPng(exportToBlob(opts)); + } else if (opts.type === "json") { + const appState = { + offsetTop: 0, + offsetLeft: 0, + width: 0, + height: 0, + ...getDefaultAppState(), + ...opts.appState, + }; + await copyToClipboard(opts.elements, appState, opts.files); + } else { + throw new Error("Invalid export type"); + } +}; + export { serializeAsJSON, serializeLibraryAsJSON } from "../data/json"; export { loadFromBlob, loadLibraryFromBlob } from "../data/blob"; export { getFreeDrawSvgPath } from "../renderer/renderElement"; From d53ac2a61e2350cde751f4f986defc365803a7d1 Mon Sep 17 00:00:00 2001 From: David Luzar Date: Fri, 29 Apr 2022 16:45:02 +0200 Subject: [PATCH 24/28] fix: library init/import race conditions (#5101) --- src/actions/actionAddToLibrary.ts | 4 +- src/components/App.tsx | 85 ++++++---- src/components/LibraryMenu.scss | 4 + src/components/LibraryMenu.tsx | 14 +- src/components/LibraryMenuItems.tsx | 32 ++-- src/data/library.ts | 212 ++++++++++++++++--------- src/packages/excalidraw/CHANGELOG.md | 4 +- src/packages/excalidraw/README_NEXT.md | 20 ++- src/packages/excalidraw/index.tsx | 1 + src/packages/utils.ts | 1 + src/tests/library.test.tsx | 4 +- 11 files changed, 248 insertions(+), 133 deletions(-) diff --git a/src/actions/actionAddToLibrary.ts b/src/actions/actionAddToLibrary.ts index 7d2f9877c..41a701786 100644 --- a/src/actions/actionAddToLibrary.ts +++ b/src/actions/actionAddToLibrary.ts @@ -25,9 +25,9 @@ export const actionAddToLibrary = register({ } return app.library - .loadLibrary() + .getLatestLibrary() .then((items) => { - return app.library.saveLibrary([ + return app.library.setLibrary([ { id: randomId(), status: "unpublished", diff --git a/src/components/App.tsx b/src/components/App.tsx index b82db477c..4bc0bc1cf 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -257,6 +257,7 @@ import { isPointHittingLinkIcon, isLocalLink, } from "../element/Hyperlink"; +import { AbortError } from "../errors"; const defaultDeviceTypeContext: DeviceType = { isMobile: false, @@ -703,21 +704,35 @@ class App extends React.Component { window.history.replaceState({}, APP_NAME, `?${query.toString()}`); } + const defaultStatus = "published"; + + this.setState({ isLibraryOpen: true }); + try { - const request = await fetch(decodeURIComponent(url)); - const blob = await request.blob(); - const defaultStatus = "published"; - const libraryItems = await loadLibraryFromBlob(blob, defaultStatus); - if ( - token === this.id || - window.confirm( - t("alerts.confirmAddLibrary", { - numShapes: libraryItems.length, - }), - ) - ) { - await this.library.importLibrary(libraryItems, defaultStatus); - } + await this.library.importLibrary( + new Promise(async (resolve, reject) => { + try { + const request = await fetch(decodeURIComponent(url)); + const blob = await request.blob(); + const libraryItems = await loadLibraryFromBlob(blob, defaultStatus); + + if ( + token === this.id || + window.confirm( + t("alerts.confirmAddLibrary", { + numShapes: libraryItems.length, + }), + ) + ) { + resolve(libraryItems); + } else { + reject(new AbortError()); + } + } catch (error: any) { + reject(error); + } + }), + ); } catch (error: any) { console.error(error); this.setState({ errorMessage: t("errors.importLibraryError") }); @@ -1674,6 +1689,11 @@ class App extends React.Component { collaborators?: SceneData["collaborators"]; commitToHistory?: SceneData["commitToHistory"]; libraryItems?: + | (( + currentLibraryItems: LibraryItems, + ) => + | Required["libraryItems"] + | Promise["libraryItems"]>) | Required["libraryItems"] | Promise["libraryItems"]>; }) => { @@ -1694,20 +1714,20 @@ class App extends React.Component { } if (sceneData.libraryItems) { - this.library.saveLibrary( - new Promise(async (resolve, reject) => { + this.library.setLibrary((currentLibraryItems) => { + const nextItems = + typeof sceneData.libraryItems === "function" + ? sceneData.libraryItems(currentLibraryItems) + : sceneData.libraryItems; + + return new Promise(async (resolve, reject) => { try { - resolve( - restoreLibraryItems( - await sceneData.libraryItems, - "unpublished", - ), - ); - } catch { - reject(new Error(t("errors.importLibraryError"))); + resolve(restoreLibraryItems(await nextItems, "unpublished")); + } catch (error: any) { + reject(error); } - }), - ); + }); + }); } }, ); @@ -5280,11 +5300,14 @@ class App extends React.Component { file?.type === MIME_TYPES.excalidrawlib || file?.name?.endsWith(".excalidrawlib") ) { - this.library - .importLibrary(file) - .catch((error) => - this.setState({ isLoading: false, errorMessage: error.message }), - ); + this.setState({ isLibraryOpen: true }); + this.library.importLibrary(file).catch((error) => { + console.error(error); + this.setState({ + isLoading: false, + errorMessage: t("errors.importLibraryError"), + }); + }); // default: assume an Excalidraw file regardless of extension/MimeType } else if (file) { this.setState({ isLoading: true }); diff --git a/src/components/LibraryMenu.scss b/src/components/LibraryMenu.scss index 803c18480..7e0f43af5 100644 --- a/src/components/LibraryMenu.scss +++ b/src/components/LibraryMenu.scss @@ -13,6 +13,10 @@ width: 100%; margin: 2px 0; + .Spinner { + margin-right: 1rem; + } + button { // 2px from the left to account for focus border of left-most button margin: 0 2px; diff --git a/src/components/LibraryMenu.tsx b/src/components/LibraryMenu.tsx index 8ecced2cf..e2389836d 100644 --- a/src/components/LibraryMenu.tsx +++ b/src/components/LibraryMenu.tsx @@ -139,7 +139,7 @@ export const LibraryMenu = ({ const nextItems = libraryItems.filter( (item) => !selectedItems.includes(item.id), ); - library.saveLibrary(nextItems).catch(() => { + library.setLibrary(nextItems).catch(() => { setAppState({ errorMessage: t("alerts.errorRemovingFromLibrary") }); }); setSelectedItems([]); @@ -170,7 +170,7 @@ export const LibraryMenu = ({ ...libraryItems, ]; onAddToLibrary(); - library.saveLibrary(nextItems).catch(() => { + library.setLibrary(nextItems).catch(() => { setAppState({ errorMessage: t("alerts.errorAddingToLibrary") }); }); }, @@ -220,7 +220,7 @@ export const LibraryMenu = ({ libItem.status = "published"; } }); - library.saveLibrary(nextLibItems); + library.setLibrary(nextLibItems); }, [setShowPublishLibraryDialog, setPublishLibSuccess, selectedItems, library], ); @@ -229,7 +229,10 @@ export const LibraryMenu = ({ LibraryItem["id"] | null >(null); - if (libraryItemsData.status === "loading") { + if ( + libraryItemsData.status === "loading" && + !libraryItemsData.isInitialized + ) { return (
@@ -255,7 +258,7 @@ export const LibraryMenu = ({ } onError={(error) => window.alert(error)} updateItemsInStorage={() => - library.saveLibrary(libraryItemsData.libraryItems) + library.setLibrary(libraryItemsData.libraryItems) } onRemove={(id: string) => setSelectedItems(selectedItems.filter((_id) => _id !== id)) @@ -264,6 +267,7 @@ export const LibraryMenu = ({ )} {publishLibSuccess && renderPublishSuccess()} removeFromLibrary(libraryItemsData.libraryItems) diff --git a/src/components/LibraryMenuItems.tsx b/src/components/LibraryMenuItems.tsx index b236e1023..11aff36cb 100644 --- a/src/components/LibraryMenuItems.tsx +++ b/src/components/LibraryMenuItems.tsx @@ -22,8 +22,10 @@ import { Tooltip } from "./Tooltip"; import "./LibraryMenuItems.scss"; import { VERSIONS } from "../constants"; +import Spinner from "./Spinner"; const LibraryMenuItems = ({ + isLoading, libraryItems, onRemoveFromLibrary, onAddToLibrary, @@ -40,6 +42,7 @@ const LibraryMenuItems = ({ onPublish, resetLibrary, }: { + isLoading: boolean; libraryItems: LibraryItems; pendingElements: LibraryItem["elements"]; onRemoveFromLibrary: () => void; @@ -108,7 +111,8 @@ const LibraryMenuItems = ({ importLibraryFromJSON(library) .catch(muteFSAbortError) .catch((error) => { - setAppState({ errorMessage: error.message }); + console.error(error); + setAppState({ errorMessage: t("errors.importLibraryError") }); }); }} className="library-actions--load" @@ -125,7 +129,7 @@ const LibraryMenuItems = ({ onClick={async () => { const libraryItems = itemsSelected ? items - : await library.loadLibrary(); + : await library.getLatestLibrary(); saveLibraryAsJSON(libraryItems) .catch(muteFSAbortError) .catch((error) => { @@ -284,16 +288,20 @@ const LibraryMenuItems = ({ {showRemoveLibAlert && renderRemoveLibAlert()}
{renderLibraryActions()} - - {t("labels.libraries")} - + {isLoading ? ( + + ) : ( + + {t("labels.libraries")} + + )}
} - | { status: "loaded"; libraryItems: LibraryItems } ->({ status: "loaded", libraryItems: [] }); +export const libraryItemsAtom = atom<{ + status: "loading" | "loaded"; + isInitialized: boolean; + libraryItems: LibraryItems; +}>({ status: "loaded", isInitialized: true, libraryItems: [] }); const cloneLibraryItems = (libraryItems: LibraryItems): LibraryItems => JSON.parse(JSON.stringify(libraryItems)); @@ -40,12 +39,28 @@ const isUniqueItem = ( }); }; +/** Merges otherItems into localItems. Unique items in otherItems array are + sorted first. */ +export const mergeLibraryItems = ( + localItems: LibraryItems, + otherItems: LibraryItems, +): LibraryItems => { + const newItems = []; + for (const item of otherItems) { + if (isUniqueItem(localItems, item)) { + newItems.push(item); + } + } + + return [...newItems, ...localItems]; +}; + class Library { - /** cache for currently active promise when initializing/updating libaries - asynchronously */ - private libraryItemsPromise: Promise | null = null; - /** last resolved libraryItems */ + /** latest libraryItems */ private lastLibraryItems: LibraryItems = []; + /** indicates whether library is initialized with library items (has gone + * though at least one update) */ + private isInitialized = false; private app: App; @@ -53,95 +68,138 @@ class Library { this.app = app; } - resetLibrary = async () => { - this.saveLibrary([]); + private updateQueue: Promise[] = []; + + private getLastUpdateTask = (): Promise | undefined => { + return this.updateQueue[this.updateQueue.length - 1]; }; - /** imports library (currently merges, removing duplicates) */ - async importLibrary( + private notifyListeners = () => { + if (this.updateQueue.length > 0) { + jotaiStore.set(libraryItemsAtom, { + status: "loading", + libraryItems: this.lastLibraryItems, + isInitialized: this.isInitialized, + }); + } else { + this.isInitialized = true; + jotaiStore.set(libraryItemsAtom, { + status: "loaded", + libraryItems: this.lastLibraryItems, + isInitialized: this.isInitialized, + }); + try { + this.app.props.onLibraryChange?.( + cloneLibraryItems(this.lastLibraryItems), + ); + } catch (error) { + console.error(error); + } + } + }; + + resetLibrary = () => { + return this.setLibrary([]); + }; + + /** + * imports library (from blob or libraryItems), merging with current library + * (attempting to remove duplicates) + */ + importLibrary( library: | Blob | Required["libraryItems"] | Promise["libraryItems"]>, defaultStatus: LibraryItem["status"] = "unpublished", - ) { - return this.saveLibrary( - new Promise(async (resolve, reject) => { - try { - let libraryItems: LibraryItems; - if (library instanceof Blob) { - libraryItems = await loadLibraryFromBlob(library, defaultStatus); - } else { - libraryItems = restoreLibraryItems(await library, defaultStatus); - } - - const existingLibraryItems = this.lastLibraryItems; - - const filteredItems = []; - for (const item of libraryItems) { - if (isUniqueItem(existingLibraryItems, item)) { - filteredItems.push(item); + ): Promise { + return this.setLibrary( + () => + new Promise(async (resolve, reject) => { + try { + let libraryItems: LibraryItems; + if (library instanceof Blob) { + libraryItems = await loadLibraryFromBlob(library, defaultStatus); + } else { + libraryItems = restoreLibraryItems(await library, defaultStatus); } - } - resolve([...filteredItems, ...existingLibraryItems]); - } catch (error) { - reject(new Error(t("errors.importLibraryError"))); - } - }), + resolve(mergeLibraryItems(this.lastLibraryItems, libraryItems)); + } catch (error) { + reject(error); + } + }), ); } - loadLibrary = (): Promise => { + /** + * @returns latest cloned libraryItems. Awaits all in-progress updates first. + */ + getLatestLibrary = (): Promise => { return new Promise(async (resolve) => { try { - resolve( - cloneLibraryItems( - await (this.libraryItemsPromise || this.lastLibraryItems), - ), - ); + const libraryItems = await (this.getLastUpdateTask() || + this.lastLibraryItems); + if (this.updateQueue.length > 0) { + resolve(this.getLatestLibrary()); + } else { + resolve(cloneLibraryItems(libraryItems)); + } } catch (error) { return resolve(this.lastLibraryItems); } }); }; - saveLibrary = async (items: LibraryItems | Promise) => { - const prevLibraryItems = this.lastLibraryItems; - try { - let nextLibraryItems; - if (isPromiseLike(items)) { - const promise = items.then((items) => cloneLibraryItems(items)); - this.libraryItemsPromise = promise; - jotaiStore.set(libraryItemsAtom, { - status: "loading", - promise, - libraryItems: null, - }); - nextLibraryItems = await promise; - } else { - nextLibraryItems = cloneLibraryItems(items); + setLibrary = ( + /** + * LibraryItems that will replace current items. Can be a function which + * will be invoked after all previous tasks are resolved + * (this is the prefered way to update the library to avoid race conditions, + * but you'll want to manually merge the library items in the callback + * - which is what we're doing in Library.importLibrary()). + * + * If supplied promise is rejected with AbortError, we swallow it and + * do not update the library. + */ + libraryItems: + | LibraryItems + | Promise + | (( + latestLibraryItems: LibraryItems, + ) => LibraryItems | Promise), + ): Promise => { + const task = new Promise(async (resolve, reject) => { + try { + await this.getLastUpdateTask(); + + if (typeof libraryItems === "function") { + libraryItems = libraryItems(this.lastLibraryItems); + } + + this.lastLibraryItems = cloneLibraryItems(await libraryItems); + + resolve(this.lastLibraryItems); + } catch (error: any) { + reject(error); } - - this.lastLibraryItems = nextLibraryItems; - this.libraryItemsPromise = null; - - jotaiStore.set(libraryItemsAtom, { - status: "loaded", - libraryItems: nextLibraryItems, + }) + .catch((error) => { + if (error.name === "AbortError") { + console.warn("Library update aborted by user"); + return this.lastLibraryItems; + } + throw error; + }) + .finally(() => { + this.updateQueue = this.updateQueue.filter((_task) => _task !== task); + this.notifyListeners(); }); - await this.app.props.onLibraryChange?.( - cloneLibraryItems(nextLibraryItems), - ); - } catch (error: any) { - this.lastLibraryItems = prevLibraryItems; - this.libraryItemsPromise = null; - jotaiStore.set(libraryItemsAtom, { - status: "loaded", - libraryItems: prevLibraryItems, - }); - throw error; - } + + this.updateQueue.push(task); + this.notifyListeners(); + + return task; }; } diff --git a/src/packages/excalidraw/CHANGELOG.md b/src/packages/excalidraw/CHANGELOG.md index ccd3ad86a..3c18aa282 100644 --- a/src/packages/excalidraw/CHANGELOG.md +++ b/src/packages/excalidraw/CHANGELOG.md @@ -17,7 +17,9 @@ Please add the latest change on the top under the correct section. #### Features -- Expose util `exportToClipboard`[https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#exportToClipboard] which allows to copy the scene contents to clipboard as `svg`, `png` or `json` [#5103](https://github.com/excalidraw/excalidraw/pull/5103). +- Support `libraryItems` argument in `initialData.libraryItems` and `updateScene({ libraryItems })` to be a Promise resolving to `LibraryItems`, and support functional update of `libraryItems` in [`updateScene({ libraryItems })`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#updateScene). [#5101](https://github.com/excalidraw/excalidraw/pull/5101). +- Expose util [`mergeLibraryItems`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#mergeLibraryItems) [#5101](https://github.com/excalidraw/excalidraw/pull/5101). +- Expose util [`exportToClipboard`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#exportToClipboard) which allows to copy the scene contents to clipboard as `svg`, `png` or `json` [#5103](https://github.com/excalidraw/excalidraw/pull/5103). - Expose `window.EXCALIDRAW_EXPORT_SOURCE` which you can use to overwrite the `source` field in exported data [#5095](https://github.com/excalidraw/excalidraw/pull/5095). - The `exportToBlob` utility now supports the `exportEmbedScene` option when generating a png image [#5047](https://github.com/excalidraw/excalidraw/pull/5047). - Exported [`restoreLibraryItems`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#restoreLibraryItems) API [#4995](https://github.com/excalidraw/excalidraw/pull/4995). diff --git a/src/packages/excalidraw/README_NEXT.md b/src/packages/excalidraw/README_NEXT.md index ee7c85c2f..13c2cf8a5 100644 --- a/src/packages/excalidraw/README_NEXT.md +++ b/src/packages/excalidraw/README_NEXT.md @@ -436,7 +436,7 @@ This helps to load Excalidraw with `initialData`. It must be an object or a [pro | `elements` | [ExcalidrawElement[]](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78) | The elements with which Excalidraw should be mounted. | | `appState` | [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L42) | The App state with which Excalidraw should be mounted. | | `scrollToContent` | boolean | This attribute implies whether to scroll to the nearest element to center once Excalidraw is mounted. By default, it will not scroll the nearest element to the center. Make sure you pass `initialData.appState.scrollX` and `initialData.appState.scrollY` when `scrollToContent` is false so that scroll positions are retained | -| `libraryItems` | [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L151) | This library items with which Excalidraw should be mounted. | +| `libraryItems` | [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200) | Promise<[LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200)> | This library items with which Excalidraw should be mounted. | | `files` | [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L64) | The files added to the scene. | ```json @@ -514,7 +514,7 @@ You can use this function to update the scene with the sceneData. It accepts the | `appState` | [`ImportedDataState["appState"]`](https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L18) | The `appState` to be updated in the scene. | | `collaborators` |
MapCollaborator>
| The list of collaborators to be updated in the scene. | | `commitToHistory` | `boolean` | Implies if the `history (undo/redo)` should be recorded. Defaults to `false`. | -| `libraryItems` | [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L258) | The `libraryItems` to be update in the scene. | +| `libraryItems` | [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200) | Promise<[LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200)> | ((currentItems: [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200)>) => [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200) | Promise<[LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200)>) | The `libraryItems` to be update in the scene. | ### `addFiles` @@ -960,7 +960,7 @@ If you want to overwrite the source field in the JSON string, you can set `windo
 serializeLibraryAsJSON({
-  libraryItems: LibraryItems[],
+  libraryItems: LibraryItems[],
 
Takes the library items and returns a JSON string. @@ -1072,6 +1072,20 @@ getNonDeletedElements(elements: +mergeLibraryItems(localItems: LibraryItems, otherItems: LibraryItems) => LibraryItems +
+ +This function merges two `LibraryItems` arrays, where unique items from `otherItems` are sorted first in the returned array. + ### Exported constants #### `FONT_FAMILY` diff --git a/src/packages/excalidraw/index.tsx b/src/packages/excalidraw/index.tsx index 8f3a30ad5..ce9b56dd9 100644 --- a/src/packages/excalidraw/index.tsx +++ b/src/packages/excalidraw/index.tsx @@ -198,6 +198,7 @@ export { loadFromBlob, getFreeDrawSvgPath, exportToClipboard, + mergeLibraryItems, } from "../../packages/utils"; export { isLinearElement } from "../../element/typeChecks"; diff --git a/src/packages/utils.ts b/src/packages/utils.ts index 4a1f92d2b..03dcd3d0a 100644 --- a/src/packages/utils.ts +++ b/src/packages/utils.ts @@ -194,3 +194,4 @@ export const exportToClipboard = async ( export { serializeAsJSON, serializeLibraryAsJSON } from "../data/json"; export { loadFromBlob, loadLibraryFromBlob } from "../data/blob"; export { getFreeDrawSvgPath } from "../renderer/renderElement"; +export { mergeLibraryItems } from "../data/library"; diff --git a/src/tests/library.test.tsx b/src/tests/library.test.tsx index 5b8bf2641..3d433940e 100644 --- a/src/tests/library.test.tsx +++ b/src/tests/library.test.tsx @@ -14,12 +14,12 @@ describe("library", () => { }); it("import library via drag&drop", async () => { - expect(await h.app.library.loadLibrary()).toEqual([]); + expect(await h.app.library.getLatestLibrary()).toEqual([]); await API.drop( await API.loadFile("./fixtures/fixture_library.excalidrawlib"), ); await waitFor(async () => { - expect(await h.app.library.loadLibrary()).toEqual([ + expect(await h.app.library.getLatestLibrary()).toEqual([ { status: "unpublished", elements: [expect.objectContaining({ id: "A" })], From 22b2e10ddbb4c83f263d6cbd5077780fa935c823 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 May 2022 14:47:37 +0530 Subject: [PATCH 25/28] chore(deps-dev): bump @babel/plugin-transform-runtime (#5125) Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.16.8 to 7.17.10. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.17.10/packages/babel-plugin-transform-runtime) --- updated-dependencies: - dependency-name: "@babel/plugin-transform-runtime" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/packages/excalidraw/package.json | 2 +- src/packages/excalidraw/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/packages/excalidraw/package.json b/src/packages/excalidraw/package.json index 8ec742f72..5ae76ebe0 100644 --- a/src/packages/excalidraw/package.json +++ b/src/packages/excalidraw/package.json @@ -47,7 +47,7 @@ "@babel/core": "7.17.0", "@babel/plugin-transform-arrow-functions": "7.16.7", "@babel/plugin-transform-async-to-generator": "7.16.0", - "@babel/plugin-transform-runtime": "7.16.8", + "@babel/plugin-transform-runtime": "7.17.10", "@babel/plugin-transform-typescript": "7.16.1", "@babel/preset-env": "7.16.7", "@babel/preset-react": "7.16.7", diff --git a/src/packages/excalidraw/yarn.lock b/src/packages/excalidraw/yarn.lock index 070712f8c..97784140d 100644 --- a/src/packages/excalidraw/yarn.lock +++ b/src/packages/excalidraw/yarn.lock @@ -862,10 +862,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-runtime@7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.8.tgz#3339368701103edae708f0fba9e4bfb70a3e5872" - integrity sha512-6Kg2XHPFnIarNweZxmzbgYnnWsXxkx9WQUVk2sksBRL80lBC1RAQV3wQagWxdCHiYHqPN+oenwNIuttlYgIbQQ== +"@babel/plugin-transform-runtime@7.17.10": + version "7.17.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.10.tgz#b89d821c55d61b5e3d3c3d1d636d8d5a81040ae1" + integrity sha512-6jrMilUAJhktTr56kACL8LnWC5hx3Lf27BS0R0DSyW/OoJfb/iTHeE96V3b1dgKG3FSFdd/0culnYWMkjcKCig== dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" From 9e6d5fdbcbfaa3a8a2818c0051df4214a57c8271 Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Mon, 2 May 2022 15:15:24 +0530 Subject: [PATCH 26/28] feat: support src collaborators (#5114) * feat: support avatarURLfor collaborators * fix * better avatars :) * use position fixed for tooltips so it renders correctly when offsets updated * update docs * Update src/excalidraw-app/collab/CollabWrapper.tsx * rename avatarUrl to src --- src/actions/actionNavigate.tsx | 9 ++--- src/components/Avatar.scss | 6 +++ src/components/Avatar.tsx | 28 +++++++++----- src/components/Tooltip.scss | 2 +- src/packages/excalidraw/CHANGELOG.md | 1 + src/packages/excalidraw/README_NEXT.md | 2 +- src/packages/excalidraw/example/App.js | 36 +++++++++++++++++- .../excalidraw/example/public/doremon.png | Bin 0 -> 201946 bytes .../excalidraw/example/public/pika.jpeg | Bin 0 -> 6250 bytes src/types.ts | 3 ++ 10 files changed, 69 insertions(+), 18 deletions(-) create mode 100644 src/packages/excalidraw/example/public/doremon.png create mode 100644 src/packages/excalidraw/example/public/pika.jpeg diff --git a/src/actions/actionNavigate.tsx b/src/actions/actionNavigate.tsx index 453fd5271..6a13ef3ad 100644 --- a/src/actions/actionNavigate.tsx +++ b/src/actions/actionNavigate.tsx @@ -1,4 +1,4 @@ -import { getClientColors, getClientInitials } from "../clients"; +import { getClientColors } from "../clients"; import { Avatar } from "../components/Avatar"; import { centerScrollOn } from "../scene/scroll"; import { Collaborator } from "../types"; @@ -43,16 +43,15 @@ export const actionGoToCollaborator = register({ } const { background, stroke } = getClientColors(clientId, appState); - const shortName = getClientInitials(collaborator.username); return ( updateData(collaborator.pointer)} - > - {shortName} - + name={collaborator.username || ""} + src={collaborator.src} + /> ); }, }); diff --git a/src/components/Avatar.scss b/src/components/Avatar.scss index d077d916b..d3f8c8bd3 100644 --- a/src/components/Avatar.scss +++ b/src/components/Avatar.scss @@ -12,5 +12,11 @@ cursor: pointer; font-size: 0.8rem; font-weight: 500; + + &-img { + width: 100%; + height: 100%; + border-radius: 100%; + } } } diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx index 2b8513707..9b2c8b71d 100644 --- a/src/components/Avatar.tsx +++ b/src/components/Avatar.tsx @@ -1,20 +1,28 @@ import "./Avatar.scss"; import React from "react"; +import { getClientInitials } from "../clients"; type AvatarProps = { - children: string; onClick: (e: React.MouseEvent) => void; color: string; border: string; + name: string; + src?: string; }; -export const Avatar = ({ children, color, border, onClick }: AvatarProps) => ( -
- {children} -
-); +export const Avatar = ({ color, border, onClick, name, src }: AvatarProps) => { + const shortName = getClientInitials(name); + const style = src + ? undefined + : { background: color, border: `1px solid ${border}` }; + return ( +
+ {src ? ( + {shortName} + ) : ( + shortName + )} +
+ ); +}; diff --git a/src/components/Tooltip.scss b/src/components/Tooltip.scss index e40f81e61..bb2b2f72e 100644 --- a/src/components/Tooltip.scss +++ b/src/components/Tooltip.scss @@ -2,7 +2,7 @@ // container in body where the actual tooltip is appended to .excalidraw-tooltip { - position: absolute; + position: fixed; z-index: 1000; padding: 8px; diff --git a/src/packages/excalidraw/CHANGELOG.md b/src/packages/excalidraw/CHANGELOG.md index 3c18aa282..3a52dbf70 100644 --- a/src/packages/excalidraw/CHANGELOG.md +++ b/src/packages/excalidraw/CHANGELOG.md @@ -17,6 +17,7 @@ Please add the latest change on the top under the correct section. #### Features +- Support [`src`](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L50) for collaborators. Now onwards host can pass `src` to render the customized avatar for collaborators [#5114](https://github.com/excalidraw/excalidraw/pull/5114). - Support `libraryItems` argument in `initialData.libraryItems` and `updateScene({ libraryItems })` to be a Promise resolving to `LibraryItems`, and support functional update of `libraryItems` in [`updateScene({ libraryItems })`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#updateScene). [#5101](https://github.com/excalidraw/excalidraw/pull/5101). - Expose util [`mergeLibraryItems`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#mergeLibraryItems) [#5101](https://github.com/excalidraw/excalidraw/pull/5101). - Expose util [`exportToClipboard`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#exportToClipboard) which allows to copy the scene contents to clipboard as `svg`, `png` or `json` [#5103](https://github.com/excalidraw/excalidraw/pull/5103). diff --git a/src/packages/excalidraw/README_NEXT.md b/src/packages/excalidraw/README_NEXT.md index 13c2cf8a5..f82ca5c8a 100644 --- a/src/packages/excalidraw/README_NEXT.md +++ b/src/packages/excalidraw/README_NEXT.md @@ -512,7 +512,7 @@ You can use this function to update the scene with the sceneData. It accepts the | --- | --- | --- | | `elements` | [`ImportedDataState["elements"]`](https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L17) | The `elements` to be updated in the scene | | `appState` | [`ImportedDataState["appState"]`](https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L18) | The `appState` to be updated in the scene. | -| `collaborators` |
MapCollaborator>
| The list of collaborators to be updated in the scene. | +| `collaborators` |
MapCollaborator>
| The list of collaborators to be updated in the scene. | | `commitToHistory` | `boolean` | Implies if the `history (undo/redo)` should be recorded. Defaults to `false`. | | `libraryItems` | [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200) | Promise<[LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200)> | ((currentItems: [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200)>) => [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200) | Promise<[LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200)>) | The `libraryItems` to be update in the scene. | diff --git a/src/packages/excalidraw/example/App.js b/src/packages/excalidraw/example/App.js index 49af956c8..34780948b 100644 --- a/src/packages/excalidraw/example/App.js +++ b/src/packages/excalidraw/example/App.js @@ -31,7 +31,10 @@ const resolvablePromise = () => { const renderTopRightUI = () => { return ( - @@ -58,6 +61,7 @@ export default function App() { const [exportWithDarkMode, setExportWithDarkMode] = useState(false); const [exportEmbedScene, setExportEmbedScene] = useState(false); const [theme, setTheme] = useState("light"); + const [isCollaborating, setIsCollaborating] = useState(false); const initialStatePromiseRef = useRef({ promise: null }); if (!initialStatePromiseRef.current.promise) { @@ -228,6 +232,36 @@ export default function App() { /> Switch to Dark Theme +