Spaces:
Build error
Build error
Commit
β’
fd46ec1
1
Parent(s):
51ead01
improve window layout
Browse files- package-lock.json +656 -33
- package.json +14 -14
- {src/app β public/images/logos}/logo-desaturated.png +0 -0
- public/images/logos/logo-discord-2.png +3 -0
- public/images/logos/logo-discord-3.png +3 -0
- {src/app β public/images/logos}/logo-no-bg.png +0 -0
- {src/app β public/images/logos}/logo-v2.png +0 -0
- {src/app β public/images/logos}/logo-v2.xcf +0 -0
- src/app/main.tsx +36 -24
- src/components/editors/EntityEditor/EntityTree/index.tsx +12 -0
- src/components/editors/EntityEditor/EntityTree/useEntityTree.ts +8 -7
- src/components/forms/FormSection.tsx +4 -2
- src/components/toolbars/top-menu/ToggleFullScreen/index.tsx +62 -0
- src/components/toolbars/top-menu/ToggleView/index.tsx +4 -2
- src/components/toolbars/top-menu/ToggleWindowLayout/index.tsx +67 -0
- src/components/toolbars/top-menu/index.tsx +7 -0
- src/components/toolbars/top-menu/view/index.tsx +60 -14
- src/components/windows/index.tsx +368 -340
- src/lib/core/constants.ts +1 -1
- src/lib/hooks/useFullscreenStatus.ts +52 -45
- src/services/windows/useWindows.ts +4 -3
package-lock.json
CHANGED
@@ -11,9 +11,9 @@
|
|
11 |
"dependencies": {
|
12 |
"@aitube/broadway": "0.1.2",
|
13 |
"@aitube/clap": "0.1.2",
|
14 |
-
"@aitube/clapper-services": "0.1.2-
|
15 |
"@aitube/engine": "0.1.2",
|
16 |
-
"@aitube/timeline": "0.1.2-
|
17 |
"@fal-ai/serverless-client": "^0.13.0",
|
18 |
"@ffmpeg/ffmpeg": "^0.12.10",
|
19 |
"@ffmpeg/util": "^0.12.1",
|
@@ -184,12 +184,12 @@
|
|
184 |
}
|
185 |
},
|
186 |
"node_modules/@aitube/clapper-services": {
|
187 |
-
"version": "0.1.2-
|
188 |
-
"resolved": "https://registry.npmjs.org/@aitube/clapper-services/-/clapper-services-0.1.2-
|
189 |
-
"integrity": "sha512-
|
190 |
"peerDependencies": {
|
191 |
"@aitube/clap": "0.1.2",
|
192 |
-
"@aitube/timeline": "0.1.2-
|
193 |
"@monaco-editor/react": "4.6.0",
|
194 |
"monaco-editor": "0.50.0",
|
195 |
"react": "*",
|
@@ -215,9 +215,9 @@
|
|
215 |
}
|
216 |
},
|
217 |
"node_modules/@aitube/timeline": {
|
218 |
-
"version": "0.1.2-
|
219 |
-
"resolved": "https://registry.npmjs.org/@aitube/timeline/-/timeline-0.1.2-
|
220 |
-
"integrity": "sha512-
|
221 |
"dependencies": {
|
222 |
"date-fns": "^3.6.0",
|
223 |
"react-virtualized-auto-sizer": "^1.0.24"
|
@@ -1547,9 +1547,9 @@
|
|
1547 |
}
|
1548 |
},
|
1549 |
"node_modules/@babel/traverse": {
|
1550 |
-
"version": "7.25.
|
1551 |
-
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.
|
1552 |
-
"integrity": "sha512-
|
1553 |
"dependencies": {
|
1554 |
"@babel/code-frame": "^7.24.7",
|
1555 |
"@babel/generator": "^7.25.0",
|
@@ -2806,6 +2806,15 @@
|
|
2806 |
"node": ">=14.14"
|
2807 |
}
|
2808 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2809 |
"node_modules/@emotion/is-prop-valid": {
|
2810 |
"version": "1.3.0",
|
2811 |
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz",
|
@@ -2829,6 +2838,70 @@
|
|
2829 |
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
|
2830 |
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
|
2831 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2832 |
"node_modules/@esbuild/darwin-arm64": {
|
2833 |
"version": "0.21.5",
|
2834 |
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
|
@@ -2845,6 +2918,294 @@
|
|
2845 |
"node": ">=12"
|
2846 |
}
|
2847 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2848 |
"node_modules/@eslint-community/eslint-utils": {
|
2849 |
"version": "4.4.0",
|
2850 |
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
|
@@ -3238,6 +3599,27 @@
|
|
3238 |
"url": "https://opencollective.com/libvips"
|
3239 |
}
|
3240 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3241 |
"node_modules/@img/sharp-libvips-linux-x64": {
|
3242 |
"version": "1.0.2",
|
3243 |
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.2.tgz",
|
@@ -3369,6 +3751,31 @@
|
|
3369 |
"@img/sharp-libvips-linux-arm64": "1.0.2"
|
3370 |
}
|
3371 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3372 |
"node_modules/@img/sharp-linux-x64": {
|
3373 |
"version": "0.33.4",
|
3374 |
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.4.tgz",
|
@@ -3444,6 +3851,27 @@
|
|
3444 |
"@img/sharp-libvips-linuxmusl-x64": "1.0.2"
|
3445 |
}
|
3446 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3447 |
"node_modules/@img/sharp-win32-ia32": {
|
3448 |
"version": "0.33.4",
|
3449 |
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.4.tgz",
|
@@ -3487,11 +3915,11 @@
|
|
3487 |
}
|
3488 |
},
|
3489 |
"node_modules/@inquirer/confirm": {
|
3490 |
-
"version": "3.1.
|
3491 |
-
"resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.
|
3492 |
-
"integrity": "sha512-
|
3493 |
"dependencies": {
|
3494 |
-
"@inquirer/core": "^9.0.
|
3495 |
"@inquirer/type": "^1.5.1"
|
3496 |
},
|
3497 |
"engines": {
|
@@ -3499,14 +3927,14 @@
|
|
3499 |
}
|
3500 |
},
|
3501 |
"node_modules/@inquirer/core": {
|
3502 |
-
"version": "9.0.
|
3503 |
-
"resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.
|
3504 |
-
"integrity": "sha512-
|
3505 |
"dependencies": {
|
3506 |
"@inquirer/figures": "^1.0.5",
|
3507 |
"@inquirer/type": "^1.5.1",
|
3508 |
"@types/mute-stream": "^0.0.4",
|
3509 |
-
"@types/node": "^20.14.
|
3510 |
"@types/wrap-ansi": "^3.0.0",
|
3511 |
"ansi-escapes": "^4.3.2",
|
3512 |
"cli-spinners": "^2.9.2",
|
@@ -6108,6 +6536,32 @@
|
|
6108 |
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
6109 |
}
|
6110 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6111 |
"node_modules/@rollup/rollup-darwin-arm64": {
|
6112 |
"version": "4.19.1",
|
6113 |
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.1.tgz",
|
@@ -6121,6 +6575,175 @@
|
|
6121 |
"darwin"
|
6122 |
]
|
6123 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6124 |
"node_modules/@rushstack/eslint-patch": {
|
6125 |
"version": "1.10.4",
|
6126 |
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz",
|
@@ -7023,9 +7646,9 @@
|
|
7023 |
}
|
7024 |
},
|
7025 |
"node_modules/@types/node": {
|
7026 |
-
"version": "20.14.
|
7027 |
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.
|
7028 |
-
"integrity": "sha512
|
7029 |
"dependencies": {
|
7030 |
"undici-types": "~5.26.4"
|
7031 |
}
|
@@ -7399,7 +8022,7 @@
|
|
7399 |
},
|
7400 |
"node_modules/@xenova/transformers": {
|
7401 |
"version": "3.0.0-alpha.0",
|
7402 |
-
"resolved": "git+ssh://git@github.com/xenova/transformers.js.git#
|
7403 |
"dependencies": {
|
7404 |
"@huggingface/jinja": "^0.2.2",
|
7405 |
"onnxruntime-web": "^1.18.0",
|
@@ -9812,9 +10435,9 @@
|
|
9812 |
}
|
9813 |
},
|
9814 |
"node_modules/detect-gpu": {
|
9815 |
-
"version": "5.0.
|
9816 |
-
"resolved": "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.
|
9817 |
-
"integrity": "sha512-
|
9818 |
"dependencies": {
|
9819 |
"webgl-constants": "^1.1.1"
|
9820 |
}
|
@@ -11637,9 +12260,9 @@
|
|
11637 |
}
|
11638 |
},
|
11639 |
"node_modules/fast-xml-parser": {
|
11640 |
-
"version": "4.4.
|
11641 |
-
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.
|
11642 |
-
"integrity": "sha512-
|
11643 |
"funding": [
|
11644 |
{
|
11645 |
"type": "github",
|
@@ -20295,9 +20918,9 @@
|
|
20295 |
}
|
20296 |
},
|
20297 |
"node_modules/zod-to-json-schema": {
|
20298 |
-
"version": "3.23.
|
20299 |
-
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.23.
|
20300 |
-
"integrity": "sha512-
|
20301 |
"peerDependencies": {
|
20302 |
"zod": "^3.23.3"
|
20303 |
}
|
|
|
11 |
"dependencies": {
|
12 |
"@aitube/broadway": "0.1.2",
|
13 |
"@aitube/clap": "0.1.2",
|
14 |
+
"@aitube/clapper-services": "0.1.2-8",
|
15 |
"@aitube/engine": "0.1.2",
|
16 |
+
"@aitube/timeline": "0.1.2-2",
|
17 |
"@fal-ai/serverless-client": "^0.13.0",
|
18 |
"@ffmpeg/ffmpeg": "^0.12.10",
|
19 |
"@ffmpeg/util": "^0.12.1",
|
|
|
184 |
}
|
185 |
},
|
186 |
"node_modules/@aitube/clapper-services": {
|
187 |
+
"version": "0.1.2-8",
|
188 |
+
"resolved": "https://registry.npmjs.org/@aitube/clapper-services/-/clapper-services-0.1.2-8.tgz",
|
189 |
+
"integrity": "sha512-LjC9J8HZ/Dt94NzkEWRnm7v51d9Hncc/SjhzkMGEc6/FGnu97IhmPsI2DCI61a+SUlqYn14Nt+FdT949NHvVLw==",
|
190 |
"peerDependencies": {
|
191 |
"@aitube/clap": "0.1.2",
|
192 |
+
"@aitube/timeline": "0.1.2-2",
|
193 |
"@monaco-editor/react": "4.6.0",
|
194 |
"monaco-editor": "0.50.0",
|
195 |
"react": "*",
|
|
|
215 |
}
|
216 |
},
|
217 |
"node_modules/@aitube/timeline": {
|
218 |
+
"version": "0.1.2-2",
|
219 |
+
"resolved": "https://registry.npmjs.org/@aitube/timeline/-/timeline-0.1.2-2.tgz",
|
220 |
+
"integrity": "sha512-4ep73A0C7zEMreQ2jpCvJbCJJNQgQZBYxTQqJmoiZg5DPiIXFzkOTOYIJuhPu4wZX/Q14wPgpyXmF3UJ1x3ujA==",
|
221 |
"dependencies": {
|
222 |
"date-fns": "^3.6.0",
|
223 |
"react-virtualized-auto-sizer": "^1.0.24"
|
|
|
1547 |
}
|
1548 |
},
|
1549 |
"node_modules/@babel/traverse": {
|
1550 |
+
"version": "7.25.1",
|
1551 |
+
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.1.tgz",
|
1552 |
+
"integrity": "sha512-LrHHoWq08ZpmmFqBAzN+hUdWwy5zt7FGa/hVwMcOqW6OVtwqaoD5utfuGYU87JYxdZgLUvktAsn37j/sYR9siA==",
|
1553 |
"dependencies": {
|
1554 |
"@babel/code-frame": "^7.24.7",
|
1555 |
"@babel/generator": "^7.25.0",
|
|
|
2806 |
"node": ">=14.14"
|
2807 |
}
|
2808 |
},
|
2809 |
+
"node_modules/@emnapi/runtime": {
|
2810 |
+
"version": "1.2.0",
|
2811 |
+
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz",
|
2812 |
+
"integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==",
|
2813 |
+
"optional": true,
|
2814 |
+
"dependencies": {
|
2815 |
+
"tslib": "^2.4.0"
|
2816 |
+
}
|
2817 |
+
},
|
2818 |
"node_modules/@emotion/is-prop-valid": {
|
2819 |
"version": "1.3.0",
|
2820 |
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz",
|
|
|
2838 |
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
|
2839 |
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
|
2840 |
},
|
2841 |
+
"node_modules/@esbuild/aix-ppc64": {
|
2842 |
+
"version": "0.21.5",
|
2843 |
+
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
2844 |
+
"integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
|
2845 |
+
"cpu": [
|
2846 |
+
"ppc64"
|
2847 |
+
],
|
2848 |
+
"dev": true,
|
2849 |
+
"optional": true,
|
2850 |
+
"os": [
|
2851 |
+
"aix"
|
2852 |
+
],
|
2853 |
+
"engines": {
|
2854 |
+
"node": ">=12"
|
2855 |
+
}
|
2856 |
+
},
|
2857 |
+
"node_modules/@esbuild/android-arm": {
|
2858 |
+
"version": "0.21.5",
|
2859 |
+
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
|
2860 |
+
"integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
|
2861 |
+
"cpu": [
|
2862 |
+
"arm"
|
2863 |
+
],
|
2864 |
+
"dev": true,
|
2865 |
+
"optional": true,
|
2866 |
+
"os": [
|
2867 |
+
"android"
|
2868 |
+
],
|
2869 |
+
"engines": {
|
2870 |
+
"node": ">=12"
|
2871 |
+
}
|
2872 |
+
},
|
2873 |
+
"node_modules/@esbuild/android-arm64": {
|
2874 |
+
"version": "0.21.5",
|
2875 |
+
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
|
2876 |
+
"integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
|
2877 |
+
"cpu": [
|
2878 |
+
"arm64"
|
2879 |
+
],
|
2880 |
+
"dev": true,
|
2881 |
+
"optional": true,
|
2882 |
+
"os": [
|
2883 |
+
"android"
|
2884 |
+
],
|
2885 |
+
"engines": {
|
2886 |
+
"node": ">=12"
|
2887 |
+
}
|
2888 |
+
},
|
2889 |
+
"node_modules/@esbuild/android-x64": {
|
2890 |
+
"version": "0.21.5",
|
2891 |
+
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
|
2892 |
+
"integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
|
2893 |
+
"cpu": [
|
2894 |
+
"x64"
|
2895 |
+
],
|
2896 |
+
"dev": true,
|
2897 |
+
"optional": true,
|
2898 |
+
"os": [
|
2899 |
+
"android"
|
2900 |
+
],
|
2901 |
+
"engines": {
|
2902 |
+
"node": ">=12"
|
2903 |
+
}
|
2904 |
+
},
|
2905 |
"node_modules/@esbuild/darwin-arm64": {
|
2906 |
"version": "0.21.5",
|
2907 |
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
|
|
|
2918 |
"node": ">=12"
|
2919 |
}
|
2920 |
},
|
2921 |
+
"node_modules/@esbuild/darwin-x64": {
|
2922 |
+
"version": "0.21.5",
|
2923 |
+
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
|
2924 |
+
"integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
|
2925 |
+
"cpu": [
|
2926 |
+
"x64"
|
2927 |
+
],
|
2928 |
+
"dev": true,
|
2929 |
+
"optional": true,
|
2930 |
+
"os": [
|
2931 |
+
"darwin"
|
2932 |
+
],
|
2933 |
+
"engines": {
|
2934 |
+
"node": ">=12"
|
2935 |
+
}
|
2936 |
+
},
|
2937 |
+
"node_modules/@esbuild/freebsd-arm64": {
|
2938 |
+
"version": "0.21.5",
|
2939 |
+
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
|
2940 |
+
"integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
|
2941 |
+
"cpu": [
|
2942 |
+
"arm64"
|
2943 |
+
],
|
2944 |
+
"dev": true,
|
2945 |
+
"optional": true,
|
2946 |
+
"os": [
|
2947 |
+
"freebsd"
|
2948 |
+
],
|
2949 |
+
"engines": {
|
2950 |
+
"node": ">=12"
|
2951 |
+
}
|
2952 |
+
},
|
2953 |
+
"node_modules/@esbuild/freebsd-x64": {
|
2954 |
+
"version": "0.21.5",
|
2955 |
+
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
|
2956 |
+
"integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
|
2957 |
+
"cpu": [
|
2958 |
+
"x64"
|
2959 |
+
],
|
2960 |
+
"dev": true,
|
2961 |
+
"optional": true,
|
2962 |
+
"os": [
|
2963 |
+
"freebsd"
|
2964 |
+
],
|
2965 |
+
"engines": {
|
2966 |
+
"node": ">=12"
|
2967 |
+
}
|
2968 |
+
},
|
2969 |
+
"node_modules/@esbuild/linux-arm": {
|
2970 |
+
"version": "0.21.5",
|
2971 |
+
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
|
2972 |
+
"integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
|
2973 |
+
"cpu": [
|
2974 |
+
"arm"
|
2975 |
+
],
|
2976 |
+
"dev": true,
|
2977 |
+
"optional": true,
|
2978 |
+
"os": [
|
2979 |
+
"linux"
|
2980 |
+
],
|
2981 |
+
"engines": {
|
2982 |
+
"node": ">=12"
|
2983 |
+
}
|
2984 |
+
},
|
2985 |
+
"node_modules/@esbuild/linux-arm64": {
|
2986 |
+
"version": "0.21.5",
|
2987 |
+
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
|
2988 |
+
"integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
|
2989 |
+
"cpu": [
|
2990 |
+
"arm64"
|
2991 |
+
],
|
2992 |
+
"dev": true,
|
2993 |
+
"optional": true,
|
2994 |
+
"os": [
|
2995 |
+
"linux"
|
2996 |
+
],
|
2997 |
+
"engines": {
|
2998 |
+
"node": ">=12"
|
2999 |
+
}
|
3000 |
+
},
|
3001 |
+
"node_modules/@esbuild/linux-ia32": {
|
3002 |
+
"version": "0.21.5",
|
3003 |
+
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
|
3004 |
+
"integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
|
3005 |
+
"cpu": [
|
3006 |
+
"ia32"
|
3007 |
+
],
|
3008 |
+
"dev": true,
|
3009 |
+
"optional": true,
|
3010 |
+
"os": [
|
3011 |
+
"linux"
|
3012 |
+
],
|
3013 |
+
"engines": {
|
3014 |
+
"node": ">=12"
|
3015 |
+
}
|
3016 |
+
},
|
3017 |
+
"node_modules/@esbuild/linux-loong64": {
|
3018 |
+
"version": "0.21.5",
|
3019 |
+
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
|
3020 |
+
"integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
|
3021 |
+
"cpu": [
|
3022 |
+
"loong64"
|
3023 |
+
],
|
3024 |
+
"dev": true,
|
3025 |
+
"optional": true,
|
3026 |
+
"os": [
|
3027 |
+
"linux"
|
3028 |
+
],
|
3029 |
+
"engines": {
|
3030 |
+
"node": ">=12"
|
3031 |
+
}
|
3032 |
+
},
|
3033 |
+
"node_modules/@esbuild/linux-mips64el": {
|
3034 |
+
"version": "0.21.5",
|
3035 |
+
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
|
3036 |
+
"integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
|
3037 |
+
"cpu": [
|
3038 |
+
"mips64el"
|
3039 |
+
],
|
3040 |
+
"dev": true,
|
3041 |
+
"optional": true,
|
3042 |
+
"os": [
|
3043 |
+
"linux"
|
3044 |
+
],
|
3045 |
+
"engines": {
|
3046 |
+
"node": ">=12"
|
3047 |
+
}
|
3048 |
+
},
|
3049 |
+
"node_modules/@esbuild/linux-ppc64": {
|
3050 |
+
"version": "0.21.5",
|
3051 |
+
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
|
3052 |
+
"integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
|
3053 |
+
"cpu": [
|
3054 |
+
"ppc64"
|
3055 |
+
],
|
3056 |
+
"dev": true,
|
3057 |
+
"optional": true,
|
3058 |
+
"os": [
|
3059 |
+
"linux"
|
3060 |
+
],
|
3061 |
+
"engines": {
|
3062 |
+
"node": ">=12"
|
3063 |
+
}
|
3064 |
+
},
|
3065 |
+
"node_modules/@esbuild/linux-riscv64": {
|
3066 |
+
"version": "0.21.5",
|
3067 |
+
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
|
3068 |
+
"integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
|
3069 |
+
"cpu": [
|
3070 |
+
"riscv64"
|
3071 |
+
],
|
3072 |
+
"dev": true,
|
3073 |
+
"optional": true,
|
3074 |
+
"os": [
|
3075 |
+
"linux"
|
3076 |
+
],
|
3077 |
+
"engines": {
|
3078 |
+
"node": ">=12"
|
3079 |
+
}
|
3080 |
+
},
|
3081 |
+
"node_modules/@esbuild/linux-s390x": {
|
3082 |
+
"version": "0.21.5",
|
3083 |
+
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
|
3084 |
+
"integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
|
3085 |
+
"cpu": [
|
3086 |
+
"s390x"
|
3087 |
+
],
|
3088 |
+
"dev": true,
|
3089 |
+
"optional": true,
|
3090 |
+
"os": [
|
3091 |
+
"linux"
|
3092 |
+
],
|
3093 |
+
"engines": {
|
3094 |
+
"node": ">=12"
|
3095 |
+
}
|
3096 |
+
},
|
3097 |
+
"node_modules/@esbuild/linux-x64": {
|
3098 |
+
"version": "0.21.5",
|
3099 |
+
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
|
3100 |
+
"integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
|
3101 |
+
"cpu": [
|
3102 |
+
"x64"
|
3103 |
+
],
|
3104 |
+
"dev": true,
|
3105 |
+
"optional": true,
|
3106 |
+
"os": [
|
3107 |
+
"linux"
|
3108 |
+
],
|
3109 |
+
"engines": {
|
3110 |
+
"node": ">=12"
|
3111 |
+
}
|
3112 |
+
},
|
3113 |
+
"node_modules/@esbuild/netbsd-x64": {
|
3114 |
+
"version": "0.21.5",
|
3115 |
+
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
|
3116 |
+
"integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
|
3117 |
+
"cpu": [
|
3118 |
+
"x64"
|
3119 |
+
],
|
3120 |
+
"dev": true,
|
3121 |
+
"optional": true,
|
3122 |
+
"os": [
|
3123 |
+
"netbsd"
|
3124 |
+
],
|
3125 |
+
"engines": {
|
3126 |
+
"node": ">=12"
|
3127 |
+
}
|
3128 |
+
},
|
3129 |
+
"node_modules/@esbuild/openbsd-x64": {
|
3130 |
+
"version": "0.21.5",
|
3131 |
+
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
|
3132 |
+
"integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
|
3133 |
+
"cpu": [
|
3134 |
+
"x64"
|
3135 |
+
],
|
3136 |
+
"dev": true,
|
3137 |
+
"optional": true,
|
3138 |
+
"os": [
|
3139 |
+
"openbsd"
|
3140 |
+
],
|
3141 |
+
"engines": {
|
3142 |
+
"node": ">=12"
|
3143 |
+
}
|
3144 |
+
},
|
3145 |
+
"node_modules/@esbuild/sunos-x64": {
|
3146 |
+
"version": "0.21.5",
|
3147 |
+
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
|
3148 |
+
"integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
|
3149 |
+
"cpu": [
|
3150 |
+
"x64"
|
3151 |
+
],
|
3152 |
+
"dev": true,
|
3153 |
+
"optional": true,
|
3154 |
+
"os": [
|
3155 |
+
"sunos"
|
3156 |
+
],
|
3157 |
+
"engines": {
|
3158 |
+
"node": ">=12"
|
3159 |
+
}
|
3160 |
+
},
|
3161 |
+
"node_modules/@esbuild/win32-arm64": {
|
3162 |
+
"version": "0.21.5",
|
3163 |
+
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
|
3164 |
+
"integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
|
3165 |
+
"cpu": [
|
3166 |
+
"arm64"
|
3167 |
+
],
|
3168 |
+
"dev": true,
|
3169 |
+
"optional": true,
|
3170 |
+
"os": [
|
3171 |
+
"win32"
|
3172 |
+
],
|
3173 |
+
"engines": {
|
3174 |
+
"node": ">=12"
|
3175 |
+
}
|
3176 |
+
},
|
3177 |
+
"node_modules/@esbuild/win32-ia32": {
|
3178 |
+
"version": "0.21.5",
|
3179 |
+
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
|
3180 |
+
"integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
|
3181 |
+
"cpu": [
|
3182 |
+
"ia32"
|
3183 |
+
],
|
3184 |
+
"dev": true,
|
3185 |
+
"optional": true,
|
3186 |
+
"os": [
|
3187 |
+
"win32"
|
3188 |
+
],
|
3189 |
+
"engines": {
|
3190 |
+
"node": ">=12"
|
3191 |
+
}
|
3192 |
+
},
|
3193 |
+
"node_modules/@esbuild/win32-x64": {
|
3194 |
+
"version": "0.21.5",
|
3195 |
+
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
|
3196 |
+
"integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
|
3197 |
+
"cpu": [
|
3198 |
+
"x64"
|
3199 |
+
],
|
3200 |
+
"dev": true,
|
3201 |
+
"optional": true,
|
3202 |
+
"os": [
|
3203 |
+
"win32"
|
3204 |
+
],
|
3205 |
+
"engines": {
|
3206 |
+
"node": ">=12"
|
3207 |
+
}
|
3208 |
+
},
|
3209 |
"node_modules/@eslint-community/eslint-utils": {
|
3210 |
"version": "4.4.0",
|
3211 |
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
|
|
|
3599 |
"url": "https://opencollective.com/libvips"
|
3600 |
}
|
3601 |
},
|
3602 |
+
"node_modules/@img/sharp-libvips-linux-s390x": {
|
3603 |
+
"version": "1.0.2",
|
3604 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.2.tgz",
|
3605 |
+
"integrity": "sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==",
|
3606 |
+
"cpu": [
|
3607 |
+
"s390x"
|
3608 |
+
],
|
3609 |
+
"optional": true,
|
3610 |
+
"os": [
|
3611 |
+
"linux"
|
3612 |
+
],
|
3613 |
+
"engines": {
|
3614 |
+
"glibc": ">=2.28",
|
3615 |
+
"npm": ">=9.6.5",
|
3616 |
+
"pnpm": ">=7.1.0",
|
3617 |
+
"yarn": ">=3.2.0"
|
3618 |
+
},
|
3619 |
+
"funding": {
|
3620 |
+
"url": "https://opencollective.com/libvips"
|
3621 |
+
}
|
3622 |
+
},
|
3623 |
"node_modules/@img/sharp-libvips-linux-x64": {
|
3624 |
"version": "1.0.2",
|
3625 |
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.2.tgz",
|
|
|
3751 |
"@img/sharp-libvips-linux-arm64": "1.0.2"
|
3752 |
}
|
3753 |
},
|
3754 |
+
"node_modules/@img/sharp-linux-s390x": {
|
3755 |
+
"version": "0.33.4",
|
3756 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.4.tgz",
|
3757 |
+
"integrity": "sha512-h3RAL3siQoyzSoH36tUeS0PDmb5wINKGYzcLB5C6DIiAn2F3udeFAum+gj8IbA/82+8RGCTn7XW8WTFnqag4tQ==",
|
3758 |
+
"cpu": [
|
3759 |
+
"s390x"
|
3760 |
+
],
|
3761 |
+
"optional": true,
|
3762 |
+
"os": [
|
3763 |
+
"linux"
|
3764 |
+
],
|
3765 |
+
"engines": {
|
3766 |
+
"glibc": ">=2.31",
|
3767 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
|
3768 |
+
"npm": ">=9.6.5",
|
3769 |
+
"pnpm": ">=7.1.0",
|
3770 |
+
"yarn": ">=3.2.0"
|
3771 |
+
},
|
3772 |
+
"funding": {
|
3773 |
+
"url": "https://opencollective.com/libvips"
|
3774 |
+
},
|
3775 |
+
"optionalDependencies": {
|
3776 |
+
"@img/sharp-libvips-linux-s390x": "1.0.2"
|
3777 |
+
}
|
3778 |
+
},
|
3779 |
"node_modules/@img/sharp-linux-x64": {
|
3780 |
"version": "0.33.4",
|
3781 |
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.4.tgz",
|
|
|
3851 |
"@img/sharp-libvips-linuxmusl-x64": "1.0.2"
|
3852 |
}
|
3853 |
},
|
3854 |
+
"node_modules/@img/sharp-wasm32": {
|
3855 |
+
"version": "0.33.4",
|
3856 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.4.tgz",
|
3857 |
+
"integrity": "sha512-Bmmauh4sXUsUqkleQahpdNXKvo+wa1V9KhT2pDA4VJGKwnKMJXiSTGphn0gnJrlooda0QxCtXc6RX1XAU6hMnQ==",
|
3858 |
+
"cpu": [
|
3859 |
+
"wasm32"
|
3860 |
+
],
|
3861 |
+
"optional": true,
|
3862 |
+
"dependencies": {
|
3863 |
+
"@emnapi/runtime": "^1.1.1"
|
3864 |
+
},
|
3865 |
+
"engines": {
|
3866 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
|
3867 |
+
"npm": ">=9.6.5",
|
3868 |
+
"pnpm": ">=7.1.0",
|
3869 |
+
"yarn": ">=3.2.0"
|
3870 |
+
},
|
3871 |
+
"funding": {
|
3872 |
+
"url": "https://opencollective.com/libvips"
|
3873 |
+
}
|
3874 |
+
},
|
3875 |
"node_modules/@img/sharp-win32-ia32": {
|
3876 |
"version": "0.33.4",
|
3877 |
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.4.tgz",
|
|
|
3915 |
}
|
3916 |
},
|
3917 |
"node_modules/@inquirer/confirm": {
|
3918 |
+
"version": "3.1.18",
|
3919 |
+
"resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.18.tgz",
|
3920 |
+
"integrity": "sha512-axDSeAtgRfMAOnI2NXJAcBliknRiPHBPBh8VpofFW2vSt5nxU/IoNcWfNBIs1LFwICyLzbvGjF3fd+rYLSU11w==",
|
3921 |
"dependencies": {
|
3922 |
+
"@inquirer/core": "^9.0.6",
|
3923 |
"@inquirer/type": "^1.5.1"
|
3924 |
},
|
3925 |
"engines": {
|
|
|
3927 |
}
|
3928 |
},
|
3929 |
"node_modules/@inquirer/core": {
|
3930 |
+
"version": "9.0.6",
|
3931 |
+
"resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.6.tgz",
|
3932 |
+
"integrity": "sha512-pmwIJJrtOBmP29JLPkdq5ORGGaSzOwZbashYyME20sD5AITiy2j3LFsnTXXuiqPIkq4XjQYOHzaExAmqjyU1Cg==",
|
3933 |
"dependencies": {
|
3934 |
"@inquirer/figures": "^1.0.5",
|
3935 |
"@inquirer/type": "^1.5.1",
|
3936 |
"@types/mute-stream": "^0.0.4",
|
3937 |
+
"@types/node": "^20.14.13",
|
3938 |
"@types/wrap-ansi": "^3.0.0",
|
3939 |
"ansi-escapes": "^4.3.2",
|
3940 |
"cli-spinners": "^2.9.2",
|
|
|
6536 |
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
6537 |
}
|
6538 |
},
|
6539 |
+
"node_modules/@rollup/rollup-android-arm-eabi": {
|
6540 |
+
"version": "4.19.1",
|
6541 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.1.tgz",
|
6542 |
+
"integrity": "sha512-XzqSg714++M+FXhHfXpS1tDnNZNpgxxuGZWlRG/jSj+VEPmZ0yg6jV4E0AL3uyBKxO8mO3xtOsP5mQ+XLfrlww==",
|
6543 |
+
"cpu": [
|
6544 |
+
"arm"
|
6545 |
+
],
|
6546 |
+
"dev": true,
|
6547 |
+
"optional": true,
|
6548 |
+
"os": [
|
6549 |
+
"android"
|
6550 |
+
]
|
6551 |
+
},
|
6552 |
+
"node_modules/@rollup/rollup-android-arm64": {
|
6553 |
+
"version": "4.19.1",
|
6554 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.1.tgz",
|
6555 |
+
"integrity": "sha512-thFUbkHteM20BGShD6P08aungq4irbIZKUNbG70LN8RkO7YztcGPiKTTGZS7Kw+x5h8hOXs0i4OaHwFxlpQN6A==",
|
6556 |
+
"cpu": [
|
6557 |
+
"arm64"
|
6558 |
+
],
|
6559 |
+
"dev": true,
|
6560 |
+
"optional": true,
|
6561 |
+
"os": [
|
6562 |
+
"android"
|
6563 |
+
]
|
6564 |
+
},
|
6565 |
"node_modules/@rollup/rollup-darwin-arm64": {
|
6566 |
"version": "4.19.1",
|
6567 |
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.1.tgz",
|
|
|
6575 |
"darwin"
|
6576 |
]
|
6577 |
},
|
6578 |
+
"node_modules/@rollup/rollup-darwin-x64": {
|
6579 |
+
"version": "4.19.1",
|
6580 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.1.tgz",
|
6581 |
+
"integrity": "sha512-4T42heKsnbjkn7ovYiAdDVRRWZLU9Kmhdt6HafZxFcUdpjlBlxj4wDrt1yFWLk7G4+E+8p2C9tcmSu0KA6auGA==",
|
6582 |
+
"cpu": [
|
6583 |
+
"x64"
|
6584 |
+
],
|
6585 |
+
"dev": true,
|
6586 |
+
"optional": true,
|
6587 |
+
"os": [
|
6588 |
+
"darwin"
|
6589 |
+
]
|
6590 |
+
},
|
6591 |
+
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
6592 |
+
"version": "4.19.1",
|
6593 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.1.tgz",
|
6594 |
+
"integrity": "sha512-MXg1xp+e5GhZ3Vit1gGEyoC+dyQUBy2JgVQ+3hUrD9wZMkUw/ywgkpK7oZgnB6kPpGrxJ41clkPPnsknuD6M2Q==",
|
6595 |
+
"cpu": [
|
6596 |
+
"arm"
|
6597 |
+
],
|
6598 |
+
"dev": true,
|
6599 |
+
"optional": true,
|
6600 |
+
"os": [
|
6601 |
+
"linux"
|
6602 |
+
]
|
6603 |
+
},
|
6604 |
+
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
6605 |
+
"version": "4.19.1",
|
6606 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.1.tgz",
|
6607 |
+
"integrity": "sha512-DZNLwIY4ftPSRVkJEaxYkq7u2zel7aah57HESuNkUnz+3bZHxwkCUkrfS2IWC1sxK6F2QNIR0Qr/YXw7nkF3Pw==",
|
6608 |
+
"cpu": [
|
6609 |
+
"arm"
|
6610 |
+
],
|
6611 |
+
"dev": true,
|
6612 |
+
"optional": true,
|
6613 |
+
"os": [
|
6614 |
+
"linux"
|
6615 |
+
]
|
6616 |
+
},
|
6617 |
+
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
6618 |
+
"version": "4.19.1",
|
6619 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.1.tgz",
|
6620 |
+
"integrity": "sha512-C7evongnjyxdngSDRRSQv5GvyfISizgtk9RM+z2biV5kY6S/NF/wta7K+DanmktC5DkuaJQgoKGf7KUDmA7RUw==",
|
6621 |
+
"cpu": [
|
6622 |
+
"arm64"
|
6623 |
+
],
|
6624 |
+
"dev": true,
|
6625 |
+
"optional": true,
|
6626 |
+
"os": [
|
6627 |
+
"linux"
|
6628 |
+
]
|
6629 |
+
},
|
6630 |
+
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
6631 |
+
"version": "4.19.1",
|
6632 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.1.tgz",
|
6633 |
+
"integrity": "sha512-89tFWqxfxLLHkAthAcrTs9etAoBFRduNfWdl2xUs/yLV+7XDrJ5yuXMHptNqf1Zw0UCA3cAutkAiAokYCkaPtw==",
|
6634 |
+
"cpu": [
|
6635 |
+
"arm64"
|
6636 |
+
],
|
6637 |
+
"dev": true,
|
6638 |
+
"optional": true,
|
6639 |
+
"os": [
|
6640 |
+
"linux"
|
6641 |
+
]
|
6642 |
+
},
|
6643 |
+
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
6644 |
+
"version": "4.19.1",
|
6645 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.1.tgz",
|
6646 |
+
"integrity": "sha512-PromGeV50sq+YfaisG8W3fd+Cl6mnOOiNv2qKKqKCpiiEke2KiKVyDqG/Mb9GWKbYMHj5a01fq/qlUR28PFhCQ==",
|
6647 |
+
"cpu": [
|
6648 |
+
"ppc64"
|
6649 |
+
],
|
6650 |
+
"dev": true,
|
6651 |
+
"optional": true,
|
6652 |
+
"os": [
|
6653 |
+
"linux"
|
6654 |
+
]
|
6655 |
+
},
|
6656 |
+
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
6657 |
+
"version": "4.19.1",
|
6658 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.1.tgz",
|
6659 |
+
"integrity": "sha512-/1BmHYh+iz0cNCP0oHCuF8CSiNj0JOGf0jRlSo3L/FAyZyG2rGBuKpkZVH9YF+x58r1jgWxvm1aRg3DHrLDt6A==",
|
6660 |
+
"cpu": [
|
6661 |
+
"riscv64"
|
6662 |
+
],
|
6663 |
+
"dev": true,
|
6664 |
+
"optional": true,
|
6665 |
+
"os": [
|
6666 |
+
"linux"
|
6667 |
+
]
|
6668 |
+
},
|
6669 |
+
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
6670 |
+
"version": "4.19.1",
|
6671 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.1.tgz",
|
6672 |
+
"integrity": "sha512-0cYP5rGkQWRZKy9/HtsWVStLXzCF3cCBTRI+qRL8Z+wkYlqN7zrSYm6FuY5Kd5ysS5aH0q5lVgb/WbG4jqXN1Q==",
|
6673 |
+
"cpu": [
|
6674 |
+
"s390x"
|
6675 |
+
],
|
6676 |
+
"dev": true,
|
6677 |
+
"optional": true,
|
6678 |
+
"os": [
|
6679 |
+
"linux"
|
6680 |
+
]
|
6681 |
+
},
|
6682 |
+
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
6683 |
+
"version": "4.19.1",
|
6684 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.1.tgz",
|
6685 |
+
"integrity": "sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q==",
|
6686 |
+
"cpu": [
|
6687 |
+
"x64"
|
6688 |
+
],
|
6689 |
+
"dev": true,
|
6690 |
+
"optional": true,
|
6691 |
+
"os": [
|
6692 |
+
"linux"
|
6693 |
+
]
|
6694 |
+
},
|
6695 |
+
"node_modules/@rollup/rollup-linux-x64-musl": {
|
6696 |
+
"version": "4.19.1",
|
6697 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.1.tgz",
|
6698 |
+
"integrity": "sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q==",
|
6699 |
+
"cpu": [
|
6700 |
+
"x64"
|
6701 |
+
],
|
6702 |
+
"dev": true,
|
6703 |
+
"optional": true,
|
6704 |
+
"os": [
|
6705 |
+
"linux"
|
6706 |
+
]
|
6707 |
+
},
|
6708 |
+
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
6709 |
+
"version": "4.19.1",
|
6710 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.1.tgz",
|
6711 |
+
"integrity": "sha512-88brja2vldW/76jWATlBqHEoGjJLRnP0WOEKAUbMcXaAZnemNhlAHSyj4jIwMoP2T750LE9lblvD4e2jXleZsA==",
|
6712 |
+
"cpu": [
|
6713 |
+
"arm64"
|
6714 |
+
],
|
6715 |
+
"dev": true,
|
6716 |
+
"optional": true,
|
6717 |
+
"os": [
|
6718 |
+
"win32"
|
6719 |
+
]
|
6720 |
+
},
|
6721 |
+
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
6722 |
+
"version": "4.19.1",
|
6723 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.1.tgz",
|
6724 |
+
"integrity": "sha512-LdxxcqRVSXi6k6JUrTah1rHuaupoeuiv38du8Mt4r4IPer3kwlTo+RuvfE8KzZ/tL6BhaPlzJ3835i6CxrFIRQ==",
|
6725 |
+
"cpu": [
|
6726 |
+
"ia32"
|
6727 |
+
],
|
6728 |
+
"dev": true,
|
6729 |
+
"optional": true,
|
6730 |
+
"os": [
|
6731 |
+
"win32"
|
6732 |
+
]
|
6733 |
+
},
|
6734 |
+
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
6735 |
+
"version": "4.19.1",
|
6736 |
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.1.tgz",
|
6737 |
+
"integrity": "sha512-2bIrL28PcK3YCqD9anGxDxamxdiJAxA+l7fWIwM5o8UqNy1t3d1NdAweO2XhA0KTDJ5aH1FsuiT5+7VhtHliXg==",
|
6738 |
+
"cpu": [
|
6739 |
+
"x64"
|
6740 |
+
],
|
6741 |
+
"dev": true,
|
6742 |
+
"optional": true,
|
6743 |
+
"os": [
|
6744 |
+
"win32"
|
6745 |
+
]
|
6746 |
+
},
|
6747 |
"node_modules/@rushstack/eslint-patch": {
|
6748 |
"version": "1.10.4",
|
6749 |
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz",
|
|
|
7646 |
}
|
7647 |
},
|
7648 |
"node_modules/@types/node": {
|
7649 |
+
"version": "20.14.13",
|
7650 |
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.13.tgz",
|
7651 |
+
"integrity": "sha512-+bHoGiZb8UiQ0+WEtmph2IWQCjIqg8MDZMAV+ppRRhUZnquF5mQkP/9vpSwJClEiSM/C7fZZExPzfU0vJTyp8w==",
|
7652 |
"dependencies": {
|
7653 |
"undici-types": "~5.26.4"
|
7654 |
}
|
|
|
8022 |
},
|
8023 |
"node_modules/@xenova/transformers": {
|
8024 |
"version": "3.0.0-alpha.0",
|
8025 |
+
"resolved": "git+ssh://git@github.com/xenova/transformers.js.git#38a3bf6dab2265d9f0c2f613064535863194e6b9",
|
8026 |
"dependencies": {
|
8027 |
"@huggingface/jinja": "^0.2.2",
|
8028 |
"onnxruntime-web": "^1.18.0",
|
|
|
10435 |
}
|
10436 |
},
|
10437 |
"node_modules/detect-gpu": {
|
10438 |
+
"version": "5.0.41",
|
10439 |
+
"resolved": "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.41.tgz",
|
10440 |
+
"integrity": "sha512-0avjQwm8zyDPLmmp2PlaUxOWp/CNLbOU4t61x1IOTmBvC7UO+NMWDlEJcIjtbRBSnulC2ote81Xyillssam0CA==",
|
10441 |
"dependencies": {
|
10442 |
"webgl-constants": "^1.1.1"
|
10443 |
}
|
|
|
12260 |
}
|
12261 |
},
|
12262 |
"node_modules/fast-xml-parser": {
|
12263 |
+
"version": "4.4.1",
|
12264 |
+
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz",
|
12265 |
+
"integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==",
|
12266 |
"funding": [
|
12267 |
{
|
12268 |
"type": "github",
|
|
|
20918 |
}
|
20919 |
},
|
20920 |
"node_modules/zod-to-json-schema": {
|
20921 |
+
"version": "3.23.2",
|
20922 |
+
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.23.2.tgz",
|
20923 |
+
"integrity": "sha512-uSt90Gzc/tUfyNqxnjlfBs8W6WSGpNBv0rVsNxP/BVSMHMKGdthPYff4xtCHYloJGM0CFxFsb3NbC0eqPhfImw==",
|
20924 |
"peerDependencies": {
|
20925 |
"zod": "^3.23.3"
|
20926 |
}
|
package.json
CHANGED
@@ -38,9 +38,9 @@
|
|
38 |
"dependencies": {
|
39 |
"@aitube/broadway": "0.1.2",
|
40 |
"@aitube/clap": "0.1.2",
|
41 |
-
"@aitube/clapper-services": "0.1.2-
|
42 |
"@aitube/engine": "0.1.2",
|
43 |
-
"@aitube/timeline": "0.1.2-
|
44 |
"@fal-ai/serverless-client": "^0.13.0",
|
45 |
"@ffmpeg/ffmpeg": "^0.12.10",
|
46 |
"@ffmpeg/util": "^0.12.1",
|
@@ -165,23 +165,23 @@
|
|
165 |
"vitest": "^2.0.2"
|
166 |
},
|
167 |
"optionalDependencies": {
|
168 |
-
"@img/sharp-win32-ia32": "0.33.4",
|
169 |
-
"@img/sharp-win32-x64": "0.33.4",
|
170 |
"@img/sharp-darwin-arm64": "0.33.4",
|
171 |
"@img/sharp-darwin-x64": "0.33.4",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
"@img/sharp-linux-arm": "0.33.4",
|
173 |
"@img/sharp-linux-arm64": "0.33.4",
|
174 |
"@img/sharp-linux-x64": "0.33.4",
|
175 |
-
"@img/sharp-linuxmusl-x64": "0.33.4",
|
176 |
"@img/sharp-linuxmusl-arm64": "0.33.4",
|
177 |
-
"@img/sharp-
|
178 |
-
"@img/sharp-
|
179 |
-
"@img/sharp-
|
180 |
-
"@img/sharp-libvips-linux-x64": "1.0.2",
|
181 |
-
"@img/sharp-libvips-linux-arm64": "1.0.2",
|
182 |
-
"@img/sharp-libvips-linuxmusl-x64": "1.0.2",
|
183 |
-
"@img/sharp-libvips-linuxmusl-arm64": "1.0.2",
|
184 |
-
"@img/sharp-libvips-darwin-x64": "1.0.2",
|
185 |
-
"@img/sharp-libvips-darwin-arm64": "1.0.2"
|
186 |
}
|
187 |
}
|
|
|
38 |
"dependencies": {
|
39 |
"@aitube/broadway": "0.1.2",
|
40 |
"@aitube/clap": "0.1.2",
|
41 |
+
"@aitube/clapper-services": "0.1.2-8",
|
42 |
"@aitube/engine": "0.1.2",
|
43 |
+
"@aitube/timeline": "0.1.2-2",
|
44 |
"@fal-ai/serverless-client": "^0.13.0",
|
45 |
"@ffmpeg/ffmpeg": "^0.12.10",
|
46 |
"@ffmpeg/util": "^0.12.1",
|
|
|
165 |
"vitest": "^2.0.2"
|
166 |
},
|
167 |
"optionalDependencies": {
|
|
|
|
|
168 |
"@img/sharp-darwin-arm64": "0.33.4",
|
169 |
"@img/sharp-darwin-x64": "0.33.4",
|
170 |
+
"@img/sharp-libvips-darwin-arm64": "1.0.2",
|
171 |
+
"@img/sharp-libvips-darwin-x64": "1.0.2",
|
172 |
+
"@img/sharp-libvips-linux-arm": "1.0.2",
|
173 |
+
"@img/sharp-libvips-linux-arm64": "1.0.2",
|
174 |
+
"@img/sharp-libvips-linux-x64": "1.0.2",
|
175 |
+
"@img/sharp-libvips-linuxmusl-arm64": "1.0.2",
|
176 |
+
"@img/sharp-libvips-linuxmusl-x64": "1.0.2",
|
177 |
+
"@img/sharp-libvips-win32-ia32": "1.0.2",
|
178 |
+
"@img/sharp-libvips-win32-x64": "1.0.2",
|
179 |
"@img/sharp-linux-arm": "0.33.4",
|
180 |
"@img/sharp-linux-arm64": "0.33.4",
|
181 |
"@img/sharp-linux-x64": "0.33.4",
|
|
|
182 |
"@img/sharp-linuxmusl-arm64": "0.33.4",
|
183 |
+
"@img/sharp-linuxmusl-x64": "0.33.4",
|
184 |
+
"@img/sharp-win32-ia32": "0.33.4",
|
185 |
+
"@img/sharp-win32-x64": "0.33.4"
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
}
|
187 |
}
|
{src/app β public/images/logos}/logo-desaturated.png
RENAMED
File without changes
|
public/images/logos/logo-discord-2.png
ADDED
Git LFS Details
|
public/images/logos/logo-discord-3.png
ADDED
Git LFS Details
|
{src/app β public/images/logos}/logo-no-bg.png
RENAMED
File without changes
|
{src/app β public/images/logos}/logo-v2.png
RENAMED
File without changes
|
{src/app β public/images/logos}/logo-v2.xcf
RENAMED
File without changes
|
src/app/main.tsx
CHANGED
@@ -118,10 +118,12 @@ function MainContent() {
|
|
118 |
<FruityWindow
|
119 |
id="ScriptEditor"
|
120 |
title="Script editor"
|
121 |
-
defaultWidth=
|
122 |
-
minWidth=
|
123 |
-
defaultHeight=
|
124 |
-
minHeight=
|
|
|
|
|
125 |
canBeClosed={false}
|
126 |
>
|
127 |
<ScriptEditor />
|
@@ -130,10 +132,12 @@ function MainContent() {
|
|
130 |
<FruityWindow
|
131 |
id="SegmentEditor"
|
132 |
title="segment editor"
|
133 |
-
defaultWidth=
|
134 |
-
minWidth=
|
135 |
-
defaultHeight=
|
136 |
-
minHeight=
|
|
|
|
|
137 |
canBeClosed={false}
|
138 |
>
|
139 |
<SegmentEditor />
|
@@ -142,10 +146,12 @@ function MainContent() {
|
|
142 |
<FruityWindow
|
143 |
id="EntityEditor"
|
144 |
title="Entity editor"
|
145 |
-
defaultWidth=
|
146 |
-
minWidth=
|
147 |
-
defaultHeight=
|
148 |
-
minHeight=
|
|
|
|
|
149 |
canBeClosed={false}
|
150 |
>
|
151 |
<EntityEditor />
|
@@ -155,10 +161,12 @@ function MainContent() {
|
|
155 |
<FruityWindow
|
156 |
id="WorkflowEditor"
|
157 |
title="Workflow editor"
|
158 |
-
defaultWidth=
|
159 |
-
minWidth=
|
160 |
-
defaultHeight=
|
161 |
-
minHeight=
|
|
|
|
|
162 |
canBeClosed={false}
|
163 |
>
|
164 |
<WorkflowEditor />
|
@@ -168,10 +176,12 @@ function MainContent() {
|
|
168 |
<FruityWindow
|
169 |
id="Monitor"
|
170 |
title="Monitor"
|
171 |
-
defaultWidth=
|
172 |
-
minWidth=
|
173 |
-
defaultHeight=
|
174 |
-
minHeight=
|
|
|
|
|
175 |
canBeClosed={false}
|
176 |
>
|
177 |
<Monitor />
|
@@ -180,10 +190,12 @@ function MainContent() {
|
|
180 |
<FruityWindow
|
181 |
id="Timeline"
|
182 |
title="Timeline"
|
183 |
-
defaultWidth=
|
184 |
-
minWidth=
|
185 |
-
defaultHeight=
|
186 |
-
minHeight=
|
|
|
|
|
187 |
canBeClosed={false}
|
188 |
>
|
189 |
<Timeline />
|
|
|
118 |
<FruityWindow
|
119 |
id="ScriptEditor"
|
120 |
title="Script editor"
|
121 |
+
defaultWidth={375}
|
122 |
+
minWidth={200}
|
123 |
+
defaultHeight={370}
|
124 |
+
minHeight={100}
|
125 |
+
defaultX={18}
|
126 |
+
defaultY={7}
|
127 |
canBeClosed={false}
|
128 |
>
|
129 |
<ScriptEditor />
|
|
|
132 |
<FruityWindow
|
133 |
id="SegmentEditor"
|
134 |
title="segment editor"
|
135 |
+
defaultWidth={342}
|
136 |
+
minWidth={200}
|
137 |
+
defaultHeight={395}
|
138 |
+
minHeight={100}
|
139 |
+
defaultX={21}
|
140 |
+
defaultY={424}
|
141 |
canBeClosed={false}
|
142 |
>
|
143 |
<SegmentEditor />
|
|
|
146 |
<FruityWindow
|
147 |
id="EntityEditor"
|
148 |
title="Entity editor"
|
149 |
+
defaultWidth={544}
|
150 |
+
minWidth={200}
|
151 |
+
defaultHeight={318}
|
152 |
+
minHeight={100}
|
153 |
+
defaultX={347}
|
154 |
+
defaultY={193}
|
155 |
canBeClosed={false}
|
156 |
>
|
157 |
<EntityEditor />
|
|
|
161 |
<FruityWindow
|
162 |
id="WorkflowEditor"
|
163 |
title="Workflow editor"
|
164 |
+
defaultWidth={459}
|
165 |
+
minWidth={200}
|
166 |
+
defaultHeight={351}
|
167 |
+
minHeight={100}
|
168 |
+
defaultX={536}
|
169 |
+
defaultY={3}
|
170 |
canBeClosed={false}
|
171 |
>
|
172 |
<WorkflowEditor />
|
|
|
176 |
<FruityWindow
|
177 |
id="Monitor"
|
178 |
title="Monitor"
|
179 |
+
defaultWidth={333}
|
180 |
+
minWidth={200}
|
181 |
+
defaultHeight={298}
|
182 |
+
minHeight={100}
|
183 |
+
defaultX={1027}
|
184 |
+
defaultY={21}
|
185 |
canBeClosed={false}
|
186 |
>
|
187 |
<Monitor />
|
|
|
190 |
<FruityWindow
|
191 |
id="Timeline"
|
192 |
title="Timeline"
|
193 |
+
defaultWidth={936}
|
194 |
+
minWidth={200}
|
195 |
+
defaultHeight={282}
|
196 |
+
minHeight={100}
|
197 |
+
defaultX={375}
|
198 |
+
defaultY={527}
|
199 |
canBeClosed={false}
|
200 |
>
|
201 |
<Timeline />
|
src/components/editors/EntityEditor/EntityTree/index.tsx
CHANGED
@@ -1,11 +1,15 @@
|
|
1 |
'use client'
|
2 |
|
|
|
|
|
|
|
3 |
import { cn } from '@/lib/utils'
|
4 |
import { isClapEntity } from '@/components/tree-browsers/utils/isSomething'
|
5 |
import { TreeNodeItem, LibraryNodeType } from '@/components/tree-browsers/types'
|
6 |
import { Tree } from '@/components/core/tree'
|
7 |
|
8 |
import { useEntityTree } from './useEntityTree'
|
|
|
9 |
|
10 |
export function EntityTree({
|
11 |
className = '',
|
@@ -15,7 +19,15 @@ export function EntityTree({
|
|
15 |
const libraryTreeRoot = useEntityTree((s) => s.libraryTreeRoot)
|
16 |
const selectTreeNode = useEntityTree((s) => s.selectTreeNode)
|
17 |
const selectedTreeNodeId = useEntityTree((s) => s.selectedTreeNodeId)
|
|
|
|
|
|
|
|
|
18 |
|
|
|
|
|
|
|
|
|
19 |
/**
|
20 |
* handle click on tree node
|
21 |
* yes, this is where the magic happens!
|
|
|
1 |
'use client'
|
2 |
|
3 |
+
import { useEffect } from 'react'
|
4 |
+
import { useTimeline } from '@aitube/timeline'
|
5 |
+
|
6 |
import { cn } from '@/lib/utils'
|
7 |
import { isClapEntity } from '@/components/tree-browsers/utils/isSomething'
|
8 |
import { TreeNodeItem, LibraryNodeType } from '@/components/tree-browsers/types'
|
9 |
import { Tree } from '@/components/core/tree'
|
10 |
|
11 |
import { useEntityTree } from './useEntityTree'
|
12 |
+
import { ClapEntity } from '@aitube/clap'
|
13 |
|
14 |
export function EntityTree({
|
15 |
className = '',
|
|
|
19 |
const libraryTreeRoot = useEntityTree((s) => s.libraryTreeRoot)
|
20 |
const selectTreeNode = useEntityTree((s) => s.selectTreeNode)
|
21 |
const selectedTreeNodeId = useEntityTree((s) => s.selectedTreeNodeId)
|
22 |
+
const setProjectEntities = useEntityTree((s) => s.setProjectEntities)
|
23 |
+
|
24 |
+
const entitiesChanged: number = useTimeline((s) => s.entitiesChanged)
|
25 |
+
const entities: ClapEntity[] = useTimeline((s) => s.entities)
|
26 |
|
27 |
+
useEffect(() => {
|
28 |
+
console.log('loading entities:', entities)
|
29 |
+
setProjectEntities(entities)
|
30 |
+
}, [entities, entitiesChanged, entities.length])
|
31 |
/**
|
32 |
* handle click on tree node
|
33 |
* yes, this is where the magic happens!
|
src/components/editors/EntityEditor/EntityTree/useEntityTree.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
'use client'
|
2 |
|
3 |
import { create } from 'zustand'
|
4 |
-
import { ClapEntity, UUID } from '@aitube/clap'
|
5 |
import {
|
6 |
LibraryTreeNode,
|
7 |
TreeNodeItem,
|
@@ -11,6 +11,7 @@ import { icons } from '@/components/icons'
|
|
11 |
import { getAppropriateIcon } from '@/components/icons/getAppropriateIcon'
|
12 |
import {
|
13 |
collectionClassName,
|
|
|
14 |
libraryClassName,
|
15 |
} from '@/components/tree-browsers/style/treeNodeStyles'
|
16 |
|
@@ -33,7 +34,7 @@ export const useEntityTree = create<{
|
|
33 |
* @param collections
|
34 |
* @returns
|
35 |
*/
|
36 |
-
|
37 |
|
38 |
/**
|
39 |
* Load entity collections (characters, locations..) from the Clapper community into the tree
|
@@ -109,11 +110,10 @@ export const useEntityTree = create<{
|
|
109 |
})
|
110 |
},
|
111 |
|
112 |
-
/*
|
113 |
setProjectEntities: async (entities: ClapEntity[]) => {
|
114 |
const characters: LibraryTreeNode = {
|
115 |
id: UUID(),
|
116 |
-
nodeType: '
|
117 |
data: undefined,
|
118 |
label: 'Characters',
|
119 |
icon: icons.characters,
|
@@ -124,7 +124,7 @@ export const useEntityTree = create<{
|
|
124 |
|
125 |
const locations: LibraryTreeNode = {
|
126 |
id: UUID(),
|
127 |
-
nodeType: '
|
128 |
data: undefined,
|
129 |
label: 'Locations',
|
130 |
icon: icons.location,
|
@@ -135,7 +135,7 @@ export const useEntityTree = create<{
|
|
135 |
|
136 |
const misc: LibraryTreeNode = {
|
137 |
id: UUID(),
|
138 |
-
nodeType: '
|
139 |
data: undefined,
|
140 |
label: 'Misc',
|
141 |
icon: icons.misc,
|
@@ -146,7 +146,7 @@ export const useEntityTree = create<{
|
|
146 |
|
147 |
entities.forEach((entity) => {
|
148 |
const node: LibraryTreeNode = {
|
149 |
-
nodeType:
|
150 |
id: entity.id,
|
151 |
data: entity,
|
152 |
label: entity.label,
|
@@ -165,6 +165,7 @@ export const useEntityTree = create<{
|
|
165 |
})
|
166 |
},
|
167 |
|
|
|
168 |
setCommunityCollections: (collections: CommunityEntityCollection[]) => {
|
169 |
// TODO: implement this
|
170 |
|
|
|
1 |
'use client'
|
2 |
|
3 |
import { create } from 'zustand'
|
4 |
+
import { ClapEntity, ClapSegmentCategory, UUID } from '@aitube/clap'
|
5 |
import {
|
6 |
LibraryTreeNode,
|
7 |
TreeNodeItem,
|
|
|
11 |
import { getAppropriateIcon } from '@/components/icons/getAppropriateIcon'
|
12 |
import {
|
13 |
collectionClassName,
|
14 |
+
itemClassName,
|
15 |
libraryClassName,
|
16 |
} from '@/components/tree-browsers/style/treeNodeStyles'
|
17 |
|
|
|
34 |
* @param collections
|
35 |
* @returns
|
36 |
*/
|
37 |
+
setProjectEntities: (entities: ClapEntity[]) => Promise<void>
|
38 |
|
39 |
/**
|
40 |
* Load entity collections (characters, locations..) from the Clapper community into the tree
|
|
|
110 |
})
|
111 |
},
|
112 |
|
|
|
113 |
setProjectEntities: async (entities: ClapEntity[]) => {
|
114 |
const characters: LibraryTreeNode = {
|
115 |
id: UUID(),
|
116 |
+
nodeType: 'ENTITY_TREE_NODE_LIST_ENTITIES',
|
117 |
data: undefined,
|
118 |
label: 'Characters',
|
119 |
icon: icons.characters,
|
|
|
124 |
|
125 |
const locations: LibraryTreeNode = {
|
126 |
id: UUID(),
|
127 |
+
nodeType: 'ENTITY_TREE_NODE_LIST_ENTITIES',
|
128 |
data: undefined,
|
129 |
label: 'Locations',
|
130 |
icon: icons.location,
|
|
|
135 |
|
136 |
const misc: LibraryTreeNode = {
|
137 |
id: UUID(),
|
138 |
+
nodeType: 'ENTITY_TREE_NODE_LIST_ENTITIES',
|
139 |
data: undefined,
|
140 |
label: 'Misc',
|
141 |
icon: icons.misc,
|
|
|
146 |
|
147 |
entities.forEach((entity) => {
|
148 |
const node: LibraryTreeNode = {
|
149 |
+
nodeType: 'ENTITY_TREE_NODE_ITEM_ENTITY',
|
150 |
id: entity.id,
|
151 |
data: entity,
|
152 |
label: entity.label,
|
|
|
165 |
})
|
166 |
},
|
167 |
|
168 |
+
/*
|
169 |
setCommunityCollections: (collections: CommunityEntityCollection[]) => {
|
170 |
// TODO: implement this
|
171 |
|
src/components/forms/FormSection.tsx
CHANGED
@@ -19,8 +19,10 @@ export function FormSection({
|
|
19 |
className
|
20 |
)}
|
21 |
>
|
22 |
-
<h2 className="pb-2 text-
|
23 |
-
<div className={cn('flex w-full', 'flex-col space-y-4')}>
|
|
|
|
|
24 |
</div>
|
25 |
)
|
26 |
}
|
|
|
19 |
className
|
20 |
)}
|
21 |
>
|
22 |
+
<h2 className="pb-2 text-lg font-normal text-white/60">{label}</h2>
|
23 |
+
<div className={cn('flex w-full', 'flex-col space-y-4 text-sm')}>
|
24 |
+
{children}
|
25 |
+
</div>
|
26 |
</div>
|
27 |
)
|
28 |
}
|
src/components/toolbars/top-menu/ToggleFullScreen/index.tsx
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { useEffect } from 'react'
|
2 |
+
import { RiFullscreenLine, RiFullscreenExitLine } from 'react-icons/ri'
|
3 |
+
|
4 |
+
import { cn } from '@/lib/utils'
|
5 |
+
import {
|
6 |
+
Tooltip,
|
7 |
+
TooltipContent,
|
8 |
+
TooltipTrigger,
|
9 |
+
} from '@/components/ui/tooltip'
|
10 |
+
import { useFullscreenStatus } from '@/lib/hooks'
|
11 |
+
|
12 |
+
export function ToggleFullScreen({
|
13 |
+
className = '',
|
14 |
+
}: {
|
15 |
+
className?: string
|
16 |
+
} = {}) {
|
17 |
+
const [isFullscreen, setFullscreen, ref] = useFullscreenStatus()
|
18 |
+
|
19 |
+
// we want the whole body to become fullscreen
|
20 |
+
// TODO: use pointer lock, to prevent the mouse from going up
|
21 |
+
useEffect(() => {
|
22 |
+
if (typeof window !== 'undefined') {
|
23 |
+
ref.current = document.body
|
24 |
+
}
|
25 |
+
}, [ref])
|
26 |
+
|
27 |
+
return (
|
28 |
+
<Tooltip>
|
29 |
+
<TooltipTrigger className="">
|
30 |
+
<div
|
31 |
+
className={cn(
|
32 |
+
`grid h-4 w-5 scale-100 cursor-pointer grid-cols-4 grid-rows-4 overflow-hidden rounded border border-neutral-100 opacity-70 transition-all duration-200 ease-in-out hover:scale-110 hover:opacity-100`,
|
33 |
+
className
|
34 |
+
)}
|
35 |
+
onClick={() => {
|
36 |
+
setFullscreen(!isFullscreen)
|
37 |
+
}}
|
38 |
+
>
|
39 |
+
<div className="flex h-4 w-4 items-center justify-center">
|
40 |
+
<RiFullscreenLine
|
41 |
+
className={cn(
|
42 |
+
`absolute -mt-0.5 ml-0.5 h-3 w-3`,
|
43 |
+
`transition-all duration-200 ease-in-out`,
|
44 |
+
!isFullscreen ? 'opacity-100' : 'opacity-0'
|
45 |
+
)}
|
46 |
+
/>
|
47 |
+
<RiFullscreenExitLine
|
48 |
+
className={cn(
|
49 |
+
`absolute -mt-0.5 ml-0.5 h-3 w-3`,
|
50 |
+
`transition-all duration-200 ease-in-out`,
|
51 |
+
isFullscreen ? 'opacity-100' : 'opacity-0'
|
52 |
+
)}
|
53 |
+
/>
|
54 |
+
</div>
|
55 |
+
</div>
|
56 |
+
</TooltipTrigger>
|
57 |
+
<TooltipContent className={cn(`mr-4 mt-2 flex text-xs font-light`)}>
|
58 |
+
Toggle fullscreen
|
59 |
+
</TooltipContent>
|
60 |
+
</Tooltip>
|
61 |
+
)
|
62 |
+
}
|
src/components/toolbars/top-menu/ToggleView/index.tsx
CHANGED
@@ -23,7 +23,7 @@ export function ToggleView({
|
|
23 |
<TooltipTrigger className="">
|
24 |
<div
|
25 |
className={cn(
|
26 |
-
`group grid h-4 w-5 scale-100 cursor-pointer grid-cols-4 grid-rows-4 overflow-hidden rounded border border-
|
27 |
)}
|
28 |
onClick={() => {
|
29 |
setVisible(!isVisible)
|
@@ -32,7 +32,9 @@ export function ToggleView({
|
|
32 |
<div
|
33 |
className={cn(
|
34 |
`flex transition-all duration-200 ease-in-out group-hover:scale-110 group-hover:border-stone-100`,
|
35 |
-
isVisible
|
|
|
|
|
36 |
className
|
37 |
)}
|
38 |
></div>
|
|
|
23 |
<TooltipTrigger className="">
|
24 |
<div
|
25 |
className={cn(
|
26 |
+
`group grid h-4 w-5 scale-100 cursor-pointer grid-cols-4 grid-rows-4 overflow-hidden rounded border border-neutral-100 opacity-70 transition-all duration-200 ease-in-out hover:scale-110 hover:opacity-100`
|
27 |
)}
|
28 |
onClick={() => {
|
29 |
setVisible(!isVisible)
|
|
|
32 |
<div
|
33 |
className={cn(
|
34 |
`flex transition-all duration-200 ease-in-out group-hover:scale-110 group-hover:border-stone-100`,
|
35 |
+
isVisible
|
36 |
+
? `border-neutral-100 bg-neutral-400`
|
37 |
+
: `border-neutral-400`,
|
38 |
className
|
39 |
)}
|
40 |
></div>
|
src/components/toolbars/top-menu/ToggleWindowLayout/index.tsx
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { VscMultipleWindows } from 'react-icons/vsc'
|
2 |
+
import { CiGrid32 } from 'react-icons/ci'
|
3 |
+
|
4 |
+
import { GiStrawberry } from 'react-icons/gi'
|
5 |
+
import { UIWindowLayout } from '@aitube/clapper-services'
|
6 |
+
|
7 |
+
import { cn } from '@/lib/utils'
|
8 |
+
import {
|
9 |
+
Tooltip,
|
10 |
+
TooltipContent,
|
11 |
+
TooltipTrigger,
|
12 |
+
} from '@/components/ui/tooltip'
|
13 |
+
import { useUI } from '@/services'
|
14 |
+
import { BiSolidWindowAlt } from 'react-icons/bi'
|
15 |
+
|
16 |
+
export function ToggleWindowLayout({
|
17 |
+
className = '',
|
18 |
+
}: {
|
19 |
+
className?: string
|
20 |
+
} = {}) {
|
21 |
+
const windowLayout = useUI((s) => s.windowLayout)
|
22 |
+
const setWindowLayout = useUI((s) => s.setWindowLayout)
|
23 |
+
|
24 |
+
return (
|
25 |
+
<Tooltip>
|
26 |
+
<TooltipTrigger className="">
|
27 |
+
<div
|
28 |
+
className={cn(
|
29 |
+
`grid h-4 w-5 scale-100 cursor-pointer grid-cols-4 grid-rows-4 overflow-hidden rounded border border-neutral-100 opacity-70 transition-all duration-200 ease-in-out hover:scale-110 hover:opacity-100`,
|
30 |
+
className
|
31 |
+
)}
|
32 |
+
onClick={() => {
|
33 |
+
setWindowLayout(
|
34 |
+
windowLayout === UIWindowLayout.FLYING
|
35 |
+
? UIWindowLayout.GRID
|
36 |
+
: UIWindowLayout.FLYING
|
37 |
+
)
|
38 |
+
}}
|
39 |
+
>
|
40 |
+
<div className="flex h-4 w-4 items-center justify-center">
|
41 |
+
<GiStrawberry
|
42 |
+
className={cn(
|
43 |
+
`absolute -mt-0.5 ml-0.5 h-3 w-3`,
|
44 |
+
`transition-all duration-200 ease-in-out`,
|
45 |
+
windowLayout === UIWindowLayout.FLYING
|
46 |
+
? 'opacity-100'
|
47 |
+
: 'opacity-0'
|
48 |
+
)}
|
49 |
+
/>
|
50 |
+
<BiSolidWindowAlt
|
51 |
+
className={cn(
|
52 |
+
`absolute -mt-0.5 ml-0.5 h-3 w-3`,
|
53 |
+
`transition-all duration-200 ease-in-out`,
|
54 |
+
windowLayout === UIWindowLayout.GRID
|
55 |
+
? 'opacity-100'
|
56 |
+
: 'opacity-0'
|
57 |
+
)}
|
58 |
+
/>
|
59 |
+
</div>
|
60 |
+
</div>
|
61 |
+
</TooltipTrigger>
|
62 |
+
<TooltipContent className={cn(`mr-4 mt-2 flex text-xs font-light`)}>
|
63 |
+
Toggle layout
|
64 |
+
</TooltipContent>
|
65 |
+
</Tooltip>
|
66 |
+
)
|
67 |
+
}
|
src/components/toolbars/top-menu/index.tsx
CHANGED
@@ -24,6 +24,8 @@ import {
|
|
24 |
import { ToggleView } from './ToggleView'
|
25 |
import { UIWindowLayout } from '@aitube/clapper-services'
|
26 |
import { Tasks } from '../bottom-bar/tasks'
|
|
|
|
|
27 |
|
28 |
export function TopMenu() {
|
29 |
const isBusyResolving = useResolver((s) => s.isBusyResolving)
|
@@ -38,6 +40,7 @@ export function TopMenu() {
|
|
38 |
const setShowAssistant = useUI((s) => s.setShowAssistant)
|
39 |
const setIsTopMenuOpen = useUI((s) => s.setIsTopMenuOpen)
|
40 |
const windowLayout = useUI((s) => s.windowLayout)
|
|
|
41 |
const hasBetaAccess = useUI((s) => s.hasBetaAccess)
|
42 |
|
43 |
return (
|
@@ -107,6 +110,10 @@ export function TopMenu() {
|
|
107 |
</>
|
108 |
)}
|
109 |
|
|
|
|
|
|
|
|
|
110 |
<Tooltip>
|
111 |
<TooltipTrigger className="">
|
112 |
<div className="ml-2 scale-100 cursor-pointer text-stone-300/70 transition-all duration-200 ease-in-out hover:scale-110 hover:text-stone-100/90">
|
|
|
24 |
import { ToggleView } from './ToggleView'
|
25 |
import { UIWindowLayout } from '@aitube/clapper-services'
|
26 |
import { Tasks } from '../bottom-bar/tasks'
|
27 |
+
import { ToggleWindowLayout } from './ToggleWindowLayout'
|
28 |
+
import { ToggleFullScreen } from './ToggleFullScreen'
|
29 |
|
30 |
export function TopMenu() {
|
31 |
const isBusyResolving = useResolver((s) => s.isBusyResolving)
|
|
|
40 |
const setShowAssistant = useUI((s) => s.setShowAssistant)
|
41 |
const setIsTopMenuOpen = useUI((s) => s.setIsTopMenuOpen)
|
42 |
const windowLayout = useUI((s) => s.windowLayout)
|
43 |
+
const setWindowLayout = useUI((s) => s.setWindowLayout)
|
44 |
const hasBetaAccess = useUI((s) => s.hasBetaAccess)
|
45 |
|
46 |
return (
|
|
|
110 |
</>
|
111 |
)}
|
112 |
|
113 |
+
<ToggleFullScreen />
|
114 |
+
|
115 |
+
<ToggleWindowLayout />
|
116 |
+
|
117 |
<Tooltip>
|
118 |
<TooltipTrigger className="">
|
119 |
<div className="ml-2 scale-100 cursor-pointer text-stone-300/70 transition-all duration-200 ease-in-out hover:scale-110 hover:text-stone-100/90">
|
src/components/toolbars/top-menu/view/index.tsx
CHANGED
@@ -5,6 +5,7 @@ import { useEffect } from 'react'
|
|
5 |
import {
|
6 |
MenubarCheckboxItem,
|
7 |
MenubarContent,
|
|
|
8 |
MenubarMenu,
|
9 |
MenubarSeparator,
|
10 |
MenubarTrigger,
|
@@ -13,6 +14,10 @@ import { useFullscreenStatus } from '@/lib/hooks'
|
|
13 |
import { useUI } from '@/services/ui'
|
14 |
import { ThemeList } from '../lists/ThemeList'
|
15 |
import { UIWindowLayout } from '@aitube/clapper-services'
|
|
|
|
|
|
|
|
|
16 |
|
17 |
export function TopMenuView() {
|
18 |
const [isFullscreen, setFullscreen, ref] = useFullscreenStatus()
|
@@ -49,14 +54,8 @@ export function TopMenuView() {
|
|
49 |
<MenubarMenu>
|
50 |
<MenubarTrigger>View</MenubarTrigger>
|
51 |
<MenubarContent>
|
52 |
-
<
|
53 |
-
checked={isFullscreen}
|
54 |
onClick={(e) => {
|
55 |
-
// currently isFullscreen is a bit buggy and might not reflect the correct value
|
56 |
-
// setFullscreen(!isFullscreen)
|
57 |
-
|
58 |
-
// so to be sure we use setFullscreen in "toggle" mode
|
59 |
-
// (ie. we don't pass a boolean, so it will act as a current value switch)
|
60 |
setFullscreen()
|
61 |
|
62 |
e.stopPropagation()
|
@@ -64,11 +63,32 @@ export function TopMenuView() {
|
|
64 |
return false
|
65 |
}}
|
66 |
>
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
onClick={(e) => {
|
73 |
setWindowLayout(
|
74 |
windowLayout === UIWindowLayout.FLYING
|
@@ -81,8 +101,34 @@ export function TopMenuView() {
|
|
81 |
return false
|
82 |
}}
|
83 |
>
|
84 |
-
|
85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
|
87 |
{/*
|
88 |
<MenubarSeparator />
|
|
|
5 |
import {
|
6 |
MenubarCheckboxItem,
|
7 |
MenubarContent,
|
8 |
+
MenubarItem,
|
9 |
MenubarMenu,
|
10 |
MenubarSeparator,
|
11 |
MenubarTrigger,
|
|
|
14 |
import { useUI } from '@/services/ui'
|
15 |
import { ThemeList } from '../lists/ThemeList'
|
16 |
import { UIWindowLayout } from '@aitube/clapper-services'
|
17 |
+
import { cn } from '@/lib/utils'
|
18 |
+
import { GiStrawberry } from 'react-icons/gi'
|
19 |
+
import { BiSolidWindowAlt } from 'react-icons/bi'
|
20 |
+
import { RiFullscreenExitLine, RiFullscreenLine } from 'react-icons/ri'
|
21 |
|
22 |
export function TopMenuView() {
|
23 |
const [isFullscreen, setFullscreen, ref] = useFullscreenStatus()
|
|
|
54 |
<MenubarMenu>
|
55 |
<MenubarTrigger>View</MenubarTrigger>
|
56 |
<MenubarContent>
|
57 |
+
<MenubarItem
|
|
|
58 |
onClick={(e) => {
|
|
|
|
|
|
|
|
|
|
|
59 |
setFullscreen()
|
60 |
|
61 |
e.stopPropagation()
|
|
|
63 |
return false
|
64 |
}}
|
65 |
>
|
66 |
+
<div
|
67 |
+
className={cn(
|
68 |
+
`grid h-4 w-5 scale-100 cursor-pointer grid-cols-4 grid-rows-4 overflow-hidden rounded border border-neutral-100 opacity-70 transition-all duration-200 ease-in-out hover:scale-110 hover:opacity-100`
|
69 |
+
)}
|
70 |
+
>
|
71 |
+
<div className="flex h-4 w-4 items-center justify-center">
|
72 |
+
<RiFullscreenLine
|
73 |
+
className={cn(
|
74 |
+
`absolute -mt-0.5 ml-0.5 h-3 w-3`,
|
75 |
+
`transition-all duration-200 ease-in-out`,
|
76 |
+
!isFullscreen ? 'opacity-100' : 'opacity-0'
|
77 |
+
)}
|
78 |
+
/>
|
79 |
+
<RiFullscreenExitLine
|
80 |
+
className={cn(
|
81 |
+
`absolute -mt-0.5 ml-0.5 h-3 w-3`,
|
82 |
+
`transition-all duration-200 ease-in-out`,
|
83 |
+
isFullscreen ? 'opacity-100' : 'opacity-0'
|
84 |
+
)}
|
85 |
+
/>
|
86 |
+
</div>
|
87 |
+
</div>
|
88 |
+
<span className="ml-2">Toggle fullscreen</span>
|
89 |
+
</MenubarItem>
|
90 |
+
|
91 |
+
<MenubarItem
|
92 |
onClick={(e) => {
|
93 |
setWindowLayout(
|
94 |
windowLayout === UIWindowLayout.FLYING
|
|
|
101 |
return false
|
102 |
}}
|
103 |
>
|
104 |
+
<div
|
105 |
+
className={cn(
|
106 |
+
`grid h-4 w-5 scale-100 cursor-pointer grid-cols-4 grid-rows-4 overflow-hidden rounded border border-neutral-100 opacity-70 transition-all duration-200 ease-in-out hover:scale-110 hover:opacity-100`
|
107 |
+
)}
|
108 |
+
>
|
109 |
+
<div className="flex h-4 w-4 items-center justify-center">
|
110 |
+
<GiStrawberry
|
111 |
+
className={cn(
|
112 |
+
`absolute -mt-0.5 ml-0.5 h-3 w-3`,
|
113 |
+
`transition-all duration-200 ease-in-out`,
|
114 |
+
windowLayout === UIWindowLayout.FLYING
|
115 |
+
? 'opacity-100'
|
116 |
+
: 'opacity-0'
|
117 |
+
)}
|
118 |
+
/>
|
119 |
+
<BiSolidWindowAlt
|
120 |
+
className={cn(
|
121 |
+
`absolute -mt-0.5 ml-0.5 h-3 w-3`,
|
122 |
+
`transition-all duration-200 ease-in-out`,
|
123 |
+
windowLayout === UIWindowLayout.GRID
|
124 |
+
? 'opacity-100'
|
125 |
+
: 'opacity-0'
|
126 |
+
)}
|
127 |
+
/>
|
128 |
+
</div>
|
129 |
+
</div>
|
130 |
+
<span className="ml-2">Toggle layout</span>
|
131 |
+
</MenubarItem>
|
132 |
|
133 |
{/*
|
134 |
<MenubarSeparator />
|
src/components/windows/index.tsx
CHANGED
@@ -1,4 +1,11 @@
|
|
1 |
-
import React, {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
import { IoClose } from 'react-icons/io5'
|
3 |
import { LuPanelTopClose, LuPanelTopOpen } from 'react-icons/lu'
|
4 |
|
@@ -7,6 +14,7 @@ import { useTheme } from '@/services'
|
|
7 |
import { useWindows } from '@/services/windows/useWindows'
|
8 |
import { useFullscreenStatus } from '@/lib/hooks'
|
9 |
import { RiFullscreenFill } from 'react-icons/ri'
|
|
|
10 |
|
11 |
// FruityDesktop component
|
12 |
export const FruityDesktop: React.FC<{
|
@@ -29,7 +37,6 @@ export const FruityDesktop: React.FC<{
|
|
29 |
)
|
30 |
}
|
31 |
|
32 |
-
// FruityWindow component
|
33 |
export const FruityWindow: React.FC<{
|
34 |
id: string
|
35 |
title?: string | JSX.Element
|
@@ -44,372 +51,393 @@ export const FruityWindow: React.FC<{
|
|
44 |
canBeFullScreen?: boolean
|
45 |
toolbar?: (props: { isFocused: boolean }) => JSX.Element
|
46 |
children?: React.ReactNode
|
47 |
-
}> = (
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
defaultY,
|
56 |
-
canBeReduced = true,
|
57 |
-
canBeClosed = true,
|
58 |
-
canBeFullScreen = true,
|
59 |
-
toolbar,
|
60 |
-
children,
|
61 |
-
}) => {
|
62 |
-
const theme = useTheme()
|
63 |
-
const windowRef = useRef<HTMLDivElement>(null)
|
64 |
-
const headerRef = useRef<HTMLDivElement>(null)
|
65 |
-
const [isEditing, setIsEditing] = useState(false)
|
66 |
-
const [isDragging, setIsDragging] = useState(false)
|
67 |
-
const [isResizing, setIsResizing] = useState(false)
|
68 |
-
const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 })
|
69 |
-
const [resizeDirection, setResizeDirection] = useState('')
|
70 |
-
|
71 |
-
const window = useWindows(useCallback((state) => state.windows[id], [id]))
|
72 |
-
const addWindow = useWindows((state) => state.addWindow)
|
73 |
-
const updateWindow = useWindows((state) => state.updateWindow)
|
74 |
-
const focusWindow = useWindows((state) => state.focusWindow)
|
75 |
-
const removeWindow = useWindows((state) => state.removeWindow)
|
76 |
-
|
77 |
-
const [isFullscreen, setFullscreen, ref] = useFullscreenStatus()
|
78 |
-
|
79 |
-
const parseSize = (size: number | string): number => {
|
80 |
-
if (typeof size === 'number') return size
|
81 |
-
if (typeof size === 'string') {
|
82 |
-
const parsed = parseInt(size, 10)
|
83 |
-
return isNaN(parsed) ? 0 : parsed
|
84 |
-
}
|
85 |
-
return 0
|
86 |
-
}
|
87 |
-
|
88 |
-
useEffect(() => {
|
89 |
-
if (!window) {
|
90 |
-
addWindow({
|
91 |
-
id,
|
92 |
-
title,
|
93 |
-
isVisible: true,
|
94 |
-
width: parseSize(defaultWidth),
|
95 |
-
height: parseSize(defaultHeight),
|
96 |
-
x: defaultX,
|
97 |
-
y: defaultY,
|
98 |
-
canBeReduced,
|
99 |
-
canBeClosed,
|
100 |
-
})
|
101 |
-
}
|
102 |
-
}, [
|
103 |
-
addWindow,
|
104 |
-
canBeClosed,
|
105 |
-
canBeReduced,
|
106 |
-
defaultHeight,
|
107 |
-
defaultWidth,
|
108 |
defaultX,
|
109 |
defaultY,
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
|
115 |
-
|
116 |
-
const
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
}
|
121 |
|
122 |
-
|
123 |
-
return () => {
|
124 |
-
document.removeEventListener('mousedown', handleMouseDown)
|
125 |
-
}
|
126 |
-
}, [focusWindow, id])
|
127 |
|
128 |
-
|
129 |
-
|
130 |
-
if (
|
131 |
-
|
132 |
-
|
133 |
-
x: e.clientX - window.x,
|
134 |
-
y: e.clientY - window.y,
|
135 |
-
})
|
136 |
}
|
137 |
-
|
138 |
-
[window]
|
139 |
-
)
|
140 |
-
|
141 |
-
const handleDrag = useCallback(
|
142 |
-
(e: MouseEvent) => {
|
143 |
-
if (isDragging && window) {
|
144 |
-
const newY = Math.max(0, e.clientY - dragOffset.y) // Ensure y is at least 32px from the top
|
145 |
-
updateWindow(id, {
|
146 |
-
x: e.clientX - dragOffset.x,
|
147 |
-
y: newY,
|
148 |
-
})
|
149 |
-
}
|
150 |
-
},
|
151 |
-
[dragOffset.x, dragOffset.y, id, isDragging, updateWindow, window]
|
152 |
-
)
|
153 |
-
const handleDragEnd = useCallback(() => {
|
154 |
-
setIsDragging(false)
|
155 |
-
}, [])
|
156 |
-
|
157 |
-
useEffect(() => {
|
158 |
-
if (isDragging) {
|
159 |
-
document.addEventListener('mousemove', handleDrag)
|
160 |
-
document.addEventListener('mouseup', handleDragEnd)
|
161 |
-
} else {
|
162 |
-
document.removeEventListener('mousemove', handleDrag)
|
163 |
-
document.removeEventListener('mouseup', handleDragEnd)
|
164 |
}
|
165 |
-
return () => {
|
166 |
-
document.removeEventListener('mousemove', handleDrag)
|
167 |
-
document.removeEventListener('mouseup', handleDragEnd)
|
168 |
-
}
|
169 |
-
}, [isDragging, handleDrag, handleDragEnd])
|
170 |
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
x:
|
180 |
-
y:
|
|
|
|
|
181 |
})
|
182 |
}
|
183 |
-
},
|
184 |
-
|
185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
let newHeight = window.height
|
194 |
-
let newX = window.x
|
195 |
-
let newY = window.y
|
196 |
|
197 |
-
|
198 |
-
|
|
|
|
|
|
|
199 |
|
200 |
-
|
201 |
-
|
202 |
-
|
|
|
|
|
|
|
|
|
|
|
203 |
}
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
|
|
|
|
|
|
|
|
|
|
211 |
}
|
212 |
-
|
213 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
215 |
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
220 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
|
|
|
|
|
|
|
|
|
|
229 |
}
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
isResizing,
|
236 |
-
minHeight,
|
237 |
-
minWidth,
|
238 |
-
resizeDirection,
|
239 |
-
updateWindow,
|
240 |
-
window,
|
241 |
-
]
|
242 |
-
)
|
243 |
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
|
|
248 |
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
document.removeEventListener('mousemove', handleResize)
|
259 |
-
document.removeEventListener('mouseup', handleResizeEnd)
|
260 |
-
}
|
261 |
-
}, [isResizing, handleResize, handleResizeEnd])
|
262 |
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
|
|
|
|
|
|
278 |
|
279 |
-
|
280 |
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
: window.isReduced
|
289 |
-
? 'auto'
|
290 |
-
: `${window.height}px`,
|
291 |
-
transform: isFullscreen
|
292 |
-
? 'none'
|
293 |
-
: `translate(${window.x}px, ${window.y}px)`,
|
294 |
-
zIndex: window.zIndex,
|
295 |
-
backgroundColor: theme.editorBgColor || 'rgb(38, 38, 38)',
|
296 |
-
borderColor:
|
297 |
-
theme.windowBorderColor ||
|
298 |
-
theme.editorBorderColor ||
|
299 |
-
'rgb(64, 64, 64)',
|
300 |
-
borderRadius: isFullscreen ? '0' : theme.windowBorderRadius || '8px',
|
301 |
-
}}
|
302 |
-
className={cn(
|
303 |
-
`absolute overflow-hidden shadow-lg`,
|
304 |
-
`border border-white/5`,
|
305 |
-
window.isFocused ? 'shadow-xl' : '',
|
306 |
-
isFullscreen ? 'fixed inset-0' : ''
|
307 |
-
)}
|
308 |
-
>
|
309 |
-
{!isFullscreen && (
|
310 |
-
<div
|
311 |
-
ref={headerRef}
|
312 |
-
className={cn(
|
313 |
-
`flex h-8 cursor-move items-center justify-between border-b border-b-white/10 px-2 text-sm text-white/60`
|
314 |
-
)}
|
315 |
-
onMouseDown={handleDragStart}
|
316 |
-
onDoubleClick={handleHeaderDoubleClick}
|
317 |
-
style={{
|
318 |
-
backgroundColor: theme.editorMenuBgColor || 'rgb(38, 38, 38)',
|
319 |
-
}}
|
320 |
-
>
|
321 |
-
{isEditing ? (
|
322 |
-
<input
|
323 |
-
type="text"
|
324 |
-
value={typeof window.title === 'string' ? window.title : ''}
|
325 |
-
onChange={(e) => updateWindow(id, { title: e.target.value })}
|
326 |
-
onBlur={() => setIsEditing(false)}
|
327 |
-
onKeyDown={(e) => {
|
328 |
-
if (e.key === 'Enter') setIsEditing(false)
|
329 |
-
}}
|
330 |
-
className="rounded-none bg-neutral-950/80 px-0 text-sm text-white/60"
|
331 |
-
autoFocus
|
332 |
-
/>
|
333 |
-
) : (
|
334 |
-
<div onDoubleClick={() => setIsEditing(true)}>
|
335 |
-
{typeof window.title === 'string'
|
336 |
-
? window.title
|
337 |
-
: (window.title as any)({ isFocused: window.isFocused })}
|
338 |
-
</div>
|
339 |
-
)}
|
340 |
-
<div className="flex space-x-2">
|
341 |
-
{toolbar && toolbar({ isFocused: window.isFocused })}
|
342 |
-
{canBeFullScreen && (
|
343 |
-
<button
|
344 |
-
onClick={() => setFullscreen(true)}
|
345 |
-
className="text-white/60 hover:text-white/80"
|
346 |
-
>
|
347 |
-
<RiFullscreenFill />
|
348 |
-
</button>
|
349 |
-
)}
|
350 |
-
{canBeReduced && (
|
351 |
-
<button
|
352 |
-
onClick={toggleReduce}
|
353 |
-
className="text-white/60 hover:text-white/80"
|
354 |
-
>
|
355 |
-
{window.isReduced ? <LuPanelTopOpen /> : <LuPanelTopClose />}
|
356 |
-
</button>
|
357 |
)}
|
358 |
-
{
|
359 |
-
|
360 |
-
|
361 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
362 |
>
|
363 |
-
|
364 |
-
|
|
|
|
|
365 |
)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
366 |
</div>
|
367 |
-
|
368 |
-
|
369 |
-
{!window.isReduced && (
|
370 |
-
<div
|
371 |
-
ref={ref as any}
|
372 |
-
className={isFullscreen ? 'h-full w-full' : 'h-[calc(100%-32px)]'}
|
373 |
-
>
|
374 |
-
{children}
|
375 |
-
</div>
|
376 |
-
)}
|
377 |
-
{!isFullscreen && !window.isReduced && (
|
378 |
-
<>
|
379 |
<div
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React, {
|
2 |
+
useState,
|
3 |
+
useCallback,
|
4 |
+
useRef,
|
5 |
+
useEffect,
|
6 |
+
useMemo,
|
7 |
+
memo,
|
8 |
+
} from 'react'
|
9 |
import { IoClose } from 'react-icons/io5'
|
10 |
import { LuPanelTopClose, LuPanelTopOpen } from 'react-icons/lu'
|
11 |
|
|
|
14 |
import { useWindows } from '@/services/windows/useWindows'
|
15 |
import { useFullscreenStatus } from '@/lib/hooks'
|
16 |
import { RiFullscreenFill } from 'react-icons/ri'
|
17 |
+
import { isValidNumber } from '@aitube/clap'
|
18 |
|
19 |
// FruityDesktop component
|
20 |
export const FruityDesktop: React.FC<{
|
|
|
37 |
)
|
38 |
}
|
39 |
|
|
|
40 |
export const FruityWindow: React.FC<{
|
41 |
id: string
|
42 |
title?: string | JSX.Element
|
|
|
51 |
canBeFullScreen?: boolean
|
52 |
toolbar?: (props: { isFocused: boolean }) => JSX.Element
|
53 |
children?: React.ReactNode
|
54 |
+
}> = memo(
|
55 |
+
({
|
56 |
+
id,
|
57 |
+
title = 'Untitled',
|
58 |
+
defaultWidth = 800,
|
59 |
+
minWidth = 160,
|
60 |
+
defaultHeight = 600,
|
61 |
+
minHeight = 100,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
defaultX,
|
63 |
defaultY,
|
64 |
+
canBeReduced = true,
|
65 |
+
canBeClosed = true,
|
66 |
+
canBeFullScreen = true,
|
67 |
+
toolbar,
|
68 |
+
children,
|
69 |
+
}) => {
|
70 |
+
const theme = useTheme()
|
71 |
+
const windowRef = useRef<HTMLDivElement>(null)
|
72 |
+
const headerRef = useRef<HTMLDivElement>(null)
|
73 |
+
const [isEditing, setIsEditing] = useState(false)
|
74 |
+
const [isDragging, setIsDragging] = useState(false)
|
75 |
+
const [isResizing, setIsResizing] = useState(false)
|
76 |
+
const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 })
|
77 |
+
const [resizeDirection, setResizeDirection] = useState('')
|
78 |
|
79 |
+
const window = useWindows(useCallback((state) => state.windows[id], [id]))
|
80 |
+
const addWindow = useWindows((state) => state.addWindow)
|
81 |
+
const updateWindow = useWindows((state) => state.updateWindow)
|
82 |
+
const focusWindow = useWindows((state) => state.focusWindow)
|
83 |
+
const removeWindow = useWindows((state) => state.removeWindow)
|
|
|
84 |
|
85 |
+
const [isFullscreen, setFullscreen, ref] = useFullscreenStatus()
|
|
|
|
|
|
|
|
|
86 |
|
87 |
+
const parseSize = (size: number | string): number => {
|
88 |
+
if (typeof size === 'number') return size
|
89 |
+
if (typeof size === 'string') {
|
90 |
+
const parsed = parseInt(size, 10)
|
91 |
+
return isNaN(parsed) ? 0 : parsed
|
|
|
|
|
|
|
92 |
}
|
93 |
+
return 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
}
|
|
|
|
|
|
|
|
|
|
|
95 |
|
96 |
+
useEffect(() => {
|
97 |
+
if (!window) {
|
98 |
+
addWindow({
|
99 |
+
id,
|
100 |
+
title,
|
101 |
+
isVisible: true,
|
102 |
+
width: parseSize(defaultWidth),
|
103 |
+
height: parseSize(defaultHeight),
|
104 |
+
x: defaultX,
|
105 |
+
y: defaultY,
|
106 |
+
canBeReduced,
|
107 |
+
canBeClosed,
|
108 |
})
|
109 |
}
|
110 |
+
}, [
|
111 |
+
addWindow,
|
112 |
+
canBeClosed,
|
113 |
+
canBeReduced,
|
114 |
+
defaultHeight,
|
115 |
+
defaultWidth,
|
116 |
+
defaultX,
|
117 |
+
defaultY,
|
118 |
+
id,
|
119 |
+
title,
|
120 |
+
window,
|
121 |
+
])
|
122 |
|
123 |
+
useEffect(() => {
|
124 |
+
const handleMouseDown = (e: MouseEvent) => {
|
125 |
+
if (windowRef.current && windowRef.current.contains(e.target as Node)) {
|
126 |
+
focusWindow(id)
|
127 |
+
}
|
128 |
+
}
|
|
|
|
|
|
|
129 |
|
130 |
+
document.addEventListener('mousedown', handleMouseDown)
|
131 |
+
return () => {
|
132 |
+
document.removeEventListener('mousedown', handleMouseDown)
|
133 |
+
}
|
134 |
+
}, [focusWindow, id])
|
135 |
|
136 |
+
const handleDragStart = useCallback(
|
137 |
+
(e: React.MouseEvent<HTMLDivElement>) => {
|
138 |
+
if (isValidNumber(window?.x) && isValidNumber(window?.y)) {
|
139 |
+
setIsDragging(true)
|
140 |
+
setDragOffset({
|
141 |
+
x: e.clientX - window.x,
|
142 |
+
y: e.clientY - window.y,
|
143 |
+
})
|
144 |
}
|
145 |
+
},
|
146 |
+
[window?.x, window?.y, setIsDragging, setDragOffset]
|
147 |
+
)
|
148 |
+
|
149 |
+
const handleDrag = useCallback(
|
150 |
+
(e: MouseEvent) => {
|
151 |
+
if (isDragging && window) {
|
152 |
+
const newY = Math.max(0, e.clientY - dragOffset.y) // Ensure y is at least 32px from the top
|
153 |
+
updateWindow(id, {
|
154 |
+
x: e.clientX - dragOffset.x,
|
155 |
+
y: newY,
|
156 |
+
})
|
157 |
}
|
158 |
+
},
|
159 |
+
[dragOffset.x, dragOffset.y, id, isDragging, updateWindow, window]
|
160 |
+
)
|
161 |
+
const handleDragEnd = useCallback(() => {
|
162 |
+
setIsDragging(false)
|
163 |
+
}, [])
|
164 |
+
|
165 |
+
useEffect(() => {
|
166 |
+
if (isDragging) {
|
167 |
+
document.addEventListener('mousemove', handleDrag)
|
168 |
+
document.addEventListener('mouseup', handleDragEnd)
|
169 |
+
} else {
|
170 |
+
document.removeEventListener('mousemove', handleDrag)
|
171 |
+
document.removeEventListener('mouseup', handleDragEnd)
|
172 |
+
}
|
173 |
+
return () => {
|
174 |
+
document.removeEventListener('mousemove', handleDrag)
|
175 |
+
document.removeEventListener('mouseup', handleDragEnd)
|
176 |
+
}
|
177 |
+
}, [isDragging, handleDrag, handleDragEnd])
|
178 |
+
|
179 |
+
const handleResizeStart = useCallback(
|
180 |
+
(e: React.MouseEvent<HTMLDivElement>, direction: string) => {
|
181 |
+
e.preventDefault()
|
182 |
+
e.stopPropagation()
|
183 |
+
if (window) {
|
184 |
+
setIsResizing(true)
|
185 |
+
setResizeDirection(direction)
|
186 |
+
setDragOffset({
|
187 |
+
x: e.clientX,
|
188 |
+
y: e.clientY,
|
189 |
+
})
|
190 |
}
|
191 |
+
},
|
192 |
+
[window, setIsResizing, setResizeDirection, setDragOffset]
|
193 |
+
)
|
194 |
+
|
195 |
+
const handleResize = useCallback(
|
196 |
+
(e: MouseEvent) => {
|
197 |
+
if (isResizing && window) {
|
198 |
+
const dx = e.clientX - dragOffset.x
|
199 |
+
const dy = e.clientY - dragOffset.y
|
200 |
+
let newWidth = window.width
|
201 |
+
let newHeight = window.height
|
202 |
+
let newX = window.x
|
203 |
+
let newY = window.y
|
204 |
+
|
205 |
+
const parsedMinWidth = parseSize(minWidth)
|
206 |
+
const parsedMinHeight = parseSize(minHeight)
|
207 |
|
208 |
+
if (resizeDirection.includes('w')) {
|
209 |
+
newWidth = Math.max(parsedMinWidth, window.width - dx)
|
210 |
+
newX = window.x + window.width - newWidth
|
211 |
+
}
|
212 |
+
if (resizeDirection.includes('e')) {
|
213 |
+
newWidth = Math.max(parsedMinWidth, window.width + dx)
|
214 |
+
}
|
215 |
+
if (resizeDirection.includes('n')) {
|
216 |
+
newHeight = Math.max(parsedMinHeight, window.height - dy)
|
217 |
+
newY = Math.max(0, window.y + window.height - newHeight)
|
218 |
+
newHeight = window.y + window.height - newY // Adjust height based on the new Y position
|
219 |
+
}
|
220 |
+
if (resizeDirection.includes('s')) {
|
221 |
+
newHeight = Math.max(parsedMinHeight, window.height + dy)
|
222 |
+
}
|
223 |
+
|
224 |
+
// Ensure the window doesn't go above the limit
|
225 |
+
if (newY < 0) {
|
226 |
+
newHeight = newHeight - (0 - newY)
|
227 |
+
newY = 0
|
228 |
+
}
|
229 |
+
|
230 |
+
updateWindow(id, {
|
231 |
+
width: newWidth,
|
232 |
+
height: newHeight,
|
233 |
+
x: newX,
|
234 |
+
y: newY,
|
235 |
+
})
|
236 |
+
setDragOffset({ x: e.clientX, y: e.clientY })
|
237 |
}
|
238 |
+
},
|
239 |
+
[
|
240 |
+
dragOffset.x,
|
241 |
+
dragOffset.y,
|
242 |
+
id,
|
243 |
+
isResizing,
|
244 |
+
minHeight,
|
245 |
+
minWidth,
|
246 |
+
resizeDirection,
|
247 |
+
updateWindow,
|
248 |
+
window,
|
249 |
+
]
|
250 |
+
)
|
251 |
|
252 |
+
const handleResizeEnd = useCallback(() => {
|
253 |
+
setIsResizing(false)
|
254 |
+
setResizeDirection('')
|
255 |
+
}, [])
|
256 |
+
|
257 |
+
useEffect(() => {
|
258 |
+
if (isResizing) {
|
259 |
+
document.addEventListener('mousemove', handleResize)
|
260 |
+
document.addEventListener('mouseup', handleResizeEnd)
|
261 |
+
} else {
|
262 |
+
document.removeEventListener('mousemove', handleResize)
|
263 |
+
document.removeEventListener('mouseup', handleResizeEnd)
|
264 |
}
|
265 |
+
return () => {
|
266 |
+
document.removeEventListener('mousemove', handleResize)
|
267 |
+
document.removeEventListener('mouseup', handleResizeEnd)
|
268 |
+
}
|
269 |
+
}, [isResizing, handleResize, handleResizeEnd])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
270 |
|
271 |
+
const toggleReduce = useCallback(() => {
|
272 |
+
if (window) {
|
273 |
+
updateWindow(id, { isReduced: !window.isReduced })
|
274 |
+
}
|
275 |
+
}, [id, updateWindow, window])
|
276 |
|
277 |
+
const handleHeaderDoubleClick = useCallback(
|
278 |
+
(e: React.MouseEvent<HTMLDivElement>) => {
|
279 |
+
// Check if the double-click occurred on the header background
|
280 |
+
if (e.target === headerRef.current) {
|
281 |
+
toggleReduce()
|
282 |
+
}
|
283 |
+
},
|
284 |
+
[toggleReduce]
|
285 |
+
)
|
|
|
|
|
|
|
|
|
286 |
|
287 |
+
const windowStyle = useMemo(
|
288 |
+
() =>
|
289 |
+
window
|
290 |
+
? {
|
291 |
+
width: isFullscreen ? '100vw' : `${window?.width}px`,
|
292 |
+
height: isFullscreen
|
293 |
+
? '100vh'
|
294 |
+
: window.isReduced
|
295 |
+
? 'auto'
|
296 |
+
: `${window.height}px`,
|
297 |
+
transform: isFullscreen
|
298 |
+
? 'none'
|
299 |
+
: `translate(${window.x}px, ${window.y}px)`,
|
300 |
+
zIndex: window.zIndex,
|
301 |
+
backgroundColor: theme.editorBgColor || 'rgb(38, 38, 38)',
|
302 |
+
borderColor:
|
303 |
+
theme.windowBorderColor ||
|
304 |
+
theme.editorBorderColor ||
|
305 |
+
'rgb(64, 64, 64)',
|
306 |
+
borderRadius: isFullscreen
|
307 |
+
? '0'
|
308 |
+
: theme.windowBorderRadius || '8px',
|
309 |
+
}
|
310 |
+
: {},
|
311 |
+
[isFullscreen, window, theme]
|
312 |
+
)
|
313 |
|
314 |
+
const windowClassName = useMemo(
|
315 |
+
() =>
|
316 |
+
window
|
317 |
+
? cn(
|
318 |
+
`absolute overflow-hidden shadow-lg`,
|
319 |
+
`border border-white/5`,
|
320 |
+
window.isFocused ? 'shadow-xl' : '',
|
321 |
+
isFullscreen ? 'fixed inset-0' : ''
|
322 |
+
)
|
323 |
+
: 'display-none',
|
324 |
+
[window, window?.isFocused, isFullscreen]
|
325 |
+
)
|
326 |
|
327 |
+
if (!window) return null
|
328 |
|
329 |
+
return (
|
330 |
+
<div ref={windowRef} style={windowStyle} className={windowClassName}>
|
331 |
+
{!isFullscreen && (
|
332 |
+
<div
|
333 |
+
ref={headerRef}
|
334 |
+
className={cn(
|
335 |
+
`flex h-8 cursor-move items-center justify-between border-b border-b-white/10 px-2 text-sm text-white/60`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
336 |
)}
|
337 |
+
onMouseDown={handleDragStart}
|
338 |
+
onDoubleClick={handleHeaderDoubleClick}
|
339 |
+
style={{
|
340 |
+
backgroundColor: theme.editorMenuBgColor || 'rgb(38, 38, 38)',
|
341 |
+
}}
|
342 |
+
>
|
343 |
+
{isEditing ? (
|
344 |
+
<input
|
345 |
+
type="text"
|
346 |
+
value={typeof window.title === 'string' ? window.title : ''}
|
347 |
+
onChange={(e) => updateWindow(id, { title: e.target.value })}
|
348 |
+
onBlur={() => setIsEditing(false)}
|
349 |
+
onKeyDown={(e) => {
|
350 |
+
if (e.key === 'Enter') setIsEditing(false)
|
351 |
+
}}
|
352 |
+
className="rounded-none bg-neutral-950/80 px-0 text-sm text-white/60"
|
353 |
+
autoFocus
|
354 |
+
/>
|
355 |
+
) : (
|
356 |
+
<div
|
357 |
+
// let's disable title editing, we don't need that for now
|
358 |
+
// onDoubleClick={() => setIsEditing(true)}
|
359 |
>
|
360 |
+
{typeof window.title === 'string'
|
361 |
+
? window.title
|
362 |
+
: (window.title as any)({ isFocused: window.isFocused })}
|
363 |
+
</div>
|
364 |
)}
|
365 |
+
<div className="flex space-x-2">
|
366 |
+
{toolbar && toolbar({ isFocused: window.isFocused })}
|
367 |
+
{canBeFullScreen && (
|
368 |
+
<button
|
369 |
+
onClick={() => setFullscreen(true)}
|
370 |
+
className="text-white/60 hover:text-white/80"
|
371 |
+
>
|
372 |
+
<RiFullscreenFill />
|
373 |
+
</button>
|
374 |
+
)}
|
375 |
+
{canBeReduced && (
|
376 |
+
<button
|
377 |
+
onClick={toggleReduce}
|
378 |
+
className="text-white/60 hover:text-white/80"
|
379 |
+
>
|
380 |
+
{window.isReduced ? <LuPanelTopOpen /> : <LuPanelTopClose />}
|
381 |
+
</button>
|
382 |
+
)}
|
383 |
+
{canBeClosed && (
|
384 |
+
<button
|
385 |
+
onClick={() => removeWindow(id)}
|
386 |
+
className="text-white/60 hover:text-white/80"
|
387 |
+
>
|
388 |
+
<IoClose />
|
389 |
+
</button>
|
390 |
+
)}
|
391 |
+
</div>
|
392 |
</div>
|
393 |
+
)}
|
394 |
+
{!window.isReduced && (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
395 |
<div
|
396 |
+
ref={ref as any}
|
397 |
+
className={isFullscreen ? 'h-full w-full' : 'h-[calc(100%-32px)]'}
|
398 |
+
>
|
399 |
+
{children}
|
400 |
+
</div>
|
401 |
+
)}
|
402 |
+
{!isFullscreen && !window.isReduced && (
|
403 |
+
<>
|
404 |
+
<div
|
405 |
+
className="absolute left-0 top-0 h-full w-2 cursor-ew-resize"
|
406 |
+
onMouseDown={(e) => handleResizeStart(e, 'w')}
|
407 |
+
/>
|
408 |
+
<div
|
409 |
+
className="absolute right-0 top-0 h-full w-2 cursor-ew-resize"
|
410 |
+
onMouseDown={(e) => handleResizeStart(e, 'e')}
|
411 |
+
/>
|
412 |
+
<div
|
413 |
+
className="absolute left-0 top-0 h-2 w-full cursor-ns-resize"
|
414 |
+
onMouseDown={(e) => handleResizeStart(e, 'n')}
|
415 |
+
/>
|
416 |
+
<div
|
417 |
+
className="absolute bottom-0 left-0 h-2 w-full cursor-ns-resize"
|
418 |
+
onMouseDown={(e) => handleResizeStart(e, 's')}
|
419 |
+
/>
|
420 |
+
<div
|
421 |
+
className="absolute left-0 top-0 h-2 w-2 cursor-nw-resize"
|
422 |
+
onMouseDown={(e) => handleResizeStart(e, 'nw')}
|
423 |
+
/>
|
424 |
+
<div
|
425 |
+
className="absolute right-0 top-0 h-2 w-2 cursor-ne-resize"
|
426 |
+
onMouseDown={(e) => handleResizeStart(e, 'ne')}
|
427 |
+
/>
|
428 |
+
<div
|
429 |
+
className="absolute bottom-0 left-0 h-2 w-2 cursor-sw-resize"
|
430 |
+
onMouseDown={(e) => handleResizeStart(e, 'sw')}
|
431 |
+
/>
|
432 |
+
<div
|
433 |
+
className="absolute bottom-0 right-0 h-2 w-2 cursor-se-resize"
|
434 |
+
onMouseDown={(e) => handleResizeStart(e, 'se')}
|
435 |
+
/>
|
436 |
+
</>
|
437 |
+
)}
|
438 |
+
</div>
|
439 |
+
)
|
440 |
+
}
|
441 |
+
)
|
442 |
+
|
443 |
+
FruityWindow.displayName = 'FruityWindow'
|
src/lib/core/constants.ts
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
export const HARD_LIMIT_NB_MAX_ASSETS_TO_GENERATE_IN_PARALLEL = 32
|
4 |
|
5 |
export const APP_NAME = 'Clapper.app'
|
6 |
-
export const APP_REVISION = '20240729+
|
7 |
|
8 |
export const APP_DOMAIN = 'Clapper.app'
|
9 |
export const APP_LINK = 'https://clapper.app'
|
|
|
3 |
export const HARD_LIMIT_NB_MAX_ASSETS_TO_GENERATE_IN_PARALLEL = 32
|
4 |
|
5 |
export const APP_NAME = 'Clapper.app'
|
6 |
+
export const APP_REVISION = '20240729+1441'
|
7 |
|
8 |
export const APP_DOMAIN = 'Clapper.app'
|
9 |
export const APP_LINK = 'https://clapper.app'
|
src/lib/hooks/useFullscreenStatus.ts
CHANGED
@@ -2,17 +2,17 @@
|
|
2 |
|
3 |
import React, {
|
4 |
useState,
|
5 |
-
|
6 |
useRef,
|
7 |
MutableRefObject,
|
8 |
useCallback,
|
9 |
} from 'react'
|
10 |
|
11 |
interface FullscreenElement {
|
12 |
-
fullscreenElement?: Element
|
13 |
-
mozFullScreenElement?: Element
|
14 |
-
msFullscreenElement?: Element
|
15 |
-
webkitFullscreenElement?: Element
|
16 |
}
|
17 |
|
18 |
declare global {
|
@@ -21,66 +21,68 @@ declare global {
|
|
21 |
|
22 |
export function useFullscreenStatus(): [
|
23 |
boolean,
|
24 |
-
(requestedValue?: boolean) => void
|
25 |
MutableRefObject<Element | null>,
|
26 |
] {
|
27 |
const elRef = useRef<Element | null>(null)
|
28 |
const [isFullscreen, setIsFullscreen] = useState(false)
|
29 |
|
30 |
-
const
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
)
|
35 |
-
: false
|
36 |
}, [])
|
37 |
|
38 |
const updateFullscreenStatus = useCallback(() => {
|
39 |
-
|
40 |
-
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
const setFullscreen = useCallback(
|
43 |
-
(
|
44 |
if (!elRef.current) return
|
45 |
|
46 |
-
const
|
47 |
-
const shouldBeFullScreen =
|
48 |
-
typeof maybeValue === 'boolean' ? maybeValue : !isFullScreen
|
49 |
|
50 |
-
if (
|
51 |
-
return
|
52 |
-
}
|
53 |
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
|
|
|
|
|
|
|
|
59 |
|
60 |
-
|
|
|
61 |
},
|
62 |
-
[
|
63 |
)
|
64 |
|
65 |
-
|
66 |
-
updateFullscreenStatus()
|
67 |
-
|
68 |
const fullscreenChangeHandler = () => {
|
69 |
-
updateFullscreenStatus
|
70 |
}
|
71 |
|
72 |
if (typeof document !== 'undefined') {
|
73 |
document.addEventListener('fullscreenchange', fullscreenChangeHandler)
|
74 |
|
75 |
-
//
|
76 |
-
|
77 |
|
78 |
return () => {
|
79 |
document.removeEventListener(
|
80 |
'fullscreenchange',
|
81 |
fullscreenChangeHandler
|
82 |
)
|
83 |
-
clearInterval(intervalId)
|
84 |
}
|
85 |
}
|
86 |
}, [updateFullscreenStatus])
|
@@ -89,15 +91,20 @@ export function useFullscreenStatus(): [
|
|
89 |
}
|
90 |
|
91 |
function getBrowserFullscreenElementProp(): keyof FullscreenElement {
|
92 |
-
if (typeof document
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
|
|
|
|
|
|
102 |
}
|
|
|
|
|
103 |
}
|
|
|
2 |
|
3 |
import React, {
|
4 |
useState,
|
5 |
+
useEffect,
|
6 |
useRef,
|
7 |
MutableRefObject,
|
8 |
useCallback,
|
9 |
} from 'react'
|
10 |
|
11 |
interface FullscreenElement {
|
12 |
+
fullscreenElement?: Element | null
|
13 |
+
mozFullScreenElement?: Element | null
|
14 |
+
msFullscreenElement?: Element | null
|
15 |
+
webkitFullscreenElement?: Element | null
|
16 |
}
|
17 |
|
18 |
declare global {
|
|
|
21 |
|
22 |
export function useFullscreenStatus(): [
|
23 |
boolean,
|
24 |
+
(requestedValue?: boolean) => Promise<void>,
|
25 |
MutableRefObject<Element | null>,
|
26 |
] {
|
27 |
const elRef = useRef<Element | null>(null)
|
28 |
const [isFullscreen, setIsFullscreen] = useState(false)
|
29 |
|
30 |
+
const getFullscreenElement = useCallback((): Element | null => {
|
31 |
+
if (typeof document === 'undefined') return null
|
32 |
+
const fullscreenProp = getBrowserFullscreenElementProp()
|
33 |
+
return document[fullscreenProp] || null
|
|
|
|
|
34 |
}, [])
|
35 |
|
36 |
const updateFullscreenStatus = useCallback(() => {
|
37 |
+
const fullscreenElement = getFullscreenElement()
|
38 |
+
setIsFullscreen(
|
39 |
+
!!elRef.current &&
|
40 |
+
!!fullscreenElement &&
|
41 |
+
fullscreenElement === elRef.current
|
42 |
+
)
|
43 |
+
}, [getFullscreenElement])
|
44 |
|
45 |
const setFullscreen = useCallback(
|
46 |
+
async (requestedValue?: boolean) => {
|
47 |
if (!elRef.current) return
|
48 |
|
49 |
+
const isCurrentlyFullscreen = getFullscreenElement() === elRef.current
|
50 |
+
const shouldBeFullScreen = requestedValue ?? !isCurrentlyFullscreen
|
|
|
51 |
|
52 |
+
if (isCurrentlyFullscreen === shouldBeFullScreen) return
|
|
|
|
|
53 |
|
54 |
+
try {
|
55 |
+
if (shouldBeFullScreen) {
|
56 |
+
await elRef.current.requestFullscreen()
|
57 |
+
} else if (document.fullscreenElement) {
|
58 |
+
await document.exitFullscreen()
|
59 |
+
}
|
60 |
+
} catch (error) {
|
61 |
+
console.error('Fullscreen error:', error)
|
62 |
+
}
|
63 |
|
64 |
+
// Wait for the next frame before updating status
|
65 |
+
requestAnimationFrame(updateFullscreenStatus)
|
66 |
},
|
67 |
+
[getFullscreenElement, updateFullscreenStatus]
|
68 |
)
|
69 |
|
70 |
+
useEffect(() => {
|
|
|
|
|
71 |
const fullscreenChangeHandler = () => {
|
72 |
+
requestAnimationFrame(updateFullscreenStatus)
|
73 |
}
|
74 |
|
75 |
if (typeof document !== 'undefined') {
|
76 |
document.addEventListener('fullscreenchange', fullscreenChangeHandler)
|
77 |
|
78 |
+
// Initial status update
|
79 |
+
updateFullscreenStatus()
|
80 |
|
81 |
return () => {
|
82 |
document.removeEventListener(
|
83 |
'fullscreenchange',
|
84 |
fullscreenChangeHandler
|
85 |
)
|
|
|
86 |
}
|
87 |
}
|
88 |
}, [updateFullscreenStatus])
|
|
|
91 |
}
|
92 |
|
93 |
function getBrowserFullscreenElementProp(): keyof FullscreenElement {
|
94 |
+
if (typeof document === 'undefined') return 'fullscreenElement'
|
95 |
+
|
96 |
+
const props: (keyof FullscreenElement)[] = [
|
97 |
+
'fullscreenElement',
|
98 |
+
'mozFullScreenElement',
|
99 |
+
'msFullscreenElement',
|
100 |
+
'webkitFullscreenElement',
|
101 |
+
]
|
102 |
+
|
103 |
+
for (const prop of props) {
|
104 |
+
if (prop in document) {
|
105 |
+
return prop
|
106 |
+
}
|
107 |
}
|
108 |
+
|
109 |
+
return 'fullscreenElement'
|
110 |
}
|
src/services/windows/useWindows.ts
CHANGED
@@ -3,13 +3,12 @@ import { create } from 'zustand'
|
|
3 |
import { WindowsStore, WindowState } from './types'
|
4 |
import { useCallback } from 'react'
|
5 |
|
6 |
-
// Create the Zustand store
|
7 |
export const useWindows = create<WindowsStore>((set, get) => ({
|
8 |
windows: {},
|
9 |
getNextPosition: (width: number, height: number) => {
|
10 |
const state = get()
|
11 |
const existingWindows = Object.values(state.windows)
|
12 |
-
const defaultOffset =
|
13 |
let newX = 0
|
14 |
let newY = 0
|
15 |
let maxIterations = 100 // Prevent infinite loop
|
@@ -73,7 +72,9 @@ export const useWindows = create<WindowsStore>((set, get) => ({
|
|
73 |
set((state) => ({
|
74 |
windows: {
|
75 |
...state.windows,
|
76 |
-
[id]:
|
|
|
|
|
77 |
},
|
78 |
})),
|
79 |
removeWindow: (id) =>
|
|
|
3 |
import { WindowsStore, WindowState } from './types'
|
4 |
import { useCallback } from 'react'
|
5 |
|
|
|
6 |
export const useWindows = create<WindowsStore>((set, get) => ({
|
7 |
windows: {},
|
8 |
getNextPosition: (width: number, height: number) => {
|
9 |
const state = get()
|
10 |
const existingWindows = Object.values(state.windows)
|
11 |
+
const defaultOffset = 100 // Offset for cascading windows
|
12 |
let newX = 0
|
13 |
let newY = 0
|
14 |
let maxIterations = 100 // Prevent infinite loop
|
|
|
72 |
set((state) => ({
|
73 |
windows: {
|
74 |
...state.windows,
|
75 |
+
[id]: state.windows[id]
|
76 |
+
? { ...state.windows[id], ...updates }
|
77 |
+
: state.windows[id],
|
78 |
},
|
79 |
})),
|
80 |
removeWindow: (id) =>
|