diff --git a/.eslintrc.json b/.eslintrc.json index 095543a85..8263b08a9 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,6 +1,21 @@ { "extends": ["@excalidraw/eslint-config", "react-app"], "rules": { + "import/order": [ + "warn", + { + "groups": ["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"], + "pathGroups": [ + { + "pattern": "@excalidraw/**", + "group": "external", + "position": "after" + } + ], + "newlines-between": "always-and-inside-groups", + "warnOnUnassignedImports": true + } + ], "import/no-anonymous-default-export": "off", "no-restricted-globals": "off", "@typescript-eslint/consistent-type-imports": [ diff --git a/dev-docs/docs/@excalidraw/excalidraw/development.mdx b/dev-docs/docs/@excalidraw/excalidraw/development.mdx index 52ec484aa..60700758f 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/development.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/development.mdx @@ -24,7 +24,7 @@ To start the example app using the `@excalidraw/excalidraw` package, follow the [http://localhost:3001](http://localhost:3001) will open in your default browser. - This is the same example as the [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/mrazator/release-v18/examples/with-script-in-browser) example. + This is the same example as the [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/master/examples/with-script-in-browser) example. ## Releasing diff --git a/dev-docs/docs/@excalidraw/excalidraw/installation.mdx b/dev-docs/docs/@excalidraw/excalidraw/installation.mdx index 2ff6c2d2d..bcab22990 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/installation.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/installation.mdx @@ -52,4 +52,4 @@ Excalidraw takes _100%_ of `width` and `height` of the containing block so make ## Demo -Go to [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/mrazator/release-v18/examples/with-script-in-browser) example. +Go to [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/master/examples/with-script-in-browser) example. diff --git a/dev-docs/docs/@excalidraw/excalidraw/integration.mdx b/dev-docs/docs/@excalidraw/excalidraw/integration.mdx index 62bbbcca5..117877b75 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/integration.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/integration.mdx @@ -131,7 +131,7 @@ If you are using `pages router` then importing the wrapper dynamically would wor {/* Link should be updated to point to the latest! */} Here is a [source code](https://github.com/excalidraw/excalidraw/tree/master/examples/with-nextjs) for the example with app and pages router. You you can try it out [here](https://excalidraw-package-example-with-nextjs.vercel.app/). -The `types` are available at `@excalidraw/excalidraw/types`, check [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/mrazator/release-v18/examples/with-script-in-browser) example for details. +The `types` are available at `@excalidraw/excalidraw/types`, check [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/master/examples/with-script-in-browser) example for details. ### Preact @@ -206,7 +206,7 @@ import TabItem from "@theme/TabItem"; ```js showLineNumbers // See https://www.npmjs.com/package/@excalidraw/excalidraw documentation. -import * as ExcalidrawLib from 'https://esm.sh/@excalidraw/excalidraw@0.18.0-rc.1/dist/dev/index.js?external=react,react-dom'; +import * as ExcalidrawLib from 'https://esm.sh/@excalidraw/excalidraw@0.18.0/dist/dev/index.js?external=react,react-dom'; import React from "https://esm.sh/react@19.0.0"; import ReactDOM from "https://esm.sh/react-dom@19.0.0" @@ -235,4 +235,4 @@ root.render(React.createElement(App)); -You can try it out [here](https://jsfiddle.net/64y130L8/1/). +You can try it out [here](https://jsfiddle.net/vfn6dm14/3/). diff --git a/dev-docs/package.json b/dev-docs/package.json index 8cbd6d232..1577df9b9 100644 --- a/dev-docs/package.json +++ b/dev-docs/package.json @@ -18,7 +18,7 @@ "@docusaurus/core": "2.2.0", "@docusaurus/preset-classic": "2.2.0", "@docusaurus/theme-live-codeblock": "2.2.0", - "@excalidraw/excalidraw": "0.18.0-rc.5", + "@excalidraw/excalidraw": "0.18.0", "@mdx-js/react": "^1.6.22", "clsx": "^1.2.1", "docusaurus-plugin-sass": "0.2.3", diff --git a/dev-docs/src/components/Homepage/index.js b/dev-docs/src/components/Homepage/index.js index e350e03a2..3c1c25f4f 100644 --- a/dev-docs/src/components/Homepage/index.js +++ b/dev-docs/src/components/Homepage/index.js @@ -1,5 +1,6 @@ -import React from "react"; import clsx from "clsx"; +import React from "react"; + import styles from "./styles.module.css"; const FeatureList = [ diff --git a/dev-docs/src/components/Homepage/index.tsx b/dev-docs/src/components/Homepage/index.tsx index ee86e9195..613eaa556 100644 --- a/dev-docs/src/components/Homepage/index.tsx +++ b/dev-docs/src/components/Homepage/index.tsx @@ -1,5 +1,6 @@ -import React from "react"; import clsx from "clsx"; +import React from "react"; + import styles from "./styles.module.css"; type FeatureItem = { diff --git a/dev-docs/src/pages/index.tsx b/dev-docs/src/pages/index.tsx index f35c2e4a7..39b66bb79 100644 --- a/dev-docs/src/pages/index.tsx +++ b/dev-docs/src/pages/index.tsx @@ -1,10 +1,11 @@ -import React from "react"; -import clsx from "clsx"; -import Layout from "@theme/Layout"; import Link from "@docusaurus/Link"; import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; -import styles from "./index.module.css"; import HomepageFeatures from "@site/src/components/Homepage"; +import Layout from "@theme/Layout"; +import clsx from "clsx"; +import React from "react"; + +import styles from "./index.module.css"; function HomepageHeader() { const { siteConfig } = useDocusaurusContext(); diff --git a/dev-docs/src/theme/MDXComponents.js b/dev-docs/src/theme/MDXComponents.js index 35234301f..97ff4d054 100644 --- a/dev-docs/src/theme/MDXComponents.js +++ b/dev-docs/src/theme/MDXComponents.js @@ -1,6 +1,6 @@ // Import the original mapper -import MDXComponents from "@theme-original/MDXComponents"; import Highlight from "@site/src/components/Highlight"; +import MDXComponents from "@theme-original/MDXComponents"; export default { // Re-use the default mapping diff --git a/dev-docs/src/theme/ReactLiveScope/index.js b/dev-docs/src/theme/ReactLiveScope/index.js index 4fa715f46..ca5a902e8 100644 --- a/dev-docs/src/theme/ReactLiveScope/index.js +++ b/dev-docs/src/theme/ReactLiveScope/index.js @@ -12,7 +12,7 @@ if (ExecutionEnvironment.canUseDOM) { const Excalidraw = React.forwardRef((props, ref) => { if (!window.EXCALIDRAW_ASSET_PATH) { window.EXCALIDRAW_ASSET_PATH = - "https://esm.sh/@excalidraw/excalidraw@0.18.0-rc.5/dist/prod/"; + "https://esm.sh/@excalidraw/excalidraw@0.18.0/dist/prod/"; } const { colorMode } = useColorMode(); diff --git a/dev-docs/yarn.lock b/dev-docs/yarn.lock index 6e54d978b..306c17f2a 100644 --- a/dev-docs/yarn.lock +++ b/dev-docs/yarn.lock @@ -1735,16 +1735,16 @@ url-loader "^4.1.1" webpack "^5.73.0" -"@excalidraw/excalidraw@0.18.0-rc.5": - version "0.18.0-rc.5" - resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.18.0-rc.5.tgz#c55598e01808693702251322e59bf9dba931b6e0" - integrity sha512-f6Z6cWlx+FWl1nxCu5F6OdKm9ooV/FPjndjIfFhGLVyERKATXhuNwZUHWwqsEW+SIGmiPG2515NG9KIOhjGd5g== +"@excalidraw/excalidraw@0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.18.0.tgz#9f818e2df80a8735af54f8cc21da67997785532f" + integrity sha512-QkIiS+5qdy8lmDWTKsuy0sK/fen/LRDtbhm2lc2xcFcqhv2/zdg95bYnl+wnwwXGHo7kEmP65BSiMHE7PJ3Zpw== dependencies: "@braintree/sanitize-url" "6.0.2" "@excalidraw/laser-pointer" "1.3.1" "@excalidraw/mermaid-to-excalidraw" "1.1.2" "@excalidraw/random-username" "1.1.0" - "@radix-ui/react-popover" "1.0.3" + "@radix-ui/react-popover" "1.1.6" "@radix-ui/react-tabs" "1.0.2" browser-fs-access "0.29.1" canvas-roundrect-polyfill "0.0.1" @@ -1796,25 +1796,32 @@ resolved "https://registry.yarnpkg.com/@excalidraw/random-username/-/random-username-1.1.0.tgz#6f388d6a9708cf655b8c9c6aa3fa569ee71ecf0f" integrity sha512-nULYsQxkWHnbmHvcs+efMkJ4/9TtvNyFeLyHdeGxW0zHs6P+jYVqcRff9A6Vq9w9JXeDRnRh2VKvTtS19GW2qA== -"@floating-ui/core@^0.7.3": - version "0.7.3" - resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.7.3.tgz#d274116678ffae87f6b60e90f88cc4083eefab86" - integrity sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg== - -"@floating-ui/dom@^0.5.3": - version "0.5.4" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.5.4.tgz#4eae73f78bcd4bd553ae2ade30e6f1f9c73fe3f1" - integrity sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg== +"@floating-ui/core@^1.6.0": + version "1.6.9" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.9.tgz#64d1da251433019dafa091de9b2886ff35ec14e6" + integrity sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw== dependencies: - "@floating-ui/core" "^0.7.3" + "@floating-ui/utils" "^0.2.9" -"@floating-ui/react-dom@0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.7.2.tgz#0bf4ceccb777a140fc535c87eb5d6241c8e89864" - integrity sha512-1T0sJcpHgX/u4I1OzIEhlcrvkUN8ln39nz7fMoE/2HDHrPiMFoOGR7++GYyfUmIQHkkrTinaeQsO3XWubjSvGg== +"@floating-ui/dom@^1.0.0": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.13.tgz#a8a938532aea27a95121ec16e667a7cbe8c59e34" + integrity sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w== dependencies: - "@floating-ui/dom" "^0.5.3" - use-isomorphic-layout-effect "^1.1.1" + "@floating-ui/core" "^1.6.0" + "@floating-ui/utils" "^0.2.9" + +"@floating-ui/react-dom@^2.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31" + integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A== + dependencies: + "@floating-ui/dom" "^1.0.0" + +"@floating-ui/utils@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429" + integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg== "@hapi/hoek@^9.0.0": version "9.3.0" @@ -1982,13 +1989,17 @@ dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-arrow@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.1.tgz#5246adf79e97f89e819af68da51ddcf349ecf1c4" - integrity sha512-1yientwXqXcErDHEv8av9ZVNEBldH8L9scVR3is20lL+jOCfcJyMFZFEY5cgIrgexsq1qggSXqiEL/d/4f+QXA== +"@radix-ui/primitive@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.1.tgz#fc169732d755c7fbad33ba8d0cd7fd10c90dc8e3" + integrity sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA== + +"@radix-ui/react-arrow@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.2.tgz#30c0d574d7bb10eed55cd7007b92d38b03c6b2ab" + integrity sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-primitive" "2.0.2" "@radix-ui/react-collection@1.0.1": version "1.0.1" @@ -2008,6 +2019,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-compose-refs@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz#6f766faa975f8738269ebb8a23bad4f5a8d2faec" + integrity sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw== + "@radix-ui/react-context@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.0.tgz#f38e30c5859a9fb5e9aa9a9da452ee3ed9e0aee0" @@ -2015,6 +2031,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-context@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a" + integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q== + "@radix-ui/react-direction@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.0.0.tgz#a2e0b552352459ecf96342c79949dd833c1e6e45" @@ -2022,34 +2043,30 @@ dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-dismissable-layer@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.2.tgz#f04d1061bddf00b1ca304148516b9ddc62e45fb2" - integrity sha512-WjJzMrTWROozDqLB0uRWYvj4UuXsM/2L19EmQ3Au+IJWqwvwq9Bwd+P8ivo0Deg9JDPArR1I6MbWNi1CmXsskg== +"@radix-ui/react-dismissable-layer@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz#96dde2be078c694a621e55e047406c58cd5fe774" + integrity sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.0" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-use-callback-ref" "1.0.0" - "@radix-ui/react-use-escape-keydown" "1.0.2" + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-escape-keydown" "1.1.0" -"@radix-ui/react-focus-guards@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.0.tgz#339c1c69c41628c1a5e655f15f7020bf11aa01fa" - integrity sha512-UagjDk4ijOAnGu4WMUPj9ahi7/zJJqNZ9ZAiGPp7waUWJO0O1aWXi/udPphI0IUjvrhBsZJGSN66dR2dsueLWQ== - dependencies: - "@babel/runtime" "^7.13.10" +"@radix-ui/react-focus-guards@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe" + integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg== -"@radix-ui/react-focus-scope@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.1.tgz#faea8c25f537c5a5c38c50914b63722db0e7f951" - integrity sha512-Ej2MQTit8IWJiS2uuujGUmxXjF/y5xZptIIQnyd2JHLwtV0R2j9NRVoRj/1j/gJ7e3REdaBw4Hjf4a1ImhkZcQ== +"@radix-ui/react-focus-scope@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz#c0a4519cd95c772606a82fc5b96226cd7fdd2602" + integrity sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-id@1.0.0": version "1.0.0" @@ -2059,52 +2076,57 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-layout-effect" "1.0.0" -"@radix-ui/react-popover@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.0.3.tgz#65ae2ee1fca2d7fd750308549eb8e0857c6160fe" - integrity sha512-YwedSukfWsyJs3/yP3yXUq44k4/JBe3jqU63Z8v2i19qZZ3dsx32oma17ztgclWPNuqp3A+Xa9UiDlZHyVX8Vg== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.0" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-context" "1.0.0" - "@radix-ui/react-dismissable-layer" "1.0.2" - "@radix-ui/react-focus-guards" "1.0.0" - "@radix-ui/react-focus-scope" "1.0.1" - "@radix-ui/react-id" "1.0.0" - "@radix-ui/react-popper" "1.1.0" - "@radix-ui/react-portal" "1.0.1" - "@radix-ui/react-presence" "1.0.0" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-slot" "1.0.1" - "@radix-ui/react-use-controllable-state" "1.0.0" - aria-hidden "^1.1.1" - react-remove-scroll "2.5.5" - -"@radix-ui/react-popper@1.1.0": +"@radix-ui/react-id@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.0.tgz#2be7e4c0cd4581f54277ca33a981c9037d2a8e60" - integrity sha512-07U7jpI0dZcLRAxT7L9qs6HecSoPhDSJybF7mEGHJDBDv+ZoGCvIlva0s+WxMXwJEav+ckX3hAlXBtnHmuvlCQ== + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" + integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== dependencies: - "@babel/runtime" "^7.13.10" - "@floating-ui/react-dom" "0.7.2" - "@radix-ui/react-arrow" "1.0.1" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-context" "1.0.0" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-use-callback-ref" "1.0.0" - "@radix-ui/react-use-layout-effect" "1.0.0" - "@radix-ui/react-use-rect" "1.0.0" - "@radix-ui/react-use-size" "1.0.0" - "@radix-ui/rect" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.1.0" -"@radix-ui/react-portal@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.1.tgz#169c5a50719c2bb0079cf4c91a27aa6d37e5dd33" - integrity sha512-NY2vUWI5WENgAT1nfC6JS7RU5xRYBfjZVLq0HmgEN1Ezy3rk/UruMV4+Rd0F40PEaFC5SrLS1ixYvcYIQrb4Ig== +"@radix-ui/react-popover@1.1.6": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.1.6.tgz#699634dbc7899429f657bb590d71fb3ca0904087" + integrity sha512-NQouW0x4/GnkFJ/pRqsIS3rM/k97VzKnVb2jB7Gq7VEGPy5g7uNV1ykySFt7eWSp3i2uSGFwaJcvIRJBAHmmFg== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-focus-guards" "1.1.1" + "@radix-ui/react-focus-scope" "1.1.2" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.2" + "@radix-ui/react-portal" "1.1.4" + "@radix-ui/react-presence" "1.1.2" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-use-controllable-state" "1.1.0" + aria-hidden "^1.2.4" + react-remove-scroll "^2.6.3" + +"@radix-ui/react-popper@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.2.tgz#d2e1ee5a9b24419c5936a1b7f6f472b7b412b029" + integrity sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA== + dependencies: + "@floating-ui/react-dom" "^2.0.0" + "@radix-ui/react-arrow" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-rect" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + "@radix-ui/rect" "1.1.0" + +"@radix-ui/react-portal@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.4.tgz#ff5401ff63c8a825c46eea96d3aef66074b8c0c8" + integrity sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA== + dependencies: + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-layout-effect" "1.1.0" "@radix-ui/react-presence@1.0.0": version "1.0.0" @@ -2115,6 +2137,14 @@ "@radix-ui/react-compose-refs" "1.0.0" "@radix-ui/react-use-layout-effect" "1.0.0" +"@radix-ui/react-presence@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.2.tgz#bb764ed8a9118b7ec4512da5ece306ded8703cdc" + integrity sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg== + dependencies: + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-primitive@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.1.tgz#c1ebcce283dd2f02e4fbefdaa49d1cb13dbc990a" @@ -2123,6 +2153,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-slot" "1.0.1" +"@radix-ui/react-primitive@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz#ac8b7854d87b0d7af388d058268d9a7eb64ca8ef" + integrity sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w== + dependencies: + "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-roving-focus@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.2.tgz#d8ac2e3b8006697bdfc2b0eb06bef7e15b6245de" @@ -2147,6 +2184,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-compose-refs" "1.0.0" +"@radix-ui/react-slot@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.2.tgz#daffff7b2bfe99ade63b5168407680b93c00e1c6" + integrity sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ== + dependencies: + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-tabs@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.0.2.tgz#8f5ec73ca41b151a413bdd6e00553408ff34ce07" @@ -2169,6 +2213,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-callback-ref@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1" + integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw== + "@radix-ui/react-use-controllable-state@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.0.tgz#a64deaafbbc52d5d407afaa22d493d687c538b7f" @@ -2177,13 +2226,19 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-callback-ref" "1.0.0" -"@radix-ui/react-use-escape-keydown@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.2.tgz#09ab6455ab240b4f0a61faf06d4e5132c4d639f6" - integrity sha512-DXGim3x74WgUv+iMNCF+cAo8xUHHeqvjx8zs7trKf+FkQKPQXLk2sX7Gx1ysH7Q76xCpZuxIJE7HLPxRE+Q+GA== +"@radix-ui/react-use-controllable-state@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0" + integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + +"@radix-ui/react-use-escape-keydown@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754" + integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-layout-effect@1.0.0": version "1.0.0" @@ -2192,28 +2247,29 @@ dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-use-rect@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.0.tgz#b040cc88a4906b78696cd3a32b075ed5b1423b3e" - integrity sha512-TB7pID8NRMEHxb/qQJpvSt3hQU4sqNPM1VCTjTRjEOa7cEop/QMuq8S6fb/5Tsz64kqSvB9WnwsDHtjnrM9qew== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/rect" "1.0.0" +"@radix-ui/react-use-layout-effect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" + integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== -"@radix-ui/react-use-size@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.0.0.tgz#a0b455ac826749419f6354dc733e2ca465054771" - integrity sha512-imZ3aYcoYCKhhgNpkNDh/aTiU05qw9hX+HHI1QDBTyIlcFjgeFlKKySNGMwTp7nYFLQg/j0VA2FmCY4WPDDHMg== +"@radix-ui/react-use-rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88" + integrity sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-layout-effect" "1.0.0" + "@radix-ui/rect" "1.1.0" -"@radix-ui/rect@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.0.tgz#0dc8e6a829ea2828d53cbc94b81793ba6383bf3c" - integrity sha512-d0O68AYy/9oeEy1DdC07bz1/ZXX+DqCskRd3i4JzLSTXwefzaepQrKjXC7aNM8lTHjFLDO0pDgaEiQ7jEk+HVg== +"@radix-ui/react-use-size@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b" + integrity sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw== dependencies: - "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438" + integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg== "@sideway/address@^4.1.3": version "4.1.4" @@ -2952,7 +3008,7 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -aria-hidden@^1.1.1: +aria-hidden@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522" integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A== @@ -7483,7 +7539,7 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1: "@types/react" "*" prop-types "^15.6.2" -react-remove-scroll-bar@^2.3.3: +react-remove-scroll-bar@^2.3.7: version "2.3.8" resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== @@ -7491,16 +7547,16 @@ react-remove-scroll-bar@^2.3.3: react-style-singleton "^2.2.2" tslib "^2.0.0" -react-remove-scroll@2.5.5: - version "2.5.5" - resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77" - integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw== +react-remove-scroll@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz#df02cde56d5f2731e058531f8ffd7f9adec91ac2" + integrity sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ== dependencies: - react-remove-scroll-bar "^2.3.3" - react-style-singleton "^2.2.1" + react-remove-scroll-bar "^2.3.7" + react-style-singleton "^2.2.3" tslib "^2.1.0" - use-callback-ref "^1.3.0" - use-sidecar "^1.1.2" + use-callback-ref "^1.3.3" + use-sidecar "^1.1.3" react-router-config@^5.1.1: version "5.1.1" @@ -7543,7 +7599,7 @@ react-simple-code-editor@^0.10.0: resolved "https://registry.yarnpkg.com/react-simple-code-editor/-/react-simple-code-editor-0.10.0.tgz#73e7ac550a928069715482aeb33ccba36efe2373" integrity sha512-bL5W5mAxSW6+cLwqqVWY47Silqgy2DKDTR4hDBrLrUqC5BXc29YVx17l2IZk5v36VcDEq1Bszu2oHm1qBwKqBA== -react-style-singleton@^2.2.1, react-style-singleton@^2.2.2: +react-style-singleton@^2.2.2, react-style-singleton@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388" integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ== @@ -8805,7 +8861,7 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" -use-callback-ref@^1.3.0: +use-callback-ref@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== @@ -8829,7 +8885,7 @@ use-latest@^1.2.1: dependencies: use-isomorphic-layout-effect "^1.1.1" -use-sidecar@^1.1.2: +use-sidecar@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb" integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ== diff --git a/examples/with-nextjs/src/app/page.tsx b/examples/with-nextjs/src/app/page.tsx index 191aca120..e23255237 100644 --- a/examples/with-nextjs/src/app/page.tsx +++ b/examples/with-nextjs/src/app/page.tsx @@ -1,5 +1,6 @@ import dynamic from "next/dynamic"; import Script from "next/script"; + import "../common.scss"; // Since client components get prerenderd on server as well hence importing the excalidraw stuff dynamically diff --git a/examples/with-nextjs/src/excalidrawWrapper.tsx b/examples/with-nextjs/src/excalidrawWrapper.tsx index b4c45fa7d..fab4df651 100644 --- a/examples/with-nextjs/src/excalidrawWrapper.tsx +++ b/examples/with-nextjs/src/excalidrawWrapper.tsx @@ -1,10 +1,11 @@ "use client"; import * as excalidrawLib from "@excalidraw/excalidraw"; import { Excalidraw } from "@excalidraw/excalidraw"; -import App from "../../with-script-in-browser/components/ExampleApp"; import "@excalidraw/excalidraw/index.css"; +import App from "../../with-script-in-browser/components/ExampleApp"; + const ExcalidrawWrapper: React.FC = () => { return ( <> diff --git a/examples/with-nextjs/src/pages/excalidraw-in-pages.tsx b/examples/with-nextjs/src/pages/excalidraw-in-pages.tsx index 527a346b9..116bb96ce 100644 --- a/examples/with-nextjs/src/pages/excalidraw-in-pages.tsx +++ b/examples/with-nextjs/src/pages/excalidraw-in-pages.tsx @@ -1,4 +1,5 @@ import dynamic from "next/dynamic"; + import "../common.scss"; // Since client components get prerenderd on server as well hence importing the excalidraw stuff dynamically diff --git a/examples/with-script-in-browser/components/CustomFooter.tsx b/examples/with-script-in-browser/components/CustomFooter.tsx index 72fd199f6..a9c902ade 100644 --- a/examples/with-script-in-browser/components/CustomFooter.tsx +++ b/examples/with-script-in-browser/components/CustomFooter.tsx @@ -1,4 +1,5 @@ import React from "react"; + import type * as TExcalidraw from "@excalidraw/excalidraw"; import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types"; diff --git a/examples/with-script-in-browser/components/ExampleApp.tsx b/examples/with-script-in-browser/components/ExampleApp.tsx index 08c8032d5..976004f04 100644 --- a/examples/with-script-in-browser/components/ExampleApp.tsx +++ b/examples/with-script-in-browser/components/ExampleApp.tsx @@ -1,3 +1,4 @@ +import { nanoid } from "nanoid"; import React, { useEffect, useState, @@ -6,13 +7,24 @@ import React, { Children, cloneElement, } from "react"; -import ExampleSidebar from "./sidebar/ExampleSidebar"; import type * as TExcalidraw from "@excalidraw/excalidraw"; +import type { ImportedLibraryData } from "@excalidraw/excalidraw/data/types"; +import type { + NonDeletedExcalidrawElement, + Theme, +} from "@excalidraw/excalidraw/element/types"; +import type { + AppState, + BinaryFileData, + ExcalidrawImperativeAPI, + ExcalidrawInitialDataState, + Gesture, + LibraryItems, + PointerDownState as ExcalidrawPointerDownState, +} from "@excalidraw/excalidraw/types"; -import { nanoid } from "nanoid"; - -import type { ResolvablePromise } from "../utils"; +import initialData from "../initialData"; import { resolvablePromise, distance2d, @@ -23,25 +35,12 @@ import { import CustomFooter from "./CustomFooter"; import MobileFooter from "./MobileFooter"; -import initialData from "../initialData"; - -import type { - AppState, - BinaryFileData, - ExcalidrawImperativeAPI, - ExcalidrawInitialDataState, - Gesture, - LibraryItems, - PointerDownState as ExcalidrawPointerDownState, -} from "@excalidraw/excalidraw/types"; -import type { - NonDeletedExcalidrawElement, - Theme, -} from "@excalidraw/excalidraw/element/types"; -import type { ImportedLibraryData } from "@excalidraw/excalidraw/data/types"; +import ExampleSidebar from "./sidebar/ExampleSidebar"; import "./ExampleApp.scss"; +import type { ResolvablePromise } from "../utils"; + type Comment = { x: number; y: number; diff --git a/examples/with-script-in-browser/components/MobileFooter.tsx b/examples/with-script-in-browser/components/MobileFooter.tsx index c8fc0f113..a6e1fa1b2 100644 --- a/examples/with-script-in-browser/components/MobileFooter.tsx +++ b/examples/with-script-in-browser/components/MobileFooter.tsx @@ -1,7 +1,9 @@ import React from "react"; -import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types"; -import CustomFooter from "./CustomFooter"; + import type * as TExcalidraw from "@excalidraw/excalidraw"; +import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types"; + +import CustomFooter from "./CustomFooter"; const MobileFooter = ({ excalidrawAPI, diff --git a/examples/with-script-in-browser/components/sidebar/ExampleSidebar.tsx b/examples/with-script-in-browser/components/sidebar/ExampleSidebar.tsx index 193913410..88950b34b 100644 --- a/examples/with-script-in-browser/components/sidebar/ExampleSidebar.tsx +++ b/examples/with-script-in-browser/components/sidebar/ExampleSidebar.tsx @@ -1,4 +1,5 @@ import React, { useState } from "react"; + import "./ExampleSidebar.scss"; export default function Sidebar({ children }: { children: React.ReactNode }) { diff --git a/examples/with-script-in-browser/index.html b/examples/with-script-in-browser/index.html index 07c36bde0..dbbc4ca21 100644 --- a/examples/with-script-in-browser/index.html +++ b/examples/with-script-in-browser/index.html @@ -12,9 +12,8 @@ - diff --git a/examples/with-script-in-browser/index.tsx b/examples/with-script-in-browser/index.tsx index 25ad96e37..8f92e7cc5 100644 --- a/examples/with-script-in-browser/index.tsx +++ b/examples/with-script-in-browser/index.tsx @@ -1,10 +1,11 @@ -import App from "./components/ExampleApp"; import React, { StrictMode } from "react"; import { createRoot } from "react-dom/client"; +import "@excalidraw/excalidraw/index.css"; + import type * as TExcalidraw from "@excalidraw/excalidraw"; -import "@excalidraw/excalidraw/index.css"; +import App from "./components/ExampleApp"; declare global { interface Window { diff --git a/examples/with-script-in-browser/package.json b/examples/with-script-in-browser/package.json index 41d31630c..3d61f1a1b 100644 --- a/examples/with-script-in-browser/package.json +++ b/examples/with-script-in-browser/package.json @@ -5,7 +5,7 @@ "dependencies": { "react": "19.0.0", "react-dom": "19.0.0", - "@excalidraw/excalidraw": "0.18.0-rc.5", + "@excalidraw/excalidraw": "*", "browser-fs-access": "0.29.1" }, "devDependencies": { @@ -15,6 +15,7 @@ "scripts": { "start": "vite", "build": "vite build", - "build:preview": "yarn build && vite preview --port 5002" + "build:preview": "yarn build && vite preview --port 5002", + "build:package": "yarn workspace @excalidraw/excalidraw run build:esm" } } diff --git a/examples/with-script-in-browser/utils.ts b/examples/with-script-in-browser/utils.ts index a77b93fb0..285e9652d 100644 --- a/examples/with-script-in-browser/utils.ts +++ b/examples/with-script-in-browser/utils.ts @@ -1,6 +1,6 @@ -import { unstable_batchedUpdates } from "react-dom"; -import { fileOpen as _fileOpen } from "browser-fs-access"; import { MIME_TYPES } from "@excalidraw/excalidraw"; +import { fileOpen as _fileOpen } from "browser-fs-access"; +import { unstable_batchedUpdates } from "react-dom"; type FILE_EXTENSION = Exclude; diff --git a/examples/with-script-in-browser/vercel.json b/examples/with-script-in-browser/vercel.json index 139f31ef0..99a5811c3 100644 --- a/examples/with-script-in-browser/vercel.json +++ b/examples/with-script-in-browser/vercel.json @@ -1,4 +1,5 @@ { "outputDirectory": "dist", - "installCommand": "yarn install" + "installCommand": "yarn install", + "buildCommand": "yarn build:package && yarn build" } diff --git a/excalidraw-app/App.tsx b/excalidraw-app/App.tsx index 2cb6e7715..dc399a7d0 100644 --- a/excalidraw-app/App.tsx +++ b/excalidraw-app/App.tsx @@ -1,24 +1,3 @@ -import polyfill from "@excalidraw/excalidraw/polyfill"; -import { useCallback, useEffect, useRef, useState } from "react"; -import { trackEvent } from "@excalidraw/excalidraw/analytics"; -import { getDefaultAppState } from "@excalidraw/excalidraw/appState"; -import { ErrorDialog } from "@excalidraw/excalidraw/components/ErrorDialog"; -import { TopErrorBoundary } from "./components/TopErrorBoundary"; -import { - APP_NAME, - EVENT, - THEME, - TITLE_TIMEOUT, - VERSION_TIMEOUT, -} from "@excalidraw/excalidraw/constants"; -import { loadFromBlob } from "@excalidraw/excalidraw/data/blob"; -import type { - FileId, - NonDeletedExcalidrawElement, - OrderedExcalidrawElement, -} from "@excalidraw/excalidraw/element/types"; -import { useCallbackRefState } from "@excalidraw/excalidraw/hooks/useCallbackRefState"; -import { t } from "@excalidraw/excalidraw/i18n"; import { Excalidraw, LiveCollaborationTrigger, @@ -26,14 +5,29 @@ import { CaptureUpdateAction, reconcileElements, } from "@excalidraw/excalidraw"; -import type { - AppState, - ExcalidrawImperativeAPI, - BinaryFiles, - ExcalidrawInitialDataState, - UIAppState, -} from "@excalidraw/excalidraw/types"; -import type { ResolvablePromise } from "@excalidraw/excalidraw/utils"; +import { trackEvent } from "@excalidraw/excalidraw/analytics"; +import { getDefaultAppState } from "@excalidraw/excalidraw/appState"; +import { + CommandPalette, + DEFAULT_CATEGORIES, +} from "@excalidraw/excalidraw/components/CommandPalette/CommandPalette"; +import { ErrorDialog } from "@excalidraw/excalidraw/components/ErrorDialog"; +import { OverwriteConfirmDialog } from "@excalidraw/excalidraw/components/OverwriteConfirm/OverwriteConfirm"; +import { openConfirmModal } from "@excalidraw/excalidraw/components/OverwriteConfirm/OverwriteConfirmState"; +import { ShareableLinkDialog } from "@excalidraw/excalidraw/components/ShareableLinkDialog"; +import Trans from "@excalidraw/excalidraw/components/Trans"; +import { + APP_NAME, + EVENT, + THEME, + TITLE_TIMEOUT, + VERSION_TIMEOUT, +} from "@excalidraw/excalidraw/constants"; +import polyfill from "@excalidraw/excalidraw/polyfill"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { loadFromBlob } from "@excalidraw/excalidraw/data/blob"; +import { useCallbackRefState } from "@excalidraw/excalidraw/hooks/useCallbackRefState"; +import { t } from "@excalidraw/excalidraw/i18n"; import { debounce, getVersion, @@ -43,74 +37,6 @@ import { resolvablePromise, isRunningInIframe, } from "@excalidraw/excalidraw/utils"; -import { - FIREBASE_STORAGE_PREFIXES, - isExcalidrawPlusSignedUser, - STORAGE_KEYS, - SYNC_BROWSER_TABS_TIMEOUT, -} from "./app_constants"; -import type { CollabAPI } from "./collab/Collab"; -import Collab, { - collabAPIAtom, - isCollaboratingAtom, - isOfflineAtom, -} from "./collab/Collab"; -import { - exportToBackend, - getCollaborationLinkData, - isCollaborationLink, - loadScene, -} from "./data"; -import { - importFromLocalStorage, - importUsernameFromLocalStorage, -} from "./data/localStorage"; -import CustomStats from "./CustomStats"; -import type { RestoredDataState } from "@excalidraw/excalidraw/data/restore"; -import { restore, restoreAppState } from "@excalidraw/excalidraw/data/restore"; -import { - ExportToExcalidrawPlus, - exportToExcalidrawPlus, -} from "./components/ExportToExcalidrawPlus"; -import { updateStaleImageStatuses } from "./data/FileManager"; -import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; -import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks"; -import { loadFilesFromFirebase } from "./data/firebase"; -import { - LibraryIndexedDBAdapter, - LibraryLocalStorageMigrationAdapter, - LocalData, -} from "./data/LocalData"; -import { isBrowserStorageStateNewer } from "./data/tabSync"; -import clsx from "clsx"; -import { - parseLibraryTokensFromUrl, - useHandleLibrary, -} from "@excalidraw/excalidraw/data/library"; -import { AppMainMenu } from "./components/AppMainMenu"; -import { AppWelcomeScreen } from "./components/AppWelcomeScreen"; -import { AppFooter } from "./components/AppFooter"; -import { - Provider, - useAtom, - useAtomValue, - useAtomWithInitialValue, - appJotaiStore, -} from "./app-jotai"; - -import "./index.scss"; -import type { ResolutionType } from "@excalidraw/excalidraw/utility-types"; -import { ShareableLinkDialog } from "@excalidraw/excalidraw/components/ShareableLinkDialog"; -import { openConfirmModal } from "@excalidraw/excalidraw/components/OverwriteConfirm/OverwriteConfirmState"; -import { OverwriteConfirmDialog } from "@excalidraw/excalidraw/components/OverwriteConfirm/OverwriteConfirm"; -import Trans from "@excalidraw/excalidraw/components/Trans"; -import { ShareDialog, shareDialogStateAtom } from "./share/ShareDialog"; -import CollabError, { collabErrorIndicatorAtom } from "./collab/CollabError"; -import type { RemoteExcalidrawElement } from "@excalidraw/excalidraw/data/reconcile"; -import { - CommandPalette, - DEFAULT_CATEGORIES, -} from "@excalidraw/excalidraw/components/CommandPalette/CommandPalette"; import { GithubIcon, XBrandIcon, @@ -121,6 +47,83 @@ import { share, youtubeIcon, } from "@excalidraw/excalidraw/components/icons"; +import { isElementLink } from "@excalidraw/excalidraw/element/elementLink"; +import { restore, restoreAppState } from "@excalidraw/excalidraw/data/restore"; +import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; +import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks"; +import clsx from "clsx"; +import { + parseLibraryTokensFromUrl, + useHandleLibrary, +} from "@excalidraw/excalidraw/data/library"; + +import type { RemoteExcalidrawElement } from "@excalidraw/excalidraw/data/reconcile"; +import type { RestoredDataState } from "@excalidraw/excalidraw/data/restore"; +import type { + FileId, + NonDeletedExcalidrawElement, + OrderedExcalidrawElement, +} from "@excalidraw/excalidraw/element/types"; +import type { + AppState, + ExcalidrawImperativeAPI, + BinaryFiles, + ExcalidrawInitialDataState, + UIAppState, +} from "@excalidraw/excalidraw/types"; +import type { ResolutionType } from "@excalidraw/excalidraw/utility-types"; +import type { ResolvablePromise } from "@excalidraw/excalidraw/utils"; + +import CustomStats from "./CustomStats"; +import { + Provider, + useAtom, + useAtomValue, + useAtomWithInitialValue, + appJotaiStore, +} from "./app-jotai"; +import { + FIREBASE_STORAGE_PREFIXES, + isExcalidrawPlusSignedUser, + STORAGE_KEYS, + SYNC_BROWSER_TABS_TIMEOUT, +} from "./app_constants"; +import Collab, { + collabAPIAtom, + isCollaboratingAtom, + isOfflineAtom, +} from "./collab/Collab"; +import { AppFooter } from "./components/AppFooter"; +import { AppMainMenu } from "./components/AppMainMenu"; +import { AppWelcomeScreen } from "./components/AppWelcomeScreen"; +import { + ExportToExcalidrawPlus, + exportToExcalidrawPlus, +} from "./components/ExportToExcalidrawPlus"; +import { TopErrorBoundary } from "./components/TopErrorBoundary"; + +import { + exportToBackend, + getCollaborationLinkData, + isCollaborationLink, + loadScene, +} from "./data"; + +import { updateStaleImageStatuses } from "./data/FileManager"; +import { + importFromLocalStorage, + importUsernameFromLocalStorage, +} from "./data/localStorage"; + +import { loadFilesFromFirebase } from "./data/firebase"; +import { + LibraryIndexedDBAdapter, + LibraryLocalStorageMigrationAdapter, + LocalData, +} from "./data/LocalData"; +import { isBrowserStorageStateNewer } from "./data/tabSync"; +import { ShareDialog, shareDialogStateAtom } from "./share/ShareDialog"; +import CollabError, { collabErrorIndicatorAtom } from "./collab/CollabError"; import { useHandleAppTheme } from "./useHandleAppTheme"; import { getPreferredLanguage } from "./app-language/language-detector"; import { useAppLangCode } from "./app-language/language-state"; @@ -131,7 +134,10 @@ import DebugCanvas, { } from "./components/DebugCanvas"; import { AIComponents } from "./components/AI"; import { ExcalidrawPlusIframeExport } from "./ExcalidrawPlusIframeExport"; -import { isElementLink } from "@excalidraw/excalidraw/element/elementLink"; + +import "./index.scss"; + +import type { CollabAPI } from "./collab/Collab"; polyfill(); diff --git a/excalidraw-app/CustomStats.tsx b/excalidraw-app/CustomStats.tsx index 96ca55d67..c57f297fe 100644 --- a/excalidraw-app/CustomStats.tsx +++ b/excalidraw-app/CustomStats.tsx @@ -1,15 +1,17 @@ -import { useEffect, useState } from "react"; +import { Stats } from "@excalidraw/excalidraw"; +import { copyTextToSystemClipboard } from "@excalidraw/excalidraw/clipboard"; +import { DEFAULT_VERSION } from "@excalidraw/excalidraw/constants"; +import { t } from "@excalidraw/excalidraw/i18n"; import { debounce, getVersion, nFormatter } from "@excalidraw/excalidraw/utils"; +import { useEffect, useState } from "react"; + +import type { NonDeletedExcalidrawElement } from "@excalidraw/excalidraw/element/types"; +import type { UIAppState } from "@excalidraw/excalidraw/types"; + import { getElementsStorageSize, getTotalStorageSize, } from "./data/localStorage"; -import { DEFAULT_VERSION } from "@excalidraw/excalidraw/constants"; -import { t } from "@excalidraw/excalidraw/i18n"; -import { copyTextToSystemClipboard } from "@excalidraw/excalidraw/clipboard"; -import type { NonDeletedExcalidrawElement } from "@excalidraw/excalidraw/element/types"; -import type { UIAppState } from "@excalidraw/excalidraw/types"; -import { Stats } from "@excalidraw/excalidraw"; type StorageSizes = { scene: number; total: number }; diff --git a/excalidraw-app/ExcalidrawPlusIframeExport.tsx b/excalidraw-app/ExcalidrawPlusIframeExport.tsx index 1f9cd631c..be046f795 100644 --- a/excalidraw-app/ExcalidrawPlusIframeExport.tsx +++ b/excalidraw-app/ExcalidrawPlusIframeExport.tsx @@ -1,13 +1,15 @@ +import { base64urlToString } from "@excalidraw/excalidraw/data/encode"; +import { ExcalidrawError } from "@excalidraw/excalidraw/errors"; import { useLayoutEffect, useRef } from "react"; -import { STORAGE_KEYS } from "./app_constants"; -import { LocalData } from "./data/LocalData"; + import type { FileId, OrderedExcalidrawElement, } from "@excalidraw/excalidraw/element/types"; import type { AppState, BinaryFileData } from "@excalidraw/excalidraw/types"; -import { ExcalidrawError } from "@excalidraw/excalidraw/errors"; -import { base64urlToString } from "@excalidraw/excalidraw/data/encode"; + +import { STORAGE_KEYS } from "./app_constants"; +import { LocalData } from "./data/LocalData"; const EVENT_REQUEST_SCENE = "REQUEST_SCENE"; diff --git a/excalidraw-app/app-language/LanguageList.tsx b/excalidraw-app/app-language/LanguageList.tsx index 001d4ea17..b4682f353 100644 --- a/excalidraw-app/app-language/LanguageList.tsx +++ b/excalidraw-app/app-language/LanguageList.tsx @@ -1,6 +1,8 @@ -import React from "react"; import { useI18n, languages } from "@excalidraw/excalidraw/i18n"; +import React from "react"; + import { useSetAtom } from "../app-jotai"; + import { appLangCodeAtom } from "./language-state"; export const LanguageList = ({ style }: { style?: React.CSSProperties }) => { diff --git a/excalidraw-app/app-language/language-detector.ts b/excalidraw-app/app-language/language-detector.ts index 52da4908f..535189d0a 100644 --- a/excalidraw-app/app-language/language-detector.ts +++ b/excalidraw-app/app-language/language-detector.ts @@ -1,5 +1,5 @@ -import LanguageDetector from "i18next-browser-languagedetector"; import { defaultLang, languages } from "@excalidraw/excalidraw"; +import LanguageDetector from "i18next-browser-languagedetector"; export const languageDetector = new LanguageDetector(); diff --git a/excalidraw-app/app-language/language-state.ts b/excalidraw-app/app-language/language-state.ts index f491c2215..d9ec90322 100644 --- a/excalidraw-app/app-language/language-state.ts +++ b/excalidraw-app/app-language/language-state.ts @@ -1,5 +1,7 @@ import { useEffect } from "react"; + import { atom, useAtom } from "../app-jotai"; + import { getPreferredLanguage, languageDetector } from "./language-detector"; export const appLangCodeAtom = atom(getPreferredLanguage()); diff --git a/excalidraw-app/collab/Collab.tsx b/excalidraw-app/collab/Collab.tsx index 9a16e0569..0964a7365 100644 --- a/excalidraw-app/collab/Collab.tsx +++ b/excalidraw-app/collab/Collab.tsx @@ -1,21 +1,3 @@ -import throttle from "lodash.throttle"; -import { PureComponent } from "react"; -import type { - BinaryFileData, - ExcalidrawImperativeAPI, - SocketId, - Collaborator, - Gesture, -} from "@excalidraw/excalidraw/types"; -import { ErrorDialog } from "@excalidraw/excalidraw/components/ErrorDialog"; -import { APP_NAME, ENV, EVENT } from "@excalidraw/excalidraw/constants"; -import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; -import type { - ExcalidrawElement, - FileId, - InitializedExcalidrawImageElement, - OrderedExcalidrawElement, -} from "@excalidraw/excalidraw/element/types"; import { CaptureUpdateAction, getSceneVersion, @@ -23,12 +5,53 @@ import { zoomToFitBounds, reconcileElements, } from "@excalidraw/excalidraw"; +import { ErrorDialog } from "@excalidraw/excalidraw/components/ErrorDialog"; +import { APP_NAME, ENV, EVENT } from "@excalidraw/excalidraw/constants"; +import { + IDLE_THRESHOLD, + ACTIVE_THRESHOLD, + UserIdleState, +} from "@excalidraw/excalidraw/constants"; +import { decryptData } from "@excalidraw/excalidraw/data/encryption"; +import { getVisibleSceneBounds } from "@excalidraw/excalidraw/element/bounds"; +import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; +import { + isImageElement, + isInitializedImageElement, +} from "@excalidraw/excalidraw/element/typeChecks"; +import { AbortError } from "@excalidraw/excalidraw/errors"; +import { t } from "@excalidraw/excalidraw/i18n"; +import { withBatchedUpdates } from "@excalidraw/excalidraw/reactUtils"; import { assertNever, preventUnload, resolvablePromise, throttleRAF, } from "@excalidraw/excalidraw/utils"; +import throttle from "lodash.throttle"; +import { PureComponent } from "react"; + +import type { + ReconciledExcalidrawElement, + RemoteExcalidrawElement, +} from "@excalidraw/excalidraw/data/reconcile"; +import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; +import type { + ExcalidrawElement, + FileId, + InitializedExcalidrawImageElement, + OrderedExcalidrawElement, +} from "@excalidraw/excalidraw/element/types"; +import type { + BinaryFileData, + ExcalidrawImperativeAPI, + SocketId, + Collaborator, + Gesture, +} from "@excalidraw/excalidraw/types"; +import type { Mutable, ValueOf } from "@excalidraw/excalidraw/utility-types"; + +import { appJotaiStore, atom } from "../app-jotai"; import { CURSOR_SYNC_TIMEOUT, FILE_UPLOAD_MAX_BYTES, @@ -39,15 +62,17 @@ import { SYNC_FULL_SCENE_INTERVAL_MS, WS_EVENTS, } from "../app_constants"; -import type { - SocketUpdateDataSource, - SyncableExcalidrawElement, -} from "../data"; import { generateCollaborationLinkData, getCollaborationLink, getSyncableElements, } from "../data"; +import { + encodeFilesForUpload, + FileManager, + updateStaleImageStatuses, +} from "../data/FileManager"; +import { LocalData } from "../data/LocalData"; import { isSavedToFirebase, loadFilesFromFirebase, @@ -59,36 +84,15 @@ import { importUsernameFromLocalStorage, saveUsernameToLocalStorage, } from "../data/localStorage"; -import Portal from "./Portal"; -import { t } from "@excalidraw/excalidraw/i18n"; -import { - IDLE_THRESHOLD, - ACTIVE_THRESHOLD, - UserIdleState, -} from "@excalidraw/excalidraw/constants"; -import { - encodeFilesForUpload, - FileManager, - updateStaleImageStatuses, -} from "../data/FileManager"; -import { AbortError } from "@excalidraw/excalidraw/errors"; -import { - isImageElement, - isInitializedImageElement, -} from "@excalidraw/excalidraw/element/typeChecks"; -import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; -import { decryptData } from "@excalidraw/excalidraw/data/encryption"; import { resetBrowserStateVersions } from "../data/tabSync"; -import { LocalData } from "../data/LocalData"; -import { appJotaiStore, atom } from "../app-jotai"; -import type { Mutable, ValueOf } from "@excalidraw/excalidraw/utility-types"; -import { getVisibleSceneBounds } from "@excalidraw/excalidraw/element/bounds"; -import { withBatchedUpdates } from "@excalidraw/excalidraw/reactUtils"; + import { collabErrorIndicatorAtom } from "./CollabError"; +import Portal from "./Portal"; + import type { - ReconciledExcalidrawElement, - RemoteExcalidrawElement, -} from "@excalidraw/excalidraw/data/reconcile"; + SocketUpdateDataSource, + SyncableExcalidrawElement, +} from "../data"; export const collabAPIAtom = atom(null); export const isCollaboratingAtom = atom(false); diff --git a/excalidraw-app/collab/CollabError.tsx b/excalidraw-app/collab/CollabError.tsx index 76828cf1a..eb6f391bc 100644 --- a/excalidraw-app/collab/CollabError.tsx +++ b/excalidraw-app/collab/CollabError.tsx @@ -2,6 +2,7 @@ import { Tooltip } from "@excalidraw/excalidraw/components/Tooltip"; import { warning } from "@excalidraw/excalidraw/components/icons"; import clsx from "clsx"; import { useEffect, useRef, useState } from "react"; + import { atom } from "../app-jotai"; import "./CollabError.scss"; diff --git a/excalidraw-app/collab/Portal.tsx b/excalidraw-app/collab/Portal.tsx index 1788d39f7..037bca314 100644 --- a/excalidraw-app/collab/Portal.tsx +++ b/excalidraw-app/collab/Portal.tsx @@ -1,25 +1,26 @@ +import { CaptureUpdateAction } from "@excalidraw/excalidraw"; +import { trackEvent } from "@excalidraw/excalidraw/analytics"; +import { encryptData } from "@excalidraw/excalidraw/data/encryption"; +import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; +import throttle from "lodash.throttle"; + +import type { UserIdleState } from "@excalidraw/excalidraw/constants"; +import type { OrderedExcalidrawElement } from "@excalidraw/excalidraw/element/types"; +import type { + OnUserFollowedPayload, + SocketId, +} from "@excalidraw/excalidraw/types"; + +import { WS_EVENTS, FILE_UPLOAD_TIMEOUT, WS_SUBTYPES } from "../app_constants"; +import { isSyncableElement } from "../data"; + import type { SocketUpdateData, SocketUpdateDataSource, SyncableExcalidrawElement, } from "../data"; -import { isSyncableElement } from "../data"; - import type { TCollabClass } from "./Collab"; - -import type { OrderedExcalidrawElement } from "@excalidraw/excalidraw/element/types"; -import { WS_EVENTS, FILE_UPLOAD_TIMEOUT, WS_SUBTYPES } from "../app_constants"; -import type { - OnUserFollowedPayload, - SocketId, -} from "@excalidraw/excalidraw/types"; -import type { UserIdleState } from "@excalidraw/excalidraw/constants"; -import { trackEvent } from "@excalidraw/excalidraw/analytics"; -import throttle from "lodash.throttle"; -import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; -import { encryptData } from "@excalidraw/excalidraw/data/encryption"; import type { Socket } from "socket.io-client"; -import { CaptureUpdateAction } from "@excalidraw/excalidraw"; class Portal { collab: TCollabClass; diff --git a/excalidraw-app/components/AI.tsx b/excalidraw-app/components/AI.tsx index fa5d12fa2..c9b6684b3 100644 --- a/excalidraw-app/components/AI.tsx +++ b/excalidraw-app/components/AI.tsx @@ -1,4 +1,3 @@ -import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types"; import { DiagramToCodePlugin, exportToBlob, @@ -9,6 +8,8 @@ import { import { getDataURL } from "@excalidraw/excalidraw/data/blob"; import { safelyParseJSON } from "@excalidraw/excalidraw/utils"; +import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types"; + export const AIComponents = ({ excalidrawAPI, }: { diff --git a/excalidraw-app/components/AppFooter.tsx b/excalidraw-app/components/AppFooter.tsx index e81df7c41..7d42d46bf 100644 --- a/excalidraw-app/components/AppFooter.tsx +++ b/excalidraw-app/components/AppFooter.tsx @@ -1,9 +1,11 @@ -import React from "react"; import { Footer } from "@excalidraw/excalidraw/index"; +import React from "react"; + +import { isExcalidrawPlusSignedUser } from "../app_constants"; + +import { DebugFooter, isVisualDebuggerEnabled } from "./DebugCanvas"; import { EncryptedIcon } from "./EncryptedIcon"; import { ExcalidrawPlusAppLink } from "./ExcalidrawPlusAppLink"; -import { isExcalidrawPlusSignedUser } from "../app_constants"; -import { DebugFooter, isVisualDebuggerEnabled } from "./DebugCanvas"; export const AppFooter = React.memo( ({ onChange }: { onChange: () => void }) => { diff --git a/excalidraw-app/components/AppMainMenu.tsx b/excalidraw-app/components/AppMainMenu.tsx index cb741cf25..996d6912d 100644 --- a/excalidraw-app/components/AppMainMenu.tsx +++ b/excalidraw-app/components/AppMainMenu.tsx @@ -1,13 +1,16 @@ -import React from "react"; import { loginIcon, ExcalLogo, eyeIcon, } from "@excalidraw/excalidraw/components/icons"; -import type { Theme } from "@excalidraw/excalidraw/element/types"; import { MainMenu } from "@excalidraw/excalidraw/index"; -import { isExcalidrawPlusSignedUser } from "../app_constants"; +import React from "react"; + +import type { Theme } from "@excalidraw/excalidraw/element/types"; + import { LanguageList } from "../app-language/LanguageList"; +import { isExcalidrawPlusSignedUser } from "../app_constants"; + import { saveDebugState } from "./DebugCanvas"; export const AppMainMenu: React.FC<{ diff --git a/excalidraw-app/components/AppWelcomeScreen.tsx b/excalidraw-app/components/AppWelcomeScreen.tsx index bdc9859f8..c33de092a 100644 --- a/excalidraw-app/components/AppWelcomeScreen.tsx +++ b/excalidraw-app/components/AppWelcomeScreen.tsx @@ -1,9 +1,10 @@ -import React from "react"; import { loginIcon } from "@excalidraw/excalidraw/components/icons"; +import { POINTER_EVENTS } from "@excalidraw/excalidraw/constants"; import { useI18n } from "@excalidraw/excalidraw/i18n"; import { WelcomeScreen } from "@excalidraw/excalidraw/index"; +import React from "react"; + import { isExcalidrawPlusSignedUser } from "../app_constants"; -import { POINTER_EVENTS } from "@excalidraw/excalidraw/constants"; export const AppWelcomeScreen: React.FC<{ onCollabDialogOpen: () => any; diff --git a/excalidraw-app/components/DebugCanvas.tsx b/excalidraw-app/components/DebugCanvas.tsx index 31898ba57..af1a2b140 100644 --- a/excalidraw-app/components/DebugCanvas.tsx +++ b/excalidraw-app/components/DebugCanvas.tsx @@ -1,24 +1,27 @@ -import { useCallback, useImperativeHandle, useRef } from "react"; -import { type AppState } from "@excalidraw/excalidraw/types"; -import { throttleRAF } from "@excalidraw/excalidraw/utils"; -import { - bootstrapCanvas, - getNormalizedCanvasDimensions, -} from "@excalidraw/excalidraw/renderer/helpers"; -import type { DebugElement } from "@excalidraw/excalidraw/visualdebug"; import { ArrowheadArrowIcon, CloseIcon, TrashIcon, } from "@excalidraw/excalidraw/components/icons"; -import { STORAGE_KEYS } from "../app_constants"; -import type { Curve } from "../../packages/math"; +import { + bootstrapCanvas, + getNormalizedCanvasDimensions, +} from "@excalidraw/excalidraw/renderer/helpers"; +import { type AppState } from "@excalidraw/excalidraw/types"; +import { throttleRAF } from "@excalidraw/excalidraw/utils"; +import { useCallback, useImperativeHandle, useRef } from "react"; + +import type { DebugElement } from "@excalidraw/excalidraw/visualdebug"; + import { isLineSegment, type GlobalPoint, type LineSegment, } from "../../packages/math"; import { isCurve } from "../../packages/math/curve"; +import { STORAGE_KEYS } from "../app_constants"; + +import type { Curve } from "../../packages/math"; const renderLine = ( context: CanvasRenderingContext2D, diff --git a/excalidraw-app/components/EncryptedIcon.tsx b/excalidraw-app/components/EncryptedIcon.tsx index a3a841783..552e7ca82 100644 --- a/excalidraw-app/components/EncryptedIcon.tsx +++ b/excalidraw-app/components/EncryptedIcon.tsx @@ -1,5 +1,5 @@ -import { shield } from "@excalidraw/excalidraw/components/icons"; import { Tooltip } from "@excalidraw/excalidraw/components/Tooltip"; +import { shield } from "@excalidraw/excalidraw/components/icons"; import { useI18n } from "@excalidraw/excalidraw/i18n"; export const EncryptedIcon = () => { diff --git a/excalidraw-app/components/ExportToExcalidrawPlus.tsx b/excalidraw-app/components/ExportToExcalidrawPlus.tsx index 782ecd963..a630f804f 100644 --- a/excalidraw-app/components/ExportToExcalidrawPlus.tsx +++ b/excalidraw-app/components/ExportToExcalidrawPlus.tsx @@ -1,8 +1,20 @@ -import React from "react"; +import { trackEvent } from "@excalidraw/excalidraw/analytics"; import { Card } from "@excalidraw/excalidraw/components/Card"; +import { ExcalidrawLogo } from "@excalidraw/excalidraw/components/ExcalidrawLogo"; import { ToolButton } from "@excalidraw/excalidraw/components/ToolButton"; +import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; +import { + encryptData, + generateEncryptionKey, +} from "@excalidraw/excalidraw/data/encryption"; import { serializeAsJSON } from "@excalidraw/excalidraw/data/json"; -import { loadFirebaseStorage, saveFilesToFirebase } from "../data/firebase"; +import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks"; +import { useI18n } from "@excalidraw/excalidraw/i18n"; +import { getFrame } from "@excalidraw/excalidraw/utils"; +import { uploadBytes, ref } from "firebase/storage"; +import { nanoid } from "nanoid"; +import React from "react"; + import type { FileId, NonDeletedExcalidrawElement, @@ -12,20 +24,10 @@ import type { BinaryFileData, BinaryFiles, } from "@excalidraw/excalidraw/types"; -import { nanoid } from "nanoid"; -import { useI18n } from "@excalidraw/excalidraw/i18n"; -import { - encryptData, - generateEncryptionKey, -} from "@excalidraw/excalidraw/data/encryption"; -import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks"; + import { FILE_UPLOAD_MAX_BYTES } from "../app_constants"; import { encodeFilesForUpload } from "../data/FileManager"; -import { uploadBytes, ref } from "firebase/storage"; -import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; -import { trackEvent } from "@excalidraw/excalidraw/analytics"; -import { getFrame } from "@excalidraw/excalidraw/utils"; -import { ExcalidrawLogo } from "@excalidraw/excalidraw/components/ExcalidrawLogo"; +import { loadFirebaseStorage, saveFilesToFirebase } from "../data/firebase"; export const exportToExcalidrawPlus = async ( elements: readonly NonDeletedExcalidrawElement[], diff --git a/excalidraw-app/components/GitHubCorner.tsx b/excalidraw-app/components/GitHubCorner.tsx index 4d74242d1..b1c17f29e 100644 --- a/excalidraw-app/components/GitHubCorner.tsx +++ b/excalidraw-app/components/GitHubCorner.tsx @@ -1,6 +1,7 @@ +import { THEME } from "@excalidraw/excalidraw/constants"; import oc from "open-color"; import React from "react"; -import { THEME } from "@excalidraw/excalidraw/constants"; + import type { Theme } from "@excalidraw/excalidraw/element/types"; // https://github.com/tholman/github-corners diff --git a/excalidraw-app/components/TopErrorBoundary.tsx b/excalidraw-app/components/TopErrorBoundary.tsx index e7e00be3b..77d9e5f4f 100644 --- a/excalidraw-app/components/TopErrorBoundary.tsx +++ b/excalidraw-app/components/TopErrorBoundary.tsx @@ -1,7 +1,7 @@ -import React from "react"; -import * as Sentry from "@sentry/browser"; -import { t } from "@excalidraw/excalidraw/i18n"; import Trans from "@excalidraw/excalidraw/components/Trans"; +import { t } from "@excalidraw/excalidraw/i18n"; +import * as Sentry from "@sentry/browser"; +import React from "react"; interface TopErrorBoundaryState { hasError: boolean; diff --git a/excalidraw-app/data/FileManager.ts b/excalidraw-app/data/FileManager.ts index f5f4eaca9..93d7ddec8 100644 --- a/excalidraw-app/data/FileManager.ts +++ b/excalidraw-app/data/FileManager.ts @@ -2,13 +2,14 @@ import { CaptureUpdateAction } from "@excalidraw/excalidraw"; import { compressData } from "@excalidraw/excalidraw/data/encode"; import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks"; +import { t } from "@excalidraw/excalidraw/i18n"; + import type { ExcalidrawElement, ExcalidrawImageElement, FileId, InitializedExcalidrawImageElement, } from "@excalidraw/excalidraw/element/types"; -import { t } from "@excalidraw/excalidraw/i18n"; import type { BinaryFileData, BinaryFileMetadata, diff --git a/excalidraw-app/data/LocalData.ts b/excalidraw-app/data/LocalData.ts index 3ab0ad931..6b53cc482 100644 --- a/excalidraw-app/data/LocalData.ts +++ b/excalidraw-app/data/LocalData.ts @@ -10,6 +10,13 @@ * (localStorage, indexedDB). */ +import { clearAppStateForLocalStorage } from "@excalidraw/excalidraw/appState"; +import { + CANVAS_SEARCH_TAB, + DEFAULT_SIDEBAR, +} from "@excalidraw/excalidraw/constants"; +import { clearElementsForLocalStorage } from "@excalidraw/excalidraw/element"; +import { debounce } from "@excalidraw/excalidraw/utils"; import { createStore, entries, @@ -19,14 +26,9 @@ import { setMany, get, } from "idb-keyval"; -import { clearAppStateForLocalStorage } from "@excalidraw/excalidraw/appState"; -import { - CANVAS_SEARCH_TAB, - DEFAULT_SIDEBAR, -} from "@excalidraw/excalidraw/constants"; + import type { LibraryPersistedData } from "@excalidraw/excalidraw/data/library"; import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; -import { clearElementsForLocalStorage } from "@excalidraw/excalidraw/element"; import type { ExcalidrawElement, FileId, @@ -37,8 +39,9 @@ import type { BinaryFiles, } from "@excalidraw/excalidraw/types"; import type { MaybePromise } from "@excalidraw/excalidraw/utility-types"; -import { debounce } from "@excalidraw/excalidraw/utils"; + import { SAVE_TO_LOCAL_STORAGE_TIMEOUT, STORAGE_KEYS } from "../app_constants"; + import { FileManager } from "./FileManager"; import { Locker } from "./Locker"; import { updateBrowserStateVersion } from "./tabSync"; diff --git a/excalidraw-app/data/firebase.ts b/excalidraw-app/data/firebase.ts index a871b4895..66893b513 100644 --- a/excalidraw-app/data/firebase.ts +++ b/excalidraw-app/data/firebase.ts @@ -1,27 +1,12 @@ import { reconcileElements } from "@excalidraw/excalidraw"; -import type { - ExcalidrawElement, - FileId, - OrderedExcalidrawElement, -} from "@excalidraw/excalidraw/element/types"; -import { getSceneVersion } from "@excalidraw/excalidraw/element"; -import type Portal from "../collab/Portal"; -import { restoreElements } from "@excalidraw/excalidraw/data/restore"; -import type { - AppState, - BinaryFileData, - BinaryFileMetadata, - DataURL, -} from "@excalidraw/excalidraw/types"; -import { FILE_CACHE_MAX_AGE_SEC } from "../app_constants"; +import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; import { decompressData } from "@excalidraw/excalidraw/data/encode"; import { encryptData, decryptData, } from "@excalidraw/excalidraw/data/encryption"; -import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; -import type { SyncableExcalidrawElement } from "."; -import { getSyncableElements } from "."; +import { restoreElements } from "@excalidraw/excalidraw/data/restore"; +import { getSceneVersion } from "@excalidraw/excalidraw/element"; import { initializeApp } from "firebase/app"; import { getFirestore, @@ -31,8 +16,27 @@ import { Bytes, } from "firebase/firestore"; import { getStorage, ref, uploadBytes } from "firebase/storage"; -import type { Socket } from "socket.io-client"; + import type { RemoteExcalidrawElement } from "@excalidraw/excalidraw/data/reconcile"; +import type { + ExcalidrawElement, + FileId, + OrderedExcalidrawElement, +} from "@excalidraw/excalidraw/element/types"; +import type { + AppState, + BinaryFileData, + BinaryFileMetadata, + DataURL, +} from "@excalidraw/excalidraw/types"; + +import { FILE_CACHE_MAX_AGE_SEC } from "../app_constants"; + +import { getSyncableElements } from "."; + +import type { SyncableExcalidrawElement } from "."; +import type Portal from "../collab/Portal"; +import type { Socket } from "socket.io-client"; // private // ----------------------------------------------------------------------------- diff --git a/excalidraw-app/data/index.ts b/excalidraw-app/data/index.ts index 6ecb98f77..e8fbc1f4d 100644 --- a/excalidraw-app/data/index.ts +++ b/excalidraw-app/data/index.ts @@ -9,34 +9,38 @@ import { } from "@excalidraw/excalidraw/data/encryption"; import { serializeAsJSON } from "@excalidraw/excalidraw/data/json"; import { restore } from "@excalidraw/excalidraw/data/restore"; -import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; -import type { SceneBounds } from "@excalidraw/excalidraw/element/bounds"; import { isInvisiblySmallElement } from "@excalidraw/excalidraw/element/sizeHelpers"; import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks"; +import { t } from "@excalidraw/excalidraw/i18n"; +import { bytesToHexString } from "@excalidraw/excalidraw/utils"; + +import type { UserIdleState } from "@excalidraw/excalidraw/constants"; +import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; +import type { SceneBounds } from "@excalidraw/excalidraw/element/bounds"; import type { ExcalidrawElement, FileId, OrderedExcalidrawElement, } from "@excalidraw/excalidraw/element/types"; -import { t } from "@excalidraw/excalidraw/i18n"; import type { AppState, BinaryFileData, BinaryFiles, SocketId, } from "@excalidraw/excalidraw/types"; -import type { UserIdleState } from "@excalidraw/excalidraw/constants"; import type { MakeBrand } from "@excalidraw/excalidraw/utility-types"; -import { bytesToHexString } from "@excalidraw/excalidraw/utils"; -import type { WS_SUBTYPES } from "../app_constants"; + import { DELETED_ELEMENT_TIMEOUT, FILE_UPLOAD_MAX_BYTES, ROOM_ID_BYTES, } from "../app_constants"; + import { encodeFilesForUpload } from "./FileManager"; import { saveFilesToFirebase } from "./firebase"; +import type { WS_SUBTYPES } from "../app_constants"; + export type SyncableExcalidrawElement = OrderedExcalidrawElement & MakeBrand<"SyncableExcalidrawElement">; diff --git a/excalidraw-app/data/localStorage.ts b/excalidraw-app/data/localStorage.ts index 640dfdb60..ac1206498 100644 --- a/excalidraw-app/data/localStorage.ts +++ b/excalidraw-app/data/localStorage.ts @@ -1,10 +1,12 @@ -import type { ExcalidrawElement } from "@excalidraw/excalidraw/element/types"; -import type { AppState } from "@excalidraw/excalidraw/types"; import { clearAppStateForLocalStorage, getDefaultAppState, } from "@excalidraw/excalidraw/appState"; import { clearElementsForLocalStorage } from "@excalidraw/excalidraw/element"; + +import type { ExcalidrawElement } from "@excalidraw/excalidraw/element/types"; +import type { AppState } from "@excalidraw/excalidraw/types"; + import { STORAGE_KEYS } from "../app_constants"; export const saveUsernameToLocalStorage = (username: string) => { diff --git a/excalidraw-app/index.tsx b/excalidraw-app/index.tsx index a28bd9e49..98c902e36 100644 --- a/excalidraw-app/index.tsx +++ b/excalidraw-app/index.tsx @@ -1,9 +1,11 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; -import ExcalidrawApp from "./App"; import { registerSW } from "virtual:pwa-register"; import "../excalidraw-app/sentry"; + +import ExcalidrawApp from "./App"; + window.__EXCALIDRAW_SHA__ = import.meta.env.VITE_APP_GIT_SHA; const rootElement = document.getElementById("root")!; const root = createRoot(rootElement); diff --git a/excalidraw-app/share/ShareDialog.tsx b/excalidraw-app/share/ShareDialog.tsx index bba7e3678..de77c6079 100644 --- a/excalidraw-app/share/ShareDialog.tsx +++ b/excalidraw-app/share/ShareDialog.tsx @@ -1,10 +1,8 @@ -import { useEffect, useRef, useState } from "react"; -import { copyTextToSystemClipboard } from "@excalidraw/excalidraw/clipboard"; import { trackEvent } from "@excalidraw/excalidraw/analytics"; -import { getFrame } from "@excalidraw/excalidraw/utils"; -import { useI18n } from "@excalidraw/excalidraw/i18n"; -import { KEYS } from "@excalidraw/excalidraw/keys"; +import { copyTextToSystemClipboard } from "@excalidraw/excalidraw/clipboard"; import { Dialog } from "@excalidraw/excalidraw/components/Dialog"; +import { FilledButton } from "@excalidraw/excalidraw/components/FilledButton"; +import { TextField } from "@excalidraw/excalidraw/components/TextField"; import { copyIcon, LinkIcon, @@ -14,16 +12,20 @@ import { shareIOS, shareWindows, } from "@excalidraw/excalidraw/components/icons"; -import { TextField } from "@excalidraw/excalidraw/components/TextField"; -import { FilledButton } from "@excalidraw/excalidraw/components/FilledButton"; -import type { CollabAPI } from "../collab/Collab"; -import { activeRoomLinkAtom } from "../collab/Collab"; import { useUIAppState } from "@excalidraw/excalidraw/context/ui-appState"; import { useCopyStatus } from "@excalidraw/excalidraw/hooks/useCopiedIndicator"; +import { useI18n } from "@excalidraw/excalidraw/i18n"; +import { KEYS } from "@excalidraw/excalidraw/keys"; +import { getFrame } from "@excalidraw/excalidraw/utils"; +import { useEffect, useRef, useState } from "react"; + import { atom, useAtom, useAtomValue } from "../app-jotai"; +import { activeRoomLinkAtom } from "../collab/Collab"; import "./ShareDialog.scss"; +import type { CollabAPI } from "../collab/Collab"; + type OnExportToBackend = () => void; type ShareDialogType = "share" | "collaborationOnly"; diff --git a/excalidraw-app/tests/MobileMenu.test.tsx b/excalidraw-app/tests/MobileMenu.test.tsx index a6eef3b51..3b05e7296 100644 --- a/excalidraw-app/tests/MobileMenu.test.tsx +++ b/excalidraw-app/tests/MobileMenu.test.tsx @@ -1,11 +1,11 @@ -import ExcalidrawApp from "../App"; +import { UI } from "@excalidraw/excalidraw/tests/helpers/ui"; import { mockBoundingClientRect, render, restoreOriginalGetBoundingClientRect, } from "@excalidraw/excalidraw/tests/test-utils"; -import { UI } from "@excalidraw/excalidraw/tests/helpers/ui"; +import ExcalidrawApp from "../App"; describe("Test MobileMenu", () => { const { h } = window; diff --git a/excalidraw-app/tests/collab.test.tsx b/excalidraw-app/tests/collab.test.tsx index 80cf4b0b9..f6cd68fab 100644 --- a/excalidraw-app/tests/collab.test.tsx +++ b/excalidraw-app/tests/collab.test.tsx @@ -1,13 +1,14 @@ -import { vi } from "vitest"; -import { act, render, waitFor } from "@excalidraw/excalidraw/tests/test-utils"; -import ExcalidrawApp from "../App"; -import { API } from "@excalidraw/excalidraw/tests/helpers/api"; -import { syncInvalidIndices } from "@excalidraw/excalidraw/fractionalIndex"; +import { CaptureUpdateAction, newElementWith } from "@excalidraw/excalidraw"; import { createRedoAction, createUndoAction, } from "@excalidraw/excalidraw/actions/actionHistory"; -import { CaptureUpdateAction, newElementWith } from "@excalidraw/excalidraw"; +import { syncInvalidIndices } from "@excalidraw/excalidraw/fractionalIndex"; +import { API } from "@excalidraw/excalidraw/tests/helpers/api"; +import { act, render, waitFor } from "@excalidraw/excalidraw/tests/test-utils"; +import { vi } from "vitest"; + +import ExcalidrawApp from "../App"; const { h } = window; diff --git a/excalidraw-app/useHandleAppTheme.ts b/excalidraw-app/useHandleAppTheme.ts index e31961174..6fc2ff54f 100644 --- a/excalidraw-app/useHandleAppTheme.ts +++ b/excalidraw-app/useHandleAppTheme.ts @@ -1,8 +1,10 @@ -import { useEffect, useLayoutEffect, useState } from "react"; import { THEME } from "@excalidraw/excalidraw"; import { EVENT } from "@excalidraw/excalidraw/constants"; -import type { Theme } from "@excalidraw/excalidraw/element/types"; import { CODES, KEYS } from "@excalidraw/excalidraw/keys"; +import { useEffect, useLayoutEffect, useState } from "react"; + +import type { Theme } from "@excalidraw/excalidraw/element/types"; + import { STORAGE_KEYS } from "./app_constants"; const getDarkThemeMediaQuery = (): MediaQueryList | undefined => diff --git a/package.json b/package.json index aaa8027a8..9ff4379d1 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "dotenv": "16.0.1", "eslint-config-prettier": "8.5.0", "eslint-config-react-app": "7.0.1", + "eslint-plugin-import": "2.31.0", "eslint-plugin-prettier": "3.3.1", "http-server": "14.1.1", "husky": "7.0.4", diff --git a/packages/excalidraw/CHANGELOG.md b/packages/excalidraw/CHANGELOG.md index cdcb39660..e4a98d19e 100644 --- a/packages/excalidraw/CHANGELOG.md +++ b/packages/excalidraw/CHANGELOG.md @@ -13,7 +13,7 @@ Please add the latest change on the top under the correct section. ## Excalidraw Library -## 18.0.0 (2025-02-28) +## 0.18.0 (2025-03-11) ### Highlights @@ -45,9 +45,9 @@ Please add the latest change on the top under the correct section. #### Deprecated UMD bundle in favor of ES modules [#7441](https://github.com/excalidraw/excalidraw/pull/7441), [#9127](https://github.com/excalidraw/excalidraw/pull/9127) -We've transitioned from `UMD` to `ESM` bundle format. Our new `dist` bundles inside `@excalidraw/excalidraw` package now contain only bundled source files, making any dependencies tree-shakable. The npm package comes with the following structure: +We've transitioned from `UMD` to `ESM` bundle format. Our new `dist` folder inside `@excalidraw/excalidraw` package now contains only bundled source files, making any dependencies tree-shakable. The package comes with the following structure: -> **Note**: The structure is simplified for the sake of brevity, omitting lazy-loadable modules, including locales (previously treated as json assets) and source maps in the development bundle. +> **Note**: The structure is simplified for the sake of brevity, omitting lazy-loadable modules, including locales (previously treated as JSON assets) and source maps in the development bundle. ``` @excalidraw/excalidraw/ @@ -64,17 +64,23 @@ We've transitioned from `UMD` to `ESM` bundle format. Our new `dist` bundles ins │ └── types/ ``` -##### JavaScript: required `"type": "module"` in package.json - -Make sure that your JavaScript environment supports ES modules, as it might be required to define `"type": "module"` in your `package.json` file or as part of the ` @@ -153,7 +159,7 @@ or, if you serve your assets from the root of your CDN, you would do: ``` -or, if you prefer the path to be dynamicly set based on the `location.origin`, you could do the following: +or, if you prefer the path to be dynamically set based on the `location.origin`, you could do the following: ```jsx // Next.js @@ -183,7 +189,7 @@ updateScene({ }); // B ``` -The `updateScene` API has changed due to the added `Store` component, as part of multiplayer undo / redo initiative. Specifically, optional `sceneData` parameter `commitToHistory: boolean` was replaced with optional `captureUpdate: CaptureUpdateActionType` parameter. Therefore, make sure to update all instances of `updateScene`, which use `commitToHistory` parameter according to the _before / after_ table below. +The `updateScene` API has changed due to the added `Store` component, as part of the multiplayer undo / redo initiative. Specifically, optional `sceneData` parameter `commitToHistory: boolean` was replaced with optional `captureUpdate: CaptureUpdateActionType` parameter. Therefore, make sure to update all instances of `updateScene`, which use `commitToHistory` parameter according to the _before / after_ table below. > **Note**: Some updates are not observed by the store / history - i.e. updates to `collaborators` object or parts of `AppState` which are not observed (not `ObservedAppState`). Such updates will never make it to the undo / redo stacks, regardless of the passed `captureUpdate` value. @@ -197,7 +203,7 @@ The `updateScene` API has changed due to the added `Store` component, as part of - `ExcalidrawTextElement.baseline` was removed and replaced with a vertical offset computation based on font metrics, performed on each text element re-render. In case of custom font usage, extend the `FONT_METRICS` object with the related properties. [#7693](https://github.com/excalidraw/excalidraw/pull/7693) -- `ExcalidrawEmbeddableElement.validated` was removed and moved to private editor state. This should largely not affect your apps unless you were reading from this attribute. We keep validating embeddable urls internally, and the public [`props.validateEmbeddable`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props#validateembeddable) still applies. [#7539](https://github.com/excalidraw/excalidraw/pull/7539) +- `ExcalidrawEmbeddableElement.validated` was removed and moved to the private editor state. This should largely not affect your apps unless you were reading from this attribute. We keep validating embeddable urls internally, and the public [`props.validateEmbeddable`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props#validateembeddable) still applies. [#7539](https://github.com/excalidraw/excalidraw/pull/7539) - Stats container CSS has changed, so if you're using `renderCustomStats`, you may need to adjust your styles to retain the same layout. [#8361](https://github.com/excalidraw/excalidraw/pull/8361) @@ -359,6 +365,8 @@ The `updateScene` API has changed due to the added `Store` component, as part of - Grouped together Undo and Redo buttons on mobile [#9109](https://github.com/excalidraw/excalidraw/pull/9109) +- Remove GA code from binding [#9042](https://github.com/excalidraw/excalidraw/pull/9042) + - Load old library if migration fails - Change LibraryPersistenceAdapter `load()` `source` -> `priority` @@ -479,7 +487,7 @@ The `updateScene` API has changed due to the added `Store` component, as part of - Linear element complete button disabled [#8492](https://github.com/excalidraw/excalidraw/pull/8492) -- Aspect ratio of distorted images are not preserved in SVG exports [#8061](https://github.com/excalidraw/excalidraw/pull/8061) +- Aspect ratios of distorted images are not preserved in SVG exports [#8061](https://github.com/excalidraw/excalidraw/pull/8061) - WYSIWYG editor padding is not normalized with zoom.value [#8481](https://github.com/excalidraw/excalidraw/pull/8481) @@ -509,7 +517,7 @@ The `updateScene` API has changed due to the added `Store` component, as part of - Round coordinates and sizes for rectangle intersection [#8366](https://github.com/excalidraw/excalidraw/pull/8366) -- Text content with tab characters act different in view/edit [#8336](https://github.com/excalidraw/excalidraw/pull/8336) +- Text content with tab characters act differently in view/edit [#8336](https://github.com/excalidraw/excalidraw/pull/8336) - Drawing from 0-dimension canvas [#8356](https://github.com/excalidraw/excalidraw/pull/8356) @@ -669,6 +677,24 @@ The `updateScene` API has changed due to the added `Store` component, as part of - Stop using structuredClone [#9128](https://github.com/excalidraw/excalidraw/pull/9128) +- Fix elbow arrow fixed binding on restore [#9197](https://github.com/excalidraw/excalidraw/pull/9197) + +- Cleanup legacy `element.rawText` (obsidian) [#9203](https://github.com/excalidraw/excalidraw/pull/9203) + +- React 18 element.ref was accessed error [#9208](https://github.com/excalidraw/excalidraw/pull/9208) + +- Docked sidebar width [#9213](https://github.com/excalidraw/excalidraw/pull/9213) + +- Arrow updated on both sides [#8593](https://github.com/excalidraw/excalidraw/pull/8593) + +- Package env vars [#9221](https://github.com/excalidraw/excalidraw/pull/9221) + +- Bound elbow arrow on duplication does not route correctly [#9236](https://github.com/excalidraw/excalidraw/pull/9236) + +- Do not rebind undragged elbow arrow endpoint [#9191](https://github.com/excalidraw/excalidraw/pull/9191) + +- Logging and fixing extremely large scenes [#9225](https://github.com/excalidraw/excalidraw/pull/9225) + ### Refactor - Remove `defaultProps` [#9035](https://github.com/excalidraw/excalidraw/pull/9035) diff --git a/packages/excalidraw/README.md b/packages/excalidraw/README.md index a24b305fd..518518553 100644 --- a/packages/excalidraw/README.md +++ b/packages/excalidraw/README.md @@ -30,7 +30,7 @@ Excalidraw takes _100%_ of `width` and `height` of the containing block so make ## Demo -Go to [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/mrazator/release-v18/examples/with-script-in-browser) example. +Go to [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/master/examples/with-script-in-browser) example. ## Integration diff --git a/packages/excalidraw/actions/actionAddToLibrary.ts b/packages/excalidraw/actions/actionAddToLibrary.ts index 3186e3bcb..b246918a0 100644 --- a/packages/excalidraw/actions/actionAddToLibrary.ts +++ b/packages/excalidraw/actions/actionAddToLibrary.ts @@ -1,10 +1,11 @@ -import { register } from "./register"; -import { deepCopyElement } from "../element/newElement"; -import { randomId } from "../random"; -import { t } from "../i18n"; import { LIBRARY_DISABLED_TYPES } from "../constants"; +import { deepCopyElement } from "../element/newElement"; +import { t } from "../i18n"; +import { randomId } from "../random"; import { CaptureUpdateAction } from "../store"; +import { register } from "./register"; + export const actionAddToLibrary = register({ name: "addToLibrary", trackEvent: { category: "element" }, diff --git a/packages/excalidraw/actions/actionAlign.tsx b/packages/excalidraw/actions/actionAlign.tsx index 53e8e618b..b42122a50 100644 --- a/packages/excalidraw/actions/actionAlign.tsx +++ b/packages/excalidraw/actions/actionAlign.tsx @@ -1,5 +1,5 @@ -import type { Alignment } from "../align"; import { alignElements } from "../align"; +import { ToolButton } from "../components/ToolButton"; import { AlignBottomIcon, AlignLeftIcon, @@ -8,19 +8,21 @@ import { CenterHorizontallyIcon, CenterVerticallyIcon, } from "../components/icons"; -import { ToolButton } from "../components/ToolButton"; import { getNonDeletedElements } from "../element"; import { isFrameLikeElement } from "../element/typeChecks"; -import type { ExcalidrawElement } from "../element/types"; import { updateFrameMembershipOfSelectedElements } from "../frame"; import { t } from "../i18n"; import { KEYS } from "../keys"; import { isSomeElementSelected } from "../scene"; import { CaptureUpdateAction } from "../store"; -import type { AppClassProperties, AppState, UIAppState } from "../types"; import { arrayToMap, getShortcutKey } from "../utils"; + import { register } from "./register"; +import type { Alignment } from "../align"; +import type { ExcalidrawElement } from "../element/types"; +import type { AppClassProperties, AppState, UIAppState } from "../types"; + export const alignActionsPredicate = ( appState: UIAppState, app: AppClassProperties, diff --git a/packages/excalidraw/actions/actionBoundText.tsx b/packages/excalidraw/actions/actionBoundText.tsx index b72ddee64..4da3f99a1 100644 --- a/packages/excalidraw/actions/actionBoundText.tsx +++ b/packages/excalidraw/actions/actionBoundText.tsx @@ -5,6 +5,11 @@ import { VERTICAL_ALIGN, } from "../constants"; import { isTextElement, newElement } from "../element"; +import { + getOriginalContainerHeightFromCache, + resetOriginalContainerCache, + updateOriginalContainerCache, +} from "../element/containerCache"; import { mutateElement } from "../element/mutateElement"; import { computeBoundTextPosition, @@ -12,16 +17,18 @@ import { getBoundTextElement, redrawTextBoundingBox, } from "../element/textElement"; -import { - getOriginalContainerHeightFromCache, - resetOriginalContainerCache, - updateOriginalContainerCache, -} from "../element/containerCache"; +import { measureText } from "../element/textMeasurements"; import { hasBoundTextElement, isTextBindableContainer, isUsingAdaptiveRadius, } from "../element/typeChecks"; +import { syncMovedIndices } from "../fractionalIndex"; +import { CaptureUpdateAction } from "../store"; +import { arrayToMap, getFontString } from "../utils"; + +import { register } from "./register"; + import type { ExcalidrawElement, ExcalidrawLinearElement, @@ -30,11 +37,6 @@ import type { } from "../element/types"; import type { AppState } from "../types"; import type { Mutable } from "../utility-types"; -import { arrayToMap, getFontString } from "../utils"; -import { register } from "./register"; -import { syncMovedIndices } from "../fractionalIndex"; -import { CaptureUpdateAction } from "../store"; -import { measureText } from "../element/textMeasurements"; export const actionUnbindText = register({ name: "unbindText", diff --git a/packages/excalidraw/actions/actionCanvas.tsx b/packages/excalidraw/actions/actionCanvas.tsx index 903a6d84a..f3e0a8a32 100644 --- a/packages/excalidraw/actions/actionCanvas.tsx +++ b/packages/excalidraw/actions/actionCanvas.tsx @@ -1,4 +1,14 @@ +import { clamp, roundToStep } from "@excalidraw/math"; + +import { + getDefaultAppState, + isEraserActive, + isHandToolActive, +} from "../appState"; +import { DEFAULT_CANVAS_BACKGROUND_PICKS } from "../colors"; import { ColorPicker } from "../components/ColorPicker/ColorPicker"; +import { ToolButton } from "../components/ToolButton"; +import { Tooltip } from "../components/Tooltip"; import { handIcon, MoonIcon, @@ -9,7 +19,6 @@ import { ZoomOutIcon, ZoomResetIcon, } from "../components/icons"; -import { ToolButton } from "../components/ToolButton"; import { CURSOR_TYPE, MAX_ZOOM, @@ -17,28 +26,22 @@ import { THEME, ZOOM_STEP, } from "../constants"; +import { setCursor } from "../cursor"; import { getCommonBounds, getNonDeletedElements } from "../element"; -import type { ExcalidrawElement } from "../element/types"; +import { newElementWith } from "../element/mutateElement"; import { t } from "../i18n"; import { CODES, KEYS } from "../keys"; import { getNormalizedZoom } from "../scene"; import { centerScrollOn } from "../scene/scroll"; import { getStateForZoom } from "../scene/zoom"; -import type { AppState, Offsets } from "../types"; -import { getShortcutKey, updateActiveTool } from "../utils"; -import { register } from "./register"; -import { Tooltip } from "../components/Tooltip"; -import { newElementWith } from "../element/mutateElement"; -import { - getDefaultAppState, - isEraserActive, - isHandToolActive, -} from "../appState"; -import { DEFAULT_CANVAS_BACKGROUND_PICKS } from "../colors"; -import type { SceneBounds } from "../element/bounds"; -import { setCursor } from "../cursor"; import { CaptureUpdateAction } from "../store"; -import { clamp, roundToStep } from "@excalidraw/math"; +import { getShortcutKey, updateActiveTool } from "../utils"; + +import { register } from "./register"; + +import type { SceneBounds } from "../element/bounds"; +import type { ExcalidrawElement } from "../element/types"; +import type { AppState, Offsets } from "../types"; export const actionChangeViewBackgroundColor = register({ name: "changeViewBackgroundColor", diff --git a/packages/excalidraw/actions/actionClipboard.tsx b/packages/excalidraw/actions/actionClipboard.tsx index fffe7b377..4ce3c39dd 100644 --- a/packages/excalidraw/actions/actionClipboard.tsx +++ b/packages/excalidraw/actions/actionClipboard.tsx @@ -1,5 +1,3 @@ -import { CODES, KEYS } from "../keys"; -import { register } from "./register"; import { copyTextToSystemClipboard, copyToClipboard, @@ -8,14 +6,17 @@ import { probablySupportsClipboardWriteText, readSystemClipboard, } from "../clipboard"; -import { actionDeleteSelected } from "./actionDeleteSelected"; +import { DuplicateIcon, cutIcon, pngIcon, svgIcon } from "../components/icons"; +import { isFirefox } from "../constants"; import { exportCanvas, prepareElementsForExport } from "../data/index"; import { getTextFromElements, isTextElement } from "../element"; import { t } from "../i18n"; -import { isFirefox } from "../constants"; -import { DuplicateIcon, cutIcon, pngIcon, svgIcon } from "../components/icons"; +import { CODES, KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; +import { actionDeleteSelected } from "./actionDeleteSelected"; +import { register } from "./register"; + export const actionCopy = register({ name: "copy", label: "labels.copy", diff --git a/packages/excalidraw/actions/actionCropEditor.tsx b/packages/excalidraw/actions/actionCropEditor.tsx index 643f666ba..c377b3a02 100644 --- a/packages/excalidraw/actions/actionCropEditor.tsx +++ b/packages/excalidraw/actions/actionCropEditor.tsx @@ -1,9 +1,11 @@ -import { register } from "./register"; -import { cropIcon } from "../components/icons"; -import { CaptureUpdateAction } from "../store"; import { ToolButton } from "../components/ToolButton"; -import { t } from "../i18n"; +import { cropIcon } from "../components/icons"; import { isImageElement } from "../element/typeChecks"; +import { t } from "../i18n"; +import { CaptureUpdateAction } from "../store"; + +import { register } from "./register"; + import type { ExcalidrawImageElement } from "../element/types"; export const actionToggleCropEditor = register({ diff --git a/packages/excalidraw/actions/actionDeleteSelected.test.tsx b/packages/excalidraw/actions/actionDeleteSelected.test.tsx index d48646fac..090c81941 100644 --- a/packages/excalidraw/actions/actionDeleteSelected.test.tsx +++ b/packages/excalidraw/actions/actionDeleteSelected.test.tsx @@ -1,7 +1,9 @@ import React from "react"; + import { Excalidraw, mutateElement } from "../index"; -import { act, assertElements, render } from "../tests/test-utils"; import { API } from "../tests/helpers/api"; +import { act, assertElements, render } from "../tests/test-utils"; + import { actionDeleteSelected } from "./actionDeleteSelected"; const { h } = window; diff --git a/packages/excalidraw/actions/actionDeleteSelected.tsx b/packages/excalidraw/actions/actionDeleteSelected.tsx index c640f9256..fe3f8c5d7 100644 --- a/packages/excalidraw/actions/actionDeleteSelected.tsx +++ b/packages/excalidraw/actions/actionDeleteSelected.tsx @@ -1,25 +1,27 @@ -import { getSelectedElements, isSomeElementSelected } from "../scene"; -import { KEYS } from "../keys"; import { ToolButton } from "../components/ToolButton"; -import { t } from "../i18n"; -import { register } from "./register"; +import { TrashIcon } from "../components/icons"; import { getNonDeletedElements } from "../element"; -import type { ExcalidrawElement } from "../element/types"; -import type { AppClassProperties, AppState } from "../types"; -import { mutateElement, newElementWith } from "../element/mutateElement"; -import { getElementsInGroup, selectGroupsForSelectedElements } from "../groups"; -import { LinearElementEditor } from "../element/linearElementEditor"; import { fixBindingsAfterDeletion } from "../element/binding"; +import { LinearElementEditor } from "../element/linearElementEditor"; +import { mutateElement, newElementWith } from "../element/mutateElement"; +import { getContainerElement } from "../element/textElement"; import { isBoundToContainer, isElbowArrow, isFrameLikeElement, } from "../element/typeChecks"; -import { updateActiveTool } from "../utils"; -import { TrashIcon } from "../components/icons"; -import { CaptureUpdateAction } from "../store"; -import { getContainerElement } from "../element/textElement"; import { getFrameChildren } from "../frame"; +import { getElementsInGroup, selectGroupsForSelectedElements } from "../groups"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { getSelectedElements, isSomeElementSelected } from "../scene"; +import { CaptureUpdateAction } from "../store"; +import { updateActiveTool } from "../utils"; + +import { register } from "./register"; + +import type { ExcalidrawElement } from "../element/types"; +import type { AppClassProperties, AppState } from "../types"; const deleteSelectedElements = ( elements: readonly ExcalidrawElement[], diff --git a/packages/excalidraw/actions/actionDistribute.tsx b/packages/excalidraw/actions/actionDistribute.tsx index 15d33b1f1..c96bdaa3e 100644 --- a/packages/excalidraw/actions/actionDistribute.tsx +++ b/packages/excalidraw/actions/actionDistribute.tsx @@ -1,22 +1,24 @@ +import { ToolButton } from "../components/ToolButton"; import { DistributeHorizontallyIcon, DistributeVerticallyIcon, } from "../components/icons"; -import { ToolButton } from "../components/ToolButton"; -import type { Distribution } from "../distribute"; import { distributeElements } from "../distribute"; import { getNonDeletedElements } from "../element"; import { isFrameLikeElement } from "../element/typeChecks"; -import type { ExcalidrawElement } from "../element/types"; import { updateFrameMembershipOfSelectedElements } from "../frame"; import { t } from "../i18n"; import { CODES, KEYS } from "../keys"; import { isSomeElementSelected } from "../scene"; import { CaptureUpdateAction } from "../store"; -import type { AppClassProperties, AppState } from "../types"; import { arrayToMap, getShortcutKey } from "../utils"; + import { register } from "./register"; +import type { Distribution } from "../distribute"; +import type { ExcalidrawElement } from "../element/types"; +import type { AppClassProperties, AppState } from "../types"; + const enableActionGroup = (appState: AppState, app: AppClassProperties) => { const selectedElements = app.scene.getSelectedElements(appState); return ( diff --git a/packages/excalidraw/actions/actionDuplicateSelection.test.tsx b/packages/excalidraw/actions/actionDuplicateSelection.test.tsx index dc471df37..2c1d44e92 100644 --- a/packages/excalidraw/actions/actionDuplicateSelection.test.tsx +++ b/packages/excalidraw/actions/actionDuplicateSelection.test.tsx @@ -1,14 +1,16 @@ +import React from "react"; + +import { ORIG_ID } from "../constants"; import { Excalidraw } from "../index"; +import { API } from "../tests/helpers/api"; import { act, assertElements, getCloneByOrigId, render, } from "../tests/test-utils"; -import { API } from "../tests/helpers/api"; + import { actionDuplicateSelection } from "./actionDuplicateSelection"; -import React from "react"; -import { ORIG_ID } from "../constants"; const { h } = window; diff --git a/packages/excalidraw/actions/actionDuplicateSelection.tsx b/packages/excalidraw/actions/actionDuplicateSelection.tsx index b28e831c8..ce225a1d6 100644 --- a/packages/excalidraw/actions/actionDuplicateSelection.tsx +++ b/packages/excalidraw/actions/actionDuplicateSelection.tsx @@ -1,27 +1,8 @@ -import { KEYS } from "../keys"; -import { register } from "./register"; -import type { ExcalidrawElement } from "../element/types"; -import { duplicateElement, getNonDeletedElements } from "../element"; -import { isSomeElementSelected } from "../scene"; import { ToolButton } from "../components/ToolButton"; -import { t } from "../i18n"; -import { - arrayToMap, - castArray, - findLastIndex, - getShortcutKey, - invariant, -} from "../utils"; -import { LinearElementEditor } from "../element/linearElementEditor"; -import { - selectGroupsForSelectedElements, - getSelectedGroupForElement, - getElementsInGroup, -} from "../groups"; -import type { AppState } from "../types"; -import { fixBindingsAfterDuplication } from "../element/binding"; -import type { ActionResult } from "./types"; +import { DuplicateIcon } from "../components/icons"; import { DEFAULT_GRID_SIZE } from "../constants"; +import { duplicateElement, getNonDeletedElements } from "../element"; +import { fixBindingsAfterDuplication } from "../element/binding"; import { bindTextToShapeAfterDuplication, getBoundTextElement, @@ -33,16 +14,37 @@ import { isFrameLikeElement, } from "../element/typeChecks"; import { normalizeElementOrder } from "../element/sortElements"; -import { DuplicateIcon } from "../components/icons"; +import { LinearElementEditor } from "../element/linearElementEditor"; import { bindElementsToFramesAfterDuplication, getFrameChildren, } from "../frame"; +import { + selectGroupsForSelectedElements, + getSelectedGroupForElement, + getElementsInGroup, +} from "../groups"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { isSomeElementSelected } from "../scene"; import { excludeElementsInFramesFromSelection, getSelectedElements, } from "../scene/selection"; import { CaptureUpdateAction } from "../store"; +import { + arrayToMap, + castArray, + findLastIndex, + getShortcutKey, + invariant, +} from "../utils"; + +import { register } from "./register"; + +import type { ActionResult } from "./types"; +import type { ExcalidrawElement } from "../element/types"; +import type { AppState } from "../types"; export const actionDuplicateSelection = register({ name: "duplicateSelection", diff --git a/packages/excalidraw/actions/actionElementLink.ts b/packages/excalidraw/actions/actionElementLink.ts index 91469fd63..69fc67dd3 100644 --- a/packages/excalidraw/actions/actionElementLink.ts +++ b/packages/excalidraw/actions/actionElementLink.ts @@ -8,6 +8,7 @@ import { import { t } from "../i18n"; import { getSelectedElements } from "../scene"; import { CaptureUpdateAction } from "../store"; + import { register } from "./register"; export const actionCopyElementLink = register({ diff --git a/packages/excalidraw/actions/actionElementLock.test.tsx b/packages/excalidraw/actions/actionElementLock.test.tsx index d6dd3f7ac..ec45ab9b2 100644 --- a/packages/excalidraw/actions/actionElementLock.test.tsx +++ b/packages/excalidraw/actions/actionElementLock.test.tsx @@ -1,9 +1,10 @@ -import React from "react"; -import { Excalidraw } from "../index"; import { queryByTestId, fireEvent } from "@testing-library/react"; -import { render } from "../tests/test-utils"; -import { Pointer, UI } from "../tests/helpers/ui"; +import React from "react"; + +import { Excalidraw } from "../index"; import { API } from "../tests/helpers/api"; +import { Pointer, UI } from "../tests/helpers/ui"; +import { render } from "../tests/test-utils"; const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/actions/actionElementLock.ts b/packages/excalidraw/actions/actionElementLock.ts index eba21f240..57ca1dded 100644 --- a/packages/excalidraw/actions/actionElementLock.ts +++ b/packages/excalidraw/actions/actionElementLock.ts @@ -1,13 +1,15 @@ import { LockedIcon, UnlockedIcon } from "../components/icons"; import { newElementWith } from "../element/mutateElement"; import { isFrameLikeElement } from "../element/typeChecks"; -import type { ExcalidrawElement } from "../element/types"; import { KEYS } from "../keys"; import { getSelectedElements } from "../scene"; import { CaptureUpdateAction } from "../store"; import { arrayToMap } from "../utils"; + import { register } from "./register"; +import type { ExcalidrawElement } from "../element/types"; + const shouldLock = (elements: readonly ExcalidrawElement[]) => elements.every((el) => !el.locked); diff --git a/packages/excalidraw/actions/actionExport.tsx b/packages/excalidraw/actions/actionExport.tsx index 8d18acd89..c9d70fc46 100644 --- a/packages/excalidraw/actions/actionExport.tsx +++ b/packages/excalidraw/actions/actionExport.tsx @@ -1,25 +1,27 @@ -import { ExportIcon, questionCircle, saveAs } from "../components/icons"; +import { useDevice } from "../components/App"; +import { CheckboxItem } from "../components/CheckboxItem"; +import { DarkModeToggle } from "../components/DarkModeToggle"; import { ProjectName } from "../components/ProjectName"; import { ToolButton } from "../components/ToolButton"; import { Tooltip } from "../components/Tooltip"; -import { DarkModeToggle } from "../components/DarkModeToggle"; -import { loadFromJSON, saveAsJSON } from "../data"; -import { resaveAsImageWithScene } from "../data/resave"; -import { t } from "../i18n"; -import { useDevice } from "../components/App"; -import { KEYS } from "../keys"; -import { register } from "./register"; -import { CheckboxItem } from "../components/CheckboxItem"; -import { getExportSize } from "../scene/export"; +import { ExportIcon, questionCircle, saveAs } from "../components/icons"; import { DEFAULT_EXPORT_PADDING, EXPORT_SCALES, THEME } from "../constants"; -import { getSelectedElements, isSomeElementSelected } from "../scene"; -import { getNonDeletedElements } from "../element"; +import { loadFromJSON, saveAsJSON } from "../data"; import { isImageFileHandle } from "../data/blob"; import { nativeFileSystemSupported } from "../data/filesystem"; -import type { Theme } from "../element/types"; +import { resaveAsImageWithScene } from "../data/resave"; +import { getNonDeletedElements } from "../element"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { getSelectedElements, isSomeElementSelected } from "../scene"; +import { getExportSize } from "../scene/export"; +import { CaptureUpdateAction } from "../store"; import "../components/ToolIcon.scss"; -import { CaptureUpdateAction } from "../store"; + +import { register } from "./register"; + +import type { Theme } from "../element/types"; export const actionChangeProjectName = register({ name: "changeProjectName", diff --git a/packages/excalidraw/actions/actionFinalize.tsx b/packages/excalidraw/actions/actionFinalize.tsx index f2d8c0158..ac8a4e036 100644 --- a/packages/excalidraw/actions/actionFinalize.tsx +++ b/packages/excalidraw/actions/actionFinalize.tsx @@ -1,22 +1,25 @@ -import { KEYS } from "../keys"; -import { isInvisiblySmallElement } from "../element"; -import { arrayToMap, updateActiveTool } from "../utils"; +import { pointFrom } from "@excalidraw/math"; + import { ToolButton } from "../components/ToolButton"; import { done } from "../components/icons"; -import { t } from "../i18n"; -import { register } from "./register"; -import { mutateElement } from "../element/mutateElement"; -import { LinearElementEditor } from "../element/linearElementEditor"; +import { resetCursor } from "../cursor"; +import { isInvisiblySmallElement } from "../element"; import { maybeBindLinearElement, bindOrUnbindLinearElement, } from "../element/binding"; +import { LinearElementEditor } from "../element/linearElementEditor"; +import { mutateElement } from "../element/mutateElement"; import { isBindingElement, isLinearElement } from "../element/typeChecks"; -import type { AppState } from "../types"; -import { resetCursor } from "../cursor"; -import { CaptureUpdateAction } from "../store"; -import { pointFrom } from "@excalidraw/math"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; import { isPathALoop } from "../shapes"; +import { CaptureUpdateAction } from "../store"; +import { arrayToMap, updateActiveTool } from "../utils"; + +import { register } from "./register"; + +import type { AppState } from "../types"; export const actionFinalize = register({ name: "finalize", diff --git a/packages/excalidraw/actions/actionFlip.test.tsx b/packages/excalidraw/actions/actionFlip.test.tsx index 94e4721dd..e9953e02d 100644 --- a/packages/excalidraw/actions/actionFlip.test.tsx +++ b/packages/excalidraw/actions/actionFlip.test.tsx @@ -1,8 +1,10 @@ -import React from "react"; -import { Excalidraw } from "../index"; -import { render } from "../tests/test-utils"; -import { API } from "../tests/helpers/api"; import { pointFrom } from "@excalidraw/math"; +import React from "react"; + +import { Excalidraw } from "../index"; +import { API } from "../tests/helpers/api"; +import { render } from "../tests/test-utils"; + import { actionFlipHorizontal, actionFlipVertical } from "./actionFlip"; const { h } = window; diff --git a/packages/excalidraw/actions/actionFlip.ts b/packages/excalidraw/actions/actionFlip.ts index 80149b877..bfc7fb721 100644 --- a/packages/excalidraw/actions/actionFlip.ts +++ b/packages/excalidraw/actions/actionFlip.ts @@ -1,6 +1,26 @@ -import { register } from "./register"; -import { getSelectedElements } from "../scene"; +import { flipHorizontal, flipVertical } from "../components/icons"; import { getNonDeletedElements } from "../element"; +import { + bindOrUnbindLinearElements, + isBindingEnabled, +} from "../element/binding"; +import { getCommonBoundingBox } from "../element/bounds"; +import { mutateElement, newElementWith } from "../element/mutateElement"; +import { deepCopyElement } from "../element/newElement"; +import { resizeMultipleElements } from "../element/resizeElements"; +import { + isArrowElement, + isElbowArrow, + isLinearElement, +} from "../element/typeChecks"; +import { updateFrameMembershipOfSelectedElements } from "../frame"; +import { CODES, KEYS } from "../keys"; +import { getSelectedElements } from "../scene"; +import { CaptureUpdateAction } from "../store"; +import { arrayToMap } from "../utils"; + +import { register } from "./register"; + import type { ExcalidrawArrowElement, ExcalidrawElbowArrowElement, @@ -8,25 +28,7 @@ import type { NonDeleted, NonDeletedSceneElementsMap, } from "../element/types"; -import { resizeMultipleElements } from "../element/resizeElements"; import type { AppClassProperties, AppState } from "../types"; -import { arrayToMap } from "../utils"; -import { CODES, KEYS } from "../keys"; -import { - bindOrUnbindLinearElements, - isBindingEnabled, -} from "../element/binding"; -import { updateFrameMembershipOfSelectedElements } from "../frame"; -import { flipHorizontal, flipVertical } from "../components/icons"; -import { CaptureUpdateAction } from "../store"; -import { - isArrowElement, - isElbowArrow, - isLinearElement, -} from "../element/typeChecks"; -import { mutateElement, newElementWith } from "../element/mutateElement"; -import { deepCopyElement } from "../element/newElement"; -import { getCommonBoundingBox } from "../element/bounds"; export const actionFlipHorizontal = register({ name: "flipHorizontal", diff --git a/packages/excalidraw/actions/actionFrame.ts b/packages/excalidraw/actions/actionFrame.ts index ce05b533b..198994b29 100644 --- a/packages/excalidraw/actions/actionFrame.ts +++ b/packages/excalidraw/actions/actionFrame.ts @@ -1,19 +1,21 @@ +import { frameToolIcon } from "../components/icons"; +import { setCursorForShape } from "../cursor"; import { getCommonBounds, getNonDeletedElements } from "../element"; -import type { ExcalidrawElement } from "../element/types"; +import { mutateElement } from "../element/mutateElement"; +import { newFrameElement } from "../element/newElement"; +import { isFrameLikeElement } from "../element/typeChecks"; import { addElementsToFrame, removeAllElementsFromFrame } from "../frame"; import { getFrameChildren } from "../frame"; -import { KEYS } from "../keys"; -import type { AppClassProperties, AppState, UIAppState } from "../types"; -import { updateActiveTool } from "../utils"; -import { setCursorForShape } from "../cursor"; -import { register } from "./register"; -import { isFrameLikeElement } from "../element/typeChecks"; -import { frameToolIcon } from "../components/icons"; -import { CaptureUpdateAction } from "../store"; -import { getSelectedElements } from "../scene"; -import { newFrameElement } from "../element/newElement"; import { getElementsInGroup } from "../groups"; -import { mutateElement } from "../element/mutateElement"; +import { KEYS } from "../keys"; +import { getSelectedElements } from "../scene"; +import { CaptureUpdateAction } from "../store"; +import { updateActiveTool } from "../utils"; + +import { register } from "./register"; + +import type { ExcalidrawElement } from "../element/types"; +import type { AppClassProperties, AppState, UIAppState } from "../types"; const isSingleFrameSelected = ( appState: UIAppState, diff --git a/packages/excalidraw/actions/actionGroup.tsx b/packages/excalidraw/actions/actionGroup.tsx index 4e98c59c7..ded2f5b72 100644 --- a/packages/excalidraw/actions/actionGroup.tsx +++ b/packages/excalidraw/actions/actionGroup.tsx @@ -1,29 +1,9 @@ -import { KEYS } from "../keys"; -import { t } from "../i18n"; -import { arrayToMap, getShortcutKey } from "../utils"; -import { register } from "./register"; -import { UngroupIcon, GroupIcon } from "../components/icons"; -import { newElementWith } from "../element/mutateElement"; -import { isSomeElementSelected } from "../scene"; -import { - getSelectedGroupIds, - selectGroup, - selectGroupsForSelectedElements, - getElementsInGroup, - addToGroup, - removeFromSelectedGroups, - isElementInGroup, -} from "../groups"; -import { getNonDeletedElements } from "../element"; -import { randomId } from "../random"; import { ToolButton } from "../components/ToolButton"; -import type { - ExcalidrawElement, - ExcalidrawTextElement, - OrderedExcalidrawElement, -} from "../element/types"; -import type { AppClassProperties, AppState } from "../types"; +import { UngroupIcon, GroupIcon } from "../components/icons"; +import { getNonDeletedElements } from "../element"; +import { newElementWith } from "../element/mutateElement"; import { isBoundToContainer } from "../element/typeChecks"; +import { syncMovedIndices } from "../fractionalIndex"; import { frameAndChildrenSelectedTogether, getElementsInResizingFrame, @@ -33,8 +13,30 @@ import { removeElementsFromFrame, replaceAllElementsInFrame, } from "../frame"; -import { syncMovedIndices } from "../fractionalIndex"; +import { + getSelectedGroupIds, + selectGroup, + selectGroupsForSelectedElements, + getElementsInGroup, + addToGroup, + removeFromSelectedGroups, + isElementInGroup, +} from "../groups"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { randomId } from "../random"; +import { isSomeElementSelected } from "../scene"; import { CaptureUpdateAction } from "../store"; +import { arrayToMap, getShortcutKey } from "../utils"; + +import { register } from "./register"; + +import type { + ExcalidrawElement, + ExcalidrawTextElement, + OrderedExcalidrawElement, +} from "../element/types"; +import type { AppClassProperties, AppState } from "../types"; const allElementsInSameGroup = (elements: readonly ExcalidrawElement[]) => { if (elements.length >= 2) { diff --git a/packages/excalidraw/actions/actionHistory.tsx b/packages/excalidraw/actions/actionHistory.tsx index 299a09f3d..da4f80219 100644 --- a/packages/excalidraw/actions/actionHistory.tsx +++ b/packages/excalidraw/actions/actionHistory.tsx @@ -1,17 +1,18 @@ -import type { Action, ActionResult } from "./types"; -import { UndoIcon, RedoIcon } from "../components/icons"; import { ToolButton } from "../components/ToolButton"; -import { t } from "../i18n"; -import type { History } from "../history"; -import { HistoryChangedEvent } from "../history"; -import type { AppClassProperties, AppState } from "../types"; -import { KEYS, matchKey } from "../keys"; -import { arrayToMap } from "../utils"; +import { UndoIcon, RedoIcon } from "../components/icons"; import { isWindows } from "../constants"; -import type { SceneElementsMap } from "../element/types"; -import type { Store } from "../store"; -import { CaptureUpdateAction } from "../store"; +import { HistoryChangedEvent } from "../history"; import { useEmitter } from "../hooks/useEmitter"; +import { t } from "../i18n"; +import { KEYS, matchKey } from "../keys"; +import { CaptureUpdateAction } from "../store"; +import { arrayToMap } from "../utils"; + +import type { SceneElementsMap } from "../element/types"; +import type { History } from "../history"; +import type { Store } from "../store"; +import type { AppClassProperties, AppState } from "../types"; +import type { Action, ActionResult } from "./types"; const executeHistoryAction = ( app: AppClassProperties, diff --git a/packages/excalidraw/actions/actionLinearEditor.tsx b/packages/excalidraw/actions/actionLinearEditor.tsx index 1f05755b5..f17f0e565 100644 --- a/packages/excalidraw/actions/actionLinearEditor.tsx +++ b/packages/excalidraw/actions/actionLinearEditor.tsx @@ -1,12 +1,14 @@ import { DEFAULT_CATEGORIES } from "../components/CommandPalette/CommandPalette"; +import { ToolButton } from "../components/ToolButton"; +import { lineEditorIcon } from "../components/icons"; import { LinearElementEditor } from "../element/linearElementEditor"; import { isElbowArrow, isLinearElement } from "../element/typeChecks"; -import type { ExcalidrawLinearElement } from "../element/types"; -import { CaptureUpdateAction } from "../store"; -import { register } from "./register"; -import { ToolButton } from "../components/ToolButton"; import { t } from "../i18n"; -import { lineEditorIcon } from "../components/icons"; +import { CaptureUpdateAction } from "../store"; + +import { register } from "./register"; + +import type { ExcalidrawLinearElement } from "../element/types"; export const actionToggleLinearEditor = register({ name: "toggleLinearEditor", diff --git a/packages/excalidraw/actions/actionLink.tsx b/packages/excalidraw/actions/actionLink.tsx index beb95d2c1..91d01b7a6 100644 --- a/packages/excalidraw/actions/actionLink.tsx +++ b/packages/excalidraw/actions/actionLink.tsx @@ -1,12 +1,13 @@ +import { ToolButton } from "../components/ToolButton"; import { getContextMenuLabel } from "../components/hyperlink/Hyperlink"; import { LinkIcon } from "../components/icons"; -import { ToolButton } from "../components/ToolButton"; import { isEmbeddableElement } from "../element/typeChecks"; import { t } from "../i18n"; import { KEYS } from "../keys"; import { getSelectedElements } from "../scene"; import { CaptureUpdateAction } from "../store"; import { getShortcutKey } from "../utils"; + import { register } from "./register"; export const actionLink = register({ diff --git a/packages/excalidraw/actions/actionMenu.tsx b/packages/excalidraw/actions/actionMenu.tsx index 9e71fe255..15b763cb9 100644 --- a/packages/excalidraw/actions/actionMenu.tsx +++ b/packages/excalidraw/actions/actionMenu.tsx @@ -1,11 +1,12 @@ -import { HamburgerMenuIcon, HelpIconThin, palette } from "../components/icons"; import { ToolButton } from "../components/ToolButton"; -import { t } from "../i18n"; +import { HamburgerMenuIcon, HelpIconThin, palette } from "../components/icons"; import { showSelectedShapeActions, getNonDeletedElements } from "../element"; -import { register } from "./register"; +import { t } from "../i18n"; import { KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; +import { register } from "./register"; + export const actionToggleCanvasMenu = register({ name: "toggleCanvasMenu", label: "buttons.menu", diff --git a/packages/excalidraw/actions/actionNavigate.tsx b/packages/excalidraw/actions/actionNavigate.tsx index 48037200c..738386839 100644 --- a/packages/excalidraw/actions/actionNavigate.tsx +++ b/packages/excalidraw/actions/actionNavigate.tsx @@ -1,6 +1,7 @@ +import clsx from "clsx"; + import { getClientColor } from "../clients"; import { Avatar } from "../components/Avatar"; -import type { GoToCollaboratorComponentProps } from "../components/UserList"; import { eyeIcon, microphoneIcon, @@ -8,9 +9,11 @@ import { } from "../components/icons"; import { t } from "../i18n"; import { CaptureUpdateAction } from "../store"; -import type { Collaborator } from "../types"; + import { register } from "./register"; -import clsx from "clsx"; + +import type { GoToCollaboratorComponentProps } from "../components/UserList"; +import type { Collaborator } from "../types"; export const actionGoToCollaborator = register({ name: "goToCollaborator", diff --git a/packages/excalidraw/actions/actionProperties.test.tsx b/packages/excalidraw/actions/actionProperties.test.tsx index 80d2ca257..c5467bb94 100644 --- a/packages/excalidraw/actions/actionProperties.test.tsx +++ b/packages/excalidraw/actions/actionProperties.test.tsx @@ -1,11 +1,12 @@ -import React from "react"; -import { Excalidraw } from "../index"; import { queryByTestId } from "@testing-library/react"; -import { render } from "../tests/test-utils"; -import { UI } from "../tests/helpers/ui"; -import { API } from "../tests/helpers/api"; +import React from "react"; + import { COLOR_PALETTE, DEFAULT_ELEMENT_BACKGROUND_PICKS } from "../colors"; import { FONT_FAMILY, STROKE_WIDTH } from "../constants"; +import { Excalidraw } from "../index"; +import { API } from "../tests/helpers/api"; +import { UI } from "../tests/helpers/ui"; +import { render } from "../tests/test-utils"; describe("element locking", () => { beforeEach(async () => { diff --git a/packages/excalidraw/actions/actionProperties.tsx b/packages/excalidraw/actions/actionProperties.tsx index 0c2ad3bab..1e24d9bed 100644 --- a/packages/excalidraw/actions/actionProperties.tsx +++ b/packages/excalidraw/actions/actionProperties.tsx @@ -1,20 +1,23 @@ +import { pointFrom } from "@excalidraw/math"; import { useEffect, useMemo, useRef, useState } from "react"; -import type { AppClassProperties, AppState, Primitive } from "../types"; -import type { CaptureUpdateActionType } from "../store"; + +import type { LocalPoint } from "@excalidraw/math"; + +import { trackEvent } from "../analytics"; import { DEFAULT_ELEMENT_BACKGROUND_COLOR_PALETTE, DEFAULT_ELEMENT_BACKGROUND_PICKS, DEFAULT_ELEMENT_STROKE_COLOR_PALETTE, DEFAULT_ELEMENT_STROKE_PICKS, } from "../colors"; -import { trackEvent } from "../analytics"; import { ButtonIconSelect } from "../components/ButtonIconSelect"; import { ColorPicker } from "../components/ColorPicker/ColorPicker"; -import { IconPicker } from "../components/IconPicker"; import { FontPicker } from "../components/FontPicker/FontPicker"; +import { IconPicker } from "../components/IconPicker"; // TODO barnabasmolnar/editor-redesign // TextAlignTopIcon, TextAlignBottomIcon,TextAlignMiddleIcon, // ArrowHead icons +import { Range } from "../components/Range"; import { ArrowheadArrowIcon, ArrowheadBarIcon, @@ -71,6 +74,14 @@ import { isTextElement, redrawTextBoundingBox, } from "../element"; +import { + bindLinearElement, + bindPointToSnapToElementOutline, + calculateFixedPointForElbowArrowBinding, + getHoveredElementForBinding, + updateBoundElements, +} from "../element/binding"; +import { LinearElementEditor } from "../element/linearElementEditor"; import { mutateElement, newElementWith } from "../element/mutateElement"; import { getBoundTextElement } from "../element/textElement"; import { @@ -80,17 +91,7 @@ import { isLinearElement, isUsingAdaptiveRadius, } from "../element/typeChecks"; -import type { - Arrowhead, - ExcalidrawBindableElement, - ExcalidrawElement, - ExcalidrawLinearElement, - ExcalidrawTextElement, - FontFamilyValues, - TextAlign, - VerticalAlign, - NonDeletedSceneElementsMap, -} from "../element/types"; +import { Fonts, getLineHeight } from "../fonts"; import { getLanguage, t } from "../i18n"; import { KEYS } from "../keys"; import { randomInteger } from "../random"; @@ -102,26 +103,29 @@ import { isSomeElementSelected, } from "../scene"; import { hasStrokeColor } from "../scene/comparisons"; +import { CaptureUpdateAction } from "../store"; import { arrayToMap, getFontFamilyString, getShortcutKey, tupleToCoors, } from "../utils"; + import { register } from "./register"; -import { CaptureUpdateAction } from "../store"; -import { Fonts, getLineHeight } from "../fonts"; -import { - bindLinearElement, - bindPointToSnapToElementOutline, - calculateFixedPointForElbowArrowBinding, - getHoveredElementForBinding, - updateBoundElements, -} from "../element/binding"; -import { LinearElementEditor } from "../element/linearElementEditor"; -import type { LocalPoint } from "@excalidraw/math"; -import { pointFrom } from "@excalidraw/math"; -import { Range } from "../components/Range"; + +import type { + Arrowhead, + ExcalidrawBindableElement, + ExcalidrawElement, + ExcalidrawLinearElement, + ExcalidrawTextElement, + FontFamilyValues, + TextAlign, + VerticalAlign, + NonDeletedSceneElementsMap, +} from "../element/types"; +import type { CaptureUpdateActionType } from "../store"; +import type { AppClassProperties, AppState, Primitive } from "../types"; const FONT_SIZE_RELATIVE_INCREASE_STEP = 0.1; diff --git a/packages/excalidraw/actions/actionSelectAll.ts b/packages/excalidraw/actions/actionSelectAll.ts index 61c278053..5f6d7eabc 100644 --- a/packages/excalidraw/actions/actionSelectAll.ts +++ b/packages/excalidraw/actions/actionSelectAll.ts @@ -1,13 +1,15 @@ -import { KEYS } from "../keys"; -import { register } from "./register"; -import { selectGroupsForSelectedElements } from "../groups"; -import { getNonDeletedElements, isTextElement } from "../element"; -import type { ExcalidrawElement } from "../element/types"; -import { isLinearElement } from "../element/typeChecks"; -import { LinearElementEditor } from "../element/linearElementEditor"; import { selectAllIcon } from "../components/icons"; +import { getNonDeletedElements, isTextElement } from "../element"; +import { LinearElementEditor } from "../element/linearElementEditor"; +import { isLinearElement } from "../element/typeChecks"; +import { selectGroupsForSelectedElements } from "../groups"; +import { KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; +import { register } from "./register"; + +import type { ExcalidrawElement } from "../element/types"; + export const actionSelectAll = register({ name: "selectAll", label: "labels.selectAll", diff --git a/packages/excalidraw/actions/actionStyles.ts b/packages/excalidraw/actions/actionStyles.ts index 01f804062..ea517c442 100644 --- a/packages/excalidraw/actions/actionStyles.ts +++ b/packages/excalidraw/actions/actionStyles.ts @@ -1,17 +1,15 @@ -import { - isTextElement, - isExcalidrawElement, - redrawTextBoundingBox, -} from "../element"; -import { CODES, KEYS } from "../keys"; -import { t } from "../i18n"; -import { register } from "./register"; -import { newElementWith } from "../element/mutateElement"; +import { paintIcon } from "../components/icons"; import { DEFAULT_FONT_SIZE, DEFAULT_FONT_FAMILY, DEFAULT_TEXT_ALIGN, } from "../constants"; +import { + isTextElement, + isExcalidrawElement, + redrawTextBoundingBox, +} from "../element"; +import { newElementWith } from "../element/mutateElement"; import { getBoundTextElement } from "../element/textElement"; import { hasBoundTextElement, @@ -20,11 +18,15 @@ import { isFrameLikeElement, isArrowElement, } from "../element/typeChecks"; -import { getSelectedElements } from "../scene"; -import type { ExcalidrawTextElement } from "../element/types"; -import { paintIcon } from "../components/icons"; -import { CaptureUpdateAction } from "../store"; import { getLineHeight } from "../fonts"; +import { t } from "../i18n"; +import { CODES, KEYS } from "../keys"; +import { getSelectedElements } from "../scene"; +import { CaptureUpdateAction } from "../store"; + +import { register } from "./register"; + +import type { ExcalidrawTextElement } from "../element/types"; // `copiedStyles` is exported only for tests. export let copiedStyles: string = "{}"; diff --git a/packages/excalidraw/actions/actionTextAutoResize.ts b/packages/excalidraw/actions/actionTextAutoResize.ts index 29f54c9a7..b9ad7783f 100644 --- a/packages/excalidraw/actions/actionTextAutoResize.ts +++ b/packages/excalidraw/actions/actionTextAutoResize.ts @@ -3,10 +3,12 @@ import { newElementWith } from "../element/mutateElement"; import { measureText } from "../element/textMeasurements"; import { getSelectedElements } from "../scene"; import { CaptureUpdateAction } from "../store"; -import type { AppClassProperties } from "../types"; import { getFontString } from "../utils"; + import { register } from "./register"; +import type { AppClassProperties } from "../types"; + export const actionTextAutoResize = register({ name: "autoResize", label: "labels.autoResize", diff --git a/packages/excalidraw/actions/actionToggleGridMode.tsx b/packages/excalidraw/actions/actionToggleGridMode.tsx index 69d657057..98360e843 100644 --- a/packages/excalidraw/actions/actionToggleGridMode.tsx +++ b/packages/excalidraw/actions/actionToggleGridMode.tsx @@ -1,9 +1,11 @@ -import { CODES, KEYS } from "../keys"; -import { register } from "./register"; -import type { AppState } from "../types"; import { gridIcon } from "../components/icons"; +import { CODES, KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; +import { register } from "./register"; + +import type { AppState } from "../types"; + export const actionToggleGridMode = register({ name: "gridMode", icon: gridIcon, diff --git a/packages/excalidraw/actions/actionToggleObjectsSnapMode.tsx b/packages/excalidraw/actions/actionToggleObjectsSnapMode.tsx index 1ae3cbe0b..d51124132 100644 --- a/packages/excalidraw/actions/actionToggleObjectsSnapMode.tsx +++ b/packages/excalidraw/actions/actionToggleObjectsSnapMode.tsx @@ -1,6 +1,7 @@ import { magnetIcon } from "../components/icons"; import { CODES, KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; + import { register } from "./register"; export const actionToggleObjectsSnapMode = register({ diff --git a/packages/excalidraw/actions/actionToggleSearchMenu.ts b/packages/excalidraw/actions/actionToggleSearchMenu.ts index 9261e79c4..75d9074c8 100644 --- a/packages/excalidraw/actions/actionToggleSearchMenu.ts +++ b/packages/excalidraw/actions/actionToggleSearchMenu.ts @@ -1,9 +1,11 @@ -import { KEYS } from "../keys"; -import { register } from "./register"; -import type { AppState } from "../types"; import { searchIcon } from "../components/icons"; -import { CaptureUpdateAction } from "../store"; import { CANVAS_SEARCH_TAB, CLASSES, DEFAULT_SIDEBAR } from "../constants"; +import { KEYS } from "../keys"; +import { CaptureUpdateAction } from "../store"; + +import { register } from "./register"; + +import type { AppState } from "../types"; export const actionToggleSearchMenu = register({ name: "searchMenu", diff --git a/packages/excalidraw/actions/actionToggleStats.tsx b/packages/excalidraw/actions/actionToggleStats.tsx index e28d099ae..d0cdc64a3 100644 --- a/packages/excalidraw/actions/actionToggleStats.tsx +++ b/packages/excalidraw/actions/actionToggleStats.tsx @@ -1,8 +1,9 @@ -import { register } from "./register"; -import { CODES, KEYS } from "../keys"; import { abacusIcon } from "../components/icons"; +import { CODES, KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; +import { register } from "./register"; + export const actionToggleStats = register({ name: "stats", label: "stats.fullTitle", diff --git a/packages/excalidraw/actions/actionToggleViewMode.tsx b/packages/excalidraw/actions/actionToggleViewMode.tsx index cae3b095e..055135263 100644 --- a/packages/excalidraw/actions/actionToggleViewMode.tsx +++ b/packages/excalidraw/actions/actionToggleViewMode.tsx @@ -1,6 +1,7 @@ import { eyeIcon } from "../components/icons"; import { CODES, KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; + import { register } from "./register"; export const actionToggleViewMode = register({ diff --git a/packages/excalidraw/actions/actionToggleZenMode.tsx b/packages/excalidraw/actions/actionToggleZenMode.tsx index 31afd3f3a..31c72bf95 100644 --- a/packages/excalidraw/actions/actionToggleZenMode.tsx +++ b/packages/excalidraw/actions/actionToggleZenMode.tsx @@ -1,6 +1,7 @@ import { coffeeIcon } from "../components/icons"; import { CODES, KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; + import { register } from "./register"; export const actionToggleZenMode = register({ diff --git a/packages/excalidraw/actions/actionZindex.tsx b/packages/excalidraw/actions/actionZindex.tsx index 4097b2df1..82d3d77da 100644 --- a/packages/excalidraw/actions/actionZindex.tsx +++ b/packages/excalidraw/actions/actionZindex.tsx @@ -1,13 +1,3 @@ -import { - moveOneLeft, - moveOneRight, - moveAllLeft, - moveAllRight, -} from "../zindex"; -import { KEYS, CODES } from "../keys"; -import { t } from "../i18n"; -import { getShortcutKey } from "../utils"; -import { register } from "./register"; import { BringForwardIcon, BringToFrontIcon, @@ -15,7 +5,18 @@ import { SendToBackIcon, } from "../components/icons"; import { isDarwin } from "../constants"; +import { t } from "../i18n"; +import { KEYS, CODES } from "../keys"; import { CaptureUpdateAction } from "../store"; +import { getShortcutKey } from "../utils"; +import { + moveOneLeft, + moveOneRight, + moveAllLeft, + moveAllRight, +} from "../zindex"; + +import { register } from "./register"; export const actionSendBackward = register({ name: "sendBackward", diff --git a/packages/excalidraw/actions/manager.tsx b/packages/excalidraw/actions/manager.tsx index f37843800..d3609640e 100644 --- a/packages/excalidraw/actions/manager.tsx +++ b/packages/excalidraw/actions/manager.tsx @@ -1,4 +1,13 @@ import React from "react"; + +import { trackEvent } from "../analytics"; +import { isPromiseLike } from "../utils"; + +import type { + ExcalidrawElement, + OrderedExcalidrawElement, +} from "../element/types"; +import type { AppClassProperties, AppState } from "../types"; import type { Action, UpdaterFn, @@ -7,13 +16,6 @@ import type { PanelComponentProps, ActionSource, } from "./types"; -import type { - ExcalidrawElement, - OrderedExcalidrawElement, -} from "../element/types"; -import type { AppClassProperties, AppState } from "../types"; -import { trackEvent } from "../analytics"; -import { isPromiseLike } from "../utils"; const trackAction = ( action: Action, diff --git a/packages/excalidraw/actions/shortcuts.ts b/packages/excalidraw/actions/shortcuts.ts index 451609dff..89a7c5ae2 100644 --- a/packages/excalidraw/actions/shortcuts.ts +++ b/packages/excalidraw/actions/shortcuts.ts @@ -1,7 +1,8 @@ import { isDarwin } from "../constants"; import { t } from "../i18n"; -import type { SubtypeOf } from "../utility-types"; import { getShortcutKey } from "../utils"; + +import type { SubtypeOf } from "../utility-types"; import type { ActionName } from "./types"; export type ShortcutName = diff --git a/packages/excalidraw/actions/types.ts b/packages/excalidraw/actions/types.ts index 71ac9f4ab..c30f53f5e 100644 --- a/packages/excalidraw/actions/types.ts +++ b/packages/excalidraw/actions/types.ts @@ -1,8 +1,8 @@ -import type React from "react"; import type { ExcalidrawElement, OrderedExcalidrawElement, } from "../element/types"; +import type { CaptureUpdateActionType } from "../store"; import type { AppClassProperties, AppState, @@ -10,7 +10,7 @@ import type { BinaryFiles, UIAppState, } from "../types"; -import type { CaptureUpdateActionType } from "../store"; +import type React from "react"; export type ActionSource = | "ui" diff --git a/packages/excalidraw/align.ts b/packages/excalidraw/align.ts index 113ba274c..36e5d6603 100644 --- a/packages/excalidraw/align.ts +++ b/packages/excalidraw/align.ts @@ -1,9 +1,10 @@ -import type { ElementsMap, ExcalidrawElement } from "./element/types"; -import { mutateElement } from "./element/mutateElement"; -import type { BoundingBox } from "./element/bounds"; -import { getCommonBoundingBox } from "./element/bounds"; -import { getMaximumGroups } from "./groups"; import { updateBoundElements } from "./element/binding"; +import { getCommonBoundingBox } from "./element/bounds"; +import { mutateElement } from "./element/mutateElement"; +import { getMaximumGroups } from "./groups"; + +import type { BoundingBox } from "./element/bounds"; +import type { ElementsMap, ExcalidrawElement } from "./element/types"; import type Scene from "./scene/Scene"; export interface Alignment { diff --git a/packages/excalidraw/animated-trail.ts b/packages/excalidraw/animated-trail.ts index 97a005461..a20460771 100644 --- a/packages/excalidraw/animated-trail.ts +++ b/packages/excalidraw/animated-trail.ts @@ -1,10 +1,13 @@ -import type { LaserPointerOptions } from "@excalidraw/laser-pointer"; import { LaserPointer } from "@excalidraw/laser-pointer"; -import type { AnimationFrameHandler } from "./animation-frame-handler"; -import type { AppState } from "./types"; -import { getSvgPathFromStroke, sceneCoordsToViewportCoords } from "./utils"; -import type App from "./components/App"; + +import type { LaserPointerOptions } from "@excalidraw/laser-pointer"; + import { SVG_NS } from "./constants"; +import { getSvgPathFromStroke, sceneCoordsToViewportCoords } from "./utils"; + +import type { AnimationFrameHandler } from "./animation-frame-handler"; +import type App from "./components/App"; +import type { AppState } from "./types"; export interface Trail { start(container: SVGSVGElement): void; diff --git a/packages/excalidraw/appState.ts b/packages/excalidraw/appState.ts index 38b85ce29..0a5eca937 100644 --- a/packages/excalidraw/appState.ts +++ b/packages/excalidraw/appState.ts @@ -11,6 +11,7 @@ import { THEME, DEFAULT_GRID_STEP, } from "./constants"; + import type { AppState, NormalizedZoomValue } from "./types"; const defaultExportScale = EXPORT_SCALES.includes(devicePixelRatio) diff --git a/packages/excalidraw/change.ts b/packages/excalidraw/change.ts index 1cbf39e89..206f3dcc7 100644 --- a/packages/excalidraw/change.ts +++ b/packages/excalidraw/change.ts @@ -1,5 +1,4 @@ import { ENV } from "./constants"; -import type { BindableProp, BindingProp } from "./element/binding"; import { BoundElement, BindableElement, @@ -7,7 +6,6 @@ import { updateBoundElements, } from "./element/binding"; import { LinearElementEditor } from "./element/linearElementEditor"; -import type { ElementUpdate } from "./element/mutateElement"; import { mutateElement, newElementWith } from "./element/mutateElement"; import { getBoundTextElementId, @@ -20,6 +18,19 @@ import { isImageElement, isTextElement, } from "./element/typeChecks"; +import { orderByFractionalIndex, syncMovedIndices } from "./fractionalIndex"; +import { getNonDeletedGroupIds } from "./groups"; +import { getObservedAppState } from "./store"; +import { + arrayToMap, + arrayToObject, + assertNever, + isShallowEqual, + toBrandedType, +} from "./utils"; + +import type { BindableProp, BindingProp } from "./element/binding"; +import type { ElementUpdate } from "./element/mutateElement"; import type { ExcalidrawElement, ExcalidrawImageElement, @@ -30,9 +41,6 @@ import type { OrderedExcalidrawElement, SceneElementsMap, } from "./element/types"; -import { orderByFractionalIndex, syncMovedIndices } from "./fractionalIndex"; -import { getNonDeletedGroupIds } from "./groups"; -import { getObservedAppState } from "./store"; import type { AppState, ObservedAppState, @@ -40,13 +48,6 @@ import type { ObservedStandaloneAppState, } from "./types"; import type { SubtypeOf, ValueOf } from "./utility-types"; -import { - arrayToMap, - arrayToObject, - assertNever, - isShallowEqual, - toBrandedType, -} from "./utils"; /** * Represents the difference between two objects of the same type. diff --git a/packages/excalidraw/charts.test.ts b/packages/excalidraw/charts.test.ts index fcd8823a9..94fa92fa0 100644 --- a/packages/excalidraw/charts.test.ts +++ b/packages/excalidraw/charts.test.ts @@ -1,6 +1,7 @@ -import type { Spreadsheet } from "./charts"; import { tryParseCells, tryParseNumber, VALID_SPREADSHEET } from "./charts"; +import type { Spreadsheet } from "./charts"; + describe("charts", () => { describe("tryParseNumber", () => { it.each<[string, number]>([ diff --git a/packages/excalidraw/charts.ts b/packages/excalidraw/charts.ts index 65d17e228..e54c55f28 100644 --- a/packages/excalidraw/charts.ts +++ b/packages/excalidraw/charts.ts @@ -1,5 +1,7 @@ -import type { Radians } from "@excalidraw/math"; import { pointFrom } from "@excalidraw/math"; + +import type { Radians } from "@excalidraw/math"; + import { COLOR_PALETTE, DEFAULT_CHART_COLOR_INDEX, @@ -11,9 +13,10 @@ import { VERTICAL_ALIGN, } from "./constants"; import { newElement, newLinearElement, newTextElement } from "./element"; -import type { NonDeletedExcalidrawElement } from "./element/types"; import { randomId } from "./random"; +import type { NonDeletedExcalidrawElement } from "./element/types"; + export type ChartElements = readonly NonDeletedExcalidrawElement[]; const BAR_WIDTH = 32; diff --git a/packages/excalidraw/clients.ts b/packages/excalidraw/clients.ts index 29d240011..6cf4613a8 100644 --- a/packages/excalidraw/clients.ts +++ b/packages/excalidraw/clients.ts @@ -6,6 +6,7 @@ import { UserIdleState, } from "./constants"; import { roundRect } from "./renderer/roundRect"; + import type { InteractiveCanvasRenderConfig } from "./scene/types"; import type { Collaborator, diff --git a/packages/excalidraw/clipboard.ts b/packages/excalidraw/clipboard.ts index 296a3415a..1b0e9942a 100644 --- a/packages/excalidraw/clipboard.ts +++ b/packages/excalidraw/clipboard.ts @@ -1,25 +1,26 @@ -import type { - ExcalidrawElement, - NonDeletedExcalidrawElement, -} from "./element/types"; -import type { BinaryFiles } from "./types"; -import type { Spreadsheet } from "./charts"; import { tryParseSpreadsheet, VALID_SPREADSHEET } from "./charts"; import { ALLOWED_PASTE_MIME_TYPES, EXPORT_DATA_TYPES, MIME_TYPES, } from "./constants"; +import { createFile, isSupportedImageFileType } from "./data/blob"; +import { mutateElement } from "./element/mutateElement"; +import { deepCopyElement } from "./element/newElement"; import { isFrameLikeElement, isInitializedImageElement, } from "./element/typeChecks"; -import { deepCopyElement } from "./element/newElement"; -import { mutateElement } from "./element/mutateElement"; +import { ExcalidrawError } from "./errors"; import { getContainingFrame } from "./frame"; import { arrayToMap, isMemberOf, isPromiseLike } from "./utils"; -import { createFile, isSupportedImageFileType } from "./data/blob"; -import { ExcalidrawError } from "./errors"; + +import type { Spreadsheet } from "./charts"; +import type { + ExcalidrawElement, + NonDeletedExcalidrawElement, +} from "./element/types"; +import type { BinaryFiles } from "./types"; type ElementsClipboard = { type: typeof EXPORT_DATA_TYPES.excalidrawClipboard; diff --git a/packages/excalidraw/colors.ts b/packages/excalidraw/colors.ts index e4cd67a94..84d04bcf4 100644 --- a/packages/excalidraw/colors.ts +++ b/packages/excalidraw/colors.ts @@ -1,4 +1,5 @@ import oc from "open-color"; + import type { Merge } from "./utility-types"; // FIXME can't put to utils.ts rn because of circular dependency diff --git a/packages/excalidraw/components/Actions.tsx b/packages/excalidraw/components/Actions.tsx index 82deee1a8..c74c1ad85 100644 --- a/packages/excalidraw/components/Actions.tsx +++ b/packages/excalidraw/components/Actions.tsx @@ -1,13 +1,25 @@ +import clsx from "clsx"; import { useState } from "react"; -import type { ActionManager } from "../actions/manager"; -import type { - ExcalidrawElement, - ExcalidrawElementType, - NonDeletedElementsMap, - NonDeletedSceneElementsMap, -} from "../element/types"; + +import { actionToggleZenMode } from "../actions"; + +import { KEYS } from "../keys"; +import { CLASSES } from "../constants"; +import { alignActionsPredicate } from "../actions/actionAlign"; +import { trackEvent } from "../analytics"; +import { useTunnels } from "../context/tunnels"; +import { + shouldAllowVerticalAlign, + suppportsHorizontalAlign, +} from "../element/textElement"; +import { + hasBoundTextElement, + isElbowArrow, + isImageElement, + isLinearElement, + isTextElement, +} from "../element/typeChecks"; import { t } from "../i18n"; -import { useDevice } from "./App"; import { canChangeRoundness, canHaveArrowheads, @@ -16,29 +28,16 @@ import { hasStrokeStyle, hasStrokeWidth, } from "../scene"; -import { SHAPES } from "../shapes"; -import type { AppClassProperties, AppProps, UIAppState, Zoom } from "../types"; -import { capitalizeString, isTransparent } from "../utils"; -import Stack from "./Stack"; -import { ToolButton } from "./ToolButton"; import { hasStrokeColor, toolIsArrow } from "../scene/comparisons"; -import { trackEvent } from "../analytics"; -import { - hasBoundTextElement, - isElbowArrow, - isImageElement, - isLinearElement, - isTextElement, -} from "../element/typeChecks"; -import clsx from "clsx"; -import { actionToggleZenMode } from "../actions"; -import { Tooltip } from "./Tooltip"; -import { - shouldAllowVerticalAlign, - suppportsHorizontalAlign, -} from "../element/textElement"; +import { SHAPES } from "../shapes"; +import { capitalizeString, isTransparent } from "../utils"; import "./Actions.scss"; + +import { useDevice } from "./App"; +import Stack from "./Stack"; +import { ToolButton } from "./ToolButton"; +import { Tooltip } from "./Tooltip"; import DropdownMenu from "./dropdownMenu/DropdownMenu"; import { EmbedIcon, @@ -48,10 +47,15 @@ import { laserPointerToolIcon, MagicIcon, } from "./icons"; -import { KEYS } from "../keys"; -import { useTunnels } from "../context/tunnels"; -import { CLASSES } from "../constants"; -import { alignActionsPredicate } from "../actions/actionAlign"; + +import type { + ExcalidrawElement, + ExcalidrawElementType, + NonDeletedElementsMap, + NonDeletedSceneElementsMap, +} from "../element/types"; +import type { AppClassProperties, AppProps, UIAppState, Zoom } from "../types"; +import type { ActionManager } from "../actions/manager"; export const canChangeStrokeColor = ( appState: UIAppState, @@ -353,25 +357,6 @@ export const ShapesSwitcher = ({ title={t("toolBar.extraTools")} > {extraToolsIcon} - {app.props.aiEnabled !== false && ( -
- AI -
- )} setIsExtraToolsMenuOpen(false)} diff --git a/packages/excalidraw/components/ActiveConfirmDialog.tsx b/packages/excalidraw/components/ActiveConfirmDialog.tsx index 699fbc61f..00c6ad579 100644 --- a/packages/excalidraw/components/ActiveConfirmDialog.tsx +++ b/packages/excalidraw/components/ActiveConfirmDialog.tsx @@ -1,6 +1,7 @@ import { actionClearCanvas } from "../actions"; -import { t } from "../i18n"; import { atom, useAtom } from "../editor-jotai"; +import { t } from "../i18n"; + import { useExcalidrawActionManager } from "./App"; import ConfirmDialog from "./ConfirmDialog"; diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 011ab6627..466517050 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -1,10 +1,26 @@ +import { + clamp, + pointFrom, + pointDistance, + vector, + pointRotateRads, + vectorScale, + vectorFromPoint, + vectorSubtract, + vectorDot, + vectorNormalize, +} from "@excalidraw/math"; +import { isPointInShape } from "@excalidraw/utils/collision"; +import { getSelectionBoxShape } from "@excalidraw/utils/geometry/shape"; +import clsx from "clsx"; +import throttle from "lodash.throttle"; +import { nanoid } from "nanoid"; import React, { useContext } from "react"; import { flushSync } from "react-dom"; - -import type { RoughCanvas } from "roughjs/bin/canvas"; import rough from "roughjs/bin/rough"; -import clsx from "clsx"; -import { nanoid } from "nanoid"; + +import type { LocalPoint, Radians } from "@excalidraw/math"; + import { actionAddToLibrary, actionBringForward, @@ -37,17 +53,29 @@ import { actionToggleObjectsSnapMode, actionToggleCropEditor, } from "../actions"; +import { actionWrapTextInContainer } from "../actions/actionBoundText"; +import { actionToggleHandTool, zoomToFit } from "../actions/actionCanvas"; +import { actionPaste } from "../actions/actionClipboard"; +import { actionCopyElementLink } from "../actions/actionElementLink"; +import { actionUnlockAllElements } from "../actions/actionElementLock"; +import { + actionRemoveAllElementsFromFrame, + actionSelectAllElementsInFrame, + actionWrapSelectionInFrame, +} from "../actions/actionFrame"; import { createRedoAction, createUndoAction } from "../actions/actionHistory"; +import { actionTextAutoResize } from "../actions/actionTextAutoResize"; +import { actionToggleViewMode } from "../actions/actionToggleViewMode"; import { ActionManager } from "../actions/manager"; import { actions } from "../actions/register"; -import type { Action, ActionResult } from "../actions/types"; +import { getShortcutFromShortcutName } from "../actions/shortcuts"; import { trackEvent } from "../analytics"; +import { AnimationFrameHandler } from "../animation-frame-handler"; import { getDefaultAppState, isEraserActive, isHandToolActive, } from "../appState"; -import type { PastedMixedContent } from "../clipboard"; import { copyTextToSystemClipboard, parseClipboard } from "../clipboard"; import { APP_NAME, @@ -92,7 +120,6 @@ import { isSafari, type EXPORT_IMAGE_TYPES, } from "../constants"; -import type { ExportedElements } from "../data"; import { exportCanvas, loadFromBlob } from "../data"; import Library, { distributeLibraryItemsOnSquareGrid } from "../data/library"; import { restore, restoreElements } from "../data/restore"; @@ -171,30 +198,6 @@ import { isLinearSwitchableElement, isLinearSwitchableToolType, } from "../element/typeChecks"; -import type { - ExcalidrawBindableElement, - ExcalidrawElement, - ExcalidrawFreeDrawElement, - ExcalidrawGenericElement, - ExcalidrawLinearElement, - ExcalidrawTextElement, - NonDeleted, - InitializedExcalidrawImageElement, - ExcalidrawImageElement, - FileId, - NonDeletedExcalidrawElement, - ExcalidrawTextContainer, - ExcalidrawFrameLikeElement, - ExcalidrawMagicFrameElement, - ExcalidrawIframeLikeElement, - IframeData, - ExcalidrawIframeElement, - ExcalidrawEmbeddableElement, - Ordered, - MagicGenerationData, - ExcalidrawNonSelectionElement, - ExcalidrawArrowElement, -} from "../element/types"; import { getCenter, getDistance } from "../gesture"; import { editGroupForSelectedElement, @@ -228,10 +231,6 @@ import { isSomeElementSelected, } from "../scene"; import Scene from "../scene/Scene"; -import type { - RenderInteractiveSceneCallback, - ScrollBars, -} from "../scene/types"; import { getStateForZoom } from "../scene/zoom"; import { findShapeByKey, @@ -240,36 +239,6 @@ import { getElementShape, isPathALoop, } from "../shapes"; -import { getSelectionBoxShape } from "@excalidraw/utils/geometry/shape"; -import { isPointInShape } from "@excalidraw/utils/collision"; -import type { - AppClassProperties, - AppProps, - AppState, - BinaryFileData, - DataURL, - ExcalidrawImperativeAPI, - BinaryFiles, - Gesture, - GestureEvent, - LibraryItems, - PointerDownState, - SceneData, - Device, - FrameNameBoundsCache, - SidebarName, - SidebarTabName, - KeyboardModifiersObject, - CollaboratorPointer, - ToolType, - OnUserFollowedPayload, - UnsubscribeCallback, - EmbedsValidationStatus, - ElementsPendingErasure, - GenerateDiagramToCode, - NullableGridSize, - Offsets, -} from "../types"; import { debounce, distance, @@ -303,11 +272,6 @@ import { maybeParseEmbedSrc, getEmbedLink, } from "../element/embeddable"; -import type { ContextMenuItems } from "./ContextMenu"; -import { ContextMenu, CONTEXT_MENU_SEPARATOR } from "./ContextMenu"; -import LayerUI from "./LayerUI"; -import { Toast } from "./Toast"; -import { actionToggleViewMode } from "../actions/actionToggleViewMode"; import { dataURLToFile, dataURLToString, @@ -330,8 +294,6 @@ import { normalizeSVG, updateImageCache as _updateImageCache, } from "../element/image"; -import throttle from "lodash.throttle"; -import type { FileSystemHandle } from "../data/filesystem"; import { fileOpen } from "../data/filesystem"; import { bindTextToShapeAfterDuplication, @@ -347,7 +309,6 @@ import { } from "../components/hyperlink/Hyperlink"; import { isLocalLink, normalizeLink, toValidURL } from "../data/url"; import { shouldShowBoundingBox } from "../element/transformHandles"; -import { actionUnlockAllElements } from "../actions/actionElementLock"; import { Fonts, getLineHeight } from "../fonts"; import { getFrameChildren, @@ -370,15 +331,7 @@ import { excludeElementsInFramesFromSelection, makeNextSelectedElementIds, } from "../scene/selection"; -import { actionPaste } from "../actions/actionClipboard"; -import { - actionRemoveAllElementsFromFrame, - actionSelectAllElementsInFrame, - actionWrapSelectionInFrame, -} from "../actions/actionFrame"; -import { actionToggleHandTool, zoomToFit } from "../actions/actionCanvas"; import { editorJotaiStore } from "../editor-jotai"; -import { activeConfirmDialogAtom } from "./ActiveConfirmDialog"; import { ImageSceneDataError } from "../errors"; import { getSnapLinesAtPointer, @@ -393,17 +346,9 @@ import { isGridModeEnabled, getGridPoint, } from "../snapping"; -import { actionWrapTextInContainer } from "../actions/actionBoundText"; -import BraveMeasureTextError from "./BraveMeasureTextError"; -import { activeEyeDropperAtom } from "./EyeDropper"; -import type { ExcalidrawElementSkeleton } from "../data/transform"; import { convertToExcalidrawElements } from "../data/transform"; -import type { ValueOf } from "../utility-types"; -import { isSidebarDockedAtom } from "./Sidebar/Sidebar"; -import { StaticCanvas, InteractiveCanvas } from "./canvases"; import { Renderer } from "../scene/Renderer"; import { ShapeCache } from "../scene/ShapeCache"; -import { SVGLayer } from "./SVGLayer"; import { setEraserCursor, setCursor, @@ -413,11 +358,7 @@ import { import { Emitter } from "../emitter"; import { ElementCanvasButtons } from "../element/ElementCanvasButtons"; import { COLOR_PALETTE } from "../colors"; -import { ElementCanvasButton } from "./MagicButton"; -import { MagicIcon, copyIcon, fullscreenIcon } from "./icons"; -import FollowMode from "./FollowMode/FollowMode"; import { Store, CaptureUpdateAction } from "../store"; -import { AnimationFrameHandler } from "../animation-frame-handler"; import { AnimatedTrail } from "../animated-trail"; import { LaserTrails } from "../laser-trails"; import { withBatchedUpdates, withBatchedUpdatesThrottled } from "../reactUtils"; @@ -430,37 +371,15 @@ import { import { textWysiwyg } from "../element/textWysiwyg"; import { isOverScrollBars } from "../scene/scrollbars"; import { syncInvalidIndices, syncMovedIndices } from "../fractionalIndex"; -import { - isPointHittingLink, - isPointHittingLinkIcon, -} from "./hyperlink/helpers"; -import { getShortcutFromShortcutName } from "../actions/shortcuts"; -import { actionTextAutoResize } from "../actions/actionTextAutoResize"; import { getVisibleSceneBounds } from "../element/bounds"; import { isMaybeMermaidDefinition } from "../mermaid"; -import NewElementCanvas from "./canvases/NewElementCanvas"; import { FlowChartCreator, FlowChartNavigator, getLinkDirectionFromKey, } from "../element/flowchart"; -import { searchItemInFocusAtom } from "./SearchMenu"; -import type { LocalPoint, Radians } from "@excalidraw/math"; -import { - clamp, - pointFrom, - pointDistance, - vector, - pointRotateRads, - vectorScale, - vectorFromPoint, - vectorSubtract, - vectorDot, - vectorNormalize, -} from "@excalidraw/math"; import { cropElement } from "../element/cropElement"; import { wrapText } from "../element/textWrapping"; -import { actionCopyElementLink } from "../actions/actionElementLink"; import { isElementLink, parseElementLinkFromURL } from "../element/elementLink"; import { isMeasureTextSupported, @@ -471,8 +390,93 @@ import { getApproxMinLineHeight, getMinTextElementWidth, } from "../element/textMeasurements"; + import ShapeSwitch from "./ShapeSwitch"; +import { activeConfirmDialogAtom } from "./ActiveConfirmDialog"; +import BraveMeasureTextError from "./BraveMeasureTextError"; +import { ContextMenu, CONTEXT_MENU_SEPARATOR } from "./ContextMenu"; +import { activeEyeDropperAtom } from "./EyeDropper"; +import FollowMode from "./FollowMode/FollowMode"; +import LayerUI from "./LayerUI"; +import { ElementCanvasButton } from "./MagicButton"; +import { SVGLayer } from "./SVGLayer"; +import { searchItemInFocusAtom } from "./SearchMenu"; +import { isSidebarDockedAtom } from "./Sidebar/Sidebar"; +import { StaticCanvas, InteractiveCanvas } from "./canvases"; +import NewElementCanvas from "./canvases/NewElementCanvas"; +import { + isPointHittingLink, + isPointHittingLinkIcon, +} from "./hyperlink/helpers"; +import { MagicIcon, copyIcon, fullscreenIcon } from "./icons"; +import { Toast } from "./Toast"; + +import type { Action, ActionResult } from "../actions/types"; +import type { PastedMixedContent } from "../clipboard"; +import type { ExportedElements } from "../data"; +import type { ContextMenuItems } from "./ContextMenu"; +import type { FileSystemHandle } from "../data/filesystem"; +import type { ExcalidrawElementSkeleton } from "../data/transform"; +import type { + ExcalidrawBindableElement, + ExcalidrawElement, + ExcalidrawFreeDrawElement, + ExcalidrawGenericElement, + ExcalidrawLinearElement, + ExcalidrawTextElement, + NonDeleted, + InitializedExcalidrawImageElement, + ExcalidrawImageElement, + FileId, + NonDeletedExcalidrawElement, + ExcalidrawTextContainer, + ExcalidrawFrameLikeElement, + ExcalidrawMagicFrameElement, + ExcalidrawIframeLikeElement, + IframeData, + ExcalidrawIframeElement, + ExcalidrawEmbeddableElement, + Ordered, + MagicGenerationData, + ExcalidrawNonSelectionElement, + ExcalidrawArrowElement, +} from "../element/types"; +import type { + RenderInteractiveSceneCallback, + ScrollBars, +} from "../scene/types"; +import type { + AppClassProperties, + AppProps, + AppState, + BinaryFileData, + DataURL, + ExcalidrawImperativeAPI, + BinaryFiles, + Gesture, + GestureEvent, + LibraryItems, + PointerDownState, + SceneData, + Device, + FrameNameBoundsCache, + SidebarName, + SidebarTabName, + KeyboardModifiersObject, + CollaboratorPointer, + ToolType, + OnUserFollowedPayload, + UnsubscribeCallback, + EmbedsValidationStatus, + ElementsPendingErasure, + GenerateDiagramToCode, + NullableGridSize, + Offsets, +} from "../types"; +import type { ValueOf } from "../utility-types"; +import type { RoughCanvas } from "roughjs/bin/canvas"; + const AppContext = React.createContext(null!); const AppPropsContext = React.createContext(null!); @@ -8590,21 +8594,78 @@ class App extends React.Component { const elements = this.scene.getElementsIncludingDeleted(); for (const element of elements) { - if ( + const isInSelection = selectedElementIds.has(element.id) || // case: the state.selectedElementIds might not have been // updated yet by the time this mousemove event is fired (element.id === hitElement?.id && - pointerDownState.hit.wasAddedToSelection) + pointerDownState.hit.wasAddedToSelection); + // NOTE (mtolmacs): This is a temporary fix for very large scenes + if ( + Math.abs(element.x) > 1e7 || + Math.abs(element.x) > 1e7 || + Math.abs(element.width) > 1e7 || + Math.abs(element.height) > 1e7 ) { + console.error( + `Alt+dragging element in scene with invalid dimensions`, + element.x, + element.y, + element.width, + element.height, + isInSelection, + ); + + return; + } + + if (isInSelection) { const duplicatedElement = duplicateElement( this.state.editingGroupId, groupIdMap, element, ); + + // NOTE (mtolmacs): This is a temporary fix for very large scenes + if ( + Math.abs(duplicatedElement.x) > 1e7 || + Math.abs(duplicatedElement.x) > 1e7 || + Math.abs(duplicatedElement.width) > 1e7 || + Math.abs(duplicatedElement.height) > 1e7 + ) { + console.error( + `Alt+dragging duplicated element with invalid dimensions`, + duplicatedElement.x, + duplicatedElement.y, + duplicatedElement.width, + duplicatedElement.height, + ); + + return; + } + const origElement = pointerDownState.originalElements.get( element.id, )!; + + // NOTE (mtolmacs): This is a temporary fix for very large scenes + if ( + Math.abs(origElement.x) > 1e7 || + Math.abs(origElement.x) > 1e7 || + Math.abs(origElement.width) > 1e7 || + Math.abs(origElement.height) > 1e7 + ) { + console.error( + `Alt+dragging duplicated element with invalid dimensions`, + origElement.x, + origElement.y, + origElement.width, + origElement.height, + ); + + return; + } + mutateElement(duplicatedElement, { x: origElement.x, y: origElement.y, diff --git a/packages/excalidraw/components/Avatar.tsx b/packages/excalidraw/components/Avatar.tsx index 9ddc319c6..648fb5fce 100644 --- a/packages/excalidraw/components/Avatar.tsx +++ b/packages/excalidraw/components/Avatar.tsx @@ -1,8 +1,9 @@ -import "./Avatar.scss"; - -import React, { useState } from "react"; -import { getNameInitial } from "../clients"; import clsx from "clsx"; +import React, { useState } from "react"; + +import { getNameInitial } from "../clients"; + +import "./Avatar.scss"; type AvatarProps = { onClick: (e: React.MouseEvent) => void; diff --git a/packages/excalidraw/components/Button.tsx b/packages/excalidraw/components/Button.tsx index 779cee582..9512d607f 100644 --- a/packages/excalidraw/components/Button.tsx +++ b/packages/excalidraw/components/Button.tsx @@ -1,6 +1,8 @@ import clsx from "clsx"; import React from "react"; + import { composeEventHandlers } from "../utils"; + import "./Button.scss"; interface ButtonProps diff --git a/packages/excalidraw/components/ButtonIcon.tsx b/packages/excalidraw/components/ButtonIcon.tsx index cbbd73df9..27b4dc3d8 100644 --- a/packages/excalidraw/components/ButtonIcon.tsx +++ b/packages/excalidraw/components/ButtonIcon.tsx @@ -1,9 +1,10 @@ -import { forwardRef } from "react"; -import type { JSX } from "react"; import clsx from "clsx"; +import { forwardRef } from "react"; import "./ButtonIcon.scss"; +import type { JSX } from "react"; + interface ButtonIconProps { icon: JSX.Element; title: string; diff --git a/packages/excalidraw/components/ButtonIconCycle.tsx b/packages/excalidraw/components/ButtonIconCycle.tsx index b73a8ec5a..53c5e12bd 100644 --- a/packages/excalidraw/components/ButtonIconCycle.tsx +++ b/packages/excalidraw/components/ButtonIconCycle.tsx @@ -1,6 +1,7 @@ -import type { JSX } from "react"; import clsx from "clsx"; +import type { JSX } from "react"; + export const ButtonIconCycle = ({ options, value, diff --git a/packages/excalidraw/components/ButtonIconSelect.tsx b/packages/excalidraw/components/ButtonIconSelect.tsx index 26191b50b..45665e4ca 100644 --- a/packages/excalidraw/components/ButtonIconSelect.tsx +++ b/packages/excalidraw/components/ButtonIconSelect.tsx @@ -1,7 +1,9 @@ -import type { JSX } from "react"; import clsx from "clsx"; + import { ButtonIcon } from "./ButtonIcon"; +import type { JSX } from "react"; + // TODO: It might be "clever" to add option.icon to the existing component export const ButtonIconSelect = ( props: { diff --git a/packages/excalidraw/components/CheckboxItem.tsx b/packages/excalidraw/components/CheckboxItem.tsx index 21c5cfafd..9c757eab5 100644 --- a/packages/excalidraw/components/CheckboxItem.tsx +++ b/packages/excalidraw/components/CheckboxItem.tsx @@ -1,5 +1,6 @@ -import React from "react"; import clsx from "clsx"; +import React from "react"; + import { checkIcon } from "./icons"; import "./CheckboxItem.scss"; diff --git a/packages/excalidraw/components/ColorPicker/ColorInput.tsx b/packages/excalidraw/components/ColorPicker/ColorInput.tsx index 837c88709..dc7d572a3 100644 --- a/packages/excalidraw/components/ColorPicker/ColorInput.tsx +++ b/packages/excalidraw/components/ColorPicker/ColorInput.tsx @@ -1,15 +1,18 @@ -import { useCallback, useEffect, useRef, useState } from "react"; -import { getColor } from "./ColorPicker"; -import type { ColorPickerType } from "./colorPickerUtils"; -import { activeColorPickerSectionAtom } from "./colorPickerUtils"; -import { eyeDropperIcon } from "../icons"; -import { useAtom } from "../../editor-jotai"; -import { KEYS } from "../../keys"; -import { activeEyeDropperAtom } from "../EyeDropper"; import clsx from "clsx"; +import { useCallback, useEffect, useRef, useState } from "react"; + +import { useAtom } from "../../editor-jotai"; import { t } from "../../i18n"; -import { useDevice } from "../App"; +import { KEYS } from "../../keys"; import { getShortcutKey } from "../../utils"; +import { useDevice } from "../App"; +import { activeEyeDropperAtom } from "../EyeDropper"; +import { eyeDropperIcon } from "../icons"; + +import { getColor } from "./ColorPicker"; +import { activeColorPickerSectionAtom } from "./colorPickerUtils"; + +import type { ColorPickerType } from "./colorPickerUtils"; interface ColorInputProps { color: string; diff --git a/packages/excalidraw/components/ColorPicker/ColorPicker.tsx b/packages/excalidraw/components/ColorPicker/ColorPicker.tsx index 74d552701..7f6ee8a85 100644 --- a/packages/excalidraw/components/ColorPicker/ColorPicker.tsx +++ b/packages/excalidraw/components/ColorPicker/ColorPicker.tsx @@ -1,26 +1,29 @@ -import { isTransparent } from "../../utils"; -import type { ExcalidrawElement } from "../../element/types"; -import type { AppState } from "../../types"; -import { TopPicks } from "./TopPicks"; -import { ButtonSeparator } from "../ButtonSeparator"; -import { Picker } from "./Picker"; import * as Popover from "@radix-ui/react-popover"; -import type { ColorPickerType } from "./colorPickerUtils"; -import { activeColorPickerSectionAtom } from "./colorPickerUtils"; -import { useExcalidrawContainer } from "../App"; -import type { ColorTuple, ColorPaletteCustom } from "../../colors"; -import { COLOR_PALETTE } from "../../colors"; -import PickerHeading from "./PickerHeading"; -import { t } from "../../i18n"; import clsx from "clsx"; import { useRef } from "react"; + +import { COLOR_PALETTE } from "../../colors"; import { useAtom } from "../../editor-jotai"; -import { ColorInput } from "./ColorInput"; +import { t } from "../../i18n"; +import { isTransparent } from "../../utils"; +import { useExcalidrawContainer } from "../App"; +import { ButtonSeparator } from "../ButtonSeparator"; import { activeEyeDropperAtom } from "../EyeDropper"; import { PropertiesPopover } from "../PropertiesPopover"; +import { ColorInput } from "./ColorInput"; +import { Picker } from "./Picker"; +import PickerHeading from "./PickerHeading"; +import { TopPicks } from "./TopPicks"; +import { activeColorPickerSectionAtom } from "./colorPickerUtils"; + import "./ColorPicker.scss"; +import type { ColorPickerType } from "./colorPickerUtils"; +import type { ColorTuple, ColorPaletteCustom } from "../../colors"; +import type { ExcalidrawElement } from "../../element/types"; +import type { AppState } from "../../types"; + const isValidColor = (color: string) => { const style = new Option().style; style.color = color; diff --git a/packages/excalidraw/components/ColorPicker/CustomColorList.tsx b/packages/excalidraw/components/ColorPicker/CustomColorList.tsx index 5fe1e3e53..2c735102a 100644 --- a/packages/excalidraw/components/ColorPicker/CustomColorList.tsx +++ b/packages/excalidraw/components/ColorPicker/CustomColorList.tsx @@ -1,8 +1,10 @@ import clsx from "clsx"; -import { useAtom } from "../../editor-jotai"; import { useEffect, useRef } from "react"; -import { activeColorPickerSectionAtom } from "./colorPickerUtils"; + +import { useAtom } from "../../editor-jotai"; + import HotkeyLabel from "./HotkeyLabel"; +import { activeColorPickerSectionAtom } from "./colorPickerUtils"; interface CustomColorListProps { colors: string[]; diff --git a/packages/excalidraw/components/ColorPicker/HotkeyLabel.tsx b/packages/excalidraw/components/ColorPicker/HotkeyLabel.tsx index 145060d19..6e4d5e39c 100644 --- a/packages/excalidraw/components/ColorPicker/HotkeyLabel.tsx +++ b/packages/excalidraw/components/ColorPicker/HotkeyLabel.tsx @@ -1,4 +1,5 @@ import React from "react"; + import { getContrastYIQ } from "./colorPickerUtils"; interface HotkeyLabelProps { diff --git a/packages/excalidraw/components/ColorPicker/Picker.tsx b/packages/excalidraw/components/ColorPicker/Picker.tsx index 88d687670..9f311e9c1 100644 --- a/packages/excalidraw/components/ColorPicker/Picker.tsx +++ b/packages/excalidraw/components/ColorPicker/Picker.tsx @@ -1,28 +1,29 @@ import React, { useEffect, useState } from "react"; -import { t } from "../../i18n"; -import type { ExcalidrawElement } from "../../element/types"; -import { ShadeList } from "./ShadeList"; - -import PickerColorList from "./PickerColorList"; +import { + DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX, + DEFAULT_ELEMENT_STROKE_COLOR_INDEX, +} from "../../colors"; +import { EVENT } from "../../constants"; import { useAtom } from "../../editor-jotai"; +import { t } from "../../i18n"; +import { KEYS } from "../../keys"; + import { CustomColorList } from "./CustomColorList"; -import { colorPickerKeyNavHandler } from "./keyboardNavHandlers"; +import PickerColorList from "./PickerColorList"; import PickerHeading from "./PickerHeading"; -import type { ColorPickerType } from "./colorPickerUtils"; +import { ShadeList } from "./ShadeList"; import { activeColorPickerSectionAtom, getColorNameAndShadeFromColor, getMostUsedCustomColors, isCustomColor, } from "./colorPickerUtils"; +import { colorPickerKeyNavHandler } from "./keyboardNavHandlers"; + +import type { ColorPickerType } from "./colorPickerUtils"; import type { ColorPaletteCustom } from "../../colors"; -import { - DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX, - DEFAULT_ELEMENT_STROKE_COLOR_INDEX, -} from "../../colors"; -import { KEYS } from "../../keys"; -import { EVENT } from "../../constants"; +import type { ExcalidrawElement } from "../../element/types"; interface PickerProps { color: string; diff --git a/packages/excalidraw/components/ColorPicker/PickerColorList.tsx b/packages/excalidraw/components/ColorPicker/PickerColorList.tsx index f43559d95..b355228f1 100644 --- a/packages/excalidraw/components/ColorPicker/PickerColorList.tsx +++ b/packages/excalidraw/components/ColorPicker/PickerColorList.tsx @@ -1,15 +1,18 @@ import clsx from "clsx"; -import { useAtom } from "../../editor-jotai"; import { useEffect, useRef } from "react"; + +import { useAtom } from "../../editor-jotai"; +import { t } from "../../i18n"; + +import HotkeyLabel from "./HotkeyLabel"; import { activeColorPickerSectionAtom, colorPickerHotkeyBindings, getColorNameAndShadeFromColor, } from "./colorPickerUtils"; -import HotkeyLabel from "./HotkeyLabel"; + import type { ColorPaletteCustom } from "../../colors"; import type { TranslationKeys } from "../../i18n"; -import { t } from "../../i18n"; interface PickerColorListProps { palette: ColorPaletteCustom; diff --git a/packages/excalidraw/components/ColorPicker/ShadeList.tsx b/packages/excalidraw/components/ColorPicker/ShadeList.tsx index 8d3d4cc2a..35d89ea80 100644 --- a/packages/excalidraw/components/ColorPicker/ShadeList.tsx +++ b/packages/excalidraw/components/ColorPicker/ShadeList.tsx @@ -1,12 +1,15 @@ import clsx from "clsx"; -import { useAtom } from "../../editor-jotai"; import { useEffect, useRef } from "react"; + +import { useAtom } from "../../editor-jotai"; +import { t } from "../../i18n"; + +import HotkeyLabel from "./HotkeyLabel"; import { activeColorPickerSectionAtom, getColorNameAndShadeFromColor, } from "./colorPickerUtils"; -import HotkeyLabel from "./HotkeyLabel"; -import { t } from "../../i18n"; + import type { ColorPaletteCustom } from "../../colors"; interface ShadeListProps { diff --git a/packages/excalidraw/components/ColorPicker/TopPicks.tsx b/packages/excalidraw/components/ColorPicker/TopPicks.tsx index 5c69d1e43..9bd8fdb9a 100644 --- a/packages/excalidraw/components/ColorPicker/TopPicks.tsx +++ b/packages/excalidraw/components/ColorPicker/TopPicks.tsx @@ -1,11 +1,13 @@ import clsx from "clsx"; -import type { ColorPickerType } from "./colorPickerUtils"; + import { DEFAULT_CANVAS_BACKGROUND_PICKS, DEFAULT_ELEMENT_BACKGROUND_PICKS, DEFAULT_ELEMENT_STROKE_PICKS, } from "../../colors"; +import type { ColorPickerType } from "./colorPickerUtils"; + interface TopPicksProps { onChange: (color: string) => void; type: ColorPickerType; diff --git a/packages/excalidraw/components/ColorPicker/colorPickerUtils.ts b/packages/excalidraw/components/ColorPicker/colorPickerUtils.ts index 2733b7aba..bbb4e587d 100644 --- a/packages/excalidraw/components/ColorPicker/colorPickerUtils.ts +++ b/packages/excalidraw/components/ColorPicker/colorPickerUtils.ts @@ -1,8 +1,9 @@ -import type { ExcalidrawElement } from "../../element/types"; -import type { ColorPickerColor, ColorPaletteCustom } from "../../colors"; import { MAX_CUSTOM_COLORS_USED_IN_CANVAS } from "../../colors"; import { atom } from "../../editor-jotai"; +import type { ColorPickerColor, ColorPaletteCustom } from "../../colors"; +import type { ExcalidrawElement } from "../../element/types"; + export const getColorNameAndShadeFromColor = ({ palette, color, diff --git a/packages/excalidraw/components/ColorPicker/keyboardNavHandlers.ts b/packages/excalidraw/components/ColorPicker/keyboardNavHandlers.ts index 7767692ed..c4e321700 100644 --- a/packages/excalidraw/components/ColorPicker/keyboardNavHandlers.ts +++ b/packages/excalidraw/components/ColorPicker/keyboardNavHandlers.ts @@ -1,16 +1,18 @@ +import { COLORS_PER_ROW, COLOR_PALETTE } from "../../colors"; import { KEYS } from "../../keys"; + +import { + colorPickerHotkeyBindings, + getColorNameAndShadeFromColor, +} from "./colorPickerUtils"; + +import type { ActiveColorPickerSectionAtomType } from "./colorPickerUtils"; import type { ColorPickerColor, ColorPalette, ColorPaletteCustom, } from "../../colors"; -import { COLORS_PER_ROW, COLOR_PALETTE } from "../../colors"; import type { ValueOf } from "../../utility-types"; -import type { ActiveColorPickerSectionAtomType } from "./colorPickerUtils"; -import { - colorPickerHotkeyBindings, - getColorNameAndShadeFromColor, -} from "./colorPickerUtils"; const arrowHandler = ( eventKey: string, diff --git a/packages/excalidraw/components/CommandPalette/CommandPalette.tsx b/packages/excalidraw/components/CommandPalette/CommandPalette.tsx index cc3c782c4..7febb61c9 100644 --- a/packages/excalidraw/components/CommandPalette/CommandPalette.tsx +++ b/packages/excalidraw/components/CommandPalette/CommandPalette.tsx @@ -1,21 +1,34 @@ +import clsx from "clsx"; +import fuzzy from "fuzzy"; import { useEffect, useRef, useState } from "react"; + +import { + actionClearCanvas, + actionLink, + actionToggleSearchMenu, +} from "../../actions"; +import { + actionCopyElementLink, + actionLinkToElement, +} from "../../actions/actionElementLink"; +import { getShortcutFromShortcutName } from "../../actions/shortcuts"; +import { trackEvent } from "../../analytics"; +import { DEFAULT_SIDEBAR, EVENT } from "../../constants"; +import { useUIAppState } from "../../context/ui-appState"; +import { deburr } from "../../deburr"; +import { atom, useAtom, editorJotaiStore } from "../../editor-jotai"; +import { t } from "../../i18n"; +import { KEYS } from "../../keys"; import { useApp, useAppProps, useExcalidrawActionManager, useExcalidrawSetAppState, } from "../App"; -import { KEYS } from "../../keys"; import { Dialog } from "../Dialog"; +import { InlineIcon } from "../InlineIcon"; import { TextField } from "../TextField"; -import clsx from "clsx"; import { getSelectedElements } from "../../scene"; -import type { Action } from "../../actions/types"; -import type { TranslationKeys } from "../../i18n"; -import { t } from "../../i18n"; -import type { ShortcutName } from "../../actions/shortcuts"; -import { getShortcutFromShortcutName } from "../../actions/shortcuts"; -import { DEFAULT_SIDEBAR, EVENT } from "../../constants"; import { LockedIcon, UnlockedIcon, @@ -28,37 +41,29 @@ import { brainIconThin, LibraryIcon, } from "../icons"; -import fuzzy from "fuzzy"; -import { useUIAppState } from "../../context/ui-appState"; -import type { AppProps, AppState, UIAppState } from "../../types"; + import { capitalizeString, getShortcutKey, isWritableElement, } from "../../utils"; -import { atom, useAtom, editorJotaiStore } from "../../editor-jotai"; -import { deburr } from "../../deburr"; -import type { MarkRequired } from "../../utility-types"; -import { InlineIcon } from "../InlineIcon"; + import { SHAPES } from "../../shapes"; import { canChangeBackgroundColor, canChangeStrokeColor } from "../Actions"; import { useStableCallback } from "../../hooks/useStableCallback"; -import { - actionClearCanvas, - actionLink, - actionToggleSearchMenu, -} from "../../actions"; import { activeConfirmDialogAtom } from "../ActiveConfirmDialog"; -import type { CommandPaletteItem } from "./types"; -import * as defaultItems from "./defaultCommandPaletteItems"; -import { trackEvent } from "../../analytics"; import { useStable } from "../../hooks/useStable"; +import * as defaultItems from "./defaultCommandPaletteItems"; + import "./CommandPalette.scss"; -import { - actionCopyElementLink, - actionLinkToElement, -} from "../../actions/actionElementLink"; + +import type { CommandPaletteItem } from "./types"; +import type { AppProps, AppState, UIAppState } from "../../types"; +import type { MarkRequired } from "../../utility-types"; +import type { ShortcutName } from "../../actions/shortcuts"; +import type { TranslationKeys } from "../../i18n"; +import type { Action } from "../../actions/types"; const lastUsedPaletteItem = atom(null); diff --git a/packages/excalidraw/components/CommandPalette/defaultCommandPaletteItems.ts b/packages/excalidraw/components/CommandPalette/defaultCommandPaletteItems.ts index dea14ff26..485e1767c 100644 --- a/packages/excalidraw/components/CommandPalette/defaultCommandPaletteItems.ts +++ b/packages/excalidraw/components/CommandPalette/defaultCommandPaletteItems.ts @@ -1,4 +1,5 @@ import { actionToggleTheme } from "../../actions"; + import type { CommandPaletteItem } from "./types"; export const toggleTheme: CommandPaletteItem = { diff --git a/packages/excalidraw/components/ConfirmDialog.tsx b/packages/excalidraw/components/ConfirmDialog.tsx index 81073ecdb..cb402dd97 100644 --- a/packages/excalidraw/components/ConfirmDialog.tsx +++ b/packages/excalidraw/components/ConfirmDialog.tsx @@ -1,13 +1,16 @@ import { flushSync } from "react-dom"; -import { t } from "../i18n"; -import type { DialogProps } from "./Dialog"; -import { Dialog } from "./Dialog"; -import "./ConfirmDialog.scss"; +import { useSetAtom } from "../editor-jotai"; +import { t } from "../i18n"; + +import { Dialog } from "./Dialog"; import DialogActionButton from "./DialogActionButton"; import { isLibraryMenuOpenAtom } from "./LibraryMenu"; import { useExcalidrawContainer, useExcalidrawSetAppState } from "./App"; -import { useSetAtom } from "../editor-jotai"; + +import "./ConfirmDialog.scss"; + +import type { DialogProps } from "./Dialog"; interface Props extends Omit { onConfirm: () => void; diff --git a/packages/excalidraw/components/ContextMenu.tsx b/packages/excalidraw/components/ContextMenu.tsx index 517e5faed..3295d1d09 100644 --- a/packages/excalidraw/components/ContextMenu.tsx +++ b/packages/excalidraw/components/ContextMenu.tsx @@ -1,15 +1,20 @@ import clsx from "clsx"; -import { Popover } from "./Popover"; -import type { TranslationKeys } from "../i18n"; +import React from "react"; + +import { getShortcutFromShortcutName } from "../actions/shortcuts"; import { t } from "../i18n"; -import "./ContextMenu.scss"; -import type { ShortcutName } from "../actions/shortcuts"; -import { getShortcutFromShortcutName } from "../actions/shortcuts"; -import type { Action } from "../actions/types"; -import type { ActionManager } from "../actions/manager"; import { useExcalidrawAppState, useExcalidrawElements } from "./App"; -import React from "react"; + +import { Popover } from "./Popover"; + +import "./ContextMenu.scss"; + +import type { ActionManager } from "../actions/manager"; +import type { ShortcutName } from "../actions/shortcuts"; +import type { Action } from "../actions/types"; + +import type { TranslationKeys } from "../i18n"; export type ContextMenuItem = typeof CONTEXT_MENU_SEPARATOR | Action; diff --git a/packages/excalidraw/components/DarkModeToggle.tsx b/packages/excalidraw/components/DarkModeToggle.tsx index 6292ba5ed..f04712944 100644 --- a/packages/excalidraw/components/DarkModeToggle.tsx +++ b/packages/excalidraw/components/DarkModeToggle.tsx @@ -1,8 +1,10 @@ +import { THEME } from "../constants"; +import { t } from "../i18n"; + +import { ToolButton } from "./ToolButton"; + import "./ToolIcon.scss"; -import { t } from "../i18n"; -import { ToolButton } from "./ToolButton"; -import { THEME } from "../constants"; import type { Theme } from "../element/types"; // We chose to use only explicit toggle and not a third option for system value, diff --git a/packages/excalidraw/components/DefaultSidebar.test.tsx b/packages/excalidraw/components/DefaultSidebar.test.tsx index ac1e2961c..f8bc0dbbb 100644 --- a/packages/excalidraw/components/DefaultSidebar.test.tsx +++ b/packages/excalidraw/components/DefaultSidebar.test.tsx @@ -1,4 +1,5 @@ import React from "react"; + import { DEFAULT_SIDEBAR } from "../constants"; import { DefaultSidebar } from "../index"; import { @@ -6,6 +7,7 @@ import { waitFor, withExcalidrawDimensions, } from "../tests/test-utils"; + import { assertExcalidrawWithSidebar, assertSidebarDockButton, diff --git a/packages/excalidraw/components/DefaultSidebar.tsx b/packages/excalidraw/components/DefaultSidebar.tsx index 70b0c2d6c..cd9683c60 100644 --- a/packages/excalidraw/components/DefaultSidebar.tsx +++ b/packages/excalidraw/components/DefaultSidebar.tsx @@ -1,4 +1,5 @@ import clsx from "clsx"; + import { CANVAS_SEARCH_TAB, DEFAULT_SIDEBAR, @@ -6,17 +7,20 @@ import { } from "../constants"; import { useTunnels } from "../context/tunnels"; import { useUIAppState } from "../context/ui-appState"; -import type { MarkOptional, Merge } from "../utility-types"; import { composeEventHandlers } from "../utils"; -import { useExcalidrawSetAppState } from "./App"; -import { withInternalFallback } from "./hoc/withInternalFallback"; -import { LibraryMenu } from "./LibraryMenu"; -import type { SidebarProps, SidebarTriggerProps } from "./Sidebar/common"; -import { Sidebar } from "./Sidebar/Sidebar"; + import "../components/dropdownMenu/DropdownMenu.scss"; + +import { useExcalidrawSetAppState } from "./App"; +import { LibraryMenu } from "./LibraryMenu"; import { SearchMenu } from "./SearchMenu"; +import { Sidebar } from "./Sidebar/Sidebar"; +import { withInternalFallback } from "./hoc/withInternalFallback"; import { LibraryIcon, searchIcon } from "./icons"; +import type { MarkOptional, Merge } from "../utility-types"; +import type { SidebarProps, SidebarTriggerProps } from "./Sidebar/common"; + const DefaultSidebarTrigger = withInternalFallback( "DefaultSidebarTrigger", ( diff --git a/packages/excalidraw/components/DiagramToCodePlugin/DiagramToCodePlugin.tsx b/packages/excalidraw/components/DiagramToCodePlugin/DiagramToCodePlugin.tsx index 950599963..e225ca193 100644 --- a/packages/excalidraw/components/DiagramToCodePlugin/DiagramToCodePlugin.tsx +++ b/packages/excalidraw/components/DiagramToCodePlugin/DiagramToCodePlugin.tsx @@ -1,5 +1,7 @@ import { useLayoutEffect } from "react"; + import { useApp } from "../App"; + import type { GenerateDiagramToCode } from "../../types"; export const DiagramToCodePlugin = (props: { diff --git a/packages/excalidraw/components/Dialog.tsx b/packages/excalidraw/components/Dialog.tsx index 0a105cf8d..cf6b1254a 100644 --- a/packages/excalidraw/components/Dialog.tsx +++ b/packages/excalidraw/components/Dialog.tsx @@ -1,21 +1,24 @@ import clsx from "clsx"; import React, { useEffect, useState } from "react"; + +import { useSetAtom } from "../editor-jotai"; import { useCallbackRefState } from "../hooks/useCallbackRefState"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { queryFocusableElements } from "../utils"; + import { useExcalidrawContainer, useDevice, useExcalidrawSetAppState, } from "./App"; -import { KEYS } from "../keys"; -import "./Dialog.scss"; import { Island } from "./Island"; -import { Modal } from "./Modal"; -import { queryFocusableElements } from "../utils"; import { isLibraryMenuOpenAtom } from "./LibraryMenu"; -import { useSetAtom } from "../editor-jotai"; -import { t } from "../i18n"; +import { Modal } from "./Modal"; import { CloseIcon } from "./icons"; +import "./Dialog.scss"; + export type DialogSize = number | "small" | "regular" | "wide" | undefined; export interface DialogProps { diff --git a/packages/excalidraw/components/DialogActionButton.tsx b/packages/excalidraw/components/DialogActionButton.tsx index 0c4f9d589..1637fc31a 100644 --- a/packages/excalidraw/components/DialogActionButton.tsx +++ b/packages/excalidraw/components/DialogActionButton.tsx @@ -1,8 +1,11 @@ import clsx from "clsx"; -import type { ReactNode } from "react"; -import "./DialogActionButton.scss"; + import Spinner from "./Spinner"; +import "./DialogActionButton.scss"; + +import type { ReactNode } from "react"; + interface DialogActionButtonProps { label: string; children?: ReactNode; diff --git a/packages/excalidraw/components/ElementLinkDialog.tsx b/packages/excalidraw/components/ElementLinkDialog.tsx index 2ec3eaa0b..7cf329633 100644 --- a/packages/excalidraw/components/ElementLinkDialog.tsx +++ b/packages/excalidraw/components/ElementLinkDialog.tsx @@ -1,21 +1,24 @@ -import { TextField } from "./TextField"; -import type { AppProps, AppState, UIAppState } from "../types"; -import DialogActionButton from "./DialogActionButton"; -import { getSelectedElements } from "../scene"; +import { useCallback, useEffect, useState } from "react"; + +import { normalizeLink } from "../data/url"; import { defaultGetElementLinkFromSelection, getLinkIdAndTypeFromSelection, } from "../element/elementLink"; import { mutateElement } from "../element/mutateElement"; -import { useCallback, useEffect, useState } from "react"; import { t } from "../i18n"; -import type { ElementsMap, ExcalidrawElement } from "../element/types"; +import { KEYS } from "../keys"; +import { getSelectedElements } from "../scene"; + +import DialogActionButton from "./DialogActionButton"; +import { TextField } from "./TextField"; import { ToolButton } from "./ToolButton"; import { TrashIcon } from "./icons"; -import { KEYS } from "../keys"; import "./ElementLinkDialog.scss"; -import { normalizeLink } from "../data/url"; + +import type { ElementsMap, ExcalidrawElement } from "../element/types"; +import type { AppProps, AppState, UIAppState } from "../types"; const ElementLinkDialog = ({ sourceElementId, diff --git a/packages/excalidraw/components/ErrorDialog.tsx b/packages/excalidraw/components/ErrorDialog.tsx index 74d265f73..132b292b9 100644 --- a/packages/excalidraw/components/ErrorDialog.tsx +++ b/packages/excalidraw/components/ErrorDialog.tsx @@ -1,8 +1,9 @@ import React, { useState } from "react"; + import { t } from "../i18n"; -import { Dialog } from "./Dialog"; import { useExcalidrawContainer } from "./App"; +import { Dialog } from "./Dialog"; export const ErrorDialog = ({ children, diff --git a/packages/excalidraw/components/EyeDropper.tsx b/packages/excalidraw/components/EyeDropper.tsx index 429c68a4a..8c4a73e32 100644 --- a/packages/excalidraw/components/EyeDropper.tsx +++ b/packages/excalidraw/components/EyeDropper.tsx @@ -1,19 +1,23 @@ import { useEffect, useRef } from "react"; import { createPortal } from "react-dom"; + import { rgbToHex } from "../colors"; import { EVENT } from "../constants"; import { useUIAppState } from "../context/ui-appState"; +import { atom } from "../editor-jotai"; import { useCreatePortalContainer } from "../hooks/useCreatePortalContainer"; import { useOutsideClick } from "../hooks/useOutsideClick"; +import { useStable } from "../hooks/useStable"; import { KEYS } from "../keys"; import { getSelectedElements } from "../scene"; + import { useApp, useExcalidrawContainer, useExcalidrawElements } from "./App"; -import { useStable } from "../hooks/useStable"; import "./EyeDropper.scss"; -import type { ColorPickerType } from "./ColorPicker/colorPickerUtils"; + import type { ExcalidrawElement } from "../element/types"; -import { atom } from "../editor-jotai"; + +import type { ColorPickerType } from "./ColorPicker/colorPickerUtils"; export type EyeDropperProperties = { keepOpenOnAlt: boolean; diff --git a/packages/excalidraw/components/FilledButton.tsx b/packages/excalidraw/components/FilledButton.tsx index 136090848..4e5b3e3ba 100644 --- a/packages/excalidraw/components/FilledButton.tsx +++ b/packages/excalidraw/components/FilledButton.tsx @@ -1,11 +1,13 @@ -import React, { forwardRef, useState } from "react"; import clsx from "clsx"; +import React, { forwardRef, useState } from "react"; + +import { AbortError } from "../errors"; +import { isPromiseLike } from "../utils"; + +import Spinner from "./Spinner"; +import { tablerCheckIcon } from "./icons"; import "./FilledButton.scss"; -import { AbortError } from "../errors"; -import Spinner from "./Spinner"; -import { isPromiseLike } from "../utils"; -import { tablerCheckIcon } from "./icons"; export type ButtonVariant = "filled" | "outlined" | "icon"; export type ButtonColor = diff --git a/packages/excalidraw/components/FixedSideContainer.tsx b/packages/excalidraw/components/FixedSideContainer.tsx index 76aee9989..3130d78e9 100644 --- a/packages/excalidraw/components/FixedSideContainer.tsx +++ b/packages/excalidraw/components/FixedSideContainer.tsx @@ -1,8 +1,8 @@ -import "./FixedSideContainer.scss"; - import React from "react"; import clsx from "clsx"; +import "./FixedSideContainer.scss"; + type FixedSideContainerProps = { children: React.ReactNode; side: "top" | "left" | "right"; diff --git a/packages/excalidraw/components/FollowMode/FollowMode.tsx b/packages/excalidraw/components/FollowMode/FollowMode.tsx index 89581bfa4..e862cb4ea 100644 --- a/packages/excalidraw/components/FollowMode/FollowMode.tsx +++ b/packages/excalidraw/components/FollowMode/FollowMode.tsx @@ -1,7 +1,9 @@ -import type { UserToFollow } from "../../types"; import { CloseIcon } from "../icons"; + import "./FollowMode.scss"; +import type { UserToFollow } from "../../types"; + interface FollowModeProps { width: number; height: number; diff --git a/packages/excalidraw/components/FontPicker/FontPicker.tsx b/packages/excalidraw/components/FontPicker/FontPicker.tsx index 4585c5841..4018ad243 100644 --- a/packages/excalidraw/components/FontPicker/FontPicker.tsx +++ b/packages/excalidraw/components/FontPicker/FontPicker.tsx @@ -1,21 +1,23 @@ -import React, { useCallback, useMemo } from "react"; import * as Popover from "@radix-ui/react-popover"; +import React, { useCallback, useMemo } from "react"; -import { FontPickerList } from "./FontPickerList"; -import { FontPickerTrigger } from "./FontPickerTrigger"; +import { FONT_FAMILY } from "../../constants"; +import { t } from "../../i18n"; import { ButtonIconSelect } from "../ButtonIconSelect"; +import { ButtonSeparator } from "../ButtonSeparator"; import { FontFamilyCodeIcon, FontFamilyNormalIcon, FreedrawIcon, } from "../icons"; -import { ButtonSeparator } from "../ButtonSeparator"; -import type { FontFamilyValues } from "../../element/types"; -import { FONT_FAMILY } from "../../constants"; -import { t } from "../../i18n"; + +import { FontPickerList } from "./FontPickerList"; +import { FontPickerTrigger } from "./FontPickerTrigger"; import "./FontPicker.scss"; +import type { FontFamilyValues } from "../../element/types"; + export const DEFAULT_FONTS = [ { value: FONT_FAMILY.Excalifont, diff --git a/packages/excalidraw/components/FontPicker/FontPickerList.tsx b/packages/excalidraw/components/FontPicker/FontPickerList.tsx index 3a680b8fe..d93b08695 100644 --- a/packages/excalidraw/components/FontPicker/FontPickerList.tsx +++ b/packages/excalidraw/components/FontPicker/FontPickerList.tsx @@ -1,4 +1,3 @@ -import type { JSX } from "react"; import React, { useMemo, useState, @@ -7,6 +6,11 @@ import React, { useCallback, type KeyboardEventHandler, } from "react"; + +import { type FontFamilyValues } from "../../element/types"; +import { Fonts } from "../../fonts"; +import { t } from "../../i18n"; +import { arrayToList, debounce, getFontFamilyString } from "../../utils"; import { useApp, useAppProps, useExcalidrawContainer } from "../App"; import { PropertiesPopover } from "../PropertiesPopover"; import { QuickSearch } from "../QuickSearch"; @@ -16,14 +20,13 @@ import DropdownMenuItem, { DropDownMenuItemBadgeType, DropDownMenuItemBadge, } from "../dropdownMenu/DropdownMenuItem"; -import { type FontFamilyValues } from "../../element/types"; -import { arrayToList, debounce, getFontFamilyString } from "../../utils"; -import { t } from "../../i18n"; -import { fontPickerKeyHandler } from "./keyboardNavHandlers"; -import { Fonts } from "../../fonts"; -import type { ValueOf } from "../../utility-types"; import { FontFamilyNormalIcon } from "../icons"; +import { fontPickerKeyHandler } from "./keyboardNavHandlers"; + +import type { ValueOf } from "../../utility-types"; +import type { JSX } from "react"; + export interface FontDescriptor { value: number; icon: JSX.Element; diff --git a/packages/excalidraw/components/FontPicker/FontPickerTrigger.tsx b/packages/excalidraw/components/FontPicker/FontPickerTrigger.tsx index 8652dabcd..d83dda0fd 100644 --- a/packages/excalidraw/components/FontPicker/FontPickerTrigger.tsx +++ b/packages/excalidraw/components/FontPicker/FontPickerTrigger.tsx @@ -1,11 +1,14 @@ import * as Popover from "@radix-ui/react-popover"; import { useMemo } from "react"; + +import { t } from "../../i18n"; import { ButtonIcon } from "../ButtonIcon"; import { TextIcon } from "../icons"; -import type { FontFamilyValues } from "../../element/types"; -import { t } from "../../i18n"; + import { isDefaultFont } from "./FontPicker"; +import type { FontFamilyValues } from "../../element/types"; + interface FontPickerTriggerProps { selectedFontFamily: FontFamilyValues | null; } diff --git a/packages/excalidraw/components/FontPicker/keyboardNavHandlers.ts b/packages/excalidraw/components/FontPicker/keyboardNavHandlers.ts index 19c4adccc..b0ecdf371 100644 --- a/packages/excalidraw/components/FontPicker/keyboardNavHandlers.ts +++ b/packages/excalidraw/components/FontPicker/keyboardNavHandlers.ts @@ -1,7 +1,9 @@ -import type { Node } from "../../utils"; import { KEYS } from "../../keys"; + import { type FontDescriptor } from "./FontPickerList"; +import type { Node } from "../../utils"; + interface FontPickerKeyNavHandlerProps { event: React.KeyboardEvent; inputRef: React.RefObject; diff --git a/packages/excalidraw/components/HandButton.tsx b/packages/excalidraw/components/HandButton.tsx index ce63791e1..4bffb1000 100644 --- a/packages/excalidraw/components/HandButton.tsx +++ b/packages/excalidraw/components/HandButton.tsx @@ -1,9 +1,11 @@ -import "./ToolIcon.scss"; - import clsx from "clsx"; + +import { KEYS } from "../keys"; + import { ToolButton } from "./ToolButton"; import { handIcon } from "./icons"; -import { KEYS } from "../keys"; + +import "./ToolIcon.scss"; type LockIconProps = { title?: string; diff --git a/packages/excalidraw/components/HelpButton.tsx b/packages/excalidraw/components/HelpButton.tsx index ce387244c..39c867cde 100644 --- a/packages/excalidraw/components/HelpButton.tsx +++ b/packages/excalidraw/components/HelpButton.tsx @@ -1,4 +1,5 @@ import { t } from "../i18n"; + import { HelpIcon } from "./icons"; type HelpButtonProps = { diff --git a/packages/excalidraw/components/HelpDialog.tsx b/packages/excalidraw/components/HelpDialog.tsx index 926096c69..19ecaa57e 100644 --- a/packages/excalidraw/components/HelpDialog.tsx +++ b/packages/excalidraw/components/HelpDialog.tsx @@ -1,14 +1,18 @@ -import type { JSX } from "react"; import React from "react"; -import { t } from "../i18n"; -import { KEYS } from "../keys"; -import { Dialog } from "./Dialog"; -import { getShortcutKey } from "../utils"; -import "./HelpDialog.scss"; -import { ExternalLinkIcon, GithubIcon, youtubeIcon } from "./icons"; + +import { getShortcutFromShortcutName } from "../actions/shortcuts"; import { probablySupportsClipboardBlob } from "../clipboard"; import { isDarwin, isFirefox, isWindows } from "../constants"; -import { getShortcutFromShortcutName } from "../actions/shortcuts"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { getShortcutKey } from "../utils"; + +import { Dialog } from "./Dialog"; +import { ExternalLinkIcon, GithubIcon, youtubeIcon } from "./icons"; + +import "./HelpDialog.scss"; + +import type { JSX } from "react"; const Header = () => (
diff --git a/packages/excalidraw/components/HintViewer.tsx b/packages/excalidraw/components/HintViewer.tsx index f09f65852..c285e361b 100644 --- a/packages/excalidraw/components/HintViewer.tsx +++ b/packages/excalidraw/components/HintViewer.tsx @@ -1,5 +1,4 @@ -import { t } from "../i18n"; -import type { AppClassProperties, Device, UIAppState } from "../types"; +import { isEraserActive } from "../appState"; import { isFlowchartNodeElement, isImageElement, @@ -7,14 +6,18 @@ import { isTextBindableContainer, isTextElement, } from "../element/typeChecks"; -import { getShortcutKey } from "../utils"; -import { isEraserActive } from "../appState"; +import { t } from "../i18n"; + +import { getShortcutKey } from "../utils"; -import "./HintViewer.scss"; import { isNodeInFlowchart } from "../element/flowchart"; import { isGridModeEnabled } from "../snapping"; import { CANVAS_SEARCH_TAB, DEFAULT_SIDEBAR } from "../constants"; +import "./HintViewer.scss"; + +import type { AppClassProperties, Device, UIAppState } from "../types"; + interface HintViewerProps { appState: UIAppState; isMobile: boolean; diff --git a/packages/excalidraw/components/IconPicker.tsx b/packages/excalidraw/components/IconPicker.tsx index ee83f905a..b91d37c23 100644 --- a/packages/excalidraw/components/IconPicker.tsx +++ b/packages/excalidraw/components/IconPicker.tsx @@ -1,15 +1,18 @@ -import type { JSX } from "react"; -import React, { useEffect } from "react"; import * as Popover from "@radix-ui/react-popover"; -import { isArrowKey, KEYS } from "../keys"; -import { getLanguage, t } from "../i18n"; import clsx from "clsx"; -import Collapsible from "./Stats/Collapsible"; +import React, { useEffect } from "react"; + import { atom, useAtom } from "../editor-jotai"; +import { getLanguage, t } from "../i18n"; +import { isArrowKey, KEYS } from "../keys"; + +import Collapsible from "./Stats/Collapsible"; import { useDevice } from "./App"; import "./IconPicker.scss"; +import type { JSX } from "react"; + const moreOptionsAtom = atom(false); type Option = { diff --git a/packages/excalidraw/components/ImageExportDialog.tsx b/packages/excalidraw/components/ImageExportDialog.tsx index d06f4a842..0d19f5b5d 100644 --- a/packages/excalidraw/components/ImageExportDialog.tsx +++ b/packages/excalidraw/components/ImageExportDialog.tsx @@ -1,8 +1,6 @@ +import { exportToCanvas } from "@excalidraw/utils/export"; import React, { useEffect, useRef, useState } from "react"; -import type { ActionManager } from "../actions/manager"; -import type { AppClassProperties, BinaryFiles, UIAppState } from "../types"; - import { actionExportWithDarkMode, actionChangeExportBackground, @@ -17,25 +15,27 @@ import { isFirefox, EXPORT_SCALES, } from "../constants"; - +import { prepareElementsForExport } from "../data"; import { canvasToBlob } from "../data/blob"; import { nativeFileSystemSupported } from "../data/filesystem"; -import type { NonDeletedExcalidrawElement } from "../element/types"; +import { useCopyStatus } from "../hooks/useCopiedIndicator"; + import { t } from "../i18n"; import { isSomeElementSelected } from "../scene"; -import { exportToCanvas } from "@excalidraw/utils/export"; +import { cloneJSON } from "../utils"; import { copyIcon, downloadIcon, helpIcon } from "./icons"; import { Dialog } from "./Dialog"; import { RadioGroup } from "./RadioGroup"; import { Switch } from "./Switch"; import { Tooltip } from "./Tooltip"; +import { FilledButton } from "./FilledButton"; import "./ImageExportDialog.scss"; -import { FilledButton } from "./FilledButton"; -import { cloneJSON } from "../utils"; -import { prepareElementsForExport } from "../data"; -import { useCopyStatus } from "../hooks/useCopiedIndicator"; + +import type { ActionManager } from "../actions/manager"; +import type { NonDeletedExcalidrawElement } from "../element/types"; +import type { AppClassProperties, BinaryFiles, UIAppState } from "../types"; const supportsContextFilters = "filter" in document.createElement("canvas").getContext("2d")!; diff --git a/packages/excalidraw/components/InitializeApp.tsx b/packages/excalidraw/components/InitializeApp.tsx index 41f90ceeb..efc83a55b 100644 --- a/packages/excalidraw/components/InitializeApp.tsx +++ b/packages/excalidraw/components/InitializeApp.tsx @@ -1,9 +1,11 @@ import React, { useEffect, useState } from "react"; -import { LoadingMessage } from "./LoadingMessage"; -import type { Language } from "../i18n"; import { defaultLang, languages, setLanguage } from "../i18n"; + +import { LoadingMessage } from "./LoadingMessage"; + import type { Theme } from "../element/types"; +import type { Language } from "../i18n"; interface Props { langCode: Language["code"]; diff --git a/packages/excalidraw/components/Island.tsx b/packages/excalidraw/components/Island.tsx index 7baf307a0..8219e5fc7 100644 --- a/packages/excalidraw/components/Island.tsx +++ b/packages/excalidraw/components/Island.tsx @@ -1,8 +1,8 @@ -import "./Island.scss"; - import React from "react"; import clsx from "clsx"; +import "./Island.scss"; + type IslandProps = { children: React.ReactNode; padding?: number; diff --git a/packages/excalidraw/components/JSONExportDialog.tsx b/packages/excalidraw/components/JSONExportDialog.tsx index 527ad5746..ae203d3e4 100644 --- a/packages/excalidraw/components/JSONExportDialog.tsx +++ b/packages/excalidraw/components/JSONExportDialog.tsx @@ -1,19 +1,22 @@ import React from "react"; -import type { NonDeletedExcalidrawElement } from "../element/types"; -import { t } from "../i18n"; -import type { ExportOpts, BinaryFiles, UIAppState } from "../types"; -import { Dialog } from "./Dialog"; -import { exportToFileIcon, LinkIcon } from "./icons"; -import { ToolButton } from "./ToolButton"; import { actionSaveFileToDisk } from "../actions/actionExport"; + +import { trackEvent } from "../analytics"; +import { nativeFileSystemSupported } from "../data/filesystem"; +import { t } from "../i18n"; +import { getFrame } from "../utils"; + import { Card } from "./Card"; +import { Dialog } from "./Dialog"; +import { ToolButton } from "./ToolButton"; +import { exportToFileIcon, LinkIcon } from "./icons"; import "./ExportDialog.scss"; -import { nativeFileSystemSupported } from "../data/filesystem"; -import { trackEvent } from "../analytics"; + import type { ActionManager } from "../actions/manager"; -import { getFrame } from "../utils"; +import type { NonDeletedExcalidrawElement } from "../element/types"; +import type { ExportOpts, BinaryFiles, UIAppState } from "../types"; export type ExportCB = ( elements: readonly NonDeletedExcalidrawElement[], diff --git a/packages/excalidraw/components/LaserPointerButton.tsx b/packages/excalidraw/components/LaserPointerButton.tsx index 35470f6e7..237d0831c 100644 --- a/packages/excalidraw/components/LaserPointerButton.tsx +++ b/packages/excalidraw/components/LaserPointerButton.tsx @@ -1,9 +1,11 @@ +import clsx from "clsx"; + import "./ToolIcon.scss"; -import clsx from "clsx"; -import type { ToolButtonSize } from "./ToolButton"; import { laserPointerToolIcon } from "./icons"; +import type { ToolButtonSize } from "./ToolButton"; + type LaserPointerIconProps = { title?: string; name?: string; diff --git a/packages/excalidraw/components/LayerUI.tsx b/packages/excalidraw/components/LayerUI.tsx index 11914d09a..83ac7ae9c 100644 --- a/packages/excalidraw/components/LayerUI.tsx +++ b/packages/excalidraw/components/LayerUI.tsx @@ -1,12 +1,58 @@ import clsx from "clsx"; import React from "react"; -import type { ActionManager } from "../actions/manager"; + +import { mutateElement } from "../element/mutateElement"; +import { ShapeCache } from "../scene/ShapeCache"; +import Scene from "../scene/Scene"; +import { actionToggleStats } from "../actions"; +import { trackEvent } from "../analytics"; +import { isHandToolActive } from "../appState"; import { CLASSES, DEFAULT_SIDEBAR, TOOL_TYPE } from "../constants"; +import { TunnelsContext, useInitializeTunnels } from "../context/tunnels"; +import { UIAppStateContext } from "../context/ui-appState"; +import { useAtom, useAtomValue } from "../editor-jotai"; import { showSelectedShapeActions } from "../element"; -import type { NonDeletedExcalidrawElement } from "../element/types"; -import type { Language } from "../i18n"; import { t } from "../i18n"; import { calculateScrollCenter } from "../scene"; +import { capitalizeString, isShallowEqual } from "../utils"; + +import { SelectedShapeActions, ShapesSwitcher } from "./Actions"; +import { LoadingMessage } from "./LoadingMessage"; +import { LockButton } from "./LockButton"; +import { MobileMenu } from "./MobileMenu"; +import { PasteChartDialog } from "./PasteChartDialog"; +import { Section } from "./Section"; +import Stack from "./Stack"; +import { UserList } from "./UserList"; +import { PenModeButton } from "./PenModeButton"; +import Footer from "./footer/Footer"; +import { isSidebarDockedAtom } from "./Sidebar/Sidebar"; +import MainMenu from "./main-menu/MainMenu"; +import { ActiveConfirmDialog } from "./ActiveConfirmDialog"; +import { useDevice } from "./App"; +import { OverwriteConfirmDialog } from "./OverwriteConfirm/OverwriteConfirm"; +import { LibraryIcon } from "./icons"; +import { DefaultSidebar } from "./DefaultSidebar"; +import { TTDDialog } from "./TTDDialog/TTDDialog"; +import { Stats } from "./Stats"; +import ElementLinkDialog from "./ElementLinkDialog"; +import { ErrorDialog } from "./ErrorDialog"; +import { EyeDropper, activeEyeDropperAtom } from "./EyeDropper"; +import { FixedSideContainer } from "./FixedSideContainer"; +import { HandButton } from "./HandButton"; +import { HelpDialog } from "./HelpDialog"; +import { HintViewer } from "./HintViewer"; +import { ImageExportDialog } from "./ImageExportDialog"; +import { Island } from "./Island"; +import { JSONExportDialog } from "./JSONExportDialog"; +import { LaserPointerButton } from "./LaserPointerButton"; + +import "./LayerUI.scss"; +import "./Toolbar.scss"; + +import type { ActionManager } from "../actions/manager"; +import type { NonDeletedExcalidrawElement } from "../element/types"; +import type { Language } from "../i18n"; import type { AppProps, AppState, @@ -15,49 +61,6 @@ import type { UIAppState, AppClassProperties, } from "../types"; -import { capitalizeString, isShallowEqual } from "../utils"; -import { SelectedShapeActions, ShapesSwitcher } from "./Actions"; -import { ErrorDialog } from "./ErrorDialog"; -import { ImageExportDialog } from "./ImageExportDialog"; -import { FixedSideContainer } from "./FixedSideContainer"; -import { HintViewer } from "./HintViewer"; -import { Island } from "./Island"; -import { LoadingMessage } from "./LoadingMessage"; -import { LockButton } from "./LockButton"; -import { MobileMenu } from "./MobileMenu"; -import { PasteChartDialog } from "./PasteChartDialog"; -import { Section } from "./Section"; -import { HelpDialog } from "./HelpDialog"; -import Stack from "./Stack"; -import { UserList } from "./UserList"; -import { JSONExportDialog } from "./JSONExportDialog"; -import { PenModeButton } from "./PenModeButton"; -import { trackEvent } from "../analytics"; -import { useDevice } from "./App"; -import Footer from "./footer/Footer"; -import { isSidebarDockedAtom } from "./Sidebar/Sidebar"; -import { useAtom, useAtomValue } from "../editor-jotai"; -import MainMenu from "./main-menu/MainMenu"; -import { ActiveConfirmDialog } from "./ActiveConfirmDialog"; -import { OverwriteConfirmDialog } from "./OverwriteConfirm/OverwriteConfirm"; -import { HandButton } from "./HandButton"; -import { isHandToolActive } from "../appState"; -import { TunnelsContext, useInitializeTunnels } from "../context/tunnels"; -import { LibraryIcon } from "./icons"; -import { UIAppStateContext } from "../context/ui-appState"; -import { DefaultSidebar } from "./DefaultSidebar"; -import { EyeDropper, activeEyeDropperAtom } from "./EyeDropper"; -import { mutateElement } from "../element/mutateElement"; -import { ShapeCache } from "../scene/ShapeCache"; -import Scene from "../scene/Scene"; -import { LaserPointerButton } from "./LaserPointerButton"; -import { TTDDialog } from "./TTDDialog/TTDDialog"; -import { Stats } from "./Stats"; -import { actionToggleStats } from "../actions"; -import ElementLinkDialog from "./ElementLinkDialog"; - -import "./LayerUI.scss"; -import "./Toolbar.scss"; interface LayerUIProps { actionManager: ActionManager; diff --git a/packages/excalidraw/components/LibraryMenu.tsx b/packages/excalidraw/components/LibraryMenu.tsx index 0162d93a0..03c476e47 100644 --- a/packages/excalidraw/components/LibraryMenu.tsx +++ b/packages/excalidraw/components/LibraryMenu.tsx @@ -6,13 +6,36 @@ import React, { memo, useRef, } from "react"; -import type Library from "../data/library"; + +import { trackEvent } from "../analytics"; +import { LIBRARY_DISABLED_TYPES } from "../constants"; +import { useUIAppState } from "../context/ui-appState"; import { distributeLibraryItemsOnSquareGrid, libraryItemsAtom, } from "../data/library"; +import { atom, useAtom } from "../editor-jotai"; import { t } from "../i18n"; import { randomId } from "../random"; +import { getSelectedElements } from "../scene"; +import { isShallowEqual } from "../utils"; + +import { + useApp, + useAppProps, + useExcalidrawElements, + useExcalidrawSetAppState, +} from "./App"; +import { LibraryMenuControlButtons } from "./LibraryMenuControlButtons"; +import LibraryMenuItems from "./LibraryMenuItems"; +import Spinner from "./Spinner"; + +import "./LibraryMenu.scss"; + +import type { + ExcalidrawElement, + NonDeletedExcalidrawElement, +} from "../element/types"; import type { LibraryItems, LibraryItem, @@ -20,27 +43,7 @@ import type { UIAppState, AppClassProperties, } from "../types"; -import LibraryMenuItems from "./LibraryMenuItems"; -import { trackEvent } from "../analytics"; -import { atom, useAtom } from "../editor-jotai"; -import Spinner from "./Spinner"; -import { - useApp, - useAppProps, - useExcalidrawElements, - useExcalidrawSetAppState, -} from "./App"; -import { getSelectedElements } from "../scene"; -import { useUIAppState } from "../context/ui-appState"; - -import "./LibraryMenu.scss"; -import { LibraryMenuControlButtons } from "./LibraryMenuControlButtons"; -import type { - ExcalidrawElement, - NonDeletedExcalidrawElement, -} from "../element/types"; -import { LIBRARY_DISABLED_TYPES } from "../constants"; -import { isShallowEqual } from "../utils"; +import type Library from "../data/library"; export const isLibraryMenuOpenAtom = atom(false); diff --git a/packages/excalidraw/components/LibraryMenuBrowseButton.tsx b/packages/excalidraw/components/LibraryMenuBrowseButton.tsx index 43fbedd77..2b2623ed1 100644 --- a/packages/excalidraw/components/LibraryMenuBrowseButton.tsx +++ b/packages/excalidraw/components/LibraryMenuBrowseButton.tsx @@ -1,5 +1,6 @@ import { VERSIONS } from "../constants"; import { t } from "../i18n"; + import type { ExcalidrawProps, UIAppState } from "../types"; const LibraryMenuBrowseButton = ({ diff --git a/packages/excalidraw/components/LibraryMenuControlButtons.tsx b/packages/excalidraw/components/LibraryMenuControlButtons.tsx index b467ca39c..1ea722168 100644 --- a/packages/excalidraw/components/LibraryMenuControlButtons.tsx +++ b/packages/excalidraw/components/LibraryMenuControlButtons.tsx @@ -1,7 +1,9 @@ -import type { ExcalidrawProps, UIAppState } from "../types"; -import LibraryMenuBrowseButton from "./LibraryMenuBrowseButton"; import clsx from "clsx"; +import LibraryMenuBrowseButton from "./LibraryMenuBrowseButton"; + +import type { ExcalidrawProps, UIAppState } from "../types"; + export const LibraryMenuControlButtons = ({ libraryReturnUrl, theme, diff --git a/packages/excalidraw/components/LibraryMenuHeaderContent.tsx b/packages/excalidraw/components/LibraryMenuHeaderContent.tsx index bec31aa36..cc6c942ae 100644 --- a/packages/excalidraw/components/LibraryMenuHeaderContent.tsx +++ b/packages/excalidraw/components/LibraryMenuHeaderContent.tsx @@ -1,12 +1,23 @@ +import clsx from "clsx"; import { useCallback, useState } from "react"; -import { t } from "../i18n"; -import Trans from "./Trans"; -import { useAtom } from "../editor-jotai"; -import type { LibraryItem, LibraryItems, UIAppState } from "../types"; -import { useApp, useExcalidrawSetAppState } from "./App"; + +import { useUIAppState } from "../context/ui-appState"; +import { fileOpen } from "../data/filesystem"; import { saveLibraryAsJSON } from "../data/json"; -import type Library from "../data/library"; import { libraryItemsAtom } from "../data/library"; +import { useAtom } from "../editor-jotai"; +import { useLibraryCache } from "../hooks/useLibraryItemSvg"; +import { t } from "../i18n"; +import { muteFSAbortError } from "../utils"; + +import { useApp, useExcalidrawSetAppState } from "./App"; +import ConfirmDialog from "./ConfirmDialog"; +import { Dialog } from "./Dialog"; +import { isLibraryMenuOpenAtom } from "./LibraryMenu"; +import PublishLibrary from "./PublishLibrary"; +import { ToolButton } from "./ToolButton"; +import Trans from "./Trans"; +import DropdownMenu from "./dropdownMenu/DropdownMenu"; import { DotsIcon, ExportIcon, @@ -14,17 +25,9 @@ import { publishIcon, TrashIcon, } from "./icons"; -import { ToolButton } from "./ToolButton"; -import { fileOpen } from "../data/filesystem"; -import { muteFSAbortError } from "../utils"; -import ConfirmDialog from "./ConfirmDialog"; -import PublishLibrary from "./PublishLibrary"; -import { Dialog } from "./Dialog"; -import DropdownMenu from "./dropdownMenu/DropdownMenu"; -import { isLibraryMenuOpenAtom } from "./LibraryMenu"; -import { useUIAppState } from "../context/ui-appState"; -import clsx from "clsx"; -import { useLibraryCache } from "../hooks/useLibraryItemSvg"; + +import type Library from "../data/library"; +import type { LibraryItem, LibraryItems, UIAppState } from "../types"; const getSelectedItems = ( libraryItems: LibraryItems, diff --git a/packages/excalidraw/components/LibraryMenuItems.tsx b/packages/excalidraw/components/LibraryMenuItems.tsx index aa2c3e68e..af5b9d3e6 100644 --- a/packages/excalidraw/components/LibraryMenuItems.tsx +++ b/packages/excalidraw/components/LibraryMenuItems.tsx @@ -5,30 +5,33 @@ import React, { useRef, useState, } from "react"; -import { serializeLibraryAsJSON } from "../data/json"; -import { t } from "../i18n"; -import type { - ExcalidrawProps, - LibraryItem, - LibraryItems, - UIAppState, -} from "../types"; -import { arrayToMap } from "../utils"; -import Stack from "./Stack"; + import { MIME_TYPES } from "../constants"; -import Spinner from "./Spinner"; +import { serializeLibraryAsJSON } from "../data/json"; import { duplicateElements } from "../element/newElement"; +import { useLibraryCache } from "../hooks/useLibraryItemSvg"; +import { useScrollPosition } from "../hooks/useScrollPosition"; +import { t } from "../i18n"; +import { arrayToMap } from "../utils"; + import { LibraryMenuControlButtons } from "./LibraryMenuControlButtons"; import { LibraryDropdownMenu } from "./LibraryMenuHeaderContent"; import { LibraryMenuSection, LibraryMenuSectionGrid, } from "./LibraryMenuSection"; -import { useScrollPosition } from "../hooks/useScrollPosition"; -import { useLibraryCache } from "../hooks/useLibraryItemSvg"; +import Spinner from "./Spinner"; +import Stack from "./Stack"; import "./LibraryMenuItems.scss"; +import type { + ExcalidrawProps, + LibraryItem, + LibraryItems, + UIAppState, +} from "../types"; + // using an odd number of items per batch so the rendering creates an irregular // pattern which looks more organic const ITEMS_RENDERED_PER_BATCH = 17; diff --git a/packages/excalidraw/components/LibraryMenuSection.tsx b/packages/excalidraw/components/LibraryMenuSection.tsx index b07d6b1cc..5f7de2b09 100644 --- a/packages/excalidraw/components/LibraryMenuSection.tsx +++ b/packages/excalidraw/components/LibraryMenuSection.tsx @@ -1,10 +1,13 @@ -import type { ReactNode } from "react"; import React, { memo, useEffect, useState } from "react"; + +import { useTransition } from "../hooks/useTransition"; + import { EmptyLibraryUnit, LibraryUnit } from "./LibraryUnit"; -import type { LibraryItem } from "../types"; + import type { ExcalidrawElement, NonDeleted } from "../element/types"; import type { SvgCache } from "../hooks/useLibraryItemSvg"; -import { useTransition } from "../hooks/useTransition"; +import type { LibraryItem } from "../types"; +import type { ReactNode } from "react"; type LibraryOrPendingItem = ( | LibraryItem diff --git a/packages/excalidraw/components/LibraryUnit.tsx b/packages/excalidraw/components/LibraryUnit.tsx index 71e1a00f5..9cd891715 100644 --- a/packages/excalidraw/components/LibraryUnit.tsx +++ b/packages/excalidraw/components/LibraryUnit.tsx @@ -1,12 +1,16 @@ import clsx from "clsx"; import { memo, useEffect, useRef, useState } from "react"; + +import { useLibraryItemSvg } from "../hooks/useLibraryItemSvg"; + import { useDevice } from "./App"; -import type { LibraryItem } from "../types"; -import "./LibraryUnit.scss"; import { CheckboxItem } from "./CheckboxItem"; import { PlusIcon } from "./icons"; + +import "./LibraryUnit.scss"; + +import type { LibraryItem } from "../types"; import type { SvgCache } from "../hooks/useLibraryItemSvg"; -import { useLibraryItemSvg } from "../hooks/useLibraryItemSvg"; export const LibraryUnit = memo( ({ diff --git a/packages/excalidraw/components/LoadingMessage.tsx b/packages/excalidraw/components/LoadingMessage.tsx index b00725257..bdcc5a341 100644 --- a/packages/excalidraw/components/LoadingMessage.tsx +++ b/packages/excalidraw/components/LoadingMessage.tsx @@ -1,8 +1,11 @@ -import { t } from "../i18n"; -import { useState, useEffect } from "react"; -import Spinner from "./Spinner"; import clsx from "clsx"; +import { useState, useEffect } from "react"; + import { THEME } from "../constants"; +import { t } from "../i18n"; + +import Spinner from "./Spinner"; + import type { Theme } from "../element/types"; export const LoadingMessage: React.FC<{ delay?: number; theme?: Theme }> = ({ diff --git a/packages/excalidraw/components/LockButton.tsx b/packages/excalidraw/components/LockButton.tsx index f7913d12d..8363ffa0c 100644 --- a/packages/excalidraw/components/LockButton.tsx +++ b/packages/excalidraw/components/LockButton.tsx @@ -1,9 +1,11 @@ +import clsx from "clsx"; + import "./ToolIcon.scss"; -import clsx from "clsx"; -import type { ToolButtonSize } from "./ToolButton"; import { LockedIcon, UnlockedIcon } from "./icons"; +import type { ToolButtonSize } from "./ToolButton"; + type LockIconProps = { title?: string; name?: string; diff --git a/packages/excalidraw/components/MagicButton.tsx b/packages/excalidraw/components/MagicButton.tsx index eedc63b3d..b2bbd03e2 100644 --- a/packages/excalidraw/components/MagicButton.tsx +++ b/packages/excalidraw/components/MagicButton.tsx @@ -1,9 +1,10 @@ -import type { JSX } from "react"; import clsx from "clsx"; -import type { ToolButtonSize } from "./ToolButton"; import "./ToolIcon.scss"; +import type { ToolButtonSize } from "./ToolButton"; +import type { JSX } from "react"; + const DEFAULT_SIZE: ToolButtonSize = "small"; export const ElementCanvasButton = (props: { diff --git a/packages/excalidraw/components/MobileMenu.tsx b/packages/excalidraw/components/MobileMenu.tsx index bef99a91a..08a20174c 100644 --- a/packages/excalidraw/components/MobileMenu.tsx +++ b/packages/excalidraw/components/MobileMenu.tsx @@ -1,5 +1,24 @@ -import type { JSX } from "react"; import React from "react"; + +import { isHandToolActive } from "../appState"; +import { useTunnels } from "../context/tunnels"; +import { showSelectedShapeActions } from "../element"; +import { t } from "../i18n"; +import { calculateScrollCenter } from "../scene"; +import { SCROLLBAR_WIDTH, SCROLLBAR_MARGIN } from "../scene/scrollbars"; + +import { SelectedShapeActions, ShapesSwitcher } from "./Actions"; +import { FixedSideContainer } from "./FixedSideContainer"; +import { HandButton } from "./HandButton"; +import { HintViewer } from "./HintViewer"; +import { Island } from "./Island"; +import { LockButton } from "./LockButton"; +import { PenModeButton } from "./PenModeButton"; +import { Section } from "./Section"; +import Stack from "./Stack"; + +import type { ActionManager } from "../actions/manager"; +import type { NonDeletedExcalidrawElement } from "../element/types"; import type { AppClassProperties, AppProps, @@ -8,23 +27,7 @@ import type { ExcalidrawProps, UIAppState, } from "../types"; -import type { ActionManager } from "../actions/manager"; -import { t } from "../i18n"; -import Stack from "./Stack"; -import { showSelectedShapeActions } from "../element"; -import type { NonDeletedExcalidrawElement } from "../element/types"; -import { FixedSideContainer } from "./FixedSideContainer"; -import { Island } from "./Island"; -import { HintViewer } from "./HintViewer"; -import { calculateScrollCenter } from "../scene"; -import { SelectedShapeActions, ShapesSwitcher } from "./Actions"; -import { Section } from "./Section"; -import { SCROLLBAR_WIDTH, SCROLLBAR_MARGIN } from "../scene/scrollbars"; -import { LockButton } from "./LockButton"; -import { PenModeButton } from "./PenModeButton"; -import { HandButton } from "./HandButton"; -import { isHandToolActive } from "../appState"; -import { useTunnels } from "../context/tunnels"; +import type { JSX } from "react"; type MobileMenuProps = { appState: UIAppState; diff --git a/packages/excalidraw/components/Modal.tsx b/packages/excalidraw/components/Modal.tsx index e8fff195b..a5ade9efa 100644 --- a/packages/excalidraw/components/Modal.tsx +++ b/packages/excalidraw/components/Modal.tsx @@ -1,11 +1,13 @@ +import clsx from "clsx"; +import { useRef } from "react"; +import { createPortal } from "react-dom"; + +import { useCreatePortalContainer } from "../hooks/useCreatePortalContainer"; +import { KEYS } from "../keys"; + import "./Modal.scss"; -import { createPortal } from "react-dom"; -import clsx from "clsx"; -import { KEYS } from "../keys"; import type { AppState } from "../types"; -import { useCreatePortalContainer } from "../hooks/useCreatePortalContainer"; -import { useRef } from "react"; export const Modal: React.FC<{ className?: string; diff --git a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx index 4bf8d6717..f2de877e0 100644 --- a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx +++ b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx @@ -3,12 +3,13 @@ import React from "react"; import { useTunnels } from "../../context/tunnels"; import { useAtom } from "../../editor-jotai"; import { Dialog } from "../Dialog"; +import { FilledButton } from "../FilledButton"; import { withInternalFallback } from "../hoc/withInternalFallback"; +import { alertTriangleIcon } from "../icons"; + +import { Actions, Action } from "./OverwriteConfirmActions"; import { overwriteConfirmStateAtom } from "./OverwriteConfirmState"; -import { FilledButton } from "../FilledButton"; -import { alertTriangleIcon } from "../icons"; -import { Actions, Action } from "./OverwriteConfirmActions"; import "./OverwriteConfirm.scss"; export type OverwriteConfirmDialogProps = { diff --git a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmActions.tsx b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmActions.tsx index 5da0a08ef..e5fb56d85 100644 --- a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmActions.tsx +++ b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmActions.tsx @@ -1,9 +1,10 @@ import React from "react"; -import { FilledButton } from "../FilledButton"; -import { useExcalidrawActionManager, useExcalidrawSetAppState } from "../App"; + import { actionSaveFileToDisk } from "../../actions"; -import { useI18n } from "../../i18n"; import { actionChangeExportEmbedScene } from "../../actions/actionExport"; +import { useI18n } from "../../i18n"; +import { useExcalidrawActionManager, useExcalidrawSetAppState } from "../App"; +import { FilledButton } from "../FilledButton"; export type ActionProps = { title: string; diff --git a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.ts b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.ts index 04616aa8d..cefb2153a 100644 --- a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.ts +++ b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.ts @@ -1,4 +1,5 @@ import { atom, editorJotaiStore } from "../../editor-jotai"; + import type React from "react"; export type OverwriteConfirmState = diff --git a/packages/excalidraw/components/PasteChartDialog.tsx b/packages/excalidraw/components/PasteChartDialog.tsx index 08a5634a9..58bd5a385 100644 --- a/packages/excalidraw/components/PasteChartDialog.tsx +++ b/packages/excalidraw/components/PasteChartDialog.tsx @@ -1,17 +1,20 @@ import oc from "open-color"; import React, { useLayoutEffect, useRef, useState } from "react"; + import { trackEvent } from "../analytics"; -import type { ChartElements, Spreadsheet } from "../charts"; import { renderSpreadsheet } from "../charts"; -import type { ChartType } from "../element/types"; import { t } from "../i18n"; import { exportToSvg } from "../scene/export"; -import type { UIAppState } from "../types"; + import { useApp } from "./App"; import { Dialog } from "./Dialog"; import "./PasteChartDialog.scss"; +import type { ChartElements, Spreadsheet } from "../charts"; +import type { ChartType } from "../element/types"; +import type { UIAppState } from "../types"; + type OnInsertChart = (chartType: ChartType, elements: ChartElements) => void; const ChartPreviewBtn = (props: { diff --git a/packages/excalidraw/components/PenModeButton.tsx b/packages/excalidraw/components/PenModeButton.tsx index ca5ceb2b6..e5df8ac9b 100644 --- a/packages/excalidraw/components/PenModeButton.tsx +++ b/packages/excalidraw/components/PenModeButton.tsx @@ -1,9 +1,11 @@ +import clsx from "clsx"; + import "./ToolIcon.scss"; -import clsx from "clsx"; -import type { ToolButtonSize } from "./ToolButton"; import { PenModeIcon } from "./icons"; +import type { ToolButtonSize } from "./ToolButton"; + type PenModeIconProps = { title?: string; name?: string; diff --git a/packages/excalidraw/components/Popover.tsx b/packages/excalidraw/components/Popover.tsx index 987e9fb91..2bd72b20b 100644 --- a/packages/excalidraw/components/Popover.tsx +++ b/packages/excalidraw/components/Popover.tsx @@ -1,8 +1,10 @@ import React, { useLayoutEffect, useRef, useEffect } from "react"; -import "./Popover.scss"; import { unstable_batchedUpdates } from "react-dom"; -import { queryFocusableElements } from "../utils"; + import { KEYS } from "../keys"; +import { queryFocusableElements } from "../utils"; + +import "./Popover.scss"; type Props = { top?: number; diff --git a/packages/excalidraw/components/ProjectName.tsx b/packages/excalidraw/components/ProjectName.tsx index 592961793..0d60ddd66 100644 --- a/packages/excalidraw/components/ProjectName.tsx +++ b/packages/excalidraw/components/ProjectName.tsx @@ -1,12 +1,13 @@ -import "./TextInput.scss"; - import React, { useState } from "react"; -import { focusNearestParent } from "../utils"; -import "./ProjectName.scss"; -import { useExcalidrawContainer } from "./App"; +import { focusNearestParent } from "../utils"; import { KEYS } from "../keys"; +import { useExcalidrawContainer } from "./App"; + +import "./TextInput.scss"; +import "./ProjectName.scss"; + type Props = { value: string; onChange: (value: string) => void; diff --git a/packages/excalidraw/components/PropertiesPopover.tsx b/packages/excalidraw/components/PropertiesPopover.tsx index 455af1184..a30f1374d 100644 --- a/packages/excalidraw/components/PropertiesPopover.tsx +++ b/packages/excalidraw/components/PropertiesPopover.tsx @@ -1,10 +1,11 @@ -import React, { type ReactNode } from "react"; -import clsx from "clsx"; import * as Popover from "@radix-ui/react-popover"; +import clsx from "clsx"; +import React, { type ReactNode } from "react"; + +import { isInteractive } from "../utils"; import { useDevice } from "./App"; import { Island } from "./Island"; -import { isInteractive } from "../utils"; interface PropertiesPopoverProps { className?: string; diff --git a/packages/excalidraw/components/PublishLibrary.tsx b/packages/excalidraw/components/PublishLibrary.tsx index fe68f880d..8a7188b63 100644 --- a/packages/excalidraw/components/PublishLibrary.tsx +++ b/packages/excalidraw/components/PublishLibrary.tsx @@ -1,13 +1,7 @@ -import type { ReactNode } from "react"; -import { useCallback, useEffect, useRef, useState } from "react"; -import OpenColor from "open-color"; - -import { Dialog } from "./Dialog"; -import { t } from "../i18n"; -import Trans from "./Trans"; - -import type { LibraryItems, LibraryItem, UIAppState } from "../types"; import { exportToCanvas, exportToSvg } from "@excalidraw/utils/export"; +import OpenColor from "open-color"; +import { useCallback, useEffect, useRef, useState } from "react"; + import { EDITOR_LS_KEYS, EXPORT_DATA_TYPES, @@ -15,16 +9,23 @@ import { MIME_TYPES, VERSIONS, } from "../constants"; -import type { ExportedLibraryData } from "../data/types"; -import { canvasToBlob, resizeImageFile } from "../data/blob"; -import { chunk } from "../utils"; -import DialogActionButton from "./DialogActionButton"; -import { CloseIcon } from "./icons"; -import { ToolButton } from "./ToolButton"; import { EditorLocalStorage } from "../data/EditorLocalStorage"; +import { canvasToBlob, resizeImageFile } from "../data/blob"; +import { t } from "../i18n"; +import { chunk } from "../utils"; + +import { Dialog } from "./Dialog"; +import DialogActionButton from "./DialogActionButton"; +import { ToolButton } from "./ToolButton"; +import Trans from "./Trans"; +import { CloseIcon } from "./icons"; import "./PublishLibrary.scss"; +import type { ReactNode } from "react"; +import type { ExportedLibraryData } from "../data/types"; +import type { LibraryItems, LibraryItem, UIAppState } from "../types"; + interface PublishLibraryDataParams { authorName: string; githubHandle: string; diff --git a/packages/excalidraw/components/QuickSearch.tsx b/packages/excalidraw/components/QuickSearch.tsx index c7ec78b50..83b65183f 100644 --- a/packages/excalidraw/components/QuickSearch.tsx +++ b/packages/excalidraw/components/QuickSearch.tsx @@ -1,5 +1,6 @@ import clsx from "clsx"; import React from "react"; + import { searchIcon } from "./icons"; import "./QuickSearch.scss"; diff --git a/packages/excalidraw/components/RadioGroup.tsx b/packages/excalidraw/components/RadioGroup.tsx index 64d4d587d..c08355aa2 100644 --- a/packages/excalidraw/components/RadioGroup.tsx +++ b/packages/excalidraw/components/RadioGroup.tsx @@ -1,4 +1,5 @@ import clsx from "clsx"; + import "./RadioGroup.scss"; export type RadioGroupChoice = { diff --git a/packages/excalidraw/components/Range.tsx b/packages/excalidraw/components/Range.tsx index cd1869cc0..3ab9ede15 100644 --- a/packages/excalidraw/components/Range.tsx +++ b/packages/excalidraw/components/Range.tsx @@ -1,6 +1,8 @@ import React, { useEffect } from "react"; + import { getFormValue } from "../actions/actionProperties"; import { t } from "../i18n"; + import "./Range.scss"; export type RangeProps = { diff --git a/packages/excalidraw/components/SVGLayer.tsx b/packages/excalidraw/components/SVGLayer.tsx index 667b89ab7..815d463a3 100644 --- a/packages/excalidraw/components/SVGLayer.tsx +++ b/packages/excalidraw/components/SVGLayer.tsx @@ -1,8 +1,9 @@ import { useEffect, useRef } from "react"; -import type { Trail } from "../animated-trail"; import "./SVGLayer.scss"; +import type { Trail } from "../animated-trail"; + type SVGLayerProps = { trails: Trail[]; }; diff --git a/packages/excalidraw/components/SearchMenu.scss b/packages/excalidraw/components/SearchMenu.scss index ae6bb5647..1f47f9876 100644 --- a/packages/excalidraw/components/SearchMenu.scss +++ b/packages/excalidraw/components/SearchMenu.scss @@ -52,7 +52,7 @@ background-color: var(--color-surface-high); } - &:first { + &:first-child { margin-right: 4px; } } diff --git a/packages/excalidraw/components/SearchMenu.tsx b/packages/excalidraw/components/SearchMenu.tsx index 873de5adb..70d3f4f27 100644 --- a/packages/excalidraw/components/SearchMenu.tsx +++ b/packages/excalidraw/components/SearchMenu.tsx @@ -1,25 +1,29 @@ -import { Fragment, memo, useEffect, useRef, useState } from "react"; -import { collapseDownIcon, upIcon, searchIcon } from "./icons"; -import { TextField } from "./TextField"; -import { Button } from "./Button"; -import { useApp, useExcalidrawSetAppState } from "./App"; -import debounce from "lodash.debounce"; -import type { AppClassProperties } from "../types"; -import { isTextElement, newTextElement } from "../element"; -import type { ExcalidrawTextElement } from "../element/types"; -import { addEventListener, getFontString } from "../utils"; -import { KEYS } from "../keys"; +import { round } from "@excalidraw/math"; import clsx from "clsx"; -import { atom, useAtom } from "../editor-jotai"; -import { t } from "../i18n"; -import { isElementCompletelyInViewport } from "../element/sizeHelpers"; -import { randomInteger } from "../random"; +import debounce from "lodash.debounce"; +import { Fragment, memo, useEffect, useRef, useState } from "react"; + import { CLASSES, EVENT } from "../constants"; +import { atom, useAtom } from "../editor-jotai"; +import { isTextElement, newTextElement } from "../element"; +import { isElementCompletelyInViewport } from "../element/sizeHelpers"; + +import { measureText } from "../element/textMeasurements"; import { useStable } from "../hooks/useStable"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { randomInteger } from "../random"; +import { addEventListener, getFontString } from "../utils"; + +import { useApp, useExcalidrawSetAppState } from "./App"; +import { Button } from "./Button"; +import { TextField } from "./TextField"; +import { collapseDownIcon, upIcon, searchIcon } from "./icons"; import "./SearchMenu.scss"; -import { round } from "@excalidraw/math"; -import { measureText } from "../element/textMeasurements"; + +import type { ExcalidrawTextElement } from "../element/types"; +import type { AppClassProperties } from "../types"; const searchQueryAtom = atom(""); export const searchItemInFocusAtom = atom(null); diff --git a/packages/excalidraw/components/Section.tsx b/packages/excalidraw/components/Section.tsx index 8cd0aaab5..e7e357bb5 100644 --- a/packages/excalidraw/components/Section.tsx +++ b/packages/excalidraw/components/Section.tsx @@ -1,5 +1,7 @@ import React from "react"; + import { t } from "../i18n"; + import { useExcalidrawContainer } from "./App"; export const Section: React.FC<{ diff --git a/packages/excalidraw/components/ShapeSwitch.tsx b/packages/excalidraw/components/ShapeSwitch.tsx index b2f7fba95..52305ff37 100644 --- a/packages/excalidraw/components/ShapeSwitch.tsx +++ b/packages/excalidraw/components/ShapeSwitch.tsx @@ -1,22 +1,13 @@ -import { getSelectedElements } from "../scene"; -import type App from "./App"; -import { ToolButton } from "./ToolButton"; -import { - ArrowIcon, - DiamondIcon, - EllipseIcon, - LineIcon, - RectangleIcon, -} from "./icons"; import { type ReactNode, useEffect, useRef } from "react"; -import { trackEvent } from "../analytics"; -import type { ToolType } from "../types"; -import { sceneCoordsToViewportCoords } from "../utils"; -import type { ExcalidrawElement } from "../element/types"; -import "./ShapeSwitch.scss"; + import clsx from "clsx"; -import { getElementAbsoluteCoords } from "../element"; + import { pointFrom, pointRotateRads } from "@excalidraw/math"; + +import { getElementAbsoluteCoords } from "../element"; +import { sceneCoordsToViewportCoords } from "../utils"; +import { getSelectedElements } from "../scene"; +import { trackEvent } from "../analytics"; import { isArrowElement, isGenericSwitchableElement, @@ -25,6 +16,21 @@ import { } from "../element/typeChecks"; import { t } from "../i18n"; +import "./ShapeSwitch.scss"; + +import { + ArrowIcon, + DiamondIcon, + EllipseIcon, + LineIcon, + RectangleIcon, +} from "./icons"; +import { ToolButton } from "./ToolButton"; + +import type App from "./App"; +import type { ExcalidrawElement } from "../element/types"; +import type { ToolType } from "../types"; + const GAP_HORIZONTAL = 8; const GAP_VERTICAL = 10; diff --git a/packages/excalidraw/components/ShapeSwitcher.tsx b/packages/excalidraw/components/ShapeSwitcher.tsx index d408fad50..558052a6c 100644 --- a/packages/excalidraw/components/ShapeSwitcher.tsx +++ b/packages/excalidraw/components/ShapeSwitcher.tsx @@ -1,9 +1,11 @@ // render the shape switcher div on top of the canvas at the selected element's position import { THEME } from "../constants"; + +import { sceneCoordsToViewportCoords } from "../utils"; + import type { ExcalidrawElement } from "../element/types"; import type { AppState } from "../types"; -import { sceneCoordsToViewportCoords } from "../utils"; const ShapeSwitcher = ({ appState, diff --git a/packages/excalidraw/components/ShareableLinkDialog.tsx b/packages/excalidraw/components/ShareableLinkDialog.tsx index 987c7bf61..514a77632 100644 --- a/packages/excalidraw/components/ShareableLinkDialog.tsx +++ b/packages/excalidraw/components/ShareableLinkDialog.tsx @@ -1,12 +1,12 @@ import { useRef, useState } from "react"; import { copyTextToSystemClipboard } from "../clipboard"; +import { useCopyStatus } from "../hooks/useCopiedIndicator"; import { useI18n } from "../i18n"; import { Dialog } from "./Dialog"; -import { TextField } from "./TextField"; import { FilledButton } from "./FilledButton"; -import { useCopyStatus } from "../hooks/useCopiedIndicator"; +import { TextField } from "./TextField"; import { copyIcon } from "./icons"; import "./ShareableLinkDialog.scss"; diff --git a/packages/excalidraw/components/Sidebar/Sidebar.test.tsx b/packages/excalidraw/components/Sidebar/Sidebar.test.tsx index b61529d9e..39a1cbc63 100644 --- a/packages/excalidraw/components/Sidebar/Sidebar.test.tsx +++ b/packages/excalidraw/components/Sidebar/Sidebar.test.tsx @@ -1,4 +1,6 @@ import React from "react"; +import { vi } from "vitest"; + import { DEFAULT_SIDEBAR } from "../../constants"; import { Excalidraw, Sidebar } from "../../index"; import { @@ -10,7 +12,7 @@ import { waitFor, withExcalidrawDimensions, } from "../../tests/test-utils"; -import { vi } from "vitest"; + import { assertExcalidrawWithSidebar, assertSidebarDockButton, diff --git a/packages/excalidraw/components/Sidebar/Sidebar.tsx b/packages/excalidraw/components/Sidebar/Sidebar.tsx index 7c747d2f4..8a008fd9f 100644 --- a/packages/excalidraw/components/Sidebar/Sidebar.tsx +++ b/packages/excalidraw/components/Sidebar/Sidebar.tsx @@ -1,3 +1,4 @@ +import clsx from "clsx"; import React, { useEffect, useLayoutEffect, @@ -7,26 +8,28 @@ import React, { useImperativeHandle, useCallback, } from "react"; -import { Island } from "../Island"; -import { atom, useSetAtom } from "../../editor-jotai"; -import type { SidebarProps, SidebarPropsContextValue } from "./common"; -import { SidebarPropsContext } from "./common"; -import { SidebarHeader } from "./SidebarHeader"; -import clsx from "clsx"; -import { useDevice, useExcalidrawSetAppState } from "../App"; -import { updateObject } from "../../utils"; -import { KEYS } from "../../keys"; + import { EVENT } from "../../constants"; -import { SidebarTrigger } from "./SidebarTrigger"; -import { SidebarTabTriggers } from "./SidebarTabTriggers"; +import { useUIAppState } from "../../context/ui-appState"; +import { atom, useSetAtom } from "../../editor-jotai"; +import { useOutsideClick } from "../../hooks/useOutsideClick"; +import { KEYS } from "../../keys"; +import { updateObject } from "../../utils"; +import { useDevice, useExcalidrawSetAppState } from "../App"; +import { Island } from "../Island"; + +import { SidebarHeader } from "./SidebarHeader"; import { SidebarTabTrigger } from "./SidebarTabTrigger"; +import { SidebarTabTriggers } from "./SidebarTabTriggers"; +import { SidebarTrigger } from "./SidebarTrigger"; +import { SidebarPropsContext } from "./common"; import { SidebarTabs } from "./SidebarTabs"; import { SidebarTab } from "./SidebarTab"; -import { useUIAppState } from "../../context/ui-appState"; -import { useOutsideClick } from "../../hooks/useOutsideClick"; import "./Sidebar.scss"; +import type { SidebarProps, SidebarPropsContextValue } from "./common"; + /** * Flags whether the currently rendered Sidebar is docked or not, for use * in upstream components that need to act on this (e.g. LayerUI to shift the diff --git a/packages/excalidraw/components/Sidebar/SidebarHeader.tsx b/packages/excalidraw/components/Sidebar/SidebarHeader.tsx index 6d046aba3..9c9e51cf5 100644 --- a/packages/excalidraw/components/Sidebar/SidebarHeader.tsx +++ b/packages/excalidraw/components/Sidebar/SidebarHeader.tsx @@ -1,11 +1,13 @@ import clsx from "clsx"; import { useContext } from "react"; + import { t } from "../../i18n"; import { useDevice } from "../App"; -import { SidebarPropsContext } from "./common"; -import { CloseIcon, PinIcon } from "../icons"; -import { Tooltip } from "../Tooltip"; import { Button } from "../Button"; +import { Tooltip } from "../Tooltip"; +import { CloseIcon, PinIcon } from "../icons"; + +import { SidebarPropsContext } from "./common"; export const SidebarHeader = ({ children, diff --git a/packages/excalidraw/components/Sidebar/SidebarTab.tsx b/packages/excalidraw/components/Sidebar/SidebarTab.tsx index 6fddab0d6..0525662f7 100644 --- a/packages/excalidraw/components/Sidebar/SidebarTab.tsx +++ b/packages/excalidraw/components/Sidebar/SidebarTab.tsx @@ -1,4 +1,5 @@ import * as RadixTabs from "@radix-ui/react-tabs"; + import type { SidebarTabName } from "../../types"; export const SidebarTab = ({ diff --git a/packages/excalidraw/components/Sidebar/SidebarTabTrigger.tsx b/packages/excalidraw/components/Sidebar/SidebarTabTrigger.tsx index 8509ef23d..9f2c09bcc 100644 --- a/packages/excalidraw/components/Sidebar/SidebarTabTrigger.tsx +++ b/packages/excalidraw/components/Sidebar/SidebarTabTrigger.tsx @@ -1,4 +1,5 @@ import * as RadixTabs from "@radix-ui/react-tabs"; + import type { SidebarTabName } from "../../types"; export const SidebarTabTrigger = ({ diff --git a/packages/excalidraw/components/Sidebar/SidebarTabs.tsx b/packages/excalidraw/components/Sidebar/SidebarTabs.tsx index a681b5ee5..448840c4a 100644 --- a/packages/excalidraw/components/Sidebar/SidebarTabs.tsx +++ b/packages/excalidraw/components/Sidebar/SidebarTabs.tsx @@ -1,4 +1,5 @@ import * as RadixTabs from "@radix-ui/react-tabs"; + import { useUIAppState } from "../../context/ui-appState"; import { useExcalidrawSetAppState } from "../App"; diff --git a/packages/excalidraw/components/Sidebar/SidebarTrigger.tsx b/packages/excalidraw/components/Sidebar/SidebarTrigger.tsx index a26e52d23..6e8bf374c 100644 --- a/packages/excalidraw/components/Sidebar/SidebarTrigger.tsx +++ b/packages/excalidraw/components/Sidebar/SidebarTrigger.tsx @@ -1,10 +1,12 @@ -import { useExcalidrawSetAppState } from "../App"; -import type { SidebarTriggerProps } from "./common"; -import { useUIAppState } from "../../context/ui-appState"; import clsx from "clsx"; +import { useUIAppState } from "../../context/ui-appState"; +import { useExcalidrawSetAppState } from "../App"; + import "./SidebarTrigger.scss"; +import type { SidebarTriggerProps } from "./common"; + export const SidebarTrigger = ({ name, tab, diff --git a/packages/excalidraw/components/Sidebar/common.ts b/packages/excalidraw/components/Sidebar/common.ts index 35c0c8bb1..239b16fc9 100644 --- a/packages/excalidraw/components/Sidebar/common.ts +++ b/packages/excalidraw/components/Sidebar/common.ts @@ -1,6 +1,7 @@ -import type { JSX } from "react"; import React from "react"; + import type { AppState, SidebarName, SidebarTabName } from "../../types"; +import type { JSX } from "react"; export type SidebarTriggerProps = { name: SidebarName; diff --git a/packages/excalidraw/components/Sidebar/siderbar.test.helpers.tsx b/packages/excalidraw/components/Sidebar/siderbar.test.helpers.tsx index c2a37431b..650eca6b0 100644 --- a/packages/excalidraw/components/Sidebar/siderbar.test.helpers.tsx +++ b/packages/excalidraw/components/Sidebar/siderbar.test.helpers.tsx @@ -1,4 +1,5 @@ import React from "react"; + import { Excalidraw } from "../.."; import { GlobalTestState, diff --git a/packages/excalidraw/components/Stack.tsx b/packages/excalidraw/components/Stack.tsx index f45d47118..75e559aa3 100644 --- a/packages/excalidraw/components/Stack.tsx +++ b/packages/excalidraw/components/Stack.tsx @@ -1,8 +1,8 @@ -import "./Stack.scss"; - import React, { forwardRef } from "react"; import clsx from "clsx"; +import "./Stack.scss"; + type StackProps = { children: React.ReactNode; gap?: number; diff --git a/packages/excalidraw/components/Stats/Angle.tsx b/packages/excalidraw/components/Stats/Angle.tsx index 409476ada..10c76d519 100644 --- a/packages/excalidraw/components/Stats/Angle.tsx +++ b/packages/excalidraw/components/Stats/Angle.tsx @@ -1,15 +1,19 @@ +import { degreesToRadians, radiansToDegrees } from "@excalidraw/math"; + +import type { Degrees } from "@excalidraw/math"; + import { mutateElement } from "../../element/mutateElement"; import { getBoundTextElement } from "../../element/textElement"; import { isArrowElement, isElbowArrow } from "../../element/typeChecks"; -import type { ExcalidrawElement } from "../../element/types"; import { angleIcon } from "../icons"; + import DragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; import { getStepSizedValue, isPropertyEditable, updateBindings } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; +import type { ExcalidrawElement } from "../../element/types"; import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import type { Degrees } from "@excalidraw/math"; -import { degreesToRadians, radiansToDegrees } from "@excalidraw/math"; interface AngleProps { element: ExcalidrawElement; diff --git a/packages/excalidraw/components/Stats/CanvasGrid.tsx b/packages/excalidraw/components/Stats/CanvasGrid.tsx index a08f709ae..4611365f4 100644 --- a/packages/excalidraw/components/Stats/CanvasGrid.tsx +++ b/packages/excalidraw/components/Stats/CanvasGrid.tsx @@ -1,8 +1,10 @@ +import { getNormalizedGridStep } from "../../scene"; + import StatsDragInput from "./DragInput"; +import { getStepSizedValue } from "./utils"; + import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import { getStepSizedValue } from "./utils"; -import { getNormalizedGridStep } from "../../scene"; interface PositionProps { property: "gridStep"; diff --git a/packages/excalidraw/components/Stats/Dimension.tsx b/packages/excalidraw/components/Stats/Dimension.tsx index ce096d280..f58c06acc 100644 --- a/packages/excalidraw/components/Stats/Dimension.tsx +++ b/packages/excalidraw/components/Stats/Dimension.tsx @@ -1,18 +1,21 @@ -import type { ExcalidrawElement } from "../../element/types"; -import DragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; -import { getStepSizedValue, isPropertyEditable } from "./utils"; +import { clamp, round } from "@excalidraw/math"; + import { MIN_WIDTH_OR_HEIGHT } from "../../constants"; -import { resizeSingleElement } from "../../element/resizeElements"; -import type Scene from "../../scene/Scene"; -import type { AppState } from "../../types"; -import { isImageElement } from "../../element/typeChecks"; import { MINIMAL_CROP_SIZE, getUncroppedWidthAndHeight, } from "../../element/cropElement"; import { mutateElement } from "../../element/mutateElement"; -import { clamp, round } from "@excalidraw/math"; +import { resizeSingleElement } from "../../element/resizeElements"; +import { isImageElement } from "../../element/typeChecks"; + +import DragInput from "./DragInput"; +import { getStepSizedValue, isPropertyEditable } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; +import type { ExcalidrawElement } from "../../element/types"; +import type Scene from "../../scene/Scene"; +import type { AppState } from "../../types"; interface DimensionDragInputProps { property: "width" | "height"; diff --git a/packages/excalidraw/components/Stats/DragInput.tsx b/packages/excalidraw/components/Stats/DragInput.tsx index 82d6419c0..fbea33e55 100644 --- a/packages/excalidraw/components/Stats/DragInput.tsx +++ b/packages/excalidraw/components/Stats/DragInput.tsx @@ -1,19 +1,22 @@ -import { useEffect, useRef, useState } from "react"; -import { EVENT } from "../../constants"; -import { KEYS } from "../../keys"; -import type { ElementsMap, ExcalidrawElement } from "../../element/types"; -import { deepCopyElement } from "../../element/newElement"; import clsx from "clsx"; +import { useEffect, useRef, useState } from "react"; + +import { EVENT } from "../../constants"; +import { deepCopyElement } from "../../element/newElement"; +import { KEYS } from "../../keys"; +import { CaptureUpdateAction } from "../../store"; +import { cloneJSON } from "../../utils"; import { useApp } from "../App"; import { InlineIcon } from "../InlineIcon"; -import type { StatsInputProperty } from "./utils"; + import { SMALLEST_DELTA } from "./utils"; -import { CaptureUpdateAction } from "../../store"; -import type Scene from "../../scene/Scene"; import "./DragInput.scss"; + +import type { StatsInputProperty } from "./utils"; +import type { ElementsMap, ExcalidrawElement } from "../../element/types"; +import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import { cloneJSON } from "../../utils"; export type DragInputCallbackType< P extends StatsInputProperty, diff --git a/packages/excalidraw/components/Stats/FontSize.tsx b/packages/excalidraw/components/Stats/FontSize.tsx index 13dc6dbee..4fbdab833 100644 --- a/packages/excalidraw/components/Stats/FontSize.tsx +++ b/packages/excalidraw/components/Stats/FontSize.tsx @@ -1,17 +1,19 @@ +import { isTextElement, redrawTextBoundingBox } from "../../element"; +import { mutateElement } from "../../element/mutateElement"; +import { getBoundTextElement } from "../../element/textElement"; +import { hasBoundTextElement } from "../../element/typeChecks"; +import { fontSizeIcon } from "../icons"; + +import StatsDragInput from "./DragInput"; +import { getStepSizedValue } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; import type { ExcalidrawElement, ExcalidrawTextElement, } from "../../element/types"; -import StatsDragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; -import { mutateElement } from "../../element/mutateElement"; -import { getStepSizedValue } from "./utils"; -import { fontSizeIcon } from "../icons"; import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import { isTextElement, redrawTextBoundingBox } from "../../element"; -import { hasBoundTextElement } from "../../element/typeChecks"; -import { getBoundTextElement } from "../../element/textElement"; interface FontSizeProps { element: ExcalidrawElement; diff --git a/packages/excalidraw/components/Stats/MultiAngle.tsx b/packages/excalidraw/components/Stats/MultiAngle.tsx index d9a78825a..ec314c183 100644 --- a/packages/excalidraw/components/Stats/MultiAngle.tsx +++ b/packages/excalidraw/components/Stats/MultiAngle.tsx @@ -1,16 +1,20 @@ +import { degreesToRadians, radiansToDegrees } from "@excalidraw/math"; + +import type { Degrees } from "@excalidraw/math"; + import { mutateElement } from "../../element/mutateElement"; import { getBoundTextElement } from "../../element/textElement"; import { isArrowElement } from "../../element/typeChecks"; -import type { ExcalidrawElement } from "../../element/types"; import { isInGroup } from "../../groups"; -import type Scene from "../../scene/Scene"; import { angleIcon } from "../icons"; + import DragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; import { getStepSizedValue, isPropertyEditable } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; +import type { ExcalidrawElement } from "../../element/types"; +import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import type { Degrees } from "@excalidraw/math"; -import { degreesToRadians, radiansToDegrees } from "@excalidraw/math"; interface MultiAngleProps { elements: readonly ExcalidrawElement[]; diff --git a/packages/excalidraw/components/Stats/MultiDimension.tsx b/packages/excalidraw/components/Stats/MultiDimension.tsx index 04f193747..fb9cea942 100644 --- a/packages/excalidraw/components/Stats/MultiDimension.tsx +++ b/packages/excalidraw/components/Stats/MultiDimension.tsx @@ -1,4 +1,7 @@ +import { pointFrom, type GlobalPoint } from "@excalidraw/math"; import { useMemo } from "react"; + +import { MIN_WIDTH_OR_HEIGHT } from "../../constants"; import { getCommonBounds, isTextElement } from "../../element"; import { updateBoundElements } from "../../element/binding"; import { mutateElement } from "../../element/mutateElement"; @@ -10,6 +13,13 @@ import { getBoundTextElement, handleBindTextResize, } from "../../element/textElement"; + +import DragInput from "./DragInput"; +import { getAtomicUnits, getStepSizedValue, isPropertyEditable } from "./utils"; +import { getElementsInAtomicUnit } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; +import type { AtomicUnit } from "./utils"; import type { ElementsMap, ExcalidrawElement, @@ -17,13 +27,6 @@ import type { } from "../../element/types"; import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import DragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; -import { getAtomicUnits, getStepSizedValue, isPropertyEditable } from "./utils"; -import { getElementsInAtomicUnit } from "./utils"; -import type { AtomicUnit } from "./utils"; -import { MIN_WIDTH_OR_HEIGHT } from "../../constants"; -import { pointFrom, type GlobalPoint } from "@excalidraw/math"; interface MultiDimensionProps { property: "width" | "height"; diff --git a/packages/excalidraw/components/Stats/MultiFontSize.tsx b/packages/excalidraw/components/Stats/MultiFontSize.tsx index 419bbbc36..8335399ef 100644 --- a/packages/excalidraw/components/Stats/MultiFontSize.tsx +++ b/packages/excalidraw/components/Stats/MultiFontSize.tsx @@ -1,19 +1,21 @@ import { isTextElement, redrawTextBoundingBox } from "../../element"; import { mutateElement } from "../../element/mutateElement"; +import { getBoundTextElement } from "../../element/textElement"; import { hasBoundTextElement } from "../../element/typeChecks"; +import { isInGroup } from "../../groups"; +import { fontSizeIcon } from "../icons"; + +import StatsDragInput from "./DragInput"; +import { getStepSizedValue } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; import type { ExcalidrawElement, ExcalidrawTextElement, NonDeletedSceneElementsMap, } from "../../element/types"; -import { isInGroup } from "../../groups"; import type Scene from "../../scene/Scene"; -import { fontSizeIcon } from "../icons"; -import StatsDragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; -import { getStepSizedValue } from "./utils"; import type { AppState } from "../../types"; -import { getBoundTextElement } from "../../element/textElement"; interface MultiFontSizeProps { elements: readonly ExcalidrawElement[]; diff --git a/packages/excalidraw/components/Stats/MultiPosition.tsx b/packages/excalidraw/components/Stats/MultiPosition.tsx index 8a29aa66d..a8fdacf29 100644 --- a/packages/excalidraw/components/Stats/MultiPosition.tsx +++ b/packages/excalidraw/components/Stats/MultiPosition.tsx @@ -1,3 +1,14 @@ +import { pointFrom, pointRotateRads } from "@excalidraw/math"; +import { useMemo } from "react"; + +import { getCommonBounds, isTextElement } from "../../element"; + +import StatsDragInput from "./DragInput"; +import { getAtomicUnits, getStepSizedValue, isPropertyEditable } from "./utils"; +import { getElementsInAtomicUnit, moveElement } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; +import type { AtomicUnit } from "./utils"; import type { ElementsMap, ExcalidrawElement, @@ -5,15 +16,7 @@ import type { NonDeletedSceneElementsMap, } from "../../element/types"; import type Scene from "../../scene/Scene"; -import StatsDragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; -import { getAtomicUnits, getStepSizedValue, isPropertyEditable } from "./utils"; -import { getCommonBounds, isTextElement } from "../../element"; -import { useMemo } from "react"; -import { getElementsInAtomicUnit, moveElement } from "./utils"; -import type { AtomicUnit } from "./utils"; import type { AppState } from "../../types"; -import { pointFrom, pointRotateRads } from "@excalidraw/math"; interface MultiPositionProps { property: "x" | "y"; diff --git a/packages/excalidraw/components/Stats/Position.tsx b/packages/excalidraw/components/Stats/Position.tsx index 038e58ebc..08d0a8830 100644 --- a/packages/excalidraw/components/Stats/Position.tsx +++ b/packages/excalidraw/components/Stats/Position.tsx @@ -1,16 +1,19 @@ -import type { ElementsMap, ExcalidrawElement } from "../../element/types"; -import StatsDragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; -import { getStepSizedValue, moveElement } from "./utils"; -import type Scene from "../../scene/Scene"; -import type { AppState } from "../../types"; import { clamp, pointFrom, pointRotateRads, round } from "@excalidraw/math"; -import { isImageElement } from "../../element/typeChecks"; + import { getFlipAdjustedCropPosition, getUncroppedWidthAndHeight, } from "../../element/cropElement"; import { mutateElement } from "../../element/mutateElement"; +import { isImageElement } from "../../element/typeChecks"; + +import StatsDragInput from "./DragInput"; +import { getStepSizedValue, moveElement } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; +import type { ElementsMap, ExcalidrawElement } from "../../element/types"; +import type Scene from "../../scene/Scene"; +import type { AppState } from "../../types"; interface PositionProps { property: "x" | "y"; diff --git a/packages/excalidraw/components/Stats/index.tsx b/packages/excalidraw/components/Stats/index.tsx index 2ccd93ca2..56764fefb 100644 --- a/packages/excalidraw/components/Stats/index.tsx +++ b/packages/excalidraw/components/Stats/index.tsx @@ -1,37 +1,40 @@ +import { round } from "@excalidraw/math"; +import clsx from "clsx"; +import throttle from "lodash.throttle"; import { useEffect, useMemo, useState, memo } from "react"; + +import { STATS_PANELS } from "../../constants"; import { getCommonBounds } from "../../element/bounds"; -import type { NonDeletedExcalidrawElement } from "../../element/types"; +import { getUncroppedWidthAndHeight } from "../../element/cropElement"; +import { isElbowArrow, isImageElement } from "../../element/typeChecks"; +import { frameAndChildrenSelectedTogether } from "../../frame"; +import { elementsAreInSameGroup } from "../../groups"; import { t } from "../../i18n"; +import { isGridModeEnabled } from "../../snapping"; +import { useExcalidrawAppState, useExcalidrawSetAppState } from "../App"; +import { Island } from "../Island"; +import { CloseIcon } from "../icons"; + +import Angle from "./Angle"; +import CanvasGrid from "./CanvasGrid"; +import Collapsible from "./Collapsible"; +import Dimension from "./Dimension"; +import FontSize from "./FontSize"; +import MultiAngle from "./MultiAngle"; +import MultiDimension from "./MultiDimension"; +import MultiFontSize from "./MultiFontSize"; +import MultiPosition from "./MultiPosition"; +import Position from "./Position"; +import { getAtomicUnits } from "./utils"; + +import "./Stats.scss"; + +import type { NonDeletedExcalidrawElement } from "../../element/types"; import type { AppClassProperties, AppState, ExcalidrawProps, } from "../../types"; -import { CloseIcon } from "../icons"; -import { Island } from "../Island"; -import throttle from "lodash.throttle"; -import Dimension from "./Dimension"; -import Angle from "./Angle"; -import FontSize from "./FontSize"; -import MultiDimension from "./MultiDimension"; -import { elementsAreInSameGroup } from "../../groups"; -import MultiAngle from "./MultiAngle"; -import MultiFontSize from "./MultiFontSize"; -import Position from "./Position"; -import MultiPosition from "./MultiPosition"; -import Collapsible from "./Collapsible"; -import { useExcalidrawAppState, useExcalidrawSetAppState } from "../App"; -import { getAtomicUnits } from "./utils"; -import { STATS_PANELS } from "../../constants"; -import { isElbowArrow, isImageElement } from "../../element/typeChecks"; -import CanvasGrid from "./CanvasGrid"; -import clsx from "clsx"; - -import "./Stats.scss"; -import { isGridModeEnabled } from "../../snapping"; -import { getUncroppedWidthAndHeight } from "../../element/cropElement"; -import { round } from "@excalidraw/math"; -import { frameAndChildrenSelectedTogether } from "../../frame"; interface StatsProps { app: AppClassProperties; diff --git a/packages/excalidraw/components/Stats/stats.test.tsx b/packages/excalidraw/components/Stats/stats.test.tsx index 49d6a625f..b1fe0d685 100644 --- a/packages/excalidraw/components/Stats/stats.test.tsx +++ b/packages/excalidraw/components/Stats/stats.test.tsx @@ -1,31 +1,35 @@ -import React from "react"; +import { degreesToRadians, pointFrom, pointRotateRads } from "@excalidraw/math"; import { act, fireEvent, queryByTestId } from "@testing-library/react"; +import React from "react"; +import { vi } from "vitest"; + +import type { Degrees } from "@excalidraw/math"; + +import { Excalidraw, mutateElement } from "../.."; +import { actionGroup } from "../../actions"; +import { getCommonBounds, isTextElement } from "../../element"; +import { isInGroup } from "../../groups"; +import { t } from "../../i18n"; +import { reseed } from "../../random"; +import * as StaticScene from "../../renderer/staticScene"; +import { API } from "../../tests/helpers/api"; import { Keyboard, Pointer, UI } from "../../tests/helpers/ui"; -import { getStepSizedValue } from "./utils"; +import { getTextEditor, updateTextEditor } from "../../tests/queries/dom"; import { GlobalTestState, mockBoundingClientRect, render, restoreOriginalGetBoundingClientRect, } from "../../tests/test-utils"; -import * as StaticScene from "../../renderer/staticScene"; -import { vi } from "vitest"; -import { reseed } from "../../random"; import { setDateTimeForTests } from "../../utils"; -import { Excalidraw, mutateElement } from "../.."; -import { t } from "../../i18n"; + +import { getStepSizedValue } from "./utils"; + import type { ExcalidrawElement, ExcalidrawLinearElement, ExcalidrawTextElement, } from "../../element/types"; -import { getTextEditor, updateTextEditor } from "../../tests/queries/dom"; -import { getCommonBounds, isTextElement } from "../../element"; -import { API } from "../../tests/helpers/api"; -import { actionGroup } from "../../actions"; -import { isInGroup } from "../../groups"; -import type { Degrees } from "@excalidraw/math"; -import { degreesToRadians, pointFrom, pointRotateRads } from "@excalidraw/math"; const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/components/Stats/utils.ts b/packages/excalidraw/components/Stats/utils.ts index 61555baeb..219e02fa5 100644 --- a/packages/excalidraw/components/Stats/utils.ts +++ b/packages/excalidraw/components/Stats/utils.ts @@ -1,5 +1,7 @@ -import type { Radians } from "@excalidraw/math"; import { pointFrom, pointRotateRads } from "@excalidraw/math"; + +import type { Radians } from "@excalidraw/math"; + import { bindOrUnbindLinearElements, updateBoundElements, @@ -11,17 +13,18 @@ import { isLinearElement, isTextElement, } from "../../element/typeChecks"; +import { + getSelectedGroupIds, + getElementsInGroup, + isInGroup, +} from "../../groups"; + import type { ElementsMap, ExcalidrawElement, NonDeletedExcalidrawElement, NonDeletedSceneElementsMap, } from "../../element/types"; -import { - getSelectedGroupIds, - getElementsInGroup, - isInGroup, -} from "../../groups"; import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; diff --git a/packages/excalidraw/components/TTDDialog/MermaidToExcalidraw.tsx b/packages/excalidraw/components/TTDDialog/MermaidToExcalidraw.tsx index 83fb91d0e..b8cd48dfa 100644 --- a/packages/excalidraw/components/TTDDialog/MermaidToExcalidraw.tsx +++ b/packages/excalidraw/components/TTDDialog/MermaidToExcalidraw.tsx @@ -1,25 +1,29 @@ import { useState, useRef, useEffect, useDeferredValue } from "react"; -import type { BinaryFiles } from "../../types"; + import { useApp } from "../App"; -import type { NonDeletedExcalidrawElement } from "../../element/types"; import { ArrowRightIcon } from "../icons"; -import "./MermaidToExcalidraw.scss"; +import { EDITOR_LS_KEYS } from "../../constants"; +import { EditorLocalStorage } from "../../data/EditorLocalStorage"; import { t } from "../../i18n"; +import { debounce, isDevEnv } from "../../utils"; import Trans from "../Trans"; -import type { MermaidToExcalidrawLibProps } from "./common"; + +import { TTDDialogInput } from "./TTDDialogInput"; +import { TTDDialogOutput } from "./TTDDialogOutput"; +import { TTDDialogPanel } from "./TTDDialogPanel"; +import { TTDDialogPanels } from "./TTDDialogPanels"; +import { TTDDialogSubmitShortcut } from "./TTDDialogSubmitShortcut"; import { convertMermaidToExcalidraw, insertToEditor, saveMermaidDataToStorage, } from "./common"; -import { TTDDialogPanels } from "./TTDDialogPanels"; -import { TTDDialogPanel } from "./TTDDialogPanel"; -import { TTDDialogInput } from "./TTDDialogInput"; -import { TTDDialogOutput } from "./TTDDialogOutput"; -import { EditorLocalStorage } from "../../data/EditorLocalStorage"; -import { EDITOR_LS_KEYS } from "../../constants"; -import { debounce, isDevEnv } from "../../utils"; -import { TTDDialogSubmitShortcut } from "./TTDDialogSubmitShortcut"; + +import "./MermaidToExcalidraw.scss"; + +import type { BinaryFiles } from "../../types"; +import type { MermaidToExcalidrawLibProps } from "./common"; +import type { NonDeletedExcalidrawElement } from "../../element/types"; const MERMAID_EXAMPLE = "flowchart TD\n A[Christmas] -->|Get money| B(Go shopping)\n B --> C{Let me think}\n C -->|One| D[Laptop]\n C -->|Two| E[iPhone]\n C -->|Three| F[Car]"; diff --git a/packages/excalidraw/components/TTDDialog/TTDDialog.tsx b/packages/excalidraw/components/TTDDialog/TTDDialog.tsx index c77dfbf68..3b9b868f7 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialog.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialog.tsx @@ -1,35 +1,39 @@ -import { Dialog } from "../Dialog"; +import { isFiniteNumber } from "@excalidraw/math"; +import { useEffect, useRef, useState } from "react"; + +import { trackEvent } from "../../analytics"; +import { useUIAppState } from "../../context/ui-appState"; +import { atom, useAtom } from "../../editor-jotai"; +import { t } from "../../i18n"; import { useApp, useExcalidrawSetAppState } from "../App"; +import { Dialog } from "../Dialog"; +import { InlineIcon } from "../InlineIcon"; +import { withInternalFallback } from "../hoc/withInternalFallback"; +import { ArrowRightIcon } from "../icons"; + import MermaidToExcalidraw from "./MermaidToExcalidraw"; import TTDDialogTabs from "./TTDDialogTabs"; -import type { ChangeEventHandler } from "react"; -import { useEffect, useRef, useState } from "react"; -import { useUIAppState } from "../../context/ui-appState"; -import { withInternalFallback } from "../hoc/withInternalFallback"; import { TTDDialogTabTriggers } from "./TTDDialogTabTriggers"; import { TTDDialogTabTrigger } from "./TTDDialogTabTrigger"; import { TTDDialogTab } from "./TTDDialogTab"; -import { t } from "../../i18n"; import { TTDDialogInput } from "./TTDDialogInput"; import { TTDDialogOutput } from "./TTDDialogOutput"; import { TTDDialogPanel } from "./TTDDialogPanel"; import { TTDDialogPanels } from "./TTDDialogPanels"; -import type { MermaidToExcalidrawLibProps } from "./common"; + import { convertMermaidToExcalidraw, insertToEditor, saveMermaidDataToStorage, } from "./common"; -import type { NonDeletedExcalidrawElement } from "../../element/types"; -import type { BinaryFiles } from "../../types"; -import { ArrowRightIcon } from "../icons"; +import { TTDDialogSubmitShortcut } from "./TTDDialogSubmitShortcut"; import "./TTDDialog.scss"; -import { atom, useAtom } from "../../editor-jotai"; -import { trackEvent } from "../../analytics"; -import { InlineIcon } from "../InlineIcon"; -import { TTDDialogSubmitShortcut } from "./TTDDialogSubmitShortcut"; -import { isFiniteNumber } from "@excalidraw/math"; + +import type { ChangeEventHandler } from "react"; +import type { MermaidToExcalidrawLibProps } from "./common"; +import type { NonDeletedExcalidrawElement } from "../../element/types"; +import type { BinaryFiles } from "../../types"; const MIN_PROMPT_LENGTH = 3; const MAX_PROMPT_LENGTH = 1000; diff --git a/packages/excalidraw/components/TTDDialog/TTDDialogInput.tsx b/packages/excalidraw/components/TTDDialog/TTDDialogInput.tsx index e11d0dc3f..8e349643e 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialogInput.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialogInput.tsx @@ -1,8 +1,10 @@ -import type { ChangeEventHandler } from "react"; import { useEffect, useRef } from "react"; + import { EVENT } from "../../constants"; import { KEYS } from "../../keys"; +import type { ChangeEventHandler } from "react"; + interface TTDDialogInputProps { input: string; placeholder: string; diff --git a/packages/excalidraw/components/TTDDialog/TTDDialogPanel.tsx b/packages/excalidraw/components/TTDDialog/TTDDialogPanel.tsx index 0a78e4969..82aede8ae 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialogPanel.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialogPanel.tsx @@ -1,8 +1,10 @@ -import type { ReactNode } from "react"; -import { Button } from "../Button"; import clsx from "clsx"; + +import { Button } from "../Button"; import Spinner from "../Spinner"; +import type { ReactNode } from "react"; + interface TTDDialogPanelProps { label: string; children: ReactNode; diff --git a/packages/excalidraw/components/TTDDialog/TTDDialogTabs.tsx b/packages/excalidraw/components/TTDDialog/TTDDialogTabs.tsx index 439f92844..1c9075e7d 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialogTabs.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialogTabs.tsx @@ -1,8 +1,10 @@ import * as RadixTabs from "@radix-ui/react-tabs"; -import type { ReactNode } from "react"; import { useRef } from "react"; -import { useExcalidrawSetAppState } from "../App"; + import { isMemberOf } from "../../utils"; +import { useExcalidrawSetAppState } from "../App"; + +import type { ReactNode } from "react"; const TTDDialogTabs = ( props: { diff --git a/packages/excalidraw/components/TTDDialog/TTDDialogTrigger.tsx b/packages/excalidraw/components/TTDDialog/TTDDialogTrigger.tsx index a73f31a68..833b659fe 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialogTrigger.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialogTrigger.tsx @@ -1,11 +1,12 @@ -import type { JSX } from "react"; -import type { ReactNode } from "react"; -import { useTunnels } from "../../context/tunnels"; -import DropdownMenu from "../dropdownMenu/DropdownMenu"; -import { useExcalidrawSetAppState } from "../App"; -import { brainIcon } from "../icons"; -import { t } from "../../i18n"; import { trackEvent } from "../../analytics"; +import { useTunnels } from "../../context/tunnels"; +import { t } from "../../i18n"; +import { useExcalidrawSetAppState } from "../App"; +import DropdownMenu from "../dropdownMenu/DropdownMenu"; +import { brainIcon } from "../icons"; + +import type { ReactNode } from "react"; +import type { JSX } from "react"; export const TTDDialogTrigger = ({ children, diff --git a/packages/excalidraw/components/TTDDialog/common.ts b/packages/excalidraw/components/TTDDialog/common.ts index 4191126a4..89c342c65 100644 --- a/packages/excalidraw/components/TTDDialog/common.ts +++ b/packages/excalidraw/components/TTDDialog/common.ts @@ -1,12 +1,14 @@ import type { MermaidConfig } from "@excalidraw/mermaid-to-excalidraw"; import type { MermaidToExcalidrawResult } from "@excalidraw/mermaid-to-excalidraw/dist/interfaces"; + import { DEFAULT_EXPORT_PADDING, EDITOR_LS_KEYS } from "../../constants"; +import { EditorLocalStorage } from "../../data/EditorLocalStorage"; +import { canvasToBlob } from "../../data/blob"; +import { t } from "../../i18n"; import { convertToExcalidrawElements, exportToCanvas } from "../../index"; + import type { NonDeletedExcalidrawElement } from "../../element/types"; import type { AppClassProperties, BinaryFiles } from "../../types"; -import { canvasToBlob } from "../../data/blob"; -import { EditorLocalStorage } from "../../data/EditorLocalStorage"; -import { t } from "../../i18n"; const resetPreview = ({ canvasRef, diff --git a/packages/excalidraw/components/TextField.tsx b/packages/excalidraw/components/TextField.tsx index c5bdc8260..d6bc315b1 100644 --- a/packages/excalidraw/components/TextField.tsx +++ b/packages/excalidraw/components/TextField.tsx @@ -1,4 +1,4 @@ -import type { KeyboardEvent } from "react"; +import clsx from "clsx"; import { forwardRef, useRef, @@ -6,12 +6,14 @@ import { useLayoutEffect, useState, } from "react"; -import clsx from "clsx"; -import "./TextField.scss"; import { Button } from "./Button"; import { eyeIcon, eyeClosedIcon } from "./icons"; +import "./TextField.scss"; + +import type { KeyboardEvent } from "react"; + type TextFieldProps = { onChange?: (value: string) => void; onClick?: () => void; diff --git a/packages/excalidraw/components/Toast.tsx b/packages/excalidraw/components/Toast.tsx index d99c9f648..a7167c00f 100644 --- a/packages/excalidraw/components/Toast.tsx +++ b/packages/excalidraw/components/Toast.tsx @@ -1,9 +1,12 @@ -import type { CSSProperties } from "react"; import { useCallback, useEffect, useRef } from "react"; + import { CloseIcon } from "./icons"; -import "./Toast.scss"; import { ToolButton } from "./ToolButton"; +import "./Toast.scss"; + +import type { CSSProperties } from "react"; + const DEFAULT_TOAST_TIMEOUT = 5000; export const Toast = ({ diff --git a/packages/excalidraw/components/ToolButton.tsx b/packages/excalidraw/components/ToolButton.tsx index 09b0b6cf8..fb76731b0 100644 --- a/packages/excalidraw/components/ToolButton.tsx +++ b/packages/excalidraw/components/ToolButton.tsx @@ -1,13 +1,16 @@ +import clsx from "clsx"; +import React, { useEffect, useRef, useState } from "react"; + +import { AbortError } from "../errors"; +import { isPromiseLike } from "../utils"; + import "./ToolIcon.scss"; -import type { CSSProperties } from "react"; -import React, { useEffect, useRef, useState } from "react"; -import clsx from "clsx"; -import { useExcalidrawContainer } from "./App"; -import { AbortError } from "../errors"; import Spinner from "./Spinner"; +import { useExcalidrawContainer } from "./App"; + import type { PointerType } from "../element/types"; -import { isPromiseLike } from "../utils"; +import type { CSSProperties } from "react"; export type ToolButtonSize = "small" | "medium"; diff --git a/packages/excalidraw/components/Tooltip.tsx b/packages/excalidraw/components/Tooltip.tsx index 38c04ef23..9c7c7ea0c 100644 --- a/packages/excalidraw/components/Tooltip.tsx +++ b/packages/excalidraw/components/Tooltip.tsx @@ -1,7 +1,7 @@ -import "./Tooltip.scss"; - import React, { useEffect } from "react"; +import "./Tooltip.scss"; + export const getTooltipDiv = () => { const existingDiv = document.querySelector( ".excalidraw-tooltip", diff --git a/packages/excalidraw/components/Trans.test.tsx b/packages/excalidraw/components/Trans.test.tsx index c331796bd..077fcb88c 100644 --- a/packages/excalidraw/components/Trans.test.tsx +++ b/packages/excalidraw/components/Trans.test.tsx @@ -1,10 +1,11 @@ import { render } from "@testing-library/react"; +import { EditorJotaiProvider } from "../editor-jotai"; import fallbackLangData from "../locales/en.json"; import Trans from "./Trans"; + import type { TranslationKeys } from "../i18n"; -import { EditorJotaiProvider } from "../editor-jotai"; describe("Test ", () => { it("should translate the the strings correctly", () => { diff --git a/packages/excalidraw/components/Trans.tsx b/packages/excalidraw/components/Trans.tsx index 0cb0f78cb..7a6215c89 100644 --- a/packages/excalidraw/components/Trans.tsx +++ b/packages/excalidraw/components/Trans.tsx @@ -1,8 +1,9 @@ import React from "react"; -import type { TranslationKeys } from "../i18n"; import { useI18n } from "../i18n"; +import type { TranslationKeys } from "../i18n"; + // Used for splitting i18nKey into tokens in Trans component // Example: // "Please click {{location}} to continue.".split(SPLIT_REGEX).filter(Boolean) diff --git a/packages/excalidraw/components/UserList.tsx b/packages/excalidraw/components/UserList.tsx index 9fbfc1aed..6c74411a1 100644 --- a/packages/excalidraw/components/UserList.tsx +++ b/packages/excalidraw/components/UserList.tsx @@ -1,20 +1,22 @@ -import "./UserList.scss"; - -import React, { useLayoutEffect } from "react"; -import clsx from "clsx"; -import type { Collaborator, SocketId } from "../types"; -import { Tooltip } from "./Tooltip"; -import { useExcalidrawActionManager } from "./App"; -import type { ActionManager } from "../actions/manager"; - import * as Popover from "@radix-ui/react-popover"; -import { Island } from "./Island"; -import { QuickSearch } from "./QuickSearch"; +import clsx from "clsx"; +import React, { useLayoutEffect } from "react"; + +import { supportsResizeObserver } from "../constants"; import { t } from "../i18n"; import { isShallowEqual } from "../utils"; -import { supportsResizeObserver } from "../constants"; -import type { MarkRequired } from "../utility-types"; + +import { useExcalidrawActionManager } from "./App"; +import { Island } from "./Island"; +import { QuickSearch } from "./QuickSearch"; import { ScrollableList } from "./ScrollableList"; +import { Tooltip } from "./Tooltip"; + +import "./UserList.scss"; + +import type { ActionManager } from "../actions/manager"; +import type { Collaborator, SocketId } from "../types"; +import type { MarkRequired } from "../utility-types"; export type GoToCollaboratorComponentProps = { socketId: SocketId; diff --git a/packages/excalidraw/components/canvases/InteractiveCanvas.tsx b/packages/excalidraw/components/canvases/InteractiveCanvas.tsx index 03ae0f6b6..8388e5e6c 100644 --- a/packages/excalidraw/components/canvases/InteractiveCanvas.tsx +++ b/packages/excalidraw/components/canvases/InteractiveCanvas.tsx @@ -1,20 +1,22 @@ import React, { useEffect, useRef } from "react"; -import { isShallowEqual, sceneCoordsToViewportCoords } from "../../utils"; + import { CURSOR_TYPE } from "../../constants"; import { t } from "../../i18n"; -import type { DOMAttributes } from "react"; -import type { AppState, Device, InteractiveCanvasAppState } from "../../types"; +import { isRenderThrottlingEnabled } from "../../reactUtils"; +import { renderInteractiveScene } from "../../renderer/interactiveScene"; +import { isShallowEqual, sceneCoordsToViewportCoords } from "../../utils"; + +import type { + NonDeletedExcalidrawElement, + NonDeletedSceneElementsMap, +} from "../../element/types"; import type { InteractiveCanvasRenderConfig, RenderableElementsMap, RenderInteractiveSceneCallback, } from "../../scene/types"; -import type { - NonDeletedExcalidrawElement, - NonDeletedSceneElementsMap, -} from "../../element/types"; -import { isRenderThrottlingEnabled } from "../../reactUtils"; -import { renderInteractiveScene } from "../../renderer/interactiveScene"; +import type { AppState, Device, InteractiveCanvasAppState } from "../../types"; +import type { DOMAttributes } from "react"; type InteractiveCanvasProps = { containerRef: React.RefObject; diff --git a/packages/excalidraw/components/canvases/NewElementCanvas.tsx b/packages/excalidraw/components/canvases/NewElementCanvas.tsx index 181567110..524d6af34 100644 --- a/packages/excalidraw/components/canvases/NewElementCanvas.tsx +++ b/packages/excalidraw/components/canvases/NewElementCanvas.tsx @@ -1,13 +1,15 @@ import { useEffect, useRef } from "react"; + +import { isRenderThrottlingEnabled } from "../../reactUtils"; +import { renderNewElementScene } from "../../renderer/renderNewElementScene"; + import type { NonDeletedSceneElementsMap } from "../../element/types"; -import type { AppState } from "../../types"; import type { RenderableElementsMap, StaticCanvasRenderConfig, } from "../../scene/types"; +import type { AppState } from "../../types"; import type { RoughCanvas } from "roughjs/bin/canvas"; -import { renderNewElementScene } from "../../renderer/renderNewElementScene"; -import { isRenderThrottlingEnabled } from "../../reactUtils"; interface NewElementCanvasProps { appState: AppState; diff --git a/packages/excalidraw/components/canvases/StaticCanvas.tsx b/packages/excalidraw/components/canvases/StaticCanvas.tsx index 9185bdd5c..6e2df9537 100644 --- a/packages/excalidraw/components/canvases/StaticCanvas.tsx +++ b/packages/excalidraw/components/canvases/StaticCanvas.tsx @@ -1,17 +1,19 @@ import React, { useEffect, useRef } from "react"; -import type { RoughCanvas } from "roughjs/bin/canvas"; + +import { isRenderThrottlingEnabled } from "../../reactUtils"; import { renderStaticScene } from "../../renderer/staticScene"; import { isShallowEqual } from "../../utils"; -import type { AppState, StaticCanvasAppState } from "../../types"; -import type { - RenderableElementsMap, - StaticCanvasRenderConfig, -} from "../../scene/types"; + import type { NonDeletedExcalidrawElement, NonDeletedSceneElementsMap, } from "../../element/types"; -import { isRenderThrottlingEnabled } from "../../reactUtils"; +import type { + RenderableElementsMap, + StaticCanvasRenderConfig, +} from "../../scene/types"; +import type { AppState, StaticCanvasAppState } from "../../types"; +import type { RoughCanvas } from "roughjs/bin/canvas"; type StaticCanvasProps = { canvas: HTMLCanvasElement; diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenu.test.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenu.test.tsx index 0c8deec87..d4c0b7a8d 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenu.test.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenu.test.tsx @@ -1,4 +1,5 @@ import React from "react"; + import { Excalidraw } from "../../index"; import { KEYS } from "../../keys"; import { Keyboard } from "../../tests/helpers/ui"; diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenu.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenu.tsx index 8f4ce435b..e1412e20b 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenu.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenu.tsx @@ -1,11 +1,12 @@ import React from "react"; -import DropdownMenuTrigger from "./DropdownMenuTrigger"; -import DropdownMenuItem from "./DropdownMenuItem"; -import MenuSeparator from "./DropdownMenuSeparator"; -import DropdownMenuGroup from "./DropdownMenuGroup"; + import DropdownMenuContent from "./DropdownMenuContent"; -import DropdownMenuItemLink from "./DropdownMenuItemLink"; +import DropdownMenuGroup from "./DropdownMenuGroup"; +import DropdownMenuItem from "./DropdownMenuItem"; import DropdownMenuItemCustom from "./DropdownMenuItemCustom"; +import DropdownMenuItemLink from "./DropdownMenuItemLink"; +import MenuSeparator from "./DropdownMenuSeparator"; +import DropdownMenuTrigger from "./DropdownMenuTrigger"; import { getMenuContentComponent, getMenuTriggerComponent, diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx index a203124d6..24a0a4d27 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx @@ -1,13 +1,15 @@ -import { Island } from "../Island"; -import { useDevice } from "../App"; import clsx from "clsx"; -import Stack from "../Stack"; import React, { useEffect, useRef } from "react"; -import { DropdownMenuContentPropsContext } from "./common"; -import { useOutsideClick } from "../../hooks/useOutsideClick"; -import { KEYS } from "../../keys"; + import { EVENT } from "../../constants"; +import { useOutsideClick } from "../../hooks/useOutsideClick"; import { useStable } from "../../hooks/useStable"; +import { KEYS } from "../../keys"; +import { useDevice } from "../App"; +import { Island } from "../Island"; +import Stack from "../Stack"; + +import { DropdownMenuContentPropsContext } from "./common"; const MenuContent = ({ children, diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx index 1ff53f8af..fc19bd1bf 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx @@ -1,13 +1,16 @@ -import type { JSX } from "react"; import React, { useEffect, useRef } from "react"; + +import { THEME } from "../../constants"; +import { useExcalidrawAppState } from "../App"; + +import MenuItemContent from "./DropdownMenuItemContent"; import { getDropdownMenuItemClassName, useHandleDropdownMenuItemClick, } from "./common"; -import MenuItemContent from "./DropdownMenuItemContent"; -import { useExcalidrawAppState } from "../App"; -import { THEME } from "../../constants"; + import type { ValueOf } from "../../utility-types"; +import type { JSX } from "react"; const DropdownMenuItem = ({ icon, diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemContent.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemContent.tsx index 000b8c344..b2f9e7e0a 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemContent.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemContent.tsx @@ -1,6 +1,7 @@ -import type { JSX } from "react"; import { useDevice } from "../App"; +import type { JSX } from "react"; + const MenuItemContent = ({ textStyle, icon, diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx index 2dbee7584..1457f5ae7 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx @@ -1,11 +1,13 @@ -import MenuItemContent from "./DropdownMenuItemContent"; -import type { JSX } from "react"; import React from "react"; + +import MenuItemContent from "./DropdownMenuItemContent"; import { getDropdownMenuItemClassName, useHandleDropdownMenuItemClick, } from "./common"; +import type { JSX } from "react"; + const DropdownMenuItemLink = ({ icon, shortcut, diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuTrigger.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuTrigger.tsx index e7369ba57..a7301fb44 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuTrigger.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuTrigger.tsx @@ -1,4 +1,5 @@ import clsx from "clsx"; + import { useDevice } from "../App"; const MenuTrigger = ({ diff --git a/packages/excalidraw/components/dropdownMenu/common.ts b/packages/excalidraw/components/dropdownMenu/common.ts index a2a46fc93..312b78aae 100644 --- a/packages/excalidraw/components/dropdownMenu/common.ts +++ b/packages/excalidraw/components/dropdownMenu/common.ts @@ -1,4 +1,5 @@ import React, { useContext } from "react"; + import { EVENT } from "../../constants"; import { composeEventHandlers } from "../../utils"; diff --git a/packages/excalidraw/components/footer/Footer.tsx b/packages/excalidraw/components/footer/Footer.tsx index ccbe9eaee..427628e7c 100644 --- a/packages/excalidraw/components/footer/Footer.tsx +++ b/packages/excalidraw/components/footer/Footer.tsx @@ -1,6 +1,7 @@ import clsx from "clsx"; + import { actionShortcuts } from "../../actions"; -import type { ActionManager } from "../../actions/manager"; +import { useTunnels } from "../../context/tunnels"; import { ExitZenModeAction, FinalizeAction, @@ -8,10 +9,11 @@ import { ZoomActions, } from "../Actions"; import { useDevice } from "../App"; -import { useTunnels } from "../../context/tunnels"; import { HelpButton } from "../HelpButton"; import { Section } from "../Section"; import Stack from "../Stack"; + +import type { ActionManager } from "../../actions/manager"; import type { UIAppState } from "../../types"; const Footer = ({ diff --git a/packages/excalidraw/components/footer/FooterCenter.tsx b/packages/excalidraw/components/footer/FooterCenter.tsx index 55a0fb998..6a44581de 100644 --- a/packages/excalidraw/components/footer/FooterCenter.tsx +++ b/packages/excalidraw/components/footer/FooterCenter.tsx @@ -1,8 +1,10 @@ import clsx from "clsx"; + import { useTunnels } from "../../context/tunnels"; -import "./FooterCenter.scss"; import { useUIAppState } from "../../context/ui-appState"; +import "./FooterCenter.scss"; + const FooterCenter = ({ children }: { children?: React.ReactNode }) => { const { FooterCenterTunnel } = useTunnels(); const appState = useUIAppState(); diff --git a/packages/excalidraw/components/hoc/withInternalFallback.test.tsx b/packages/excalidraw/components/hoc/withInternalFallback.test.tsx index 554313377..1f30a64c4 100644 --- a/packages/excalidraw/components/hoc/withInternalFallback.test.tsx +++ b/packages/excalidraw/components/hoc/withInternalFallback.test.tsx @@ -1,6 +1,7 @@ import React from "react"; -import { render, queryAllByTestId } from "../../tests/test-utils"; + import { Excalidraw, MainMenu } from "../../index"; +import { render, queryAllByTestId } from "../../tests/test-utils"; describe("Test internal component fallback rendering", () => { it("should render only one menu per excalidraw instance (custom menu first scenario)", async () => { diff --git a/packages/excalidraw/components/hoc/withInternalFallback.tsx b/packages/excalidraw/components/hoc/withInternalFallback.tsx index 5906b30f5..298f58dd9 100644 --- a/packages/excalidraw/components/hoc/withInternalFallback.tsx +++ b/packages/excalidraw/components/hoc/withInternalFallback.tsx @@ -1,4 +1,5 @@ import React, { useLayoutEffect, useRef } from "react"; + import { useTunnels } from "../../context/tunnels"; import { atom } from "../../editor-jotai"; diff --git a/packages/excalidraw/components/hyperlink/Hyperlink.tsx b/packages/excalidraw/components/hyperlink/Hyperlink.tsx index 4d3dce640..88983aeab 100644 --- a/packages/excalidraw/components/hyperlink/Hyperlink.tsx +++ b/packages/excalidraw/components/hyperlink/Hyperlink.tsx @@ -1,20 +1,5 @@ -import type { AppState, ExcalidrawProps, UIAppState } from "../../types"; -import { - sceneCoordsToViewportCoords, - viewportCoordsToSceneCoords, - wrapEvent, -} from "../../utils"; -import { getEmbedLink, embeddableURLValidator } from "../../element/embeddable"; -import { mutateElement } from "../../element/mutateElement"; -import type { - ElementsMap, - ExcalidrawEmbeddableElement, - NonDeletedExcalidrawElement, -} from "../../element/types"; - -import { ToolButton } from "../ToolButton"; -import { FreedrawIcon, TrashIcon, elementLinkIcon } from "../icons"; -import { t } from "../../i18n"; +import { pointFrom, type GlobalPoint } from "@excalidraw/math"; +import clsx from "clsx"; import { useCallback, useEffect, @@ -22,23 +7,40 @@ import { useRef, useState, } from "react"; -import clsx from "clsx"; -import { KEYS } from "../../keys"; -import { EVENT, HYPERLINK_TOOLTIP_DELAY } from "../../constants"; -import { getElementAbsoluteCoords } from "../../element/bounds"; -import { getTooltipDiv, updateTooltipPosition } from "../../components/Tooltip"; -import { getSelectedElements } from "../../scene"; -import { hitElementBoundingBox } from "../../element/collision"; -import { isLocalLink, normalizeLink } from "../../data/url"; + import { trackEvent } from "../../analytics"; -import { useAppProps, useDevice, useExcalidrawAppState } from "../App"; -import { isEmbeddableElement } from "../../element/typeChecks"; -import { getLinkHandleFromCoords } from "./helpers"; -import { pointFrom, type GlobalPoint } from "@excalidraw/math"; +import { getTooltipDiv, updateTooltipPosition } from "../../components/Tooltip"; +import { EVENT, HYPERLINK_TOOLTIP_DELAY } from "../../constants"; +import { isLocalLink, normalizeLink } from "../../data/url"; +import { getElementAbsoluteCoords } from "../../element/bounds"; +import { hitElementBoundingBox } from "../../element/collision"; import { isElementLink } from "../../element/elementLink"; +import { getEmbedLink, embeddableURLValidator } from "../../element/embeddable"; +import { mutateElement } from "../../element/mutateElement"; +import { t } from "../../i18n"; +import { + sceneCoordsToViewportCoords, + viewportCoordsToSceneCoords, + wrapEvent, +} from "../../utils"; +import { useAppProps, useDevice, useExcalidrawAppState } from "../App"; +import { ToolButton } from "../ToolButton"; +import { FreedrawIcon, TrashIcon, elementLinkIcon } from "../icons"; +import { KEYS } from "../../keys"; +import { getSelectedElements } from "../../scene"; +import { isEmbeddableElement } from "../../element/typeChecks"; + +import { getLinkHandleFromCoords } from "./helpers"; import "./Hyperlink.scss"; +import type { + ElementsMap, + ExcalidrawEmbeddableElement, + NonDeletedExcalidrawElement, +} from "../../element/types"; +import type { AppState, ExcalidrawProps, UIAppState } from "../../types"; + const POPUP_WIDTH = 380; const POPUP_HEIGHT = 42; const POPUP_PADDING = 5; diff --git a/packages/excalidraw/components/hyperlink/helpers.ts b/packages/excalidraw/components/hyperlink/helpers.ts index 75c5dad9c..3d39e2ebe 100644 --- a/packages/excalidraw/components/hyperlink/helpers.ts +++ b/packages/excalidraw/components/hyperlink/helpers.ts @@ -1,14 +1,17 @@ -import type { GlobalPoint, Radians } from "@excalidraw/math"; import { pointFrom, pointRotateRads } from "@excalidraw/math"; + +import type { GlobalPoint, Radians } from "@excalidraw/math"; + import { MIME_TYPES } from "../../constants"; -import type { Bounds } from "../../element/bounds"; import { getElementAbsoluteCoords } from "../../element/bounds"; import { hitElementBoundingBox } from "../../element/collision"; +import { DEFAULT_LINK_SIZE } from "../../renderer/renderElement"; + +import type { Bounds } from "../../element/bounds"; import type { ElementsMap, NonDeletedExcalidrawElement, } from "../../element/types"; -import { DEFAULT_LINK_SIZE } from "../../renderer/renderElement"; import type { AppState, UIAppState } from "../../types"; export const EXTERNAL_LINK_IMG = document.createElement("img"); diff --git a/packages/excalidraw/components/icons.tsx b/packages/excalidraw/components/icons.tsx index 073d7a9f7..03e6ca2bb 100644 --- a/packages/excalidraw/components/icons.tsx +++ b/packages/excalidraw/components/icons.tsx @@ -6,13 +6,14 @@ // Note: when adding new icons, review https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/RTL_Guidelines // to determine whether or not the icons should be mirrored in right-to-left languages. +import clsx from "clsx"; +import oc from "open-color"; import React from "react"; -import oc from "open-color"; -import clsx from "clsx"; -import type { Theme } from "../element/types"; import { THEME } from "../constants"; +import type { Theme } from "../element/types"; + export const iconFillColor = (theme: Theme) => "var(--icon-fill-color)"; const handlerColor = (theme: Theme) => diff --git a/packages/excalidraw/components/live-collaboration/LiveCollaborationTrigger.tsx b/packages/excalidraw/components/live-collaboration/LiveCollaborationTrigger.tsx index a22bc523a..1aa187167 100644 --- a/packages/excalidraw/components/live-collaboration/LiveCollaborationTrigger.tsx +++ b/packages/excalidraw/components/live-collaboration/LiveCollaborationTrigger.tsx @@ -1,12 +1,12 @@ -import { t } from "../../i18n"; -import { share } from "../icons"; -import { Button } from "../Button"; - import clsx from "clsx"; -import "./LiveCollaborationTrigger.scss"; +import { t } from "../../i18n"; +import { Button } from "../Button"; +import { share } from "../icons"; import { useUIAppState } from "../../context/ui-appState"; +import "./LiveCollaborationTrigger.scss"; + const LiveCollaborationTrigger = ({ isCollaborating, onSelect, diff --git a/packages/excalidraw/components/main-menu/DefaultItems.tsx b/packages/excalidraw/components/main-menu/DefaultItems.tsx index 632ea4ffa..c2307d521 100644 --- a/packages/excalidraw/components/main-menu/DefaultItems.tsx +++ b/packages/excalidraw/components/main-menu/DefaultItems.tsx @@ -1,11 +1,32 @@ +import clsx from "clsx"; + +import { + actionClearCanvas, + actionLoadScene, + actionSaveToActiveFile, + actionShortcuts, + actionToggleSearchMenu, + actionToggleTheme, +} from "../../actions"; import { getShortcutFromShortcutName } from "../../actions/shortcuts"; +import { trackEvent } from "../../analytics"; +import { THEME } from "../../constants"; +import { useUIAppState } from "../../context/ui-appState"; +import { useSetAtom } from "../../editor-jotai"; import { useI18n } from "../../i18n"; +import { activeConfirmDialogAtom } from "../ActiveConfirmDialog"; import { useExcalidrawSetAppState, useExcalidrawActionManager, useExcalidrawElements, useAppProps, } from "../App"; +import { openConfirmModal } from "../OverwriteConfirm/OverwriteConfirmState"; +import Trans from "../Trans"; +import DropdownMenuItem from "../dropdownMenu/DropdownMenuItem"; +import DropdownMenuItemContentRadio from "../dropdownMenu/DropdownMenuItemContentRadio"; +import DropdownMenuItemLink from "../dropdownMenu/DropdownMenuItemLink"; +import { GithubIcon, DiscordIcon, XBrandIcon } from "../icons"; import { boltIcon, DeviceDesktopIcon, @@ -20,29 +41,11 @@ import { TrashIcon, usersIcon, } from "../icons"; -import { GithubIcon, DiscordIcon, XBrandIcon } from "../icons"; -import DropdownMenuItem from "../dropdownMenu/DropdownMenuItem"; -import DropdownMenuItemLink from "../dropdownMenu/DropdownMenuItemLink"; -import { - actionClearCanvas, - actionLoadScene, - actionSaveToActiveFile, - actionShortcuts, - actionToggleSearchMenu, - actionToggleTheme, -} from "../../actions"; -import clsx from "clsx"; -import { activeConfirmDialogAtom } from "../ActiveConfirmDialog"; -import { useSetAtom } from "../../editor-jotai"; -import { useUIAppState } from "../../context/ui-appState"; -import { openConfirmModal } from "../OverwriteConfirm/OverwriteConfirmState"; -import Trans from "../Trans"; -import DropdownMenuItemContentRadio from "../dropdownMenu/DropdownMenuItemContentRadio"; -import { THEME } from "../../constants"; -import type { Theme } from "../../element/types"; -import { trackEvent } from "../../analytics"; + import "./DefaultItems.scss"; +import type { Theme } from "../../element/types"; + export const LoadScene = () => { const { t } = useI18n(); const actionManager = useExcalidrawActionManager(); diff --git a/packages/excalidraw/components/main-menu/MainMenu.tsx b/packages/excalidraw/components/main-menu/MainMenu.tsx index 07afd3c1d..54f60a364 100644 --- a/packages/excalidraw/components/main-menu/MainMenu.tsx +++ b/packages/excalidraw/components/main-menu/MainMenu.tsx @@ -1,16 +1,16 @@ import React from "react"; -import { useDevice, useExcalidrawSetAppState } from "../App"; -import DropdownMenu from "../dropdownMenu/DropdownMenu"; -import * as DefaultItems from "./DefaultItems"; - -import { UserList } from "../UserList"; -import { t } from "../../i18n"; -import { HamburgerMenuIcon } from "../icons"; -import { withInternalFallback } from "../hoc/withInternalFallback"; -import { composeEventHandlers } from "../../utils"; import { useTunnels } from "../../context/tunnels"; import { useUIAppState } from "../../context/ui-appState"; +import { t } from "../../i18n"; +import { composeEventHandlers } from "../../utils"; +import { useDevice, useExcalidrawSetAppState } from "../App"; +import { UserList } from "../UserList"; +import DropdownMenu from "../dropdownMenu/DropdownMenu"; +import { withInternalFallback } from "../hoc/withInternalFallback"; +import { HamburgerMenuIcon } from "../icons"; + +import * as DefaultItems from "./DefaultItems"; const MainMenu = Object.assign( withInternalFallback( diff --git a/packages/excalidraw/components/welcome-screen/WelcomeScreen.Center.tsx b/packages/excalidraw/components/welcome-screen/WelcomeScreen.Center.tsx index 4faa41bf7..bd9b9e55b 100644 --- a/packages/excalidraw/components/welcome-screen/WelcomeScreen.Center.tsx +++ b/packages/excalidraw/components/welcome-screen/WelcomeScreen.Center.tsx @@ -1,12 +1,13 @@ -import type { JSX } from "react"; import { actionLoadScene, actionShortcuts } from "../../actions"; import { getShortcutFromShortcutName } from "../../actions/shortcuts"; +import { useTunnels } from "../../context/tunnels"; +import { useUIAppState } from "../../context/ui-appState"; import { t, useI18n } from "../../i18n"; import { useDevice, useExcalidrawActionManager } from "../App"; -import { useTunnels } from "../../context/tunnels"; -import { HelpIcon, LoadIcon, usersIcon } from "../icons"; -import { useUIAppState } from "../../context/ui-appState"; import { ExcalidrawLogo } from "../ExcalidrawLogo"; +import { HelpIcon, LoadIcon, usersIcon } from "../icons"; + +import type { JSX } from "react"; const WelcomeScreenMenuItemContent = ({ icon, diff --git a/packages/excalidraw/components/welcome-screen/WelcomeScreen.Hints.tsx b/packages/excalidraw/components/welcome-screen/WelcomeScreen.Hints.tsx index 896f4014e..e47a5a1d3 100644 --- a/packages/excalidraw/components/welcome-screen/WelcomeScreen.Hints.tsx +++ b/packages/excalidraw/components/welcome-screen/WelcomeScreen.Hints.tsx @@ -1,5 +1,5 @@ -import { t } from "../../i18n"; import { useTunnels } from "../../context/tunnels"; +import { t } from "../../i18n"; import { WelcomeScreenHelpArrow, WelcomeScreenMenuArrow, diff --git a/packages/excalidraw/components/welcome-screen/WelcomeScreen.scss b/packages/excalidraw/components/welcome-screen/WelcomeScreen.scss index dc8826a66..8e3a01030 100644 --- a/packages/excalidraw/components/welcome-screen/WelcomeScreen.scss +++ b/packages/excalidraw/components/welcome-screen/WelcomeScreen.scss @@ -222,16 +222,6 @@ .welcome-screen-menu-item__text { color: var(--color-gray-100); } - - &--promo { - color: var(--color-promo) !important; - - &:hover { - .welcome-screen-menu-item__text { - color: var(--color-promo) !important; - } - } - } } &.theme--dark { diff --git a/packages/excalidraw/constants.ts b/packages/excalidraw/constants.ts index 616ced1a7..88cddd5c5 100644 --- a/packages/excalidraw/constants.ts +++ b/packages/excalidraw/constants.ts @@ -1,7 +1,8 @@ -import type { AppProps, AppState } from "./types"; -import type { ExcalidrawElement, FontFamilyValues } from "./element/types"; import { COLOR_PALETTE } from "./colors"; +import type { ExcalidrawElement, FontFamilyValues } from "./element/types"; +import type { AppProps, AppState } from "./types"; + export const isDarwin = /Mac|iPod|iPhone|iPad/.test(navigator.platform); export const isWindows = /^Win/.test(navigator.platform); export const isAndroid = /\b(android)\b/i.test(navigator.userAgent); diff --git a/packages/excalidraw/context/tunnels.ts b/packages/excalidraw/context/tunnels.ts index 73b85ba6a..370a0f2bb 100644 --- a/packages/excalidraw/context/tunnels.ts +++ b/packages/excalidraw/context/tunnels.ts @@ -1,6 +1,6 @@ +import { createIsolation } from "jotai-scope"; import React from "react"; import tunnel from "tunnel-rat"; -import { createIsolation } from "jotai-scope"; export type Tunnel = ReturnType; diff --git a/packages/excalidraw/context/ui-appState.ts b/packages/excalidraw/context/ui-appState.ts index f94ce28c3..174b6e89c 100644 --- a/packages/excalidraw/context/ui-appState.ts +++ b/packages/excalidraw/context/ui-appState.ts @@ -1,4 +1,5 @@ import React from "react"; + import type { UIAppState } from "../types"; export const UIAppStateContext = React.createContext(null!); diff --git a/packages/excalidraw/cursor.ts b/packages/excalidraw/cursor.ts index 759b7a4ae..1aa6e52d2 100644 --- a/packages/excalidraw/cursor.ts +++ b/packages/excalidraw/cursor.ts @@ -1,7 +1,9 @@ -import { CURSOR_TYPE, MIME_TYPES, THEME } from "./constants"; import OpenColor from "open-color"; -import type { AppState, DataURL } from "./types"; + import { isHandToolActive, isEraserActive } from "./appState"; +import { CURSOR_TYPE, MIME_TYPES, THEME } from "./constants"; + +import type { AppState, DataURL } from "./types"; const laserPointerCursorSVG_tag = ``; const laserPointerCursorBackgroundSVG = ``; diff --git a/packages/excalidraw/data/blob.ts b/packages/excalidraw/data/blob.ts index 2293f860c..54505068f 100644 --- a/packages/excalidraw/data/blob.ts +++ b/packages/excalidraw/data/blob.ts @@ -1,19 +1,22 @@ import { nanoid } from "nanoid"; + import { cleanAppStateForExport } from "../appState"; import { IMAGE_MIME_TYPES, MIME_TYPES } from "../constants"; import { clearElementsForExport } from "../element"; -import type { ExcalidrawElement, FileId } from "../element/types"; import { CanvasError, ImageSceneDataError } from "../errors"; import { calculateScrollCenter } from "../scene"; import { decodeSvgBase64Payload } from "../scene/export"; -import type { AppState, DataURL, LibraryItem } from "../types"; -import type { ValueOf } from "../utility-types"; import { bytesToHexString, isPromiseLike } from "../utils"; + import { base64ToString, stringToBase64, toByteString } from "./encode"; -import type { FileSystemHandle } from "./filesystem"; import { nativeFileSystemSupported } from "./filesystem"; import { isValidExcalidrawData, isValidLibrary } from "./json"; import { restore, restoreLibraryItems } from "./restore"; + +import type { FileSystemHandle } from "./filesystem"; +import type { ExcalidrawElement, FileId } from "../element/types"; +import type { AppState, DataURL, LibraryItem } from "../types"; +import type { ValueOf } from "../utility-types"; import type { ImportedLibraryData } from "./types"; const parseFileContents = async (blob: Blob | File): Promise => { diff --git a/packages/excalidraw/data/encode.ts b/packages/excalidraw/data/encode.ts index 15dfdb2c0..31d7a5bc1 100644 --- a/packages/excalidraw/data/encode.ts +++ b/packages/excalidraw/data/encode.ts @@ -1,4 +1,5 @@ import { deflate, inflate } from "pako"; + import { encryptData, decryptData } from "./encryption"; // ----------------------------------------------------------------------------- diff --git a/packages/excalidraw/data/encryption.ts b/packages/excalidraw/data/encryption.ts index 33e689977..a796d05b4 100644 --- a/packages/excalidraw/data/encryption.ts +++ b/packages/excalidraw/data/encryption.ts @@ -1,4 +1,5 @@ import { ENCRYPTION_KEY_BITS } from "../constants"; + import { blobToArrayBuffer } from "./blob"; export const IV_LENGTH_BYTES = 12; diff --git a/packages/excalidraw/data/filesystem.ts b/packages/excalidraw/data/filesystem.ts index 186d58734..0bdab68fd 100644 --- a/packages/excalidraw/data/filesystem.ts +++ b/packages/excalidraw/data/filesystem.ts @@ -1,13 +1,15 @@ -import type { FileSystemHandle } from "browser-fs-access"; import { fileOpen as _fileOpen, fileSave as _fileSave, supported as nativeFileSystemSupported, } from "browser-fs-access"; + import { EVENT, MIME_TYPES } from "../constants"; import { AbortError } from "../errors"; import { debounce } from "../utils"; +import type { FileSystemHandle } from "browser-fs-access"; + type FILE_EXTENSION = Exclude; const INPUT_CHANGE_INTERVAL_MS = 500; diff --git a/packages/excalidraw/data/image.ts b/packages/excalidraw/data/image.ts index 0359a9c32..e54f7bab5 100644 --- a/packages/excalidraw/data/image.ts +++ b/packages/excalidraw/data/image.ts @@ -1,9 +1,11 @@ -import decodePng from "png-chunks-extract"; import tEXt from "png-chunk-text"; import encodePng from "png-chunks-encode"; -import { encode, decode } from "./encode"; +import decodePng from "png-chunks-extract"; + import { EXPORT_DATA_TYPES, MIME_TYPES } from "../constants"; + import { blobToArrayBuffer } from "./blob"; +import { encode, decode } from "./encode"; // ----------------------------------------------------------------------------- // PNG diff --git a/packages/excalidraw/data/index.ts b/packages/excalidraw/data/index.ts index 04cdcaf95..013ac5b75 100644 --- a/packages/excalidraw/data/index.ts +++ b/packages/excalidraw/data/index.ts @@ -11,22 +11,24 @@ import { } from "../constants"; import { getNonDeletedElements } from "../element"; import { isFrameLikeElement } from "../element/typeChecks"; +import { getElementsOverlappingFrame } from "../frame"; +import { t } from "../i18n"; +import { getSelectedElements, isSomeElementSelected } from "../scene"; +import { exportToCanvas, exportToSvg } from "../scene/export"; +import { cloneJSON } from "../utils"; + +import { canvasToBlob } from "./blob"; +import { fileSave } from "./filesystem"; +import { serializeAsJSON } from "./json"; + +import type { FileSystemHandle } from "./filesystem"; import type { ExcalidrawElement, ExcalidrawFrameLikeElement, NonDeletedExcalidrawElement, } from "../element/types"; -import { getElementsOverlappingFrame } from "../frame"; -import { t } from "../i18n"; -import { getSelectedElements, isSomeElementSelected } from "../scene"; -import { exportToCanvas, exportToSvg } from "../scene/export"; import type { ExportType } from "../scene/types"; import type { AppState, BinaryFiles } from "../types"; -import { cloneJSON } from "../utils"; -import { canvasToBlob } from "./blob"; -import type { FileSystemHandle } from "./filesystem"; -import { fileSave } from "./filesystem"; -import { serializeAsJSON } from "./json"; export { loadFromBlob } from "./blob"; export { loadFromJSON, saveAsJSON } from "./json"; diff --git a/packages/excalidraw/data/json.ts b/packages/excalidraw/data/json.ts index 1270fd1b4..c1cdd4f92 100644 --- a/packages/excalidraw/data/json.ts +++ b/packages/excalidraw/data/json.ts @@ -1,4 +1,3 @@ -import { fileOpen, fileSave } from "./filesystem"; import { cleanAppStateForExport, clearAppStateForDatabase } from "../appState"; import { DEFAULT_FILENAME, @@ -8,10 +7,12 @@ import { VERSIONS, } from "../constants"; import { clearElementsForDatabase, clearElementsForExport } from "../element"; + +import { isImageFileHandle, loadFromBlob, normalizeFile } from "./blob"; +import { fileOpen, fileSave } from "./filesystem"; + import type { ExcalidrawElement } from "../element/types"; import type { AppState, BinaryFiles, LibraryItems } from "../types"; -import { isImageFileHandle, loadFromBlob, normalizeFile } from "./blob"; - import type { ExportedDataState, ImportedDataState, diff --git a/packages/excalidraw/data/library.ts b/packages/excalidraw/data/library.ts index 1c23edcf0..76424f54a 100644 --- a/packages/excalidraw/data/library.ts +++ b/packages/excalidraw/data/library.ts @@ -1,19 +1,5 @@ -import { loadLibraryFromBlob } from "./blob"; -import type { - LibraryItems, - LibraryItem, - ExcalidrawImperativeAPI, - LibraryItemsSource, - LibraryItems_anyVersion, -} from "../types"; -import { restoreLibraryItems } from "./restore"; -import type App from "../components/App"; -import { atom, editorJotaiStore } from "../editor-jotai"; -import type { ExcalidrawElement } from "../element/types"; -import { getCommonBoundingBox } from "../element/bounds"; -import { AbortError } from "../errors"; -import { t } from "../i18n"; import { useEffect, useRef } from "react"; + import { URL_HASH_KEYS, URL_QUERY_KEYS, @@ -22,7 +8,14 @@ import { DEFAULT_SIDEBAR, LIBRARY_SIDEBAR_TAB, } from "../constants"; +import { atom, editorJotaiStore } from "../editor-jotai"; +import { hashElementsVersion, hashString } from "../element"; +import { getCommonBoundingBox } from "../element/bounds"; +import { Emitter } from "../emitter"; +import { AbortError } from "../errors"; import { libraryItemSvgsCache } from "../hooks/useLibraryItemSvg"; +import { t } from "../i18n"; +import { Queue } from "../queue"; import { arrayToMap, cloneJSON, @@ -30,12 +23,22 @@ import { promiseTry, resolvablePromise, } from "../utils"; -import type { MaybePromise } from "../utility-types"; -import { Emitter } from "../emitter"; -import { Queue } from "../queue"; -import { hashElementsVersion, hashString } from "../element"; + +import { loadLibraryFromBlob } from "./blob"; +import { restoreLibraryItems } from "./restore"; import { toValidURL } from "./url"; +import type App from "../components/App"; +import type { ExcalidrawElement } from "../element/types"; +import type { + LibraryItems, + LibraryItem, + ExcalidrawImperativeAPI, + LibraryItemsSource, + LibraryItems_anyVersion, +} from "../types"; +import type { MaybePromise } from "../utility-types"; + /** * format: hostname or hostname/pathname * diff --git a/packages/excalidraw/data/reconcile.ts b/packages/excalidraw/data/reconcile.ts index fa4cff8d1..ef644c3aa 100644 --- a/packages/excalidraw/data/reconcile.ts +++ b/packages/excalidraw/data/reconcile.ts @@ -1,14 +1,16 @@ import throttle from "lodash.throttle"; + import { ENV } from "../constants"; -import type { OrderedExcalidrawElement } from "../element/types"; import { orderByFractionalIndex, syncInvalidIndices, validateFractionalIndices, } from "../fractionalIndex"; +import { arrayToMap } from "../utils"; + +import type { OrderedExcalidrawElement } from "../element/types"; import type { AppState } from "../types"; import type { MakeBrand } from "../utility-types"; -import { arrayToMap } from "../utils"; export type ReconciledExcalidrawElement = OrderedExcalidrawElement & MakeBrand<"ReconciledElement">; diff --git a/packages/excalidraw/data/resave.ts b/packages/excalidraw/data/resave.ts index 624918425..2c448429a 100644 --- a/packages/excalidraw/data/resave.ts +++ b/packages/excalidraw/data/resave.ts @@ -1,7 +1,9 @@ +import { getFileHandleType, isImageFileHandleType } from "./blob"; + +import { exportCanvas, prepareElementsForExport } from "."; + import type { ExcalidrawElement } from "../element/types"; import type { AppState, BinaryFiles } from "../types"; -import { exportCanvas, prepareElementsForExport } from "."; -import { getFileHandleType, isImageFileHandleType } from "./blob"; export const resaveAsImageWithScene = async ( elements: readonly ExcalidrawElement[], diff --git a/packages/excalidraw/data/restore.ts b/packages/excalidraw/data/restore.ts index 257a2208a..df1a64621 100644 --- a/packages/excalidraw/data/restore.ts +++ b/packages/excalidraw/data/restore.ts @@ -1,34 +1,8 @@ -import type { - ExcalidrawArrowElement, - ExcalidrawElbowArrowElement, - ExcalidrawElement, - ExcalidrawElementType, - ExcalidrawLinearElement, - ExcalidrawSelectionElement, - ExcalidrawTextElement, - FixedPointBinding, - FontFamilyValues, - OrderedExcalidrawElement, - PointBinding, - StrokeRoundness, -} from "../element/types"; -import type { AppState, BinaryFiles, LibraryItem } from "../types"; -import type { ImportedDataState, LegacyAppState } from "./types"; -import { - getNonDeletedElements, - getNormalizedDimensions, - isInvisiblySmallElement, - refreshTextDimensions, -} from "../element"; -import { - isArrowElement, - isElbowArrow, - isFixedPointBinding, - isLinearElement, - isTextElement, - isUsingAdaptiveRadius, -} from "../element/typeChecks"; -import { randomId } from "../random"; +import { isFiniteNumber, pointFrom } from "@excalidraw/math"; + +import type { LocalPoint, Radians } from "@excalidraw/math"; + +import { getDefaultAppState } from "../appState"; import { DEFAULT_FONT_FAMILY, DEFAULT_TEXT_ALIGN, @@ -40,26 +14,61 @@ import { DEFAULT_GRID_SIZE, DEFAULT_GRID_STEP, } from "../constants"; -import { getDefaultAppState } from "../appState"; +import { + getNonDeletedElements, + getNormalizedDimensions, + isInvisiblySmallElement, + refreshTextDimensions, +} from "../element"; +import { normalizeFixedPoint } from "../element/binding"; +import { + updateElbowArrowPoints, + validateElbowPoints, +} from "../element/elbowArrow"; import { LinearElementEditor } from "../element/linearElementEditor"; import { bumpVersion } from "../element/mutateElement"; -import { getUpdatedTimestamp, updateActiveTool } from "../utils"; -import { arrayToMap } from "../utils"; -import type { MarkOptional, Mutable } from "../utility-types"; import { getContainerElement } from "../element/textElement"; -import { normalizeLink } from "./url"; -import { syncInvalidIndices } from "../fractionalIndex"; -import { getSizeFromPoints } from "../points"; +import { detectLineHeight } from "../element/textMeasurements"; +import { + isArrowElement, + isElbowArrow, + isFixedPointBinding, + isLinearElement, + isTextElement, + isUsingAdaptiveRadius, +} from "../element/typeChecks"; import { getLineHeight } from "../fonts"; -import { normalizeFixedPoint } from "../element/binding"; +import { syncInvalidIndices } from "../fractionalIndex"; +import { randomId } from "../random"; import { getNormalizedGridSize, getNormalizedGridStep, getNormalizedZoom, } from "../scene"; -import type { LocalPoint, Radians } from "@excalidraw/math"; -import { isFiniteNumber, pointFrom } from "@excalidraw/math"; -import { detectLineHeight } from "../element/textMeasurements"; +import { getUpdatedTimestamp, updateActiveTool } from "../utils"; +import { arrayToMap } from "../utils"; +import { getSizeFromPoints } from "../points"; + +import { normalizeLink } from "./url"; + +import type { + ExcalidrawArrowElement, + ExcalidrawElbowArrowElement, + ExcalidrawElement, + ExcalidrawElementType, + ExcalidrawLinearElement, + ExcalidrawSelectionElement, + ExcalidrawTextElement, + FixedPointBinding, + FontFamilyValues, + NonDeletedSceneElementsMap, + OrderedExcalidrawElement, + PointBinding, + StrokeRoundness, +} from "../element/types"; +import type { AppState, BinaryFiles, LibraryItem } from "../types"; +import type { MarkOptional, Mutable } from "../utility-types"; +import type { ImportedDataState, LegacyAppState } from "./types"; type RestoredAppState = Omit< AppState, @@ -206,24 +215,6 @@ const restoreElementWithProperties = < "customData" in extra ? extra.customData : element.customData; } - // NOTE (mtolmacs): This is a temporary check to detect extremely large - // element position or sizing - if ( - element.x < -1e6 || - element.x > 1e6 || - element.y < -1e6 || - element.y > 1e6 || - element.width < -1e6 || - element.width > 1e6 || - element.height < -1e6 || - element.height > 1e6 - ) { - console.error( - "Restore element with properties size or position is too large", - { element }, - ); - } - return { // spread the original element properties to not lose unknown ones // for forward-compatibility @@ -240,21 +231,6 @@ const restoreElement = ( ): typeof element | null => { element = { ...element }; - // NOTE (mtolmacs): This is a temporary check to detect extremely large - // element position or sizing - if ( - element.x < -1e6 || - element.x > 1e6 || - element.y < -1e6 || - element.y > 1e6 || - element.width < -1e6 || - element.width > 1e6 || - element.height < -1e6 || - element.height > 1e6 - ) { - console.error("Restore element size or position is too large", { element }); - } - switch (element.type) { case "text": // temp fix: cleanup legacy obsidian-excalidraw attribute else it'll @@ -596,7 +572,73 @@ export const restoreElements = ( } } - return restoredElements; + // NOTE (mtolmacs): Temporary fix for extremely large arrows + // Need to iterate again so we have attached text nodes in elementsMap + return restoredElements.map((element) => { + if ( + isElbowArrow(element) && + element.startBinding == null && + element.endBinding == null && + !validateElbowPoints(element.points) + ) { + return { + ...element, + ...updateElbowArrowPoints( + element, + restoredElementsMap as NonDeletedSceneElementsMap, + { + points: [ + pointFrom(0, 0), + element.points[element.points.length - 1], + ], + }, + ), + index: element.index, + }; + } + + if ( + isElbowArrow(element) && + element.startBinding && + element.endBinding && + element.startBinding.elementId === element.endBinding.elementId && + element.points.length > 1 && + element.points.some( + ([rx, ry]) => Math.abs(rx) > 1e6 || Math.abs(ry) > 1e6, + ) + ) { + console.error("Fixing self-bound elbow arrow", element.id); + const boundElement = restoredElementsMap.get( + element.startBinding.elementId, + ); + if (!boundElement) { + console.error( + "Bound element not found", + element.startBinding.elementId, + ); + return element; + } + + return { + ...element, + x: boundElement.x + boundElement.width / 2, + y: boundElement.y - 5, + width: boundElement.width, + height: boundElement.height, + points: [ + pointFrom(0, 0), + pointFrom(0, -10), + pointFrom(boundElement.width / 2 + 5, -10), + pointFrom( + boundElement.width / 2 + 5, + boundElement.height / 2 + 5, + ), + ], + }; + } + + return element; + }); }; const coalesceAppStateValue = < diff --git a/packages/excalidraw/data/transform.test.ts b/packages/excalidraw/data/transform.test.ts index a36af0c35..94f7b6c82 100644 --- a/packages/excalidraw/data/transform.test.ts +++ b/packages/excalidraw/data/transform.test.ts @@ -1,8 +1,10 @@ -import { vi } from "vitest"; -import type { ExcalidrawElementSkeleton } from "./transform"; -import { convertToExcalidrawElements } from "./transform"; -import type { ExcalidrawArrowElement } from "../element/types"; import { pointFrom } from "@excalidraw/math"; +import { vi } from "vitest"; + +import { convertToExcalidrawElements } from "./transform"; + +import type { ExcalidrawElementSkeleton } from "./transform"; +import type { ExcalidrawArrowElement } from "../element/types"; const opts = { regenerateIds: false }; diff --git a/packages/excalidraw/data/transform.ts b/packages/excalidraw/data/transform.ts index 023740cf1..704b63cb5 100644 --- a/packages/excalidraw/data/transform.ts +++ b/packages/excalidraw/data/transform.ts @@ -1,3 +1,5 @@ +import { pointFrom, type LocalPoint } from "@excalidraw/math"; + import { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, @@ -11,7 +13,6 @@ import { redrawTextBoundingBox, } from "../element"; import { bindLinearElement } from "../element/binding"; -import type { ElementConstructorOpts } from "../element/newElement"; import { newArrowElement, newFrameElement, @@ -19,6 +20,22 @@ import { newMagicFrameElement, newTextElement, } from "../element/newElement"; +import { measureText, normalizeText } from "../element/textMeasurements"; +import { isArrowElement } from "../element/typeChecks"; +import { getLineHeight } from "../fonts"; +import { syncInvalidIndices } from "../fractionalIndex"; +import { getSizeFromPoints } from "../points"; +import { randomId } from "../random"; +import { + arrayToMap, + assertNever, + cloneJSON, + getFontString, + isDevEnv, + toBrandedType, +} from "../utils"; + +import type { ElementConstructorOpts } from "../element/newElement"; import type { ElementsMap, ExcalidrawArrowElement, @@ -40,21 +57,6 @@ import type { VerticalAlign, } from "../element/types"; import type { MarkOptional } from "../utility-types"; -import { - arrayToMap, - assertNever, - cloneJSON, - getFontString, - isDevEnv, - toBrandedType, -} from "../utils"; -import { getSizeFromPoints } from "../points"; -import { randomId } from "../random"; -import { syncInvalidIndices } from "../fractionalIndex"; -import { getLineHeight } from "../fonts"; -import { isArrowElement } from "../element/typeChecks"; -import { pointFrom, type LocalPoint } from "@excalidraw/math"; -import { measureText, normalizeText } from "../element/textMeasurements"; export type ValidLinearElement = { type: "arrow" | "line"; diff --git a/packages/excalidraw/data/types.ts b/packages/excalidraw/data/types.ts index f5f5535a5..de3436137 100644 --- a/packages/excalidraw/data/types.ts +++ b/packages/excalidraw/data/types.ts @@ -1,3 +1,5 @@ +import type { cleanAppStateForExport } from "../appState"; +import type { VERSIONS } from "../constants"; import type { ExcalidrawElement } from "../element/types"; import type { AppState, @@ -5,8 +7,6 @@ import type { LibraryItems, LibraryItems_anyVersion, } from "../types"; -import type { cleanAppStateForExport } from "../appState"; -import type { VERSIONS } from "../constants"; export interface ExportedDataState { type: string; diff --git a/packages/excalidraw/data/url.ts b/packages/excalidraw/data/url.ts index 2ab553bb8..a758d233e 100644 --- a/packages/excalidraw/data/url.ts +++ b/packages/excalidraw/data/url.ts @@ -1,4 +1,5 @@ import { sanitizeUrl } from "@braintree/sanitize-url"; + import { escapeDoubleQuotes } from "../utils"; export const normalizeLink = (link: string) => { diff --git a/packages/excalidraw/distribute.ts b/packages/excalidraw/distribute.ts index 368b2f24d..767d3802c 100644 --- a/packages/excalidraw/distribute.ts +++ b/packages/excalidraw/distribute.ts @@ -1,6 +1,7 @@ +import { getCommonBoundingBox } from "./element/bounds"; import { newElementWith } from "./element/mutateElement"; import { getMaximumGroups } from "./groups"; -import { getCommonBoundingBox } from "./element/bounds"; + import type { ElementsMap, ExcalidrawElement } from "./element/types"; export interface Distribution { diff --git a/packages/excalidraw/element/ElementCanvasButtons.tsx b/packages/excalidraw/element/ElementCanvasButtons.tsx index 1bcad97b4..e67e8d5bc 100644 --- a/packages/excalidraw/element/ElementCanvasButtons.tsx +++ b/packages/excalidraw/element/ElementCanvasButtons.tsx @@ -1,11 +1,14 @@ -import type { AppState } from "../types"; -import { sceneCoordsToViewportCoords } from "../utils"; -import type { ElementsMap, NonDeletedExcalidrawElement } from "./types"; -import { getElementAbsoluteCoords } from "."; import { useExcalidrawAppState } from "../components/App"; +import { sceneCoordsToViewportCoords } from "../utils"; import "./ElementCanvasButtons.scss"; +import { getElementAbsoluteCoords } from "."; + +import type { AppState } from "../types"; + +import type { ElementsMap, NonDeletedExcalidrawElement } from "./types"; + const CONTAINER_PADDING = 5; const getContainerCoords = ( diff --git a/packages/excalidraw/element/binding.ts b/packages/excalidraw/element/binding.ts index b679ae9d0..fa472d211 100644 --- a/packages/excalidraw/element/binding.ts +++ b/packages/excalidraw/element/binding.ts @@ -1,3 +1,67 @@ +import { + lineSegment, + pointFrom, + pointRotateRads, + type GlobalPoint, + vectorFromPoint, + pointDistanceSq, + clamp, + pointDistance, + pointFromVector, + vectorScale, + vectorNormalize, + vectorCross, + pointsEqual, + lineSegmentIntersectionPoints, + round, + PRECISION, +} from "@excalidraw/math"; +import { isPointOnShape } from "@excalidraw/utils/collision"; + +import type { LocalPoint, Radians } from "@excalidraw/math"; + +import { KEYS } from "../keys"; +import { aabbForElement, getElementShape, pointInsideBounds } from "../shapes"; +import { + arrayToMap, + isBindingFallthroughEnabled, + tupleToCoors, +} from "../utils"; + +import { + getCenterForBounds, + getElementBounds, + doBoundsIntersect, +} from "./bounds"; +import { intersectElementWithLineSegment } from "./collision"; +import { distanceToBindableElement } from "./distance"; +import { + compareHeading, + HEADING_DOWN, + HEADING_RIGHT, + HEADING_UP, + headingForPointFromElement, + vectorToHeading, + type Heading, +} from "./heading"; +import { LinearElementEditor } from "./linearElementEditor"; +import { mutateElement } from "./mutateElement"; +import { getBoundTextElement, handleBindTextResize } from "./textElement"; +import { + isArrowElement, + isBindableElement, + isBindingElement, + isBoundToContainer, + isElbowArrow, + isFixedPointBinding, + isFrameLikeElement, + isLinearElement, + isRectanguloidElement, + isTextElement, +} from "./typeChecks"; + +import type { Bounds } from "./bounds"; +import type { ElementUpdate } from "./mutateElement"; import type { ExcalidrawBindableElement, ExcalidrawElement, @@ -15,67 +79,8 @@ import type { SceneElementsMap, FixedPointBinding, } from "./types"; - -import type { Bounds } from "./bounds"; -import { - getCenterForBounds, - getElementBounds, - doBoundsIntersect, -} from "./bounds"; -import type { AppState } from "../types"; -import { isPointOnShape } from "@excalidraw/utils/collision"; -import { - isArrowElement, - isBindableElement, - isBindingElement, - isBoundToContainer, - isElbowArrow, - isFixedPointBinding, - isFrameLikeElement, - isLinearElement, - isRectanguloidElement, - isTextElement, -} from "./typeChecks"; -import type { ElementUpdate } from "./mutateElement"; -import { mutateElement } from "./mutateElement"; import type Scene from "../scene/Scene"; -import { LinearElementEditor } from "./linearElementEditor"; -import { - arrayToMap, - isBindingFallthroughEnabled, - tupleToCoors, -} from "../utils"; -import { KEYS } from "../keys"; -import { getBoundTextElement, handleBindTextResize } from "./textElement"; -import { aabbForElement, getElementShape, pointInsideBounds } from "../shapes"; -import { - compareHeading, - HEADING_DOWN, - HEADING_RIGHT, - HEADING_UP, - headingForPointFromElement, - vectorToHeading, - type Heading, -} from "./heading"; -import type { LocalPoint, Radians } from "@excalidraw/math"; -import { - lineSegment, - pointFrom, - pointRotateRads, - type GlobalPoint, - vectorFromPoint, - pointDistanceSq, - clamp, - pointDistance, - pointFromVector, - vectorScale, - vectorNormalize, - vectorCross, - pointsEqual, - lineSegmentIntersectionPoints, -} from "@excalidraw/math"; -import { intersectElementWithLineSegment } from "./collision"; -import { distanceToBindableElement } from "./distance"; +import type { AppState } from "../types"; export type SuggestedBinding = | NonDeleted @@ -272,14 +277,16 @@ const getBindingStrategyForDraggingArrowEndpoints = ( zoom, ) : null // If binding is disabled and start is dragged, break all binds - : // We have to update the focus and gap of the binding, so let's rebind + : !isElbowArrow(selectedElement) + ? // We have to update the focus and gap of the binding, so let's rebind getElligibleElementForBindingElement( selectedElement, "start", elementsMap, elements, zoom, - ); + ) + : "keep"; const end = endDragged ? isBindingEnabled ? getElligibleElementForBindingElement( @@ -290,14 +297,16 @@ const getBindingStrategyForDraggingArrowEndpoints = ( zoom, ) : null // If binding is disabled and end is dragged, break all binds - : // We have to update the focus and gap of the binding, so let's rebind + : !isElbowArrow(selectedElement) + ? // We have to update the focus and gap of the binding, so let's rebind getElligibleElementForBindingElement( selectedElement, "end", elementsMap, elements, zoom, - ); + ) + : "keep"; return [start, end]; }; @@ -309,6 +318,11 @@ const getBindingStrategyForDraggingArrowOrJoints = ( isBindingEnabled: boolean, zoom?: AppState["zoom"], ): (NonDeleted | null | "keep")[] => { + // Elbow arrows don't bind when dragged as a whole + if (isElbowArrow(selectedElement)) { + return ["keep", "keep"]; + } + const [startIsClose, endIsClose] = getOriginalBindingsIfStillCloseToArrowEnds( selectedElement, elementsMap, @@ -943,21 +957,28 @@ export const bindPointToSnapToElementOutline = ( ), )[0]; const currentDistance = pointDistance(p, center); - const fullDistance = pointDistance(intersection, center); - const ratio = currentDistance / fullDistance; + const fullDistance = Math.max( + pointDistance(intersection ?? p, center), + PRECISION, + ); + const ratio = round(currentDistance / fullDistance, 6); switch (true) { case ratio > 0.9: - if (currentDistance - fullDistance > FIXED_BINDING_DISTANCE) { + if ( + currentDistance - fullDistance > FIXED_BINDING_DISTANCE || + // Too close to determine vector from intersection to p + pointDistanceSq(p, intersection) < PRECISION + ) { return p; } return pointFromVector( vectorScale( - vectorNormalize(vectorFromPoint(p, intersection)), + vectorNormalize(vectorFromPoint(p, intersection ?? center)), ratio > 1 ? FIXED_BINDING_DISTANCE : -FIXED_BINDING_DISTANCE, ), - intersection, + intersection ?? center, ); default: diff --git a/packages/excalidraw/element/bounds.test.ts b/packages/excalidraw/element/bounds.test.ts index 9d91d0925..936ebf797 100644 --- a/packages/excalidraw/element/bounds.test.ts +++ b/packages/excalidraw/element/bounds.test.ts @@ -1,8 +1,12 @@ -import type { LocalPoint } from "@excalidraw/math"; import { pointFrom } from "@excalidraw/math"; + +import type { LocalPoint } from "@excalidraw/math"; + import { ROUNDNESS } from "../constants"; import { arrayToMap } from "../utils"; + import { getElementAbsoluteCoords, getElementBounds } from "./bounds"; + import type { ExcalidrawElement, ExcalidrawLinearElement } from "./types"; const _ce = ({ diff --git a/packages/excalidraw/element/bounds.ts b/packages/excalidraw/element/bounds.ts index e4be1dfbd..9d8fd22d3 100644 --- a/packages/excalidraw/element/bounds.ts +++ b/packages/excalidraw/element/bounds.ts @@ -1,3 +1,39 @@ +import { + degreesToRadians, + lineSegment, + pointFrom, + pointDistance, + pointFromArray, + pointRotateRads, +} from "@excalidraw/math"; +import { getCurvePathOps } from "@excalidraw/utils/geometry/shape"; +import rough from "roughjs/bin/rough"; + +import type { + Degrees, + GlobalPoint, + LineSegment, + LocalPoint, + Radians, +} from "@excalidraw/math"; + +import { rescalePoints } from "../points"; +import { generateRoughOptions } from "../scene/Shape"; +import { ShapeCache } from "../scene/ShapeCache"; +import { arrayToMap, invariant } from "../utils"; + +import { LinearElementEditor } from "./linearElementEditor"; +import { getBoundTextElement, getContainerElement } from "./textElement"; +import { + isArrowElement, + isBoundToContainer, + isFreeDrawElement, + isLinearElement, + isTextElement, +} from "./typeChecks"; + +import type { AppState } from "../types"; +import type { Mutable } from "../utility-types"; import type { ExcalidrawElement, ExcalidrawLinearElement, @@ -7,39 +43,8 @@ import type { ExcalidrawTextElementWithContainer, ElementsMap, } from "./types"; -import rough from "roughjs/bin/rough"; -import type { Point as RoughPoint } from "roughjs/bin/geometry"; import type { Drawable, Op } from "roughjs/bin/core"; -import type { AppState } from "../types"; -import { generateRoughOptions } from "../scene/Shape"; -import { - isArrowElement, - isBoundToContainer, - isFreeDrawElement, - isLinearElement, - isTextElement, -} from "./typeChecks"; -import { rescalePoints } from "../points"; -import { getBoundTextElement, getContainerElement } from "./textElement"; -import { LinearElementEditor } from "./linearElementEditor"; -import { ShapeCache } from "../scene/ShapeCache"; -import { arrayToMap, invariant } from "../utils"; -import type { - Degrees, - GlobalPoint, - LineSegment, - LocalPoint, - Radians, -} from "@excalidraw/math"; -import { - degreesToRadians, - lineSegment, - pointFrom, - pointDistance, - pointFromArray, - pointRotateRads, -} from "@excalidraw/math"; -import type { Mutable } from "../utility-types"; +import type { Point as RoughPoint } from "roughjs/bin/geometry"; export type RectangleBox = { x: number; @@ -367,15 +372,6 @@ export const getDiamondPoints = (element: ExcalidrawElement) => { return [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY]; }; -export const getCurvePathOps = (shape: Drawable): Op[] => { - for (const set of shape.sets) { - if (set.type === "path") { - return set.ops; - } - } - return shape.sets[0].ops; -}; - // reference: https://eliot-jones.com/2019/12/cubic-bezier-curve-bounding-boxes const getBezierValueForT = ( t: number, @@ -583,6 +579,10 @@ export const getArrowheadPoints = ( position: "start" | "end", arrowhead: Arrowhead, ) => { + if (shape.length < 1) { + return null; + } + const ops = getCurvePathOps(shape[0]); if (ops.length < 1) { return null; diff --git a/packages/excalidraw/element/collision.ts b/packages/excalidraw/element/collision.ts index b0a2ce9a5..a86cbd62f 100644 --- a/packages/excalidraw/element/collision.ts +++ b/packages/excalidraw/element/collision.ts @@ -1,31 +1,3 @@ -import type { - ElementsMap, - ExcalidrawDiamondElement, - ExcalidrawElement, - ExcalidrawEllipseElement, - ExcalidrawRectangleElement, - ExcalidrawRectanguloidElement, -} from "./types"; -import { getElementBounds } from "./bounds"; -import type { FrameNameBounds } from "../types"; -import type { GeometricShape } from "@excalidraw/utils/geometry/shape"; -import { getPolygonShape } from "@excalidraw/utils/geometry/shape"; -import { isPointInShape, isPointOnShape } from "@excalidraw/utils/collision"; -import { isTransparent } from "../utils"; -import { - hasBoundTextElement, - isIframeLikeElement, - isImageElement, - isTextElement, -} from "./typeChecks"; -import { getBoundTextShape, isPathALoop } from "../shapes"; -import type { - GlobalPoint, - LineSegment, - LocalPoint, - Polygon, - Radians, -} from "@excalidraw/math"; import { curveIntersectLineSegment, isPointWithinBounds, @@ -40,11 +12,43 @@ import { ellipse, ellipseLineIntersectionPoints, } from "@excalidraw/math/ellipse"; +import { isPointInShape, isPointOnShape } from "@excalidraw/utils/collision"; +import { getPolygonShape } from "@excalidraw/utils/geometry/shape"; + +import type { + GlobalPoint, + LineSegment, + LocalPoint, + Polygon, + Radians, +} from "@excalidraw/math"; +import type { GeometricShape } from "@excalidraw/utils/geometry/shape"; + +import { getBoundTextShape, isPathALoop } from "../shapes"; +import { isTransparent } from "../utils"; + +import { getElementBounds } from "./bounds"; +import { + hasBoundTextElement, + isIframeLikeElement, + isImageElement, + isTextElement, +} from "./typeChecks"; import { deconstructDiamondElement, deconstructRectanguloidElement, } from "./utils"; +import type { + ElementsMap, + ExcalidrawDiamondElement, + ExcalidrawElement, + ExcalidrawEllipseElement, + ExcalidrawRectangleElement, + ExcalidrawRectanguloidElement, +} from "./types"; +import type { FrameNameBounds } from "../types"; + export const shouldTestInside = (element: ExcalidrawElement) => { if (element.type === "arrow") { return false; diff --git a/packages/excalidraw/element/cropElement.ts b/packages/excalidraw/element/cropElement.ts index b10980209..dd75f9360 100644 --- a/packages/excalidraw/element/cropElement.ts +++ b/packages/excalidraw/element/cropElement.ts @@ -1,4 +1,3 @@ -import { type Point } from "points-on-curve"; import { type Radians, pointFrom, @@ -13,6 +12,13 @@ import { clamp, isCloseTo, } from "@excalidraw/math"; +import { type Point } from "points-on-curve"; + +import { + getElementAbsoluteCoords, + getResizedElementAbsoluteCoords, +} from "./bounds"; + import type { TransformHandleType } from "./transformHandles"; import type { ElementsMap, @@ -21,10 +27,6 @@ import type { ImageCrop, NonDeleted, } from "./types"; -import { - getElementAbsoluteCoords, - getResizedElementAbsoluteCoords, -} from "./bounds"; export const MINIMAL_CROP_SIZE = 10; diff --git a/packages/excalidraw/element/distance.ts b/packages/excalidraw/element/distance.ts index 0010ab953..038233555 100644 --- a/packages/excalidraw/element/distance.ts +++ b/packages/excalidraw/element/distance.ts @@ -1,4 +1,3 @@ -import type { GlobalPoint, Radians } from "@excalidraw/math"; import { curvePointDistance, distanceToLineSegment, @@ -6,16 +5,20 @@ import { pointRotateRads, } from "@excalidraw/math"; import { ellipse, ellipseDistanceFromPoint } from "@excalidraw/math/ellipse"; + +import type { GlobalPoint, Radians } from "@excalidraw/math"; + +import { + deconstructDiamondElement, + deconstructRectanguloidElement, +} from "./utils"; + import type { ExcalidrawBindableElement, ExcalidrawDiamondElement, ExcalidrawEllipseElement, ExcalidrawRectanguloidElement, } from "./types"; -import { - deconstructDiamondElement, - deconstructRectanguloidElement, -} from "./utils"; export const distanceToBindableElement = ( element: ExcalidrawBindableElement, diff --git a/packages/excalidraw/element/dragElements.ts b/packages/excalidraw/element/dragElements.ts index bb8fd237e..4cc408b21 100644 --- a/packages/excalidraw/element/dragElements.ts +++ b/packages/excalidraw/element/dragElements.ts @@ -1,17 +1,13 @@ +import { TEXT_AUTOWRAP_THRESHOLD } from "../constants"; +import { getGridPoint } from "../snapping"; +import { getFontString } from "../utils"; + import { updateBoundElements } from "./binding"; -import type { Bounds } from "./bounds"; import { getCommonBounds } from "./bounds"; import { mutateElement } from "./mutateElement"; import { getPerfectElementSize } from "./sizeHelpers"; -import type { NonDeletedExcalidrawElement } from "./types"; -import type { - AppState, - NormalizedZoomValue, - NullableGridSize, - PointerDownState, -} from "../types"; import { getBoundTextElement } from "./textElement"; -import type Scene from "../scene/Scene"; +import { getMinTextElementWidth } from "./textMeasurements"; import { isArrowElement, isElbowArrow, @@ -19,10 +15,16 @@ import { isImageElement, isTextElement, } from "./typeChecks"; -import { getFontString } from "../utils"; -import { TEXT_AUTOWRAP_THRESHOLD } from "../constants"; -import { getGridPoint } from "../snapping"; -import { getMinTextElementWidth } from "./textMeasurements"; + +import type { Bounds } from "./bounds"; +import type { NonDeletedExcalidrawElement } from "./types"; +import type Scene from "../scene/Scene"; +import type { + AppState, + NormalizedZoomValue, + NullableGridSize, + PointerDownState, +} from "../types"; export const dragSelectedElements = ( pointerDownState: PointerDownState, diff --git a/packages/excalidraw/element/elbowArrow.test.tsx b/packages/excalidraw/element/elbowArrow.test.tsx index 1839e978c..91e280d30 100644 --- a/packages/excalidraw/element/elbowArrow.test.tsx +++ b/packages/excalidraw/element/elbowArrow.test.tsx @@ -1,24 +1,31 @@ +import { pointFrom } from "@excalidraw/math"; import React from "react"; + +import type { LocalPoint } from "@excalidraw/math"; + +import "../../utils/test-utils"; +import { actionSelectAll } from "../actions"; +import { actionDuplicateSelection } from "../actions/actionDuplicateSelection"; +import { ARROW_TYPE } from "../constants"; +import { Excalidraw, mutateElement } from "../index"; import Scene from "../scene/Scene"; import { API } from "../tests/helpers/api"; import { Pointer, UI } from "../tests/helpers/ui"; import { + act, fireEvent, GlobalTestState, queryByTestId, render, } from "../tests/test-utils"; + import { bindLinearElement } from "./binding"; -import { Excalidraw, mutateElement } from "../index"; + import type { ExcalidrawArrowElement, ExcalidrawBindableElement, ExcalidrawElbowArrowElement, } from "./types"; -import { ARROW_TYPE } from "../constants"; -import "../../utils/test-utils"; -import type { LocalPoint } from "@excalidraw/math"; -import { pointFrom } from "@excalidraw/math"; const { h } = window; @@ -292,4 +299,114 @@ describe("elbow arrow ui", () => { [103, 165], ]); }); + + it("keeps arrow shape when the whole set of arrow and bindables are duplicated", async () => { + UI.createElement("rectangle", { + x: -150, + y: -150, + width: 100, + height: 100, + }); + UI.createElement("rectangle", { + x: 50, + y: 50, + width: 100, + height: 100, + }); + + UI.clickTool("arrow"); + UI.clickOnTestId("elbow-arrow"); + + mouse.reset(); + mouse.moveTo(-43, -99); + mouse.click(); + mouse.moveTo(43, 99); + mouse.click(); + + const arrow = h.scene.getSelectedElements( + h.state, + )[0] as ExcalidrawArrowElement; + const originalArrowId = arrow.id; + + expect(arrow.startBinding).not.toBe(null); + expect(arrow.endBinding).not.toBe(null); + + act(() => { + h.app.actionManager.executeAction(actionSelectAll); + }); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + expect(h.elements.length).toEqual(6); + + const duplicatedArrow = h.scene.getSelectedElements( + h.state, + )[2] as ExcalidrawArrowElement; + + expect(duplicatedArrow.id).not.toBe(originalArrowId); + expect(duplicatedArrow.type).toBe("arrow"); + expect(duplicatedArrow.elbowed).toBe(true); + expect(duplicatedArrow.points).toEqual([ + [0, 0], + [45, 0], + [45, 200], + [90, 200], + ]); + expect(arrow.startBinding).not.toBe(null); + expect(arrow.endBinding).not.toBe(null); + }); + + it("keeps arrow shape when only the bound arrow is duplicated", async () => { + UI.createElement("rectangle", { + x: -150, + y: -150, + width: 100, + height: 100, + }); + UI.createElement("rectangle", { + x: 50, + y: 50, + width: 100, + height: 100, + }); + + UI.clickTool("arrow"); + UI.clickOnTestId("elbow-arrow"); + + mouse.reset(); + mouse.moveTo(-43, -99); + mouse.click(); + mouse.moveTo(43, 99); + mouse.click(); + + const arrow = h.scene.getSelectedElements( + h.state, + )[0] as ExcalidrawArrowElement; + const originalArrowId = arrow.id; + + expect(arrow.startBinding).not.toBe(null); + expect(arrow.endBinding).not.toBe(null); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + expect(h.elements.length).toEqual(4); + + const duplicatedArrow = h.scene.getSelectedElements( + h.state, + )[0] as ExcalidrawArrowElement; + + expect(duplicatedArrow.id).not.toBe(originalArrowId); + expect(duplicatedArrow.type).toBe("arrow"); + expect(duplicatedArrow.elbowed).toBe(true); + expect(duplicatedArrow.points).toEqual([ + [0, 0], + [45, 0], + [45, 200], + [90, 200], + ]); + }); }); diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index 703cea0d5..5b8dc3813 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -12,11 +12,12 @@ import { type GlobalPoint, type LocalPoint, } from "@excalidraw/math"; + import BinaryHeap from "../binaryheap"; import { getSizeFromPoints } from "../points"; import { aabbForElement, pointInsideBounds } from "../shapes"; -import { invariant, isAnyTrue, toBrandedType, tupleToCoors } from "../utils"; -import type { AppState } from "../types"; +import { invariant, isAnyTrue, tupleToCoors } from "../utils"; + import { bindPointToSnapToElementOutline, FIXED_BINDING_DISTANCE, @@ -25,8 +26,7 @@ import { snapToMid, getHoveredElementForBinding, } from "./binding"; -import type { Bounds } from "./bounds"; -import type { Heading } from "./heading"; +import { distanceToBindableElement } from "./distance"; import { compareHeading, flipHeading, @@ -46,14 +46,18 @@ import { type NonDeletedSceneElementsMap, type SceneElementsMap, } from "./types"; + +import type { Bounds } from "./bounds"; +import type { Heading } from "./heading"; import type { Arrowhead, ElementsMap, ExcalidrawBindableElement, FixedPointBinding, FixedSegment, + NonDeletedExcalidrawElement, } from "./types"; -import { distanceToBindableElement } from "./distance"; +import type { AppState } from "../types"; type GridAddress = [number, number] & { _brand: "gridaddress" }; @@ -101,7 +105,7 @@ export const BASE_PADDING = 40; const handleSegmentRenormalization = ( arrow: ExcalidrawElbowArrowElement, - elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, + elementsMap: NonDeletedSceneElementsMap, ) => { const nextFixedSegments: FixedSegment[] | null = arrow.fixedSegments ? arrow.fixedSegments.slice() @@ -234,6 +238,16 @@ const handleSegmentRenormalization = ( nextPoints.map((p) => pointFrom(p[0] - arrow.x, p[1] - arrow.y), ), + arrow.startBinding && + getBindableElementForId( + arrow.startBinding.elementId, + elementsMap, + ), + arrow.endBinding && + getBindableElementForId( + arrow.endBinding.elementId, + elementsMap, + ), ), ) ?? [], ), @@ -271,7 +285,7 @@ const handleSegmentRenormalization = ( const handleSegmentRelease = ( arrow: ExcalidrawElbowArrowElement, fixedSegments: readonly FixedSegment[], - elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, + elementsMap: NonDeletedSceneElementsMap, ) => { const newFixedSegmentIndices = fixedSegments.map((segment) => segment.index); const oldFixedSegmentIndices = @@ -295,6 +309,8 @@ const handleSegmentRelease = ( // We need to render a sub-arrow path to restore deleted segments const x = arrow.x + (prevSegment ? prevSegment.end[0] : 0); const y = arrow.y + (prevSegment ? prevSegment.end[1] : 0); + const startBinding = prevSegment ? null : arrow.startBinding; + const endBinding = nextSegment ? null : arrow.endBinding; const { startHeading, endHeading, @@ -307,10 +323,11 @@ const handleSegmentRelease = ( { x, y, - startBinding: prevSegment ? null : arrow.startBinding, - endBinding: nextSegment ? null : arrow.endBinding, + startBinding, + endBinding, startArrowhead: null, endArrowhead: null, + points: arrow.points, }, elementsMap, [ @@ -324,6 +341,9 @@ const handleSegmentRelease = ( y, ), ], + startBinding && + getBindableElementForId(startBinding.elementId, elementsMap), + endBinding && getBindableElementForId(endBinding.elementId, elementsMap), { isDragging: false }, ); @@ -870,7 +890,7 @@ const MAX_POS = 1e6; */ export const updateElbowArrowPoints = ( arrow: Readonly, - elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, + elementsMap: NonDeletedSceneElementsMap, updates: { points?: readonly LocalPoint[]; fixedSegments?: FixedSegment[] | null; @@ -963,24 +983,6 @@ export const updateElbowArrowPoints = ( ); } - // 0. During all element replacement in the scene, we just need to renormalize - // the arrow - // TODO (dwelle,mtolmacs): Remove this once Scene.getScene() is removed - if ( - elementsMap.size === 0 && - updates.points && - validateElbowPoints(updates.points) - ) { - return normalizeArrowElementUpdate( - updates.points.map((p) => - pointFrom(arrow.x + p[0], arrow.y + p[1]), - ), - arrow.fixedSegments, - arrow.startIsSpecial, - arrow.endIsSpecial, - ); - } - const updatedPoints: readonly LocalPoint[] = updates.points ? updates.points && updates.points.length === 2 ? arrow.points.map((p, idx) => @@ -993,6 +995,37 @@ export const updateElbowArrowPoints = ( : updates.points.slice() : arrow.points.slice(); + // 0. During all element replacement in the scene, we just need to renormalize + // the arrow + // TODO (dwelle,mtolmacs): Remove this once Scene.getScene() is removed + const startBinding = + typeof updates.startBinding !== "undefined" + ? updates.startBinding + : arrow.startBinding; + const endBinding = + typeof updates.endBinding !== "undefined" + ? updates.endBinding + : arrow.endBinding; + const startElement = + startBinding && + getBindableElementForId(startBinding.elementId, elementsMap); + const endElement = + endBinding && getBindableElementForId(endBinding.elementId, elementsMap); + if ( + (elementsMap.size === 0 && validateElbowPoints(updatedPoints)) || + startElement?.id !== startBinding?.elementId || + endElement?.id !== endBinding?.elementId + ) { + return normalizeArrowElementUpdate( + updatedPoints.map((p) => + pointFrom(arrow.x + p[0], arrow.y + p[1]), + ), + arrow.fixedSegments, + arrow.startIsSpecial, + arrow.endIsSpecial, + ); + } + const { startHeading, endHeading, @@ -1005,19 +1038,16 @@ export const updateElbowArrowPoints = ( { x: arrow.x, y: arrow.y, - startBinding: - typeof updates.startBinding !== "undefined" - ? updates.startBinding - : arrow.startBinding, - endBinding: - typeof updates.endBinding !== "undefined" - ? updates.endBinding - : arrow.endBinding, + startBinding, + endBinding, startArrowhead: arrow.startArrowhead, endArrowhead: arrow.endArrowhead, + points: arrow.points, }, elementsMap, updatedPoints, + startElement, + endElement, options, ); @@ -1038,7 +1068,13 @@ export const updateElbowArrowPoints = ( // Short circuit on no-op to avoid huge performance hit if ( updates.startBinding === arrow.startBinding && - updates.endBinding === arrow.endBinding + updates.endBinding === arrow.endBinding && + (updates.points ?? []).every((p, i) => + pointsEqual( + p, + arrow.points[i] ?? pointFrom(Infinity, Infinity), + ), + ) ) { return {}; } @@ -1145,9 +1181,12 @@ const getElbowArrowData = ( endBinding: FixedPointBinding | null; startArrowhead: Arrowhead | null; endArrowhead: Arrowhead | null; + points: readonly LocalPoint[]; }, - elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, + elementsMap: NonDeletedSceneElementsMap, nextPoints: readonly LocalPoint[], + startElement: ExcalidrawBindableElement | null, + endElement: ExcalidrawBindableElement | null, options?: { isDragging?: boolean; zoom?: AppState["zoom"]; @@ -1161,20 +1200,27 @@ const getElbowArrowData = ( LocalPoint, GlobalPoint >(nextPoints[nextPoints.length - 1], vector(arrow.x, arrow.y)); - const startElement = - arrow.startBinding && - getBindableElementForId(arrow.startBinding.elementId, elementsMap); - const endElement = - arrow.endBinding && - getBindableElementForId(arrow.endBinding.elementId, elementsMap); - const [hoveredStartElement, hoveredEndElement] = options?.isDragging - ? getHoveredElements( + + let hoveredStartElement = startElement; + let hoveredEndElement = endElement; + if (options?.isDragging) { + const elements = Array.from(elementsMap.values()); + hoveredStartElement = + getHoveredElement( origStartGlobalPoint, + elementsMap, + elements, + options?.zoom, + ) || startElement; + hoveredEndElement = + getHoveredElement( origEndGlobalPoint, elementsMap, + elements, options?.zoom, - ) - : [startElement, endElement]; + ) || endElement; + } + const startGlobalPoint = getGlobalPoint( { ...arrow, @@ -2034,7 +2080,6 @@ const normalizeArrowElementUpdate = ( } => { const offsetX = global[0][0]; const offsetY = global[0][1]; - let points = global.map((p) => pointTranslate( p, @@ -2205,42 +2250,26 @@ const getBindPointHeading = ( origPoint, ); -const getHoveredElements = ( - origStartGlobalPoint: GlobalPoint, - origEndGlobalPoint: GlobalPoint, - elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, +const getHoveredElement = ( + origPoint: GlobalPoint, + elementsMap: NonDeletedSceneElementsMap, + elements: readonly NonDeletedExcalidrawElement[], zoom?: AppState["zoom"], ) => { - // TODO: Might be a performance bottleneck and the Map type - // remembers the insertion order anyway... - const nonDeletedSceneElementsMap = toBrandedType( - new Map([...elementsMap].filter((el) => !el[1].isDeleted)), + return getHoveredElementForBinding( + tupleToCoors(origPoint), + elements, + elementsMap, + zoom, + true, + true, ); - const elements = Array.from(elementsMap.values()); - return [ - getHoveredElementForBinding( - tupleToCoors(origStartGlobalPoint), - elements, - nonDeletedSceneElementsMap, - zoom, - true, - true, - ), - getHoveredElementForBinding( - tupleToCoors(origEndGlobalPoint), - elements, - nonDeletedSceneElementsMap, - zoom, - true, - true, - ), - ]; }; const gridAddressesEqual = (a: GridAddress, b: GridAddress): boolean => a[0] === b[0] && a[1] === b[1]; -const validateElbowPoints =

( +export const validateElbowPoints =

( points: readonly P[], tolerance: number = DEDUP_TRESHOLD, ) => diff --git a/packages/excalidraw/element/elementLink.ts b/packages/excalidraw/element/elementLink.ts index 991f9caec..79b689c93 100644 --- a/packages/excalidraw/element/elementLink.ts +++ b/packages/excalidraw/element/elementLink.ts @@ -5,6 +5,7 @@ import { ELEMENT_LINK_KEY } from "../constants"; import { normalizeLink } from "../data/url"; import { elementsAreInSameGroup } from "../groups"; + import type { AppProps, AppState } from "../types"; import type { ExcalidrawElement } from "./types"; diff --git a/packages/excalidraw/element/embeddable.ts b/packages/excalidraw/element/embeddable.ts index 8265a0b13..1dc1968a0 100644 --- a/packages/excalidraw/element/embeddable.ts +++ b/packages/excalidraw/element/embeddable.ts @@ -1,18 +1,20 @@ import { register } from "../actions/register"; import { FONT_FAMILY, VERTICAL_ALIGN } from "../constants"; -import type { ExcalidrawProps } from "../types"; -import { escapeDoubleQuotes, getFontString, updateActiveTool } from "../utils"; import { setCursorForShape } from "../cursor"; +import { CaptureUpdateAction } from "../store"; +import { escapeDoubleQuotes, getFontString, updateActiveTool } from "../utils"; + import { newTextElement } from "./newElement"; import { wrapText } from "./textWrapping"; import { isIframeElement } from "./typeChecks"; + +import type { ExcalidrawProps } from "../types"; +import type { MarkRequired } from "../utility-types"; import type { ExcalidrawElement, ExcalidrawIframeLikeElement, IframeData, } from "./types"; -import type { MarkRequired } from "../utility-types"; -import { CaptureUpdateAction } from "../store"; type IframeDataWithSandbox = MarkRequired; diff --git a/packages/excalidraw/element/flowchart.test.tsx b/packages/excalidraw/element/flowchart.test.tsx index d47c850b7..bc026e7d7 100644 --- a/packages/excalidraw/element/flowchart.test.tsx +++ b/packages/excalidraw/element/flowchart.test.tsx @@ -1,9 +1,9 @@ -import { render, unmountComponent } from "../tests/test-utils"; -import { reseed } from "../random"; -import { UI, Keyboard, Pointer } from "../tests/helpers/ui"; import { Excalidraw } from "../index"; -import { API } from "../tests/helpers/api"; import { KEYS } from "../keys"; +import { reseed } from "../random"; +import { API } from "../tests/helpers/api"; +import { UI, Keyboard, Pointer } from "../tests/helpers/ui"; +import { render, unmountComponent } from "../tests/test-utils"; unmountComponent(); diff --git a/packages/excalidraw/element/flowchart.ts b/packages/excalidraw/element/flowchart.ts index 02ee1ff29..9880f27af 100644 --- a/packages/excalidraw/element/flowchart.ts +++ b/packages/excalidraw/element/flowchart.ts @@ -1,3 +1,12 @@ +import { pointFrom, type LocalPoint } from "@excalidraw/math"; + +import { elementOverlapsWithFrame, elementsAreInFrameBounds } from "../frame"; +import { KEYS } from "../keys"; +import { aabbForElement } from "../shapes"; +import { invariant, toBrandedType } from "../utils"; + +import { bindLinearElement } from "./binding"; +import { updateElbowArrowPoints } from "./elbowArrow"; import { HEADING_DOWN, HEADING_LEFT, @@ -7,10 +16,15 @@ import { headingForPointFromElement, type Heading, } from "./heading"; -import { bindLinearElement } from "./binding"; import { LinearElementEditor } from "./linearElementEditor"; +import { mutateElement } from "./mutateElement"; import { newArrowElement, newElement } from "./newElement"; -import type { SceneElementsMap } from "./types"; +import { + isBindableElement, + isElbowArrow, + isFrameElement, + isFlowchartNodeElement, +} from "./typeChecks"; import { type ElementsMap, type ExcalidrawBindableElement, @@ -20,20 +34,8 @@ import { type Ordered, type OrderedExcalidrawElement, } from "./types"; -import { KEYS } from "../keys"; + import type { AppState, PendingExcalidrawElements } from "../types"; -import { mutateElement } from "./mutateElement"; -import { elementOverlapsWithFrame, elementsAreInFrameBounds } from "../frame"; -import { - isBindableElement, - isElbowArrow, - isFrameElement, - isFlowchartNodeElement, -} from "./typeChecks"; -import { invariant, toBrandedType } from "../utils"; -import { pointFrom, type LocalPoint } from "@excalidraw/math"; -import { aabbForElement } from "../shapes"; -import { updateElbowArrowPoints } from "./elbowArrow"; type LinkDirection = "up" | "right" | "down" | "left"; @@ -472,7 +474,7 @@ const createBindingArrow = ( const update = updateElbowArrowPoints( bindingArrow, - toBrandedType( + toBrandedType( new Map([ ...elementsMap.entries(), [startBindingElement.id, startBindingElement], diff --git a/packages/excalidraw/element/heading.ts b/packages/excalidraw/element/heading.ts index 94e86339d..ddebeca53 100644 --- a/packages/excalidraw/element/heading.ts +++ b/packages/excalidraw/element/heading.ts @@ -1,10 +1,3 @@ -import type { - LocalPoint, - GlobalPoint, - Triangle, - Vector, - Radians, -} from "@excalidraw/math"; import { pointFrom, pointRotateRads, @@ -13,7 +6,17 @@ import { triangleIncludesPoint, vectorFromPoint, } from "@excalidraw/math"; + +import type { + LocalPoint, + GlobalPoint, + Triangle, + Vector, + Radians, +} from "@excalidraw/math"; + import { getCenterForBounds, type Bounds } from "./bounds"; + import type { ExcalidrawBindableElement } from "./types"; export const HEADING_RIGHT = [1, 0] as Heading; diff --git a/packages/excalidraw/element/image.ts b/packages/excalidraw/element/image.ts index 32644b64d..0d5f9fb5a 100644 --- a/packages/excalidraw/element/image.ts +++ b/packages/excalidraw/element/image.ts @@ -3,8 +3,10 @@ // ----------------------------------------------------------------------------- import { MIME_TYPES, SVG_NS } from "../constants"; -import type { AppClassProperties, DataURL, BinaryFiles } from "../types"; + import { isInitializedImageElement } from "./typeChecks"; + +import type { AppClassProperties, DataURL, BinaryFiles } from "../types"; import type { ExcalidrawElement, FileId, diff --git a/packages/excalidraw/element/index.ts b/packages/excalidraw/element/index.ts index a9b747681..abe84e031 100644 --- a/packages/excalidraw/element/index.ts +++ b/packages/excalidraw/element/index.ts @@ -1,10 +1,11 @@ +import { isInvisiblySmallElement } from "./sizeHelpers"; +import { isLinearElementType } from "./typeChecks"; + import type { ExcalidrawElement, NonDeletedExcalidrawElement, NonDeleted, } from "./types"; -import { isInvisiblySmallElement } from "./sizeHelpers"; -import { isLinearElementType } from "./typeChecks"; export { newElement, diff --git a/packages/excalidraw/element/linearElementEditor.ts b/packages/excalidraw/element/linearElementEditor.ts index 4bf1e988b..f9b23f048 100644 --- a/packages/excalidraw/element/linearElementEditor.ts +++ b/packages/excalidraw/element/linearElementEditor.ts @@ -1,3 +1,48 @@ +import { + pointCenter, + pointFrom, + pointRotateRads, + pointsEqual, + type GlobalPoint, + type LocalPoint, + pointDistance, + vectorFromPoint, +} from "@excalidraw/math"; +import { getCurvePathOps } from "@excalidraw/utils/geometry/shape"; + +import type { Radians } from "@excalidraw/math"; + +import { DRAGGING_THRESHOLD } from "../constants"; +import { KEYS, shouldRotateWithDiscreteAngle } from "../keys"; +import { ShapeCache } from "../scene/ShapeCache"; +import { + getBezierCurveLength, + getBezierXY, + getControlPointsForBezierCurve, + isPathALoop, + mapIntervalToBezierT, +} from "../shapes"; +import { getGridPoint } from "../snapping"; +import { invariant, tupleToCoors } from "../utils"; + +import { + bindOrUnbindLinearElement, + getHoveredElementForBinding, + isBindingEnabled, +} from "./binding"; +import { getElementPointsCoords, getMinMaxXYFromCurvePathOps } from "./bounds"; +import { headingIsHorizontal, vectorToHeading } from "./heading"; +import { mutateElement } from "./mutateElement"; +import { getBoundTextElement, handleBindTextResize } from "./textElement"; +import { + isBindingElement, + isElbowArrow, + isFixedPointBinding, +} from "./typeChecks"; + +import { getElementAbsoluteCoords, getLockedLinearCursorAlignSize } from "."; + +import type { Bounds } from "./bounds"; import type { NonDeleted, ExcalidrawLinearElement, @@ -12,13 +57,8 @@ import type { FixedSegment, ExcalidrawElbowArrowElement, } from "./types"; -import { getElementAbsoluteCoords, getLockedLinearCursorAlignSize } from "."; -import type { Bounds } from "./bounds"; -import { - getCurvePathOps, - getElementPointsCoords, - getMinMaxXYFromCurvePathOps, -} from "./bounds"; +import type Scene from "../scene/Scene"; +import type { Store } from "../store"; import type { AppState, PointerCoords, @@ -27,48 +67,7 @@ import type { NullableGridSize, Zoom, } from "../types"; -import { mutateElement } from "./mutateElement"; - -import { - bindOrUnbindLinearElement, - getHoveredElementForBinding, - isBindingEnabled, -} from "./binding"; -import { invariant, tupleToCoors } from "../utils"; -import { - isBindingElement, - isElbowArrow, - isFixedPointBinding, -} from "./typeChecks"; -import { KEYS, shouldRotateWithDiscreteAngle } from "../keys"; -import { getBoundTextElement, handleBindTextResize } from "./textElement"; -import { DRAGGING_THRESHOLD } from "../constants"; import type { Mutable } from "../utility-types"; -import { ShapeCache } from "../scene/ShapeCache"; -import type { Store } from "../store"; -import type Scene from "../scene/Scene"; -import type { Radians } from "@excalidraw/math"; -import { - pointCenter, - pointFrom, - pointRotateRads, - pointsEqual, - vector, - type GlobalPoint, - type LocalPoint, - pointDistance, - pointTranslate, - vectorFromPoint, -} from "@excalidraw/math"; -import { - getBezierCurveLength, - getBezierXY, - getControlPointsForBezierCurve, - isPathALoop, - mapIntervalToBezierT, -} from "../shapes"; -import { getGridPoint } from "../snapping"; -import { headingIsHorizontal, vectorToHeading } from "./heading"; const editorMidPointsCache: { version: number | null; @@ -1273,34 +1272,28 @@ export class LinearElementEditor { // all the other points in the opposite direction by delta to // offset it. We do the same with actual element.x/y position, so // this hacks are completely transparent to the user. - let offsetX = 0; - let offsetY = 0; + const [deltaX, deltaY] = + targetPoints.find(({ index }) => index === 0)?.point ?? + pointFrom(0, 0); + const [offsetX, offsetY] = pointFrom( + deltaX - points[0][0], + deltaY - points[0][1], + ); - const selectedOriginPoint = targetPoints.find(({ index }) => index === 0); + const nextPoints = isElbowArrow(element) + ? [ + targetPoints.find((t) => t.index === 0)?.point ?? points[0], + targetPoints.find((t) => t.index === points.length - 1)?.point ?? + points[points.length - 1], + ] + : points.map((p, idx) => { + const current = targetPoints.find((t) => t.index === idx)?.point ?? p; - if (selectedOriginPoint) { - offsetX = - selectedOriginPoint.point[0] + points[selectedOriginPoint.index][0]; - offsetY = - selectedOriginPoint.point[1] + points[selectedOriginPoint.index][1]; - } - - const nextPoints: LocalPoint[] = points.map((p, idx) => { - const selectedPointData = targetPoints.find((t) => t.index === idx); - if (selectedPointData) { - if (selectedPointData.index === 0) { - return p; - } - - const deltaX = - selectedPointData.point[0] - points[selectedPointData.index][0]; - const deltaY = - selectedPointData.point[1] - points[selectedPointData.index][1]; - - return pointFrom(p[0] + deltaX - offsetX, p[1] + deltaY - offsetY); - } - return offsetX || offsetY ? pointFrom(p[0] - offsetX, p[1] - offsetY) : p; - }); + return pointFrom( + current[0] - offsetX, + current[1] - offsetY, + ); + }); LinearElementEditor._updatePoints( element, @@ -1451,14 +1444,6 @@ export class LinearElementEditor { } updates.points = Array.from(nextPoints); - updates.points[0] = pointTranslate( - updates.points[0], - vector(offsetX, offsetY), - ); - updates.points[updates.points.length - 1] = pointTranslate( - updates.points[updates.points.length - 1], - vector(offsetX, offsetY), - ); mutateElement(element, updates, true, { isDragging: options?.isDragging, diff --git a/packages/excalidraw/element/mutateElement.ts b/packages/excalidraw/element/mutateElement.ts index b64366be9..fc96ec312 100644 --- a/packages/excalidraw/element/mutateElement.ts +++ b/packages/excalidraw/element/mutateElement.ts @@ -1,13 +1,16 @@ -import type { ExcalidrawElement, SceneElementsMap } from "./types"; -import Scene from "../scene/Scene"; +import type { Radians } from "@excalidraw/math"; + import { getSizeFromPoints } from "../points"; import { randomInteger } from "../random"; -import { getUpdatedTimestamp, toBrandedType } from "../utils"; -import type { Mutable } from "../utility-types"; +import Scene from "../scene/Scene"; import { ShapeCache } from "../scene/ShapeCache"; -import { isElbowArrow } from "./typeChecks"; +import { getUpdatedTimestamp, toBrandedType } from "../utils"; + import { updateElbowArrowPoints } from "./elbowArrow"; -import type { Radians } from "@excalidraw/math"; +import { isElbowArrow } from "./typeChecks"; + +import type { ExcalidrawElement, NonDeletedSceneElementsMap } from "./types"; +import type { Mutable } from "../utility-types"; export type ElementUpdate = Omit< Partial, @@ -44,7 +47,7 @@ export const mutateElement = >( typeof startBinding !== "undefined" || typeof endBinding !== "undefined") // manual binding to element ) { - const elementsMap = toBrandedType( + const elementsMap = toBrandedType( Scene.getScene(element)?.getNonDeletedElementsMap() ?? new Map(), ); diff --git a/packages/excalidraw/element/newElement.test.ts b/packages/excalidraw/element/newElement.test.ts index 9c9006b6c..418ede1be 100644 --- a/packages/excalidraw/element/newElement.test.ts +++ b/packages/excalidraw/element/newElement.test.ts @@ -1,12 +1,16 @@ -import { duplicateElement, duplicateElements } from "./newElement"; -import { mutateElement } from "./mutateElement"; -import { API } from "../tests/helpers/api"; -import { FONT_FAMILY, ROUNDNESS } from "../constants"; -import { isPrimitive } from "../utils"; -import type { ExcalidrawLinearElement } from "./types"; -import type { LocalPoint } from "@excalidraw/math"; import { pointFrom } from "@excalidraw/math"; +import type { LocalPoint } from "@excalidraw/math"; + +import { FONT_FAMILY, ROUNDNESS } from "../constants"; +import { API } from "../tests/helpers/api"; +import { isPrimitive } from "../utils"; + +import { mutateElement } from "./mutateElement"; +import { duplicateElement, duplicateElements } from "./newElement"; + +import type { ExcalidrawLinearElement } from "./types"; + const assertCloneObjects = (source: any, clone: any) => { for (const key in clone) { if (clone.hasOwnProperty(key) && !isPrimitive(clone[key])) { diff --git a/packages/excalidraw/element/newElement.ts b/packages/excalidraw/element/newElement.ts index 7d1f14910..d11c4c20f 100644 --- a/packages/excalidraw/element/newElement.ts +++ b/packages/excalidraw/element/newElement.ts @@ -1,3 +1,32 @@ +import type { Radians } from "@excalidraw/math"; + +import { + DEFAULT_ELEMENT_PROPS, + DEFAULT_FONT_FAMILY, + DEFAULT_FONT_SIZE, + DEFAULT_TEXT_ALIGN, + DEFAULT_VERTICAL_ALIGN, + ORIG_ID, + VERTICAL_ALIGN, +} from "../constants"; +import { getLineHeight } from "../fonts"; +import { getNewGroupIdsForDuplication } from "../groups"; +import { randomInteger, randomId } from "../random"; +import { + arrayToMap, + getFontString, + getUpdatedTimestamp, + isTestEnv, +} from "../utils"; + +import { getResizedElementAbsoluteCoords } from "./bounds"; +import { bumpVersion, newElementWith } from "./mutateElement"; +import { getBoundTextMaxWidth } from "./textElement"; +import { normalizeText, measureText } from "./textMeasurements"; +import { wrapText } from "./textWrapping"; + +import { getElementAbsoluteCoords } from "."; + import type { ExcalidrawElement, ExcalidrawImageElement, @@ -21,33 +50,8 @@ import type { FixedSegment, ExcalidrawElbowArrowElement, } from "./types"; -import { - arrayToMap, - getFontString, - getUpdatedTimestamp, - isTestEnv, -} from "../utils"; -import { randomInteger, randomId } from "../random"; -import { bumpVersion, newElementWith } from "./mutateElement"; -import { getNewGroupIdsForDuplication } from "../groups"; import type { AppState } from "../types"; -import { getElementAbsoluteCoords } from "."; -import { getResizedElementAbsoluteCoords } from "./bounds"; -import { getBoundTextMaxWidth } from "./textElement"; -import { wrapText } from "./textWrapping"; -import { - DEFAULT_ELEMENT_PROPS, - DEFAULT_FONT_FAMILY, - DEFAULT_FONT_SIZE, - DEFAULT_TEXT_ALIGN, - DEFAULT_VERTICAL_ALIGN, - ORIG_ID, - VERTICAL_ALIGN, -} from "../constants"; import type { MarkOptional, Merge, Mutable } from "../utility-types"; -import { getLineHeight } from "../fonts"; -import type { Radians } from "@excalidraw/math"; -import { normalizeText, measureText } from "./textMeasurements"; export type ElementConstructorOpts = MarkOptional< Omit, diff --git a/packages/excalidraw/element/resizeElements.ts b/packages/excalidraw/element/resizeElements.ts index f71a0bc7a..cd51b8bd5 100644 --- a/packages/excalidraw/element/resizeElements.ts +++ b/packages/excalidraw/element/resizeElements.ts @@ -1,5 +1,60 @@ +import { + pointCenter, + normalizeRadians, + pointFrom, + pointFromPair, + pointRotateRads, + type Radians, + type LocalPoint, +} from "@excalidraw/math"; + +import type { GlobalPoint } from "@excalidraw/math"; + import { MIN_FONT_SIZE, SHIFT_LOCKING_ANGLE } from "../constants"; +import { isInGroup } from "../groups"; import { rescalePoints } from "../points"; +import { getFontString } from "../utils"; + +import { getArrowLocalFixedPoints, updateBoundElements } from "./binding"; +import { + getElementAbsoluteCoords, + getCommonBounds, + getResizedElementAbsoluteCoords, + getCommonBoundingBox, + getElementBounds, +} from "./bounds"; +import { LinearElementEditor } from "./linearElementEditor"; +import { mutateElement } from "./mutateElement"; +import { + getBoundTextElement, + getBoundTextElementId, + getContainerElement, + handleBindTextResize, + getBoundTextMaxWidth, +} from "./textElement"; +import { + getMinTextElementWidth, + measureText, + getApproxMinLineWidth, + getApproxMinLineHeight, +} from "./textMeasurements"; +import { wrapText } from "./textWrapping"; +import { + isArrowElement, + isBoundToContainer, + isElbowArrow, + isFrameLikeElement, + isFreeDrawElement, + isImageElement, + isLinearElement, + isTextElement, +} from "./typeChecks"; + +import type { BoundingBox } from "./bounds"; +import type { + MaybeTransformHandleType, + TransformHandleDirection, +} from "./transformHandles"; import type { ExcalidrawLinearElement, ExcalidrawTextElement, @@ -12,60 +67,9 @@ import type { SceneElementsMap, ExcalidrawElbowArrowElement, } from "./types"; -import type { Mutable } from "../utility-types"; -import { - getElementAbsoluteCoords, - getCommonBounds, - getResizedElementAbsoluteCoords, - getCommonBoundingBox, - getElementBounds, -} from "./bounds"; -import type { BoundingBox } from "./bounds"; -import { - isArrowElement, - isBoundToContainer, - isElbowArrow, - isFrameLikeElement, - isFreeDrawElement, - isImageElement, - isLinearElement, - isTextElement, -} from "./typeChecks"; -import { mutateElement } from "./mutateElement"; -import { getFontString } from "../utils"; -import { getArrowLocalFixedPoints, updateBoundElements } from "./binding"; -import type { - MaybeTransformHandleType, - TransformHandleDirection, -} from "./transformHandles"; -import type { PointerDownState } from "../types"; import type Scene from "../scene/Scene"; -import { - getBoundTextElement, - getBoundTextElementId, - getContainerElement, - handleBindTextResize, - getBoundTextMaxWidth, -} from "./textElement"; -import { wrapText } from "./textWrapping"; -import { LinearElementEditor } from "./linearElementEditor"; -import { isInGroup } from "../groups"; -import type { GlobalPoint } from "@excalidraw/math"; -import { - pointCenter, - normalizeRadians, - pointFrom, - pointFromPair, - pointRotateRads, - type Radians, - type LocalPoint, -} from "@excalidraw/math"; -import { - getMinTextElementWidth, - measureText, - getApproxMinLineWidth, - getApproxMinLineHeight, -} from "./textMeasurements"; +import type { PointerDownState } from "../types"; +import type { Mutable } from "../utility-types"; // Returns true when transform (resizing/rotation) happened export const transformElements = ( @@ -769,32 +773,12 @@ const getResizedOrigin = ( y: y - (newHeight - prevHeight) / 2, }; case "east-side": - // NOTE (mtolmacs): Reverting this for a short period to test if it is - // the cause of the megasized elbow arrows showing up. - if ( - Math.abs( - y + - ((prevWidth - newWidth) / 2) * Math.sin(angle) + - (prevHeight - newHeight) / 2, - ) > 1e6 - ) { - console.error( - "getResizedOrigin() new calculation creates extremely large (> 1e6) y value where the old calculation resulted in", - { - result: - y + - (newHeight - prevHeight) / 2 + - ((prevWidth - newWidth) / 2) * Math.sin(angle), - }, - ); - } - return { x: x + ((prevWidth - newWidth) / 2) * (Math.cos(angle) + 1), y: y + - (newHeight - prevHeight) / 2 + - ((prevWidth - newWidth) / 2) * Math.sin(angle), + ((prevWidth - newWidth) / 2) * Math.sin(angle) + + (prevHeight - newHeight) / 2, }; case "west-side": return { diff --git a/packages/excalidraw/element/resizeTest.ts b/packages/excalidraw/element/resizeTest.ts index 375ff980b..1eb36d0b2 100644 --- a/packages/excalidraw/element/resizeTest.ts +++ b/packages/excalidraw/element/resizeTest.ts @@ -1,27 +1,3 @@ -import type { - ExcalidrawElement, - PointerType, - NonDeletedExcalidrawElement, - ElementsMap, -} from "./types"; - -import type { - TransformHandleType, - TransformHandle, - MaybeTransformHandleType, -} from "./transformHandles"; -import { - getTransformHandlesFromCoords, - getTransformHandles, - getOmitSidesForDevice, - canResizeFromSides, -} from "./transformHandles"; -import type { AppState, Device, Zoom } from "../types"; -import type { Bounds } from "./bounds"; -import { getElementAbsoluteCoords } from "./bounds"; -import { SIDE_RESIZING_THRESHOLD } from "../constants"; -import { isImageElement, isLinearElement } from "./typeChecks"; -import type { GlobalPoint, LineSegment, LocalPoint } from "@excalidraw/math"; import { pointFrom, pointOnLineSegment, @@ -29,6 +5,33 @@ import { type Radians, } from "@excalidraw/math"; +import type { GlobalPoint, LineSegment, LocalPoint } from "@excalidraw/math"; + +import { SIDE_RESIZING_THRESHOLD } from "../constants"; + +import { getElementAbsoluteCoords } from "./bounds"; +import { + getTransformHandlesFromCoords, + getTransformHandles, + getOmitSidesForDevice, + canResizeFromSides, +} from "./transformHandles"; +import { isImageElement, isLinearElement } from "./typeChecks"; + +import type { AppState, Device, Zoom } from "../types"; +import type { Bounds } from "./bounds"; +import type { + TransformHandleType, + TransformHandle, + MaybeTransformHandleType, +} from "./transformHandles"; +import type { + ExcalidrawElement, + PointerType, + NonDeletedExcalidrawElement, + ElementsMap, +} from "./types"; + const isInsideTransformHandle = ( transformHandle: TransformHandle, x: number, diff --git a/packages/excalidraw/element/showSelectedShapeActions.ts b/packages/excalidraw/element/showSelectedShapeActions.ts index bbf313d01..44c2e75c3 100644 --- a/packages/excalidraw/element/showSelectedShapeActions.ts +++ b/packages/excalidraw/element/showSelectedShapeActions.ts @@ -1,6 +1,7 @@ -import type { NonDeletedExcalidrawElement } from "./types"; import { getSelectedElements } from "../scene"; + import type { UIAppState } from "../types"; +import type { NonDeletedExcalidrawElement } from "./types"; export const showSelectedShapeActions = ( appState: UIAppState, diff --git a/packages/excalidraw/element/sizeHelpers.test.ts b/packages/excalidraw/element/sizeHelpers.test.ts index 8e63dd9da..c882e1f3c 100644 --- a/packages/excalidraw/element/sizeHelpers.test.ts +++ b/packages/excalidraw/element/sizeHelpers.test.ts @@ -1,7 +1,9 @@ import { vi } from "vitest"; -import { getPerfectElementSize } from "./sizeHelpers"; + import * as constants from "../constants"; +import { getPerfectElementSize } from "./sizeHelpers"; + const EPSILON_DIGITS = 3; // Needed so that we can mock the value of constants which is done in // below tests. In Jest this wasn't needed as global override was possible diff --git a/packages/excalidraw/element/sizeHelpers.ts b/packages/excalidraw/element/sizeHelpers.ts index f633789a9..33b13e188 100644 --- a/packages/excalidraw/element/sizeHelpers.ts +++ b/packages/excalidraw/element/sizeHelpers.ts @@ -1,10 +1,12 @@ -import type { ElementsMap, ExcalidrawElement } from "./types"; +import { SHIFT_LOCKING_ANGLE } from "../constants"; +import { viewportCoordsToSceneCoords } from "../utils"; + +import { getCommonBounds, getElementBounds } from "./bounds"; import { mutateElement } from "./mutateElement"; import { isFreeDrawElement, isLinearElement } from "./typeChecks"; -import { SHIFT_LOCKING_ANGLE } from "../constants"; + +import type { ElementsMap, ExcalidrawElement } from "./types"; import type { AppState, Offsets, Zoom } from "../types"; -import { getCommonBounds, getElementBounds } from "./bounds"; -import { viewportCoordsToSceneCoords } from "../utils"; // TODO: remove invisible elements consistently actions, so that invisible elements are not recorded by the store, exported, broadcasted or persisted // - perhaps could be as part of a standalone 'cleanup' action, in addition to 'finalize' diff --git a/packages/excalidraw/element/sortElements.test.ts b/packages/excalidraw/element/sortElements.test.ts index a7b78e8ea..5f7c4b2e6 100644 --- a/packages/excalidraw/element/sortElements.test.ts +++ b/packages/excalidraw/element/sortElements.test.ts @@ -1,6 +1,8 @@ import { API } from "../tests/helpers/api"; + import { mutateElement } from "./mutateElement"; import { normalizeElementOrder } from "./sortElements"; + import type { ExcalidrawElement } from "./types"; const assertOrder = ( diff --git a/packages/excalidraw/element/sortElements.ts b/packages/excalidraw/element/sortElements.ts index 3078a6827..d395adf2f 100644 --- a/packages/excalidraw/element/sortElements.ts +++ b/packages/excalidraw/element/sortElements.ts @@ -1,4 +1,5 @@ import { arrayToMapWithIndex } from "../utils"; + import type { ExcalidrawElement } from "./types"; const normalizeGroupElementOrder = (elements: readonly ExcalidrawElement[]) => { diff --git a/packages/excalidraw/element/textElement.test.ts b/packages/excalidraw/element/textElement.test.ts index 2c23c2b06..41531a738 100644 --- a/packages/excalidraw/element/textElement.test.ts +++ b/packages/excalidraw/element/textElement.test.ts @@ -1,6 +1,7 @@ import { FONT_FAMILY } from "../constants"; import { getLineHeight } from "../fonts"; import { API } from "../tests/helpers/api"; + import { computeContainerDimensionForBoundText, getContainerCoords, @@ -8,6 +9,7 @@ import { getBoundTextMaxHeight, } from "./textElement"; import { detectLineHeight, getLineHeightInPx } from "./textMeasurements"; + import type { ExcalidrawTextElementWithContainer } from "./types"; describe("Test measureText", () => { diff --git a/packages/excalidraw/element/textElement.ts b/packages/excalidraw/element/textElement.ts index de948d9ce..9893ba5d6 100644 --- a/packages/excalidraw/element/textElement.ts +++ b/packages/excalidraw/element/textElement.ts @@ -1,4 +1,26 @@ +import { + ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO, + ARROW_LABEL_WIDTH_FRACTION, + BOUND_TEXT_PADDING, + DEFAULT_FONT_SIZE, + TEXT_ALIGN, + VERTICAL_ALIGN, +} from "../constants"; import { getFontString, arrayToMap } from "../utils"; + +import { + resetOriginalContainerCache, + updateOriginalContainerCache, +} from "./containerCache"; +import { LinearElementEditor } from "./linearElementEditor"; +import { mutateElement } from "./mutateElement"; +import { measureText } from "./textMeasurements"; +import { wrapText } from "./textWrapping"; +import { isBoundToContainer, isArrowElement } from "./typeChecks"; + +import { isTextElement } from "."; + +import type { MaybeTransformHandleType } from "./transformHandles"; import type { ElementsMap, ExcalidrawElement, @@ -8,27 +30,8 @@ import type { ExcalidrawTextElementWithContainer, NonDeletedExcalidrawElement, } from "./types"; -import { mutateElement } from "./mutateElement"; -import { - ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO, - ARROW_LABEL_WIDTH_FRACTION, - BOUND_TEXT_PADDING, - DEFAULT_FONT_SIZE, - TEXT_ALIGN, - VERTICAL_ALIGN, -} from "../constants"; -import type { MaybeTransformHandleType } from "./transformHandles"; -import { isTextElement } from "."; -import { wrapText } from "./textWrapping"; -import { isBoundToContainer, isArrowElement } from "./typeChecks"; -import { LinearElementEditor } from "./linearElementEditor"; import type { AppState } from "../types"; -import { - resetOriginalContainerCache, - updateOriginalContainerCache, -} from "./containerCache"; import type { ExtractSetType } from "../utility-types"; -import { measureText } from "./textMeasurements"; export const redrawTextBoundingBox = ( textElement: ExcalidrawTextElement, diff --git a/packages/excalidraw/element/textMeasurements.ts b/packages/excalidraw/element/textMeasurements.ts index f2a132a3a..840896cfc 100644 --- a/packages/excalidraw/element/textMeasurements.ts +++ b/packages/excalidraw/element/textMeasurements.ts @@ -4,6 +4,7 @@ import { DEFAULT_FONT_FAMILY, } from "../constants"; import { getFontString, isTestEnv, normalizeEOL } from "../utils"; + import type { FontString, ExcalidrawTextElement } from "./types"; export const measureText = ( diff --git a/packages/excalidraw/element/textWrapping.test.ts b/packages/excalidraw/element/textWrapping.test.ts index 6c7bcb819..357736a2e 100644 --- a/packages/excalidraw/element/textWrapping.test.ts +++ b/packages/excalidraw/element/textWrapping.test.ts @@ -1,4 +1,5 @@ import { wrapText, parseTokens } from "./textWrapping"; + import type { FontString } from "./types"; describe("Test wrapText", () => { diff --git a/packages/excalidraw/element/textWrapping.ts b/packages/excalidraw/element/textWrapping.ts index 1913f6ed3..5df7051c0 100644 --- a/packages/excalidraw/element/textWrapping.ts +++ b/packages/excalidraw/element/textWrapping.ts @@ -1,5 +1,7 @@ import { ENV } from "../constants"; + import { charWidth, getLineWidth } from "./textMeasurements"; + import type { FontString } from "./types"; let cachedCjkRegex: RegExp | undefined; diff --git a/packages/excalidraw/element/textWysiwyg.test.tsx b/packages/excalidraw/element/textWysiwyg.test.tsx index 0842e30fd..11c700e33 100644 --- a/packages/excalidraw/element/textWysiwyg.test.tsx +++ b/packages/excalidraw/element/textWysiwyg.test.tsx @@ -1,29 +1,31 @@ +import { pointFrom } from "@excalidraw/math"; +import { queryByText } from "@testing-library/react"; import React from "react"; + +import { FONT_FAMILY, TEXT_ALIGN, VERTICAL_ALIGN } from "../constants"; import { Excalidraw } from "../index"; +import { CODES, KEYS } from "../keys"; +import { API } from "../tests/helpers/api"; +import { Keyboard, Pointer, UI } from "../tests/helpers/ui"; +import { getTextEditor, updateTextEditor } from "../tests/queries/dom"; import { GlobalTestState, render, screen, unmountComponent, } from "../tests/test-utils"; -import { Keyboard, Pointer, UI } from "../tests/helpers/ui"; -import { CODES, KEYS } from "../keys"; import { fireEvent, mockBoundingClientRect, restoreOriginalGetBoundingClientRect, } from "../tests/test-utils"; -import { queryByText } from "@testing-library/react"; -import { FONT_FAMILY, TEXT_ALIGN, VERTICAL_ALIGN } from "../constants"; +import { getOriginalContainerHeightFromCache } from "./containerCache"; + import type { ExcalidrawTextElement, ExcalidrawTextElementWithContainer, } from "./types"; -import { API } from "../tests/helpers/api"; -import { getOriginalContainerHeightFromCache } from "./containerCache"; -import { getTextEditor, updateTextEditor } from "../tests/queries/dom"; -import { pointFrom } from "@excalidraw/math"; unmountComponent(); diff --git a/packages/excalidraw/element/textWysiwyg.tsx b/packages/excalidraw/element/textWysiwyg.tsx index 01dfc600f..4897f323e 100644 --- a/packages/excalidraw/element/textWysiwyg.tsx +++ b/packages/excalidraw/element/textWysiwyg.tsx @@ -1,24 +1,28 @@ +import { + actionResetZoom, + actionZoomIn, + actionZoomOut, +} from "../actions/actionCanvas"; +import { + actionDecreaseFontSize, + actionIncreaseFontSize, +} from "../actions/actionProperties"; +import { parseClipboard } from "../clipboard"; +import { CLASSES, POINTER_BUTTON } from "../constants"; import { CODES, KEYS } from "../keys"; +import Scene from "../scene/Scene"; import { isWritableElement, getFontString, getFontFamilyString, isTestEnv, } from "../utils"; -import Scene from "../scene/Scene"; + import { - isArrowElement, - isBoundToContainer, - isTextElement, -} from "./typeChecks"; -import { CLASSES, POINTER_BUTTON } from "../constants"; -import type { - ExcalidrawElement, - ExcalidrawLinearElement, - ExcalidrawTextElementWithContainer, - ExcalidrawTextElement, -} from "./types"; -import type { AppState } from "../types"; + originalContainerCache, + updateOriginalContainerCache, +} from "./containerCache"; +import { LinearElementEditor } from "./linearElementEditor"; import { bumpVersion, mutateElement } from "./mutateElement"; import { getBoundTextElementId, @@ -31,25 +35,23 @@ import { computeBoundTextPosition, getBoundTextElement, } from "./textElement"; -import { wrapText } from "./textWrapping"; -import { - actionDecreaseFontSize, - actionIncreaseFontSize, -} from "../actions/actionProperties"; -import { - actionResetZoom, - actionZoomIn, - actionZoomOut, -} from "../actions/actionCanvas"; -import type App from "../components/App"; -import { LinearElementEditor } from "./linearElementEditor"; -import { parseClipboard } from "../clipboard"; -import { - originalContainerCache, - updateOriginalContainerCache, -} from "./containerCache"; import { getTextWidth, measureText } from "./textMeasurements"; import { normalizeText } from "./textMeasurements"; +import { wrapText } from "./textWrapping"; +import { + isArrowElement, + isBoundToContainer, + isTextElement, +} from "./typeChecks"; + +import type { + ExcalidrawElement, + ExcalidrawLinearElement, + ExcalidrawTextElementWithContainer, + ExcalidrawTextElement, +} from "./types"; +import type App from "../components/App"; +import type { AppState } from "../types"; const getTransform = ( width: number, diff --git a/packages/excalidraw/element/transformHandles.ts b/packages/excalidraw/element/transformHandles.ts index d34eb3279..ab5691df8 100644 --- a/packages/excalidraw/element/transformHandles.ts +++ b/packages/excalidraw/element/transformHandles.ts @@ -1,26 +1,29 @@ -import type { - ElementsMap, - ExcalidrawElement, - NonDeletedExcalidrawElement, - PointerType, -} from "./types"; +import { pointFrom, pointRotateRads } from "@excalidraw/math"; + +import type { Radians } from "@excalidraw/math"; + +import { + DEFAULT_TRANSFORM_HANDLE_SPACING, + isAndroid, + isIOS, +} from "../constants"; -import type { Bounds } from "./bounds"; import { getElementAbsoluteCoords } from "./bounds"; -import type { Device, InteractiveCanvasAppState, Zoom } from "../types"; import { isElbowArrow, isFrameLikeElement, isImageElement, isLinearElement, } from "./typeChecks"; -import { - DEFAULT_TRANSFORM_HANDLE_SPACING, - isAndroid, - isIOS, -} from "../constants"; -import type { Radians } from "@excalidraw/math"; -import { pointFrom, pointRotateRads } from "@excalidraw/math"; + +import type { Device, InteractiveCanvasAppState, Zoom } from "../types"; +import type { Bounds } from "./bounds"; +import type { + ElementsMap, + ExcalidrawElement, + NonDeletedExcalidrawElement, + PointerType, +} from "./types"; export type TransformHandleDirection = | "n" diff --git a/packages/excalidraw/element/typeChecks.test.ts b/packages/excalidraw/element/typeChecks.test.ts index 60eb9e273..44e4dd755 100644 --- a/packages/excalidraw/element/typeChecks.test.ts +++ b/packages/excalidraw/element/typeChecks.test.ts @@ -1,4 +1,5 @@ import { API } from "../tests/helpers/api"; + import { hasBoundTextElement } from "./typeChecks"; describe("Test TypeChecks", () => { diff --git a/packages/excalidraw/element/typeChecks.ts b/packages/excalidraw/element/typeChecks.ts index 1c560d576..988ce4497 100644 --- a/packages/excalidraw/element/typeChecks.ts +++ b/packages/excalidraw/element/typeChecks.ts @@ -1,7 +1,8 @@ import { ROUNDNESS } from "../constants"; +import { assertNever } from "../utils"; + import type { ElementOrToolType } from "../types"; import type { MarkNonNullable } from "../utility-types"; -import { assertNever } from "../utils"; import type { Bounds } from "./bounds"; import type { ExcalidrawElement, diff --git a/packages/excalidraw/element/types.ts b/packages/excalidraw/element/types.ts index 596586743..49ad800af 100644 --- a/packages/excalidraw/element/types.ts +++ b/packages/excalidraw/element/types.ts @@ -1,4 +1,5 @@ import type { LocalPoint, Radians } from "@excalidraw/math"; + import type { FONT_FAMILY, ROUNDNESS, diff --git a/packages/excalidraw/element/utils.ts b/packages/excalidraw/element/utils.ts index d85cd78c6..8992850dc 100644 --- a/packages/excalidraw/element/utils.ts +++ b/packages/excalidraw/element/utils.ts @@ -1,5 +1,3 @@ -import { getDiamondPoints } from "."; -import type { Curve, LineSegment } from "@excalidraw/math"; import { curve, lineSegment, @@ -11,7 +9,13 @@ import { vectorScale, type GlobalPoint, } from "@excalidraw/math"; + +import type { Curve, LineSegment } from "@excalidraw/math"; + import { getCornerRadius } from "../shapes"; + +import { getDiamondPoints } from "."; + import type { ExcalidrawDiamondElement, ExcalidrawRectanguloidElement, diff --git a/packages/excalidraw/env.cjs b/packages/excalidraw/env.cjs index 8d7862246..63c1bde5f 100644 --- a/packages/excalidraw/env.cjs +++ b/packages/excalidraw/env.cjs @@ -9,9 +9,10 @@ const parseEnvVariables = (filepath) => { }, {}, ); - envVars.VITE_PKG_NAME = pkg.name; - envVars.VITE_PKG_VERSION = pkg.version; - envVars.VITE_IS_EXCALIDRAW_NPM_PACKAGE = true; + + envVars.PKG_NAME = pkg.name; + envVars.PKG_VERSION = pkg.version; + return envVars; }; diff --git a/packages/excalidraw/fonts/Cascadia/index.ts b/packages/excalidraw/fonts/Cascadia/index.ts index ecd111644..aad91ff0c 100644 --- a/packages/excalidraw/fonts/Cascadia/index.ts +++ b/packages/excalidraw/fonts/Cascadia/index.ts @@ -1,7 +1,7 @@ -import CascadiaCodeRegular from "./CascadiaCode-Regular.woff2"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import CascadiaCodeRegular from "./CascadiaCode-Regular.woff2"; + export const CascadiaFontFaces: ExcalidrawFontFaceDescriptor[] = [ { uri: CascadiaCodeRegular, diff --git a/packages/excalidraw/fonts/ComicShanns/index.ts b/packages/excalidraw/fonts/ComicShanns/index.ts index bf78650b4..20d23c28e 100644 --- a/packages/excalidraw/fonts/ComicShanns/index.ts +++ b/packages/excalidraw/fonts/ComicShanns/index.ts @@ -1,13 +1,13 @@ // The following file content was generated with https://chinese-font.netlify.app/online-split, // but has been manully rewritten from `@font-face` rules into TS while leveraging FontFace API. -import _0 from "./ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2"; -import _1 from "./ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2"; -import _2 from "./ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2"; -import _3 from "./ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import _0 from "./ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2"; +import _3 from "./ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2"; +import _2 from "./ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2"; +import _1 from "./ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2"; + /* Generated By cn-font-split@5.2.2 https://www.npmjs.com/package/cn-font-split CreateTime: Thu, 17 Oct 2024 09:57:51 GMT; Origin File Name Table: diff --git a/packages/excalidraw/fonts/Emoji/index.ts b/packages/excalidraw/fonts/Emoji/index.ts index 491c7b8c9..323d075cb 100644 --- a/packages/excalidraw/fonts/Emoji/index.ts +++ b/packages/excalidraw/fonts/Emoji/index.ts @@ -1,5 +1,4 @@ import { LOCAL_FONT_PROTOCOL } from "../FontMetadata"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; export const EmojiFontFaces: ExcalidrawFontFaceDescriptor[] = [ diff --git a/packages/excalidraw/fonts/ExcalidrawFontFace.ts b/packages/excalidraw/fonts/ExcalidrawFontFace.ts index a20a45577..615fef20f 100644 --- a/packages/excalidraw/fonts/ExcalidrawFontFace.ts +++ b/packages/excalidraw/fonts/ExcalidrawFontFace.ts @@ -1,6 +1,7 @@ -import { promiseTry } from "../utils"; -import { LOCAL_FONT_PROTOCOL } from "./FontMetadata"; import { subsetWoff2GlyphsByCodepoints } from "../subset/subset-main"; +import { promiseTry } from "../utils"; + +import { LOCAL_FONT_PROTOCOL } from "./FontMetadata"; type DataURL = string; @@ -9,9 +10,9 @@ export class ExcalidrawFontFace { public readonly fontFace: FontFace; private static readonly ASSETS_FALLBACK_URL = `https://esm.sh/${ - import.meta.env.VITE_PKG_NAME - ? `${import.meta.env.VITE_PKG_NAME}@${import.meta.env.VITE_PKG_VERSION}` // should be provided by vite during package build - : "@excalidraw/excalidraw" // fallback to latest package version (i.e. for app) + import.meta.env.PKG_NAME + ? `${import.meta.env.PKG_NAME}@${import.meta.env.PKG_VERSION}` // is provided during package build + : "@excalidraw/excalidraw" // fallback to the latest package version (i.e. for app) }/dist/prod/`; constructor(family: string, uri: string, descriptors?: FontFaceDescriptors) { diff --git a/packages/excalidraw/fonts/Excalifont/index.ts b/packages/excalidraw/fonts/Excalifont/index.ts index 7e11af6c6..bcd384be5 100644 --- a/packages/excalidraw/fonts/Excalifont/index.ts +++ b/packages/excalidraw/fonts/Excalifont/index.ts @@ -1,13 +1,13 @@ -import _0 from "./Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2"; -import _1 from "./Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2"; -import _2 from "./Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2"; -import _3 from "./Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2"; -import _4 from "./Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2"; -import _5 from "./Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2"; -import _6 from "./Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import _5 from "./Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2"; +import _4 from "./Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2"; +import _3 from "./Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2"; +import _6 from "./Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2"; +import _0 from "./Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2"; +import _2 from "./Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2"; +import _1 from "./Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2"; + /* Generated By cn-font-split@5.2.2 https://www.npmjs.com/package/cn-font-split CreateTime: Mon, 14 Oct 2024 18:59:19 GMT; Origin File Name Table: diff --git a/packages/excalidraw/fonts/FontMetadata.ts b/packages/excalidraw/fonts/FontMetadata.ts index e93380e81..e8b46205b 100644 --- a/packages/excalidraw/fonts/FontMetadata.ts +++ b/packages/excalidraw/fonts/FontMetadata.ts @@ -1,4 +1,3 @@ -import type { JSX } from "react"; import { FreedrawIcon, FontFamilyNormalIcon, @@ -7,6 +6,8 @@ import { } from "../components/icons"; import { FONT_FAMILY, FONT_FAMILY_FALLBACKS } from "../constants"; +import type { JSX } from "react"; + /** * Encapsulates font metrics with additional font metadata. * */ diff --git a/packages/excalidraw/fonts/Fonts.ts b/packages/excalidraw/fonts/Fonts.ts index 4b8ba7828..c1b94bdef 100644 --- a/packages/excalidraw/fonts/Fonts.ts +++ b/packages/excalidraw/fonts/Fonts.ts @@ -7,15 +7,17 @@ import { } from "../constants"; import { isTextElement } from "../element"; import { getContainerElement } from "../element/textElement"; +import { charWidth } from "../element/textMeasurements"; import { containsCJK } from "../element/textWrapping"; import { ShapeCache } from "../scene/ShapeCache"; import { getFontString, PromisePool, promiseTry } from "../utils"; -import { ExcalidrawFontFace } from "./ExcalidrawFontFace"; import { CascadiaFontFaces } from "./Cascadia"; import { ComicShannsFontFaces } from "./ComicShanns"; import { EmojiFontFaces } from "./Emoji"; +import { ExcalidrawFontFace } from "./ExcalidrawFontFace"; import { ExcalifontFontFaces } from "./Excalifont"; +import { FONT_METADATA, type FontMetadata } from "./FontMetadata"; import { HelveticaFontFaces } from "./Helvetica"; import { LiberationFontFaces } from "./Liberation"; import { LilitaFontFaces } from "./Lilita"; @@ -23,7 +25,6 @@ import { NunitoFontFaces } from "./Nunito"; import { VirgilFontFaces } from "./Virgil"; import { XiaolaiFontFaces } from "./Xiaolai"; -import { FONT_METADATA, type FontMetadata } from "./FontMetadata"; import type { ExcalidrawElement, ExcalidrawTextElement, @@ -31,7 +32,6 @@ import type { } from "../element/types"; import type Scene from "../scene/Scene"; import type { ValueOf } from "../utility-types"; -import { charWidth } from "../element/textMeasurements"; export class Fonts { // it's ok to track fonts across multiple instances only once, so let's use diff --git a/packages/excalidraw/fonts/Helvetica/index.ts b/packages/excalidraw/fonts/Helvetica/index.ts index a0e7ecb61..f13d15118 100644 --- a/packages/excalidraw/fonts/Helvetica/index.ts +++ b/packages/excalidraw/fonts/Helvetica/index.ts @@ -1,5 +1,4 @@ import { LOCAL_FONT_PROTOCOL } from "../FontMetadata"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; export const HelveticaFontFaces: ExcalidrawFontFaceDescriptor[] = [ diff --git a/packages/excalidraw/fonts/Liberation/index.ts b/packages/excalidraw/fonts/Liberation/index.ts index 5bc964815..86b3e72ec 100644 --- a/packages/excalidraw/fonts/Liberation/index.ts +++ b/packages/excalidraw/fonts/Liberation/index.ts @@ -1,7 +1,7 @@ -import LiberationSansRegular from "./LiberationSans-Regular.woff2"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import LiberationSansRegular from "./LiberationSans-Regular.woff2"; + export const LiberationFontFaces: ExcalidrawFontFaceDescriptor[] = [ { uri: LiberationSansRegular, diff --git a/packages/excalidraw/fonts/Lilita/index.ts b/packages/excalidraw/fonts/Lilita/index.ts index d5ea82e58..37a5d6a5e 100644 --- a/packages/excalidraw/fonts/Lilita/index.ts +++ b/packages/excalidraw/fonts/Lilita/index.ts @@ -1,10 +1,9 @@ -import LilitaLatin from "./Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2"; -import LilitaLatinExt from "./Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2"; - import { GOOGLE_FONTS_RANGES } from "../FontMetadata"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import LilitaLatinExt from "./Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2"; +import LilitaLatin from "./Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2"; + export const LilitaFontFaces: ExcalidrawFontFaceDescriptor[] = [ { uri: LilitaLatinExt, diff --git a/packages/excalidraw/fonts/Nunito/index.ts b/packages/excalidraw/fonts/Nunito/index.ts index 4db432d07..3b092b0d6 100644 --- a/packages/excalidraw/fonts/Nunito/index.ts +++ b/packages/excalidraw/fonts/Nunito/index.ts @@ -1,13 +1,12 @@ -import Latin from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2"; -import LatinExt from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2"; -import Cyrilic from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2"; -import CyrilicExt from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2"; -import Vietnamese from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2"; - import { GOOGLE_FONTS_RANGES } from "../FontMetadata"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import Cyrilic from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2"; +import Latin from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2"; +import CyrilicExt from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2"; +import LatinExt from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2"; +import Vietnamese from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2"; + export const NunitoFontFaces: ExcalidrawFontFaceDescriptor[] = [ { uri: CyrilicExt, diff --git a/packages/excalidraw/fonts/Virgil/index.ts b/packages/excalidraw/fonts/Virgil/index.ts index fdd5ffcfc..b9ce7ee78 100644 --- a/packages/excalidraw/fonts/Virgil/index.ts +++ b/packages/excalidraw/fonts/Virgil/index.ts @@ -1,7 +1,7 @@ -import Virgil from "./Virgil-Regular.woff2"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import Virgil from "./Virgil-Regular.woff2"; + export const VirgilFontFaces: ExcalidrawFontFaceDescriptor[] = [ { uri: Virgil, diff --git a/packages/excalidraw/fonts/Xiaolai/index.ts b/packages/excalidraw/fonts/Xiaolai/index.ts index 17fd71831..67476b912 100644 --- a/packages/excalidraw/fonts/Xiaolai/index.ts +++ b/packages/excalidraw/fonts/Xiaolai/index.ts @@ -1,23 +1,31 @@ // The following file content was generated with https://chinese-font.netlify.app/online-split, // but has been manully rewritten from `@font-face` rules into TS while leveraging FontFace API. +import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; + +import _80 from "./Xiaolai-Regular-019d66dcad46dc156b162d267f981c20.woff2"; +import _16 from "./Xiaolai-Regular-04b718e5623574919c8b0dea5f301444.woff2"; +import _13 from "./Xiaolai-Regular-069e77aac84590e2e991d0a0176d34f2.woff2"; +import _166 from "./Xiaolai-Regular-06c77b8c66e51ed6c63ccb502dd8b8af.woff2"; +import _71 from "./Xiaolai-Regular-08e0dc436ad0ad61ba5558db0674d762.woff2"; +import _161 from "./Xiaolai-Regular-093b9ef39a46ceae95a1df18a0a3a326.woff2"; +import _183 from "./Xiaolai-Regular-095c169f3314805276f603a362766abd.woff2"; import _0 from "./Xiaolai-Regular-09850c4077f3fffe707905872e0e2460.woff2"; -import _1 from "./Xiaolai-Regular-7eb9fffd1aa890d07d0f88cc82e6cfe4.woff2"; +import _14 from "./Xiaolai-Regular-41521fade99856108931b4768b1b2648.woff2"; +import _10 from "./Xiaolai-Regular-544fc28abe2c5c30e62383fd4dac255f.woff2"; import _2 from "./Xiaolai-Regular-60a3089806700d379f11827ee9843b6b.woff2"; +import _1 from "./Xiaolai-Regular-7eb9fffd1aa890d07d0f88cc82e6cfe4.woff2"; import _3 from "./Xiaolai-Regular-6fe5c5973cc06f74b2387a631ea36b88.woff2"; +import _6 from "./Xiaolai-Regular-a4c34be6d42152e64b0df90bc4607f64.woff2"; import _4 from "./Xiaolai-Regular-b96d9226ce77ec94ceca043d712182e6.woff2"; import _5 from "./Xiaolai-Regular-6ae5b42180ad70b971c91e7eefb8eba2.woff2"; -import _6 from "./Xiaolai-Regular-a4c34be6d42152e64b0df90bc4607f64.woff2"; import _7 from "./Xiaolai-Regular-c69f61a4ab18d0488c8d1fc12e7028e8.woff2"; +import _30 from "./Xiaolai-Regular-cb17fc3db95f6d139afc9d31a8e93293.woff2"; import _8 from "./Xiaolai-Regular-e3fcf5180fd466c8915c4e8069491054.woff2"; import _9 from "./Xiaolai-Regular-c1f94158256bb1f3bf665b053d895af9.woff2"; -import _10 from "./Xiaolai-Regular-544fc28abe2c5c30e62383fd4dac255f.woff2"; import _11 from "./Xiaolai-Regular-7197d6fda6cba7c3874c53d6381ca239.woff2"; import _12 from "./Xiaolai-Regular-70c2eb8d64e71a42a834eb857ea9df51.woff2"; -import _13 from "./Xiaolai-Regular-069e77aac84590e2e991d0a0176d34f2.woff2"; -import _14 from "./Xiaolai-Regular-41521fade99856108931b4768b1b2648.woff2"; import _15 from "./Xiaolai-Regular-a004ddfcb26e67bd6e678c8ed19e25ce.woff2"; -import _16 from "./Xiaolai-Regular-04b718e5623574919c8b0dea5f301444.woff2"; import _17 from "./Xiaolai-Regular-7e4bde7e9c7f84cd34d8a845e384c746.woff2"; import _18 from "./Xiaolai-Regular-23686f7f29da6e8008c36dd3a80c83d6.woff2"; import _19 from "./Xiaolai-Regular-69c09cc5fa3e55c74fc4821f76909cc3.woff2"; @@ -31,7 +39,6 @@ import _26 from "./Xiaolai-Regular-7e929f262f30c8ee78bf398150b1a7cd.woff2"; import _27 from "./Xiaolai-Regular-73e309718fd16cea44b4d54a33581811.woff2"; import _28 from "./Xiaolai-Regular-9eb5a99df4e76ac3363453ac9ca288b1.woff2"; import _29 from "./Xiaolai-Regular-3e63ed8162808a9e425ed80a8bc79114.woff2"; -import _30 from "./Xiaolai-Regular-cb17fc3db95f6d139afc9d31a8e93293.woff2"; import _31 from "./Xiaolai-Regular-c8b71798409ccc126ee264a00aadcf21.woff2"; import _32 from "./Xiaolai-Regular-11c345711937f0ba4b8f7b6b919c8440.woff2"; import _33 from "./Xiaolai-Regular-e480d9c614742d05f0e78f274f1e69e6.woff2"; @@ -40,15 +47,17 @@ import _35 from "./Xiaolai-Regular-2cf96d082d35ea3d8106851223ad0d16.woff2"; import _36 from "./Xiaolai-Regular-2d43040e86ff03ba677f6f9c04cd0805.woff2"; import _37 from "./Xiaolai-Regular-2a26d20a23b00898ce82f09d2ee47c3f.woff2"; import _38 from "./Xiaolai-Regular-a365e82ed54697a52f27adcea1315fe8.woff2"; +import _41 from "./Xiaolai-Regular-e4bca6cfa53e499cae0a6be4894a90e9.woff2"; +import _105 from "./Xiaolai-Regular-e51ef413167c6e14e0c0fdcc585f2fc9.woff2"; +import _82 from "./Xiaolai-Regular-e5f453bb04da18eed01675eeebd88bf8.woff2"; +import _45 from "./Xiaolai-Regular-e656f091b9dc4709722c9f4b84d3c797.woff2"; +import _47 from "./Xiaolai-Regular-f0f13b5c60e0af5553bd359f5513be1b.woff2"; import _39 from "./Xiaolai-Regular-f5d079153c99a25b9be5b8583c4cc8a7.woff2"; import _40 from "./Xiaolai-Regular-10a7ae9a371830a80c3d844acf1c02d7.woff2"; -import _41 from "./Xiaolai-Regular-e4bca6cfa53e499cae0a6be4894a90e9.woff2"; import _42 from "./Xiaolai-Regular-60a41c7e1c68f22424e6d22df544bc82.woff2"; import _43 from "./Xiaolai-Regular-7ab2bed91166a9dca83a5ebfbe2a7f38.woff2"; import _44 from "./Xiaolai-Regular-670ba603758d94268e8606f240a42e12.woff2"; -import _45 from "./Xiaolai-Regular-e656f091b9dc4709722c9f4b84d3c797.woff2"; import _46 from "./Xiaolai-Regular-15dc6d811c9cd078f9086a740d5a1038.woff2"; -import _47 from "./Xiaolai-Regular-f0f13b5c60e0af5553bd359f5513be1b.woff2"; import _48 from "./Xiaolai-Regular-8c2f33cee3993174f7e87c28e4bf42ee.woff2"; import _49 from "./Xiaolai-Regular-761d05e3cd968cf574166867998ef06a.woff2"; import _50 from "./Xiaolai-Regular-642b26e2e5f5fb780b51b593dbc8c851.woff2"; @@ -72,7 +81,6 @@ import _67 from "./Xiaolai-Regular-0b5d723fdc4e249c140f0909e87d03b4.woff2"; import _68 from "./Xiaolai-Regular-cdbce89e82cc1ab53a2decbf5819278f.woff2"; import _69 from "./Xiaolai-Regular-739bc1a567439c7cffcd1614644593d2.woff2"; import _70 from "./Xiaolai-Regular-72252d73220fa3cd856677888cee1635.woff2"; -import _71 from "./Xiaolai-Regular-08e0dc436ad0ad61ba5558db0674d762.woff2"; import _72 from "./Xiaolai-Regular-cf6ff4e0f491ca0cf3038187a997b9b4.woff2"; import _73 from "./Xiaolai-Regular-9cfb2a77a4e45025105ad29a1748b90d.woff2"; import _74 from "./Xiaolai-Regular-450da755d5bcb70906e1295e559b9602.woff2"; @@ -81,9 +89,7 @@ import _76 from "./Xiaolai-Regular-1ee544f0f1dac422545c505baa788992.woff2"; import _77 from "./Xiaolai-Regular-4806e761d750087c2d734fc64596eaff.woff2"; import _78 from "./Xiaolai-Regular-33432927cd87d40cfe393c7482bf221f.woff2"; import _79 from "./Xiaolai-Regular-be549ab72f0719d606a5c01e2c0219b6.woff2"; -import _80 from "./Xiaolai-Regular-019d66dcad46dc156b162d267f981c20.woff2"; import _81 from "./Xiaolai-Regular-b5c1596551c256e0e9cf02028595b092.woff2"; -import _82 from "./Xiaolai-Regular-e5f453bb04da18eed01675eeebd88bf8.woff2"; import _83 from "./Xiaolai-Regular-cf2cc71752631e579e35b0e423bf2638.woff2"; import _84 from "./Xiaolai-Regular-6f3256af8454371776bc46670d33cc65.woff2"; import _85 from "./Xiaolai-Regular-23f228f3999c01983860012330e4be08.woff2"; @@ -106,7 +112,6 @@ import _101 from "./Xiaolai-Regular-4a0fdb40036e87b40aa08dd30584cb85.woff2"; import _102 from "./Xiaolai-Regular-0f626226ba1272e832aea87bafd9720e.woff2"; import _103 from "./Xiaolai-Regular-938d90c10ff8c20386af7f242c05d6b0.woff2"; import _104 from "./Xiaolai-Regular-b6d128682ee29e471486354d486a1b90.woff2"; -import _105 from "./Xiaolai-Regular-e51ef413167c6e14e0c0fdcc585f2fc9.woff2"; import _106 from "./Xiaolai-Regular-9d81066dd2b337c938df6e90380a00dc.woff2"; import _107 from "./Xiaolai-Regular-20e7bf72fa05de9adf7dbcc7bf51dde6.woff2"; import _108 from "./Xiaolai-Regular-4095eb84ef3874e2600247bee0b04026.woff2"; @@ -162,15 +167,14 @@ import _157 from "./Xiaolai-Regular-774d4f764a1299da5d28ec2f2ffe0d69.woff2"; import _158 from "./Xiaolai-Regular-7718fe60986d8b42b1be9c5ace5ccf25.woff2"; import _159 from "./Xiaolai-Regular-aa5c9ca6cf4fba00433b7aa3fa10671a.woff2"; import _160 from "./Xiaolai-Regular-4f50e5136e136527280bc902c5817561.woff2"; -import _161 from "./Xiaolai-Regular-093b9ef39a46ceae95a1df18a0a3a326.woff2"; import _162 from "./Xiaolai-Regular-a0ca5df4258213d7fc9fce80f65ce760.woff2"; import _163 from "./Xiaolai-Regular-d2666cbed13462c5dc36fa2f15c202ca.woff2"; import _164 from "./Xiaolai-Regular-1e6fd68f1f3902ce48ce8c69df385622.woff2"; import _165 from "./Xiaolai-Regular-87599f94b6cc129d505b375798d0d751.woff2"; -import _166 from "./Xiaolai-Regular-06c77b8c66e51ed6c63ccb502dd8b8af.woff2"; import _167 from "./Xiaolai-Regular-13ae07ed2e272d26d59bc0691cd7117a.woff2"; import _168 from "./Xiaolai-Regular-353f33792a8f60dc69323ddf635a269e.woff2"; import _169 from "./Xiaolai-Regular-0facdf1ea213ba40261022f5d5ed4493.woff2"; +import _202 from "./Xiaolai-Regular-f6032fc06eb20480f096199713f70885.woff2"; import _170 from "./Xiaolai-Regular-f8ee5d36068a42b51d0e4a1116cfcec1.woff2"; import _171 from "./Xiaolai-Regular-79d494361ae093b69e74ee9dbe65bfd4.woff2"; import _172 from "./Xiaolai-Regular-74e2263a91439c25b91d5132ce9f4d62.woff2"; @@ -184,7 +188,6 @@ import _179 from "./Xiaolai-Regular-8e9f97f01034820170065b2921b4fb5e.woff2"; import _180 from "./Xiaolai-Regular-13d2887ec8ee73c43acdabc52a05af7b.woff2"; import _181 from "./Xiaolai-Regular-72536a3d71b694a0d53dd90ddceae41e.woff2"; import _182 from "./Xiaolai-Regular-603aefd23e350ba7eb124273e3c9bcf1.woff2"; -import _183 from "./Xiaolai-Regular-095c169f3314805276f603a362766abd.woff2"; import _184 from "./Xiaolai-Regular-9544732d2e62d1a429674f8ee41b5d3a.woff2"; import _185 from "./Xiaolai-Regular-d3716376641d615e2995605b29bca7b6.woff2"; import _186 from "./Xiaolai-Regular-5a1ce3117cfe90c48e8fb4a9a00f694d.woff2"; @@ -203,7 +206,6 @@ import _198 from "./Xiaolai-Regular-24476a126f129212beb33f66853ea151.woff2"; import _199 from "./Xiaolai-Regular-1b611157cd46bb184d4fa4dae2d6a2b8.woff2"; import _200 from "./Xiaolai-Regular-56a32a7689abd0326e57c10c6c069bb4.woff2"; import _201 from "./Xiaolai-Regular-3cc70dbb64df5b21f1326cc24dee2195.woff2"; -import _202 from "./Xiaolai-Regular-f6032fc06eb20480f096199713f70885.woff2"; import _203 from "./Xiaolai-Regular-e2ead7ea7da0437f085f42ffc05f8d13.woff2"; import _204 from "./Xiaolai-Regular-97f7f48ce90c9429bf32ae51469db74d.woff2"; import _205 from "./Xiaolai-Regular-24a21c1e4449222e8d1898d69ff3a404.woff2"; @@ -211,8 +213,6 @@ import _206 from "./Xiaolai-Regular-726303e0774b4e678bff8c2deb6ca603.woff2"; import _207 from "./Xiaolai-Regular-5a7fac4b8b23a6e4e5ba0c9bf1756c91.woff2"; import _208 from "./Xiaolai-Regular-2b7441d46298788ac94e610ffcc709b6.woff2"; -import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; - /* Generated By cn-font-split@5.2.2 https://www.npmjs.com/package/cn-font-split CreateTime: Tue, 08 Oct 2024 18:34:44 GMT; Origin File Name Table: diff --git a/packages/excalidraw/fractionalIndex.ts b/packages/excalidraw/fractionalIndex.ts index dfb8a4672..8a1459ddd 100644 --- a/packages/excalidraw/fractionalIndex.ts +++ b/packages/excalidraw/fractionalIndex.ts @@ -1,14 +1,16 @@ import { generateNKeysBetween } from "fractional-indexing"; + import { mutateElement } from "./element/mutateElement"; +import { getBoundTextElement } from "./element/textElement"; +import { hasBoundTextElement } from "./element/typeChecks"; +import { InvalidFractionalIndexError } from "./errors"; +import { arrayToMap } from "./utils"; + import type { ExcalidrawElement, FractionalIndex, OrderedExcalidrawElement, } from "./element/types"; -import { InvalidFractionalIndexError } from "./errors"; -import { hasBoundTextElement } from "./element/typeChecks"; -import { getBoundTextElement } from "./element/textElement"; -import { arrayToMap } from "./utils"; /** * Envisioned relation between array order and fractional indices: diff --git a/packages/excalidraw/frame.test.tsx b/packages/excalidraw/frame.test.tsx index 6a5045b2c..fce420c02 100644 --- a/packages/excalidraw/frame.test.tsx +++ b/packages/excalidraw/frame.test.tsx @@ -1,9 +1,11 @@ -import type { ExcalidrawElement } from "./element/types"; -import { convertToExcalidrawElements, Excalidraw } from "./index"; import { API } from "./tests/helpers/api"; import { Keyboard, Pointer } from "./tests/helpers/ui"; import { getCloneByOrigId, render } from "./tests/test-utils"; +import { convertToExcalidrawElements, Excalidraw } from "./index"; + +import type { ExcalidrawElement } from "./element/types"; + const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/frame.ts b/packages/excalidraw/frame.ts index 4659a34a0..758bc273e 100644 --- a/packages/excalidraw/frame.ts +++ b/packages/excalidraw/frame.ts @@ -1,8 +1,25 @@ +import { isPointWithinBounds, pointFrom } from "@excalidraw/math"; +import { + doLineSegmentsIntersect, + elementsOverlappingBBox, +} from "@excalidraw/utils"; + import { getCommonBounds, getElementAbsoluteCoords, isTextElement, } from "./element"; +import { getElementLineSegments } from "./element/bounds"; +import { mutateElement } from "./element/mutateElement"; +import { + getBoundTextElement, + getContainerElement, +} from "./element/textElement"; +import { isFrameElement, isFrameLikeElement } from "./element/typeChecks"; +import { getElementsInGroup, selectGroupsFromGivenElements } from "./groups"; +import { getElementsWithinSelection, getSelectedElements } from "./scene"; +import { arrayToMap } from "./utils"; + import type { ElementsMap, ElementsMapOrArray, @@ -11,28 +28,13 @@ import type { NonDeleted, NonDeletedExcalidrawElement, } from "./element/types"; -import { - getBoundTextElement, - getContainerElement, -} from "./element/textElement"; -import { arrayToMap } from "./utils"; -import { mutateElement } from "./element/mutateElement"; +import type { ExcalidrawElementsIncludingDeleted } from "./scene/Scene"; import type { AppClassProperties, AppState, StaticCanvasAppState, } from "./types"; -import { getElementsWithinSelection, getSelectedElements } from "./scene"; -import { getElementsInGroup, selectGroupsFromGivenElements } from "./groups"; -import type { ExcalidrawElementsIncludingDeleted } from "./scene/Scene"; -import { getElementLineSegments } from "./element/bounds"; -import { - doLineSegmentsIntersect, - elementsOverlappingBBox, -} from "@excalidraw/utils"; -import { isFrameElement, isFrameLikeElement } from "./element/typeChecks"; import type { ReadonlySetLike } from "./utility-types"; -import { isPointWithinBounds, pointFrom } from "@excalidraw/math"; // --------------------------- Frame State ------------------------------------ export const bindElementsToFramesAfterDuplication = ( diff --git a/packages/excalidraw/groups.ts b/packages/excalidraw/groups.ts index 5a4e606f7..cedc4af0f 100644 --- a/packages/excalidraw/groups.ts +++ b/packages/excalidraw/groups.ts @@ -1,3 +1,7 @@ +import { getBoundTextElement } from "./element/textElement"; +import { getSelectedElements } from "./scene"; +import { makeNextSelectedElementIds } from "./scene/selection"; + import type { GroupId, ExcalidrawElement, @@ -11,9 +15,6 @@ import type { AppState, InteractiveCanvasAppState, } from "./types"; -import { getSelectedElements } from "./scene"; -import { getBoundTextElement } from "./element/textElement"; -import { makeNextSelectedElementIds } from "./scene/selection"; import type { Mutable } from "./utility-types"; export const selectGroup = ( diff --git a/packages/excalidraw/history.ts b/packages/excalidraw/history.ts index daed2a394..48ea012bd 100644 --- a/packages/excalidraw/history.ts +++ b/packages/excalidraw/history.ts @@ -1,6 +1,7 @@ +import { Emitter } from "./emitter"; + import type { AppStateChange, ElementsChange } from "./change"; import type { SceneElementsMap } from "./element/types"; -import { Emitter } from "./emitter"; import type { Snapshot } from "./store"; import type { AppState } from "./types"; diff --git a/packages/excalidraw/hooks/useCreatePortalContainer.ts b/packages/excalidraw/hooks/useCreatePortalContainer.ts index e8f5e3db6..b557d7e2f 100644 --- a/packages/excalidraw/hooks/useCreatePortalContainer.ts +++ b/packages/excalidraw/hooks/useCreatePortalContainer.ts @@ -1,4 +1,5 @@ import { useState, useLayoutEffect } from "react"; + import { useDevice, useExcalidrawContainer } from "../components/App"; import { THEME } from "../constants"; import { useUIAppState } from "../context/ui-appState"; diff --git a/packages/excalidraw/hooks/useEmitter.ts b/packages/excalidraw/hooks/useEmitter.ts index 27b94bc91..eebbaaf30 100644 --- a/packages/excalidraw/hooks/useEmitter.ts +++ b/packages/excalidraw/hooks/useEmitter.ts @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; + import type { Emitter } from "../emitter"; export const useEmitter = ( diff --git a/packages/excalidraw/hooks/useLibraryItemSvg.ts b/packages/excalidraw/hooks/useLibraryItemSvg.ts index 72b648d11..a79aab5c5 100644 --- a/packages/excalidraw/hooks/useLibraryItemSvg.ts +++ b/packages/excalidraw/hooks/useLibraryItemSvg.ts @@ -1,7 +1,9 @@ +import { exportToSvg } from "@excalidraw/utils/export"; import { useEffect, useState } from "react"; + import { COLOR_PALETTE } from "../colors"; import { atom, useAtom } from "../editor-jotai"; -import { exportToSvg } from "@excalidraw/utils/export"; + import type { LibraryItem } from "../types"; export type SvgCache = Map; diff --git a/packages/excalidraw/hooks/useOutsideClick.ts b/packages/excalidraw/hooks/useOutsideClick.ts index da9a54d08..7ec2113c2 100644 --- a/packages/excalidraw/hooks/useOutsideClick.ts +++ b/packages/excalidraw/hooks/useOutsideClick.ts @@ -1,4 +1,5 @@ import { useEffect } from "react"; + import { EVENT } from "../constants"; export function useOutsideClick( diff --git a/packages/excalidraw/hooks/useScrollPosition.ts b/packages/excalidraw/hooks/useScrollPosition.ts index 0be2eab95..1fb1408b5 100644 --- a/packages/excalidraw/hooks/useScrollPosition.ts +++ b/packages/excalidraw/hooks/useScrollPosition.ts @@ -1,6 +1,7 @@ -import { useEffect } from "react"; -import { atom, useAtom } from "../editor-jotai"; import throttle from "lodash.throttle"; +import { useEffect } from "react"; + +import { atom, useAtom } from "../editor-jotai"; const scrollPositionAtom = atom(0); diff --git a/packages/excalidraw/i18n.ts b/packages/excalidraw/i18n.ts index e1da5fc44..47bae5979 100644 --- a/packages/excalidraw/i18n.ts +++ b/packages/excalidraw/i18n.ts @@ -1,6 +1,7 @@ +import { useAtomValue, editorJotaiStore, atom } from "./editor-jotai"; import fallbackLangData from "./locales/en.json"; import percentages from "./locales/percentages.json"; -import { useAtomValue, editorJotaiStore, atom } from "./editor-jotai"; + import type { NestedKeyOf } from "./utility-types"; const COMPLETION_THRESHOLD = 85; diff --git a/packages/excalidraw/index-node.ts b/packages/excalidraw/index-node.ts index e966b1d52..3b9499149 100644 --- a/packages/excalidraw/index-node.ts +++ b/packages/excalidraw/index-node.ts @@ -1,5 +1,7 @@ -import { exportToCanvas } from "./scene/export"; import { getDefaultAppState } from "./appState"; +import { exportToCanvas } from "./scene/export"; + +const fs = require("fs"); const { registerFont, createCanvas } = require("canvas"); @@ -74,7 +76,6 @@ const canvas = exportToCanvas( createCanvas, ); -const fs = require("fs"); const out = fs.createWriteStream("test.png"); const stream = (canvas as any).createPNGStream(); stream.pipe(out); diff --git a/packages/excalidraw/index.tsx b/packages/excalidraw/index.tsx index b4b8574bd..f9f25b530 100644 --- a/packages/excalidraw/index.tsx +++ b/packages/excalidraw/index.tsx @@ -1,21 +1,22 @@ import React, { useEffect } from "react"; -import { InitializeApp } from "./components/InitializeApp"; + import App from "./components/App"; -import { isShallowEqual } from "./utils"; +import { InitializeApp } from "./components/InitializeApp"; +import Footer from "./components/footer/FooterCenter"; +import LiveCollaborationTrigger from "./components/live-collaboration/LiveCollaborationTrigger"; +import MainMenu from "./components/main-menu/MainMenu"; +import WelcomeScreen from "./components/welcome-screen/WelcomeScreen"; +import { DEFAULT_UI_OPTIONS } from "./constants"; +import { defaultLang } from "./i18n"; +import { EditorJotaiProvider, editorJotaiStore } from "./editor-jotai"; import polyfill from "./polyfill"; +import { isShallowEqual } from "./utils"; import "./css/app.scss"; import "./css/styles.scss"; import "./fonts/fonts.css"; import type { AppProps, ExcalidrawProps } from "./types"; -import { defaultLang } from "./i18n"; -import { DEFAULT_UI_OPTIONS } from "./constants"; -import { EditorJotaiProvider, editorJotaiStore } from "./editor-jotai"; -import Footer from "./components/footer/FooterCenter"; -import MainMenu from "./components/main-menu/MainMenu"; -import WelcomeScreen from "./components/welcome-screen/WelcomeScreen"; -import LiveCollaborationTrigger from "./components/live-collaboration/LiveCollaborationTrigger"; polyfill(); diff --git a/packages/excalidraw/keys.ts b/packages/excalidraw/keys.ts index 2088f89d6..948e7f568 100644 --- a/packages/excalidraw/keys.ts +++ b/packages/excalidraw/keys.ts @@ -1,4 +1,5 @@ import { isDarwin } from "./constants"; + import type { ValueOf } from "./utility-types"; export const CODES = { diff --git a/packages/excalidraw/laser-trails.ts b/packages/excalidraw/laser-trails.ts index b7733baed..06e6b573a 100644 --- a/packages/excalidraw/laser-trails.ts +++ b/packages/excalidraw/laser-trails.ts @@ -1,12 +1,14 @@ import type { LaserPointerOptions } from "@excalidraw/laser-pointer"; -import type { Trail } from "./animated-trail"; + import { AnimatedTrail } from "./animated-trail"; +import { getClientColor } from "./clients"; +import { DEFAULT_LASER_COLOR } from "./constants"; +import { easeOut } from "./utils"; + +import type { Trail } from "./animated-trail"; import type { AnimationFrameHandler } from "./animation-frame-handler"; import type App from "./components/App"; import type { SocketId } from "./types"; -import { easeOut } from "./utils"; -import { getClientColor } from "./clients"; -import { DEFAULT_LASER_COLOR } from "./constants"; export class LaserTrails implements Trail { public localTrail: AnimatedTrail; diff --git a/packages/excalidraw/queue.ts b/packages/excalidraw/queue.ts index 9cac2c5e9..b7369e5e0 100644 --- a/packages/excalidraw/queue.ts +++ b/packages/excalidraw/queue.ts @@ -1,6 +1,7 @@ +import { promiseTry, resolvablePromise } from "./utils"; + import type { MaybePromise } from "./utility-types"; import type { ResolvablePromise } from "./utils"; -import { promiseTry, resolvablePromise } from "./utils"; type Job = (...args: TArgs) => MaybePromise; diff --git a/packages/excalidraw/random.ts b/packages/excalidraw/random.ts index 851bc28ec..4a4424a76 100644 --- a/packages/excalidraw/random.ts +++ b/packages/excalidraw/random.ts @@ -1,5 +1,6 @@ -import { Random } from "roughjs/bin/math"; import { nanoid } from "nanoid"; +import { Random } from "roughjs/bin/math"; + import { isTestEnv } from "./utils"; let random = new Random(Date.now()); diff --git a/packages/excalidraw/reactUtils.ts b/packages/excalidraw/reactUtils.ts index 535302d42..5bc466395 100644 --- a/packages/excalidraw/reactUtils.ts +++ b/packages/excalidraw/reactUtils.ts @@ -2,8 +2,9 @@ * @param func handler taking at most single parameter (event). */ -import { unstable_batchedUpdates } from "react-dom"; import { version as ReactVersion } from "react"; +import { unstable_batchedUpdates } from "react-dom"; + import { throttleRAF } from "./utils"; export const withBatchedUpdates = < diff --git a/packages/excalidraw/renderer/helpers.ts b/packages/excalidraw/renderer/helpers.ts index 90f40099f..05097f95b 100644 --- a/packages/excalidraw/renderer/helpers.ts +++ b/packages/excalidraw/renderer/helpers.ts @@ -1,8 +1,7 @@ -import type { StaticCanvasAppState, AppState } from "../types"; +import { THEME, THEME_FILTER } from "../constants"; import type { StaticCanvasRenderConfig } from "../scene/types"; - -import { THEME, THEME_FILTER } from "../constants"; +import type { StaticCanvasAppState, AppState } from "../types"; export const fillCircle = ( context: CanvasRenderingContext2D, diff --git a/packages/excalidraw/renderer/interactiveScene.ts b/packages/excalidraw/renderer/interactiveScene.ts index 9aa832770..257decd62 100644 --- a/packages/excalidraw/renderer/interactiveScene.ts +++ b/packages/excalidraw/renderer/interactiveScene.ts @@ -1,48 +1,23 @@ +import { + pointFrom, + type GlobalPoint, + type LocalPoint, + type Radians, +} from "@excalidraw/math"; +import oc from "open-color"; + +import { getClientColor, renderRemoteCursors } from "../clients"; +import { + DEFAULT_TRANSFORM_HANDLE_SPACING, + FRAME_STYLE, + THEME, +} from "../constants"; import { getElementAbsoluteCoords, getTransformHandlesFromCoords, getTransformHandles, getCommonBounds, } from "../element"; - -import { roundRect } from "../renderer/roundRect"; - -import { - getScrollBars, - SCROLLBAR_COLOR, - SCROLLBAR_WIDTH, -} from "../scene/scrollbars"; - -import { renderSelectionElement } from "../renderer/renderElement"; -import { getClientColor, renderRemoteCursors } from "../clients"; -import { - isSelectedViaGroup, - getSelectedGroupIds, - getElementsInGroup, - selectGroupsFromGivenElements, -} from "../groups"; -import type { - TransformHandles, - TransformHandleType, -} from "../element/transformHandles"; -import { - getOmitSidesForDevice, - shouldShowBoundingBox, -} from "../element/transformHandles"; -import { arrayToMap, invariant, throttleRAF } from "../utils"; -import { - DEFAULT_TRANSFORM_HANDLE_SPACING, - FRAME_STYLE, - THEME, -} from "../constants"; -import { type InteractiveCanvasAppState } from "../types"; - -import { renderSnaps } from "../renderer/renderSnaps"; - -import type { - SuggestedBinding, - SuggestedPointBinding, -} from "../element/binding"; import { BINDING_HIGHLIGHT_OFFSET, BINDING_HIGHLIGHT_THICKNESS, @@ -50,11 +25,9 @@ import { } from "../element/binding"; import { LinearElementEditor } from "../element/linearElementEditor"; import { - bootstrapCanvas, - fillCircle, - getNormalizedCanvasDimensions, -} from "./helpers"; -import oc from "open-color"; + getOmitSidesForDevice, + shouldShowBoundingBox, +} from "../element/transformHandles"; import { isElbowArrow, isFrameLikeElement, @@ -62,6 +35,38 @@ import { isLinearElement, isTextElement, } from "../element/typeChecks"; +import { + isSelectedViaGroup, + getSelectedGroupIds, + getElementsInGroup, + selectGroupsFromGivenElements, +} from "../groups"; +import { renderSelectionElement } from "../renderer/renderElement"; +import { renderSnaps } from "../renderer/renderSnaps"; +import { roundRect } from "../renderer/roundRect"; +import { + getScrollBars, + SCROLLBAR_COLOR, + SCROLLBAR_WIDTH, +} from "../scene/scrollbars"; +import { getCornerRadius } from "../shapes"; +import { type InteractiveCanvasAppState } from "../types"; +import { arrayToMap, invariant, throttleRAF } from "../utils"; + +import { + bootstrapCanvas, + fillCircle, + getNormalizedCanvasDimensions, +} from "./helpers"; + +import type { + SuggestedBinding, + SuggestedPointBinding, +} from "../element/binding"; +import type { + TransformHandles, + TransformHandleType, +} from "../element/transformHandles"; import type { ElementsMap, ExcalidrawBindableElement, @@ -78,13 +83,6 @@ import type { InteractiveSceneRenderConfig, RenderableElementsMap, } from "../scene/types"; -import { - pointFrom, - type GlobalPoint, - type LocalPoint, - type Radians, -} from "@excalidraw/math"; -import { getCornerRadius } from "../shapes"; const renderElbowArrowMidPointHighlight = ( context: CanvasRenderingContext2D, diff --git a/packages/excalidraw/renderer/renderElement.ts b/packages/excalidraw/renderer/renderElement.ts index d93469c2d..9209c46d6 100644 --- a/packages/excalidraw/renderer/renderElement.ts +++ b/packages/excalidraw/renderer/renderElement.ts @@ -1,3 +1,43 @@ +import { isRightAngleRads } from "@excalidraw/math"; +import { getStroke } from "perfect-freehand"; +import rough from "roughjs/bin/rough"; + +import { getDefaultAppState } from "../appState"; +import { + BOUND_TEXT_PADDING, + DEFAULT_REDUCED_GLOBAL_ALPHA, + ELEMENT_READY_TO_ERASE_OPACITY, + FRAME_STYLE, + MIME_TYPES, + THEME, +} from "../constants"; +import { getElementAbsoluteCoords } from "../element/bounds"; +import { getUncroppedImageElement } from "../element/cropElement"; +import { LinearElementEditor } from "../element/linearElementEditor"; +import { + getBoundTextElement, + getContainerCoords, + getContainerElement, + getBoundTextMaxHeight, + getBoundTextMaxWidth, +} from "../element/textElement"; +import { getLineHeightInPx } from "../element/textMeasurements"; +import { + isTextElement, + isLinearElement, + isFreeDrawElement, + isInitializedImageElement, + isArrowElement, + hasBoundTextElement, + isMagicFrameElement, + isImageElement, +} from "../element/typeChecks"; +import { getVerticalOffset } from "../fonts"; +import { getContainingFrame } from "../frame"; +import { ShapeCache } from "../scene/ShapeCache"; +import { getCornerRadius } from "../shapes"; +import { distance, getFontString, isRTL } from "../utils"; + import type { ExcalidrawElement, ExcalidrawTextElement, @@ -9,26 +49,11 @@ import type { NonDeletedSceneElementsMap, ElementsMap, } from "../element/types"; -import { - isTextElement, - isLinearElement, - isFreeDrawElement, - isInitializedImageElement, - isArrowElement, - hasBoundTextElement, - isMagicFrameElement, - isImageElement, -} from "../element/typeChecks"; -import { getElementAbsoluteCoords } from "../element/bounds"; -import type { RoughCanvas } from "roughjs/bin/canvas"; - import type { StaticCanvasRenderConfig, RenderableElementsMap, InteractiveCanvasRenderConfig, } from "../scene/types"; -import { distance, getFontString, isRTL } from "../utils"; -import rough from "roughjs/bin/rough"; import type { AppState, StaticCanvasAppState, @@ -37,33 +62,8 @@ import type { ElementsPendingErasure, PendingExcalidrawElements, } from "../types"; -import { getDefaultAppState } from "../appState"; -import { - BOUND_TEXT_PADDING, - DEFAULT_REDUCED_GLOBAL_ALPHA, - ELEMENT_READY_TO_ERASE_OPACITY, - FRAME_STYLE, - MIME_TYPES, - THEME, -} from "../constants"; import type { StrokeOptions } from "perfect-freehand"; -import { getStroke } from "perfect-freehand"; -import { - getBoundTextElement, - getContainerCoords, - getContainerElement, - getBoundTextMaxHeight, - getBoundTextMaxWidth, -} from "../element/textElement"; -import { LinearElementEditor } from "../element/linearElementEditor"; - -import { getContainingFrame } from "../frame"; -import { ShapeCache } from "../scene/ShapeCache"; -import { getVerticalOffset } from "../fonts"; -import { isRightAngleRads } from "@excalidraw/math"; -import { getCornerRadius } from "../shapes"; -import { getUncroppedImageElement } from "../element/cropElement"; -import { getLineHeightInPx } from "../element/textMeasurements"; +import type { RoughCanvas } from "roughjs/bin/canvas"; // using a stronger invert (100% vs our regular 93%) and saturate // as a temp hack to make images in dark theme look closer to original diff --git a/packages/excalidraw/renderer/renderNewElementScene.ts b/packages/excalidraw/renderer/renderNewElementScene.ts index caa7f581c..f80408366 100644 --- a/packages/excalidraw/renderer/renderNewElementScene.ts +++ b/packages/excalidraw/renderer/renderNewElementScene.ts @@ -1,8 +1,10 @@ -import type { NewElementSceneRenderConfig } from "../scene/types"; import { throttleRAF } from "../utils"; + import { bootstrapCanvas, getNormalizedCanvasDimensions } from "./helpers"; import { renderElement } from "./renderElement"; +import type { NewElementSceneRenderConfig } from "../scene/types"; + const _renderNewElementScene = ({ canvas, rc, diff --git a/packages/excalidraw/renderer/renderSnaps.ts b/packages/excalidraw/renderer/renderSnaps.ts index 878e8e523..8c26675ac 100644 --- a/packages/excalidraw/renderer/renderSnaps.ts +++ b/packages/excalidraw/renderer/renderSnaps.ts @@ -1,5 +1,7 @@ import { pointFrom, type GlobalPoint, type LocalPoint } from "@excalidraw/math"; + import { THEME } from "../constants"; + import type { PointSnapLine, PointerSnapLine } from "../snapping"; import type { InteractiveCanvasAppState } from "../types"; diff --git a/packages/excalidraw/renderer/staticScene.ts b/packages/excalidraw/renderer/staticScene.ts index 21fca4590..62aeed5b9 100644 --- a/packages/excalidraw/renderer/staticScene.ts +++ b/packages/excalidraw/renderer/staticScene.ts @@ -1,19 +1,28 @@ +import { + EXTERNAL_LINK_IMG, + ELEMENT_LINK_IMG, + getLinkHandleFromCoords, +} from "../components/hyperlink/helpers"; import { FRAME_STYLE } from "../constants"; import { getElementAbsoluteCoords } from "../element"; - -import { - elementOverlapsWithFrame, - getTargetFrame, - shouldApplyFrameClip, -} from "../frame"; +import { isElementLink } from "../element/elementLink"; +import { createPlaceholderEmbeddableLabel } from "../element/embeddable"; +import { getBoundTextElement } from "../element/textElement"; import { isEmbeddableElement, isIframeLikeElement, isTextElement, } from "../element/typeChecks"; +import { + elementOverlapsWithFrame, + getTargetFrame, + shouldApplyFrameClip, +} from "../frame"; import { renderElement } from "../renderer/renderElement"; -import { createPlaceholderEmbeddableLabel } from "../element/embeddable"; -import type { StaticCanvasAppState, Zoom } from "../types"; +import { throttleRAF } from "../utils"; + +import { bootstrapCanvas, getNormalizedCanvasDimensions } from "./helpers"; + import type { ElementsMap, ExcalidrawFrameLikeElement, @@ -23,15 +32,7 @@ import type { StaticCanvasRenderConfig, StaticSceneRenderConfig, } from "../scene/types"; -import { - EXTERNAL_LINK_IMG, - ELEMENT_LINK_IMG, - getLinkHandleFromCoords, -} from "../components/hyperlink/helpers"; -import { bootstrapCanvas, getNormalizedCanvasDimensions } from "./helpers"; -import { throttleRAF } from "../utils"; -import { getBoundTextElement } from "../element/textElement"; -import { isElementLink } from "../element/elementLink"; +import type { StaticCanvasAppState, Zoom } from "../types"; const GridLineColor = { Bold: "#dddddd", @@ -351,7 +352,14 @@ const _renderStaticScene = ({ renderLinkIcon(element, context, appState, elementsMap); } } catch (error: any) { - console.error(error); + console.error( + error, + element.id, + element.x, + element.y, + element.width, + element.height, + ); } }); diff --git a/packages/excalidraw/renderer/staticSvgScene.ts b/packages/excalidraw/renderer/staticSvgScene.ts index b14faf7f4..23a6890df 100644 --- a/packages/excalidraw/renderer/staticSvgScene.ts +++ b/packages/excalidraw/renderer/staticSvgScene.ts @@ -1,5 +1,3 @@ -import type { Drawable } from "roughjs/bin/core"; -import type { RoughSVG } from "roughjs/bin/svg"; import { FRAME_STYLE, MAX_DECIMALS_FOR_SVG_EXPORT, @@ -8,6 +6,7 @@ import { } from "../constants"; import { normalizeLink, toValidURL } from "../data/url"; import { getElementAbsoluteCoords, hashString } from "../element"; +import { getUncroppedWidthAndHeight } from "../element/cropElement"; import { createPlaceholderEmbeddableLabel, getEmbedLink, @@ -17,27 +16,30 @@ import { getBoundTextElement, getContainerElement, } from "../element/textElement"; +import { getLineHeightInPx } from "../element/textMeasurements"; import { isArrowElement, isIframeLikeElement, isInitializedImageElement, isTextElement, } from "../element/typeChecks"; +import { getVerticalOffset } from "../fonts"; +import { getContainingFrame } from "../frame"; +import { ShapeCache } from "../scene/ShapeCache"; +import { getCornerRadius, isPathALoop } from "../shapes"; +import { getFontFamilyString, isRTL, isTestEnv } from "../utils"; + +import { getFreeDrawSvgPath, IMAGE_INVERT_FILTER } from "./renderElement"; + import type { ExcalidrawElement, ExcalidrawTextElementWithContainer, NonDeletedExcalidrawElement, } from "../element/types"; -import { getContainingFrame } from "../frame"; -import { ShapeCache } from "../scene/ShapeCache"; import type { RenderableElementsMap, SVGRenderConfig } from "../scene/types"; import type { AppState, BinaryFiles } from "../types"; -import { getFontFamilyString, isRTL, isTestEnv } from "../utils"; -import { getFreeDrawSvgPath, IMAGE_INVERT_FILTER } from "./renderElement"; -import { getVerticalOffset } from "../fonts"; -import { getCornerRadius, isPathALoop } from "../shapes"; -import { getUncroppedWidthAndHeight } from "../element/cropElement"; -import { getLineHeightInPx } from "../element/textMeasurements"; +import type { Drawable } from "roughjs/bin/core"; +import type { RoughSVG } from "roughjs/bin/svg"; const roughSVGDrawWithPrecision = ( rsvg: RoughSVG, diff --git a/packages/excalidraw/scene/Renderer.ts b/packages/excalidraw/scene/Renderer.ts index 8048d20c1..19a6c0b10 100644 --- a/packages/excalidraw/scene/Renderer.ts +++ b/packages/excalidraw/scene/Renderer.ts @@ -1,17 +1,17 @@ import { isElementInViewport } from "../element/sizeHelpers"; import { isImageElement } from "../element/typeChecks"; +import { renderInteractiveSceneThrottled } from "../renderer/interactiveScene"; +import { renderStaticSceneThrottled } from "../renderer/staticScene"; +import { memoize, toBrandedType } from "../utils"; + +import type Scene from "./Scene"; +import type { RenderableElementsMap } from "./types"; import type { ExcalidrawElement, NonDeletedElementsMap, NonDeletedExcalidrawElement, } from "../element/types"; -import { renderInteractiveSceneThrottled } from "../renderer/interactiveScene"; -import { renderStaticSceneThrottled } from "../renderer/staticScene"; - import type { AppState } from "../types"; -import { memoize, toBrandedType } from "../utils"; -import type Scene from "./Scene"; -import type { RenderableElementsMap } from "./types"; export class Renderer { private scene: Scene; diff --git a/packages/excalidraw/scene/Scene.ts b/packages/excalidraw/scene/Scene.ts index 99bb9e1e4..0eab8b80e 100644 --- a/packages/excalidraw/scene/Scene.ts +++ b/packages/excalidraw/scene/Scene.ts @@ -1,4 +1,21 @@ import throttle from "lodash.throttle"; + +import { ENV } from "../constants"; +import { isNonDeletedElement } from "../element"; +import { isFrameLikeElement } from "../element/typeChecks"; +import { + syncInvalidIndices, + syncMovedIndices, + validateFractionalIndices, +} from "../fractionalIndex"; +import { getElementsInGroup } from "../groups"; +import { randomInteger } from "../random"; +import { arrayToMap } from "../utils"; +import { toBrandedType } from "../utils"; + +import { getSelectedElements } from "./selection"; + +import type { LinearElementEditor } from "../element/linearElementEditor"; import type { ExcalidrawElement, NonDeletedExcalidrawElement, @@ -10,22 +27,8 @@ import type { OrderedExcalidrawElement, Ordered, } from "../element/types"; -import { isNonDeletedElement } from "../element"; -import type { LinearElementEditor } from "../element/linearElementEditor"; -import { isFrameLikeElement } from "../element/typeChecks"; -import { getSelectedElements } from "./selection"; import type { AppState } from "../types"; import type { Assert, SameType } from "../utility-types"; -import { randomInteger } from "../random"; -import { - syncInvalidIndices, - syncMovedIndices, - validateFractionalIndices, -} from "../fractionalIndex"; -import { arrayToMap } from "../utils"; -import { toBrandedType } from "../utils"; -import { ENV } from "../constants"; -import { getElementsInGroup } from "../groups"; type ElementIdKey = InstanceType["elementId"]; type ElementKey = ExcalidrawElement | ElementIdKey; diff --git a/packages/excalidraw/scene/Shape.ts b/packages/excalidraw/scene/Shape.ts index 0fef0b2b2..64d90b789 100644 --- a/packages/excalidraw/scene/Shape.ts +++ b/packages/excalidraw/scene/Shape.ts @@ -1,19 +1,9 @@ -import type { Point as RoughPoint } from "roughjs/bin/geometry"; -import type { Drawable, Options } from "roughjs/bin/core"; -import type { RoughGenerator } from "roughjs/bin/generator"; -import { getDiamondPoints, getArrowheadPoints } from "../element"; -import type { ElementShapes } from "./types"; -import type { - ExcalidrawElement, - NonDeletedExcalidrawElement, - ExcalidrawSelectionElement, - ExcalidrawLinearElement, - Arrowhead, -} from "../element/types"; -import { generateFreeDrawShape } from "../renderer/renderElement"; -import { isTransparent, assertNever } from "../utils"; +import { pointFrom, pointDistance, type LocalPoint } from "@excalidraw/math"; import { simplify } from "points-on-curve"; + import { ROUGHNESS } from "../constants"; +import { getDiamondPoints, getArrowheadPoints } from "../element"; +import { headingForPointIsHorizontal } from "../element/heading"; import { isElbowArrow, isEmbeddableElement, @@ -21,11 +11,24 @@ import { isIframeLikeElement, isLinearElement, } from "../element/typeChecks"; -import { canChangeRoundness } from "./comparisons"; -import type { EmbedsValidationStatus } from "../types"; -import { pointFrom, pointDistance, type LocalPoint } from "@excalidraw/math"; +import { generateFreeDrawShape } from "../renderer/renderElement"; import { getCornerRadius, isPathALoop } from "../shapes"; -import { headingForPointIsHorizontal } from "../element/heading"; +import { isTransparent, assertNever } from "../utils"; + +import { canChangeRoundness } from "./comparisons"; + +import type { + ExcalidrawElement, + NonDeletedExcalidrawElement, + ExcalidrawSelectionElement, + ExcalidrawLinearElement, + Arrowhead, +} from "../element/types"; +import type { EmbedsValidationStatus } from "../types"; +import type { ElementShapes } from "./types"; +import type { Drawable, Options } from "roughjs/bin/core"; +import type { RoughGenerator } from "roughjs/bin/generator"; +import type { Point as RoughPoint } from "roughjs/bin/geometry"; const getDashArrayDashed = (strokeWidth: number) => [8, 8 + strokeWidth]; @@ -430,12 +433,26 @@ export const _generateElementShape = ( : [pointFrom(0, 0)]; if (isElbowArrow(element)) { - shape = [ - generator.path( - generateElbowArrowShape(points, 16), - generateRoughOptions(element, true), - ), - ]; + // NOTE (mtolmacs): Temporary fix for extremely big arrow shapes + if ( + !points.every( + (point) => Math.abs(point[0]) <= 1e6 && Math.abs(point[1]) <= 1e6, + ) + ) { + console.error( + `Elbow arrow with extreme point positions detected. Arrow not rendered.`, + element.id, + JSON.stringify(points), + ); + shape = []; + } else { + shape = [ + generator.path( + generateElbowArrowShape(points, 16), + generateRoughOptions(element, true), + ), + ]; + } } else if (!element.roundness) { // curve is always the first element // this simplifies finding the curve for an element diff --git a/packages/excalidraw/scene/ShapeCache.ts b/packages/excalidraw/scene/ShapeCache.ts index 39d388a7b..c170b0a80 100644 --- a/packages/excalidraw/scene/ShapeCache.ts +++ b/packages/excalidraw/scene/ShapeCache.ts @@ -1,14 +1,17 @@ -import type { Drawable } from "roughjs/bin/core"; import { RoughGenerator } from "roughjs/bin/generator"; + +import { COLOR_PALETTE } from "../colors"; +import { elementWithCanvasCache } from "../renderer/renderElement"; + +import { _generateElementShape } from "./Shape"; + import type { ExcalidrawElement, ExcalidrawSelectionElement, } from "../element/types"; -import { elementWithCanvasCache } from "../renderer/renderElement"; -import { _generateElementShape } from "./Shape"; -import type { ElementShape, ElementShapes } from "./types"; -import { COLOR_PALETTE } from "../colors"; import type { AppState, EmbedsValidationStatus } from "../types"; +import type { ElementShape, ElementShapes } from "./types"; +import type { Drawable } from "roughjs/bin/core"; export class ShapeCache { private static rg = new RoughGenerator(); diff --git a/packages/excalidraw/scene/export.ts b/packages/excalidraw/scene/export.ts index 7b3325690..8ca35de2c 100644 --- a/packages/excalidraw/scene/export.ts +++ b/packages/excalidraw/scene/export.ts @@ -1,16 +1,6 @@ import rough from "roughjs/bin/rough"; -import type { - ExcalidrawElement, - ExcalidrawFrameLikeElement, - ExcalidrawTextElement, - NonDeletedExcalidrawElement, - NonDeletedSceneElementsMap, -} from "../element/types"; -import type { Bounds } from "../element/bounds"; -import { getCommonBounds, getElementAbsoluteCoords } from "../element/bounds"; -import { renderSceneToSvg } from "../renderer/staticSvgScene"; -import { arrayToMap, distance, getFontString, toBrandedType } from "../utils"; -import type { AppState, BinaryFiles } from "../types"; + +import { getDefaultAppState } from "../appState"; import { DEFAULT_EXPORT_PADDING, FRAME_STYLE, @@ -21,27 +11,39 @@ import { MIME_TYPES, EXPORT_DATA_TYPES, } from "../constants"; -import { getDefaultAppState } from "../appState"; +import { base64ToString, decode, encode, stringToBase64 } from "../data/encode"; import { serializeAsJSON } from "../data/json"; +import { newTextElement } from "../element"; +import { getCommonBounds, getElementAbsoluteCoords } from "../element/bounds"; import { getInitializedImageElements, updateImageCache, } from "../element/image"; +import { newElementWith } from "../element/mutateElement"; +import { isFrameLikeElement } from "../element/typeChecks"; +import { Fonts } from "../fonts"; +import { syncInvalidIndices } from "../fractionalIndex"; import { getElementsOverlappingFrame, getFrameLikeElements, getFrameLikeTitle, getRootElements, } from "../frame"; -import { newTextElement } from "../element"; -import { type Mutable } from "../utility-types"; -import { newElementWith } from "../element/mutateElement"; -import { isFrameLikeElement } from "../element/typeChecks"; -import type { RenderableElementsMap } from "./types"; -import { syncInvalidIndices } from "../fractionalIndex"; import { renderStaticScene } from "../renderer/staticScene"; -import { Fonts } from "../fonts"; -import { base64ToString, decode, encode, stringToBase64 } from "../data/encode"; +import { renderSceneToSvg } from "../renderer/staticSvgScene"; +import { type Mutable } from "../utility-types"; +import { arrayToMap, distance, getFontString, toBrandedType } from "../utils"; + +import type { RenderableElementsMap } from "./types"; +import type { Bounds } from "../element/bounds"; +import type { + ExcalidrawElement, + ExcalidrawFrameLikeElement, + ExcalidrawTextElement, + NonDeletedExcalidrawElement, + NonDeletedSceneElementsMap, +} from "../element/types"; +import type { AppState, BinaryFiles } from "../types"; const truncateText = (element: ExcalidrawTextElement, maxWidth: number) => { if (element.width <= maxWidth) { diff --git a/packages/excalidraw/scene/normalize.ts b/packages/excalidraw/scene/normalize.ts index 2a025fc27..0c73c5a8a 100644 --- a/packages/excalidraw/scene/normalize.ts +++ b/packages/excalidraw/scene/normalize.ts @@ -1,5 +1,7 @@ import { clamp, round } from "@excalidraw/math"; + import { MAX_ZOOM, MIN_ZOOM } from "../constants"; + import type { NormalizedZoomValue } from "../types"; export const getNormalizedZoom = (zoom: number): NormalizedZoomValue => { diff --git a/packages/excalidraw/scene/scroll.ts b/packages/excalidraw/scene/scroll.ts index 5d059e5b4..989564eb0 100644 --- a/packages/excalidraw/scene/scroll.ts +++ b/packages/excalidraw/scene/scroll.ts @@ -1,16 +1,16 @@ -import type { AppState, Offsets, PointerCoords, Zoom } from "../types"; -import type { ExcalidrawElement } from "../element/types"; import { getCommonBounds, getClosestElementBounds, getVisibleElements, } from "../element"; - import { sceneCoordsToViewportCoords, viewportCoordsToSceneCoords, } from "../utils"; +import type { ExcalidrawElement } from "../element/types"; +import type { AppState, Offsets, PointerCoords, Zoom } from "../types"; + const isOutsideViewPort = (appState: AppState, cords: Array) => { const [x1, y1, x2, y2] = cords; const { x: viewportX1, y: viewportY1 } = sceneCoordsToViewportCoords( diff --git a/packages/excalidraw/scene/scrollbars.ts b/packages/excalidraw/scene/scrollbars.ts index 70f7033fb..b44d79f2b 100644 --- a/packages/excalidraw/scene/scrollbars.ts +++ b/packages/excalidraw/scene/scrollbars.ts @@ -1,9 +1,10 @@ import { getCommonBounds } from "../element"; +import { getLanguage } from "../i18n"; +import { getGlobalCSSVariable } from "../utils"; + +import type { ExcalidrawElement } from "../element/types"; import type { InteractiveCanvasAppState } from "../types"; import type { ScrollBars } from "./types"; -import { getGlobalCSSVariable } from "../utils"; -import { getLanguage } from "../i18n"; -import type { ExcalidrawElement } from "../element/types"; export const SCROLLBAR_MARGIN = 4; export const SCROLLBAR_WIDTH = 6; diff --git a/packages/excalidraw/scene/selection.ts b/packages/excalidraw/scene/selection.ts index 3ca91cd50..02f8f05e7 100644 --- a/packages/excalidraw/scene/selection.ts +++ b/packages/excalidraw/scene/selection.ts @@ -1,11 +1,5 @@ -import type { - ElementsMap, - ElementsMapOrArray, - ExcalidrawElement, - NonDeletedExcalidrawElement, -} from "../element/types"; import { getElementAbsoluteCoords, getElementBounds } from "../element"; -import type { AppState, InteractiveCanvasAppState } from "../types"; +import { isElementInViewport } from "../element/sizeHelpers"; import { isBoundToContainer, isFrameLikeElement } from "../element/typeChecks"; import { elementOverlapsWithFrame, @@ -13,7 +7,14 @@ import { getFrameChildren, } from "../frame"; import { isShallowEqual } from "../utils"; -import { isElementInViewport } from "../element/sizeHelpers"; + +import type { + ElementsMap, + ElementsMapOrArray, + ExcalidrawElement, + NonDeletedExcalidrawElement, +} from "../element/types"; +import type { AppState, InteractiveCanvasAppState } from "../types"; /** * Frames and their containing elements are not to be selected at the same time. diff --git a/packages/excalidraw/scene/types.ts b/packages/excalidraw/scene/types.ts index c0bfd1bba..3c198d153 100644 --- a/packages/excalidraw/scene/types.ts +++ b/packages/excalidraw/scene/types.ts @@ -1,5 +1,4 @@ -import type { RoughCanvas } from "roughjs/bin/canvas"; -import type { Drawable } from "roughjs/bin/core"; +import type { UserIdleState } from "../constants"; import type { ExcalidrawElement, NonDeletedElementsMap, @@ -18,7 +17,8 @@ import type { PendingExcalidrawElements, } from "../types"; import type { MakeBrand } from "../utility-types"; -import type { UserIdleState } from "../constants"; +import type { RoughCanvas } from "roughjs/bin/canvas"; +import type { Drawable } from "roughjs/bin/core"; export type RenderableElementsMap = NonDeletedElementsMap & MakeBrand<"RenderableElementsMap">; diff --git a/packages/excalidraw/shapes.tsx b/packages/excalidraw/shapes.tsx index cfd639f2d..b2c391a42 100644 --- a/packages/excalidraw/shapes.tsx +++ b/packages/excalidraw/shapes.tsx @@ -17,6 +17,7 @@ import { getPolygonShape, type GeometricShape, } from "@excalidraw/utils/geometry/shape"; + import { ArrowIcon, DiamondIcon, @@ -36,20 +37,21 @@ import { ROUNDNESS, } from "./constants"; import { getElementAbsoluteCoords } from "./element"; -import type { Bounds } from "./element/bounds"; import { shouldTestInside } from "./element/collision"; import { LinearElementEditor } from "./element/linearElementEditor"; import { getBoundTextElement } from "./element/textElement"; +import { KEYS } from "./keys"; +import { ShapeCache } from "./scene/ShapeCache"; +import { invariant } from "./utils"; + +import type { Bounds } from "./element/bounds"; import type { ElementsMap, ExcalidrawElement, ExcalidrawLinearElement, NonDeleted, } from "./element/types"; -import { KEYS } from "./keys"; -import { ShapeCache } from "./scene/ShapeCache"; import type { NormalizedZoomValue, Zoom } from "./types"; -import { invariant } from "./utils"; export const SHAPES = [ { diff --git a/packages/excalidraw/snapping.ts b/packages/excalidraw/snapping.ts index 1b661516e..7c85f4112 100644 --- a/packages/excalidraw/snapping.ts +++ b/packages/excalidraw/snapping.ts @@ -1,4 +1,3 @@ -import type { InclusiveRange } from "@excalidraw/math"; import { pointFrom, pointRotateRads, @@ -7,26 +6,30 @@ import { rangesOverlap, type GlobalPoint, } from "@excalidraw/math"; + +import type { InclusiveRange } from "@excalidraw/math"; + import { TOOL_TYPE } from "./constants"; -import type { Bounds } from "./element/bounds"; import { getCommonBounds, getDraggedElementsBounds, getElementAbsoluteCoords, } from "./element/bounds"; -import type { MaybeTransformHandleType } from "./element/transformHandles"; import { isBoundToContainer, isFrameLikeElement } from "./element/typeChecks"; -import type { - ElementsMap, - ExcalidrawElement, - NonDeletedExcalidrawElement, -} from "./element/types"; import { getMaximumGroups } from "./groups"; import { KEYS } from "./keys"; import { getSelectedElements, getVisibleAndNonSelectedElements, } from "./scene/selection"; + +import type { Bounds } from "./element/bounds"; +import type { MaybeTransformHandleType } from "./element/transformHandles"; +import type { + ElementsMap, + ExcalidrawElement, + NonDeletedExcalidrawElement, +} from "./element/types"; import type { AppClassProperties, AppState, diff --git a/packages/excalidraw/store.ts b/packages/excalidraw/store.ts index 1343347c4..8b0065884 100644 --- a/packages/excalidraw/store.ts +++ b/packages/excalidraw/store.ts @@ -3,11 +3,12 @@ import { AppStateChange, ElementsChange } from "./change"; import { ENV } from "./constants"; import { newElementWith } from "./element/mutateElement"; import { deepCopyElement } from "./element/newElement"; -import type { OrderedExcalidrawElement } from "./element/types"; import { Emitter } from "./emitter"; +import { isShallowEqual } from "./utils"; + +import type { OrderedExcalidrawElement } from "./element/types"; import type { AppState, ObservedAppState } from "./types"; import type { ValueOf } from "./utility-types"; -import { isShallowEqual } from "./utils"; // hidden non-enumerable property for runtime checks const hiddenObservedAppStateProp = "__observedAppState"; diff --git a/packages/excalidraw/subset/harfbuzz/harfbuzz-loader.ts b/packages/excalidraw/subset/harfbuzz/harfbuzz-loader.ts index 9a48d19c4..120dedb7f 100644 --- a/packages/excalidraw/subset/harfbuzz/harfbuzz-loader.ts +++ b/packages/excalidraw/subset/harfbuzz/harfbuzz-loader.ts @@ -7,8 +7,8 @@ * In the future consider separating common utils into a separate shared chunk. */ -import binary from "./harfbuzz-wasm"; import bindings from "./harfbuzz-bindings"; +import binary from "./harfbuzz-wasm"; /** * Lazy loads wasm and respective bindings for font subsetting based on the harfbuzzjs. diff --git a/packages/excalidraw/subset/subset-main.ts b/packages/excalidraw/subset/subset-main.ts index afccf0d20..5f39af99c 100644 --- a/packages/excalidraw/subset/subset-main.ts +++ b/packages/excalidraw/subset/subset-main.ts @@ -1,6 +1,6 @@ -import { WorkerPool } from "../workers"; -import { isServerEnv, promiseTry } from "../utils"; import { WorkerInTheMainChunkError, WorkerUrlNotDefinedError } from "../errors"; +import { isServerEnv, promiseTry } from "../utils"; +import { WorkerPool } from "../workers"; import type { Commands } from "./subset-shared.chunk"; diff --git a/packages/excalidraw/subset/subset-shared.chunk.ts b/packages/excalidraw/subset/subset-shared.chunk.ts index b64a3825e..4e4b88424 100644 --- a/packages/excalidraw/subset/subset-shared.chunk.ts +++ b/packages/excalidraw/subset/subset-shared.chunk.ts @@ -7,8 +7,8 @@ * In the future consider separating common utils into a separate shared chunk. */ -import loadWoff2 from "./woff2/woff2-loader"; import loadHbSubset from "./harfbuzz/harfbuzz-loader"; +import loadWoff2 from "./woff2/woff2-loader"; /** * Shared commands between the main thread and worker threads. diff --git a/packages/excalidraw/subset/woff2/woff2-loader.ts b/packages/excalidraw/subset/woff2/woff2-loader.ts index 446dc9f8b..7d5de3095 100644 --- a/packages/excalidraw/subset/woff2/woff2-loader.ts +++ b/packages/excalidraw/subset/woff2/woff2-loader.ts @@ -7,8 +7,8 @@ * In the future consider separating common utils into a separate shared chunk. */ -import binary from "./woff2-wasm"; import bindings from "./woff2-bindings"; +import binary from "./woff2-wasm"; /** * Lazy loads wasm and respective bindings for woff2 compression and decompression. diff --git a/packages/excalidraw/tests/App.test.tsx b/packages/excalidraw/tests/App.test.tsx index ad62706a5..8b86477f9 100644 --- a/packages/excalidraw/tests/App.test.tsx +++ b/packages/excalidraw/tests/App.test.tsx @@ -1,10 +1,10 @@ import React from "react"; -import * as StaticScene from "../renderer/staticScene"; -import { reseed } from "../random"; -import { render, queryByTestId, unmountComponent } from "../tests/test-utils"; +import { vi } from "vitest"; import { Excalidraw } from "../index"; -import { vi } from "vitest"; +import { reseed } from "../random"; +import * as StaticScene from "../renderer/staticScene"; +import { render, queryByTestId, unmountComponent } from "../tests/test-utils"; const renderStaticScene = vi.spyOn(StaticScene, "renderStaticScene"); diff --git a/packages/excalidraw/tests/MermaidToExcalidraw.test.tsx b/packages/excalidraw/tests/MermaidToExcalidraw.test.tsx index 05727a0f4..cedb70487 100644 --- a/packages/excalidraw/tests/MermaidToExcalidraw.test.tsx +++ b/packages/excalidraw/tests/MermaidToExcalidraw.test.tsx @@ -1,9 +1,11 @@ import React from "react"; -import { render, waitFor } from "./test-utils"; -import { Excalidraw } from "../index"; import { expect } from "vitest"; -import { getTextEditor, updateTextEditor } from "./queries/dom"; + +import { Excalidraw } from "../index"; + import { mockMermaidToExcalidraw } from "./helpers/mocks"; +import { getTextEditor, updateTextEditor } from "./queries/dom"; +import { render, waitFor } from "./test-utils"; mockMermaidToExcalidraw({ mockRef: true, diff --git a/packages/excalidraw/tests/actionStyles.test.tsx b/packages/excalidraw/tests/actionStyles.test.tsx index abe4a7c00..2e60000ad 100644 --- a/packages/excalidraw/tests/actionStyles.test.tsx +++ b/packages/excalidraw/tests/actionStyles.test.tsx @@ -1,4 +1,6 @@ import React from "react"; + +import { copiedStyles } from "../actions/actionStyles"; import { Excalidraw } from "../index"; import { CODES } from "../keys"; import { API } from "../tests/helpers/api"; @@ -10,7 +12,6 @@ import { screen, togglePopover, } from "../tests/test-utils"; -import { copiedStyles } from "../actions/actionStyles"; const { h } = window; diff --git a/packages/excalidraw/tests/align.test.tsx b/packages/excalidraw/tests/align.test.tsx index 47624e8f4..d29e497ec 100644 --- a/packages/excalidraw/tests/align.test.tsx +++ b/packages/excalidraw/tests/align.test.tsx @@ -1,10 +1,5 @@ import React from "react"; -import { act, unmountComponent, render } from "./test-utils"; -import { Excalidraw } from "../index"; -import { defaultLang, setLanguage } from "../i18n"; -import { UI, Pointer, Keyboard } from "./helpers/ui"; -import { API } from "./helpers/api"; -import { KEYS } from "../keys"; + import { actionAlignVerticallyCentered, actionAlignHorizontallyCentered, @@ -14,6 +9,13 @@ import { actionAlignLeft, actionAlignRight, } from "../actions"; +import { defaultLang, setLanguage } from "../i18n"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; + +import { API } from "./helpers/api"; +import { UI, Pointer, Keyboard } from "./helpers/ui"; +import { act, unmountComponent, render } from "./test-utils"; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/tests/appState.test.tsx b/packages/excalidraw/tests/appState.test.tsx index 4a937cd56..e97c5f3be 100644 --- a/packages/excalidraw/tests/appState.test.tsx +++ b/packages/excalidraw/tests/appState.test.tsx @@ -1,10 +1,13 @@ import React from "react"; -import { fireEvent, queryByTestId, render, waitFor } from "./test-utils"; -import { Excalidraw } from "../index"; -import { API } from "./helpers/api"; + import { getDefaultAppState } from "../appState"; import { EXPORT_DATA_TYPES, MIME_TYPES } from "../constants"; +import { Excalidraw } from "../index"; + +import { API } from "./helpers/api"; import { Pointer, UI } from "./helpers/ui"; +import { fireEvent, queryByTestId, render, waitFor } from "./test-utils"; + import type { ExcalidrawTextElement } from "../element/types"; const { h } = window; diff --git a/packages/excalidraw/tests/binding.test.tsx b/packages/excalidraw/tests/binding.test.tsx index 905a44e70..1c50062c1 100644 --- a/packages/excalidraw/tests/binding.test.tsx +++ b/packages/excalidraw/tests/binding.test.tsx @@ -1,13 +1,15 @@ -import React from "react"; -import { fireEvent, render } from "./test-utils"; -import { Excalidraw, isLinearElement } from "../index"; -import { UI, Pointer, Keyboard } from "./helpers/ui"; -import { getTransformHandles } from "../element/transformHandles"; -import { API } from "./helpers/api"; -import { KEYS } from "../keys"; -import { actionWrapTextInContainer } from "../actions/actionBoundText"; -import { arrayToMap } from "../utils"; import { pointFrom } from "@excalidraw/math"; +import React from "react"; + +import { actionWrapTextInContainer } from "../actions/actionBoundText"; +import { getTransformHandles } from "../element/transformHandles"; +import { Excalidraw, isLinearElement } from "../index"; +import { KEYS } from "../keys"; +import { arrayToMap } from "../utils"; + +import { API } from "./helpers/api"; +import { UI, Pointer, Keyboard } from "./helpers/ui"; +import { fireEvent, render } from "./test-utils"; const { h } = window; diff --git a/packages/excalidraw/tests/clipboard.test.tsx b/packages/excalidraw/tests/clipboard.test.tsx index c2c0a5e2d..c7e17f49d 100644 --- a/packages/excalidraw/tests/clipboard.test.tsx +++ b/packages/excalidraw/tests/clipboard.test.tsx @@ -1,22 +1,25 @@ import React from "react"; import { vi } from "vitest"; + +import { createPasteEvent, serializeAsClipboardJSON } from "../clipboard"; +import { getElementBounds } from "../element"; +import { getLineHeightInPx } from "../element/textMeasurements"; +import { getLineHeight } from "../fonts"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { arrayToMap } from "../utils"; + +import { API } from "./helpers/api"; +import { mockMermaidToExcalidraw } from "./helpers/mocks"; +import { Pointer, Keyboard } from "./helpers/ui"; import { render, waitFor, GlobalTestState, unmountComponent, } from "./test-utils"; -import { Pointer, Keyboard } from "./helpers/ui"; -import { Excalidraw } from "../index"; -import { KEYS } from "../keys"; -import { getLineHeightInPx } from "../element/textMeasurements"; -import { getElementBounds } from "../element"; + import type { NormalizedZoomValue } from "../types"; -import { API } from "./helpers/api"; -import { createPasteEvent, serializeAsClipboardJSON } from "../clipboard"; -import { arrayToMap } from "../utils"; -import { mockMermaidToExcalidraw } from "./helpers/mocks"; -import { getLineHeight } from "../fonts"; const { h } = window; diff --git a/packages/excalidraw/tests/contextmenu.test.tsx b/packages/excalidraw/tests/contextmenu.test.tsx index bb3f415f1..7de349516 100644 --- a/packages/excalidraw/tests/contextmenu.test.tsx +++ b/packages/excalidraw/tests/contextmenu.test.tsx @@ -1,4 +1,15 @@ import React from "react"; +import { vi } from "vitest"; + +import { copiedStyles } from "../actions/actionStyles"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { reseed } from "../random"; +import * as StaticScene from "../renderer/staticScene"; +import { setDateTimeForTests } from "../utils"; + +import { API } from "./helpers/api"; +import { UI, Pointer, Keyboard } from "./helpers/ui"; import { render, fireEvent, @@ -12,16 +23,8 @@ import { togglePopover, unmountComponent, } from "./test-utils"; -import { Excalidraw } from "../index"; -import * as StaticScene from "../renderer/staticScene"; -import { reseed } from "../random"; -import { UI, Pointer, Keyboard } from "./helpers/ui"; -import { KEYS } from "../keys"; + import type { ShortcutName } from "../actions/shortcuts"; -import { copiedStyles } from "../actions/actionStyles"; -import { API } from "./helpers/api"; -import { setDateTimeForTests } from "../utils"; -import { vi } from "vitest"; import type { ActionName } from "../actions/types"; const checkpoint = (name: string) => { diff --git a/packages/excalidraw/tests/cropElement.test.tsx b/packages/excalidraw/tests/cropElement.test.tsx index a508f5d64..ddc93e3fe 100644 --- a/packages/excalidraw/tests/cropElement.test.tsx +++ b/packages/excalidraw/tests/cropElement.test.tsx @@ -1,15 +1,18 @@ import React from "react"; import { vi } from "vitest"; -import { Keyboard, Pointer, UI } from "./helpers/ui"; -import type { ExcalidrawImageElement, ImageCrop } from "../element/types"; -import { act, GlobalTestState, render, unmountComponent } from "./test-utils"; + import { Excalidraw, exportToCanvas, exportToSvg } from ".."; -import { API } from "./helpers/api"; -import type { NormalizedZoomValue } from "../types"; -import { KEYS } from "../keys"; -import { duplicateElement } from "../element"; -import { cloneJSON } from "../utils"; import { actionFlipHorizontal, actionFlipVertical } from "../actions"; +import { duplicateElement } from "../element"; +import { KEYS } from "../keys"; +import { cloneJSON } from "../utils"; + +import { API } from "./helpers/api"; +import { Keyboard, Pointer, UI } from "./helpers/ui"; +import { act, GlobalTestState, render, unmountComponent } from "./test-utils"; + +import type { ExcalidrawImageElement, ImageCrop } from "../element/types"; +import type { NormalizedZoomValue } from "../types"; const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/tests/data/reconcile.test.ts b/packages/excalidraw/tests/data/reconcile.test.ts index f0e8105a1..35a33956a 100644 --- a/packages/excalidraw/tests/data/reconcile.test.ts +++ b/packages/excalidraw/tests/data/reconcile.test.ts @@ -1,13 +1,14 @@ -import type { RemoteExcalidrawElement } from "../../data/reconcile"; import { reconcileElements } from "../../data/reconcile"; +import { syncInvalidIndices } from "../../fractionalIndex"; +import { randomInteger } from "../../random"; +import { cloneJSON } from "../../utils"; + +import type { RemoteExcalidrawElement } from "../../data/reconcile"; import type { ExcalidrawElement, OrderedExcalidrawElement, } from "../../element/types"; -import { syncInvalidIndices } from "../../fractionalIndex"; -import { randomInteger } from "../../random"; import type { AppState } from "../../types"; -import { cloneJSON } from "../../utils"; type Id = string; type ElementLike = { diff --git a/packages/excalidraw/tests/data/restore.test.ts b/packages/excalidraw/tests/data/restore.test.ts index 37a27ac6a..529284358 100644 --- a/packages/excalidraw/tests/data/restore.test.ts +++ b/packages/excalidraw/tests/data/restore.test.ts @@ -1,19 +1,21 @@ +import { pointFrom } from "@excalidraw/math"; +import { vi } from "vitest"; + +import { getDefaultAppState } from "../../appState"; +import { DEFAULT_SIDEBAR, FONT_FAMILY, ROUNDNESS } from "../../constants"; import * as restore from "../../data/restore"; +import { newElementWith } from "../../element/mutateElement"; +import * as sizeHelpers from "../../element/sizeHelpers"; +import { API } from "../helpers/api"; + +import type { ImportedDataState } from "../../data/types"; import type { ExcalidrawElement, ExcalidrawFreeDrawElement, ExcalidrawLinearElement, ExcalidrawTextElement, } from "../../element/types"; -import * as sizeHelpers from "../../element/sizeHelpers"; -import { API } from "../helpers/api"; -import { getDefaultAppState } from "../../appState"; -import type { ImportedDataState } from "../../data/types"; import type { NormalizedZoomValue } from "../../types"; -import { DEFAULT_SIDEBAR, FONT_FAMILY, ROUNDNESS } from "../../constants"; -import { newElementWith } from "../../element/mutateElement"; -import { vi } from "vitest"; -import { pointFrom } from "@excalidraw/math"; describe("restoreElements", () => { const mockSizeHelper = vi.spyOn(sizeHelpers, "isInvisiblySmallElement"); diff --git a/packages/excalidraw/tests/dragCreate.test.tsx b/packages/excalidraw/tests/dragCreate.test.tsx index 743ba7947..ecdfbcb64 100644 --- a/packages/excalidraw/tests/dragCreate.test.tsx +++ b/packages/excalidraw/tests/dragCreate.test.tsx @@ -1,8 +1,12 @@ import React from "react"; +import { vi } from "vitest"; + import { Excalidraw } from "../index"; -import * as StaticScene from "../renderer/staticScene"; -import * as InteractiveScene from "../renderer/interactiveScene"; import { KEYS } from "../keys"; +import { reseed } from "../random"; +import * as InteractiveScene from "../renderer/interactiveScene"; +import * as StaticScene from "../renderer/staticScene"; + import { render, fireEvent, @@ -10,9 +14,8 @@ import { restoreOriginalGetBoundingClientRect, unmountComponent, } from "./test-utils"; + import type { ExcalidrawLinearElement } from "../element/types"; -import { reseed } from "../random"; -import { vi } from "vitest"; unmountComponent(); diff --git a/packages/excalidraw/tests/elementLocking.test.tsx b/packages/excalidraw/tests/elementLocking.test.tsx index 281c26892..a1ca14683 100644 --- a/packages/excalidraw/tests/elementLocking.test.tsx +++ b/packages/excalidraw/tests/elementLocking.test.tsx @@ -1,12 +1,13 @@ import React from "react"; + +import { actionSelectAll } from "../actions"; +import { mutateElement } from "../element/mutateElement"; +import { t } from "../i18n"; import { Excalidraw } from "../index"; -import { render, unmountComponent } from "../tests/test-utils"; -import { Keyboard, Pointer, UI } from "../tests/helpers/ui"; import { KEYS } from "../keys"; import { API } from "../tests/helpers/api"; -import { actionSelectAll } from "../actions"; -import { t } from "../i18n"; -import { mutateElement } from "../element/mutateElement"; +import { Keyboard, Pointer, UI } from "../tests/helpers/ui"; +import { render, unmountComponent } from "../tests/test-utils"; unmountComponent(); diff --git a/packages/excalidraw/tests/excalidraw.test.tsx b/packages/excalidraw/tests/excalidraw.test.tsx index 6fbcf2adc..0e33f8167 100644 --- a/packages/excalidraw/tests/excalidraw.test.tsx +++ b/packages/excalidraw/tests/excalidraw.test.tsx @@ -1,10 +1,12 @@ -import React from "react"; -import { fireEvent, GlobalTestState, toggleMenu, render } from "./test-utils"; -import { Excalidraw, Footer, MainMenu } from "../index"; import { queryByText, queryByTestId } from "@testing-library/react"; +import React from "react"; +import { useMemo } from "react"; + import { THEME } from "../constants"; import { t } from "../i18n"; -import { useMemo } from "react"; +import { Excalidraw, Footer, MainMenu } from "../index"; + +import { fireEvent, GlobalTestState, toggleMenu, render } from "./test-utils"; const { h } = window; diff --git a/packages/excalidraw/tests/export.test.tsx b/packages/excalidraw/tests/export.test.tsx index 3547b2978..c10336271 100644 --- a/packages/excalidraw/tests/export.test.tsx +++ b/packages/excalidraw/tests/export.test.tsx @@ -1,18 +1,21 @@ import React from "react"; -import { render, waitFor } from "./test-utils"; -import { Excalidraw } from "../index"; -import { API } from "./helpers/api"; + +import { getDefaultAppState } from "../appState"; +import { SVG_NS } from "../constants"; +import { getDataURL } from "../data/blob"; import { encodePngMetadata } from "../data/image"; import { serializeAsJSON } from "../data/json"; +import { Excalidraw } from "../index"; import { decodeSvgBase64Payload, encodeSvgBase64Payload, exportToSvg, } from "../scene/export"; + +import { API } from "./helpers/api"; +import { render, waitFor } from "./test-utils"; + import type { FileId } from "../element/types"; -import { getDataURL } from "../data/blob"; -import { getDefaultAppState } from "../appState"; -import { SVG_NS } from "../constants"; const { h } = window; diff --git a/packages/excalidraw/tests/fitToContent.test.tsx b/packages/excalidraw/tests/fitToContent.test.tsx index a4f03910b..bfd16c4e1 100644 --- a/packages/excalidraw/tests/fitToContent.test.tsx +++ b/packages/excalidraw/tests/fitToContent.test.tsx @@ -1,9 +1,10 @@ import React from "react"; -import { act, render } from "./test-utils"; -import { API } from "./helpers/api"; +import { vi } from "vitest"; import { Excalidraw } from "../index"; -import { vi } from "vitest"; + +import { API } from "./helpers/api"; +import { act, render } from "./test-utils"; const { h } = window; diff --git a/packages/excalidraw/tests/fixtures/diagramFixture.ts b/packages/excalidraw/tests/fixtures/diagramFixture.ts index 72b909af8..a4fdc1560 100644 --- a/packages/excalidraw/tests/fixtures/diagramFixture.ts +++ b/packages/excalidraw/tests/fixtures/diagramFixture.ts @@ -1,4 +1,5 @@ import { VERSIONS } from "../../constants"; + import { diamondFixture, ellipseFixture, diff --git a/packages/excalidraw/tests/fixtures/elementFixture.ts b/packages/excalidraw/tests/fixtures/elementFixture.ts index f0470ec86..a7d8c5080 100644 --- a/packages/excalidraw/tests/fixtures/elementFixture.ts +++ b/packages/excalidraw/tests/fixtures/elementFixture.ts @@ -1,5 +1,7 @@ import type { Radians } from "@excalidraw/math"; + import { DEFAULT_FONT_FAMILY } from "../../constants"; + import type { ExcalidrawElement } from "../../element/types"; const elementBase: Omit = { diff --git a/packages/excalidraw/tests/flip.test.tsx b/packages/excalidraw/tests/flip.test.tsx index e3f44b333..9d9f68611 100644 --- a/packages/excalidraw/tests/flip.test.tsx +++ b/packages/excalidraw/tests/flip.test.tsx @@ -1,4 +1,21 @@ +import { pointFrom, type Radians } from "@excalidraw/math"; import React from "react"; +import { vi } from "vitest"; + +import type { LocalPoint } from "@excalidraw/math"; + +import { actionFlipHorizontal, actionFlipVertical } from "../actions"; +import { createPasteEvent } from "../clipboard"; +import { ROUNDNESS } from "../constants"; +import { getElementAbsoluteCoords } from "../element"; +import { newLinearElement } from "../element"; +import { getBoundTextElementPosition } from "../element/textElement"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { arrayToMap, cloneJSON } from "../utils"; + +import { API } from "./helpers/api"; +import { UI, Pointer, Keyboard } from "./helpers/ui"; import { fireEvent, GlobalTestState, @@ -7,10 +24,7 @@ import { unmountComponent, waitFor, } from "./test-utils"; -import { UI, Pointer, Keyboard } from "./helpers/ui"; -import { API } from "./helpers/api"; -import { actionFlipHorizontal, actionFlipVertical } from "../actions"; -import { getElementAbsoluteCoords } from "../element"; + import type { ExcalidrawElement, ExcalidrawImageElement, @@ -18,17 +32,7 @@ import type { ExcalidrawTextElementWithContainer, FileId, } from "../element/types"; -import { newLinearElement } from "../element"; -import { Excalidraw } from "../index"; import type { NormalizedZoomValue } from "../types"; -import { ROUNDNESS } from "../constants"; -import { vi } from "vitest"; -import { KEYS } from "../keys"; -import { getBoundTextElementPosition } from "../element/textElement"; -import { createPasteEvent } from "../clipboard"; -import { arrayToMap, cloneJSON } from "../utils"; -import type { LocalPoint } from "@excalidraw/math"; -import { pointFrom, type Radians } from "@excalidraw/math"; const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/tests/fractionalIndex.test.ts b/packages/excalidraw/tests/fractionalIndex.test.ts index b57af016b..dbd55bd92 100644 --- a/packages/excalidraw/tests/fractionalIndex.test.ts +++ b/packages/excalidraw/tests/fractionalIndex.test.ts @@ -1,15 +1,18 @@ /* eslint-disable no-lone-blocks */ +import { generateKeyBetween } from "fractional-indexing"; + +import { deepCopyElement } from "../element/newElement"; +import { InvalidFractionalIndexError } from "../errors"; import { syncInvalidIndices, syncMovedIndices, validateFractionalIndices, } from "../fractionalIndex"; -import { API } from "./helpers/api"; import { arrayToMap } from "../utils"; -import { InvalidFractionalIndexError } from "../errors"; + +import { API } from "./helpers/api"; + import type { ExcalidrawElement, FractionalIndex } from "../element/types"; -import { deepCopyElement } from "../element/newElement"; -import { generateKeyBetween } from "fractional-indexing"; describe("sync invalid indices with array order", () => { describe("should NOT sync empty array", () => { diff --git a/packages/excalidraw/tests/helpers/api.ts b/packages/excalidraw/tests/helpers/api.ts index 218f37116..2aa9ee999 100644 --- a/packages/excalidraw/tests/helpers/api.ts +++ b/packages/excalidraw/tests/helpers/api.ts @@ -1,3 +1,32 @@ +import fs from "fs"; +import path from "path"; +import util from "util"; + +import { pointFrom, type LocalPoint, type Radians } from "@excalidraw/math"; + +import { getDefaultAppState } from "../../appState"; +import { createTestHook } from "../../components/App"; +import { DEFAULT_VERTICAL_ALIGN, ROUNDNESS } from "../../constants"; +import { getMimeType } from "../../data/blob"; +import { newElement, newTextElement, newLinearElement } from "../../element"; +import { mutateElement } from "../../element/mutateElement"; +import { + newArrowElement, + newEmbeddableElement, + newFrameElement, + newFreeDrawElement, + newIframeElement, + newImageElement, + newMagicFrameElement, +} from "../../element/newElement"; +import { isLinearElementType } from "../../element/typeChecks"; +import { selectGroupsForSelectedElements } from "../../groups"; +import { getSelectedElements } from "../../scene/selection"; +import { assertNever } from "../../utils"; +import { GlobalTestState, createEvent, fireEvent, act } from "../test-utils"; + +import type { Action } from "../../actions/types"; +import type App from "../../components/App"; import type { ExcalidrawElement, ExcalidrawGenericElement, @@ -13,34 +42,8 @@ import type { ExcalidrawArrowElement, FixedSegment, } from "../../element/types"; -import { newElement, newTextElement, newLinearElement } from "../../element"; -import { DEFAULT_VERTICAL_ALIGN, ROUNDNESS } from "../../constants"; -import { getDefaultAppState } from "../../appState"; -import { GlobalTestState, createEvent, fireEvent, act } from "../test-utils"; -import fs from "fs"; -import util from "util"; -import path from "path"; -import { getMimeType } from "../../data/blob"; -import { - newArrowElement, - newEmbeddableElement, - newFrameElement, - newFreeDrawElement, - newIframeElement, - newImageElement, - newMagicFrameElement, -} from "../../element/newElement"; import type { AppState } from "../../types"; -import { getSelectedElements } from "../../scene/selection"; -import { isLinearElementType } from "../../element/typeChecks"; import type { Mutable } from "../../utility-types"; -import { assertNever } from "../../utils"; -import type App from "../../components/App"; -import { createTestHook } from "../../components/App"; -import type { Action } from "../../actions/types"; -import { mutateElement } from "../../element/mutateElement"; -import { pointFrom, type LocalPoint, type Radians } from "@excalidraw/math"; -import { selectGroupsForSelectedElements } from "../../groups"; const readFile = util.promisify(fs.readFile); // so that window.h is available when App.tsx is not imported as well. diff --git a/packages/excalidraw/tests/helpers/mocks.ts b/packages/excalidraw/tests/helpers/mocks.ts index a87523ec1..10e1dee2b 100644 --- a/packages/excalidraw/tests/helpers/mocks.ts +++ b/packages/excalidraw/tests/helpers/mocks.ts @@ -1,7 +1,8 @@ -import { vi } from "vitest"; import * as MermaidToExcalidraw from "@excalidraw/mermaid-to-excalidraw"; -import type { parseMermaidToExcalidraw } from "@excalidraw/mermaid-to-excalidraw"; import React from "react"; +import { vi } from "vitest"; + +import type { parseMermaidToExcalidraw } from "@excalidraw/mermaid-to-excalidraw"; export const mockMermaidToExcalidraw = (opts: { parseMermaidToExcalidraw: typeof parseMermaidToExcalidraw; diff --git a/packages/excalidraw/tests/helpers/ui.ts b/packages/excalidraw/tests/helpers/ui.ts index b9b7023c1..a72e3fa74 100644 --- a/packages/excalidraw/tests/helpers/ui.ts +++ b/packages/excalidraw/tests/helpers/ui.ts @@ -1,3 +1,33 @@ +import { pointFrom, pointRotateRads } from "@excalidraw/math"; + +import type { GlobalPoint, LocalPoint, Radians } from "@excalidraw/math"; + +import { createTestHook } from "../../components/App"; +import { getCommonBounds, getElementPointsCoords } from "../../element/bounds"; +import { cropElement } from "../../element/cropElement"; +import { mutateElement } from "../../element/mutateElement"; +import { + getTransformHandles, + getTransformHandlesFromCoords, + OMIT_SIDES_FOR_FRAME, + OMIT_SIDES_FOR_MULTIPLE_ELEMENTS, + type TransformHandle, + type TransformHandleDirection, +} from "../../element/transformHandles"; +import { + isLinearElement, + isFreeDrawElement, + isTextElement, + isFrameLikeElement, +} from "../../element/typeChecks"; +import { KEYS } from "../../keys"; +import { arrayToMap } from "../../utils"; +import { getTextEditor } from "../queries/dom"; +import { act, fireEvent, GlobalTestState, screen } from "../test-utils"; + +import { API } from "./api"; + +import type { TransformHandleType } from "../../element/transformHandles"; import type { ExcalidrawElement, ExcalidrawLinearElement, @@ -10,32 +40,6 @@ import type { ExcalidrawTextElementWithContainer, ExcalidrawImageElement, } from "../../element/types"; -import type { TransformHandleType } from "../../element/transformHandles"; -import { - getTransformHandles, - getTransformHandlesFromCoords, - OMIT_SIDES_FOR_FRAME, - OMIT_SIDES_FOR_MULTIPLE_ELEMENTS, - type TransformHandle, - type TransformHandleDirection, -} from "../../element/transformHandles"; -import { KEYS } from "../../keys"; -import { act, fireEvent, GlobalTestState, screen } from "../test-utils"; -import { mutateElement } from "../../element/mutateElement"; -import { API } from "./api"; -import { - isLinearElement, - isFreeDrawElement, - isTextElement, - isFrameLikeElement, -} from "../../element/typeChecks"; -import { getCommonBounds, getElementPointsCoords } from "../../element/bounds"; -import { getTextEditor } from "../queries/dom"; -import { arrayToMap } from "../../utils"; -import { createTestHook } from "../../components/App"; -import type { GlobalPoint, LocalPoint, Radians } from "@excalidraw/math"; -import { pointFrom, pointRotateRads } from "@excalidraw/math"; -import { cropElement } from "../../element/cropElement"; import type { ToolType } from "../../types"; // so that window.h is available when App.tsx is not imported as well. diff --git a/packages/excalidraw/tests/history.test.tsx b/packages/excalidraw/tests/history.test.tsx index ffddec49f..6e7066b90 100644 --- a/packages/excalidraw/tests/history.test.tsx +++ b/packages/excalidraw/tests/history.test.tsx @@ -1,6 +1,43 @@ import React from "react"; +import { + queryByText, + fireEvent, + queryByTestId, + waitFor, +} from "@testing-library/react"; +import { vi } from "vitest"; +import { pointFrom } from "@excalidraw/math"; + +import type { LocalPoint, Radians } from "@excalidraw/math"; + import "../global.d.ts"; +import "../../utils/test-utils"; + +import { + actionSendBackward, + actionBringForward, + actionSendToBack, +} from "../actions"; +import { createUndoAction, createRedoAction } from "../actions/actionHistory"; +import { actionToggleViewMode } from "../actions/actionToggleViewMode"; +import { getDefaultAppState } from "../appState"; +import { HistoryEntry } from "../history"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; import * as StaticScene from "../renderer/staticScene"; +import { EXPORT_DATA_TYPES, MIME_TYPES, ORIG_ID } from "../constants"; +import { Snapshot, CaptureUpdateAction } from "../store"; +import { arrayToMap } from "../utils"; +import { + COLOR_PALETTE, + DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX, + DEFAULT_ELEMENT_STROKE_COLOR_INDEX, +} from "../colors"; +import { newElementWith } from "../element/mutateElement"; +import { AppStateChange, ElementsChange } from "../change"; + +import { API } from "./helpers/api"; +import { Keyboard, Pointer, UI } from "./helpers/ui"; import { GlobalTestState, act, @@ -9,24 +46,7 @@ import { togglePopover, getCloneByOrigId, } from "./test-utils"; -import "../../utils/test-utils"; -import { Excalidraw } from "../index"; -import { Keyboard, Pointer, UI } from "./helpers/ui"; -import { API } from "./helpers/api"; -import { getDefaultAppState } from "../appState"; -import { fireEvent, queryByTestId, waitFor } from "@testing-library/react"; -import { createUndoAction, createRedoAction } from "../actions/actionHistory"; -import { actionToggleViewMode } from "../actions/actionToggleViewMode"; -import { EXPORT_DATA_TYPES, MIME_TYPES, ORIG_ID } from "../constants"; -import type { AppState } from "../types"; -import { arrayToMap } from "../utils"; -import { - COLOR_PALETTE, - DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX, - DEFAULT_ELEMENT_STROKE_COLOR_INDEX, -} from "../colors"; -import { KEYS } from "../keys"; -import { newElementWith } from "../element/mutateElement"; + import type { ExcalidrawElbowArrowElement, ExcalidrawFrameElement, @@ -37,18 +57,7 @@ import type { FractionalIndex, SceneElementsMap, } from "../element/types"; -import { - actionSendBackward, - actionBringForward, - actionSendToBack, -} from "../actions"; -import { vi } from "vitest"; -import { queryByText } from "@testing-library/react"; -import { HistoryEntry } from "../history"; -import { AppStateChange, ElementsChange } from "../change"; -import { Snapshot, CaptureUpdateAction } from "../store"; -import type { LocalPoint, Radians } from "@excalidraw/math"; -import { pointFrom } from "@excalidraw/math"; +import type { AppState } from "../types"; const { h } = window; diff --git a/packages/excalidraw/tests/library.test.tsx b/packages/excalidraw/tests/library.test.tsx index 7b48407b7..b084d835b 100644 --- a/packages/excalidraw/tests/library.test.tsx +++ b/packages/excalidraw/tests/library.test.tsx @@ -1,18 +1,20 @@ +import { act, queryByTestId } from "@testing-library/react"; import React from "react"; import { vi } from "vitest"; -import { fireEvent, getCloneByOrigId, render, waitFor } from "./test-utils"; -import { act, queryByTestId } from "@testing-library/react"; -import { Excalidraw } from "../index"; -import { API } from "./helpers/api"; import { MIME_TYPES, ORIG_ID } from "../constants"; -import type { LibraryItem, LibraryItems } from "../types"; -import { UI } from "./helpers/ui"; +import { parseLibraryJSON } from "../data/blob"; import { serializeLibraryAsJSON } from "../data/json"; import { distributeLibraryItemsOnSquareGrid } from "../data/library"; -import type { ExcalidrawGenericElement } from "../element/types"; import { getCommonBoundingBox } from "../element/bounds"; -import { parseLibraryJSON } from "../data/blob"; +import { Excalidraw } from "../index"; + +import { API } from "./helpers/api"; +import { UI } from "./helpers/ui"; +import { fireEvent, getCloneByOrigId, render, waitFor } from "./test-utils"; + +import type { ExcalidrawGenericElement } from "../element/types"; +import type { LibraryItem, LibraryItems } from "../types"; const { h } = window; diff --git a/packages/excalidraw/tests/linearElementEditor.test.tsx b/packages/excalidraw/tests/linearElementEditor.test.tsx index 98d6058c2..162dbb3f0 100644 --- a/packages/excalidraw/tests/linearElementEditor.test.tsx +++ b/packages/excalidraw/tests/linearElementEditor.test.tsx @@ -1,14 +1,25 @@ +import { pointCenter, pointFrom } from "@excalidraw/math"; +import { act, queryByTestId, queryByText } from "@testing-library/react"; import React from "react"; -import type { - ExcalidrawElement, - ExcalidrawLinearElement, - ExcalidrawTextElementWithContainer, - FontString, -} from "../element/types"; +import { vi } from "vitest"; + +import type { GlobalPoint } from "@excalidraw/math"; + +import { ROUNDNESS, VERTICAL_ALIGN } from "../constants"; +import { LinearElementEditor } from "../element/linearElementEditor"; +import { + getBoundTextElementPosition, + getBoundTextMaxWidth, +} from "../element/textElement"; +import * as textElementUtils from "../element/textElement"; +import { wrapText } from "../element/textWrapping"; import { Excalidraw, mutateElement } from "../index"; +import { KEYS } from "../keys"; import { reseed } from "../random"; -import * as StaticScene from "../renderer/staticScene"; import * as InteractiveCanvas from "../renderer/interactiveScene"; +import * as StaticScene from "../renderer/staticScene"; +import { API } from "../tests/helpers/api"; +import { arrayToMap } from "../utils"; import { Keyboard, Pointer, UI } from "./helpers/ui"; import { @@ -18,21 +29,13 @@ import { GlobalTestState, unmountComponent, } from "./test-utils"; -import { API } from "../tests/helpers/api"; -import { KEYS } from "../keys"; -import { LinearElementEditor } from "../element/linearElementEditor"; -import { act, queryByTestId, queryByText } from "@testing-library/react"; -import { - getBoundTextElementPosition, - getBoundTextMaxWidth, -} from "../element/textElement"; -import * as textElementUtils from "../element/textElement"; -import { ROUNDNESS, VERTICAL_ALIGN } from "../constants"; -import { vi } from "vitest"; -import { arrayToMap } from "../utils"; -import type { GlobalPoint } from "@excalidraw/math"; -import { pointCenter, pointFrom } from "@excalidraw/math"; -import { wrapText } from "../element/textWrapping"; + +import type { + ExcalidrawElement, + ExcalidrawLinearElement, + ExcalidrawTextElementWithContainer, + FontString, +} from "../element/types"; const renderInteractiveScene = vi.spyOn( InteractiveCanvas, diff --git a/packages/excalidraw/tests/move.test.tsx b/packages/excalidraw/tests/move.test.tsx index 528f9554d..855496f44 100644 --- a/packages/excalidraw/tests/move.test.tsx +++ b/packages/excalidraw/tests/move.test.tsx @@ -1,19 +1,22 @@ import React from "react"; +import { vi } from "vitest"; + import "../../utils/test-utils"; -import { render, fireEvent, act, unmountComponent } from "./test-utils"; -import { Excalidraw } from "../index"; -import * as StaticScene from "../renderer/staticScene"; -import * as InteractiveCanvas from "../renderer/interactiveScene"; -import { reseed } from "../random"; import { bindOrUnbindLinearElement } from "../element/binding"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { reseed } from "../random"; +import * as InteractiveCanvas from "../renderer/interactiveScene"; +import * as StaticScene from "../renderer/staticScene"; + +import { UI, Pointer, Keyboard } from "./helpers/ui"; +import { render, fireEvent, act, unmountComponent } from "./test-utils"; + import type { ExcalidrawLinearElement, NonDeleted, ExcalidrawRectangleElement, } from "../element/types"; -import { UI, Pointer, Keyboard } from "./helpers/ui"; -import { KEYS } from "../keys"; -import { vi } from "vitest"; import type Scene from "../scene/Scene"; unmountComponent(); diff --git a/packages/excalidraw/tests/multiPointCreate.test.tsx b/packages/excalidraw/tests/multiPointCreate.test.tsx index df94eb9da..5cbce4966 100644 --- a/packages/excalidraw/tests/multiPointCreate.test.tsx +++ b/packages/excalidraw/tests/multiPointCreate.test.tsx @@ -1,4 +1,12 @@ import React from "react"; +import { vi } from "vitest"; + +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { reseed } from "../random"; +import * as InteractiveCanvas from "../renderer/interactiveScene"; +import * as StaticScene from "../renderer/staticScene"; + import { render, fireEvent, @@ -6,13 +14,8 @@ import { restoreOriginalGetBoundingClientRect, unmountComponent, } from "./test-utils"; -import { Excalidraw } from "../index"; -import * as StaticScene from "../renderer/staticScene"; -import * as InteractiveCanvas from "../renderer/interactiveScene"; -import { KEYS } from "../keys"; + import type { ExcalidrawLinearElement } from "../element/types"; -import { reseed } from "../random"; -import { vi } from "vitest"; unmountComponent(); diff --git a/packages/excalidraw/tests/packages/events.test.tsx b/packages/excalidraw/tests/packages/events.test.tsx index ad8b3c6d9..3e79239c8 100644 --- a/packages/excalidraw/tests/packages/events.test.tsx +++ b/packages/excalidraw/tests/packages/events.test.tsx @@ -1,11 +1,13 @@ import React from "react"; import { vi } from "vitest"; + import { Excalidraw, CaptureUpdateAction } from "../../index"; -import type { ExcalidrawImperativeAPI } from "../../types"; import { resolvablePromise } from "../../utils"; -import { render } from "../test-utils"; -import { Pointer } from "../helpers/ui"; import { API } from "../helpers/api"; +import { Pointer } from "../helpers/ui"; +import { render } from "../test-utils"; + +import type { ExcalidrawImperativeAPI } from "../../types"; describe("event callbacks", () => { const h = window.h; diff --git a/packages/excalidraw/tests/queries/toolQueries.ts b/packages/excalidraw/tests/queries/toolQueries.ts index df0afa117..ed168735d 100644 --- a/packages/excalidraw/tests/queries/toolQueries.ts +++ b/packages/excalidraw/tests/queries/toolQueries.ts @@ -1,7 +1,9 @@ import { queries, buildQueries } from "@testing-library/react"; -import type { ToolType } from "../../types"; + import { TOOL_TYPE } from "../../constants"; +import type { ToolType } from "../../types"; + const _getAllByToolName = (container: HTMLElement, tool: ToolType | "lock") => { const toolTitle = tool === "lock" ? "lock" : TOOL_TYPE[tool]; return queries.getAllByTestId(container, `toolbar-${toolTitle}`); diff --git a/packages/excalidraw/tests/regressionTests.test.tsx b/packages/excalidraw/tests/regressionTests.test.tsx index a3e45bca6..8407f0766 100644 --- a/packages/excalidraw/tests/regressionTests.test.tsx +++ b/packages/excalidraw/tests/regressionTests.test.tsx @@ -1,10 +1,13 @@ import React from "react"; -import type { ExcalidrawElement } from "../element/types"; -import { CODES, KEYS } from "../keys"; +import { vi } from "vitest"; + +import { FONT_FAMILY } from "../constants"; import { Excalidraw } from "../index"; +import { CODES, KEYS } from "../keys"; import { reseed } from "../random"; import * as StaticScene from "../renderer/staticScene"; import { setDateTimeForTests } from "../utils"; + import { API } from "./helpers/api"; import { Keyboard, Pointer, UI } from "./helpers/ui"; import { @@ -15,8 +18,8 @@ import { togglePopover, unmountComponent, } from "./test-utils"; -import { FONT_FAMILY } from "../constants"; -import { vi } from "vitest"; + +import type { ExcalidrawElement } from "../element/types"; const { h } = window; diff --git a/packages/excalidraw/tests/resize.test.tsx b/packages/excalidraw/tests/resize.test.tsx index a12d31048..055b097b3 100644 --- a/packages/excalidraw/tests/resize.test.tsx +++ b/packages/excalidraw/tests/resize.test.tsx @@ -1,24 +1,28 @@ +import { pointFrom } from "@excalidraw/math"; import React from "react"; -import { render, unmountComponent } from "./test-utils"; + +import type { LocalPoint } from "@excalidraw/math"; + +import { getElementPointsCoords } from "../element/bounds"; +import { LinearElementEditor } from "../element/linearElementEditor"; +import { resizeSingleElement } from "../element/resizeElements"; +import { isLinearElement } from "../element/typeChecks"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { getSizeFromPoints } from "../points"; import { reseed } from "../random"; +import { arrayToMap } from "../utils"; + +import { API } from "./helpers/api"; import { UI, Keyboard, Pointer } from "./helpers/ui"; +import { render, unmountComponent } from "./test-utils"; + +import type { Bounds } from "../element/bounds"; import type { ExcalidrawElbowArrowElement, ExcalidrawFreeDrawElement, ExcalidrawLinearElement, } from "../element/types"; -import type { Bounds } from "../element/bounds"; -import { getElementPointsCoords } from "../element/bounds"; -import { Excalidraw } from "../index"; -import { API } from "./helpers/api"; -import { KEYS } from "../keys"; -import { isLinearElement } from "../element/typeChecks"; -import { LinearElementEditor } from "../element/linearElementEditor"; -import { arrayToMap } from "../utils"; -import type { LocalPoint } from "@excalidraw/math"; -import { pointFrom } from "@excalidraw/math"; -import { resizeSingleElement } from "../element/resizeElements"; -import { getSizeFromPoints } from "../points"; unmountComponent(); @@ -533,9 +537,8 @@ describe("arrow element", () => { expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.75); UI.resize([rectangle, arrow], "nw", [300, 350]); - - expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(-0.13); - expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.11); + expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(0); + expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.25); }); }); diff --git a/packages/excalidraw/tests/rotate.test.tsx b/packages/excalidraw/tests/rotate.test.tsx index 367313ea9..2c678f45b 100644 --- a/packages/excalidraw/tests/rotate.test.tsx +++ b/packages/excalidraw/tests/rotate.test.tsx @@ -1,10 +1,12 @@ import React from "react"; -import { render, unmountComponent } from "./test-utils"; -import { reseed } from "../random"; -import { UI } from "./helpers/ui"; -import { Excalidraw } from "../index"; import { expect } from "vitest"; +import { Excalidraw } from "../index"; +import { reseed } from "../random"; + +import { UI } from "./helpers/ui"; +import { render, unmountComponent } from "./test-utils"; + unmountComponent(); beforeEach(() => { diff --git a/packages/excalidraw/tests/scene/export.test.ts b/packages/excalidraw/tests/scene/export.test.ts index 6fd8a8b85..43c37eb28 100644 --- a/packages/excalidraw/tests/scene/export.test.ts +++ b/packages/excalidraw/tests/scene/export.test.ts @@ -1,8 +1,7 @@ -import type { - ExcalidrawTextElement, - FractionalIndex, - NonDeletedExcalidrawElement, -} from "../../element/types"; +import { exportToCanvas, exportToSvg } from "@excalidraw/utils"; + +import { FONT_FAMILY, FRAME_STYLE } from "../../constants"; +import { prepareElementsForExport } from "../../data"; import * as exportUtils from "../../scene/export"; import { diamondFixture, @@ -11,9 +10,12 @@ import { textFixture, } from "../fixtures/elementFixture"; import { API } from "../helpers/api"; -import { exportToCanvas, exportToSvg } from "@excalidraw/utils"; -import { FONT_FAMILY, FRAME_STYLE } from "../../constants"; -import { prepareElementsForExport } from "../../data"; + +import type { + ExcalidrawTextElement, + FractionalIndex, + NonDeletedExcalidrawElement, +} from "../../element/types"; describe("exportToSvg", () => { const ELEMENT_HEIGHT = 100; diff --git a/packages/excalidraw/tests/scroll.test.tsx b/packages/excalidraw/tests/scroll.test.tsx index 1a3f80c14..2ccc4546f 100644 --- a/packages/excalidraw/tests/scroll.test.tsx +++ b/packages/excalidraw/tests/scroll.test.tsx @@ -1,14 +1,16 @@ import React from "react"; + +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; + +import { API } from "./helpers/api"; +import { Keyboard } from "./helpers/ui"; import { mockBoundingClientRect, render, restoreOriginalGetBoundingClientRect, waitFor, } from "./test-utils"; -import { Excalidraw } from "../index"; -import { API } from "./helpers/api"; -import { Keyboard } from "./helpers/ui"; -import { KEYS } from "../keys"; const { h } = window; diff --git a/packages/excalidraw/tests/search.test.tsx b/packages/excalidraw/tests/search.test.tsx index 68ad65826..d3622d4b1 100644 --- a/packages/excalidraw/tests/search.test.tsx +++ b/packages/excalidraw/tests/search.test.tsx @@ -1,11 +1,14 @@ import React from "react"; -import { act, render, waitFor } from "./test-utils"; -import { Excalidraw } from "../index"; + import { CANVAS_SEARCH_TAB, CLASSES, DEFAULT_SIDEBAR } from "../constants"; -import { Keyboard } from "./helpers/ui"; +import { Excalidraw } from "../index"; import { KEYS } from "../keys"; -import { updateTextEditor } from "./queries/dom"; + import { API } from "./helpers/api"; +import { Keyboard } from "./helpers/ui"; +import { updateTextEditor } from "./queries/dom"; +import { act, render, waitFor } from "./test-utils"; + import type { ExcalidrawTextElement } from "../element/types"; const { h } = window; diff --git a/packages/excalidraw/tests/selection.test.tsx b/packages/excalidraw/tests/selection.test.tsx index 0b1f6e50d..d93d3eff5 100644 --- a/packages/excalidraw/tests/selection.test.tsx +++ b/packages/excalidraw/tests/selection.test.tsx @@ -1,4 +1,15 @@ import React from "react"; +import { vi } from "vitest"; + +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { reseed } from "../random"; +import * as InteractiveCanvas from "../renderer/interactiveScene"; +import * as StaticScene from "../renderer/staticScene"; +import { SHAPES } from "../shapes"; + +import { API } from "./helpers/api"; +import { Keyboard, Pointer, UI } from "./helpers/ui"; import { render, fireEvent, @@ -7,15 +18,6 @@ import { assertSelectedElements, unmountComponent, } from "./test-utils"; -import { Excalidraw } from "../index"; -import * as StaticScene from "../renderer/staticScene"; -import * as InteractiveCanvas from "../renderer/interactiveScene"; -import { KEYS } from "../keys"; -import { reseed } from "../random"; -import { API } from "./helpers/api"; -import { Keyboard, Pointer, UI } from "./helpers/ui"; -import { SHAPES } from "../shapes"; -import { vi } from "vitest"; unmountComponent(); diff --git a/packages/excalidraw/tests/shortcuts.test.tsx b/packages/excalidraw/tests/shortcuts.test.tsx index e02ed0193..ee2234ecc 100644 --- a/packages/excalidraw/tests/shortcuts.test.tsx +++ b/packages/excalidraw/tests/shortcuts.test.tsx @@ -1,6 +1,8 @@ import React from "react"; -import { KEYS } from "../keys"; + import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; + import { API } from "./helpers/api"; import { Keyboard } from "./helpers/ui"; import { fireEvent, render, waitFor } from "./test-utils"; diff --git a/packages/excalidraw/tests/test-utils.ts b/packages/excalidraw/tests/test-utils.ts index 84936f520..73b340982 100644 --- a/packages/excalidraw/tests/test-utils.ts +++ b/packages/excalidraw/tests/test-utils.ts @@ -1,6 +1,4 @@ import "pepjs"; - -import type { RenderResult, RenderOptions } from "@testing-library/react"; import { act } from "@testing-library/react"; import { render, @@ -9,16 +7,20 @@ import { fireEvent, cleanup, } from "@testing-library/react"; - -import * as toolQueries from "./queries/toolQueries"; -import type { ImportedDataState } from "../data/types"; -import { STORAGE_KEYS } from "../../../excalidraw-app/app_constants"; -import { getSelectedElements } from "../scene/selection"; -import type { ExcalidrawElement } from "../element/types"; -import { UI } from "./helpers/ui"; import ansi from "ansicolor"; + +import { STORAGE_KEYS } from "../../../excalidraw-app/app_constants"; import { ORIG_ID } from "../constants"; +import { getSelectedElements } from "../scene/selection"; import { arrayToMap } from "../utils"; + +import { UI } from "./helpers/ui"; +import * as toolQueries from "./queries/toolQueries"; + +import type { RenderResult, RenderOptions } from "@testing-library/react"; + +import type { ImportedDataState } from "../data/types"; +import type { ExcalidrawElement } from "../element/types"; import type { AllPossibleKeys } from "../utility-types"; export { cleanup as unmountComponent }; diff --git a/packages/excalidraw/tests/tool.test.tsx b/packages/excalidraw/tests/tool.test.tsx index 662c61baa..f70d1ccdd 100644 --- a/packages/excalidraw/tests/tool.test.tsx +++ b/packages/excalidraw/tests/tool.test.tsx @@ -1,9 +1,12 @@ import React from "react"; + import { Excalidraw } from "../index"; -import type { ExcalidrawImperativeAPI } from "../types"; import { resolvablePromise } from "../utils"; -import { act, render } from "./test-utils"; + import { Pointer } from "./helpers/ui"; +import { act, render } from "./test-utils"; + +import type { ExcalidrawImperativeAPI } from "../types"; describe("setActiveTool()", () => { const h = window.h; diff --git a/packages/excalidraw/tests/viewMode.test.tsx b/packages/excalidraw/tests/viewMode.test.tsx index 66eca8c7f..c190ee0e3 100644 --- a/packages/excalidraw/tests/viewMode.test.tsx +++ b/packages/excalidraw/tests/viewMode.test.tsx @@ -1,10 +1,12 @@ import React from "react"; -import { render, GlobalTestState } from "./test-utils"; + +import { CURSOR_TYPE } from "../constants"; import { Excalidraw } from "../index"; import { KEYS } from "../keys"; -import { Keyboard, Pointer, UI } from "./helpers/ui"; -import { CURSOR_TYPE } from "../constants"; + import { API } from "./helpers/api"; +import { Keyboard, Pointer, UI } from "./helpers/ui"; +import { render, GlobalTestState } from "./test-utils"; const mouse = new Pointer("mouse"); const touch = new Pointer("touch"); diff --git a/packages/excalidraw/tests/zindex.test.tsx b/packages/excalidraw/tests/zindex.test.tsx index f15d55931..c8e166aff 100644 --- a/packages/excalidraw/tests/zindex.test.tsx +++ b/packages/excalidraw/tests/zindex.test.tsx @@ -1,7 +1,5 @@ import React from "react"; -import { act, getCloneByOrigId, render, unmountComponent } from "./test-utils"; -import { Excalidraw } from "../index"; -import { reseed } from "../random"; + import { actionSendBackward, actionBringForward, @@ -9,14 +7,19 @@ import { actionSendToBack, actionDuplicateSelection, } from "../actions"; -import type { AppState } from "../types"; -import { API } from "./helpers/api"; import { selectGroupsForSelectedElements } from "../groups"; +import { Excalidraw } from "../index"; +import { reseed } from "../random"; + +import { API } from "./helpers/api"; +import { act, getCloneByOrigId, render, unmountComponent } from "./test-utils"; + import type { ExcalidrawElement, ExcalidrawFrameElement, ExcalidrawSelectionElement, } from "../element/types"; +import type { AppState } from "../types"; unmountComponent(); diff --git a/packages/excalidraw/types.ts b/packages/excalidraw/types.ts index 13523a269..b9a0649cb 100644 --- a/packages/excalidraw/types.ts +++ b/packages/excalidraw/types.ts @@ -1,5 +1,19 @@ -import type { JSX } from "react"; -import type React from "react"; +import type { Action } from "./actions/types"; +import type { Spreadsheet } from "./charts"; +import type { ClipboardData } from "./clipboard"; +import type App from "./components/App"; +import type Library from "./data/library"; +import type { FileSystemHandle } from "./data/filesystem"; +import type { IMAGE_MIME_TYPES, MIME_TYPES } from "./constants"; +import type { ContextMenuItems } from "./components/ContextMenu"; +import type { SnapLine } from "./snapping"; +import type { Merge, MaybePromise, ValueOf, MakeBrand } from "./utility-types"; +import type { CaptureUpdateActionType } from "./store"; +import type { UserIdleState } from "./constants"; +import type { ImportedDataState } from "./data/types"; +import type { SuggestedBinding } from "./element/binding"; +import type { LinearElementEditor } from "./element/linearElementEditor"; +import type { MaybeTransformHandleType } from "./element/transformHandles"; import type { PointerType, ExcalidrawLinearElement, @@ -24,25 +38,11 @@ import type { OrderedExcalidrawElement, ExcalidrawNonSelectionElement, } from "./element/types"; -import type { Action } from "./actions/types"; -import type { LinearElementEditor } from "./element/linearElementEditor"; -import type { SuggestedBinding } from "./element/binding"; -import type { ImportedDataState } from "./data/types"; -import type App from "./components/App"; -import type { throttleRAF } from "./utils"; -import type { Spreadsheet } from "./charts"; import type { Language } from "./i18n"; -import type { ClipboardData } from "./clipboard"; import type { isOverScrollBars } from "./scene/scrollbars"; -import type { MaybeTransformHandleType } from "./element/transformHandles"; -import type Library from "./data/library"; -import type { FileSystemHandle } from "./data/filesystem"; -import type { IMAGE_MIME_TYPES, MIME_TYPES } from "./constants"; -import type { ContextMenuItems } from "./components/ContextMenu"; -import type { SnapLine } from "./snapping"; -import type { Merge, MaybePromise, ValueOf, MakeBrand } from "./utility-types"; -import type { CaptureUpdateActionType } from "./store"; -import type { UserIdleState } from "./constants"; +import type { throttleRAF } from "./utils"; +import type React from "react"; +import type { JSX } from "react"; export type SocketId = string & { _brand: "SocketId" }; diff --git a/packages/excalidraw/utils.ts b/packages/excalidraw/utils.ts index e3e18eb93..84f6637f1 100644 --- a/packages/excalidraw/utils.ts +++ b/packages/excalidraw/utils.ts @@ -1,7 +1,7 @@ -import Pool from "es6-promise-pool"; import { average } from "@excalidraw/math"; +import Pool from "es6-promise-pool"; + import { COLOR_PALETTE } from "./colors"; -import type { EVENT } from "./constants"; import { DEFAULT_VERSION, FONT_FAMILY, @@ -9,6 +9,8 @@ import { isDarwin, WINDOWS_EMOJI_FALLBACK_FONT, } from "./constants"; + +import type { EVENT } from "./constants"; import type { ExcalidrawBindableElement, FontFamilyValues, diff --git a/packages/excalidraw/visualdebug.ts b/packages/excalidraw/visualdebug.ts index 862f2cf20..6b7014864 100644 --- a/packages/excalidraw/visualdebug.ts +++ b/packages/excalidraw/visualdebug.ts @@ -1,4 +1,3 @@ -import type { Curve } from "@excalidraw/math"; import { isLineSegment, lineSegment, @@ -6,10 +5,14 @@ import { type GlobalPoint, type LocalPoint, } from "@excalidraw/math"; + +import type { Curve } from "@excalidraw/math"; import type { LineSegment } from "@excalidraw/utils"; -import type { Bounds } from "./element/bounds"; + import { isBounds } from "./element/typeChecks"; +import type { Bounds } from "./element/bounds"; + // The global data holder to collect the debug operations declare global { interface Window { diff --git a/packages/excalidraw/vite-env.d.ts b/packages/excalidraw/vite-env.d.ts index 628275181..4292e3b6a 100644 --- a/packages/excalidraw/vite-env.d.ts +++ b/packages/excalidraw/vite-env.d.ts @@ -43,9 +43,8 @@ interface ImportMetaEnv { VITE_APP_ENABLE_ESLINT: string; VITE_APP_ENABLE_TRACKING: string; - VITE_PKG_NAME: string; - VITE_PKG_VERSION: string; - VITE_IS_EXCALIDRAW_NPM_PACKAGE: string; + PKG_NAME: string; + PKG_VERSION: string; VITE_APP_PLUS_LP: string; VITE_APP_PLUS_APP: string; diff --git a/packages/excalidraw/zindex.ts b/packages/excalidraw/zindex.ts index 1118ed533..8ffcec5d1 100644 --- a/packages/excalidraw/zindex.ts +++ b/packages/excalidraw/zindex.ts @@ -1,15 +1,16 @@ import { isFrameLikeElement } from "./element/typeChecks"; -import type { - ExcalidrawElement, - ExcalidrawFrameLikeElement, -} from "./element/types"; import { syncMovedIndices } from "./fractionalIndex"; import { getElementsInGroup } from "./groups"; import { getSelectedElements } from "./scene"; import Scene from "./scene/Scene"; -import type { AppState } from "./types"; import { arrayToMap, findIndex, findLastIndex } from "./utils"; +import type { + ExcalidrawElement, + ExcalidrawFrameLikeElement, +} from "./element/types"; +import type { AppState } from "./types"; + const isOfTargetFrame = (element: ExcalidrawElement, frameId: string) => { return element.frameId === frameId || element.id === frameId; }; diff --git a/packages/math/angle.ts b/packages/math/angle.ts index 8d473cf55..353dc5dad 100644 --- a/packages/math/angle.ts +++ b/packages/math/angle.ts @@ -1,3 +1,5 @@ +import { PRECISION } from "./utils"; + import type { Degrees, GlobalPoint, @@ -5,7 +7,6 @@ import type { PolarCoords, Radians, } from "./types"; -import { PRECISION } from "./utils"; // TODO: Simplify with modulo and fix for angles beyond 4*Math.PI and - 4*Math.PI export const normalizeRadians = (angle: Radians): Radians => { diff --git a/packages/math/curve.test.ts b/packages/math/curve.test.ts index 94670d7ab..8d60a7346 100644 --- a/packages/math/curve.test.ts +++ b/packages/math/curve.test.ts @@ -1,4 +1,5 @@ import "../utils/test-utils"; + import { curve, curveClosestPoint, diff --git a/packages/math/curve.ts b/packages/math/curve.ts index 9b275ceec..cd466bbc7 100644 --- a/packages/math/curve.ts +++ b/packages/math/curve.ts @@ -1,7 +1,8 @@ -import type { Bounds } from "../excalidraw/element/bounds"; import { isPoint, pointDistance, pointFrom } from "./point"; import { rectangle, rectangleIntersectLineSegment } from "./rectangle"; + import type { Curve, GlobalPoint, LineSegment, LocalPoint } from "./types"; +import type { Bounds } from "../excalidraw/element/bounds"; /** * diff --git a/packages/math/ellipse.test.ts b/packages/math/ellipse.test.ts index 507cc5a1a..bcaab2a5d 100644 --- a/packages/math/ellipse.test.ts +++ b/packages/math/ellipse.test.ts @@ -8,6 +8,7 @@ import { import { line } from "./line"; import { pointFrom } from "./point"; import { lineSegment } from "./segment"; + import type { Ellipse, GlobalPoint } from "./types"; describe("point and ellipse", () => { diff --git a/packages/math/ellipse.ts b/packages/math/ellipse.ts index c32def0eb..741a77df3 100644 --- a/packages/math/ellipse.ts +++ b/packages/math/ellipse.ts @@ -4,13 +4,6 @@ import { pointFromVector, pointsEqual, } from "./point"; -import type { - Ellipse, - GlobalPoint, - Line, - LineSegment, - LocalPoint, -} from "./types"; import { PRECISION } from "./utils"; import { vector, @@ -20,6 +13,14 @@ import { vectorScale, } from "./vector"; +import type { + Ellipse, + GlobalPoint, + Line, + LineSegment, + LocalPoint, +} from "./types"; + /** * Construct an Ellipse object from the parameters * diff --git a/packages/math/line.ts b/packages/math/line.ts index bcb4f6d90..889fa08ce 100644 --- a/packages/math/line.ts +++ b/packages/math/line.ts @@ -1,4 +1,5 @@ import { pointFrom } from "./point"; + import type { GlobalPoint, Line, LocalPoint } from "./types"; /** diff --git a/packages/math/point.test.ts b/packages/math/point.test.ts index 89cc4f8f3..0ed59ee9a 100644 --- a/packages/math/point.test.ts +++ b/packages/math/point.test.ts @@ -1,4 +1,5 @@ import { pointFrom, pointRotateRads } from "./point"; + import type { Radians } from "./types"; describe("rotate", () => { diff --git a/packages/math/point.ts b/packages/math/point.ts index 92df18773..f6234c8ea 100644 --- a/packages/math/point.ts +++ b/packages/math/point.ts @@ -1,4 +1,7 @@ import { degreesToRadians } from "./angle"; +import { PRECISION } from "./utils"; +import { vectorFromPoint, vectorScale } from "./vector"; + import type { LocalPoint, GlobalPoint, @@ -6,8 +9,6 @@ import type { Degrees, Vector, } from "./types"; -import { PRECISION } from "./utils"; -import { vectorFromPoint, vectorScale } from "./vector"; /** * Create a properly typed Point instance from the X and Y coordinates. diff --git a/packages/math/polygon.ts b/packages/math/polygon.ts index 783bc4cf3..762c82dbf 100644 --- a/packages/math/polygon.ts +++ b/packages/math/polygon.ts @@ -1,8 +1,9 @@ import { pointsEqual } from "./point"; import { lineSegment, pointOnLineSegment } from "./segment"; -import type { GlobalPoint, LocalPoint, Polygon } from "./types"; import { PRECISION } from "./utils"; +import type { GlobalPoint, LocalPoint, Polygon } from "./types"; + export function polygon( ...points: Point[] ) { diff --git a/packages/math/range.ts b/packages/math/range.ts index d90530cba..dee3d7edf 100644 --- a/packages/math/range.ts +++ b/packages/math/range.ts @@ -1,4 +1,5 @@ import { toBrandedType } from "@excalidraw/excalidraw/utils"; + import type { InclusiveRange } from "./types"; /** diff --git a/packages/math/rectangle.ts b/packages/math/rectangle.ts index 7dde15ded..394b5c2f8 100644 --- a/packages/math/rectangle.ts +++ b/packages/math/rectangle.ts @@ -1,5 +1,6 @@ import { pointFrom } from "./point"; import { lineSegment, lineSegmentIntersectionPoints } from "./segment"; + import type { GlobalPoint, LineSegment, LocalPoint, Rectangle } from "./types"; export function rectangle

( diff --git a/packages/math/segment.ts b/packages/math/segment.ts index 60943aacb..e38978b7e 100644 --- a/packages/math/segment.ts +++ b/packages/math/segment.ts @@ -5,7 +5,6 @@ import { pointFromVector, pointRotateRads, } from "./point"; -import type { GlobalPoint, LineSegment, LocalPoint, Radians } from "./types"; import { PRECISION } from "./utils"; import { vectorAdd, @@ -15,6 +14,8 @@ import { vectorSubtract, } from "./vector"; +import type { GlobalPoint, LineSegment, LocalPoint, Radians } from "./types"; + /** * Create a line segment from two points. * diff --git a/packages/utils/bbox.ts b/packages/utils/bbox.ts index 19a1a5430..61c75a668 100644 --- a/packages/utils/bbox.ts +++ b/packages/utils/bbox.ts @@ -4,6 +4,7 @@ import { type GlobalPoint, type LocalPoint, } from "@excalidraw/math"; + import type { Bounds } from "@excalidraw/excalidraw/element/bounds"; export type LineSegment

= [P, P]; diff --git a/packages/utils/collision.test.ts b/packages/utils/collision.test.ts index 744bea367..24f96e985 100644 --- a/packages/utils/collision.test.ts +++ b/packages/utils/collision.test.ts @@ -1,4 +1,3 @@ -import type { Curve, Degrees, GlobalPoint } from "@excalidraw/math"; import { curve, degreesToRadians, @@ -7,7 +6,11 @@ import { pointFrom, pointRotateDegs, } from "@excalidraw/math"; + +import type { Curve, Degrees, GlobalPoint } from "@excalidraw/math"; + import { pointOnCurve, pointOnPolyline } from "./collision"; + import type { Polyline } from "./geometry/shape"; describe("point and curve", () => { diff --git a/packages/utils/collision.ts b/packages/utils/collision.ts index fb48f4e45..f90019418 100644 --- a/packages/utils/collision.ts +++ b/packages/utils/collision.ts @@ -1,10 +1,3 @@ -import type { Polycurve, Polyline } from "./geometry/shape"; -import { - pointInEllipse, - pointOnEllipse, - type GeometricShape, -} from "./geometry/shape"; -import type { Curve } from "@excalidraw/math"; import { lineSegment, pointFrom, @@ -17,6 +10,16 @@ import { type Polygon, } from "@excalidraw/math"; +import type { Curve } from "@excalidraw/math"; + +import { + pointInEllipse, + pointOnEllipse, + type GeometricShape, +} from "./geometry/shape"; + +import type { Polycurve, Polyline } from "./geometry/shape"; + // check if the given point is considered on the given shape's border export const isPointOnShape = ( point: Point, diff --git a/packages/utils/export.test.ts b/packages/utils/export.test.ts index e2af763b5..86bbe80b7 100644 --- a/packages/utils/export.test.ts +++ b/packages/utils/export.test.ts @@ -1,9 +1,9 @@ -import * as utils from "."; +import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; +import * as mockedSceneExportUtils from "@excalidraw/excalidraw/scene/export"; import { diagramFactory } from "@excalidraw/excalidraw/tests/fixtures/diagramFixture"; import { vi } from "vitest"; -import * as mockedSceneExportUtils from "@excalidraw/excalidraw/scene/export"; -import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; +import * as utils from "."; const exportToSvgSpy = vi.spyOn(mockedSceneExportUtils, "exportToSvg"); diff --git a/packages/utils/export.ts b/packages/utils/export.ts index 22287ce7e..6de25c62b 100644 --- a/packages/utils/export.ts +++ b/packages/utils/export.ts @@ -1,23 +1,24 @@ -import { - exportToCanvas as _exportToCanvas, - exportToSvg as _exportToSvg, -} from "@excalidraw/excalidraw/scene/export"; import { getDefaultAppState } from "@excalidraw/excalidraw/appState"; -import type { AppState, BinaryFiles } from "@excalidraw/excalidraw/types"; -import type { - ExcalidrawElement, - ExcalidrawFrameLikeElement, - NonDeleted, -} from "@excalidraw/excalidraw/element/types"; -import { restore } from "@excalidraw/excalidraw/data/restore"; -import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; -import { encodePngMetadata } from "@excalidraw/excalidraw/data/image"; -import { serializeAsJSON } from "@excalidraw/excalidraw/data/json"; import { copyBlobToClipboardAsPng, copyTextToSystemClipboard, copyToClipboard, } from "@excalidraw/excalidraw/clipboard"; +import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; +import { encodePngMetadata } from "@excalidraw/excalidraw/data/image"; +import { serializeAsJSON } from "@excalidraw/excalidraw/data/json"; +import { restore } from "@excalidraw/excalidraw/data/restore"; +import { + exportToCanvas as _exportToCanvas, + exportToSvg as _exportToSvg, +} from "@excalidraw/excalidraw/scene/export"; + +import type { + ExcalidrawElement, + ExcalidrawFrameLikeElement, + NonDeleted, +} from "@excalidraw/excalidraw/element/types"; +import type { AppState, BinaryFiles } from "@excalidraw/excalidraw/types"; export { MIME_TYPES }; diff --git a/packages/utils/geometry/geometry.test.ts b/packages/utils/geometry/geometry.test.ts index e9ad067fe..6ddab71b0 100644 --- a/packages/utils/geometry/geometry.test.ts +++ b/packages/utils/geometry/geometry.test.ts @@ -1,9 +1,3 @@ -import type { - GlobalPoint, - LineSegment, - Polygon, - Radians, -} from "@excalidraw/math"; import { pointFrom, lineSegment, @@ -13,6 +7,14 @@ import { polygonIncludesPoint, segmentsIntersectAt, } from "@excalidraw/math"; + +import type { + GlobalPoint, + LineSegment, + Polygon, + Radians, +} from "@excalidraw/math"; + import { pointInEllipse, pointOnEllipse, type Ellipse } from "./shape"; describe("point and line", () => { diff --git a/packages/utils/geometry/shape.ts b/packages/utils/geometry/shape.ts index 2ba04a2b2..ea3cde3f6 100644 --- a/packages/utils/geometry/shape.ts +++ b/packages/utils/geometry/shape.ts @@ -12,7 +12,8 @@ * to pure shapes */ -import type { Curve, LineSegment, Polygon, Radians } from "@excalidraw/math"; +import { getElementAbsoluteCoords } from "@excalidraw/excalidraw/element"; +import { invariant } from "@excalidraw/excalidraw/utils"; import { curve, lineSegment, @@ -32,7 +33,8 @@ import { type GlobalPoint, type LocalPoint, } from "@excalidraw/math"; -import { getElementAbsoluteCoords } from "@excalidraw/excalidraw/element"; +import { pointsOnBezierCurves } from "points-on-curve"; + import type { ElementsMap, ExcalidrawBindableElement, @@ -49,9 +51,9 @@ import type { ExcalidrawSelectionElement, ExcalidrawTextElement, } from "@excalidraw/excalidraw/element/types"; -import { pointsOnBezierCurves } from "points-on-curve"; +import type { Curve, LineSegment, Polygon, Radians } from "@excalidraw/math"; + import type { Drawable, Op } from "roughjs/bin/core"; -import { invariant } from "@excalidraw/excalidraw/utils"; // a polyline (made up term here) is a line consisting of other line segments // this corresponds to a straight line element in the editor but it could also @@ -192,6 +194,11 @@ export const getEllipseShape = ( }; export const getCurvePathOps = (shape: Drawable): Op[] => { + // NOTE (mtolmacs): Temporary fix for extremely large elements + if (!shape) { + return []; + } + for (const set of shape.sets) { if (set.type === "path") { return set.ops; diff --git a/packages/utils/utils.unmocked.test.ts b/packages/utils/utils.unmocked.test.ts index 341adef95..417eabda1 100644 --- a/packages/utils/utils.unmocked.test.ts +++ b/packages/utils/utils.unmocked.test.ts @@ -1,8 +1,10 @@ -import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; -import * as utils from "./index"; -import { API } from "@excalidraw/excalidraw/tests/helpers/api"; -import { decodeSvgBase64Payload } from "@excalidraw/excalidraw/scene/export"; import { decodePngMetadata } from "@excalidraw/excalidraw/data/image"; +import { decodeSvgBase64Payload } from "@excalidraw/excalidraw/scene/export"; +import { API } from "@excalidraw/excalidraw/tests/helpers/api"; + +import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; + +import * as utils from "./index"; // NOTE this test file is using the actual API, unmocked. Hence splitting it // from the other test file, because I couldn't figure out how to test diff --git a/packages/utils/withinBounds.test.ts b/packages/utils/withinBounds.test.ts index 85354d742..b07d0bc33 100644 --- a/packages/utils/withinBounds.test.ts +++ b/packages/utils/withinBounds.test.ts @@ -1,5 +1,7 @@ -import type { Bounds } from "@excalidraw/excalidraw/element/bounds"; import { API } from "@excalidraw/excalidraw/tests/helpers/api"; + +import type { Bounds } from "@excalidraw/excalidraw/element/bounds"; + import { elementPartiallyOverlapsWithOrContainsBBox, elementsOverlappingBBox, diff --git a/packages/utils/withinBounds.ts b/packages/utils/withinBounds.ts index 8d52eb3ad..71bc78969 100644 --- a/packages/utils/withinBounds.ts +++ b/packages/utils/withinBounds.ts @@ -1,9 +1,4 @@ -import type { - ExcalidrawElement, - ExcalidrawFreeDrawElement, - ExcalidrawLinearElement, - NonDeletedExcalidrawElement, -} from "@excalidraw/excalidraw/element/types"; +import { getElementBounds } from "@excalidraw/excalidraw/element/bounds"; import { isArrowElement, isExcalidrawElement, @@ -11,10 +6,7 @@ import { isLinearElement, isTextElement, } from "@excalidraw/excalidraw/element/typeChecks"; -import type { Bounds } from "@excalidraw/excalidraw/element/bounds"; -import { getElementBounds } from "@excalidraw/excalidraw/element/bounds"; import { arrayToMap } from "@excalidraw/excalidraw/utils"; -import type { LocalPoint } from "@excalidraw/math"; import { rangeIncludesValue, pointFrom, @@ -22,6 +14,15 @@ import { rangeInclusive, } from "@excalidraw/math"; +import type { Bounds } from "@excalidraw/excalidraw/element/bounds"; +import type { + ExcalidrawElement, + ExcalidrawFreeDrawElement, + ExcalidrawLinearElement, + NonDeletedExcalidrawElement, +} from "@excalidraw/excalidraw/element/types"; +import type { LocalPoint } from "@excalidraw/math"; + type Element = NonDeletedExcalidrawElement; type Elements = readonly NonDeletedExcalidrawElement[]; diff --git a/scripts/autorelease.js b/scripts/autorelease.js index f506cf13c..6ca5af213 100644 --- a/scripts/autorelease.js +++ b/scripts/autorelease.js @@ -1,5 +1,6 @@ -const fs = require("fs"); const { exec, execSync } = require("child_process"); +const fs = require("fs"); + const core = require("@actions/core"); const excalidrawDir = `${__dirname}/../packages/excalidraw`; diff --git a/scripts/buildMath.js b/scripts/buildMath.js index fd2f820ea..ba421b48c 100644 --- a/scripts/buildMath.js +++ b/scripts/buildMath.js @@ -1,4 +1,5 @@ const path = require("path"); + const { build } = require("esbuild"); const { sassPlugin } = require("esbuild-sass-plugin"); diff --git a/scripts/buildPackage.js b/scripts/buildPackage.js index 653af50f2..3dd15eeca 100644 --- a/scripts/buildPackage.js +++ b/scripts/buildPackage.js @@ -1,6 +1,8 @@ const path = require("path"); + const { build } = require("esbuild"); const { sassPlugin } = require("esbuild-sass-plugin"); + const { parseEnvVariables } = require("../packages/excalidraw/env.cjs"); const ENV_VARS = { diff --git a/scripts/buildUtils.js b/scripts/buildUtils.js index 65b947385..b5718f57e 100644 --- a/scripts/buildUtils.js +++ b/scripts/buildUtils.js @@ -1,6 +1,8 @@ const path = require("path"); + const { build } = require("esbuild"); const { sassPlugin } = require("esbuild-sass-plugin"); + const { woff2ServerPlugin } = require("./woff2/woff2-esbuild-plugins"); // contains all dependencies bundled inside diff --git a/scripts/prerelease.js b/scripts/prerelease.js index 3b8080d33..005a6cf5f 100644 --- a/scripts/prerelease.js +++ b/scripts/prerelease.js @@ -1,5 +1,6 @@ const fs = require("fs"); const util = require("util"); + const exec = util.promisify(require("child_process").exec); const updateChangelog = require("./updateChangelog"); diff --git a/scripts/woff2/woff2-esbuild-plugins.js b/scripts/woff2/woff2-esbuild-plugins.js index 19ebafc93..2116dd059 100644 --- a/scripts/woff2/woff2-esbuild-plugins.js +++ b/scripts/woff2/woff2-esbuild-plugins.js @@ -1,9 +1,10 @@ +const { execSync } = require("child_process"); const fs = require("fs"); const path = require("path"); -const { execSync } = require("child_process"); -const which = require("which"); -const wawoff = require("wawoff2"); + const { Font } = require("fonteditor-core"); +const wawoff = require("wawoff2"); +const which = require("which"); /** * Custom esbuild plugin to: diff --git a/setupTests.ts b/setupTests.ts index 20d2cc517..2aec616b4 100644 --- a/setupTests.ts +++ b/setupTests.ts @@ -1,11 +1,13 @@ +import fs from "fs"; + // vitest.setup.ts import "vitest-canvas-mock"; import "@testing-library/jest-dom"; -import fs from "fs"; import { vi } from "vitest"; + import polyfill from "./packages/excalidraw/polyfill"; -import { testPolyfills } from "./packages/excalidraw/tests/helpers/polyfills"; import { yellow } from "./packages/excalidraw/tests/helpers/colorize"; +import { testPolyfills } from "./packages/excalidraw/tests/helpers/polyfills"; // mock for pep.js not working with setPointerCapture() HTMLElement.prototype.setPointerCapture = vi.fn(); diff --git a/yarn.lock b/yarn.lock index d1c522a91..ccd0827fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1442,43 +1442,6 @@ resolved "https://registry.yarnpkg.com/@excalidraw/eslint-config/-/eslint-config-1.0.3.tgz#2122ef7413ae77874ae9848ce0f1c6b3f0d8bbbd" integrity sha512-GemHNF5Z6ga0BWBSX7GJaNBUchLu6RwTcAB84eX1MeckRNhNasAsPCdelDlFalz27iS4RuYEQh0bPE8SRxJgbQ== -"@excalidraw/excalidraw@0.18.0-rc.5": - version "0.18.0-rc.5" - resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.18.0-rc.5.tgz#c55598e01808693702251322e59bf9dba931b6e0" - integrity sha512-f6Z6cWlx+FWl1nxCu5F6OdKm9ooV/FPjndjIfFhGLVyERKATXhuNwZUHWwqsEW+SIGmiPG2515NG9KIOhjGd5g== - dependencies: - "@braintree/sanitize-url" "6.0.2" - "@excalidraw/laser-pointer" "1.3.1" - "@excalidraw/mermaid-to-excalidraw" "1.1.2" - "@excalidraw/random-username" "1.1.0" - "@radix-ui/react-popover" "1.0.3" - "@radix-ui/react-tabs" "1.0.2" - browser-fs-access "0.29.1" - canvas-roundrect-polyfill "0.0.1" - clsx "1.1.1" - cross-env "7.0.3" - es6-promise-pool "2.5.0" - fractional-indexing "3.2.0" - fuzzy "0.1.3" - image-blob-reduce "3.0.1" - jotai "2.11.0" - jotai-scope "0.7.2" - lodash.debounce "4.0.8" - lodash.throttle "4.1.1" - nanoid "3.3.3" - open-color "1.9.1" - pako "2.0.3" - perfect-freehand "1.2.0" - pica "7.1.1" - png-chunk-text "1.0.0" - png-chunks-encode "1.0.0" - png-chunks-extract "1.0.0" - points-on-curve "1.0.1" - pwacompat "2.0.17" - roughjs "4.6.4" - sass "1.51.0" - tunnel-rat "0.1.2" - "@excalidraw/laser-pointer@1.3.1": version "1.3.1" resolved "https://registry.yarnpkg.com/@excalidraw/laser-pointer/-/laser-pointer-1.3.1.tgz#7c40836598e8e6ad91f01057883ed8b88fb9266c" @@ -1904,11 +1867,6 @@ resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz#a73bab8eb491d7b8b7be2f0e6c310647835afe83" integrity sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ== -"@floating-ui/core@^0.7.3": - version "0.7.3" - resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.7.3.tgz#d274116678ffae87f6b60e90f88cc4083eefab86" - integrity sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg== - "@floating-ui/core@^1.6.0": version "1.6.9" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.9.tgz#64d1da251433019dafa091de9b2886ff35ec14e6" @@ -1916,13 +1874,6 @@ dependencies: "@floating-ui/utils" "^0.2.9" -"@floating-ui/dom@^0.5.3": - version "0.5.4" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.5.4.tgz#4eae73f78bcd4bd553ae2ade30e6f1f9c73fe3f1" - integrity sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg== - dependencies: - "@floating-ui/core" "^0.7.3" - "@floating-ui/dom@^1.0.0": version "1.6.13" resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.13.tgz#a8a938532aea27a95121ec16e667a7cbe8c59e34" @@ -1931,14 +1882,6 @@ "@floating-ui/core" "^1.6.0" "@floating-ui/utils" "^0.2.9" -"@floating-ui/react-dom@0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.7.2.tgz#0bf4ceccb777a140fc535c87eb5d6241c8e89864" - integrity sha512-1T0sJcpHgX/u4I1OzIEhlcrvkUN8ln39nz7fMoE/2HDHrPiMFoOGR7++GYyfUmIQHkkrTinaeQsO3XWubjSvGg== - dependencies: - "@floating-ui/dom" "^0.5.3" - use-isomorphic-layout-effect "^1.1.1" - "@floating-ui/react-dom@^2.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31" @@ -2289,14 +2232,6 @@ resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.1.tgz#fc169732d755c7fbad33ba8d0cd7fd10c90dc8e3" integrity sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA== -"@radix-ui/react-arrow@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.1.tgz#5246adf79e97f89e819af68da51ddcf349ecf1c4" - integrity sha512-1yientwXqXcErDHEv8av9ZVNEBldH8L9scVR3is20lL+jOCfcJyMFZFEY5cgIrgexsq1qggSXqiEL/d/4f+QXA== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-arrow@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.2.tgz#30c0d574d7bb10eed55cd7007b92d38b03c6b2ab" @@ -2346,18 +2281,6 @@ dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-dismissable-layer@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.2.tgz#f04d1061bddf00b1ca304148516b9ddc62e45fb2" - integrity sha512-WjJzMrTWROozDqLB0uRWYvj4UuXsM/2L19EmQ3Au+IJWqwvwq9Bwd+P8ivo0Deg9JDPArR1I6MbWNi1CmXsskg== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.0" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-use-callback-ref" "1.0.0" - "@radix-ui/react-use-escape-keydown" "1.0.2" - "@radix-ui/react-dismissable-layer@1.1.5": version "1.1.5" resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz#96dde2be078c694a621e55e047406c58cd5fe774" @@ -2369,28 +2292,11 @@ "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-escape-keydown" "1.1.0" -"@radix-ui/react-focus-guards@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.0.tgz#339c1c69c41628c1a5e655f15f7020bf11aa01fa" - integrity sha512-UagjDk4ijOAnGu4WMUPj9ahi7/zJJqNZ9ZAiGPp7waUWJO0O1aWXi/udPphI0IUjvrhBsZJGSN66dR2dsueLWQ== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-focus-guards@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe" integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg== -"@radix-ui/react-focus-scope@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.1.tgz#faea8c25f537c5a5c38c50914b63722db0e7f951" - integrity sha512-Ej2MQTit8IWJiS2uuujGUmxXjF/y5xZptIIQnyd2JHLwtV0R2j9NRVoRj/1j/gJ7e3REdaBw4Hjf4a1ImhkZcQ== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-use-callback-ref" "1.0.0" - "@radix-ui/react-focus-scope@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz#c0a4519cd95c772606a82fc5b96226cd7fdd2602" @@ -2415,28 +2321,6 @@ dependencies: "@radix-ui/react-use-layout-effect" "1.1.0" -"@radix-ui/react-popover@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.0.3.tgz#65ae2ee1fca2d7fd750308549eb8e0857c6160fe" - integrity sha512-YwedSukfWsyJs3/yP3yXUq44k4/JBe3jqU63Z8v2i19qZZ3dsx32oma17ztgclWPNuqp3A+Xa9UiDlZHyVX8Vg== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.0" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-context" "1.0.0" - "@radix-ui/react-dismissable-layer" "1.0.2" - "@radix-ui/react-focus-guards" "1.0.0" - "@radix-ui/react-focus-scope" "1.0.1" - "@radix-ui/react-id" "1.0.0" - "@radix-ui/react-popper" "1.1.0" - "@radix-ui/react-portal" "1.0.1" - "@radix-ui/react-presence" "1.0.0" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-slot" "1.0.1" - "@radix-ui/react-use-controllable-state" "1.0.0" - aria-hidden "^1.1.1" - react-remove-scroll "2.5.5" - "@radix-ui/react-popover@1.1.6": version "1.1.6" resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.1.6.tgz#699634dbc7899429f657bb590d71fb3ca0904087" @@ -2458,23 +2342,6 @@ aria-hidden "^1.2.4" react-remove-scroll "^2.6.3" -"@radix-ui/react-popper@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.0.tgz#2be7e4c0cd4581f54277ca33a981c9037d2a8e60" - integrity sha512-07U7jpI0dZcLRAxT7L9qs6HecSoPhDSJybF7mEGHJDBDv+ZoGCvIlva0s+WxMXwJEav+ckX3hAlXBtnHmuvlCQ== - dependencies: - "@babel/runtime" "^7.13.10" - "@floating-ui/react-dom" "0.7.2" - "@radix-ui/react-arrow" "1.0.1" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-context" "1.0.0" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-use-callback-ref" "1.0.0" - "@radix-ui/react-use-layout-effect" "1.0.0" - "@radix-ui/react-use-rect" "1.0.0" - "@radix-ui/react-use-size" "1.0.0" - "@radix-ui/rect" "1.0.0" - "@radix-ui/react-popper@1.2.2": version "1.2.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.2.tgz#d2e1ee5a9b24419c5936a1b7f6f472b7b412b029" @@ -2491,14 +2358,6 @@ "@radix-ui/react-use-size" "1.1.0" "@radix-ui/rect" "1.1.0" -"@radix-ui/react-portal@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.1.tgz#169c5a50719c2bb0079cf4c91a27aa6d37e5dd33" - integrity sha512-NY2vUWI5WENgAT1nfC6JS7RU5xRYBfjZVLq0HmgEN1Ezy3rk/UruMV4+Rd0F40PEaFC5SrLS1ixYvcYIQrb4Ig== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-portal@1.1.4": version "1.1.4" resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.4.tgz#ff5401ff63c8a825c46eea96d3aef66074b8c0c8" @@ -2612,14 +2471,6 @@ dependencies: "@radix-ui/react-use-callback-ref" "1.1.0" -"@radix-ui/react-use-escape-keydown@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.2.tgz#09ab6455ab240b4f0a61faf06d4e5132c4d639f6" - integrity sha512-DXGim3x74WgUv+iMNCF+cAo8xUHHeqvjx8zs7trKf+FkQKPQXLk2sX7Gx1ysH7Q76xCpZuxIJE7HLPxRE+Q+GA== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-callback-ref" "1.0.0" - "@radix-ui/react-use-escape-keydown@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754" @@ -2639,14 +2490,6 @@ resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== -"@radix-ui/react-use-rect@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.0.tgz#b040cc88a4906b78696cd3a32b075ed5b1423b3e" - integrity sha512-TB7pID8NRMEHxb/qQJpvSt3hQU4sqNPM1VCTjTRjEOa7cEop/QMuq8S6fb/5Tsz64kqSvB9WnwsDHtjnrM9qew== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/rect" "1.0.0" - "@radix-ui/react-use-rect@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88" @@ -2654,14 +2497,6 @@ dependencies: "@radix-ui/rect" "1.1.0" -"@radix-ui/react-use-size@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.0.0.tgz#a0b455ac826749419f6354dc733e2ca465054771" - integrity sha512-imZ3aYcoYCKhhgNpkNDh/aTiU05qw9hX+HHI1QDBTyIlcFjgeFlKKySNGMwTp7nYFLQg/j0VA2FmCY4WPDDHMg== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-layout-effect" "1.0.0" - "@radix-ui/react-use-size@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b" @@ -2669,13 +2504,6 @@ dependencies: "@radix-ui/react-use-layout-effect" "1.1.0" -"@radix-ui/rect@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.0.tgz#0dc8e6a829ea2828d53cbc94b81793ba6383bf3c" - integrity sha512-d0O68AYy/9oeEy1DdC07bz1/ZXX+DqCskRd3i4JzLSTXwefzaepQrKjXC7aNM8lTHjFLDO0pDgaEiQ7jEk+HVg== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/rect@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438" @@ -3191,7 +3019,14 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78" integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== -"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0": +"@types/node@*": + version "22.13.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.10.tgz#df9ea358c5ed991266becc3109dc2dc9125d77e4" + integrity sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw== + dependencies: + undici-types "~6.20.0" + +"@types/node@>=12.12.47", "@types/node@>=13.7.0": version "22.13.8" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.8.tgz#57e2450295b33a6518d6fd4f65f47236d3e41d8d" integrity sha512-G3EfaZS+iOGYWLLRCEAXdWK9my08oHNZ+FHluRiggIYJPOXzhOiDgpVCUHaUvyIC5/fj7C/p637jdzC666AOKQ== @@ -3638,7 +3473,12 @@ acorn@^7.4.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.14.0, acorn@^8.8.2: +acorn@^8.14.0: + version "8.14.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" + integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== + +acorn@^8.8.2: version "8.14.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== @@ -3758,7 +3598,7 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -aria-hidden@^1.1.1, aria-hidden@^1.2.4: +aria-hidden@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522" integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A== @@ -4177,7 +4017,12 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001335, caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001688: +caniuse-lite@^1.0.30001335: + version "1.0.30001703" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001703.tgz#977cb4920598c158f491ecf4f4f2cfed9e354718" + integrity sha512-kRlAGTRWgPsOj7oARC9m1okJEXdL/8fekFVcxA8Hl7GH4r/sN4OJn/i6Flde373T50KS7Y37oFbMwlE8+F42kQ== + +caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001688: version "1.0.30001701" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001701.tgz#ad9c90301f7153cf6b3314d16cc30757285bf9e7" integrity sha512-faRs/AW3jA9nTwmJBSO1PQ6L/EOgsB5HMQQq4iCu5zhPgVVgO/pZRHlmatwijZKetFw8/Pr4q6dEN8sJuq8qTw== @@ -4912,9 +4757,9 @@ decimal.js@^10.4.3: integrity sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw== decode-named-character-reference@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" - integrity sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg== + version "1.1.0" + resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz#5d6ce68792808901210dac42a8e9853511e2b8bf" + integrity sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w== dependencies: character-entities "^2.0.0" @@ -5509,7 +5354,7 @@ eslint-plugin-flowtype@^8.0.3: lodash "^4.17.21" string-natural-compare "^3.0.1" -eslint-plugin-import@^2.25.3: +eslint-plugin-import@2.31.0, eslint-plugin-import@^2.25.3: version "2.31.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz#310ce7e720ca1d9c0bb3f69adfd1c6bdd7d9e0e7" integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A== @@ -7636,7 +7481,12 @@ nanoid@4.0.2: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.2.tgz#140b3c5003959adbebf521c170f282c5e7f9fb9e" integrity sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw== -nanoid@^3.3.2, nanoid@^3.3.6, nanoid@^3.3.8: +nanoid@^3.3.2: + version "3.3.9" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.9.tgz#e0097d8e026b3343ff053e9ccd407360a03f503a" + integrity sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg== + +nanoid@^3.3.6, nanoid@^3.3.8: version "3.3.8" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== @@ -8320,7 +8170,7 @@ react-refresh@^0.14.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== -react-remove-scroll-bar@^2.3.3, react-remove-scroll-bar@^2.3.7: +react-remove-scroll-bar@^2.3.7: version "2.3.8" resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== @@ -8328,17 +8178,6 @@ react-remove-scroll-bar@^2.3.3, react-remove-scroll-bar@^2.3.7: react-style-singleton "^2.2.2" tslib "^2.0.0" -react-remove-scroll@2.5.5: - version "2.5.5" - resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77" - integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw== - dependencies: - react-remove-scroll-bar "^2.3.3" - react-style-singleton "^2.2.1" - tslib "^2.1.0" - use-callback-ref "^1.3.0" - use-sidecar "^1.1.2" - react-remove-scroll@^2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz#df02cde56d5f2731e058531f8ffd7f9adec91ac2" @@ -8350,7 +8189,7 @@ react-remove-scroll@^2.6.3: use-callback-ref "^1.3.3" use-sidecar "^1.1.3" -react-style-singleton@^2.2.1, react-style-singleton@^2.2.2, react-style-singleton@^2.2.3: +react-style-singleton@^2.2.2, react-style-singleton@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388" integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ== @@ -9270,9 +9109,9 @@ tempy@^0.6.0: unique-string "^2.0.0" terser-webpack-plugin@^5.3.11: - version "5.3.12" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.12.tgz#d9518c80493081bace668aa8613b22e4a838810c" - integrity sha512-jDLYqo7oF8tJIttjXO6jBY5Hk8p3A8W4ttih7cCEq64fQFWmgJ4VqAQjKr7WwIDlmXKEc6QeoRb5ecjZ+2afcg== + version "5.3.14" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz#9031d48e57ab27567f02ace85c7d690db66c3e06" + integrity sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw== dependencies: "@jridgewell/trace-mapping" "^0.3.25" jest-worker "^27.4.5" @@ -9650,19 +9489,14 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" -use-callback-ref@^1.3.0, use-callback-ref@^1.3.3: +use-callback-ref@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== dependencies: tslib "^2.0.0" -use-isomorphic-layout-effect@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz#afb292eb284c39219e8cb8d3d62d71999361a21d" - integrity sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w== - -use-sidecar@^1.1.2, use-sidecar@^1.1.3: +use-sidecar@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb" integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==