generated from template/vite-react-template
temp
This commit is contained in:
parent
fd3288cb5b
commit
4a04a432ca
@ -15,9 +15,9 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
<!-- <script type="module" src="/src/main.tsx"></script> -->
|
||||||
<!-- <script type="module" src="/aidist/router.es.js"></script> -->
|
<!-- <script type="module" src="/aidist/router.es.js"></script> -->
|
||||||
<!-- <script type="module" src="/template/index.ts"></script> -->
|
<script type="module" src="/template/index.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
11
package.json
11
package.json
@ -20,14 +20,12 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^5.6.1",
|
"@ant-design/icons": "^5.6.1",
|
||||||
"@blueprintjs/core": "^5.17.2",
|
|
||||||
"@blueprintjs/icons": "^5.19.1",
|
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@kevisual/cache": "^0.0.1",
|
"@kevisual/cache": "^0.0.1",
|
||||||
"@kevisual/query": "0.0.9-alpha.2",
|
"@kevisual/query": "0.0.9-alpha.2",
|
||||||
"@kevisual/router": "0.0.8",
|
"@kevisual/router": "0.0.9",
|
||||||
"@kevisual/system-lib": "0.0.21-beta.2",
|
"@kevisual/system-lib": "0.0.21-beta.3",
|
||||||
"@kevisual/system-ui": "^0.0.3",
|
"@kevisual/system-ui": "^0.0.3",
|
||||||
"@kevisual/ui": "^0.0.4-alpha-1",
|
"@kevisual/ui": "^0.0.4-alpha-1",
|
||||||
"@mui/material": "^6.4.6",
|
"@mui/material": "^6.4.6",
|
||||||
@ -47,6 +45,7 @@
|
|||||||
"@xyflow/react": "^12.4.4",
|
"@xyflow/react": "^12.4.4",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
|
"eventemitter3": "^5.0.1",
|
||||||
"github-markdown-css": "^5.8.1",
|
"github-markdown-css": "^5.8.1",
|
||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
"idb": "^8.0.2",
|
"idb": "^8.0.2",
|
||||||
@ -73,7 +72,7 @@
|
|||||||
"@eslint/js": "^9.21.0",
|
"@eslint/js": "^9.21.0",
|
||||||
"@kevisual/types": "^0.0.6",
|
"@kevisual/types": "^0.0.6",
|
||||||
"@tailwindcss/vite": "^4.0.9",
|
"@tailwindcss/vite": "^4.0.9",
|
||||||
"@types/node": "^22.13.8",
|
"@types/node": "^22.13.9",
|
||||||
"@types/react": "^19.0.10",
|
"@types/react": "^19.0.10",
|
||||||
"@types/react-dom": "^19.0.4",
|
"@types/react-dom": "^19.0.4",
|
||||||
"@types/react-resizable": "^3.0.8",
|
"@types/react-resizable": "^3.0.8",
|
||||||
@ -87,7 +86,7 @@
|
|||||||
"tailwindcss": "^4.0.9",
|
"tailwindcss": "^4.0.9",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.2",
|
||||||
"typescript-eslint": "^8.25.0",
|
"typescript-eslint": "^8.26.0",
|
||||||
"vite": "^6.2.0"
|
"vite": "^6.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
423
pnpm-lock.yaml
generated
423
pnpm-lock.yaml
generated
@ -11,12 +11,6 @@ importers:
|
|||||||
'@ant-design/icons':
|
'@ant-design/icons':
|
||||||
specifier: ^5.6.1
|
specifier: ^5.6.1
|
||||||
version: 5.6.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 5.6.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
'@blueprintjs/core':
|
|
||||||
specifier: ^5.17.2
|
|
||||||
version: 5.17.2(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
|
||||||
'@blueprintjs/icons':
|
|
||||||
specifier: ^5.19.1
|
|
||||||
version: 5.19.1(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
|
||||||
'@emotion/react':
|
'@emotion/react':
|
||||||
specifier: ^11.14.0
|
specifier: ^11.14.0
|
||||||
version: 11.14.0(@types/react@19.0.10)(react@19.0.0)
|
version: 11.14.0(@types/react@19.0.10)(react@19.0.0)
|
||||||
@ -30,11 +24,11 @@ importers:
|
|||||||
specifier: 0.0.9-alpha.2
|
specifier: 0.0.9-alpha.2
|
||||||
version: 0.0.9-alpha.2(ws@8.18.0)
|
version: 0.0.9-alpha.2(ws@8.18.0)
|
||||||
'@kevisual/router':
|
'@kevisual/router':
|
||||||
specifier: 0.0.8
|
specifier: 0.0.9
|
||||||
version: 0.0.8
|
version: 0.0.9
|
||||||
'@kevisual/system-lib':
|
'@kevisual/system-lib':
|
||||||
specifier: 0.0.21-beta.2
|
specifier: 0.0.21-beta.3
|
||||||
version: 0.0.21-beta.2
|
version: 0.0.21-beta.3
|
||||||
'@kevisual/system-ui':
|
'@kevisual/system-ui':
|
||||||
specifier: ^0.0.3
|
specifier: ^0.0.3
|
||||||
version: 0.0.3
|
version: 0.0.3
|
||||||
@ -92,6 +86,9 @@ importers:
|
|||||||
dayjs:
|
dayjs:
|
||||||
specifier: ^1.11.13
|
specifier: ^1.11.13
|
||||||
version: 1.11.13
|
version: 1.11.13
|
||||||
|
eventemitter3:
|
||||||
|
specifier: ^5.0.1
|
||||||
|
version: 5.0.1
|
||||||
github-markdown-css:
|
github-markdown-css:
|
||||||
specifier: ^5.8.1
|
specifier: ^5.8.1
|
||||||
version: 5.8.1
|
version: 5.8.1
|
||||||
@ -164,10 +161,10 @@ importers:
|
|||||||
version: 0.0.6
|
version: 0.0.6
|
||||||
'@tailwindcss/vite':
|
'@tailwindcss/vite':
|
||||||
specifier: ^4.0.9
|
specifier: ^4.0.9
|
||||||
version: 4.0.9(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1))
|
version: 4.0.9(vite@6.2.0(@types/node@22.13.9)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1))
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^22.13.8
|
specifier: ^22.13.9
|
||||||
version: 22.13.8
|
version: 22.13.9
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: ^19.0.10
|
specifier: ^19.0.10
|
||||||
version: 19.0.10
|
version: 19.0.10
|
||||||
@ -179,10 +176,10 @@ importers:
|
|||||||
version: 3.0.8
|
version: 3.0.8
|
||||||
'@vitejs/plugin-basic-ssl':
|
'@vitejs/plugin-basic-ssl':
|
||||||
specifier: ^2.0.0
|
specifier: ^2.0.0
|
||||||
version: 2.0.0(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1))
|
version: 2.0.0(vite@6.2.0(@types/node@22.13.9)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1))
|
||||||
'@vitejs/plugin-react':
|
'@vitejs/plugin-react':
|
||||||
specifier: ^4.3.4
|
specifier: ^4.3.4
|
||||||
version: 4.3.4(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1))
|
version: 4.3.4(vite@6.2.0(@types/node@22.13.9)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1))
|
||||||
eslint:
|
eslint:
|
||||||
specifier: ^9.21.0
|
specifier: ^9.21.0
|
||||||
version: 9.21.0(jiti@2.4.2)
|
version: 9.21.0(jiti@2.4.2)
|
||||||
@ -208,11 +205,11 @@ importers:
|
|||||||
specifier: ^5.8.2
|
specifier: ^5.8.2
|
||||||
version: 5.8.2
|
version: 5.8.2
|
||||||
typescript-eslint:
|
typescript-eslint:
|
||||||
specifier: ^8.25.0
|
specifier: ^8.26.0
|
||||||
version: 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
version: 8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
||||||
vite:
|
vite:
|
||||||
specifier: ^6.2.0
|
specifier: ^6.2.0
|
||||||
version: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1)
|
version: 6.2.0(@types/node@22.13.9)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1)
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
@ -333,30 +330,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==}
|
resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@blueprintjs/colors@5.1.8':
|
|
||||||
resolution: {integrity: sha512-rCl+NZwR6xjJeCB6yWglbqWU2zOdVgeI5unBASalzMXWpRO0UXIjx0pA/Vtii4cB2kIdk8PaHTlGmZnLTu/MSg==}
|
|
||||||
|
|
||||||
'@blueprintjs/core@5.17.2':
|
|
||||||
resolution: {integrity: sha512-6jLZAdwwmIQHJqX7XxGw32EZrYIQcOwZAhDuyzsWDD+vUzWkciogn/LYD4S4hr3tU5MRX5nVWbUHrHhgrd8RKQ==}
|
|
||||||
hasBin: true
|
|
||||||
peerDependencies:
|
|
||||||
'@types/react': ^16.14.41 || 17 || 18
|
|
||||||
react: ^16.8 || 17 || 18
|
|
||||||
react-dom: ^16.8 || 17 || 18
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@blueprintjs/icons@5.19.1':
|
|
||||||
resolution: {integrity: sha512-BRHIkoM0gXGYIA48xGjyegGE78L+9wrkhBGEGnnU436YRO2cznHEb/pl9AqCsw+2CEfYy5ubieWM30OiX2hpMw==}
|
|
||||||
peerDependencies:
|
|
||||||
'@types/react': ^16.14.41 || 17 || 18
|
|
||||||
react: ^16.8 || 17 || 18
|
|
||||||
react-dom: ^16.8 || 17 || 18
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@ctrl/tinycolor@3.6.1':
|
'@ctrl/tinycolor@3.6.1':
|
||||||
resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==}
|
resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -643,11 +616,11 @@ packages:
|
|||||||
'@kevisual/query@0.0.9-alpha.2':
|
'@kevisual/query@0.0.9-alpha.2':
|
||||||
resolution: {integrity: sha512-bpMHngIB5et7s83b6gCty9PzvU2JMEe41LhdE+9IHUj8iD0Jg6gD0RlX1t3SFW1Thgc6DoCFcTEPAOCYXqoE5w==}
|
resolution: {integrity: sha512-bpMHngIB5et7s83b6gCty9PzvU2JMEe41LhdE+9IHUj8iD0Jg6gD0RlX1t3SFW1Thgc6DoCFcTEPAOCYXqoE5w==}
|
||||||
|
|
||||||
'@kevisual/router@0.0.8':
|
'@kevisual/router@0.0.9':
|
||||||
resolution: {integrity: sha512-/Y8u7sJBNDcrTPirIT7vujwBT9GVWeJYquaf1M29fsyftqBv7jLxNlLzRNnWmBsHrTDYO1onrewgzGTBxzPH1g==}
|
resolution: {integrity: sha512-qPyC2GVJ7iOIdJCCKNDsWMAKOQeSJW9HBpL5ZWKHTbi+t4jJBGTzIlXmjKeMHRd0lr/Qq1imQvlkSh4hlrbodA==}
|
||||||
|
|
||||||
'@kevisual/system-lib@0.0.21-beta.2':
|
'@kevisual/system-lib@0.0.21-beta.3':
|
||||||
resolution: {integrity: sha512-oqUQFQp1GD7AM8VmGa0aBLkAO6xHzyuL2gr+dG7ag5CZj0GFNaNr5klTLm6O8ngMHaziMFLD2B0rQfu9/k+/7Q==}
|
resolution: {integrity: sha512-R9OtkZqAuUzAk22760xyXQ6qMOvDZSuj5GNUctr4nToo2DE6OZ7hwpX35p4srrcycfiBfWHaKjZmaH8U+EflfQ==}
|
||||||
|
|
||||||
'@kevisual/system-ui@0.0.3':
|
'@kevisual/system-ui@0.0.3':
|
||||||
resolution: {integrity: sha512-zRtUnL6wNe6R1W7X6eirDADZWeTmxZCNpLwxCLu30yeNuIhpFJdxHyOg0nX9aOZn6F0Kb6lB3Li2fZpKwdpk0w==}
|
resolution: {integrity: sha512-zRtUnL6wNe6R1W7X6eirDADZWeTmxZCNpLwxCLu30yeNuIhpFJdxHyOg0nX9aOZn6F0Kb6lB3Li2fZpKwdpk0w==}
|
||||||
@ -1189,8 +1162,8 @@ packages:
|
|||||||
'@types/node@18.19.78':
|
'@types/node@18.19.78':
|
||||||
resolution: {integrity: sha512-m1ilZCTwKLkk9rruBJXFeYN0Bc5SbjirwYX/Td3MqPfioYbgun3IvK/m8dQxMCnrPGZPg1kvXjp3SIekCN/ynw==}
|
resolution: {integrity: sha512-m1ilZCTwKLkk9rruBJXFeYN0Bc5SbjirwYX/Td3MqPfioYbgun3IvK/m8dQxMCnrPGZPg1kvXjp3SIekCN/ynw==}
|
||||||
|
|
||||||
'@types/node@22.13.8':
|
'@types/node@22.13.9':
|
||||||
resolution: {integrity: sha512-G3EfaZS+iOGYWLLRCEAXdWK9my08oHNZ+FHluRiggIYJPOXzhOiDgpVCUHaUvyIC5/fj7C/p637jdzC666AOKQ==}
|
resolution: {integrity: sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==}
|
||||||
|
|
||||||
'@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==}
|
||||||
@ -1223,51 +1196,51 @@ packages:
|
|||||||
'@types/unist@3.0.3':
|
'@types/unist@3.0.3':
|
||||||
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
|
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
|
||||||
|
|
||||||
'@typescript-eslint/eslint-plugin@8.25.0':
|
'@typescript-eslint/eslint-plugin@8.26.0':
|
||||||
resolution: {integrity: sha512-VM7bpzAe7JO/BFf40pIT1lJqS/z1F8OaSsUB3rpFJucQA4cOSuH2RVVVkFULN+En0Djgr29/jb4EQnedUo95KA==}
|
resolution: {integrity: sha512-cLr1J6pe56zjKYajK6SSSre6nl1Gj6xDp1TY0trpgPzjVbgDwd09v2Ws37LABxzkicmUjhEeg/fAUjPJJB1v5Q==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
|
'@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
|
||||||
eslint: ^8.57.0 || ^9.0.0
|
eslint: ^8.57.0 || ^9.0.0
|
||||||
typescript: '>=4.8.4 <5.8.0'
|
typescript: '>=4.8.4 <5.9.0'
|
||||||
|
|
||||||
'@typescript-eslint/parser@8.25.0':
|
'@typescript-eslint/parser@8.26.0':
|
||||||
resolution: {integrity: sha512-4gbs64bnbSzu4FpgMiQ1A+D+urxkoJk/kqlDJ2W//5SygaEiAP2B4GoS7TEdxgwol2el03gckFV9lJ4QOMiiHg==}
|
resolution: {integrity: sha512-mNtXP9LTVBy14ZF3o7JG69gRPBK/2QWtQd0j0oH26HcY/foyJJau6pNUez7QrM5UHnSvwlQcJXKsk0I99B9pOA==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0
|
eslint: ^8.57.0 || ^9.0.0
|
||||||
typescript: '>=4.8.4 <5.8.0'
|
typescript: '>=4.8.4 <5.9.0'
|
||||||
|
|
||||||
'@typescript-eslint/scope-manager@8.25.0':
|
'@typescript-eslint/scope-manager@8.26.0':
|
||||||
resolution: {integrity: sha512-6PPeiKIGbgStEyt4NNXa2ru5pMzQ8OYKO1hX1z53HMomrmiSB+R5FmChgQAP1ro8jMtNawz+TRQo/cSXrauTpg==}
|
resolution: {integrity: sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@typescript-eslint/type-utils@8.25.0':
|
'@typescript-eslint/type-utils@8.26.0':
|
||||||
resolution: {integrity: sha512-d77dHgHWnxmXOPJuDWO4FDWADmGQkN5+tt6SFRZz/RtCWl4pHgFl3+WdYCn16+3teG09DY6XtEpf3gGD0a186g==}
|
resolution: {integrity: sha512-ruk0RNChLKz3zKGn2LwXuVoeBcUMh+jaqzN461uMMdxy5H9epZqIBtYj7UiPXRuOpaALXGbmRuZQhmwHhaS04Q==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0
|
eslint: ^8.57.0 || ^9.0.0
|
||||||
typescript: '>=4.8.4 <5.8.0'
|
typescript: '>=4.8.4 <5.9.0'
|
||||||
|
|
||||||
'@typescript-eslint/types@8.25.0':
|
'@typescript-eslint/types@8.26.0':
|
||||||
resolution: {integrity: sha512-+vUe0Zb4tkNgznQwicsvLUJgZIRs6ITeWSCclX1q85pR1iOiaj+4uZJIUp//Z27QWu5Cseiw3O3AR8hVpax7Aw==}
|
resolution: {integrity: sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@8.25.0':
|
'@typescript-eslint/typescript-estree@8.26.0':
|
||||||
resolution: {integrity: sha512-ZPaiAKEZ6Blt/TPAx5Ot0EIB/yGtLI2EsGoY6F7XKklfMxYQyvtL+gT/UCqkMzO0BVFHLDlzvFqQzurYahxv9Q==}
|
resolution: {integrity: sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <5.8.0'
|
typescript: '>=4.8.4 <5.9.0'
|
||||||
|
|
||||||
'@typescript-eslint/utils@8.25.0':
|
'@typescript-eslint/utils@8.26.0':
|
||||||
resolution: {integrity: sha512-syqRbrEv0J1wywiLsK60XzHnQe/kRViI3zwFALrNEgnntn1l24Ra2KvOAWwWbWZ1lBZxZljPDGOq967dsl6fkA==}
|
resolution: {integrity: sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0
|
eslint: ^8.57.0 || ^9.0.0
|
||||||
typescript: '>=4.8.4 <5.8.0'
|
typescript: '>=4.8.4 <5.9.0'
|
||||||
|
|
||||||
'@typescript-eslint/visitor-keys@8.25.0':
|
'@typescript-eslint/visitor-keys@8.26.0':
|
||||||
resolution: {integrity: sha512-kCYXKAum9CecGVHGij7muybDfTS2sD3t0L4bJsEZLkyrXUImiCTq1M3LG2SRtOhiHFwMR9wAFplpT6XHYjTkwQ==}
|
resolution: {integrity: sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@vitejs/plugin-basic-ssl@2.0.0':
|
'@vitejs/plugin-basic-ssl@2.0.0':
|
||||||
@ -1352,22 +1325,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
camel-case@4.1.2:
|
|
||||||
resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==}
|
|
||||||
|
|
||||||
caniuse-lite@1.0.30001684:
|
caniuse-lite@1.0.30001684:
|
||||||
resolution: {integrity: sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==}
|
resolution: {integrity: sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==}
|
||||||
|
|
||||||
capital-case@1.0.4:
|
|
||||||
resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==}
|
|
||||||
|
|
||||||
chalk@4.1.2:
|
chalk@4.1.2:
|
||||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
change-case@4.1.2:
|
|
||||||
resolution: {integrity: sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==}
|
|
||||||
|
|
||||||
classcat@5.0.5:
|
classcat@5.0.5:
|
||||||
resolution: {integrity: sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==}
|
resolution: {integrity: sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==}
|
||||||
|
|
||||||
@ -1399,9 +1363,6 @@ packages:
|
|||||||
concat-map@0.0.1:
|
concat-map@0.0.1:
|
||||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||||
|
|
||||||
constant-case@3.0.4:
|
|
||||||
resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==}
|
|
||||||
|
|
||||||
convert-source-map@1.9.0:
|
convert-source-map@1.9.0:
|
||||||
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
|
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
|
||||||
|
|
||||||
@ -1502,9 +1463,6 @@ packages:
|
|||||||
dom-helpers@5.2.1:
|
dom-helpers@5.2.1:
|
||||||
resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
|
resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
|
||||||
|
|
||||||
dot-case@3.0.4:
|
|
||||||
resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==}
|
|
||||||
|
|
||||||
dunder-proto@1.0.1:
|
dunder-proto@1.0.1:
|
||||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@ -1612,6 +1570,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
|
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
eventemitter3@5.0.1:
|
||||||
|
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
|
||||||
|
|
||||||
fast-deep-equal@3.1.3:
|
fast-deep-equal@3.1.3:
|
||||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||||
|
|
||||||
@ -1739,9 +1700,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
header-case@2.0.4:
|
|
||||||
resolution: {integrity: sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==}
|
|
||||||
|
|
||||||
highlight.js@11.11.1:
|
highlight.js@11.11.1:
|
||||||
resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==}
|
resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==}
|
||||||
engines: {node: '>=12.0.0'}
|
engines: {node: '>=12.0.0'}
|
||||||
@ -1928,9 +1886,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
lower-case@2.0.2:
|
|
||||||
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
|
|
||||||
|
|
||||||
lowlight@3.3.0:
|
lowlight@3.3.0:
|
||||||
resolution: {integrity: sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==}
|
resolution: {integrity: sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==}
|
||||||
|
|
||||||
@ -2003,9 +1958,6 @@ packages:
|
|||||||
natural-compare@1.4.0:
|
natural-compare@1.4.0:
|
||||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||||
|
|
||||||
no-case@3.0.4:
|
|
||||||
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
|
|
||||||
|
|
||||||
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'}
|
||||||
@ -2026,9 +1978,6 @@ packages:
|
|||||||
node-releases@2.0.18:
|
node-releases@2.0.18:
|
||||||
resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
|
resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
|
||||||
|
|
||||||
normalize.css@8.0.1:
|
|
||||||
resolution: {integrity: sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==}
|
|
||||||
|
|
||||||
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'}
|
||||||
@ -2060,9 +2009,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
|
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
param-case@3.0.4:
|
|
||||||
resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==}
|
|
||||||
|
|
||||||
parent-module@1.0.1:
|
parent-module@1.0.1:
|
||||||
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
|
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@ -2071,12 +2017,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
|
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
pascal-case@3.1.2:
|
|
||||||
resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==}
|
|
||||||
|
|
||||||
path-case@3.0.4:
|
|
||||||
resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==}
|
|
||||||
|
|
||||||
path-exists@4.0.0:
|
path-exists@4.0.0:
|
||||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@ -2207,9 +2147,6 @@ packages:
|
|||||||
react: '>= 16.3.0'
|
react: '>= 16.3.0'
|
||||||
react-dom: '>= 16.3.0'
|
react-dom: '>= 16.3.0'
|
||||||
|
|
||||||
react-fast-compare@3.2.2:
|
|
||||||
resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
|
|
||||||
|
|
||||||
react-is@16.13.1:
|
react-is@16.13.1:
|
||||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||||
|
|
||||||
@ -2219,13 +2156,6 @@ packages:
|
|||||||
react-is@19.0.0:
|
react-is@19.0.0:
|
||||||
resolution: {integrity: sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==}
|
resolution: {integrity: sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==}
|
||||||
|
|
||||||
react-popper@2.3.0:
|
|
||||||
resolution: {integrity: sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==}
|
|
||||||
peerDependencies:
|
|
||||||
'@popperjs/core': ^2.0.0
|
|
||||||
react: ^16.8.0 || ^17 || ^18
|
|
||||||
react-dom: ^16.8.0 || ^17 || ^18
|
|
||||||
|
|
||||||
react-refresh@0.14.2:
|
react-refresh@0.14.2:
|
||||||
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
|
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -2270,16 +2200,6 @@ packages:
|
|||||||
react: '>=16.6.0'
|
react: '>=16.6.0'
|
||||||
react-dom: '>=16.6.0'
|
react-dom: '>=16.6.0'
|
||||||
|
|
||||||
react-uid@2.4.0:
|
|
||||||
resolution: {integrity: sha512-+MVs/25NrcZuGrmlVRWPOSsbS8y72GJOBsR7d68j3/wqOrRBF52U29XAw4+XSelw0Vm6s5VmGH5mCbTCPGVCVg==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
peerDependencies:
|
|
||||||
'@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
react@19.0.0:
|
react@19.0.0:
|
||||||
resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
|
resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -2334,9 +2254,6 @@ packages:
|
|||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
sentence-case@3.0.4:
|
|
||||||
resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==}
|
|
||||||
|
|
||||||
set-cookie-parser@2.7.1:
|
set-cookie-parser@2.7.1:
|
||||||
resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==}
|
resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==}
|
||||||
|
|
||||||
@ -2348,9 +2265,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
snake-case@3.0.4:
|
|
||||||
resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==}
|
|
||||||
|
|
||||||
source-map-js@1.2.1:
|
source-map-js@1.2.1:
|
||||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -2427,12 +2341,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
|
|
||||||
typescript-eslint@8.25.0:
|
typescript-eslint@8.26.0:
|
||||||
resolution: {integrity: sha512-TxRdQQLH4g7JkoFlYG3caW5v1S6kEkz8rqt80iQJZUYPq1zD1Ra7HfQBJJ88ABRaMvHAXnwRvRB4V+6sQ9xN5Q==}
|
resolution: {integrity: sha512-PtVz9nAnuNJuAVeUFvwztjuUgSnJInODAUx47VDwWPXzd5vismPOtPtt83tzNXyOjVQbPRp786D6WFW/M2koIA==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0
|
eslint: ^8.57.0 || ^9.0.0
|
||||||
typescript: '>=4.8.4 <5.8.0'
|
typescript: '>=4.8.4 <5.9.0'
|
||||||
|
|
||||||
typescript@5.8.2:
|
typescript@5.8.2:
|
||||||
resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==}
|
resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==}
|
||||||
@ -2454,12 +2368,6 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
browserslist: '>= 4.21.0'
|
browserslist: '>= 4.21.0'
|
||||||
|
|
||||||
upper-case-first@2.0.2:
|
|
||||||
resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==}
|
|
||||||
|
|
||||||
upper-case@2.0.2:
|
|
||||||
resolution: {integrity: sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==}
|
|
||||||
|
|
||||||
uri-js@4.4.1:
|
uri-js@4.4.1:
|
||||||
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||||
|
|
||||||
@ -2511,9 +2419,6 @@ packages:
|
|||||||
w3c-keyname@2.2.8:
|
w3c-keyname@2.2.8:
|
||||||
resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
|
resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
|
||||||
|
|
||||||
warning@4.0.3:
|
|
||||||
resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
|
|
||||||
|
|
||||||
web-streams-polyfill@4.0.0-beta.3:
|
web-streams-polyfill@4.0.0-beta.3:
|
||||||
resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==}
|
resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==}
|
||||||
engines: {node: '>= 14'}
|
engines: {node: '>= 14'}
|
||||||
@ -2745,37 +2650,6 @@ snapshots:
|
|||||||
'@babel/helper-string-parser': 7.25.9
|
'@babel/helper-string-parser': 7.25.9
|
||||||
'@babel/helper-validator-identifier': 7.25.9
|
'@babel/helper-validator-identifier': 7.25.9
|
||||||
|
|
||||||
'@blueprintjs/colors@5.1.8':
|
|
||||||
dependencies:
|
|
||||||
tslib: 2.6.3
|
|
||||||
|
|
||||||
'@blueprintjs/core@5.17.2(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
|
||||||
dependencies:
|
|
||||||
'@blueprintjs/colors': 5.1.8
|
|
||||||
'@blueprintjs/icons': 5.19.1(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
|
||||||
'@popperjs/core': 2.11.8
|
|
||||||
classnames: 2.5.1
|
|
||||||
normalize.css: 8.0.1
|
|
||||||
react: 19.0.0
|
|
||||||
react-dom: 19.0.0(react@19.0.0)
|
|
||||||
react-popper: 2.3.0(@popperjs/core@2.11.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
|
||||||
react-transition-group: 4.4.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
|
||||||
react-uid: 2.4.0(@types/react@19.0.10)(react@19.0.0)
|
|
||||||
tslib: 2.6.3
|
|
||||||
use-sync-external-store: 1.2.2(react@19.0.0)
|
|
||||||
optionalDependencies:
|
|
||||||
'@types/react': 19.0.10
|
|
||||||
|
|
||||||
'@blueprintjs/icons@5.19.1(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
|
||||||
dependencies:
|
|
||||||
change-case: 4.1.2
|
|
||||||
classnames: 2.5.1
|
|
||||||
react: 19.0.0
|
|
||||||
react-dom: 19.0.0(react@19.0.0)
|
|
||||||
tslib: 2.6.3
|
|
||||||
optionalDependencies:
|
|
||||||
'@types/react': 19.0.10
|
|
||||||
|
|
||||||
'@ctrl/tinycolor@3.6.1': {}
|
'@ctrl/tinycolor@3.6.1': {}
|
||||||
|
|
||||||
'@emotion/babel-plugin@11.13.5':
|
'@emotion/babel-plugin@11.13.5':
|
||||||
@ -3028,7 +2902,7 @@ snapshots:
|
|||||||
- ws
|
- ws
|
||||||
- zod
|
- zod
|
||||||
|
|
||||||
'@kevisual/router@0.0.8':
|
'@kevisual/router@0.0.9':
|
||||||
dependencies:
|
dependencies:
|
||||||
path-to-regexp: 8.2.0
|
path-to-regexp: 8.2.0
|
||||||
selfsigned: 2.4.1
|
selfsigned: 2.4.1
|
||||||
@ -3037,7 +2911,7 @@ snapshots:
|
|||||||
- bufferutil
|
- bufferutil
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
|
|
||||||
'@kevisual/system-lib@0.0.21-beta.2': {}
|
'@kevisual/system-lib@0.0.21-beta.3': {}
|
||||||
|
|
||||||
'@kevisual/system-ui@0.0.3':
|
'@kevisual/system-ui@0.0.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -3297,13 +3171,13 @@ snapshots:
|
|||||||
'@tailwindcss/oxide-win32-arm64-msvc': 4.0.9
|
'@tailwindcss/oxide-win32-arm64-msvc': 4.0.9
|
||||||
'@tailwindcss/oxide-win32-x64-msvc': 4.0.9
|
'@tailwindcss/oxide-win32-x64-msvc': 4.0.9
|
||||||
|
|
||||||
'@tailwindcss/vite@4.0.9(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1))':
|
'@tailwindcss/vite@4.0.9(vite@6.2.0(@types/node@22.13.9)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tailwindcss/node': 4.0.9
|
'@tailwindcss/node': 4.0.9
|
||||||
'@tailwindcss/oxide': 4.0.9
|
'@tailwindcss/oxide': 4.0.9
|
||||||
lightningcss: 1.29.1
|
lightningcss: 1.29.1
|
||||||
tailwindcss: 4.0.9
|
tailwindcss: 4.0.9
|
||||||
vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1)
|
vite: 6.2.0(@types/node@22.13.9)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1)
|
||||||
|
|
||||||
'@tiptap/core@2.11.5(@tiptap/pm@2.11.5)':
|
'@tiptap/core@2.11.5(@tiptap/pm@2.11.5)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -3539,18 +3413,18 @@ snapshots:
|
|||||||
|
|
||||||
'@types/node-fetch@2.6.12':
|
'@types/node-fetch@2.6.12':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 22.13.8
|
'@types/node': 22.13.9
|
||||||
form-data: 4.0.2
|
form-data: 4.0.2
|
||||||
|
|
||||||
'@types/node-forge@1.3.11':
|
'@types/node-forge@1.3.11':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 22.13.8
|
'@types/node': 22.13.9
|
||||||
|
|
||||||
'@types/node@18.19.78':
|
'@types/node@18.19.78':
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 5.26.5
|
undici-types: 5.26.5
|
||||||
|
|
||||||
'@types/node@22.13.8':
|
'@types/node@22.13.9':
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.20.0
|
undici-types: 6.20.0
|
||||||
|
|
||||||
@ -3580,14 +3454,14 @@ snapshots:
|
|||||||
|
|
||||||
'@types/unist@3.0.3': {}
|
'@types/unist@3.0.3': {}
|
||||||
|
|
||||||
'@typescript-eslint/eslint-plugin@8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)':
|
'@typescript-eslint/eslint-plugin@8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/regexpp': 4.12.1
|
'@eslint-community/regexpp': 4.12.1
|
||||||
'@typescript-eslint/parser': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
'@typescript-eslint/parser': 8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
||||||
'@typescript-eslint/scope-manager': 8.25.0
|
'@typescript-eslint/scope-manager': 8.26.0
|
||||||
'@typescript-eslint/type-utils': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
'@typescript-eslint/type-utils': 8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
||||||
'@typescript-eslint/utils': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
'@typescript-eslint/utils': 8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
||||||
'@typescript-eslint/visitor-keys': 8.25.0
|
'@typescript-eslint/visitor-keys': 8.26.0
|
||||||
eslint: 9.21.0(jiti@2.4.2)
|
eslint: 9.21.0(jiti@2.4.2)
|
||||||
graphemer: 1.4.0
|
graphemer: 1.4.0
|
||||||
ignore: 5.3.2
|
ignore: 5.3.2
|
||||||
@ -3597,27 +3471,27 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)':
|
'@typescript-eslint/parser@8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/scope-manager': 8.25.0
|
'@typescript-eslint/scope-manager': 8.26.0
|
||||||
'@typescript-eslint/types': 8.25.0
|
'@typescript-eslint/types': 8.26.0
|
||||||
'@typescript-eslint/typescript-estree': 8.25.0(typescript@5.8.2)
|
'@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2)
|
||||||
'@typescript-eslint/visitor-keys': 8.25.0
|
'@typescript-eslint/visitor-keys': 8.26.0
|
||||||
debug: 4.3.7
|
debug: 4.3.7
|
||||||
eslint: 9.21.0(jiti@2.4.2)
|
eslint: 9.21.0(jiti@2.4.2)
|
||||||
typescript: 5.8.2
|
typescript: 5.8.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/scope-manager@8.25.0':
|
'@typescript-eslint/scope-manager@8.26.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.25.0
|
'@typescript-eslint/types': 8.26.0
|
||||||
'@typescript-eslint/visitor-keys': 8.25.0
|
'@typescript-eslint/visitor-keys': 8.26.0
|
||||||
|
|
||||||
'@typescript-eslint/type-utils@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)':
|
'@typescript-eslint/type-utils@8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/typescript-estree': 8.25.0(typescript@5.8.2)
|
'@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2)
|
||||||
'@typescript-eslint/utils': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
'@typescript-eslint/utils': 8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
||||||
debug: 4.3.7
|
debug: 4.3.7
|
||||||
eslint: 9.21.0(jiti@2.4.2)
|
eslint: 9.21.0(jiti@2.4.2)
|
||||||
ts-api-utils: 2.0.1(typescript@5.8.2)
|
ts-api-utils: 2.0.1(typescript@5.8.2)
|
||||||
@ -3625,12 +3499,12 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/types@8.25.0': {}
|
'@typescript-eslint/types@8.26.0': {}
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@8.25.0(typescript@5.8.2)':
|
'@typescript-eslint/typescript-estree@8.26.0(typescript@5.8.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.25.0
|
'@typescript-eslint/types': 8.26.0
|
||||||
'@typescript-eslint/visitor-keys': 8.25.0
|
'@typescript-eslint/visitor-keys': 8.26.0
|
||||||
debug: 4.3.7
|
debug: 4.3.7
|
||||||
fast-glob: 3.3.2
|
fast-glob: 3.3.2
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
@ -3641,34 +3515,34 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/utils@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)':
|
'@typescript-eslint/utils@8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/eslint-utils': 4.4.0(eslint@9.21.0(jiti@2.4.2))
|
'@eslint-community/eslint-utils': 4.4.0(eslint@9.21.0(jiti@2.4.2))
|
||||||
'@typescript-eslint/scope-manager': 8.25.0
|
'@typescript-eslint/scope-manager': 8.26.0
|
||||||
'@typescript-eslint/types': 8.25.0
|
'@typescript-eslint/types': 8.26.0
|
||||||
'@typescript-eslint/typescript-estree': 8.25.0(typescript@5.8.2)
|
'@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2)
|
||||||
eslint: 9.21.0(jiti@2.4.2)
|
eslint: 9.21.0(jiti@2.4.2)
|
||||||
typescript: 5.8.2
|
typescript: 5.8.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/visitor-keys@8.25.0':
|
'@typescript-eslint/visitor-keys@8.26.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.25.0
|
'@typescript-eslint/types': 8.26.0
|
||||||
eslint-visitor-keys: 4.2.0
|
eslint-visitor-keys: 4.2.0
|
||||||
|
|
||||||
'@vitejs/plugin-basic-ssl@2.0.0(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1))':
|
'@vitejs/plugin-basic-ssl@2.0.0(vite@6.2.0(@types/node@22.13.9)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1)
|
vite: 6.2.0(@types/node@22.13.9)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1)
|
||||||
|
|
||||||
'@vitejs/plugin-react@4.3.4(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1))':
|
'@vitejs/plugin-react@4.3.4(vite@6.2.0(@types/node@22.13.9)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.26.0
|
'@babel/core': 7.26.0
|
||||||
'@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0)
|
'@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0)
|
||||||
'@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0)
|
'@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0)
|
||||||
'@types/babel__core': 7.20.5
|
'@types/babel__core': 7.20.5
|
||||||
react-refresh: 0.14.2
|
react-refresh: 0.14.2
|
||||||
vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1)
|
vite: 6.2.0(@types/node@22.13.9)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@ -3757,39 +3631,13 @@ snapshots:
|
|||||||
|
|
||||||
callsites@3.1.0: {}
|
callsites@3.1.0: {}
|
||||||
|
|
||||||
camel-case@4.1.2:
|
|
||||||
dependencies:
|
|
||||||
pascal-case: 3.1.2
|
|
||||||
tslib: 2.6.3
|
|
||||||
|
|
||||||
caniuse-lite@1.0.30001684: {}
|
caniuse-lite@1.0.30001684: {}
|
||||||
|
|
||||||
capital-case@1.0.4:
|
|
||||||
dependencies:
|
|
||||||
no-case: 3.0.4
|
|
||||||
tslib: 2.6.3
|
|
||||||
upper-case-first: 2.0.2
|
|
||||||
|
|
||||||
chalk@4.1.2:
|
chalk@4.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-styles: 4.3.0
|
ansi-styles: 4.3.0
|
||||||
supports-color: 7.2.0
|
supports-color: 7.2.0
|
||||||
|
|
||||||
change-case@4.1.2:
|
|
||||||
dependencies:
|
|
||||||
camel-case: 4.1.2
|
|
||||||
capital-case: 1.0.4
|
|
||||||
constant-case: 3.0.4
|
|
||||||
dot-case: 3.0.4
|
|
||||||
header-case: 2.0.4
|
|
||||||
no-case: 3.0.4
|
|
||||||
param-case: 3.0.4
|
|
||||||
pascal-case: 3.1.2
|
|
||||||
path-case: 3.0.4
|
|
||||||
sentence-case: 3.0.4
|
|
||||||
snake-case: 3.0.4
|
|
||||||
tslib: 2.6.3
|
|
||||||
|
|
||||||
classcat@5.0.5: {}
|
classcat@5.0.5: {}
|
||||||
|
|
||||||
classnames@2.5.1: {}
|
classnames@2.5.1: {}
|
||||||
@ -3812,12 +3660,6 @@ snapshots:
|
|||||||
|
|
||||||
concat-map@0.0.1: {}
|
concat-map@0.0.1: {}
|
||||||
|
|
||||||
constant-case@3.0.4:
|
|
||||||
dependencies:
|
|
||||||
no-case: 3.0.4
|
|
||||||
tslib: 2.6.3
|
|
||||||
upper-case: 2.0.2
|
|
||||||
|
|
||||||
convert-source-map@1.9.0: {}
|
convert-source-map@1.9.0: {}
|
||||||
|
|
||||||
convert-source-map@2.0.0: {}
|
convert-source-map@2.0.0: {}
|
||||||
@ -3903,11 +3745,6 @@ snapshots:
|
|||||||
'@babel/runtime': 7.26.0
|
'@babel/runtime': 7.26.0
|
||||||
csstype: 3.1.3
|
csstype: 3.1.3
|
||||||
|
|
||||||
dot-case@3.0.4:
|
|
||||||
dependencies:
|
|
||||||
no-case: 3.0.4
|
|
||||||
tslib: 2.6.3
|
|
||||||
|
|
||||||
dunder-proto@1.0.1:
|
dunder-proto@1.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind-apply-helpers: 1.0.2
|
call-bind-apply-helpers: 1.0.2
|
||||||
@ -4054,6 +3891,8 @@ snapshots:
|
|||||||
|
|
||||||
event-target-shim@5.0.1: {}
|
event-target-shim@5.0.1: {}
|
||||||
|
|
||||||
|
eventemitter3@5.0.1: {}
|
||||||
|
|
||||||
fast-deep-equal@3.1.3: {}
|
fast-deep-equal@3.1.3: {}
|
||||||
|
|
||||||
fast-glob@3.3.2:
|
fast-glob@3.3.2:
|
||||||
@ -4171,11 +4010,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
function-bind: 1.1.2
|
function-bind: 1.1.2
|
||||||
|
|
||||||
header-case@2.0.4:
|
|
||||||
dependencies:
|
|
||||||
capital-case: 1.0.4
|
|
||||||
tslib: 2.6.3
|
|
||||||
|
|
||||||
highlight.js@11.11.1: {}
|
highlight.js@11.11.1: {}
|
||||||
|
|
||||||
hoist-non-react-statics@3.3.2:
|
hoist-non-react-statics@3.3.2:
|
||||||
@ -4317,10 +4151,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
js-tokens: 4.0.0
|
js-tokens: 4.0.0
|
||||||
|
|
||||||
lower-case@2.0.2:
|
|
||||||
dependencies:
|
|
||||||
tslib: 2.6.3
|
|
||||||
|
|
||||||
lowlight@3.3.0:
|
lowlight@3.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/hast': 3.0.4
|
'@types/hast': 3.0.4
|
||||||
@ -4385,11 +4215,6 @@ snapshots:
|
|||||||
|
|
||||||
natural-compare@1.4.0: {}
|
natural-compare@1.4.0: {}
|
||||||
|
|
||||||
no-case@3.0.4:
|
|
||||||
dependencies:
|
|
||||||
lower-case: 2.0.2
|
|
||||||
tslib: 2.6.3
|
|
||||||
|
|
||||||
node-domexception@1.0.0: {}
|
node-domexception@1.0.0: {}
|
||||||
|
|
||||||
node-fetch@2.7.0:
|
node-fetch@2.7.0:
|
||||||
@ -4400,8 +4225,6 @@ snapshots:
|
|||||||
|
|
||||||
node-releases@2.0.18: {}
|
node-releases@2.0.18: {}
|
||||||
|
|
||||||
normalize.css@8.0.1: {}
|
|
||||||
|
|
||||||
object-assign@4.1.1: {}
|
object-assign@4.1.1: {}
|
||||||
|
|
||||||
openai@4.86.1(ws@8.18.0):
|
openai@4.86.1(ws@8.18.0):
|
||||||
@ -4437,11 +4260,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
p-limit: 3.1.0
|
p-limit: 3.1.0
|
||||||
|
|
||||||
param-case@3.0.4:
|
|
||||||
dependencies:
|
|
||||||
dot-case: 3.0.4
|
|
||||||
tslib: 2.6.3
|
|
||||||
|
|
||||||
parent-module@1.0.1:
|
parent-module@1.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
callsites: 3.1.0
|
callsites: 3.1.0
|
||||||
@ -4453,16 +4271,6 @@ snapshots:
|
|||||||
json-parse-even-better-errors: 2.3.1
|
json-parse-even-better-errors: 2.3.1
|
||||||
lines-and-columns: 1.2.4
|
lines-and-columns: 1.2.4
|
||||||
|
|
||||||
pascal-case@3.1.2:
|
|
||||||
dependencies:
|
|
||||||
no-case: 3.0.4
|
|
||||||
tslib: 2.6.3
|
|
||||||
|
|
||||||
path-case@3.0.4:
|
|
||||||
dependencies:
|
|
||||||
dot-case: 3.0.4
|
|
||||||
tslib: 2.6.3
|
|
||||||
|
|
||||||
path-exists@4.0.0: {}
|
path-exists@4.0.0: {}
|
||||||
|
|
||||||
path-key@3.1.1: {}
|
path-key@3.1.1: {}
|
||||||
@ -4623,22 +4431,12 @@ snapshots:
|
|||||||
react: 19.0.0
|
react: 19.0.0
|
||||||
react-dom: 19.0.0(react@19.0.0)
|
react-dom: 19.0.0(react@19.0.0)
|
||||||
|
|
||||||
react-fast-compare@3.2.2: {}
|
|
||||||
|
|
||||||
react-is@16.13.1: {}
|
react-is@16.13.1: {}
|
||||||
|
|
||||||
react-is@18.3.1: {}
|
react-is@18.3.1: {}
|
||||||
|
|
||||||
react-is@19.0.0: {}
|
react-is@19.0.0: {}
|
||||||
|
|
||||||
react-popper@2.3.0(@popperjs/core@2.11.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
|
||||||
dependencies:
|
|
||||||
'@popperjs/core': 2.11.8
|
|
||||||
react: 19.0.0
|
|
||||||
react-dom: 19.0.0(react@19.0.0)
|
|
||||||
react-fast-compare: 3.2.2
|
|
||||||
warning: 4.0.3
|
|
||||||
|
|
||||||
react-refresh@0.14.2: {}
|
react-refresh@0.14.2: {}
|
||||||
|
|
||||||
react-resizable-panels@2.1.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
react-resizable-panels@2.1.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||||
@ -4685,13 +4483,6 @@ snapshots:
|
|||||||
react: 19.0.0
|
react: 19.0.0
|
||||||
react-dom: 19.0.0(react@19.0.0)
|
react-dom: 19.0.0(react@19.0.0)
|
||||||
|
|
||||||
react-uid@2.4.0(@types/react@19.0.10)(react@19.0.0):
|
|
||||||
dependencies:
|
|
||||||
react: 19.0.0
|
|
||||||
tslib: 2.6.3
|
|
||||||
optionalDependencies:
|
|
||||||
'@types/react': 19.0.10
|
|
||||||
|
|
||||||
react@19.0.0: {}
|
react@19.0.0: {}
|
||||||
|
|
||||||
regenerator-runtime@0.14.1: {}
|
regenerator-runtime@0.14.1: {}
|
||||||
@ -4756,12 +4547,6 @@ snapshots:
|
|||||||
|
|
||||||
semver@7.6.3: {}
|
semver@7.6.3: {}
|
||||||
|
|
||||||
sentence-case@3.0.4:
|
|
||||||
dependencies:
|
|
||||||
no-case: 3.0.4
|
|
||||||
tslib: 2.6.3
|
|
||||||
upper-case-first: 2.0.2
|
|
||||||
|
|
||||||
set-cookie-parser@2.7.1: {}
|
set-cookie-parser@2.7.1: {}
|
||||||
|
|
||||||
shebang-command@2.0.0:
|
shebang-command@2.0.0:
|
||||||
@ -4770,11 +4555,6 @@ snapshots:
|
|||||||
|
|
||||||
shebang-regex@3.0.0: {}
|
shebang-regex@3.0.0: {}
|
||||||
|
|
||||||
snake-case@3.0.4:
|
|
||||||
dependencies:
|
|
||||||
dot-case: 3.0.4
|
|
||||||
tslib: 2.6.3
|
|
||||||
|
|
||||||
source-map-js@1.2.1: {}
|
source-map-js@1.2.1: {}
|
||||||
|
|
||||||
source-map@0.5.7: {}
|
source-map@0.5.7: {}
|
||||||
@ -4823,7 +4603,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
typescript: 5.8.2
|
typescript: 5.8.2
|
||||||
|
|
||||||
tslib@2.6.3: {}
|
tslib@2.6.3:
|
||||||
|
optional: true
|
||||||
|
|
||||||
turbo-stream@2.4.0: {}
|
turbo-stream@2.4.0: {}
|
||||||
|
|
||||||
@ -4835,11 +4616,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
prelude-ls: 1.2.1
|
prelude-ls: 1.2.1
|
||||||
|
|
||||||
typescript-eslint@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2):
|
typescript-eslint@8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/eslint-plugin': 8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
'@typescript-eslint/eslint-plugin': 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
||||||
'@typescript-eslint/parser': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
'@typescript-eslint/parser': 8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
||||||
'@typescript-eslint/utils': 8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
'@typescript-eslint/utils': 8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
|
||||||
eslint: 9.21.0(jiti@2.4.2)
|
eslint: 9.21.0(jiti@2.4.2)
|
||||||
typescript: 5.8.2
|
typescript: 5.8.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@ -4859,14 +4640,6 @@ snapshots:
|
|||||||
escalade: 3.2.0
|
escalade: 3.2.0
|
||||||
picocolors: 1.1.0
|
picocolors: 1.1.0
|
||||||
|
|
||||||
upper-case-first@2.0.2:
|
|
||||||
dependencies:
|
|
||||||
tslib: 2.6.3
|
|
||||||
|
|
||||||
upper-case@2.0.2:
|
|
||||||
dependencies:
|
|
||||||
tslib: 2.6.3
|
|
||||||
|
|
||||||
uri-js@4.4.1:
|
uri-js@4.4.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
punycode: 2.3.1
|
punycode: 2.3.1
|
||||||
@ -4875,13 +4648,13 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
react: 19.0.0
|
react: 19.0.0
|
||||||
|
|
||||||
vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1):
|
vite@6.2.0(@types/node@22.13.9)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.5.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.25.0
|
esbuild: 0.25.0
|
||||||
postcss: 8.5.3
|
postcss: 8.5.3
|
||||||
rollup: 4.34.8
|
rollup: 4.34.8
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 22.13.8
|
'@types/node': 22.13.9
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
jiti: 2.4.2
|
jiti: 2.4.2
|
||||||
lightningcss: 1.29.1
|
lightningcss: 1.29.1
|
||||||
@ -4889,10 +4662,6 @@ snapshots:
|
|||||||
|
|
||||||
w3c-keyname@2.2.8: {}
|
w3c-keyname@2.2.8: {}
|
||||||
|
|
||||||
warning@4.0.3:
|
|
||||||
dependencies:
|
|
||||||
loose-envify: 1.4.0
|
|
||||||
|
|
||||||
web-streams-polyfill@4.0.0-beta.3: {}
|
web-streams-polyfill@4.0.0-beta.3: {}
|
||||||
|
|
||||||
webidl-conversions@3.0.1: {}
|
webidl-conversions@3.0.1: {}
|
||||||
|
87
src/main.tsx
87
src/main.tsx
@ -1,87 +1,16 @@
|
|||||||
import { createRoot, Root } from 'react-dom/client';
|
import { page, app } from './routes';
|
||||||
import { App } from './App.tsx';
|
|
||||||
import { useContextKey } from '@kevisual/system-lib/dist/web-config';
|
|
||||||
import './index.css';
|
|
||||||
import { QueryRouterServer } from '@kevisual/system-lib/dist/router-browser';
|
|
||||||
import { Editor } from './pages/editor/index.tsx';
|
|
||||||
import { ExampleApp } from './modules/panels/Example.tsx';
|
|
||||||
|
|
||||||
const page = useContextKey('page');
|
page.addPage('/', 'wallnote');
|
||||||
const wallnoteDom = useContextKey('wallnoteDom', () => {
|
|
||||||
return document.getElementById('root');
|
|
||||||
});
|
|
||||||
const app = useContextKey<QueryRouterServer>('app');
|
|
||||||
app
|
|
||||||
.route({
|
|
||||||
path: 'wallnote',
|
|
||||||
key: 'getDomId',
|
|
||||||
description: '获取墙记的dom',
|
|
||||||
run: async (ctx) => {
|
|
||||||
console.log('ctx', ctx);
|
|
||||||
ctx.body = 'wallnoteDom';
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.addTo(app);
|
|
||||||
|
|
||||||
let root: Root | null = null;
|
|
||||||
app
|
|
||||||
.route({
|
|
||||||
path: 'wallnote',
|
|
||||||
key: 'getWallnoteReactDom',
|
|
||||||
description: '获取墙记的react dom',
|
|
||||||
run: async (ctx) => {
|
|
||||||
const root = await useContextKey('wallReactRoot');
|
|
||||||
if (!root) {
|
|
||||||
ctx.throw(404, 'wallReactRoot not found');
|
|
||||||
}
|
|
||||||
ctx.body = 'wallReactRoot';
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.addTo(app);
|
|
||||||
|
|
||||||
app
|
|
||||||
.route({
|
|
||||||
path: 'wallnote',
|
|
||||||
key: 'render',
|
|
||||||
description: '渲染墙记',
|
|
||||||
run: async (ctx) => {
|
|
||||||
root = createRoot(wallnoteDom!);
|
|
||||||
root.render(<App />);
|
|
||||||
useContextKey('wallReactRoot', () => root, true);
|
|
||||||
ctx.body = 'wallReactRoot';
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.addTo(app);
|
|
||||||
|
|
||||||
page.addPage('/note/:id', 'wallnote');
|
|
||||||
page.subscribe(
|
|
||||||
'wallnote',
|
|
||||||
() => {
|
|
||||||
root = createRoot(wallnoteDom!);
|
|
||||||
root.render(<App />);
|
|
||||||
},
|
|
||||||
{ runImmediately: false },
|
|
||||||
);
|
|
||||||
|
|
||||||
page.addPage('/editor', 'editor');
|
|
||||||
page.subscribe(
|
|
||||||
'editor',
|
|
||||||
() => {
|
|
||||||
root = createRoot(wallnoteDom!);
|
|
||||||
root.render(<Editor />);
|
|
||||||
},
|
|
||||||
{ runImmediately: false },
|
|
||||||
);
|
|
||||||
|
|
||||||
page.addPage('/panels', 'panels');
|
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
page.subscribe(
|
page.subscribe(
|
||||||
'panels',
|
'wallnote',
|
||||||
() => {
|
() => {
|
||||||
root = createRoot(wallnoteDom!);
|
app.call({
|
||||||
root.render(<ExampleApp />);
|
path: 'wallnote',
|
||||||
|
key: 'render',
|
||||||
|
});
|
||||||
},
|
},
|
||||||
{ runImmediately: true },
|
{ runImmediately: false },
|
||||||
);
|
);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
41
src/modules/ReactRenderer.tsx
Normal file
41
src/modules/ReactRenderer.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|
||||||
|
export class ReactRenderer {
|
||||||
|
component: any;
|
||||||
|
element: HTMLElement;
|
||||||
|
ref: React.RefObject<any>;
|
||||||
|
props: any;
|
||||||
|
root: any;
|
||||||
|
constructor(component: any, { props, className }: any) {
|
||||||
|
this.component = component;
|
||||||
|
const el = document.createElement('div');
|
||||||
|
this.element = el;
|
||||||
|
this.ref = React.createRef();
|
||||||
|
this.props = {
|
||||||
|
...props,
|
||||||
|
ref: this.ref,
|
||||||
|
};
|
||||||
|
el.className = className;
|
||||||
|
this.root = createRoot(this.element);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateProps(props: any) {
|
||||||
|
this.props = {
|
||||||
|
...this.props,
|
||||||
|
...props,
|
||||||
|
};
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
this.root.render(React.createElement(this.component, this.props));
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
this.root.unmount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReactRenderer;
|
4
src/modules/app.ts
Normal file
4
src/modules/app.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { useContextKey } from '@kevisual/system-lib/dist/web-config';
|
||||||
|
import { QueryRouterServer } from '@kevisual/system-lib/dist/router-browser';
|
||||||
|
|
||||||
|
export const app = useContextKey<QueryRouterServer>('app');
|
39
src/modules/editor/index.tsx
Normal file
39
src/modules/editor/index.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { TextEditor } from '@/modules/tiptap/editor';
|
||||||
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
|
||||||
|
type EditorProps = {
|
||||||
|
className?: string;
|
||||||
|
value?: string;
|
||||||
|
id?: string;
|
||||||
|
onChange?: (value: string) => void;
|
||||||
|
};
|
||||||
|
export const Editor = ({ className, value, onChange, id }: EditorProps) => {
|
||||||
|
const textEditorRef = useRef<TextEditor | null>(null);
|
||||||
|
const editorRef = useRef<HTMLDivElement>(null);
|
||||||
|
const [mount, setMount] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
const editor = new TextEditor();
|
||||||
|
textEditorRef.current = editor;
|
||||||
|
editor.createEditor(editorRef.current!, {
|
||||||
|
html: value,
|
||||||
|
onUpdateHtml: (html) => {
|
||||||
|
onChange?.(html);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
setMount(true);
|
||||||
|
return () => {
|
||||||
|
editor.destroy();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
useEffect(() => {
|
||||||
|
if (textEditorRef.current && id && mount) {
|
||||||
|
textEditorRef.current.setContent(value || '');
|
||||||
|
}
|
||||||
|
}, [id, mount]);
|
||||||
|
return (
|
||||||
|
<div className={clsx('w-full h-full editor-container relative', className)}>
|
||||||
|
<div ref={editorRef} className={clsx('w-full h-full node-editor', className)}></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -1,33 +0,0 @@
|
|||||||
import React, { useEffect } from 'react';
|
|
||||||
import WindowManager from './components/WindowManager';
|
|
||||||
import { demoWindows } from './demo/DemoWindows';
|
|
||||||
import './style.css';
|
|
||||||
import { useShallow } from 'zustand/react/shallow';
|
|
||||||
import { usePanelStore } from './store';
|
|
||||||
import { useListenCmdB } from './hooks/use-listen-b';
|
|
||||||
|
|
||||||
export function ExampleApp() {
|
|
||||||
const { data, toggleAICommand, init } = usePanelStore(
|
|
||||||
useShallow((state) => {
|
|
||||||
return {
|
|
||||||
data: state.data,
|
|
||||||
toggleAICommand: state.toggleAICommand,
|
|
||||||
init: state.init,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
useEffect(() => {
|
|
||||||
init?.();
|
|
||||||
}, [init]);
|
|
||||||
useListenCmdB(() => {
|
|
||||||
toggleAICommand?.();
|
|
||||||
console.log('toggleAICommand');
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<div className='h-screen w-screen overflow-hidden bg-gray-800'>
|
|
||||||
<WindowManager windows={data?.windows || []} showTaskbar={data?.showTaskbar} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ExampleApp;
|
|
52
src/modules/panels/Panels.tsx
Normal file
52
src/modules/panels/Panels.tsx
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import React, { useEffect, useRef } from 'react';
|
||||||
|
import WindowManager from './components/WindowManager';
|
||||||
|
import { demoWindows } from './demo/DemoWindows';
|
||||||
|
import './style.css';
|
||||||
|
import { useShallow } from 'zustand/react/shallow';
|
||||||
|
import { usePanelStore } from './store';
|
||||||
|
import { useListenCmdB } from './hooks/use-listen-b';
|
||||||
|
import { managerRender } from './render/main';
|
||||||
|
console.log('managerRender', managerRender);
|
||||||
|
export function Panels() {
|
||||||
|
const ref = useRef<any>(null);
|
||||||
|
const { data, toggleAICommand, init } = usePanelStore(
|
||||||
|
useShallow((state) => {
|
||||||
|
return {
|
||||||
|
data: state.data,
|
||||||
|
toggleAICommand: state.toggleAICommand,
|
||||||
|
init: state.init,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
useEffect(() => {
|
||||||
|
init?.();
|
||||||
|
}, [init]);
|
||||||
|
useListenCmdB(() => {
|
||||||
|
handleCommand();
|
||||||
|
});
|
||||||
|
const handleCommand = () => {
|
||||||
|
const windows = ref.current?.getWindows();
|
||||||
|
const newWindows = toggleAICommand?.(windows);
|
||||||
|
// saveWindows?.(newWindows);
|
||||||
|
ref.current?.setWindows(newWindows);
|
||||||
|
console.log('toggleAICommand', newWindows);
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('data windows', data);
|
||||||
|
}, [data]);
|
||||||
|
return (
|
||||||
|
<div className='h-screen w-screen overflow-hidden'>
|
||||||
|
<WindowManager
|
||||||
|
ref={ref}
|
||||||
|
windows={data?.windows || []}
|
||||||
|
// windows={demoWindows.slice(0, 2)}
|
||||||
|
showTaskbar={data?.showTaskbar}
|
||||||
|
onCommand={() => {
|
||||||
|
handleCommand();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Panels;
|
41
src/modules/panels/components/ReactRenderer.tsx
Normal file
41
src/modules/panels/components/ReactRenderer.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|
||||||
|
export class ReactRenderer {
|
||||||
|
component: any;
|
||||||
|
element: HTMLElement;
|
||||||
|
ref: React.RefObject<any>;
|
||||||
|
props: any;
|
||||||
|
root: any;
|
||||||
|
constructor(component: any, { props, className }: any) {
|
||||||
|
this.component = component;
|
||||||
|
const el = document.createElement('div');
|
||||||
|
this.element = el;
|
||||||
|
this.ref = React.createRef();
|
||||||
|
this.props = {
|
||||||
|
...props,
|
||||||
|
ref: this.ref,
|
||||||
|
};
|
||||||
|
el.className = className;
|
||||||
|
this.root = createRoot(this.element);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateProps(props: any) {
|
||||||
|
this.props = {
|
||||||
|
...this.props,
|
||||||
|
...props,
|
||||||
|
};
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
this.root.render(React.createElement(this.component, this.props));
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
this.root.unmount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReactRenderer;
|
@ -1,30 +1,32 @@
|
|||||||
import React, { useState, useCallback, useRef, useEffect, RefObject } from 'react';
|
import React, { useState, useCallback, useRef, useEffect, RefObject } from 'react';
|
||||||
import { Maximize2, Minimize2, Minimize, Expand, X, SquareMinus, Maximize, ChevronDown } from 'lucide-react';
|
import { Maximize2, Minimize2, Minimize, Expand, X, SquareMinus, Maximize, ChevronDown, CommandIcon } from 'lucide-react';
|
||||||
import { WindowData, WindowPosition } from '../types';
|
import { WindowData, WindowPosition } from '../types';
|
||||||
import classNames from 'clsx';
|
import classNames from 'clsx';
|
||||||
import Draggable from 'react-draggable';
|
import Draggable from 'react-draggable';
|
||||||
import { ResizableBox } from 'react-resizable';
|
import { ResizableBox } from 'react-resizable';
|
||||||
import { getIconForWindowType } from './WindowIcons';
|
import { getIconForWindowType } from './WindowIcons';
|
||||||
import { useImperativeHandle } from 'react';
|
import { useImperativeHandle } from 'react';
|
||||||
|
import { emitter } from '../modules';
|
||||||
interface WindowManagerProps {
|
interface WindowManagerProps {
|
||||||
windows: WindowData[];
|
windows: WindowData[];
|
||||||
showTaskbar?: boolean;
|
showTaskbar?: boolean;
|
||||||
onSave?: (windows: WindowData[]) => void;
|
onSave?: (windows: WindowData[]) => void;
|
||||||
|
onCommand?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Minimum window dimensions
|
// Minimum window dimensions
|
||||||
const MIN_WINDOW_WIDTH = 300;
|
const MIN_WINDOW_WIDTH = 300;
|
||||||
const MIN_WINDOW_HEIGHT = 200;
|
const MIN_WINDOW_HEIGHT = 200;
|
||||||
|
|
||||||
const WindowManager = React.forwardRef(({ windows: initialWindows, showTaskbar = true, onSave }: WindowManagerProps, ref) => {
|
const WindowManager = React.forwardRef(({ windows: initialWindows, showTaskbar = true, onSave, onCommand }: WindowManagerProps, ref) => {
|
||||||
const [windows, setWindows] = useState<WindowData[]>(initialWindows);
|
const [windows, setWindows] = useState<WindowData[]>(initialWindows);
|
||||||
const [minimizedWindows, setMinimizedWindows] = useState<string[]>([]);
|
|
||||||
const [fullscreenWindow, setFullscreenWindow] = useState<string | null>(null);
|
const [fullscreenWindow, setFullscreenWindow] = useState<string | null>(null);
|
||||||
const [windowPositions, setWindowPositions] = useState<Record<string, WindowPosition>>({});
|
const [windowPositions, setWindowPositions] = useState<Record<string, WindowPosition>>({});
|
||||||
const [activeWindow, setActiveWindow] = useState<string | null>(null);
|
const [activeWindow, setActiveWindow] = useState<string | null>(null);
|
||||||
const [maxZIndex, setMaxZIndex] = useState(100);
|
const [maxZIndex, setMaxZIndex] = useState(100);
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const [mount, setMount] = useState(false);
|
const [mount, setMount] = useState(false);
|
||||||
|
const [update, setUpdate] = useState(0);
|
||||||
// Create stable refs for each window
|
// Create stable refs for each window
|
||||||
const windowRefs = useRef<Record<string, React.RefObject<HTMLDivElement | null>>>({});
|
const windowRefs = useRef<Record<string, React.RefObject<HTMLDivElement | null>>>({});
|
||||||
const draggableRefs = useRef<Record<string, React.RefObject<HTMLDivElement | null>>>({});
|
const draggableRefs = useRef<Record<string, React.RefObject<HTMLDivElement | null>>>({});
|
||||||
@ -36,6 +38,11 @@ const WindowManager = React.forwardRef(({ windows: initialWindows, showTaskbar =
|
|||||||
getWindows: () => {
|
getWindows: () => {
|
||||||
return windows;
|
return windows;
|
||||||
},
|
},
|
||||||
|
setWindows: (windows: WindowData[]) => {
|
||||||
|
console.log('setWindows in manager', windows);
|
||||||
|
setWindows(windows);
|
||||||
|
setUpdate((prev) => prev + 1);
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('initialWindows', initialWindows);
|
console.log('initialWindows', initialWindows);
|
||||||
@ -71,7 +78,7 @@ const WindowManager = React.forwardRef(({ windows: initialWindows, showTaskbar =
|
|||||||
setWindowPositions(positions);
|
setWindowPositions(positions);
|
||||||
setMaxZIndex(1000 + windows.length);
|
setMaxZIndex(1000 + windows.length);
|
||||||
setMount(true);
|
setMount(true);
|
||||||
}, [windows.length]);
|
}, [windows.length, update]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mount) {
|
if (mount) {
|
||||||
const newWindows = windows
|
const newWindows = windows
|
||||||
@ -106,12 +113,20 @@ const WindowManager = React.forwardRef(({ windows: initialWindows, showTaskbar =
|
|||||||
const handleRemoveWindow = useCallback(
|
const handleRemoveWindow = useCallback(
|
||||||
(windowId: string) => {
|
(windowId: string) => {
|
||||||
const window = windows.find((w) => w.id === windowId);
|
const window = windows.find((w) => w.id === windowId);
|
||||||
if (window?.onHidden) {
|
const command = window?.commandList?.find((c) => c.key === 'close');
|
||||||
window.onHidden();
|
if (command) {
|
||||||
|
emitter.emit('window-command', { windowData: window, command });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setWindows((prev) => prev.filter((w) => w.id !== windowId));
|
setWindows((prev) => prev.filter((w) => w.id !== windowId));
|
||||||
setMinimizedWindows((prev) => prev.filter((id) => id !== windowId));
|
setWindows((prev) =>
|
||||||
|
prev.map((w) => {
|
||||||
|
if (w.id === windowId) {
|
||||||
|
return { ...w, isMinimized: false };
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
}),
|
||||||
|
);
|
||||||
if (fullscreenWindow === windowId) {
|
if (fullscreenWindow === windowId) {
|
||||||
setFullscreenWindow(null);
|
setFullscreenWindow(null);
|
||||||
}
|
}
|
||||||
@ -122,36 +137,44 @@ const WindowManager = React.forwardRef(({ windows: initialWindows, showTaskbar =
|
|||||||
// Handle window minimize
|
// Handle window minimize
|
||||||
const handleMinimizeWindow = useCallback(
|
const handleMinimizeWindow = useCallback(
|
||||||
(windowId: string) => {
|
(windowId: string) => {
|
||||||
if (minimizedWindows.includes(windowId)) {
|
let needBringToFront = false;
|
||||||
setMinimizedWindows((prev) => prev.filter((id) => id !== windowId));
|
setWindows((prev) =>
|
||||||
// Bring window to front when unminimizing
|
prev.map((w) => {
|
||||||
bringToFront(windowId);
|
if (w.id === windowId) {
|
||||||
} else {
|
needBringToFront = !w.isMinimized;
|
||||||
setMinimizedWindows((prev) => [...prev, windowId]);
|
return { ...w, isMinimized: !w.isMinimized };
|
||||||
}
|
}
|
||||||
|
return w;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
if (fullscreenWindow === windowId) {
|
if (fullscreenWindow === windowId) {
|
||||||
setFullscreenWindow(null);
|
setFullscreenWindow(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needBringToFront) {
|
||||||
|
bringToFront(windowId);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[minimizedWindows, fullscreenWindow],
|
[, fullscreenWindow],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handle window fullscreen
|
// Handle window fullscreen
|
||||||
const handleFullscreenWindow = useCallback(
|
const handleFullscreenWindow = useCallback((windowId: string) => {
|
||||||
(windowId: string) => {
|
|
||||||
setFullscreenWindow((prev) => (prev === windowId ? null : windowId));
|
setFullscreenWindow((prev) => (prev === windowId ? null : windowId));
|
||||||
|
|
||||||
// Ensure window is not minimized when going fullscreen
|
// Ensure window is not minimized when going fullscreen
|
||||||
if (minimizedWindows.includes(windowId)) {
|
setWindows((prev) =>
|
||||||
setMinimizedWindows((prev) => prev.filter((id) => id !== windowId));
|
prev.map((w) => {
|
||||||
|
if (w.id === windowId) {
|
||||||
|
return { ...w, isMinimized: false };
|
||||||
}
|
}
|
||||||
|
return w;
|
||||||
|
}),
|
||||||
|
);
|
||||||
// Bring to front when going fullscreen
|
// Bring to front when going fullscreen
|
||||||
bringToFront(windowId);
|
bringToFront(windowId);
|
||||||
},
|
}, []);
|
||||||
[minimizedWindows],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Bring window to front
|
// Bring window to front
|
||||||
const bringToFront = useCallback(
|
const bringToFront = useCallback(
|
||||||
@ -228,19 +251,19 @@ const WindowManager = React.forwardRef(({ windows: initialWindows, showTaskbar =
|
|||||||
// Render the taskbar with minimized windows
|
// Render the taskbar with minimized windows
|
||||||
const renderTaskbar = () => {
|
const renderTaskbar = () => {
|
||||||
const showWindowsList = windows.filter((window) => window.show && window.showTaskbar);
|
const showWindowsList = windows.filter((window) => window.show && window.showTaskbar);
|
||||||
if (showWindowsList.length === 0) return null;
|
// if (showWindowsList.length === 0) return null;
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// const handleResize = () => {
|
// const handleResize = () => {
|
||||||
// const icons = document.querySelectorAll('.more-icon');
|
// // const icons = document.querySelectorAll('.more-icon');
|
||||||
// icons.forEach((iconEl) => {
|
// // icons.forEach((iconEl) => {
|
||||||
// const icon = iconEl as HTMLElement;
|
// // const icon = iconEl as HTMLElement;
|
||||||
// const button = icon.closest('button');
|
// // const button = icon.closest('button');
|
||||||
// if (button && button.offsetWidth <= 150) {
|
// // if (button && button.offsetWidth <= 150) {
|
||||||
// icon.style.display = 'none';
|
// // icon.style.display = 'none';
|
||||||
// } else {
|
// // } else {
|
||||||
// icon.style.display = 'block';
|
// // icon.style.display = 'block';
|
||||||
// }
|
// // }
|
||||||
// });
|
// // });
|
||||||
// };
|
// };
|
||||||
|
|
||||||
// window.addEventListener('resize', handleResize);
|
// window.addEventListener('resize', handleResize);
|
||||||
@ -251,9 +274,16 @@ const WindowManager = React.forwardRef(({ windows: initialWindows, showTaskbar =
|
|||||||
// };
|
// };
|
||||||
// }, []);
|
// }, []);
|
||||||
return (
|
return (
|
||||||
<div className=' pointer-events-auto fixed w-full overflow-x-auto bottom-0 left-0 right-0 bg-gray-200 text-white p-2 flex space-x-2 z-[9000]'>
|
<div className=' pointer-events-auto fixed w-full overflow-x-auto bottom-0 left-0 right-0 bg-gray-200 text-white p-2 flex space-x-2 z-[9000] h-[40px]'>
|
||||||
|
<div
|
||||||
|
className='flex items-center space-x-2 cursor-pointer bg-blue-600 rounded-md p-1'
|
||||||
|
onClick={() => {
|
||||||
|
onCommand?.();
|
||||||
|
}}>
|
||||||
|
<CommandIcon size={16} />
|
||||||
|
</div>
|
||||||
{showWindowsList.map((window) => {
|
{showWindowsList.map((window) => {
|
||||||
const isMinimized = minimizedWindows.includes(window.id);
|
const isMinimized = window.isMinimized;
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={window.id}
|
key={window.id}
|
||||||
@ -261,10 +291,11 @@ const WindowManager = React.forwardRef(({ windows: initialWindows, showTaskbar =
|
|||||||
'px-3 py-1 rounded text-sm max-w-[200px] truncate flex items-center justify-between',
|
'px-3 py-1 rounded text-sm max-w-[200px] truncate flex items-center justify-between',
|
||||||
isMinimized ? 'bg-gray-600 hover:bg-gray-500' : 'bg-blue-600 hover:bg-blue-500',
|
isMinimized ? 'bg-gray-600 hover:bg-gray-500' : 'bg-blue-600 hover:bg-blue-500',
|
||||||
activeWindow === window.id && 'shadow-lg',
|
activeWindow === window.id && 'shadow-lg',
|
||||||
|
'bar-button',
|
||||||
'cursor-pointer',
|
'cursor-pointer',
|
||||||
)}
|
)}
|
||||||
onClick={() => handleMinimizeWindow(window.id)}>
|
onClick={() => handleMinimizeWindow(window.id)}>
|
||||||
<span className='truncate min-w-[16px]'>{window.title}</span>
|
<span className='truncate min-w-[8px]'>{window.title}</span>
|
||||||
<div className='flex items-center space-x-1 ml-2'>
|
<div className='flex items-center space-x-1 ml-2'>
|
||||||
{/* {isMinimized ? <Maximize className='cursor-pointer more-icon' size={16} /> : <SquareMinus className='cursor-pointer more-icon' size={16} />} */}
|
{/* {isMinimized ? <Maximize className='cursor-pointer more-icon' size={16} /> : <SquareMinus className='cursor-pointer more-icon' size={16} />} */}
|
||||||
<ChevronDown className='cursor-pointer' size={16} />
|
<ChevronDown className='cursor-pointer' size={16} />
|
||||||
@ -288,13 +319,12 @@ const WindowManager = React.forwardRef(({ windows: initialWindows, showTaskbar =
|
|||||||
|
|
||||||
// Render a fixed position window
|
// Render a fixed position window
|
||||||
const renderFixedWindow = (windowData: WindowData) => {
|
const renderFixedWindow = (windowData: WindowData) => {
|
||||||
const isMinimized = minimizedWindows.includes(windowData.id);
|
const isMinimized = windowData.isMinimized;
|
||||||
const isFullscreen = fullscreenWindow === windowData.id;
|
const isFullscreen = fullscreenWindow === windowData.id;
|
||||||
const position = windowPositions[windowData.id];
|
const position = windowPositions[windowData.id];
|
||||||
const Icon = getIconForWindowType(windowData.type || 'welcome');
|
const Icon = getIconForWindowType(windowData.type || 'welcome');
|
||||||
const showRounded = windowData.showRounded ?? true;
|
const showRounded = windowData.showRounded ?? true;
|
||||||
if (!position) return null;
|
if (!position) return null;
|
||||||
if (isMinimized) return null;
|
|
||||||
|
|
||||||
// Convert width and height to numbers for Resizable component
|
// Convert width and height to numbers for Resizable component
|
||||||
const width = isFullscreen ? window.innerWidth : position.width;
|
const width = isFullscreen ? window.innerWidth : position.width;
|
||||||
@ -310,21 +340,25 @@ const WindowManager = React.forwardRef(({ windows: initialWindows, showTaskbar =
|
|||||||
|
|
||||||
const windowRef = windowRefs.current[windowData.id];
|
const windowRef = windowRefs.current[windowData.id];
|
||||||
const draggableRef = draggableRefs.current[windowData.id];
|
const draggableRef = draggableRefs.current[windowData.id];
|
||||||
|
const zIndex = isFullscreen ? 9999 : windowData.id == '__ai__' ? 3000 : position.zIndex;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={windowData.id}
|
key={windowData.id}
|
||||||
className={classNames('absolute pointer-events-auto', windowData.show && 'block', !windowData.show && 'hidden')}
|
className={classNames(
|
||||||
|
'absolute pointer-events-auto', //
|
||||||
|
windowData.show && !isMinimized && 'block',
|
||||||
|
(!windowData.show || isMinimized) && 'hidden',
|
||||||
|
)}
|
||||||
style={{
|
style={{
|
||||||
left: isFullscreen ? 0 : position.x,
|
left: isFullscreen ? 0 : position.x,
|
||||||
top: isFullscreen ? 0 : position.y,
|
top: isFullscreen ? 0 : position.y,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
zIndex: isFullscreen ? 9999 : position.zIndex,
|
zIndex: zIndex,
|
||||||
}}
|
}}
|
||||||
ref={windowRef}>
|
ref={windowRef}>
|
||||||
<div
|
<div
|
||||||
className={classNames('window-container', isFullscreen && 'fullscreen')}
|
className={classNames('window-container', isFullscreen && 'fullscreen', showTaskbar && 'hidden-taskbar', windowData.show && !isMinimized && 'block')}
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
@ -383,7 +417,7 @@ const WindowManager = React.forwardRef(({ windows: initialWindows, showTaskbar =
|
|||||||
</div>
|
</div>
|
||||||
<div className='window-controls'>{renderWindowControls(windowData.id)}</div>
|
<div className='window-controls'>{renderWindowControls(windowData.id)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='window-content h-[calc(100%-32px)] overflow-auto p-4'>
|
<div className='window-content h-[calc(100%-32px)] overflow-auto'>
|
||||||
<div className='h-full flex flex-col'>
|
<div className='h-full flex flex-col'>
|
||||||
<WindowContent window={windowData} />
|
<WindowContent window={windowData} />
|
||||||
</div>
|
</div>
|
||||||
@ -396,7 +430,6 @@ const WindowManager = React.forwardRef(({ windows: initialWindows, showTaskbar =
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='h-screen w-screen overflow-hidden' ref={containerRef}>
|
<div className='h-screen w-screen overflow-hidden' ref={containerRef}>
|
||||||
{windows.map((window) => renderFixedWindow(window))}
|
{windows.map((window) => renderFixedWindow(window))}
|
||||||
@ -409,10 +442,10 @@ export const WindowContent = React.memo((props: { window: WindowData }) => {
|
|||||||
const { window } = props;
|
const { window } = props;
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ref.current) {
|
emitter.emit('window-load', { windowData: window, el: ref.current });
|
||||||
// 获取属性,判断是否加载对应的应用
|
return () => {
|
||||||
}
|
emitter.emit('window-unload', { windowData: window, el: ref.current });
|
||||||
console.log('window editor render', window);
|
};
|
||||||
}, []);
|
}, []);
|
||||||
return <div data-id={window.id} className='flex-1 overflow-auto editor-window' ref={ref}></div>;
|
return <div data-id={window.id} className='flex-1 overflow-auto editor-window' ref={ref}></div>;
|
||||||
});
|
});
|
||||||
|
25
src/modules/panels/components/content/SplitPanel.tsx
Normal file
25
src/modules/panels/components/content/SplitPanel.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import { useRef } from 'react';
|
||||||
|
export const SplitPanel = (porps: any) => {
|
||||||
|
const { direction, headerHeight, showHeader, chatBoxHeight, showChatBox, bodyHeight, showFooter, footerClassName, className } = porps;
|
||||||
|
const editorRef = useRef<HTMLDivElement>(null);
|
||||||
|
return (
|
||||||
|
<PanelGroup autoSaveId='example' direction={direction} className='w-full h-full editor-container relative'>
|
||||||
|
<Panel minSize={10} defaultSize={headerHeight} className={clsx('editor-header h-10', showHeader ? 'block' : 'hidden')}>
|
||||||
|
<div className='w-full h-full'>{/* editor-header */}</div>
|
||||||
|
</Panel>
|
||||||
|
<PanelResizeHandle className={clsx('editor-resize-handle border-gray-300 border-1', showHeader ? 'block' : 'hidden')} />
|
||||||
|
<Panel minSize={10} defaultSize={chatBoxHeight} className={clsx('editor-chat-box h-66', showChatBox ? 'block' : 'hidden')}>
|
||||||
|
<div className='w-full h-full'>{/* editor-chat-box */}</div>
|
||||||
|
</Panel>
|
||||||
|
<PanelResizeHandle className={clsx('editor-resize-handle border-gray-300 border-1', showChatBox ? 'block' : 'hidden')} />
|
||||||
|
<Panel minSize={10} defaultSize={bodyHeight}>
|
||||||
|
<div ref={editorRef} className={clsx('w-full h-full node-editor', className)}></div>
|
||||||
|
</Panel>
|
||||||
|
<Panel className={clsx('editor-footer h-10', showFooter ? 'block' : 'hidden', footerClassName)}>
|
||||||
|
<div className='w-full h-full'>{/* editor-footer */}</div>
|
||||||
|
</Panel>
|
||||||
|
</PanelGroup>
|
||||||
|
);
|
||||||
|
};
|
@ -1,6 +1,6 @@
|
|||||||
import { WindowData } from '../types';
|
import { WindowData } from '../types';
|
||||||
|
|
||||||
export const createEditorWindow = (data: any): WindowData => {
|
export const createDemoEditorWindow = (data: any): WindowData => {
|
||||||
return {
|
return {
|
||||||
...data,
|
...data,
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
@ -104,17 +104,17 @@ const windowPositions = {
|
|||||||
|
|
||||||
// Demo windows data using the createEditorWindow function
|
// Demo windows data using the createEditorWindow function
|
||||||
export const demoWindows: WindowData[] = [
|
export const demoWindows: WindowData[] = [
|
||||||
createEditorWindow({ title: 'Welcome', id: 'window1', type: 'welcome' }),
|
createDemoEditorWindow({ title: 'Welcome', id: 'window1', type: 'welcome' }),
|
||||||
createEditorWindow({ title: 'Image Viewer', id: 'window2', type: 'image' }),
|
createDemoEditorWindow({ title: 'Image Viewer', id: 'window2', type: 'image' }),
|
||||||
createEditorWindow({ title: 'Text Editor', id: 'window3', type: 'document' }),
|
createDemoEditorWindow({ title: 'Text Editor', id: 'window3', type: 'document' }),
|
||||||
createEditorWindow({ title: 'Calculator', id: 'window4', type: 'calculator' }),
|
createDemoEditorWindow({ title: 'Calculator', id: 'window4', type: 'calculator' }),
|
||||||
createEditorWindow({ title: 'Code Editor', id: 'code-editor', type: 'code' }),
|
createDemoEditorWindow({ title: 'Code Editor', id: 'code-editor', type: 'code' }),
|
||||||
createEditorWindow({ title: 'Document', id: 'document', type: 'document' }),
|
createDemoEditorWindow({ title: 'Document', id: 'document', type: 'document' }),
|
||||||
createEditorWindow({ title: 'Analytics', id: 'analytics', type: 'analytics' }),
|
createDemoEditorWindow({ title: 'Analytics', id: 'analytics', type: 'analytics' }),
|
||||||
createEditorWindow({ title: 'Settings', id: 'settings', type: 'settings' }),
|
createDemoEditorWindow({ title: 'Settings', id: 'settings', type: 'settings' }),
|
||||||
createEditorWindow({ title: 'Layers', id: 'layers', type: 'layers' }),
|
createDemoEditorWindow({ title: 'Layers', id: 'layers', type: 'layers' }),
|
||||||
createEditorWindow({ title: 'Database', id: 'database', type: 'database' }),
|
createDemoEditorWindow({ title: 'Database', id: 'database', type: 'database' }),
|
||||||
createEditorWindow({ title: 'Server', id: 'server', type: 'server' }),
|
createDemoEditorWindow({ title: 'Server', id: 'server', type: 'server' }),
|
||||||
createEditorWindow({ title: 'Terminal', id: 'terminal', type: 'terminal' }),
|
createDemoEditorWindow({ title: 'Terminal', id: 'terminal', type: 'terminal' }),
|
||||||
createEditorWindow({ title: 'Command', id: 'command', type: 'command' }),
|
createDemoEditorWindow({ title: 'Command', id: 'command', type: 'command' }),
|
||||||
].map((window) => ({ ...window, position: windowPositions[window.id] }));
|
].map((window) => ({ ...window, position: windowPositions[window.id] }));
|
||||||
|
@ -5,7 +5,7 @@ export const useListenCmdB = (callback: () => void) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
// Check for Command key on macOS
|
// Check for Command key on macOS
|
||||||
if (isMac ? event.metaKey && event.key === 'b' : event.ctrlKey && event.key === 'b') {
|
if ((event.metaKey || event.ctrlKey) && event.key === 'b') {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
import './style.css';
|
import './style.css';
|
||||||
|
|
||||||
|
export { Panels } from './Panels';
|
5
src/modules/panels/modules/index.ts
Normal file
5
src/modules/panels/modules/index.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { useContextKey } from '@kevisual/system-lib/dist/web-config';
|
||||||
|
import { EventEmitter } from 'eventemitter3';
|
||||||
|
export const emitter = useContextKey<EventEmitter>('emitter', () => {
|
||||||
|
return new EventEmitter();
|
||||||
|
});
|
9
src/modules/panels/render/main.ts
Normal file
9
src/modules/panels/render/main.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { useContextKey } from '@kevisual/system-lib/dist/web-config';
|
||||||
|
import { emitter } from '../modules/index';
|
||||||
|
import { ManagerRender } from './manager/manager';
|
||||||
|
export { emitter };
|
||||||
|
export { useContextKey };
|
||||||
|
|
||||||
|
export const managerRender = useContextKey<ManagerRender>('managerRender', () => {
|
||||||
|
return new ManagerRender();
|
||||||
|
});
|
111
src/modules/panels/render/manager/manager.ts
Normal file
111
src/modules/panels/render/manager/manager.ts
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import { EventEmitter } from 'eventemitter3';
|
||||||
|
import { WindowData } from '../../types';
|
||||||
|
import { useContextKey } from '@kevisual/system-lib/dist/web-config';
|
||||||
|
import { ReactRenderer } from '../../components/ReactRenderer';
|
||||||
|
import { BaseLoad } from '@kevisual/system-lib/dist/load';
|
||||||
|
import { QueryRouterServer } from '@kevisual/system-lib/dist/router-browser';
|
||||||
|
|
||||||
|
export const emitter = useContextKey<EventEmitter>('emitter', () => {
|
||||||
|
return new EventEmitter();
|
||||||
|
});
|
||||||
|
// const load = new BaseLoad();
|
||||||
|
|
||||||
|
class HtmlRender {
|
||||||
|
render({ renderRoot, data }: any) {
|
||||||
|
const div = `<div id="${data.id}">${data.title}</div>`;
|
||||||
|
renderRoot.appendChild(div);
|
||||||
|
}
|
||||||
|
destroy() {
|
||||||
|
// 什么也不做
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class BaseRender {
|
||||||
|
/**
|
||||||
|
* 在页面当中是否加载
|
||||||
|
* */
|
||||||
|
isLoaded = false;
|
||||||
|
status = 'loading';
|
||||||
|
element?: HTMLElement;
|
||||||
|
windowData?: WindowData;
|
||||||
|
render?: ReactRenderer | HtmlRender;
|
||||||
|
type?: 'react' | 'html';
|
||||||
|
async load(windowData: WindowData, element: HTMLElement) {
|
||||||
|
this.isLoaded = true;
|
||||||
|
this.windowData = windowData;
|
||||||
|
this.status = 'loaded';
|
||||||
|
this.element = element;
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const app = (await useContextKey('app')) as QueryRouterServer;
|
||||||
|
const render = windowData.render;
|
||||||
|
if (render?.command) {
|
||||||
|
const res = await app.call({
|
||||||
|
path: render.command.path,
|
||||||
|
key: render.command.key,
|
||||||
|
payload: render.command.payload,
|
||||||
|
});
|
||||||
|
if (res.code === 200) {
|
||||||
|
const { lib, type } = res.body;
|
||||||
|
if (type === 'react') {
|
||||||
|
const ReactNode = lib;
|
||||||
|
// 这是一个打开后就不需要再管理的组件
|
||||||
|
const renderNote = new ReactRenderer(ReactNode, {
|
||||||
|
props: {
|
||||||
|
id: windowData.id,
|
||||||
|
windowData: windowData,
|
||||||
|
},
|
||||||
|
className: 'w-full h-full',
|
||||||
|
});
|
||||||
|
this.render = renderNote;
|
||||||
|
this.element.appendChild(renderNote.element);
|
||||||
|
} else if (type === 'html') {
|
||||||
|
this.render = new lib() as HtmlRender;
|
||||||
|
this.render.render({
|
||||||
|
renderRoot: this.element,
|
||||||
|
data: windowData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async unload(windowData: WindowData) {
|
||||||
|
this.isLoaded = false;
|
||||||
|
if (this.type === 'react') {
|
||||||
|
this.render?.destroy();
|
||||||
|
} else if (this.type === 'html') {
|
||||||
|
this.render?.destroy();
|
||||||
|
}
|
||||||
|
this.status = 'loading';
|
||||||
|
this.windowData = undefined;
|
||||||
|
this.element = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ManagerRender {
|
||||||
|
constructor() {
|
||||||
|
const that = this;
|
||||||
|
emitter.on('window-load', (data: { windowData: WindowData; el: HTMLElement }) => {
|
||||||
|
that.load(data.windowData, data.el);
|
||||||
|
});
|
||||||
|
emitter.on('window-unload', (windowData: WindowData) => {
|
||||||
|
that.unload(windowData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
renders = new Map<string, BaseRender>();
|
||||||
|
load(windowData: WindowData, element: HTMLElement) {
|
||||||
|
const id = windowData.id;
|
||||||
|
if (this.renders.has(id)) {
|
||||||
|
this.renders.get(id)?.load(windowData, element);
|
||||||
|
} else {
|
||||||
|
const render = new BaseRender();
|
||||||
|
this.renders.set(id, render);
|
||||||
|
render.load(windowData, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unload(windowData: WindowData) {
|
||||||
|
const id = windowData.id;
|
||||||
|
if (this.renders.has(id)) {
|
||||||
|
this.renders.get(id)?.unload(windowData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
src/modules/panels/routes.ts
Normal file
42
src/modules/panels/routes.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { useContextKey } from '@kevisual/system-lib/dist/web-config';
|
||||||
|
import { QueryRouterServer } from '@kevisual/system-lib/dist/router-browser';
|
||||||
|
import { usePanelStore } from './store';
|
||||||
|
import { createEditorWindow } from './store/create/create-editor-window';
|
||||||
|
export const app = useContextKey<QueryRouterServer>('app');
|
||||||
|
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'panels',
|
||||||
|
key: 'add-editor-window',
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const { data } = ctx.query;
|
||||||
|
const state = usePanelStore.getState();
|
||||||
|
|
||||||
|
const newWindow = createEditorWindow(data.pageId, data.nodeData, {
|
||||||
|
id: data.nodeData.id,
|
||||||
|
title: data.nodeData.title,
|
||||||
|
show: true,
|
||||||
|
position: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 600,
|
||||||
|
height: 400,
|
||||||
|
zIndex: 1000,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
state.setEditorWindow(newWindow.windowData);
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'panels',
|
||||||
|
key: 'close-editor-window',
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const { data } = ctx.query;
|
||||||
|
const state = usePanelStore.getState();
|
||||||
|
state.closeEditorWindow(data.id);
|
||||||
|
})
|
||||||
|
.addTo(app);
|
56
src/modules/panels/store/create/create-editor-window.ts
Normal file
56
src/modules/panels/store/create/create-editor-window.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { WindowData } from '../../types';
|
||||||
|
import { getDocumentWidthAndHeight } from '../../utils/document-width';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建编辑器窗口
|
||||||
|
* @param id 整个页面的的id
|
||||||
|
* @param nodeData 节点数据
|
||||||
|
* @param windowData 窗口数据
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const createEditorWindow = (pageId: string, nodeData: any, windowData?: WindowData) => {
|
||||||
|
const { width, height } = getDocumentWidthAndHeight();
|
||||||
|
return {
|
||||||
|
nodeData,
|
||||||
|
windowData: {
|
||||||
|
id: nodeData.id,
|
||||||
|
type: 'editor',
|
||||||
|
title: nodeData.title || '编辑器',
|
||||||
|
showTitle: true,
|
||||||
|
showRounded: true,
|
||||||
|
showTaskbar: true,
|
||||||
|
showMoreTools: true,
|
||||||
|
defaultPosition: {
|
||||||
|
x: width - 1000,
|
||||||
|
y: 0,
|
||||||
|
width: 1000,
|
||||||
|
height: height,
|
||||||
|
zIndex: 1000,
|
||||||
|
},
|
||||||
|
moreTools: [
|
||||||
|
{
|
||||||
|
command: {
|
||||||
|
path: 'window',
|
||||||
|
key: 'close',
|
||||||
|
payload: {
|
||||||
|
id: nodeData.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
title: '关闭',
|
||||||
|
key: 'close',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
render: {
|
||||||
|
command: {
|
||||||
|
path: 'editor',
|
||||||
|
key: 'render',
|
||||||
|
payload: {
|
||||||
|
pageId: pageId,
|
||||||
|
id: nodeData.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...windowData,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
@ -5,6 +5,8 @@ import { query } from '@/modules/query';
|
|||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { getDocumentWidthAndHeight } from '../utils/document-width';
|
import { getDocumentWidthAndHeight } from '../utils/document-width';
|
||||||
import { produce } from 'immer';
|
import { produce } from 'immer';
|
||||||
|
import { createEditorWindow } from './create/create-editor-window';
|
||||||
|
import { createDemoEditorWindow } from '../demo/DemoWindows';
|
||||||
|
|
||||||
interface PanelStore {
|
interface PanelStore {
|
||||||
data?: PanelData;
|
data?: PanelData;
|
||||||
@ -12,7 +14,10 @@ interface PanelStore {
|
|||||||
init?: (id?: string) => Promise<any>;
|
init?: (id?: string) => Promise<any>;
|
||||||
id: string;
|
id: string;
|
||||||
setId: (id: string) => void;
|
setId: (id: string) => void;
|
||||||
toggleAICommand: () => void;
|
toggleAICommand: (windows: WindowData[]) => WindowData[];
|
||||||
|
saveWindows: (windows: WindowData[]) => void;
|
||||||
|
setEditorWindow: (windowData: WindowData) => void;
|
||||||
|
closeEditorWindow: (id: string) => void;
|
||||||
}
|
}
|
||||||
interface PanelData {
|
interface PanelData {
|
||||||
/**
|
/**
|
||||||
@ -22,7 +27,7 @@ interface PanelData {
|
|||||||
/**
|
/**
|
||||||
* 是否显示任务栏
|
* 是否显示任务栏
|
||||||
*/
|
*/
|
||||||
showTaskbar: boolean;
|
showTaskbar?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const usePanelStore = create<PanelStore>((set, get) => ({
|
export const usePanelStore = create<PanelStore>((set, get) => ({
|
||||||
@ -39,60 +44,91 @@ export const usePanelStore = create<PanelStore>((set, get) => ({
|
|||||||
},
|
},
|
||||||
|
|
||||||
init: async (id?: string) => {
|
init: async (id?: string) => {
|
||||||
const cache = new MyCache<PanelData>(id || 'workspace');
|
// const cache = new MyCache<PanelData>(id || 'workspace');
|
||||||
if (id) {
|
// if (id) {
|
||||||
// id存在,则获取本地和获取远程,进行对比,如果需要更新,则更新
|
// // id存在,则获取本地和获取远程,进行对比,如果需要更新,则更新
|
||||||
if (cache.data) {
|
// if (cache.data) {
|
||||||
const updatedAt = cache.updatedAt;
|
// const updatedAt = cache.updatedAt;
|
||||||
const res = await query.post({ path: 'workspace', key: 'env', id, updatedAt });
|
// const res = await query.post({ path: 'workspace', key: 'env', id, updatedAt });
|
||||||
if (res.code === 200) {
|
// if (res.code === 200) {
|
||||||
const newData = res.data;
|
// const newData = res.data;
|
||||||
if (newData) {
|
// if (newData) {
|
||||||
cache.setData(newData);
|
// cache.setData(newData);
|
||||||
|
// set({
|
||||||
|
// data: newData,
|
||||||
|
// id: id,
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// set({ data: cache.data, id: id });
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// toast.error('获取环境失败');
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// const res = await query.post({ path: 'workspace', key: 'env', id });
|
||||||
|
// if (res.code === 200) {
|
||||||
|
// const newData = res.data;
|
||||||
|
// if (newData) {
|
||||||
|
// cache.setData(newData);
|
||||||
|
// set({
|
||||||
|
// data: newData,
|
||||||
|
// id: id,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else if (cache.data) {
|
||||||
|
// set({
|
||||||
|
// data: cache.data,
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// set({
|
||||||
|
// data: { windows: [], showTaskbar: true },
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
set({
|
set({
|
||||||
data: newData,
|
data: {
|
||||||
id: id,
|
windows: [e.windowData],
|
||||||
});
|
showTaskbar: true,
|
||||||
} else {
|
|
||||||
set({ data: cache.data, id: id });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
toast.error('获取环境失败');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const res = await query.post({ path: 'workspace', key: 'env', id });
|
|
||||||
if (res.code === 200) {
|
|
||||||
const newData = res.data;
|
|
||||||
if (newData) {
|
|
||||||
cache.setData(newData);
|
|
||||||
set({
|
|
||||||
data: newData,
|
|
||||||
id: id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (cache.data) {
|
|
||||||
set({
|
|
||||||
data: cache.data,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
set({
|
|
||||||
data: { windows: [], showTaskbar: true },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
toggleAICommand: () => {
|
});
|
||||||
|
},
|
||||||
|
setEditorWindow: (windowData: WindowData) => {
|
||||||
const { data } = get();
|
const { data } = get();
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const has = data.windows.find((w) => w.id === windowData.id);
|
||||||
|
if (has) {
|
||||||
|
data.windows = data.windows.map((w) => {
|
||||||
|
if (w.id === windowData.id) {
|
||||||
|
return windowData;
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
data.windows.push(windowData);
|
||||||
|
}
|
||||||
|
console.log('data', data);
|
||||||
|
set({ data: { ...data, windows: data.windows } });
|
||||||
|
},
|
||||||
|
toggleAICommand: (windows: WindowData[]) => {
|
||||||
|
// const { data } = get();
|
||||||
|
// if (!data) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
const data = { windows };
|
||||||
const has = data.windows.find((w) => w.id === '__ai__');
|
const has = data.windows.find((w) => w.id === '__ai__');
|
||||||
if (has) {
|
if (has) {
|
||||||
data.windows = data.windows.map((w) => {
|
data.windows = data.windows.map((w) => {
|
||||||
if (w.id === '__ai__') {
|
if (w.id === '__ai__') {
|
||||||
return { ...w, show: !w.show };
|
console.log('w', w.isMinimized, w.show);
|
||||||
|
if (w.isMinimized || !w.show) {
|
||||||
|
return { ...w, show: true, isMinimized: false };
|
||||||
|
}
|
||||||
|
return { ...w, show: !w.show, isMinimized: false };
|
||||||
}
|
}
|
||||||
return w;
|
return w;
|
||||||
});
|
});
|
||||||
@ -101,10 +137,10 @@ export const usePanelStore = create<PanelStore>((set, get) => ({
|
|||||||
data.windows.push({
|
data.windows.push({
|
||||||
id: '__ai__',
|
id: '__ai__',
|
||||||
title: 'AI Command',
|
title: 'AI Command',
|
||||||
type: 'commandƒ',
|
type: 'command',
|
||||||
position: {
|
position: {
|
||||||
x: 100,
|
x: 100,
|
||||||
y: height - 200,
|
y: height - 200 - 40,
|
||||||
width: width - 200,
|
width: width - 200,
|
||||||
height: 200,
|
height: 200,
|
||||||
zIndex: 1000,
|
zIndex: 1000,
|
||||||
@ -113,7 +149,37 @@ export const usePanelStore = create<PanelStore>((set, get) => ({
|
|||||||
show: true,
|
show: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
set({ data: { ...data, windows: data.windows } });
|
// set({ data: { ...data, windows: data.windows } });
|
||||||
console.log('data', data);
|
console.log('data', data);
|
||||||
|
return data.windows;
|
||||||
|
},
|
||||||
|
saveWindows: (windows: WindowData[]) => {
|
||||||
|
set({ data: { ...get().data, windows } });
|
||||||
|
},
|
||||||
|
closeEditorWindow: (id: string) => {
|
||||||
|
const { data } = get();
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data.windows = data.windows.filter((w) => w.id !== id);
|
||||||
|
set({ data: { ...data, windows: data.windows } });
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const e = createEditorWindow(
|
||||||
|
'123',
|
||||||
|
{
|
||||||
|
id: '123',
|
||||||
|
title: '123',
|
||||||
|
type: 'editor',
|
||||||
|
position: { x: 0, y: 0, width: 100, height: 100, zIndex: 1000 },
|
||||||
|
},
|
||||||
|
createDemoEditorWindow({
|
||||||
|
id: '123',
|
||||||
|
title: '123',
|
||||||
|
type: 'editor',
|
||||||
|
position: { x: 0, y: 0, width: 100, height: 100, zIndex: 1000 },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('e', e);
|
||||||
|
@ -22,8 +22,12 @@
|
|||||||
right: 0 !important;
|
right: 0 !important;
|
||||||
bottom: 40px !important; /* Leave space for taskbar */
|
bottom: 40px !important; /* Leave space for taskbar */
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: calc(100% - 40px) !important;
|
height: calc(100% - 40px);
|
||||||
z-index: 9999 !important;
|
z-index: 9900 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fullscreen.hidden-taskbar {
|
||||||
|
height: calc(100% - 0px) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resize handles */
|
/* Resize handles */
|
||||||
|
@ -6,6 +6,19 @@ export interface WindowPosition {
|
|||||||
height: number;
|
height: number;
|
||||||
zIndex: number;
|
zIndex: number;
|
||||||
}
|
}
|
||||||
|
export type WindowCommand = {
|
||||||
|
path: string;
|
||||||
|
key?: string;
|
||||||
|
payload?: any;
|
||||||
|
};
|
||||||
|
export type WindowCommandData = {
|
||||||
|
command: WindowCommand;
|
||||||
|
title: string;
|
||||||
|
key: string;
|
||||||
|
description?: string;
|
||||||
|
icon?: string;
|
||||||
|
onClick?: WindowCommand;
|
||||||
|
};
|
||||||
export interface WindowData {
|
export interface WindowData {
|
||||||
// 窗口的唯一标识
|
// 窗口的唯一标识
|
||||||
id: string;
|
id: string;
|
||||||
@ -34,18 +47,13 @@ export interface WindowData {
|
|||||||
// 是否显示更多工具
|
// 是否显示更多工具
|
||||||
showMoreTools?: boolean;
|
showMoreTools?: boolean;
|
||||||
// 更多工具
|
// 更多工具
|
||||||
moreTools?: MoreTool[];
|
moreTools?: WindowCommandData[];
|
||||||
// 当隐藏窗口存在,只关闭隐藏窗口,不退出程序
|
// 工具列表
|
||||||
onHidden?: () => void;
|
commandList?: WindowCommandData[];
|
||||||
}
|
// 渲染
|
||||||
export interface MoreTool {
|
render?: {
|
||||||
// 工具的名称
|
command: WindowCommand;
|
||||||
title?: string;
|
props?: any;
|
||||||
description?: string;
|
className?: string;
|
||||||
path?: string;
|
};
|
||||||
key?: string;
|
|
||||||
// 工具的图标
|
|
||||||
icon?: string;
|
|
||||||
// 工具的点击事件
|
|
||||||
onClick?: () => void;
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import Typography from '@tiptap/extension-typography';
|
|||||||
import { Markdown } from 'tiptap-markdown';
|
import { Markdown } from 'tiptap-markdown';
|
||||||
|
|
||||||
import Placeholder from '@tiptap/extension-placeholder';
|
import Placeholder from '@tiptap/extension-placeholder';
|
||||||
import { Commands, getSuggestionItems, createSuggestionConfig } from './extensions/suggestions';
|
import { Commands, getSuggestionItems, createSuggestionConfig, CommandItem } from './extensions/suggestions';
|
||||||
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight';
|
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight';
|
||||||
import { all, createLowlight } from 'lowlight';
|
import { all, createLowlight } from 'lowlight';
|
||||||
import 'highlight.js/styles/github.css';
|
import 'highlight.js/styles/github.css';
|
||||||
@ -28,22 +28,28 @@ lowlight.register('markdown', markdown);
|
|||||||
|
|
||||||
export class TextEditor {
|
export class TextEditor {
|
||||||
private editor?: Editor;
|
private editor?: Editor;
|
||||||
|
private opts?: { markdown?: string; html?: string; items?: CommandItem[]; onUpdateHtml?: (html: string) => void };
|
||||||
|
private element?: HTMLElement;
|
||||||
|
private isInitialSetup: boolean = true;
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
createEditor(el: HTMLElement, opts?: { markdown?: string; html?: string }) {
|
createEditor(el: HTMLElement, opts?: { markdown?: string; html?: string; items?: CommandItem[]; onUpdateHtml?: (html: string) => void }) {
|
||||||
if (this.editor) {
|
if (this.editor) {
|
||||||
this.destroy();
|
this.destroy();
|
||||||
}
|
}
|
||||||
|
this.opts = opts;
|
||||||
|
this.element = el;
|
||||||
const html = opts?.html || '';
|
const html = opts?.html || '';
|
||||||
const items = getSuggestionItems();
|
const items = opts?.items || getSuggestionItems();
|
||||||
const suggestionConfig = createSuggestionConfig(items);
|
const suggestionConfig = createSuggestionConfig(items);
|
||||||
|
this.isInitialSetup = true;
|
||||||
this.editor = new Editor({
|
this.editor = new Editor({
|
||||||
element: el, // 指定编辑器容器
|
element: el, // 指定编辑器容器
|
||||||
extensions: [
|
extensions: [
|
||||||
StarterKit, // 使用 StarterKit 包含基础功能
|
StarterKit, // 使用 StarterKit 包含基础功能
|
||||||
Highlight,
|
Highlight,
|
||||||
Placeholder.configure({
|
Placeholder.configure({
|
||||||
placeholder: 'Type ! to see commands (e.g., !today, !list, !good)...',
|
placeholder: 'Type ! to see commands (e.g., !today, !list !test )...',
|
||||||
}),
|
}),
|
||||||
Typography,
|
Typography,
|
||||||
Markdown,
|
Markdown,
|
||||||
@ -81,11 +87,37 @@ export class TextEditor {
|
|||||||
suggestion: suggestionConfig,
|
suggestion: suggestionConfig,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
content: html, // 初始化内容
|
content: html, // 初始化内容,
|
||||||
|
onUpdate: () => {
|
||||||
|
if (this.isInitialSetup) {
|
||||||
|
this.isInitialSetup = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.opts?.onUpdateHtml) {
|
||||||
|
this.opts.onUpdateHtml(this.editor?.getHTML() || '');
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setContent(html: string) {
|
updateSugestionConfig(items: CommandItem[]) {
|
||||||
this.editor?.commands.setContent(html);
|
if (!this.element) return;
|
||||||
|
const element = this.element;
|
||||||
|
if (this.editor) {
|
||||||
|
const content = this.editor.getHTML(); // Save current content
|
||||||
|
const opts = { ...this.opts, html: content, items };
|
||||||
|
this.createEditor(element, opts); // Recreate the editor with the new config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setContent(html: string, emitUpdate?: boolean) {
|
||||||
|
this.editor?.commands.setContent(html, emitUpdate);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* before set options ,you should has element and editor
|
||||||
|
* @param opts
|
||||||
|
*/
|
||||||
|
setOptions(opts: { markdown?: string; html?: string; items?: CommandItem[]; onUpdateHtml?: (html: string) => void }) {
|
||||||
|
this.opts = { ...this.opts, ...opts };
|
||||||
|
this.createEditor(this.element!, this.opts!);
|
||||||
}
|
}
|
||||||
getHtml() {
|
getHtml() {
|
||||||
return this.editor?.getHTML();
|
return this.editor?.getHTML();
|
||||||
@ -93,12 +125,6 @@ export class TextEditor {
|
|||||||
getContent() {
|
getContent() {
|
||||||
return this.editor?.getText();
|
return this.editor?.getText();
|
||||||
}
|
}
|
||||||
onContentChange(callback: (html: string) => void) {
|
|
||||||
this.editor?.off('update'); // 移除之前的监听
|
|
||||||
this.editor?.on('update', () => {
|
|
||||||
callback(this.editor?.getHTML() || '');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
foucus() {
|
foucus() {
|
||||||
this.editor?.view?.focus?.();
|
this.editor?.view?.focus?.();
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ export const Commands = Extension.create({
|
|||||||
suggestion: {
|
suggestion: {
|
||||||
char: '!',
|
char: '!',
|
||||||
command: ({ editor, range, props }: any) => {
|
command: ({ editor, range, props }: any) => {
|
||||||
console.log('sdfsd')
|
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
.focus()
|
.focus()
|
||||||
|
@ -60,7 +60,7 @@ export const createSuggestionConfig = (items: CommandItem[]) => {
|
|||||||
popup = document.createElement('div');
|
popup = document.createElement('div');
|
||||||
popup.className = 'commands-popup';
|
popup.className = 'commands-popup';
|
||||||
popup.style.position = 'fixed'; // Use fixed instead of absolute for better viewport positioning
|
popup.style.position = 'fixed'; // Use fixed instead of absolute for better viewport positioning
|
||||||
popup.style.zIndex = '1000';
|
popup.style.zIndex = '9999';
|
||||||
document.body.appendChild(popup);
|
document.body.appendChild(popup);
|
||||||
|
|
||||||
popup.appendChild(component.element);
|
popup.appendChild(component.element);
|
||||||
|
87
src/pages/editor/NodeTextEditor.tsx
Normal file
87
src/pages/editor/NodeTextEditor.tsx
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import { TextEditor } from '@/modules/tiptap/editor';
|
||||||
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import { Save } from 'lucide-react';
|
||||||
|
import { useWallStore } from '../wall/store/wall';
|
||||||
|
import { useShallow } from 'zustand/react/shallow';
|
||||||
|
import { app } from '../editor/app';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听ctrl+s保存内容
|
||||||
|
* esc退出编辑
|
||||||
|
* @param saveContent 保存内容
|
||||||
|
* @param exitEdit 退出编辑
|
||||||
|
*/
|
||||||
|
export const useListenCtrlS = (saveContent: () => void, exitEdit: () => void) => {
|
||||||
|
useEffect(() => {
|
||||||
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
|
if ((event.ctrlKey || event.metaKey) && event.key === 's') {
|
||||||
|
saveContent();
|
||||||
|
} else if (event.key === 'Escape') {
|
||||||
|
exitEdit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener('keydown', handleKeyDown);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('keydown', handleKeyDown);
|
||||||
|
};
|
||||||
|
}, [saveContent]);
|
||||||
|
};
|
||||||
|
type EditorProps = {
|
||||||
|
id?: string;
|
||||||
|
};
|
||||||
|
export const NodeTextEditor = ({ id }: EditorProps) => {
|
||||||
|
const textEditorRef = useRef<TextEditor | null>(null);
|
||||||
|
const editorRef = useRef<HTMLDivElement>(null);
|
||||||
|
const { getNodeById, saveNodeById } = useWallStore(useShallow((state) => ({ getNodeById: state.getNodeById, saveNodeById: state.saveNodeById })));
|
||||||
|
useEffect(() => {
|
||||||
|
const editor = new TextEditor();
|
||||||
|
textEditorRef.current = editor;
|
||||||
|
editor.createEditor(editorRef.current!, { html: '' });
|
||||||
|
getIdContent();
|
||||||
|
return () => {
|
||||||
|
editor.destroy();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
const getIdContent = async () => {
|
||||||
|
if (!id) return;
|
||||||
|
const node = await getNodeById(id);
|
||||||
|
if (node) {
|
||||||
|
textEditorRef.current?.setContent(node.data.html);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const saveContent = async () => {
|
||||||
|
if (!id) return;
|
||||||
|
const html = await textEditorRef.current?.getHtml();
|
||||||
|
if (html) {
|
||||||
|
saveNodeById(id, {
|
||||||
|
html: html,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const exitEdit = () => {
|
||||||
|
// 退出编辑
|
||||||
|
saveContent()
|
||||||
|
setTimeout(() => {
|
||||||
|
app.call({
|
||||||
|
path: 'panels',
|
||||||
|
key: 'close-editor-window',
|
||||||
|
payload: {
|
||||||
|
data: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
useListenCtrlS(saveContent, exitEdit);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={clsx('w-full h-full relative')}>
|
||||||
|
<div ref={editorRef} className={clsx('w-full h-full node-editor')}></div>
|
||||||
|
<div className='absolute top-2 right-2 cursor-pointer' onClick={() => saveContent()}>
|
||||||
|
<Save />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
5
src/pages/editor/app.ts
Normal file
5
src/pages/editor/app.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { useContextKey } from '@kevisual/system-lib/dist/web-config';
|
||||||
|
import { QueryRouterServer } from '@kevisual/system-lib/dist/router-browser';
|
||||||
|
|
||||||
|
export const app = useContextKey<QueryRouterServer>('app');
|
||||||
|
|
@ -1,32 +1,2 @@
|
|||||||
import { TextEditor } from '@/modules/tiptap/editor';
|
import { Editor } from '@/modules/editor';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
export { Editor };
|
||||||
import clsx from 'clsx';
|
|
||||||
type EditorProps = {
|
|
||||||
className?: string;
|
|
||||||
value?: string;
|
|
||||||
id?: string;
|
|
||||||
onChange?: (value: string) => void;
|
|
||||||
};
|
|
||||||
export const Editor = ({ className, value, onChange, id }: EditorProps) => {
|
|
||||||
const textEditorRef = useRef<TextEditor | null>(null);
|
|
||||||
const editorRef = useRef<HTMLDivElement>(null);
|
|
||||||
const [mount, setMount] = useState(false);
|
|
||||||
useEffect(() => {
|
|
||||||
const editor = new TextEditor();
|
|
||||||
textEditorRef.current = editor;
|
|
||||||
editor.createEditor(editorRef.current!, { html: value });
|
|
||||||
editor.onContentChange((content) => {
|
|
||||||
onChange?.(content);
|
|
||||||
});
|
|
||||||
setMount(true);
|
|
||||||
return () => {
|
|
||||||
editor.destroy();
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
useEffect(() => {
|
|
||||||
if (textEditorRef.current && id && mount) {
|
|
||||||
textEditorRef.current.setContent(value || '');
|
|
||||||
}
|
|
||||||
}, [id, mount]);
|
|
||||||
return <div ref={editorRef} className={clsx('w-full h-full node-editor', className)}></div>;
|
|
||||||
};
|
|
||||||
|
6
src/pages/wall/app.ts
Normal file
6
src/pages/wall/app.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { useContextKey } from '@kevisual/system-lib/dist/web-config';
|
||||||
|
import { QueryRouterServer } from '@kevisual/system-lib/dist/router-browser';
|
||||||
|
|
||||||
|
export const app = useContextKey<QueryRouterServer>('app');
|
||||||
|
|
||||||
|
|
@ -40,7 +40,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.tiptap {
|
.tiptap {
|
||||||
margin: 0.5rem 1rem;
|
/* margin: 0.5rem 1rem; */
|
||||||
|
margin: 0;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
|
@ -5,6 +5,7 @@ import { useWallStore } from '../store/wall';
|
|||||||
import { useShallow } from 'zustand/react/shallow';
|
import { useShallow } from 'zustand/react/shallow';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { message } from '@/modules/message';
|
import { message } from '@/modules/message';
|
||||||
|
import { app } from '../app';
|
||||||
import hljs from 'highlight.js';
|
import hljs from 'highlight.js';
|
||||||
import { Edit } from 'lucide-react';
|
import { Edit } from 'lucide-react';
|
||||||
export type WallData<T = Record<string, any>> = {
|
export type WallData<T = Record<string, any>> = {
|
||||||
@ -50,6 +51,7 @@ export const CustomNode = (props: { id: string; data: WallData; selected: boolea
|
|||||||
const wallStore = useWallStore(
|
const wallStore = useWallStore(
|
||||||
useShallow((state) => {
|
useShallow((state) => {
|
||||||
return {
|
return {
|
||||||
|
id: state.id,
|
||||||
setSelectedNode: state.setSelectedNode,
|
setSelectedNode: state.setSelectedNode,
|
||||||
saveNodes: state.saveNodes,
|
saveNodes: state.saveNodes,
|
||||||
checkAndOpen: state.checkAndOpen,
|
checkAndOpen: state.checkAndOpen,
|
||||||
@ -83,17 +85,6 @@ export const CustomNode = (props: { id: string; data: WallData; selected: boolea
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
// useEffect(() => {
|
|
||||||
// if (selected) {
|
|
||||||
// const handleDelete = (e: KeyboardEvent) => {
|
|
||||||
// if (e.key === 'Delete') {
|
|
||||||
// store.deleteNode(props.id);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// window.addEventListener('keydown', handleDelete);
|
|
||||||
// return () => window.removeEventListener('keydown', handleDelete);
|
|
||||||
// }
|
|
||||||
// }, [selected]);
|
|
||||||
const width = data.width || 100;
|
const width = data.width || 100;
|
||||||
const height = data.height || 100;
|
const height = data.height || 100;
|
||||||
const style: React.CSSProperties = {};
|
const style: React.CSSProperties = {};
|
||||||
@ -102,19 +93,30 @@ export const CustomNode = (props: { id: string; data: WallData; selected: boolea
|
|||||||
const showOpen = () => {
|
const showOpen = () => {
|
||||||
const node = store.getNode(props.id);
|
const node = store.getNode(props.id);
|
||||||
console.log('node eidt', node);
|
console.log('node eidt', node);
|
||||||
if (node) {
|
app.call({
|
||||||
const dataType: string = (node?.data?.dataType as string) || '';
|
path: 'panels',
|
||||||
if (dataType && dataType?.startsWith('image')) {
|
key: 'add-editor-window',
|
||||||
message.error('不支持编辑图片');
|
payload: {
|
||||||
return;
|
data: {
|
||||||
} else if (dataType) {
|
pageId: wallStore.id || 'local-browser',
|
||||||
message.error('不支持编辑');
|
type: 'wallnote',
|
||||||
return;
|
nodeData: node,
|
||||||
}
|
},
|
||||||
wallStore.checkAndOpen(true, node);
|
},
|
||||||
} else {
|
});
|
||||||
message.error('节点不存在');
|
// if (node) {
|
||||||
}
|
// const dataType: string = (node?.data?.dataType as string) || '';
|
||||||
|
// if (dataType && dataType?.startsWith('image')) {
|
||||||
|
// message.error('不支持编辑图片');
|
||||||
|
// return;
|
||||||
|
// } else if (dataType) {
|
||||||
|
// message.error('不支持编辑');
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// wallStore.checkAndOpen(true, node);
|
||||||
|
// } else {
|
||||||
|
// message.error('节点不存在');
|
||||||
|
// }
|
||||||
};
|
};
|
||||||
const handleSize = Math.max(10, 10 / zoom);
|
const handleSize = Math.max(10, 10 / zoom);
|
||||||
return (
|
return (
|
||||||
|
@ -57,6 +57,8 @@ interface WallState {
|
|||||||
clearId: () => Promise<void>;
|
clearId: () => Promise<void>;
|
||||||
mouseSelect: boolean;
|
mouseSelect: boolean;
|
||||||
setMouseSelect: (mouseSelect: boolean) => void;
|
setMouseSelect: (mouseSelect: boolean) => void;
|
||||||
|
getNodeById: (id: string) => Promise<NodeData | null>;
|
||||||
|
saveNodeById: (id: string, data: any) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useWallStore = create<WallState>((set, get) => ({
|
export const useWallStore = create<WallState>((set, get) => ({
|
||||||
@ -72,7 +74,6 @@ export const useWallStore = create<WallState>((set, get) => ({
|
|||||||
if (!get().id) {
|
if (!get().id) {
|
||||||
const covertData = getNodeData(nodes);
|
const covertData = getNodeData(nodes);
|
||||||
setWallData({ nodes: covertData });
|
setWallData({ nodes: covertData });
|
||||||
showMessage && message.success('保存到本地');
|
|
||||||
} else {
|
} else {
|
||||||
const { id } = get();
|
const { id } = get();
|
||||||
const userWallStore = useUserWallStore.getState();
|
const userWallStore = useUserWallStore.getState();
|
||||||
@ -201,4 +202,28 @@ export const useWallStore = create<WallState>((set, get) => ({
|
|||||||
},
|
},
|
||||||
mouseSelect: true,
|
mouseSelect: true,
|
||||||
setMouseSelect: (mouseSelect) => set({ mouseSelect }),
|
setMouseSelect: (mouseSelect) => set({ mouseSelect }),
|
||||||
|
getNodeById: async (id: string) => {
|
||||||
|
const data = await getWallData();
|
||||||
|
const nodes = data?.nodes || [];
|
||||||
|
return nodes.find((node) => node.id === id);
|
||||||
|
},
|
||||||
|
saveNodeById: async (id: string, data: any) => {
|
||||||
|
let node = await get().getNodeById(id);
|
||||||
|
if (node) {
|
||||||
|
node.data = {
|
||||||
|
...node.data,
|
||||||
|
...data,
|
||||||
|
};
|
||||||
|
const newNodes = get().nodes.map((item) => {
|
||||||
|
if (item.id === id) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
set({
|
||||||
|
nodes: newNodes,
|
||||||
|
});
|
||||||
|
get().saveNodes(newNodes, { showMessage: false });
|
||||||
|
}
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
73
src/routes.tsx
Normal file
73
src/routes.tsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
import { App } from './App.tsx';
|
||||||
|
import { useContextKey } from '@kevisual/system-lib/dist/web-config';
|
||||||
|
import './index.css';
|
||||||
|
import { QueryRouterServer } from '@kevisual/system-lib/dist/router-browser';
|
||||||
|
import { NodeTextEditor } from './pages/editor/NodeTextEditor.tsx';
|
||||||
|
import { Panels } from './modules/panels/index.tsx';
|
||||||
|
import { Page } from '@kevisual/system-lib/dist/web-page';
|
||||||
|
|
||||||
|
import './modules/panels/routes.ts';
|
||||||
|
|
||||||
|
export const page = useContextKey<Page>('page');
|
||||||
|
export const app = useContextKey<QueryRouterServer>('app');
|
||||||
|
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'wallnote',
|
||||||
|
key: 'render',
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const rootEl = document.getElementById('root') as HTMLElement;
|
||||||
|
const root = createRoot(rootEl);
|
||||||
|
useContextKey('wallnoteRoot', () => root, true);
|
||||||
|
root.render(<App />);
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'wallnote',
|
||||||
|
key: 'lib',
|
||||||
|
description: '获取编辑器',
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
ctx.body = { Panels };
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'editor',
|
||||||
|
key: 'render',
|
||||||
|
description: '获取编辑器',
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
ctx.body = { lib: NodeTextEditor, type: 'react', Panels };
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'editor',
|
||||||
|
key: 'render2',
|
||||||
|
description: '获取编辑器',
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
class HtmlRender {
|
||||||
|
render({ renderRoot, data }: any) {
|
||||||
|
const newDivStr = `<div id="${data.id}">${data.title}</div>`;
|
||||||
|
const newDiv = document.createElement('div');
|
||||||
|
newDiv.innerHTML = newDivStr;
|
||||||
|
renderRoot.appendChild(newDiv);
|
||||||
|
}
|
||||||
|
destroy() {
|
||||||
|
// 什么也不做
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.body = {
|
||||||
|
lib: HtmlRender,
|
||||||
|
type: 'html',
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.addTo(app);
|
@ -1,8 +1,6 @@
|
|||||||
import { createRoot, Root } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
import { AiApp } from './AiApp';
|
|
||||||
import { app, initAIAppRootOrCreate, useContextKey } from '../app';
|
import { app, initAIAppRootOrCreate, useContextKey } from '../app';
|
||||||
import { Editor } from '@/pages/editor/index';
|
import { Panels } from '@/modules/panels/index';
|
||||||
import { ExampleApp } from '@/modules/panels/Example';
|
|
||||||
initAIAppRootOrCreate();
|
initAIAppRootOrCreate();
|
||||||
|
|
||||||
app
|
app
|
||||||
@ -12,15 +10,11 @@ app
|
|||||||
description: '渲染AI应用',
|
description: '渲染AI应用',
|
||||||
run: async (ctx) => {
|
run: async (ctx) => {
|
||||||
const root = initAIAppRootOrCreate();
|
const root = initAIAppRootOrCreate();
|
||||||
console.log('ai render');
|
|
||||||
console.log('ai render', root);
|
|
||||||
if (!root) {
|
if (!root) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const aiRoot = createRoot(root!);
|
const aiRoot = createRoot(root!);
|
||||||
// aiRoot.render(<Editor />);
|
aiRoot.render(<Panels />);
|
||||||
// aiRoot.render(<AiApp />);
|
|
||||||
aiRoot.render(<ExampleApp />);
|
|
||||||
useContextKey('aiRoot', () => aiRoot, true);
|
useContextKey('aiRoot', () => aiRoot, true);
|
||||||
ctx.body = 'aiRoot';
|
ctx.body = 'aiRoot';
|
||||||
},
|
},
|
||||||
|
@ -28,6 +28,7 @@ export const queryAI = useContextKey<QueryAI>('queryAI', () => {
|
|||||||
return new QueryAI();
|
return new QueryAI();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const rootEl = document.getElementById('root') as HTMLElement;
|
||||||
export const initAIAppRootOrCreate = () => {
|
export const initAIAppRootOrCreate = () => {
|
||||||
const root = document.getElementById('ai-root');
|
const root = document.getElementById('ai-root');
|
||||||
if (!root) {
|
if (!root) {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { app, page, load } from './app';
|
import { app, page, load } from './app';
|
||||||
|
import '../src/routes';
|
||||||
import './ai-app/main';
|
import './ai-app/main';
|
||||||
import './tailwind.css';
|
import './tailwind.css';
|
||||||
import './workspace/entry';
|
import './workspace/entry';
|
||||||
@ -8,6 +9,7 @@ page.addPage('/', 'workspace');
|
|||||||
const runLoad = () => {
|
const runLoad = () => {
|
||||||
load.load(
|
load.load(
|
||||||
() => {
|
() => {
|
||||||
|
console.log('runLoad');
|
||||||
// @TODO 这里需要优化,不能每次都去调用
|
// @TODO 这里需要优化,不能每次都去调用
|
||||||
page.subscribe(
|
page.subscribe(
|
||||||
'workspace',
|
'workspace',
|
||||||
@ -36,4 +38,4 @@ const runLoad = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// runLoad()
|
runLoad()
|
@ -12,14 +12,14 @@
|
|||||||
|
|
||||||
/* # 背景设置为透明 */
|
/* # 背景设置为透明 */
|
||||||
#ai-root {
|
#ai-root {
|
||||||
/* @apply bg-transparent */
|
@apply bg-transparent;
|
||||||
@apply border-none box-border border-2 border-gray-300 rounded-md;
|
@apply border-none box-border border-2 border-gray-300 rounded-md;
|
||||||
@apply pointer-events-none;
|
@apply pointer-events-none;
|
||||||
}
|
}
|
||||||
#ai-root {
|
#ai-root {
|
||||||
.node-editor {
|
.node-editor {
|
||||||
@apply pointer-events-auto;
|
@apply pointer-events-auto;
|
||||||
@apply absolute bottom-0 left-0 w-full h-[20vh] border border-gray-300 shadow-md;
|
@apply absolute bottom-0 left-0 w-full border border-gray-300 shadow-md;
|
||||||
.tiptap {
|
.tiptap {
|
||||||
@apply mx-0 h-full overflow-y-auto;
|
@apply mx-0 h-full overflow-y-auto;
|
||||||
}
|
}
|
||||||
@ -28,5 +28,3 @@
|
|||||||
@apply w-full h-full overflow-hidden;
|
@apply w-full h-full overflow-hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,15 +15,16 @@ app
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log('workspace enter');
|
console.log('workspace enter');
|
||||||
|
console.log('workspace enter', isRender);
|
||||||
if (!isRender) {
|
if (!isRender) {
|
||||||
app.call({
|
const res = await app.call({
|
||||||
path: 'wallnote',
|
path: 'wallnote',
|
||||||
key: 'render',
|
key: 'render',
|
||||||
});
|
});
|
||||||
|
console.log('res', res);
|
||||||
isRender = true;
|
isRender = true;
|
||||||
}
|
}
|
||||||
ctx.body = '';
|
ctx.body = '';
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.addTo(app);
|
.addTo(app);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user