From 472c51dab1725eac967c075527323f52c20fc10c Mon Sep 17 00:00:00 2001 From: Suni Date: Wed, 9 Aug 2023 23:55:49 +0800 Subject: [PATCH] Major update --- README.md | 4 - package.json | 1 + pnpm-lock.yaml | 545 +++++++++++++++++++++++- public/favicon.svg | 15 +- public/logo.svg | 12 +- src/App.tsx | 6 +- src/components/code-mind.tsx | 2 + src/components/editable-node.tsx | 4 +- src/components/mind-container.tsx | 36 +- src/components/mind-control.tsx | 48 +++ src/global.d.ts | 12 +- src/lib/save.ts | 30 +- src/lib/storage.ts | 3 +- src/share.ts | 36 +- src/styles/index.scss | 3 +- src/styles/mind-node.scss | 3 + src/styles/{editor.scss => monaco.scss} | 0 src/svgs/brush.svg | 3 + src/svgs/center.svg | 3 + src/svgs/github.tsx | 7 - src/svgs/zoom-in.svg | 6 + src/svgs/zoom-out.svg | 5 + src/themes/sunset/goose-1.svg | 3 + src/themes/sunset/goose-2.svg | 3 + src/themes/sunset/islet.svg | 30 ++ src/themes/sunset/scene.tsx | 43 ++ src/themes/sunset/sun.svg | 9 + src/themes/sunset/wave-deep.svg | 3 + src/themes/sunset/wave-shallow.svg | 3 + src/utils.ts | 4 + tailwind.config.js | 2 +- vite.config.ts | 5 +- 32 files changed, 825 insertions(+), 64 deletions(-) create mode 100644 src/components/mind-control.tsx create mode 100644 src/styles/mind-node.scss rename src/styles/{editor.scss => monaco.scss} (100%) create mode 100644 src/svgs/brush.svg create mode 100644 src/svgs/center.svg delete mode 100644 src/svgs/github.tsx create mode 100644 src/svgs/zoom-in.svg create mode 100644 src/svgs/zoom-out.svg create mode 100644 src/themes/sunset/goose-1.svg create mode 100644 src/themes/sunset/goose-2.svg create mode 100644 src/themes/sunset/islet.svg create mode 100644 src/themes/sunset/scene.tsx create mode 100644 src/themes/sunset/sun.svg create mode 100644 src/themes/sunset/wave-deep.svg create mode 100644 src/themes/sunset/wave-shallow.svg diff --git a/README.md b/README.md index 7084210..ab3d36a 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,6 @@ Online mind mapping that supports code writing, single and native. - Type `/code` to switch to a code node (ts). - Use Ctrl/Command + s to save to local storage. -## Why - -Xmind is the best mind mapping tool I have used, but it tends to freeze after working with hundreds of nodes. Additionally, I want to be able to write code with highlights within a mind map. - ## To Do - [x] Background diff --git a/package.json b/package.json index fbb41a9..5999ce9 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "react-dom": "^18.2.0", "react-textarea-autosize": "^8.5.2", "sonner": "^0.6.2", + "vite-plugin-svgr": "^3.2.0", "vite-tsconfig-paths": "^4.2.0" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9a50219..6fc3acb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ dependencies: sonner: specifier: ^0.6.2 version: 0.6.2(react-dom@18.2.0)(react@18.2.0) + vite-plugin-svgr: + specifier: ^3.2.0 + version: 3.2.0(vite@4.3.9) vite-tsconfig-paths: specifier: ^4.2.0 version: 4.2.0(typescript@5.1.3)(vite@4.3.9) @@ -87,6 +90,169 @@ packages: engines: {node: '>=10'} dev: true + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 + dev: false + + /@babel/code-frame@7.22.10: + resolution: {integrity: sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.22.10 + chalk: 2.4.2 + dev: false + + /@babel/compat-data@7.22.9: + resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/core@7.22.10: + resolution: {integrity: sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.22.10 + '@babel/generator': 7.22.10 + '@babel/helper-compilation-targets': 7.22.10 + '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.10) + '@babel/helpers': 7.22.10 + '@babel/parser': 7.22.10 + '@babel/template': 7.22.5 + '@babel/traverse': 7.22.10 + '@babel/types': 7.22.10 + convert-source-map: 1.9.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/generator@7.22.10: + resolution: {integrity: sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.10 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 + jsesc: 2.5.2 + dev: false + + /@babel/helper-compilation-targets@7.22.10: + resolution: {integrity: sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.22.9 + '@babel/helper-validator-option': 7.22.5 + browserslist: 4.21.10 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: false + + /@babel/helper-environment-visitor@7.22.5: + resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-function-name@7.22.5: + resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.5 + '@babel/types': 7.22.10 + dev: false + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.10 + dev: false + + /@babel/helper-module-imports@7.22.5: + resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.10 + dev: false + + /@babel/helper-module-transforms@7.22.9(@babel/core@7.22.10): + resolution: {integrity: sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.22.10 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-module-imports': 7.22.5 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.5 + dev: false + + /@babel/helper-simple-access@7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.10 + dev: false + + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.10 + dev: false + + /@babel/helper-string-parser@7.22.5: + resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-validator-identifier@7.22.5: + resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-validator-option@7.22.5: + resolution: {integrity: sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helpers@7.22.10: + resolution: {integrity: sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.5 + '@babel/traverse': 7.22.10 + '@babel/types': 7.22.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/highlight@7.22.10: + resolution: {integrity: sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.5 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: false + + /@babel/parser@7.22.10: + resolution: {integrity: sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.22.10 + dev: false + /@babel/runtime@7.22.6: resolution: {integrity: sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==} engines: {node: '>=6.9.0'} @@ -94,6 +260,42 @@ packages: regenerator-runtime: 0.13.11 dev: false + /@babel/template@7.22.5: + resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.10 + '@babel/parser': 7.22.10 + '@babel/types': 7.22.10 + dev: false + + /@babel/traverse@7.22.10: + resolution: {integrity: sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.10 + '@babel/generator': 7.22.10 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-function-name': 7.22.5 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.22.10 + '@babel/types': 7.22.10 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/types@7.22.10: + resolution: {integrity: sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.22.5 + '@babel/helper-validator-identifier': 7.22.5 + to-fast-properties: 2.0.0 + dev: false + /@esbuild/android-arm64@0.17.19: resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} engines: {node: '>=12'} @@ -334,32 +536,26 @@ packages: '@jridgewell/set-array': 1.1.2 '@jridgewell/sourcemap-codec': 1.4.15 '@jridgewell/trace-mapping': 0.3.18 - dev: true /@jridgewell/resolve-uri@3.1.0: resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} engines: {node: '>=6.0.0'} - dev: true /@jridgewell/set-array@1.1.2: resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} engines: {node: '>=6.0.0'} - dev: true /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} - dev: true /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true /@jridgewell/trace-mapping@0.3.18: resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} dependencies: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 - dev: true /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -430,6 +626,141 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@rollup/pluginutils@5.0.2: + resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.1 + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: false + + /@svgr/babel-plugin-add-jsx-attribute@7.0.0(@babel/core@7.22.10): + resolution: {integrity: sha512-khWbXesWIP9v8HuKCl2NU2HNAyqpSQ/vkIl36Nbn4HIwEYSRWL0H7Gs6idJdha2DkpFDWlsqMELvoCE8lfFY6Q==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.10 + dev: false + + /@svgr/babel-plugin-remove-jsx-attribute@7.0.0(@babel/core@7.22.10): + resolution: {integrity: sha512-iiZaIvb3H/c7d3TH2HBeK91uI2rMhZNwnsIrvd7ZwGLkFw6mmunOCoVnjdYua662MqGFxlN9xTq4fv9hgR4VXQ==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.10 + dev: false + + /@svgr/babel-plugin-remove-jsx-empty-expression@7.0.0(@babel/core@7.22.10): + resolution: {integrity: sha512-sQQmyo+qegBx8DfFc04PFmIO1FP1MHI1/QEpzcIcclo5OAISsOJPW76ZIs0bDyO/DBSJEa/tDa1W26pVtt0FRw==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.10 + dev: false + + /@svgr/babel-plugin-replace-jsx-attribute-value@7.0.0(@babel/core@7.22.10): + resolution: {integrity: sha512-i6MaAqIZXDOJeikJuzocByBf8zO+meLwfQ/qMHIjCcvpnfvWf82PFvredEZElErB5glQFJa2KVKk8N2xV6tRRA==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.10 + dev: false + + /@svgr/babel-plugin-svg-dynamic-title@7.0.0(@babel/core@7.22.10): + resolution: {integrity: sha512-BoVSh6ge3SLLpKC0pmmN9DFlqgFy4NxNgdZNLPNJWBUU7TQpDWeBuyVuDW88iXydb5Cv0ReC+ffa5h3VrKfk1w==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.10 + dev: false + + /@svgr/babel-plugin-svg-em-dimensions@7.0.0(@babel/core@7.22.10): + resolution: {integrity: sha512-tNDcBa+hYn0gO+GkP/AuNKdVtMufVhU9fdzu+vUQsR18RIJ9RWe7h/pSBY338RO08wArntwbDk5WhQBmhf2PaA==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.10 + dev: false + + /@svgr/babel-plugin-transform-react-native-svg@7.0.0(@babel/core@7.22.10): + resolution: {integrity: sha512-qw54u8ljCJYL2KtBOjI5z7Nzg8LnSvQOP5hPKj77H4VQL4+HdKbAT5pnkkZLmHKYwzsIHSYKXxHouD8zZamCFQ==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.10 + dev: false + + /@svgr/babel-plugin-transform-svg-component@7.0.0(@babel/core@7.22.10): + resolution: {integrity: sha512-CcFECkDj98daOg9jE3Bh3uyD9kzevCAnZ+UtzG6+BQG/jOQ2OA3jHnX6iG4G1MCJkUQFnUvEv33NvQfqrb/F3A==} + engines: {node: '>=12'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.10 + dev: false + + /@svgr/babel-preset@7.0.0(@babel/core@7.22.10): + resolution: {integrity: sha512-EX/NHeFa30j5UjldQGVQikuuQNHUdGmbh9kEpBKofGUtF0GUPJ4T4rhoYiqDAOmBOxojyot36JIFiDUHUK1ilQ==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.10 + '@svgr/babel-plugin-add-jsx-attribute': 7.0.0(@babel/core@7.22.10) + '@svgr/babel-plugin-remove-jsx-attribute': 7.0.0(@babel/core@7.22.10) + '@svgr/babel-plugin-remove-jsx-empty-expression': 7.0.0(@babel/core@7.22.10) + '@svgr/babel-plugin-replace-jsx-attribute-value': 7.0.0(@babel/core@7.22.10) + '@svgr/babel-plugin-svg-dynamic-title': 7.0.0(@babel/core@7.22.10) + '@svgr/babel-plugin-svg-em-dimensions': 7.0.0(@babel/core@7.22.10) + '@svgr/babel-plugin-transform-react-native-svg': 7.0.0(@babel/core@7.22.10) + '@svgr/babel-plugin-transform-svg-component': 7.0.0(@babel/core@7.22.10) + dev: false + + /@svgr/core@7.0.0: + resolution: {integrity: sha512-ztAoxkaKhRVloa3XydohgQQCb0/8x9T63yXovpmHzKMkHO6pkjdsIAWKOS4bE95P/2quVh1NtjSKlMRNzSBffw==} + engines: {node: '>=14'} + dependencies: + '@babel/core': 7.22.10 + '@svgr/babel-preset': 7.0.0(@babel/core@7.22.10) + camelcase: 6.3.0 + cosmiconfig: 8.2.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@svgr/hast-util-to-babel-ast@7.0.0: + resolution: {integrity: sha512-42Ej9sDDEmsJKjrfQ1PHmiDiHagh/u9AHO9QWbeNx4KmD9yS5d1XHmXUNINfUcykAU+4431Cn+k6Vn5mWBYimQ==} + engines: {node: '>=14'} + dependencies: + '@babel/types': 7.22.10 + entities: 4.5.0 + dev: false + + /@svgr/plugin-jsx@7.0.0: + resolution: {integrity: sha512-SWlTpPQmBUtLKxXWgpv8syzqIU8XgFRvyhfkam2So8b3BE0OS0HPe5UfmlJ2KIC+a7dpuuYovPR2WAQuSyMoPw==} + engines: {node: '>=14'} + dependencies: + '@babel/core': 7.22.10 + '@svgr/babel-preset': 7.0.0(@babel/core@7.22.10) + '@svgr/hast-util-to-babel-ast': 7.0.0 + svg-parser: 2.0.4 + transitivePeerDependencies: + - supports-color + dev: false + /@swc/core-darwin-arm64@1.3.64: resolution: {integrity: sha512-gSPld6wxZBZoEvZXWmNfd+eJGlGvrEXmhMBCUwSccpuMa0KqK7F6AAZVu7kFkmlXPq2kS8owjk6/VXnVBmm5Vw==} engines: {node: '>=10'} @@ -546,6 +877,10 @@ packages: '@swc/core-win32-x64-msvc': 1.3.64 dev: true + /@types/estree@1.0.1: + resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} + dev: false + /@types/json-schema@7.0.12: resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} dev: true @@ -755,6 +1090,13 @@ packages: engines: {node: '>=8'} dev: true + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: false + /ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -779,7 +1121,6 @@ packages: /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} @@ -823,6 +1164,17 @@ packages: dependencies: fill-range: 7.0.1 + /browserslist@4.21.10: + resolution: {integrity: sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001519 + electron-to-chromium: 1.4.488 + node-releases: 2.0.13 + update-browserslist-db: 1.0.11(browserslist@4.21.10) + dev: false + /browserslist@4.21.8: resolution: {integrity: sha512-j+7xYe+v+q2Id9qbBeCI8WX5NmZSRe8es1+0xntD/+gaWXznP8tFEkv5IgSaHf5dS1YwVMbX/4W6m937mj+wQw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -837,17 +1189,34 @@ packages: /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - dev: true /camelcase-css@2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} dev: true + /camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: false + /caniuse-lite@1.0.30001503: resolution: {integrity: sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw==} dev: true + /caniuse-lite@1.0.30001519: + resolution: {integrity: sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==} + dev: false + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: false + /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -875,6 +1244,12 @@ packages: engines: {node: '>=6'} dev: false + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: false + /color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -882,6 +1257,10 @@ packages: color-name: 1.1.4 dev: true + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: false + /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} dev: true @@ -895,6 +1274,20 @@ packages: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true + /convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + dev: false + + /cosmiconfig@8.2.0: + resolution: {integrity: sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==} + engines: {node: '>=14'} + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + dev: false + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -954,6 +1347,21 @@ packages: resolution: {integrity: sha512-FytjTbGwz///F+ToZ5XSeXbbSaXalsVRXsz2mHityI5gfxft7ieW3HqFLkU5V1aIrY42aflICqbmFoDxW10etg==} dev: true + /electron-to-chromium@1.4.488: + resolution: {integrity: sha512-Dv4sTjiW7t/UWGL+H8ZkgIjtUAVZDgb/PwGWvMsCT7jipzUV/u5skbLXPFKb6iV0tiddVi/bcS2/kUrczeWgIQ==} + dev: false + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + dev: false + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: false + /esbuild@0.17.19: resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} engines: {node: '>=12'} @@ -986,7 +1394,11 @@ packages: /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} - dev: true + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: false /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} @@ -1112,6 +1524,10 @@ packages: engines: {node: '>=4.0'} dev: true + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: false + /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -1198,6 +1614,11 @@ packages: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: true + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: false + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1233,6 +1654,11 @@ packages: path-is-absolute: 1.0.1 dev: true + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: false + /globals@13.20.0: resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} engines: {node: '>=8'} @@ -1264,6 +1690,11 @@ packages: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: false + /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -1290,7 +1721,6 @@ packages: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - dev: true /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} @@ -1308,6 +1738,10 @@ packages: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: true + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: false + /is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -1357,7 +1791,16 @@ packages: hasBin: true dependencies: argparse: 2.0.1 - dev: true + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: false /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -1367,6 +1810,12 @@ packages: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: false + /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1382,7 +1831,6 @@ packages: /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true /locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -1402,6 +1850,12 @@ packages: js-tokens: 4.0.0 dev: false + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: false + /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -1460,6 +1914,10 @@ packages: resolution: {integrity: sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==} dev: true + /node-releases@2.0.13: + resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} + dev: false + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -1516,7 +1974,16 @@ packages: engines: {node: '>=6'} dependencies: callsites: 3.1.0 - dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.22.10 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: false /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} @@ -1540,7 +2007,6 @@ packages: /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - dev: true /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} @@ -1750,7 +2216,6 @@ packages: /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - dev: true /resolve@1.22.2: resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} @@ -1801,6 +2266,11 @@ packages: loose-envify: 1.4.0 dev: false + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: false + /semver@7.5.1: resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==} engines: {node: '>=10'} @@ -1866,6 +2336,13 @@ packages: ts-interface-checker: 0.1.13 dev: true + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: false + /supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -1878,6 +2355,10 @@ packages: engines: {node: '>= 0.4'} dev: true + /svg-parser@2.0.4: + resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} + dev: false + /tailwindcss@3.3.2: resolution: {integrity: sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==} engines: {node: '>=14.0.0'} @@ -1927,6 +2408,11 @@ packages: any-promise: 1.3.0 dev: true + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: false + /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -1981,6 +2467,17 @@ packages: engines: {node: '>=14.17'} hasBin: true + /update-browserslist-db@1.0.11(browserslist@4.21.10): + resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.21.10 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: false + /update-browserslist-db@1.0.11(browserslist@4.21.8): resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} hasBin: true @@ -2037,6 +2534,20 @@ packages: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: true + /vite-plugin-svgr@3.2.0(vite@4.3.9): + resolution: {integrity: sha512-Uvq6niTvhqJU6ga78qLKBFJSDvxWhOnyfQSoKpDPMAGxJPo5S3+9hyjExE5YDj6Lpa4uaLkGc1cBgxXov+LjSw==} + peerDependencies: + vite: ^2.6.0 || 3 || 4 + dependencies: + '@rollup/pluginutils': 5.0.2 + '@svgr/core': 7.0.0 + '@svgr/plugin-jsx': 7.0.0 + vite: 4.3.9(sass@1.63.4) + transitivePeerDependencies: + - rollup + - supports-color + dev: false + /vite-tsconfig-paths@4.2.0(typescript@5.1.3)(vite@4.3.9): resolution: {integrity: sha512-jGpus0eUy5qbbMVGiTxCL1iB9ZGN6Bd37VGLJU39kTDD6ZfULTTb1bcc5IeTWqWJKiWV5YihCaibeASPiGi8kw==} peerDependencies: @@ -2103,6 +2614,10 @@ packages: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: true + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: false + /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true diff --git a/public/favicon.svg b/public/favicon.svg index dcbc4ed..c904af6 100644 --- a/public/favicon.svg +++ b/public/favicon.svg @@ -1,5 +1,12 @@ - - - - + + + + + + + + + + + diff --git a/public/logo.svg b/public/logo.svg index 42eecbb..438dbc0 100644 --- a/public/logo.svg +++ b/public/logo.svg @@ -1,4 +1,10 @@ - - - + + + + + + + + + diff --git a/src/App.tsx b/src/App.tsx index 0e37f6a..01d1359 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,18 +1,14 @@ import CodeMind from './components/code-mind' -import GithubSVG from './svgs/github' import { Toaster } from 'sonner' function App() { return ( <>
+
- - - - diff --git a/src/components/code-mind.tsx b/src/components/code-mind.tsx index 6702f95..480fea7 100644 --- a/src/components/code-mind.tsx +++ b/src/components/code-mind.tsx @@ -4,6 +4,7 @@ import { createContext, useEffect, useState } from 'react' import MindContainer from './mind-container' import MindNode from './mind-node' import { getLocalNodeTree, stateStore } from '../lib/save' +import MindControl from './mind-control' export const MindContext = createContext({ distance: 0, @@ -57,6 +58,7 @@ export default function CodeMind({ + ) } diff --git a/src/components/editable-node.tsx b/src/components/editable-node.tsx index 560f769..5090aae 100644 --- a/src/components/editable-node.tsx +++ b/src/components/editable-node.tsx @@ -174,6 +174,8 @@ const _EditableNode = forwardRef<{ getContent: () => string; getType: () => Node generateChild() } else if (event.key === 'Escape') { setEditable(false) + } else if (!editable && /^[a-zA-Z/]$/.test(event.key)) { + setEditable(true) } else if ( (!editable || innerRef.current!.innerHTML === '') && (event.key === 'Delete' || event.key === 'Backspace') @@ -186,7 +188,7 @@ const _EditableNode = forwardRef<{ getContent: () => string; getType: () => Node } }} contentEditable={editable} - className='relative w-max shrink-0 cursor-default break-all rounded bg-white/90 px-8 py-4 font-medium outline-2 outline-offset-2 outline-focus focus:outline' + className='mind-node' style={{ maxWidth: defaultMaxWidth, minWidth }} /> ) diff --git a/src/components/mind-container.tsx b/src/components/mind-container.tsx index 2f94bfe..ac73052 100644 --- a/src/components/mind-container.tsx +++ b/src/components/mind-container.tsx @@ -1,16 +1,34 @@ import { useEffect, useRef } from 'react' import { useSpring, animated } from '@react-spring/web' -import { containerState } from '@/share' +import { MAX_SCALE, MIN_SCALE, containerState, controls } from '@/share' import { createUseGesture, dragAction, pinchAction, wheelAction } from '@use-gesture/react' +import Scene from '@/themes/sunset/scene' const useGesture = createUseGesture([dragAction, pinchAction, wheelAction]) export default function MindContainer({ children }: PropsWithChildren) { const [springs, api] = useSpring(() => ({ - from: { x: 0, y: 0, scale: 1 }, + from: { x: containerState.x(), y: containerState.y(), scale: containerState.scale }, config: { tension: 100, friction: 5, mass: 0.1 } })) + // Initialize controls in share file + useEffect(() => { + controls.setScale = (s: number) => { + containerState.scale = s + api.start({ scale: s }) + } + controls.clearOffset = () => { + containerState.offsetX = 0 + containerState.offsetY = 0 + containerState.initialX = 0 + containerState.initialY = 0 + containerState.wheelX = 0 + containerState.wheelY = 0 + api.start({ x: 0, y: 0 }) + } + }, [api]) + const containerRef = useRef(null) // Prevent default gesture event @@ -36,8 +54,8 @@ export default function MindContainer({ children }: PropsWithChildren) { onDrag: ({ offset, target, cancel, pinching }) => { if (pinching) return cancel() - containerState._x = offset[0] - containerState._y = offset[1] + containerState.offsetX = offset[0] + containerState.offsetY = offset[1] api.set({ x: containerState.x(), y: containerState.y() }) }, onWheel: ({ offset, pinching, event }) => { @@ -53,7 +71,7 @@ export default function MindContainer({ children }: PropsWithChildren) { }, { target: containerRef, - pinch: { scaleBounds: { min: 0.5, max: 2 }, rubberband: true }, + pinch: { scaleBounds: { min: MIN_SCALE, max: MAX_SCALE }, rubberband: true }, drag: { pointer: { keys: false, buttons: 4 } } } ) @@ -83,11 +101,11 @@ export default function MindContainer({ children }: PropsWithChildren) { return (
+ className='code-mind relative flex h-full w-full touch-none items-center justify-center overflow-hidden'>
- - {children} + + +
{children}
diff --git a/src/components/mind-control.tsx b/src/components/mind-control.tsx new file mode 100644 index 0000000..c6c4482 --- /dev/null +++ b/src/components/mind-control.tsx @@ -0,0 +1,48 @@ +import { ReactComponent as BrushSVG } from '@/svgs/brush.svg' +import { ReactComponent as ZoomInSVG } from '@/svgs/zoom-in.svg' +import { ReactComponent as ZoomOutSVG } from '@/svgs/zoom-out.svg' +import { ReactComponent as CenterSVG } from '@/svgs/center.svg' +import { toast } from 'sonner' +import { MAX_SCALE, MIN_SCALE, containerState, controls } from '@/share' + +export default function MindControl() { + return ( + + ) +} diff --git a/src/global.d.ts b/src/global.d.ts index c6f261d..2610e61 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -1,3 +1,12 @@ +declare module '*.svg' { + const src: string + export default src + export const ReactComponent: React.FC> +} +declare type PropsWithChildren = React.PropsWithChildren + +declare type NodeRef = React.RefObject + declare type LineType = 'straight' | 'straight-with-handle' | 'right-angle' | 'bezier' declare type NodeType = 'text' | 'code' @@ -11,6 +20,3 @@ declare type MindNode = { type?: NodeType code?: string } - -declare type NodeRef = React.RefObject -declare type PropsWithChildren = React.PropsWithChildren diff --git a/src/lib/save.ts b/src/lib/save.ts index 95c642d..b145863 100644 --- a/src/lib/save.ts +++ b/src/lib/save.ts @@ -1,10 +1,11 @@ -import { initialNode } from '../share' +import { isObject } from '@/utils' +import { containerState, initialNode } from '../share' import { getStorage, setStorage } from './storage' import { toast } from 'sonner' export const stateStore: { current: MindNode[]; saveHandle: () => void } = { current: [], saveHandle: () => {} } -export const getLocalNodeTree = () => { +export function getLocalNodeTree() { const local = getStorage('state') if (local) { @@ -36,6 +37,20 @@ export const getLocalNodeTree = () => { return initialNode } +export function getLocalContainerState() { + const local = getStorage('container') + + if (local) { + const state = JSON.parse(local) + + if (isObject(state)) { + return state + } + } + + return null +} + async function save() { return new Promise(resolve => { stateStore.current = [] @@ -46,12 +61,23 @@ async function save() { const state = JSON.stringify(stateStore.current) setStorage('state', state) + saveContainerState() resolve(true) }, 0) }) } +function saveContainerState() { + const containerState_amend = { + initialX: containerState.x(), + initialY: containerState.y(), + scale: containerState.scale + } + + setStorage('container', JSON.stringify(containerState_amend)) +} + window.addEventListener('keydown', async event => { if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') { event.preventDefault() diff --git a/src/lib/storage.ts b/src/lib/storage.ts index 0fa8df8..ca22d81 100644 --- a/src/lib/storage.ts +++ b/src/lib/storage.ts @@ -1,6 +1,7 @@ const state = 'state' +const container = 'container' -type Key = typeof state +type Key = typeof state | typeof container export const setStorage = (key: Key, value: string) => { window.localStorage.setItem(key, value) diff --git a/src/share.ts b/src/share.ts index ad71fed..1d51002 100644 --- a/src/share.ts +++ b/src/share.ts @@ -1,3 +1,5 @@ +import { getLocalContainerState } from './lib/save' + export const initialNode: MindNode = { id: '0', value: 'CodeMind', @@ -7,17 +9,39 @@ export const initialNode: MindNode = { ] } +export const MAX_SCALE = 2 +export const MIN_SCALE = 0.5 + export const containerState = { - _x: 0, - _y: 0, + initialX: 0, + initialY: 0, + offsetX: 0, + offsetY: 0, wheelX: 0, wheelY: 0, - x() { - return this._x - this.wheelX + return this.offsetX - this.wheelX + this.initialX }, y() { - return this._y - this.wheelY + return this.offsetY - this.wheelY + this.initialY }, - scale: 1 + + scale: 1, + + ...getLocalContainerState() +} as { + initialX: number + initialY: number + offsetX: number + offsetY: number + wheelX: number + wheelY: number + x: () => number + y: () => number + scale: number +} + +export const controls = { + setScale(s: number) {}, + clearOffset() {} } diff --git a/src/styles/index.scss b/src/styles/index.scss index bf0b82e..1430f8e 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -2,7 +2,8 @@ @tailwind components; @tailwind utilities; -@import './editor'; +@import './monaco'; +@import './mind-node'; html, body, diff --git a/src/styles/mind-node.scss b/src/styles/mind-node.scss new file mode 100644 index 0000000..7acacdc --- /dev/null +++ b/src/styles/mind-node.scss @@ -0,0 +1,3 @@ +.mind-node { + @apply relative w-max shrink-0 break-all rounded-md bg-white/80 px-8 py-4 font-medium outline-2 outline-offset-2 outline-focus backdrop-blur focus:outline; +} diff --git a/src/styles/editor.scss b/src/styles/monaco.scss similarity index 100% rename from src/styles/editor.scss rename to src/styles/monaco.scss diff --git a/src/svgs/brush.svg b/src/svgs/brush.svg new file mode 100644 index 0000000..d55344d --- /dev/null +++ b/src/svgs/brush.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/svgs/center.svg b/src/svgs/center.svg new file mode 100644 index 0000000..e2e63b3 --- /dev/null +++ b/src/svgs/center.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/svgs/github.tsx b/src/svgs/github.tsx deleted file mode 100644 index 27fb1bf..0000000 --- a/src/svgs/github.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function GithubSVG(props: React.SVGProps) { - return ( - - - - ) -} diff --git a/src/svgs/zoom-in.svg b/src/svgs/zoom-in.svg new file mode 100644 index 0000000..d99962f --- /dev/null +++ b/src/svgs/zoom-in.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/svgs/zoom-out.svg b/src/svgs/zoom-out.svg new file mode 100644 index 0000000..6be47e9 --- /dev/null +++ b/src/svgs/zoom-out.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/themes/sunset/goose-1.svg b/src/themes/sunset/goose-1.svg new file mode 100644 index 0000000..434a6b6 --- /dev/null +++ b/src/themes/sunset/goose-1.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/themes/sunset/goose-2.svg b/src/themes/sunset/goose-2.svg new file mode 100644 index 0000000..683ca75 --- /dev/null +++ b/src/themes/sunset/goose-2.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/themes/sunset/islet.svg b/src/themes/sunset/islet.svg new file mode 100644 index 0000000..c6dc05d --- /dev/null +++ b/src/themes/sunset/islet.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/themes/sunset/scene.tsx b/src/themes/sunset/scene.tsx new file mode 100644 index 0000000..a84d96d --- /dev/null +++ b/src/themes/sunset/scene.tsx @@ -0,0 +1,43 @@ +import { ReactComponent as SunSVG } from './sun.svg' +import { ReactComponent as Goose1SVG } from './goose-1.svg' +import { ReactComponent as Goose2SVG } from './goose-2.svg' +import src_shallowWave from './wave-shallow.svg' +import src_deepWave from './wave-deep.svg' +import { ReactComponent as IsletSVG } from './islet.svg' + +export default function Scene() { + return ( +
+ + + + +
+
+
+
+
+
+ + +
+ ) +} diff --git a/src/themes/sunset/sun.svg b/src/themes/sunset/sun.svg new file mode 100644 index 0000000..19a08c7 --- /dev/null +++ b/src/themes/sunset/sun.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/themes/sunset/wave-deep.svg b/src/themes/sunset/wave-deep.svg new file mode 100644 index 0000000..6fb1cce --- /dev/null +++ b/src/themes/sunset/wave-deep.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/themes/sunset/wave-shallow.svg b/src/themes/sunset/wave-shallow.svg new file mode 100644 index 0000000..1bbb53a --- /dev/null +++ b/src/themes/sunset/wave-shallow.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/utils.ts b/src/utils.ts index e7b612e..d11a60e 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -26,3 +26,7 @@ export function getMonacoContent(monacoElement?: HTMLDivElement | null) { return '' } + +export function isObject(o: unknown) { + return Object.prototype.toString.call(o) === '[object Object]' +} diff --git a/tailwind.config.js b/tailwind.config.js index 6e5dc6a..3ba415a 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -10,7 +10,7 @@ export default { bg: '#FEF3E1', text: 'black', focus: '#51A8B9', - edge: '#7597E8', + edge: '#FED2CB', '#1': '#FD9886', '#2': '#51A8B9' }, diff --git a/vite.config.ts b/vite.config.ts index 804401d..f7d6be2 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,11 +1,12 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react-swc' import tsconfigPaths from 'vite-tsconfig-paths' +import svgr from 'vite-plugin-svgr' export default defineConfig({ - plugins: [react(), tsconfigPaths()], + plugins: [react(), svgr(), tsconfigPaths()], server: { - port: 2002, + port: 2222, host: '0.0.0.0' }, build: {