change to libs

This commit is contained in:
熊潇 2025-04-02 18:34:07 +08:00
parent 6d5f6f21a1
commit 62b8c787a1
22 changed files with 811 additions and 51 deletions

4
.npmrc
View File

@ -1,2 +1,4 @@
//npm.xiongxiao.me/:_authToken=${ME_NPM_TOKEN} //npm.xiongxiao.me/:_authToken=${ME_NPM_TOKEN}
//registry.npmjs.org/:_authToken=${NPM_TOKEN} //registry.npmjs.org/:_authToken=${NPM_TOKEN}
ignore-workspace-root-check=true

View File

@ -1,16 +1,18 @@
{ {
"name": "@kevisual/draw", "name": "@kevisual/draw",
"version": "0.0.1", "version": "0.0.2",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"basename": "/root/draw", "basename": "/root/draw/",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"dev:web": "cross-env WEB_DEV=true vite --mode web", "dev:web": "cross-env WEB_DEV=true vite --mode web",
"build": "vite build", "build": "vite build",
"build:css": "tailwindcss -i ./src/index.css -o ./dist/render.css --minify",
"postbuild": "pnpm build:css",
"lint": "eslint .", "lint": "eslint .",
"preview": "vite preview", "preview": "vite preview",
"pub": "envision deploy ./dist -k draw -v 0.0.1 -o root -u", "pub": "envision deploy ./dist -k draw -v 0.0.2 -o root -u",
"ev": "npm run build && npm run deploy", "ev": "npm run build && npm run deploy",
"dev:lib": "turbo run dev:lib --filter=./submodules/*" "dev:lib": "turbo run dev:lib --filter=./submodules/*"
}, },
@ -28,11 +30,13 @@
"@kevisual/mark": "link:submodules/mark", "@kevisual/mark": "link:submodules/mark",
"@kevisual/query": "0.0.15", "@kevisual/query": "0.0.15",
"@kevisual/query-mark": "workspace:*", "@kevisual/query-mark": "workspace:*",
"@kevisual/query-upload": "^0.0.1",
"@kevisual/router": "0.0.9", "@kevisual/router": "0.0.9",
"@kevisual/store": "workspace:*", "@kevisual/store": "workspace:*",
"@mui/material": "^6.4.8", "@mui/material": "^6.4.8",
"antd": "^5.24.5", "antd": "^5.24.5",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"i18next-http-backend": "^3.0.2", "i18next-http-backend": "^3.0.2",
"idb-keyval": "^6.2.1", "idb-keyval": "^6.2.1",
@ -40,8 +44,10 @@
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"lucide-react": "^0.484.0", "lucide-react": "^0.484.0",
"nanoid": "^5.1.5", "nanoid": "^5.1.5",
"nprogress": "^0.2.0",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-i18next": "^15.4.1",
"react-router": "^7.4.0", "react-router": "^7.4.0",
"react-router-dom": "^7.4.0", "react-router-dom": "^7.4.0",
"react-toastify": "^11.0.5", "react-toastify": "^11.0.5",
@ -50,9 +56,12 @@
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.23.0", "@eslint/js": "^9.23.0",
"@kevisual/types": "^0.0.6", "@kevisual/types": "^0.0.6",
"@tailwindcss/cli": "^4.1.0",
"@tailwindcss/vite": "^4.0.16", "@tailwindcss/vite": "^4.0.16",
"@types/crypto-js": "^4.2.2",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/node": "^22.13.13", "@types/node": "^22.13.13",
"@types/nprogress": "^0.2.3",
"@types/react": "^19.0.12", "@types/react": "^19.0.12",
"@types/react-dom": "^19.0.4", "@types/react-dom": "^19.0.4",
"@vitejs/plugin-basic-ssl": "^2.0.0", "@vitejs/plugin-basic-ssl": "^2.0.0",

@ -1 +1 @@
Subproject commit 62c5c2a82a2d346e27e064301a7c36c114f8512a Subproject commit a857afbb2c8f5b5f98771824e875dfffd23b6ad2

346
pnpm-lock.yaml generated
View File

@ -32,6 +32,9 @@ importers:
'@kevisual/query-mark': '@kevisual/query-mark':
specifier: workspace:* specifier: workspace:*
version: link:submodules/query-mark version: link:submodules/query-mark
'@kevisual/query-upload':
specifier: ^0.0.1
version: 0.0.1
'@kevisual/router': '@kevisual/router':
specifier: 0.0.9 specifier: 0.0.9
version: 0.0.9 version: 0.0.9
@ -47,6 +50,9 @@ importers:
clsx: clsx:
specifier: ^2.1.1 specifier: ^2.1.1
version: 2.1.1 version: 2.1.1
crypto-js:
specifier: ^4.2.0
version: 4.2.0
dayjs: dayjs:
specifier: ^1.11.13 specifier: ^1.11.13
version: 1.11.13 version: 1.11.13
@ -68,12 +74,18 @@ importers:
nanoid: nanoid:
specifier: ^5.1.5 specifier: ^5.1.5
version: 5.1.5 version: 5.1.5
nprogress:
specifier: ^0.2.0
version: 0.2.0
react: react:
specifier: ^19.0.0 specifier: ^19.0.0
version: 19.0.0 version: 19.0.0
react-dom: react-dom:
specifier: ^19.0.0 specifier: ^19.0.0
version: 19.0.0(react@19.0.0) version: 19.0.0(react@19.0.0)
react-i18next:
specifier: ^15.4.1
version: 15.4.1(i18next@24.2.3(typescript@5.8.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react-router: react-router:
specifier: ^7.4.0 specifier: ^7.4.0
version: 7.4.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) version: 7.4.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@ -93,15 +105,24 @@ importers:
'@kevisual/types': '@kevisual/types':
specifier: ^0.0.6 specifier: ^0.0.6
version: 0.0.6 version: 0.0.6
'@tailwindcss/cli':
specifier: ^4.1.0
version: 4.1.0
'@tailwindcss/vite': '@tailwindcss/vite':
specifier: ^4.0.16 specifier: ^4.0.16
version: 4.0.16(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.51.0)(yaml@2.5.1)) version: 4.0.16(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.51.0)(yaml@2.5.1))
'@types/crypto-js':
specifier: ^4.2.2
version: 4.2.2
'@types/lodash-es': '@types/lodash-es':
specifier: ^4.17.12 specifier: ^4.17.12
version: 4.17.12 version: 4.17.12
'@types/node': '@types/node':
specifier: ^22.13.13 specifier: ^22.13.13
version: 22.13.13 version: 22.13.13
'@types/nprogress':
specifier: ^0.2.3
version: 0.2.3
'@types/react': '@types/react':
specifier: ^19.0.12 specifier: ^19.0.12
version: 19.0.12 version: 19.0.12
@ -816,6 +837,9 @@ packages:
'@kevisual/components@0.0.1': '@kevisual/components@0.0.1':
resolution: {integrity: sha512-+5UD9GZLh2dcgfMVB4dHEUNC7J35NI7M4WNWQMiL7k4y9P5Q3B3AyUoLenLrD82wCvdghNUszNu99Bs7lBkV4Q==} resolution: {integrity: sha512-+5UD9GZLh2dcgfMVB4dHEUNC7J35NI7M4WNWQMiL7k4y9P5Q3B3AyUoLenLrD82wCvdghNUszNu99Bs7lBkV4Q==}
'@kevisual/query-upload@0.0.1':
resolution: {integrity: sha512-kBPdwsnFFEcYbQppNeyylYzR30NNWuhF3PsTfBCzVyokkeJsZ0T+Tp+ikt2FXvE+Fc7Qd/C/kIbiHSBYePgwRQ==}
'@kevisual/query@0.0.15': '@kevisual/query@0.0.15':
resolution: {integrity: sha512-DK41qvyOiJMmlj70QyVP/48M0gszA39DdnBLtgU94YwAe6OqKrr9tYXHLjZrOROmUVMezIIBQuWMLedSAvb54A==} resolution: {integrity: sha512-DK41qvyOiJMmlj70QyVP/48M0gszA39DdnBLtgU94YwAe6OqKrr9tYXHLjZrOROmUVMezIIBQuWMLedSAvb54A==}
@ -930,6 +954,88 @@ packages:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
'@parcel/watcher-android-arm64@2.5.1':
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [android]
'@parcel/watcher-darwin-arm64@2.5.1':
resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [darwin]
'@parcel/watcher-darwin-x64@2.5.1':
resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [darwin]
'@parcel/watcher-freebsd-x64@2.5.1':
resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [freebsd]
'@parcel/watcher-linux-arm-glibc@2.5.1':
resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
'@parcel/watcher-linux-arm-musl@2.5.1':
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
'@parcel/watcher-linux-arm64-glibc@2.5.1':
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
'@parcel/watcher-linux-arm64-musl@2.5.1':
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
'@parcel/watcher-linux-x64-glibc@2.5.1':
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
'@parcel/watcher-linux-x64-musl@2.5.1':
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
'@parcel/watcher-win32-arm64@2.5.1':
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [win32]
'@parcel/watcher-win32-ia32@2.5.1':
resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==}
engines: {node: '>= 10.0.0'}
cpu: [ia32]
os: [win32]
'@parcel/watcher-win32-x64@2.5.1':
resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [win32]
'@parcel/watcher@2.5.1':
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
engines: {node: '>= 10.0.0'}
'@pkgjs/parseargs@0.11.0': '@pkgjs/parseargs@0.11.0':
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'} engines: {node: '>=14'}
@ -1442,12 +1548,19 @@ packages:
'@rushstack/ts-command-line@4.23.7': '@rushstack/ts-command-line@4.23.7':
resolution: {integrity: sha512-Gr9cB7DGe6uz5vq2wdr89WbVDKz0UeuFEn5H2CfWDe7JvjFFaiV15gi6mqDBTbHhHCWS7w8mF1h3BnIfUndqdA==} resolution: {integrity: sha512-Gr9cB7DGe6uz5vq2wdr89WbVDKz0UeuFEn5H2CfWDe7JvjFFaiV15gi6mqDBTbHhHCWS7w8mF1h3BnIfUndqdA==}
'@tailwindcss/cli@4.1.0':
resolution: {integrity: sha512-r3coRYp4Rp00L85gwIb4AKqSX7hJ8IwvD7ENQLP8/AlBiP0tcgNy6gAQJD57ERuJljco2dstadP7kMyllzBaSw==}
hasBin: true
'@tailwindcss/node@4.0.16': '@tailwindcss/node@4.0.16':
resolution: {integrity: sha512-T6IK79hoCFScxD5tRxWMtwqwSs4sT81Vw+YbzL7RZD0/Ndm4y5kboV7LdQ97YGH6udoOZyVT/uEfrnU2L5Nkog==} resolution: {integrity: sha512-T6IK79hoCFScxD5tRxWMtwqwSs4sT81Vw+YbzL7RZD0/Ndm4y5kboV7LdQ97YGH6udoOZyVT/uEfrnU2L5Nkog==}
'@tailwindcss/node@4.0.17': '@tailwindcss/node@4.0.17':
resolution: {integrity: sha512-LIdNwcqyY7578VpofXyqjH6f+3fP4nrz7FBLki5HpzqjYfXdF2m/eW18ZfoKePtDGg90Bvvfpov9d2gy5XVCbg==} resolution: {integrity: sha512-LIdNwcqyY7578VpofXyqjH6f+3fP4nrz7FBLki5HpzqjYfXdF2m/eW18ZfoKePtDGg90Bvvfpov9d2gy5XVCbg==}
'@tailwindcss/node@4.1.0':
resolution: {integrity: sha512-mfgxGxFaxbsUbaGwKIAQXUSm7Qoojw53FftpoKwo4ANwr9wnDaByz4vi1gMti/xfJvmQ5lzA1DvPiX5yCHtBkQ==}
'@tailwindcss/oxide-android-arm64@4.0.16': '@tailwindcss/oxide-android-arm64@4.0.16':
resolution: {integrity: sha512-mieEZrNLHatpQu6ad0pWBnL8ObUE9ZSe4eoX6GKTqsKv98AxNw5lUa5nJM0FgD8rYJeZ2dPtHNN/YM2xY9R+9g==} resolution: {integrity: sha512-mieEZrNLHatpQu6ad0pWBnL8ObUE9ZSe4eoX6GKTqsKv98AxNw5lUa5nJM0FgD8rYJeZ2dPtHNN/YM2xY9R+9g==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -1460,6 +1573,12 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@tailwindcss/oxide-android-arm64@4.1.0':
resolution: {integrity: sha512-UredFljuHey2Kh5qyYfQVBr0Xfq70ZE5Df6i5IubNYQGs2JXXT4VL0SIUjwzHx5W9T6t7dT7banunlV6lthGPQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [android]
'@tailwindcss/oxide-darwin-arm64@4.0.16': '@tailwindcss/oxide-darwin-arm64@4.0.16':
resolution: {integrity: sha512-pfilSvgrX5UDdjh09gGVMhAPfZVucm4AnwFBkwBe6WFl7gzMAZ92/35GC0yMDeS+W+RNSXclXJz+HamF1iS/aA==} resolution: {integrity: sha512-pfilSvgrX5UDdjh09gGVMhAPfZVucm4AnwFBkwBe6WFl7gzMAZ92/35GC0yMDeS+W+RNSXclXJz+HamF1iS/aA==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -1472,6 +1591,12 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@tailwindcss/oxide-darwin-arm64@4.1.0':
resolution: {integrity: sha512-QHQ/46lRVwH9zEBNiRk8AJ3Af4pMq6DuZAI//q323qrPOXjsRdrhLsH9LUO3mqBfHr5EZNUxN3Am5vpO89sntw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
'@tailwindcss/oxide-darwin-x64@4.0.16': '@tailwindcss/oxide-darwin-x64@4.0.16':
resolution: {integrity: sha512-Z3lJY3yUjlHbzgXwWH9Y6IGeSGXfwjbXuvTPolyJUGMZl2ZaHdQMPOZ8dMll1knSLjctOif+QijMab0+GSXYLQ==} resolution: {integrity: sha512-Z3lJY3yUjlHbzgXwWH9Y6IGeSGXfwjbXuvTPolyJUGMZl2ZaHdQMPOZ8dMll1knSLjctOif+QijMab0+GSXYLQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -1484,6 +1609,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@tailwindcss/oxide-darwin-x64@4.1.0':
resolution: {integrity: sha512-lEMgYHCvQQ6x2KOZ4FwnPprwfnc+UnjzwXRqEYIhB/NlYvXQD1QMf7oKEDRqy94DiZaYox9ZRfG2YJOBgM0UkA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
'@tailwindcss/oxide-freebsd-x64@4.0.16': '@tailwindcss/oxide-freebsd-x64@4.0.16':
resolution: {integrity: sha512-dv2U8Yc7vKIDyiJkUouhjsl+dTfRImNyZRCTFsHvvrhJvenYZBRtE/wDSYlZHR0lWKhIocxk1ScAkAcMR3F3QQ==} resolution: {integrity: sha512-dv2U8Yc7vKIDyiJkUouhjsl+dTfRImNyZRCTFsHvvrhJvenYZBRtE/wDSYlZHR0lWKhIocxk1ScAkAcMR3F3QQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -1496,6 +1627,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@tailwindcss/oxide-freebsd-x64@4.1.0':
resolution: {integrity: sha512-9fdImTc+2lA5yHqJ61oeTXfCtzylNOzJVFhyWwVQAJESJJbVCPnj6f+b+Zf/AYAdKQfS6FCThbPEahkQrDCgLQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [freebsd]
'@tailwindcss/oxide-linux-arm-gnueabihf@4.0.16': '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.16':
resolution: {integrity: sha512-XBRXyUUyjMg5UMiyuQxJqWSs27w0V49g1iPuhrFakmu1/idDSly59XYteRrI2onoS9AzmMwfyzdiQSJXM89+PQ==} resolution: {integrity: sha512-XBRXyUUyjMg5UMiyuQxJqWSs27w0V49g1iPuhrFakmu1/idDSly59XYteRrI2onoS9AzmMwfyzdiQSJXM89+PQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -1508,6 +1645,12 @@ packages:
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.0':
resolution: {integrity: sha512-HB0bTkUOuTLLSdadyRhKE9yps4/ZBjrojbHTPMSvvf/8yBLZRPpWb+A6IgW5R+2A2AL4KhVPgLwWfoXsErxJFg==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
'@tailwindcss/oxide-linux-arm64-gnu@4.0.16': '@tailwindcss/oxide-linux-arm64-gnu@4.0.16':
resolution: {integrity: sha512-+bL1zkU8MDzv389OqyI0SJbrG9kGsdxf+k2ZAILlw1TPWg5oeMkwoqgaQRqGwpOHz0pycT94qIgWVNJavAz+Iw==} resolution: {integrity: sha512-+bL1zkU8MDzv389OqyI0SJbrG9kGsdxf+k2ZAILlw1TPWg5oeMkwoqgaQRqGwpOHz0pycT94qIgWVNJavAz+Iw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -1520,6 +1663,12 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@tailwindcss/oxide-linux-arm64-gnu@4.1.0':
resolution: {integrity: sha512-+QtYCwvKLjC46h6RikKkpELJWrpiMMtgyK0aaqhwPLEx1icGgIhwz8dqrkAiqbFRE0KiRrE2aenhYoEkplyRmA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@tailwindcss/oxide-linux-arm64-musl@4.0.16': '@tailwindcss/oxide-linux-arm64-musl@4.0.16':
resolution: {integrity: sha512-Uqfnyx9oFxoX+/iy9pIDTADHLLNwuZNB8QSp+BwKAhtHjBTTYmDAdxKy3u8lJZve1aOd+S145eWpn3tT08cm4w==} resolution: {integrity: sha512-Uqfnyx9oFxoX+/iy9pIDTADHLLNwuZNB8QSp+BwKAhtHjBTTYmDAdxKy3u8lJZve1aOd+S145eWpn3tT08cm4w==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -1532,6 +1681,12 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@tailwindcss/oxide-linux-arm64-musl@4.1.0':
resolution: {integrity: sha512-nApadFKM9GauzuPZPlt6TKfELavMHqJ0gVd+GYkYBTwr2t9KhgCAb2sKiFDDIhs1a7gOjsU7P1lEauv3iKFp+Q==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@tailwindcss/oxide-linux-x64-gnu@4.0.16': '@tailwindcss/oxide-linux-x64-gnu@4.0.16':
resolution: {integrity: sha512-v0Hx0KD94F6FG0IW3AJyCzQepSv/47xhShCgiWJ2TNVu406VtREkGpJtxS0Gu1ecSXhgn/36LToU5kivAuQiPg==} resolution: {integrity: sha512-v0Hx0KD94F6FG0IW3AJyCzQepSv/47xhShCgiWJ2TNVu406VtREkGpJtxS0Gu1ecSXhgn/36LToU5kivAuQiPg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -1544,6 +1699,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@tailwindcss/oxide-linux-x64-gnu@4.1.0':
resolution: {integrity: sha512-cp0Rf9Wit2kZHhrV8HIoDFD8dxU2+ZTCFCFbDj3a07pGyyPwLCJm5H5VipKXgYrBaLmlYu73ERidW0S5sdEXEg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@tailwindcss/oxide-linux-x64-musl@4.0.16': '@tailwindcss/oxide-linux-x64-musl@4.0.16':
resolution: {integrity: sha512-CjV6hhQAVNYw6W2EXp1ZVL81CTSBEh6nTmS5EZq5rdEhqOx8G8YQtFKjcCJiojsS+vMXt9r87gGoORJcHOA0lg==} resolution: {integrity: sha512-CjV6hhQAVNYw6W2EXp1ZVL81CTSBEh6nTmS5EZq5rdEhqOx8G8YQtFKjcCJiojsS+vMXt9r87gGoORJcHOA0lg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -1556,6 +1717,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@tailwindcss/oxide-linux-x64-musl@4.1.0':
resolution: {integrity: sha512-4/wf42XWBJGXsOS6BhgPhdQbg/qyfdZ1nZvTL9sJoxYN+Ah+cfY5Dd7R0smzI8hmgCRt3TD1lYb72ChTyIA59w==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@tailwindcss/oxide-win32-arm64-msvc@4.0.16': '@tailwindcss/oxide-win32-arm64-msvc@4.0.16':
resolution: {integrity: sha512-Pj9eaAtXYH7NrvVx8Jx0U/sEaNpcIbb8d+2WnC8a+xL0LfIXWsu4AyeRUeTeb8Ty4fTGhKSJTohdXj1iSdN9WQ==} resolution: {integrity: sha512-Pj9eaAtXYH7NrvVx8Jx0U/sEaNpcIbb8d+2WnC8a+xL0LfIXWsu4AyeRUeTeb8Ty4fTGhKSJTohdXj1iSdN9WQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -1568,6 +1735,12 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@tailwindcss/oxide-win32-arm64-msvc@4.1.0':
resolution: {integrity: sha512-caXJJ0G6NwGbcoxEYdH3MZYN84C3PldaMdAEPMU6bjJXURQlKdSlQ/Ecis7/nSgBkMkicZyhqWmb36Tw/BFSIw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
'@tailwindcss/oxide-win32-x64-msvc@4.0.16': '@tailwindcss/oxide-win32-x64-msvc@4.0.16':
resolution: {integrity: sha512-M35hoFrhJe+1QdSiZpn85y8K7tfEVw6lswv3TjIfJ44JiPjPzZ4URg+rsTjTq0kue6NjNCbbY99AsRSSpJZxOw==} resolution: {integrity: sha512-M35hoFrhJe+1QdSiZpn85y8K7tfEVw6lswv3TjIfJ44JiPjPzZ4URg+rsTjTq0kue6NjNCbbY99AsRSSpJZxOw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -1580,6 +1753,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@tailwindcss/oxide-win32-x64-msvc@4.1.0':
resolution: {integrity: sha512-ZHXRXRxB7HBmkUE8U13nmkGGYfR1I2vsuhiYjeDDUFIYpk1BL6caU8hvzkSlL/X5CAQNdIUUJRGom5I0ZyfJOA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
'@tailwindcss/oxide@4.0.16': '@tailwindcss/oxide@4.0.16':
resolution: {integrity: sha512-n++F8Rzvo/e+FYxikZgKW4sCRXneSstLhTI91Ay9toeRcE/+WO33SQWzGtgmjWJcTupXZreskJ8FCr9b+kdXew==} resolution: {integrity: sha512-n++F8Rzvo/e+FYxikZgKW4sCRXneSstLhTI91Ay9toeRcE/+WO33SQWzGtgmjWJcTupXZreskJ8FCr9b+kdXew==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
@ -1588,6 +1767,10 @@ packages:
resolution: {integrity: sha512-B4OaUIRD2uVrULpAD1Yksx2+wNarQr2rQh65nXqaqbLY1jCd8fO+3KLh/+TH4Hzh2NTHQvgxVbPdUDOtLk7vAw==} resolution: {integrity: sha512-B4OaUIRD2uVrULpAD1Yksx2+wNarQr2rQh65nXqaqbLY1jCd8fO+3KLh/+TH4Hzh2NTHQvgxVbPdUDOtLk7vAw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
'@tailwindcss/oxide@4.1.0':
resolution: {integrity: sha512-A33oyZKpPFH08d7xkl13Dc8OTsbPhsuls0z9gUCxIHvn8c1BsUACddQxL6HwaeJR1fSYyXZUw8bdWcD8bVawpQ==}
engines: {node: '>= 10'}
'@tailwindcss/vite@4.0.16': '@tailwindcss/vite@4.0.16':
resolution: {integrity: sha512-6mZVWhAyjVNMMRw0Pvv2RZfTttjsAClU8HouLNZbeLbX0yURMa0UYEY/qS4dB1tZlRpiDBnCLsGsWbxEyIjW6A==} resolution: {integrity: sha512-6mZVWhAyjVNMMRw0Pvv2RZfTttjsAClU8HouLNZbeLbX0yURMa0UYEY/qS4dB1tZlRpiDBnCLsGsWbxEyIjW6A==}
peerDependencies: peerDependencies:
@ -1628,6 +1811,9 @@ packages:
'@types/cookie@0.6.0': '@types/cookie@0.6.0':
resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==}
'@types/crypto-js@4.2.2':
resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==}
'@types/d3-scale-chromatic@3.1.0': '@types/d3-scale-chromatic@3.1.0':
resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==}
@ -1673,6 +1859,9 @@ packages:
'@types/node@22.13.14': '@types/node@22.13.14':
resolution: {integrity: sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==} resolution: {integrity: sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==}
'@types/nprogress@0.2.3':
resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==}
'@types/parse-json@4.0.2': '@types/parse-json@4.0.2':
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
@ -2044,6 +2233,9 @@ packages:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
crypto-js@4.2.0:
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
csstype@3.1.3: csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
@ -2243,6 +2435,11 @@ packages:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'} engines: {node: '>=6'}
detect-libc@1.0.3:
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
engines: {node: '>=0.10'}
hasBin: true
detect-libc@2.0.3: detect-libc@2.0.3:
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -3023,6 +3220,9 @@ packages:
natural-compare@1.4.0: natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
node-domexception@1.0.0: node-domexception@1.0.0:
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
engines: {node: '>=10.5.0'} engines: {node: '>=10.5.0'}
@ -3050,6 +3250,9 @@ packages:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
nprogress@0.2.0:
resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==}
object-assign@4.1.1: object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -3738,6 +3941,9 @@ packages:
tailwindcss@4.0.17: tailwindcss@4.0.17:
resolution: {integrity: sha512-OErSiGzRa6rLiOvaipsDZvLMSpsBZ4ysB4f0VKGXUrjw2jfkJRd6kjRKV2+ZmTCNvwtvgdDam5D7w6WXsdLJZw==} resolution: {integrity: sha512-OErSiGzRa6rLiOvaipsDZvLMSpsBZ4ysB4f0VKGXUrjw2jfkJRd6kjRKV2+ZmTCNvwtvgdDam5D7w6WXsdLJZw==}
tailwindcss@4.1.0:
resolution: {integrity: sha512-vBYstoFnvUZCDxaauNGQQEvJNQgCd1vSMDRYuZZMH1xRRcTboOk1rJrW5yFkEabU9X6Yx1C4LQ+QvPOvQj4Daw==}
tapable@2.2.1: tapable@2.2.1:
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -4649,6 +4855,8 @@ snapshots:
- '@types/react' - '@types/react'
- supports-color - supports-color
'@kevisual/query-upload@0.0.1': {}
'@kevisual/query@0.0.15(ws@8.18.0)': '@kevisual/query@0.0.15(ws@8.18.0)':
dependencies: dependencies:
openai: 4.89.0(ws@8.18.0) openai: 4.89.0(ws@8.18.0)
@ -4820,6 +5028,66 @@ snapshots:
'@nodelib/fs.scandir': 2.1.5 '@nodelib/fs.scandir': 2.1.5
fastq: 1.17.1 fastq: 1.17.1
'@parcel/watcher-android-arm64@2.5.1':
optional: true
'@parcel/watcher-darwin-arm64@2.5.1':
optional: true
'@parcel/watcher-darwin-x64@2.5.1':
optional: true
'@parcel/watcher-freebsd-x64@2.5.1':
optional: true
'@parcel/watcher-linux-arm-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-arm-musl@2.5.1':
optional: true
'@parcel/watcher-linux-arm64-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-arm64-musl@2.5.1':
optional: true
'@parcel/watcher-linux-x64-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-x64-musl@2.5.1':
optional: true
'@parcel/watcher-win32-arm64@2.5.1':
optional: true
'@parcel/watcher-win32-ia32@2.5.1':
optional: true
'@parcel/watcher-win32-x64@2.5.1':
optional: true
'@parcel/watcher@2.5.1':
dependencies:
detect-libc: 1.0.3
is-glob: 4.0.3
micromatch: 4.0.8
node-addon-api: 7.1.1
optionalDependencies:
'@parcel/watcher-android-arm64': 2.5.1
'@parcel/watcher-darwin-arm64': 2.5.1
'@parcel/watcher-darwin-x64': 2.5.1
'@parcel/watcher-freebsd-x64': 2.5.1
'@parcel/watcher-linux-arm-glibc': 2.5.1
'@parcel/watcher-linux-arm-musl': 2.5.1
'@parcel/watcher-linux-arm64-glibc': 2.5.1
'@parcel/watcher-linux-arm64-musl': 2.5.1
'@parcel/watcher-linux-x64-glibc': 2.5.1
'@parcel/watcher-linux-x64-musl': 2.5.1
'@parcel/watcher-win32-arm64': 2.5.1
'@parcel/watcher-win32-ia32': 2.5.1
'@parcel/watcher-win32-x64': 2.5.1
'@pkgjs/parseargs@0.11.0': '@pkgjs/parseargs@0.11.0':
optional: true optional: true
@ -5345,6 +5613,16 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- '@types/node' - '@types/node'
'@tailwindcss/cli@4.1.0':
dependencies:
'@parcel/watcher': 2.5.1
'@tailwindcss/node': 4.1.0
'@tailwindcss/oxide': 4.1.0
enhanced-resolve: 5.18.1
mri: 1.2.0
picocolors: 1.1.1
tailwindcss: 4.1.0
'@tailwindcss/node@4.0.16': '@tailwindcss/node@4.0.16':
dependencies: dependencies:
enhanced-resolve: 5.18.1 enhanced-resolve: 5.18.1
@ -5357,72 +5635,112 @@ snapshots:
jiti: 2.4.2 jiti: 2.4.2
tailwindcss: 4.0.17 tailwindcss: 4.0.17
'@tailwindcss/node@4.1.0':
dependencies:
enhanced-resolve: 5.18.1
jiti: 2.4.2
lightningcss: 1.29.2
tailwindcss: 4.1.0
'@tailwindcss/oxide-android-arm64@4.0.16': '@tailwindcss/oxide-android-arm64@4.0.16':
optional: true optional: true
'@tailwindcss/oxide-android-arm64@4.0.17': '@tailwindcss/oxide-android-arm64@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-android-arm64@4.1.0':
optional: true
'@tailwindcss/oxide-darwin-arm64@4.0.16': '@tailwindcss/oxide-darwin-arm64@4.0.16':
optional: true optional: true
'@tailwindcss/oxide-darwin-arm64@4.0.17': '@tailwindcss/oxide-darwin-arm64@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-darwin-arm64@4.1.0':
optional: true
'@tailwindcss/oxide-darwin-x64@4.0.16': '@tailwindcss/oxide-darwin-x64@4.0.16':
optional: true optional: true
'@tailwindcss/oxide-darwin-x64@4.0.17': '@tailwindcss/oxide-darwin-x64@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-darwin-x64@4.1.0':
optional: true
'@tailwindcss/oxide-freebsd-x64@4.0.16': '@tailwindcss/oxide-freebsd-x64@4.0.16':
optional: true optional: true
'@tailwindcss/oxide-freebsd-x64@4.0.17': '@tailwindcss/oxide-freebsd-x64@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-freebsd-x64@4.1.0':
optional: true
'@tailwindcss/oxide-linux-arm-gnueabihf@4.0.16': '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.16':
optional: true optional: true
'@tailwindcss/oxide-linux-arm-gnueabihf@4.0.17': '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.0':
optional: true
'@tailwindcss/oxide-linux-arm64-gnu@4.0.16': '@tailwindcss/oxide-linux-arm64-gnu@4.0.16':
optional: true optional: true
'@tailwindcss/oxide-linux-arm64-gnu@4.0.17': '@tailwindcss/oxide-linux-arm64-gnu@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-linux-arm64-gnu@4.1.0':
optional: true
'@tailwindcss/oxide-linux-arm64-musl@4.0.16': '@tailwindcss/oxide-linux-arm64-musl@4.0.16':
optional: true optional: true
'@tailwindcss/oxide-linux-arm64-musl@4.0.17': '@tailwindcss/oxide-linux-arm64-musl@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-linux-arm64-musl@4.1.0':
optional: true
'@tailwindcss/oxide-linux-x64-gnu@4.0.16': '@tailwindcss/oxide-linux-x64-gnu@4.0.16':
optional: true optional: true
'@tailwindcss/oxide-linux-x64-gnu@4.0.17': '@tailwindcss/oxide-linux-x64-gnu@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-linux-x64-gnu@4.1.0':
optional: true
'@tailwindcss/oxide-linux-x64-musl@4.0.16': '@tailwindcss/oxide-linux-x64-musl@4.0.16':
optional: true optional: true
'@tailwindcss/oxide-linux-x64-musl@4.0.17': '@tailwindcss/oxide-linux-x64-musl@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-linux-x64-musl@4.1.0':
optional: true
'@tailwindcss/oxide-win32-arm64-msvc@4.0.16': '@tailwindcss/oxide-win32-arm64-msvc@4.0.16':
optional: true optional: true
'@tailwindcss/oxide-win32-arm64-msvc@4.0.17': '@tailwindcss/oxide-win32-arm64-msvc@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-win32-arm64-msvc@4.1.0':
optional: true
'@tailwindcss/oxide-win32-x64-msvc@4.0.16': '@tailwindcss/oxide-win32-x64-msvc@4.0.16':
optional: true optional: true
'@tailwindcss/oxide-win32-x64-msvc@4.0.17': '@tailwindcss/oxide-win32-x64-msvc@4.0.17':
optional: true optional: true
'@tailwindcss/oxide-win32-x64-msvc@4.1.0':
optional: true
'@tailwindcss/oxide@4.0.16': '@tailwindcss/oxide@4.0.16':
optionalDependencies: optionalDependencies:
'@tailwindcss/oxide-android-arm64': 4.0.16 '@tailwindcss/oxide-android-arm64': 4.0.16
@ -5451,6 +5769,20 @@ snapshots:
'@tailwindcss/oxide-win32-arm64-msvc': 4.0.17 '@tailwindcss/oxide-win32-arm64-msvc': 4.0.17
'@tailwindcss/oxide-win32-x64-msvc': 4.0.17 '@tailwindcss/oxide-win32-x64-msvc': 4.0.17
'@tailwindcss/oxide@4.1.0':
optionalDependencies:
'@tailwindcss/oxide-android-arm64': 4.1.0
'@tailwindcss/oxide-darwin-arm64': 4.1.0
'@tailwindcss/oxide-darwin-x64': 4.1.0
'@tailwindcss/oxide-freebsd-x64': 4.1.0
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.0
'@tailwindcss/oxide-linux-arm64-gnu': 4.1.0
'@tailwindcss/oxide-linux-arm64-musl': 4.1.0
'@tailwindcss/oxide-linux-x64-gnu': 4.1.0
'@tailwindcss/oxide-linux-x64-musl': 4.1.0
'@tailwindcss/oxide-win32-arm64-msvc': 4.1.0
'@tailwindcss/oxide-win32-x64-msvc': 4.1.0
'@tailwindcss/vite@4.0.16(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.51.0)(yaml@2.5.1))': '@tailwindcss/vite@4.0.16(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.51.0)(yaml@2.5.1))':
dependencies: dependencies:
'@tailwindcss/node': 4.0.16 '@tailwindcss/node': 4.0.16
@ -5500,6 +5832,8 @@ snapshots:
'@types/cookie@0.6.0': {} '@types/cookie@0.6.0': {}
'@types/crypto-js@4.2.2': {}
'@types/d3-scale-chromatic@3.1.0': {} '@types/d3-scale-chromatic@3.1.0': {}
'@types/d3-scale@4.0.9': '@types/d3-scale@4.0.9':
@ -5549,6 +5883,8 @@ snapshots:
dependencies: dependencies:
undici-types: 6.20.0 undici-types: 6.20.0
'@types/nprogress@0.2.3': {}
'@types/parse-json@4.0.2': {} '@types/parse-json@4.0.2': {}
'@types/prop-types@15.7.14': {} '@types/prop-types@15.7.14': {}
@ -6006,6 +6342,8 @@ snapshots:
shebang-command: 2.0.0 shebang-command: 2.0.0
which: 2.0.2 which: 2.0.2
crypto-js@4.2.0: {}
csstype@3.1.3: {} csstype@3.1.3: {}
cytoscape-cose-bilkent@4.1.0(cytoscape@3.31.1): cytoscape-cose-bilkent@4.1.0(cytoscape@3.31.1):
@ -6215,6 +6553,8 @@ snapshots:
dequal@2.0.3: {} dequal@2.0.3: {}
detect-libc@1.0.3: {}
detect-libc@2.0.3: {} detect-libc@2.0.3: {}
detect-node-es@1.1.0: {} detect-node-es@1.1.0: {}
@ -7038,6 +7378,8 @@ snapshots:
natural-compare@1.4.0: {} natural-compare@1.4.0: {}
node-addon-api@7.1.1: {}
node-domexception@1.0.0: {} node-domexception@1.0.0: {}
node-fetch@2.7.0: node-fetch@2.7.0:
@ -7052,6 +7394,8 @@ snapshots:
normalize-path@3.0.0: {} normalize-path@3.0.0: {}
nprogress@0.2.0: {}
object-assign@4.1.1: {} object-assign@4.1.1: {}
open-color@1.9.1: {} open-color@1.9.1: {}
@ -7797,6 +8141,8 @@ snapshots:
tailwindcss@4.0.17: {} tailwindcss@4.0.17: {}
tailwindcss@4.1.0: {}
tapable@2.2.1: {} tapable@2.2.1: {}
thenify-all@1.6.0: thenify-all@1.6.0:

38
public/demo.html Normal file
View File

@ -0,0 +1,38 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Excalidraw</title>
<style>
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#root {
width: 100%;
height: 100%;
}
</style>
<link rel="stylesheet" crossorigin href="./render.css">
</head>
<body>
<div id="root"></div>
<script type="module">
import { render } from './render.js';
console.log('render', render);
const opts = {
renderRoot: document.getElementById('root'),
}
render(opts);
</script>
</body>
</html>

38
public/index.html Normal file
View File

@ -0,0 +1,38 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Excalidraw</title>
<style>
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#root {
width: 100%;
height: 100%;
}
</style>
<link rel="stylesheet" crossorigin href="./render.css">
</head>
<body>
<div id="root"></div>
<script type="module">
import { render } from './render.js';
console.log('render', render);
const opts = {
renderRoot: document.getElementById('root'),
}
render(opts);
</script>
</body>
</html>

View File

@ -9,5 +9,6 @@
"title": "Title", "title": "Title",
"thumbnail": "Thumbnail", "thumbnail": "Thumbnail",
"save": "Save", "save": "Save",
"editMarkSuccess": "Edit Mark Success" "editMarkSuccess": "Edit Mark Success",
"deleteMarkSuccess": "Delete Mark Success"
} }

View File

@ -9,5 +9,6 @@
"title": "标题", "title": "标题",
"thumbnail": "缩略图", "thumbnail": "缩略图",
"save": "保存", "save": "保存",
"editMarkSuccess": "编辑成功" "editMarkSuccess": "编辑成功",
"deleteMarkSuccess": "删除成功"
} }

View File

@ -5,7 +5,6 @@ import { Draw } from './pages/Draw';
// import { App as Manager } from './manager/Manager'; // import { App as Manager } from './manager/Manager';
import { Manager } from '@kevisual/mark/src/Module'; import { Manager } from '@kevisual/mark/src/Module';
console.log('basename', basename);
export const App = () => { export const App = () => {
const [id, setId] = useState(''); const [id, setId] = useState('');
useEffect(() => { useEffect(() => {
@ -15,7 +14,7 @@ export const App = () => {
} }
}, []); }, []);
return ( return (
<div className='bg-slate-200 w-full h-full flex'> <div className='bg-white w-full h-full flex'>
<Manager <Manager
showSearch={true} showSearch={true}
showAdd={true} showAdd={true}
@ -44,7 +43,9 @@ export const App = () => {
}} }}
/> />
) : ( ) : (
<div></div> <div className='flex items-center justify-center h-full text-gray-500'>
{/* 请选择一个画布 */}
</div>
)} )}
</div> </div>
</Manager> </Manager>

22
src/Bootstrap.tsx Normal file
View File

@ -0,0 +1,22 @@
import { createRoot } from 'react-dom/client';
import { App } from './App.tsx';
import { ToastContainer } from 'react-toastify';
import { I18NextProvider, initI18n } from '@kevisual/components/translate/index.tsx';
import { basename } from './modules/basename';
export const Bootstrap = (element: HTMLElement) => {
createRoot(element).render(
<>
<I18NextProvider basename={'/root/locales'} noUse={false}>
<App />
</I18NextProvider>
<ToastContainer />
</>,
);
};
type RenderProps = {
renderRoot: HTMLElement;
};
export const render = ({ renderRoot }: RenderProps) => {
Bootstrap(renderRoot);
};

File diff suppressed because one or more lines are too long

View File

@ -1,17 +1,7 @@
@import 'tailwindcss'; @import 'tailwindcss';
@import '@kevisual/components/theme/wind-theme.css'; @import '@kevisual/components/theme/wind-theme.css';
/* .sidebar-trigger__label-element { @import 'nprogress/nprogress.css';
display: none; /* @import '@excalidraw/excalidraw/dist/prod/index.css'; */
} */ @import './assets/excalidraw.css';
.HelpDialog__btn[href='https://plus.excalidraw.com/blog'] {
display: none;
}
.HelpDialog__btn[href='https://youtube.com/@excalidraw'] {
display: none;
}
/* .Excalidraw__loading {
display: none;
} */

8
src/libs.ts Normal file
View File

@ -0,0 +1,8 @@
import { Bootstrap } from './Bootstrap';
type RenderProps = {
renderRoot: HTMLElement;
};
export const render = ({ renderRoot }: RenderProps) => {
Bootstrap(renderRoot);
};

View File

@ -1,15 +1,4 @@
import { createRoot } from 'react-dom/client'; import { render } from './Bootstrap';
import { App } from './App.tsx';
import { ToastContainer } from 'react-toastify';
import './index.css'; import './index.css';
import { I18NextProvider, initI18n } from '@kevisual/components/translate/index.tsx'; // import '@excalidraw/excalidraw/index.css';
import { basename } from './modules/basename'; render({ renderRoot: document.getElementById('root')! });
createRoot(document.getElementById('root')!).render(
<>
<I18NextProvider basename={basename} noUse={false}>
<App />
</I18NextProvider>
<ToastContainer />
</>,
);

View File

@ -0,0 +1,42 @@
import { toast } from 'react-toastify';
import { useTranslation } from 'react-i18next';
// Custom message component
const LoginMessage = (props: ToastLoginProps) => {
const { t } = useTranslation();
const handleClick = () => {
const currentUrl = window.location.href;
const redirect = encodeURIComponent(props?.redirectUrl || currentUrl);
const loginUrl = props?.loginUrl || '/user/login/';
const newUrl = location.origin + loginUrl + '?redirect=' + redirect;
window.open(newUrl, '_self');
};
return (
<div className='msg-container' onClick={handleClick} style={{ cursor: 'pointer' }}>
<p className='msg-title'>{t('Please login')}</p>
<p className='msg-description'>{t('Click here to go to the login page.')}</p>
</div>
);
};
type ToastLoginProps = {
/**
* , /user/login
*/
loginUrl?: string;
/**
* ,
*/
redirectUrl?: string;
};
/**
*
* @param props
* @example
* toastLogin({
* loginUrl: '/user/login/',
* redirectUrl: window.location.href,
* });
*/
export const toastLogin = (props: ToastLoginProps = {}) => {
toast.info(<LoginMessage {...props} />);
};

32
src/modules/hash-file.ts Normal file
View File

@ -0,0 +1,32 @@
import MD5 from 'crypto-js/md5';
export const hashFile = (file: File): Promise<string> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = async (event) => {
try {
const content = event.target?.result;
if (content instanceof ArrayBuffer) {
const contentString = new TextDecoder().decode(content);
const hashHex = MD5(contentString).toString();
resolve(hashHex);
} else if (typeof content === 'string') {
const hashHex = MD5(content).toString();
resolve(hashHex);
} else {
throw new Error('Invalid content type');
}
} catch (error) {
console.error('hashFile error', error);
reject(error);
}
};
reader.onerror = (error) => {
reject(error);
};
// 读取文件为 ArrayBuffer
reader.readAsArrayBuffer(file);
});
};

112
src/modules/to-file.ts Normal file
View File

@ -0,0 +1,112 @@
const getFileExtension = (filename: string) => {
return filename.split('.').pop();
};
const getFileType = (extension: string) => {
switch (extension) {
case 'js':
return 'text/javascript';
case 'css':
return 'text/css';
case 'html':
return 'text/html';
case 'json':
return 'application/json';
case 'png':
return 'image/png';
case 'jpg':
return 'image/jpeg';
case 'jpeg':
return 'image/jpeg';
case 'gif':
return 'image/gif';
case 'svg':
return 'image/svg+xml';
case 'webp':
return 'image/webp';
case 'ico':
return 'image/x-icon';
default:
return 'text/plain';
}
};
const checkIsBase64 = (content: string) => {
return content.startsWith('data:');
};
/**
*
* @param filename
* @returns
*/
export const getDirectoryAndName = (filename: string) => {
if (!filename) {
return null;
}
if (filename.startsWith('.')) {
return null;
} else {
filename = filename.replace(/^\/+/, ''); // Remove all leading slashes
}
const hasDirectory = filename.includes('/');
if (!hasDirectory) {
return { directory: '', name: filename };
}
const parts = filename.split('/');
const name = parts.pop()!; // Get the last part as the file name
const directory = parts.join('/'); // Join the remaining parts as the directory
return { directory, name };
};
/**
* filename的扩展名.
* base64的字符串转为blob
* @param content
* @param filename
* @returns
*/
export const toFile = (content: string, filename: string) => {
// 如果文件名是 a/d/a.js 格式的则需要把d作为目录a.js作为文件名
const directoryAndName = getDirectoryAndName(filename);
if (!directoryAndName) {
throw new Error('Invalid filename');
}
const { name } = directoryAndName;
const extension = getFileExtension(name);
if (!extension) {
throw new Error('Invalid filename');
}
const isBase64 = checkIsBase64(content);
const type = getFileType(extension);
if (isBase64) {
// Decode base64 string
let base64Data = content.split(',')[1]; // Remove the data URL prefix
const byteCharacters = atob(base64Data);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
const blob = new Blob([byteArray], { type });
return new File([blob], filename, { type });
} else {
const blob = new Blob([content], { type });
return new File([blob], filename, { type });
}
};
/**
*
* @param content
* @param filename
* @returns
*/
export const toTextFile = (content: string = 'keep directory exist', filename: string = 'keep.txt') => {
const file = toFile(content, filename);
return file;
};
export const downloadFile = (file: File) => {
const a = document.createElement('a');
a.href = URL.createObjectURL(file);
a.download = file.name;
a.click();
};

53
src/modules/upload.ts Normal file
View File

@ -0,0 +1,53 @@
import NProgress from 'nprogress';
import { Id, toast } from 'react-toastify';
import { toastLogin } from './ToastLogin';
import { uploadFileChunked, UploadProgress } from '@kevisual/query-upload/query-upload';
export type ConvertOpts = {
appKey?: string;
version?: string;
username?: string;
directory?: string;
isPublic?: boolean;
filename?: string;
};
export const uploadChunkV2 = async (file: File, opts: ConvertOpts) => {
const filename = opts.filename || file.name;
const token = localStorage.getItem('token');
if (!token) {
console.log('uploadChunk token', token);
toastLogin();
return;
}
let loaded: Id;
const uploadProgress = new UploadProgress({
onStart: function () {
NProgress.start();
loaded = toast.loading(`${filename} 上传中...`);
},
onDone: () => {
NProgress.done();
toast.dismiss(loaded);
},
onProgress: (progress, data) => {
NProgress.set(progress);
// console.log('uploadChunk progress', progress, data);
toast.update(loaded, {
render: `${filename} 上传中... ${progress.toFixed(2)}%`,
isLoading: true,
autoClose: false,
});
},
});
const result = await uploadFileChunked(file, opts, {
uploadProgress,
token,
createEventSource: (url: string, searchParams: URLSearchParams) => {
return new EventSource(url + '?' + searchParams.toString());
},
FormDataFn: FormData,
});
return result;
};

View File

@ -1,7 +1,7 @@
import { Excalidraw } from '@excalidraw/excalidraw'; import { Excalidraw } from '@excalidraw/excalidraw';
import '@excalidraw/excalidraw/index.css';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { ExcalidrawImperativeAPI } from '@excalidraw/excalidraw/types'; import { BinaryFileData, ExcalidrawImperativeAPI } from '@excalidraw/excalidraw/types';
import { Languages, LogOut, Save } from 'lucide-react'; import { Languages, LogOut, Save } from 'lucide-react';
import { MainMenu, Sidebar, Footer } from '@excalidraw/excalidraw'; import { MainMenu, Sidebar, Footer } from '@excalidraw/excalidraw';
import { throttle } from 'lodash-es'; import { throttle } from 'lodash-es';
@ -9,6 +9,10 @@ import { useMarkStore } from '@/store';
import { useShallow } from 'zustand/shallow'; import { useShallow } from 'zustand/shallow';
import { useListenLang } from './hooks/listen-lang'; import { useListenLang } from './hooks/listen-lang';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { hashFile } from '@/modules/hash-file';
import { uploadChunkV2 } from '../../modules/upload';
import { downloadFile, toFile } from '../../modules/to-file';
type ImageResource = {}; type ImageResource = {};
export const ImagesResources = (props: ImageResource) => { export const ImagesResources = (props: ImageResource) => {
const [images, setImages] = useState<string[]>([]); const [images, setImages] = useState<string[]>([]);
@ -152,6 +156,7 @@ type CoreProps = {
export const Core = ({ onClose, id }: CoreProps) => { export const Core = ({ onClose, id }: CoreProps) => {
const ref = useRef<ExcalidrawImperativeAPI>(null); const ref = useRef<ExcalidrawImperativeAPI>(null);
const { lang } = useListenLang(); const { lang } = useListenLang();
const uploadLoadingRef = useRef<boolean>(false);
const store = useMarkStore( const store = useMarkStore(
useShallow((state) => { useShallow((state) => {
return { return {
@ -181,6 +186,7 @@ export const Core = ({ onClose, id }: CoreProps) => {
if (loading) { if (loading) {
return; return;
} }
if (uploadLoadingRef.current) return;
let isChange = false; let isChange = false;
const elementsObj = elements.reduce((acc, e) => { const elementsObj = elements.reduce((acc, e) => {
acc[e.id] = e.version; acc[e.id] = e.version;
@ -189,10 +195,37 @@ export const Core = ({ onClose, id }: CoreProps) => {
if (JSON.stringify(elementsObj) !== JSON.stringify(cacheElements)) { if (JSON.stringify(elementsObj) !== JSON.stringify(cacheElements)) {
isChange = true; isChange = true;
} }
if (!isChange) { if (JSON.stringify(cacheFiles) !== JSON.stringify(filesObject)) {
if (JSON.stringify(cacheFiles) !== JSON.stringify(filesObject)) { isChange = true;
isChange = true; const files = Object.values(filesObject) as any as BinaryFileData[];
uploadLoadingRef.current = true;
for (const file of files) {
if (file.dataURL.startsWith('data')) {
const _file = toFile(file.dataURL, file.id);
const res = (await uploadChunkV2(_file, {
filename: file.id,
directory: id,
})) as any;
if (res.code === 200) {
toast.success('上传图片成功');
} else {
toast.error('上传图片失败');
}
const [upload] = res.data?.upload || [];
if (upload) {
filesObject[file.id] = {
...filesObject[file.id],
dataURL: upload.path,
};
} else {
toast.error('上传图片失败');
}
} else {
continue;
}
} }
uploadLoadingRef.current = false;
} }
console.log('onSave', elements, appState, filesObject, 'isChange', isChange); console.log('onSave', elements, appState, filesObject, 'isChange', isChange);
if (!isChange) { if (!isChange) {
@ -215,10 +248,6 @@ export const Core = ({ onClose, id }: CoreProps) => {
onSave(elements, appState, filesObject); onSave(elements, appState, filesObject);
}} }}
langCode={lang || 'en'} langCode={lang || 'en'}
onPaste={async (e) => {
toast.info('paste is not allowed, is development');
return false;
}}
renderTopRightUI={() => { renderTopRightUI={() => {
return <div></div>; return <div></div>;
}} }}
@ -237,7 +266,13 @@ export const Core = ({ onClose, id }: CoreProps) => {
}; };
}} }}
generateIdForFile={async (file) => { generateIdForFile={async (file) => {
return '1.png'; // return dayjs().format('YYYY-MM-DD-HH-mm-ss') + '.' + file.type.split('/')[1];
const hash = await hashFile(file);
console.log('hash', hash, 'filetype', file.type);
const fileId = hash + '.' + file.type.split('/')[1];
console.log('fileId', fileId);
return fileId;
}}> }}>
<ExcalidrawExpand onClose={onClose} /> <ExcalidrawExpand onClose={onClose} />
</Excalidraw> </Excalidraw>

View File

@ -85,7 +85,8 @@ export const createMarkStore: StateCreator<MarkStore, [], [], MarkStore> = (set,
return; return;
} }
const { data } = mark; const { data } = mark;
const { elements, filesObject } = data;
console.log('updateMark', elements, filesObject);
const res = await queryMark.updateMark({ id, data }); const res = await queryMark.updateMark({ id, data });
if (res.code === 200) { if (res.code === 200) {
set(() => ({ mark: res.data })); set(() => ({ mark: res.data }));

@ -1 +1 @@
Subproject commit a99d9c2322df537d7ffaac09545e9b2e121511fa Subproject commit 540de3df4dee9a8529c8faa53d4143d80577cc91

View File

@ -31,15 +31,54 @@ export default defineConfig({
'@': path.resolve(__dirname, './src'), '@': path.resolve(__dirname, './src'),
}, },
}, },
base: basename, // base: basename,
base: './',
define: { define: {
DEV_SERVER: JSON.stringify(process.env.NODE_ENV === 'development'), DEV_SERVER: JSON.stringify(process.env.NODE_ENV === 'development'),
VERSION: JSON.stringify(version), VERSION: JSON.stringify(version),
BASE_NAME: JSON.stringify(basename), BASE_NAME: JSON.stringify(basename),
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
}, },
build: { build: {
target: 'esnext', target: 'modules',
// minify: false,
lib: {
entry: './src/libs.ts',
formats: ['es'],
fileName: ()=>`render.js`,
cssFileName: `render`,
},
rollupOptions: {
output: {
exports: 'named',
// entryFileNames: 'main.js',
assetFileNames: (chunkInfo) => {
const names = chunkInfo.names || [];
console.log('names',names);
if(names.includes('libs')){
return '[name].[ext]'
}
return 'assets/[name].[hash].[ext]';
},
// chunkFileNames: (chunkInfo) => {
// const names = chunkInfo.names || [];
// return 'assets/[name].[hash].[ext]';
// },
},
// output: {
// assetFileNames: (chunkInfo) => {
// console.log(chunkInfo.names);
// if (chunkInfo.names?.includes('render')) {
// return '[name].[ext]';
// }
// return 'assets/[name].[hash].[ext]';
// },
// },
},
}, },
server: { server: {
port: 6006, port: 6006,
host: '0.0.0.0', host: '0.0.0.0',