dx4 v2
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
@@ -0,0 +1,75 @@
|
||||
# React + TypeScript + Vite
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
|
||||
Currently, two official plugins are available:
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||
|
||||
## React Compiler
|
||||
|
||||
The React Compiler is enabled on this template. See [this documentation](https://react.dev/learn/react-compiler) for more information.
|
||||
|
||||
Note: This will impact Vite dev & build performances.
|
||||
|
||||
## Expanding the ESLint configuration
|
||||
|
||||
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
|
||||
|
||||
```js
|
||||
export default defineConfig([
|
||||
globalIgnores(['dist']),
|
||||
{
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
extends: [
|
||||
// Other configs...
|
||||
|
||||
// Remove tseslint.configs.recommended and replace with this
|
||||
tseslint.configs.recommendedTypeChecked,
|
||||
// Alternatively, use this for stricter rules
|
||||
tseslint.configs.strictTypeChecked,
|
||||
// Optionally, add this for stylistic rules
|
||||
tseslint.configs.stylisticTypeChecked,
|
||||
|
||||
// Other configs...
|
||||
],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
// other options...
|
||||
},
|
||||
},
|
||||
])
|
||||
```
|
||||
|
||||
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
|
||||
|
||||
```js
|
||||
// eslint.config.js
|
||||
import reactX from 'eslint-plugin-react-x'
|
||||
import reactDom from 'eslint-plugin-react-dom'
|
||||
|
||||
export default defineConfig([
|
||||
globalIgnores(['dist']),
|
||||
{
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
extends: [
|
||||
// Other configs...
|
||||
// Enable lint rules for React
|
||||
reactX.configs['recommended-typescript'],
|
||||
// Enable lint rules for React DOM
|
||||
reactDom.configs.recommended,
|
||||
],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
// other options...
|
||||
},
|
||||
},
|
||||
])
|
||||
```
|
||||
@@ -0,0 +1,569 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "dx4dashboard",
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"jotai": "^2.16.1",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"tailwindcss": "^4.1.18",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.1",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/react": "^19.2.5",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.1",
|
||||
"babel-plugin-react-compiler": "^1.0.0",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.24",
|
||||
"globals": "^16.5.0",
|
||||
"typescript": "~5.9.3",
|
||||
"typescript-eslint": "^8.46.4",
|
||||
"vite": "^7.2.4",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
|
||||
|
||||
"@babel/compat-data": ["@babel/compat-data@7.28.5", "", {}, "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA=="],
|
||||
|
||||
"@babel/core": ["@babel/core@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw=="],
|
||||
|
||||
"@babel/generator": ["@babel/generator@7.28.5", "", { "dependencies": { "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ=="],
|
||||
|
||||
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="],
|
||||
|
||||
"@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
|
||||
|
||||
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
|
||||
|
||||
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.28.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="],
|
||||
|
||||
"@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="],
|
||||
|
||||
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
|
||||
|
||||
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
|
||||
|
||||
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
|
||||
|
||||
"@babel/helpers": ["@babel/helpers@7.28.4", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.4" } }, "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w=="],
|
||||
|
||||
"@babel/parser": ["@babel/parser@7.28.5", "", { "dependencies": { "@babel/types": "^7.28.5" }, "bin": "./bin/babel-parser.js" }, "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ=="],
|
||||
|
||||
"@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="],
|
||||
|
||||
"@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="],
|
||||
|
||||
"@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
|
||||
|
||||
"@babel/traverse": ["@babel/traverse@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/types": "^7.28.5", "debug": "^4.3.1" } }, "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ=="],
|
||||
|
||||
"@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="],
|
||||
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.2", "", { "os": "android", "cpu": "arm64" }, "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA=="],
|
||||
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.27.2", "", { "os": "android", "cpu": "x64" }, "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A=="],
|
||||
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg=="],
|
||||
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA=="],
|
||||
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g=="],
|
||||
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA=="],
|
||||
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw=="],
|
||||
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw=="],
|
||||
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w=="],
|
||||
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg=="],
|
||||
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw=="],
|
||||
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ=="],
|
||||
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA=="],
|
||||
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w=="],
|
||||
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA=="],
|
||||
|
||||
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw=="],
|
||||
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.2", "", { "os": "none", "cpu": "x64" }, "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA=="],
|
||||
|
||||
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA=="],
|
||||
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg=="],
|
||||
|
||||
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag=="],
|
||||
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg=="],
|
||||
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg=="],
|
||||
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="],
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="],
|
||||
|
||||
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
|
||||
|
||||
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
|
||||
|
||||
"@eslint/config-array": ["@eslint/config-array@0.21.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA=="],
|
||||
|
||||
"@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="],
|
||||
|
||||
"@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="],
|
||||
|
||||
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.3", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ=="],
|
||||
|
||||
"@eslint/js": ["@eslint/js@9.39.2", "", {}, "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA=="],
|
||||
|
||||
"@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="],
|
||||
|
||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="],
|
||||
|
||||
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
||||
|
||||
"@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="],
|
||||
|
||||
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
|
||||
|
||||
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
||||
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||
|
||||
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
|
||||
|
||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
||||
|
||||
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.53", "", {}, "sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ=="],
|
||||
|
||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.55.1", "", { "os": "android", "cpu": "arm" }, "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg=="],
|
||||
|
||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.55.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg=="],
|
||||
|
||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.55.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg=="],
|
||||
|
||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.55.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ=="],
|
||||
|
||||
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.55.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg=="],
|
||||
|
||||
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.55.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.55.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.55.1", "", { "os": "linux", "cpu": "arm" }, "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.55.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.55.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA=="],
|
||||
|
||||
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.55.1", "", { "os": "linux", "cpu": "none" }, "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g=="],
|
||||
|
||||
"@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.55.1", "", { "os": "linux", "cpu": "none" }, "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw=="],
|
||||
|
||||
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.55.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw=="],
|
||||
|
||||
"@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.55.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw=="],
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.55.1", "", { "os": "linux", "cpu": "none" }, "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw=="],
|
||||
|
||||
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.55.1", "", { "os": "linux", "cpu": "none" }, "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg=="],
|
||||
|
||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.55.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.55.1", "", { "os": "linux", "cpu": "x64" }, "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.55.1", "", { "os": "linux", "cpu": "x64" }, "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w=="],
|
||||
|
||||
"@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.55.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg=="],
|
||||
|
||||
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.55.1", "", { "os": "none", "cpu": "arm64" }, "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw=="],
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.55.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g=="],
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.55.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA=="],
|
||||
|
||||
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.55.1", "", { "os": "win32", "cpu": "x64" }, "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg=="],
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.55.1", "", { "os": "win32", "cpu": "x64" }, "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw=="],
|
||||
|
||||
"@tailwindcss/node": ["@tailwindcss/node@4.1.18", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.1.18" } }, "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ=="],
|
||||
|
||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.18", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.18", "@tailwindcss/oxide-darwin-arm64": "4.1.18", "@tailwindcss/oxide-darwin-x64": "4.1.18", "@tailwindcss/oxide-freebsd-x64": "4.1.18", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", "@tailwindcss/oxide-linux-x64-musl": "4.1.18", "@tailwindcss/oxide-wasm32-wasi": "4.1.18", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" } }, "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A=="],
|
||||
|
||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.18", "", { "os": "android", "cpu": "arm64" }, "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q=="],
|
||||
|
||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.18", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A=="],
|
||||
|
||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.18", "", { "os": "darwin", "cpu": "x64" }, "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw=="],
|
||||
|
||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.18", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18", "", { "os": "linux", "cpu": "arm" }, "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.18", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.0", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA=="],
|
||||
|
||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.18", "", { "os": "win32", "cpu": "arm64" }, "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA=="],
|
||||
|
||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.18", "", { "os": "win32", "cpu": "x64" }, "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q=="],
|
||||
|
||||
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.18", "", { "dependencies": { "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA=="],
|
||||
|
||||
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
|
||||
|
||||
"@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
|
||||
|
||||
"@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
|
||||
|
||||
"@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
|
||||
|
||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||
|
||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||
|
||||
"@types/node": ["@types/node@24.10.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg=="],
|
||||
|
||||
"@types/react": ["@types/react@19.2.7", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg=="],
|
||||
|
||||
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.52.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.52.0", "@typescript-eslint/type-utils": "8.52.0", "@typescript-eslint/utils": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.52.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q=="],
|
||||
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.52.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.52.0", "@typescript-eslint/types": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg=="],
|
||||
|
||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.52.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.52.0", "@typescript-eslint/types": "^8.52.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw=="],
|
||||
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0" } }, "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA=="],
|
||||
|
||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.52.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg=="],
|
||||
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0", "@typescript-eslint/utils": "8.52.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ=="],
|
||||
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.52.0", "", {}, "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.52.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.52.0", "@typescript-eslint/tsconfig-utils": "8.52.0", "@typescript-eslint/types": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ=="],
|
||||
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.52.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.52.0", "@typescript-eslint/types": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ=="],
|
||||
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ=="],
|
||||
|
||||
"@vitejs/plugin-react": ["@vitejs/plugin-react@5.1.2", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.53", "@types/babel__core": "^7.20.5", "react-refresh": "^0.18.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ=="],
|
||||
|
||||
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
||||
|
||||
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
|
||||
|
||||
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
||||
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||
|
||||
"babel-plugin-react-compiler": ["babel-plugin-react-compiler@1.0.0", "", { "dependencies": { "@babel/types": "^7.26.0" } }, "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw=="],
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.9.11", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ=="],
|
||||
|
||||
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
||||
|
||||
"browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="],
|
||||
|
||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001762", "", {}, "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw=="],
|
||||
|
||||
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||
|
||||
"convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
|
||||
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||
|
||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
||||
|
||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.267", "", {}, "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw=="],
|
||||
|
||||
"enhanced-resolve": ["enhanced-resolve@5.18.4", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q=="],
|
||||
|
||||
"esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="],
|
||||
|
||||
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
||||
|
||||
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||
|
||||
"eslint": ["eslint@9.39.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.39.2", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw=="],
|
||||
|
||||
"eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@7.0.1", "", { "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA=="],
|
||||
|
||||
"eslint-plugin-react-refresh": ["eslint-plugin-react-refresh@0.4.26", "", { "peerDependencies": { "eslint": ">=8.40" } }, "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ=="],
|
||||
|
||||
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
|
||||
|
||||
"eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
|
||||
|
||||
"espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
|
||||
|
||||
"esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
|
||||
|
||||
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
|
||||
|
||||
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
|
||||
|
||||
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
|
||||
|
||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||
|
||||
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
|
||||
|
||||
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
|
||||
|
||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
|
||||
|
||||
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
|
||||
|
||||
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
|
||||
|
||||
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
|
||||
|
||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||
|
||||
"gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
|
||||
|
||||
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
||||
|
||||
"globals": ["globals@16.5.0", "", {}, "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ=="],
|
||||
|
||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||
|
||||
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||
|
||||
"hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="],
|
||||
|
||||
"hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="],
|
||||
|
||||
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
||||
|
||||
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
||||
|
||||
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||
|
||||
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||
|
||||
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
|
||||
|
||||
"jotai": ["jotai@2.16.1", "", { "peerDependencies": { "@babel/core": ">=7.0.0", "@babel/template": ">=7.0.0", "@types/react": ">=17.0.0", "react": ">=17.0.0" }, "optionalPeers": ["@babel/core", "@babel/template", "@types/react", "react"] }, "sha512-vrHcAbo3P7Br37C8Bv6JshMtlKMPqqmx0DDREtTjT4nf3QChDrYdbH+4ik/9V0cXA57dK28RkJ5dctYvavcIlg=="],
|
||||
|
||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||
|
||||
"js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
|
||||
|
||||
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
|
||||
|
||||
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
|
||||
|
||||
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
||||
|
||||
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
|
||||
|
||||
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
|
||||
|
||||
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
|
||||
|
||||
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
|
||||
|
||||
"lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="],
|
||||
|
||||
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="],
|
||||
|
||||
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA=="],
|
||||
|
||||
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ=="],
|
||||
|
||||
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA=="],
|
||||
|
||||
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.2", "", { "os": "linux", "cpu": "arm" }, "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA=="],
|
||||
|
||||
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A=="],
|
||||
|
||||
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA=="],
|
||||
|
||||
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w=="],
|
||||
|
||||
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="],
|
||||
|
||||
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="],
|
||||
|
||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="],
|
||||
|
||||
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
||||
|
||||
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
||||
|
||||
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
||||
|
||||
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||
|
||||
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||
|
||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||
|
||||
"node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
|
||||
|
||||
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
|
||||
|
||||
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
|
||||
|
||||
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
|
||||
|
||||
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
|
||||
|
||||
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
|
||||
|
||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||
|
||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||
|
||||
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||
|
||||
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||
|
||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||
|
||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||
|
||||
"react": ["react@19.2.3", "", {}, "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA=="],
|
||||
|
||||
"react-dom": ["react-dom@19.2.3", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg=="],
|
||||
|
||||
"react-icons": ["react-icons@5.5.0", "", { "peerDependencies": { "react": "*" } }, "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw=="],
|
||||
|
||||
"react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="],
|
||||
|
||||
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||
|
||||
"rollup": ["rollup@4.55.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.55.1", "@rollup/rollup-android-arm64": "4.55.1", "@rollup/rollup-darwin-arm64": "4.55.1", "@rollup/rollup-darwin-x64": "4.55.1", "@rollup/rollup-freebsd-arm64": "4.55.1", "@rollup/rollup-freebsd-x64": "4.55.1", "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", "@rollup/rollup-linux-arm-musleabihf": "4.55.1", "@rollup/rollup-linux-arm64-gnu": "4.55.1", "@rollup/rollup-linux-arm64-musl": "4.55.1", "@rollup/rollup-linux-loong64-gnu": "4.55.1", "@rollup/rollup-linux-loong64-musl": "4.55.1", "@rollup/rollup-linux-ppc64-gnu": "4.55.1", "@rollup/rollup-linux-ppc64-musl": "4.55.1", "@rollup/rollup-linux-riscv64-gnu": "4.55.1", "@rollup/rollup-linux-riscv64-musl": "4.55.1", "@rollup/rollup-linux-s390x-gnu": "4.55.1", "@rollup/rollup-linux-x64-gnu": "4.55.1", "@rollup/rollup-linux-x64-musl": "4.55.1", "@rollup/rollup-openbsd-x64": "4.55.1", "@rollup/rollup-openharmony-arm64": "4.55.1", "@rollup/rollup-win32-arm64-msvc": "4.55.1", "@rollup/rollup-win32-ia32-msvc": "4.55.1", "@rollup/rollup-win32-x64-gnu": "4.55.1", "@rollup/rollup-win32-x64-msvc": "4.55.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A=="],
|
||||
|
||||
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
||||
|
||||
"semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||
|
||||
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
|
||||
|
||||
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||
|
||||
"tailwindcss": ["tailwindcss@4.1.18", "", {}, "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw=="],
|
||||
|
||||
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||
|
||||
"ts-api-utils": ["ts-api-utils@2.4.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA=="],
|
||||
|
||||
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
|
||||
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"typescript-eslint": ["typescript-eslint@8.52.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.52.0", "@typescript-eslint/parser": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0", "@typescript-eslint/utils": "8.52.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-atlQQJ2YkO4pfTVQmQ+wvYQwexPDOIgo+RaVcD7gHgzy/IQA+XTyuxNM9M9TVXvttkF7koBHmcwisKdOAf2EcA=="],
|
||||
|
||||
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
|
||||
|
||||
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
||||
|
||||
"vite": ["vite@7.3.0", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg=="],
|
||||
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
||||
|
||||
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
||||
|
||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||
|
||||
"zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="],
|
||||
|
||||
"zod-validation-error": ["zod-validation-error@4.0.2", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ=="],
|
||||
|
||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||
|
||||
"@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import js from "@eslint/js";
|
||||
import globals from "globals";
|
||||
import reactHooks from "eslint-plugin-react-hooks";
|
||||
import reactRefresh from "eslint-plugin-react-refresh";
|
||||
import tseslint from "typescript-eslint";
|
||||
import { defineConfig, globalIgnores } from "eslint/config";
|
||||
|
||||
export default defineConfig([
|
||||
globalIgnores(["dist"]),
|
||||
{
|
||||
files: ["**/*.{ts,tsx}"],
|
||||
extends: [
|
||||
js.configs.recommended,
|
||||
tseslint.configs.recommended,
|
||||
reactHooks.configs.flat.recommended,
|
||||
reactRefresh.configs.vite,
|
||||
],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2020,
|
||||
globals: globals.browser,
|
||||
},
|
||||
rules: {
|
||||
"no-unused-vars": ["warn", { varsIgnorePattern: "^[A-Z_]|^motion$" }],
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"warn",
|
||||
{ varsIgnorePattern: "^[A-Z_]|^motion$" },
|
||||
],
|
||||
"react-hooks/exhaustive-deps": ["off"],
|
||||
},
|
||||
},
|
||||
]);
|
||||
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>dx4dashboard</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "dx4dashboard",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"jotai": "^2.16.1",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"tailwindcss": "^4.1.18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.1",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/react": "^19.2.5",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.1",
|
||||
"babel-plugin-react-compiler": "^1.0.0",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.24",
|
||||
"globals": "^16.5.0",
|
||||
"typescript": "~5.9.3",
|
||||
"typescript-eslint": "^8.46.4",
|
||||
"vite": "^7.2.4"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,104 @@
|
||||
// CHANGE TO YOUR API DESTINATION
|
||||
export const API_BASE_URL = "http://localhost:8321/admin_api.php";
|
||||
// export const API_BASE_URL = "http://192.168.3.10:8321/admin_api.php";
|
||||
// export const API_BASE_URL = "http://x90620bx.beget.tech/dx4back/admin_api.php"
|
||||
|
||||
// TYPE: url/dx4/
|
||||
export const CLIENT_FRONTEND_URL = "http://localhost:5173/dx4/";
|
||||
// export const CLIENT_FRONTEND_URL = "http://x90620bx.beget.tech/dx4/";
|
||||
|
||||
import { atom, useAtom } from "jotai";
|
||||
import { atomWithStorage } from "jotai/utils";
|
||||
import { useEffect } from "react";
|
||||
import LoginPage from "./pages/LoginPage";
|
||||
import DashPage from "./pages/DashPage";
|
||||
import ClassProfilePage from "./pages/ClassProfile";
|
||||
const passAtom = atomWithStorage("DX4DASH_pass", "");
|
||||
|
||||
// KATAMAZ DENGI ROUTER 4 PRO MAX ULTIMATE (from dx4, yeah, oh now in typescript)
|
||||
// 💀💀
|
||||
// PROS - vrode raboatat,
|
||||
// too simple, lightweight, stupidly fast
|
||||
// (beacause you basicly download entire site, lol)
|
||||
// CONS - shit
|
||||
function firstPathSegment(path: string) {
|
||||
const m = path.match(/^\/?([^/]+)/);
|
||||
return m ? m[1] : "";
|
||||
}
|
||||
const secondPathSegment = (p: string) =>
|
||||
p.replace(/^\/?[^/]+/, "").replace(/^\/+/, "");
|
||||
|
||||
const routeAtom = atom("/");
|
||||
const basePageProps = {
|
||||
// atoms
|
||||
passAtom,
|
||||
routeAtom,
|
||||
|
||||
// fucntions
|
||||
setsetRoute,
|
||||
secondPathSegment,
|
||||
|
||||
// constants
|
||||
API_BASE_URL,
|
||||
};
|
||||
|
||||
const pages = {
|
||||
"/": <LoginPage {...basePageProps} />,
|
||||
"/dash": <DashPage {...basePageProps} />,
|
||||
"/class": <ClassProfilePage {...basePageProps} />,
|
||||
};
|
||||
|
||||
let changeAnchor = true;
|
||||
const defaultAnchor = document.location.hash.substring(1);
|
||||
|
||||
// lol 💀
|
||||
function setsetRoute(setRoute: (s: string) => void, path: string) {
|
||||
changeAnchor = true;
|
||||
setRoute(path);
|
||||
document.location.hash = path;
|
||||
}
|
||||
|
||||
export default function DX4() {
|
||||
const [route, _setRoute] = useAtom(routeAtom);
|
||||
useEffect(() => {
|
||||
if (
|
||||
document.location.hash &&
|
||||
document.location.hash.substring(1) !== route
|
||||
) {
|
||||
_setRoute(document.location.hash.substring(1));
|
||||
}
|
||||
window.addEventListener("load", () => {
|
||||
if (defaultAnchor == "" || defaultAnchor == "/") {
|
||||
document.location.hash = defaultAnchor;
|
||||
}
|
||||
});
|
||||
}, [route, _setRoute]);
|
||||
window.addEventListener("hashchange", () => {
|
||||
if (document.location.hash == "") {
|
||||
document.location.hash = "/";
|
||||
}
|
||||
if (changeAnchor) {
|
||||
changeAnchor = false;
|
||||
return;
|
||||
}
|
||||
_setRoute(document.location.hash.substring(1));
|
||||
});
|
||||
const page = Object.entries(pages).find(
|
||||
([key]) => firstPathSegment(key) == firstPathSegment(route)
|
||||
);
|
||||
return (
|
||||
(page ? page[1] : false) || <ERROR404 /> || <div>some shit happened</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ERROR404() {
|
||||
const route = useAtom(routeAtom)[0];
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen flex-col gap-10">
|
||||
<div className="text-6xl font-black bg-linear-to-r from-red-400 to-pink-300 bg-clip-text text-transparent">
|
||||
404((((
|
||||
</div>
|
||||
<div>{route}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_2026_10)">
|
||||
<g filter="url(#filter0_d_2026_10)">
|
||||
<mask id="mask0_2026_10" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="89" y="110" width="325" height="281">
|
||||
<path d="M229.595 373.25L321.333 295.083L229.595 214.853V373.25Z" fill="white"/>
|
||||
<path d="M321.333 295.083L229.595 373.25M321.333 295.083L229.595 214.853M321.333 295.083L402.292 214.853M321.333 295.083L402.292 378.833M229.595 373.25V214.853M229.595 373.25H104.393C101.851 373.25 100.461 370.288 102.085 368.333L229.595 214.853M229.595 214.853V122" stroke="white" stroke-width="23" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_2026_10)">
|
||||
<rect width="350" height="287" transform="matrix(1 0 0 -1 76 395)" fill="url(#paint0_linear_2026_10)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_2026_10" x="34.365" y="55" width="434.927" height="390.833" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="27.75"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.34 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2026_10"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2026_10" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_2026_10" x1="-73.3091" y1="366.596" x2="487.371" y2="-46.6548" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="0.528846" stop-color="#a19597ff"/>
|
||||
<stop offset="1" stop-color="#6b2c3cff"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_2026_10">
|
||||
<rect width="500" height="500" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1,31 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
:root {
|
||||
font-family: "Jost","Segoe UI", sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: dark;
|
||||
color: #ffffffde;
|
||||
background-color: #141414;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* ensure selectable elements still selectable */
|
||||
.selectable,
|
||||
.selectable::after,
|
||||
.selectable::before,
|
||||
.selectable *,
|
||||
.selectable *::before,
|
||||
.selectable *::after,
|
||||
input {
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.bg-grain {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3Cfilter id='noise' x='0' y='0'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.8 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.45'/%3E%3C/svg%3E");
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import './index.css'
|
||||
import App from './App.tsx'
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
)
|
||||
@@ -0,0 +1,556 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { useAtom } from "jotai";
|
||||
import type { ssroutetype } from "../types";
|
||||
import { CoolBg, CopyClassLink, Header } from "./DashPage";
|
||||
import {
|
||||
AvailableAdminSymbols,
|
||||
copyDXLink,
|
||||
randomString,
|
||||
secondPathSegment,
|
||||
} from "../stilltrash/trash";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
DengiButton,
|
||||
DengiEditable,
|
||||
DengiYesOrNoDialog,
|
||||
LoadingSpinner,
|
||||
TextPreloader,
|
||||
} from "../stilltrash/dengi_components";
|
||||
import {
|
||||
AdminCreateReq,
|
||||
AdminRemoveReq,
|
||||
AdminUpdateReq,
|
||||
ClassReq,
|
||||
ClassUpdateNameReq,
|
||||
DELETEClassRequest,
|
||||
} from "../stilltrash/req_mgr";
|
||||
import {
|
||||
BiCheckCircle,
|
||||
BiLink,
|
||||
BiPlus,
|
||||
BiPlusCircle,
|
||||
BiTrash,
|
||||
BiX,
|
||||
} from "react-icons/bi";
|
||||
|
||||
export default function ClassProfilePage({
|
||||
passAtom,
|
||||
routeAtom,
|
||||
setsetRoute,
|
||||
}: {
|
||||
passAtom: any;
|
||||
routeAtom: any;
|
||||
setsetRoute: ssroutetype;
|
||||
}) {
|
||||
const [route, setRoute] = useAtom(routeAtom);
|
||||
const [pass, _setPass] = useAtom(passAtom);
|
||||
const classId = secondPathSegment(route as string);
|
||||
if (classId == "") setRoute("/dash/");
|
||||
return (
|
||||
<>
|
||||
<div className="w-full h-screen flex flex-col items-center justify-center gap-5 overflow-x-hidden z-2">
|
||||
<div className="w-screen h-screen flex flex-col sm:max-w-125 sm:max-h-[90vh] gap-3">
|
||||
<Header {...{ setsetRoute, setRoute }} back />
|
||||
<div className="bg-grain bg-zinc-800/50 p-5 items-center rounded-2xl not-md:w-[90%] flex flex-col gap-3">
|
||||
<ClassProfileEditor
|
||||
{...{ classId }}
|
||||
pass={pass as string}
|
||||
setRoute={(r) => setsetRoute(setRoute, r)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<CoolBg />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ClassProfileEditor({
|
||||
pass,
|
||||
classId,
|
||||
setRoute,
|
||||
}: {
|
||||
pass: string;
|
||||
classId: string;
|
||||
setRoute: (r: string) => void;
|
||||
}) {
|
||||
const [classData, setClassData] = useState<Record<string, string> | false>(
|
||||
false
|
||||
);
|
||||
const [adminsData, setAdminsData] = useState<
|
||||
Record<string, string>[] | false
|
||||
>(false);
|
||||
const [dataI, setDataI] = useState(0);
|
||||
useEffect(() => {
|
||||
ClassReq(pass, classId).then((i) => {
|
||||
if (i[0]) {
|
||||
setClassData(i[1]["class"]);
|
||||
setAdminsData(i[1]["admins"]);
|
||||
}
|
||||
});
|
||||
}, [classId, dataI]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1 className="flex gap-3 text-2xl items-center">
|
||||
управление классом <b>{classId}</b>{" "}
|
||||
{classData ? <b>({classData.userclassname})</b> : <TextPreloader />}
|
||||
</h1>
|
||||
<table className="max-w-80">
|
||||
<tbody className="*:*:min-w-20 *:*:h-10">
|
||||
<tr>
|
||||
<td className="">classId</td>
|
||||
<td className="font-mono text-center select-all selectable">
|
||||
{classId}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="">название</td>
|
||||
<td className="w-40">
|
||||
<DengiEditable
|
||||
value={classData ? classData.userclassname : false}
|
||||
onSubmit={async (v, idle) => {
|
||||
idle(true);
|
||||
const r = await ClassUpdateNameReq(
|
||||
pass,
|
||||
classId,
|
||||
v as string
|
||||
);
|
||||
if (r[1] === true) {
|
||||
setClassData((prev) => ({
|
||||
...prev,
|
||||
userclassname: v as string,
|
||||
}));
|
||||
}
|
||||
idle(false);
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="w-50 mt-5 flex gap-2 items-center justify-center">
|
||||
<CopyClassLink {...{ classId }} />
|
||||
{classData && (
|
||||
<RemoveClassButton
|
||||
{...{ classId, pass, setRoute, className: classData.userclassname }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<span className="h-px w-[80%] bg-zinc-700 block my-5 "></span>
|
||||
<span className="text-xl font-bold block">админы</span>
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr className="*:px-2">
|
||||
<th>имя</th>
|
||||
<th>id</th>
|
||||
<th>уров.</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{adminsData &&
|
||||
adminsData.map((i) => (
|
||||
<AdminProfileRow
|
||||
key={i.adminId}
|
||||
{...{
|
||||
adminId: i.adminId,
|
||||
pass: pass as string,
|
||||
adminName: i.adminName,
|
||||
adminLevel: i.adminPrems.toString(),
|
||||
classId,
|
||||
update: () => {
|
||||
setDataI(dataI + 1);
|
||||
},
|
||||
setAdminFrId: (v: string) => {
|
||||
setAdminsData(
|
||||
(prev) =>
|
||||
prev &&
|
||||
prev.map((a: any) =>
|
||||
a.adminId === i.adminId ? { ...a, adminName: v } : a
|
||||
)
|
||||
);
|
||||
},
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
{!adminsData && (
|
||||
<tr>
|
||||
<td>
|
||||
<span className="flex w-full justify-center">
|
||||
<TextPreloader />
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span className="flex w-full justify-center">
|
||||
<TextPreloader />
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span className="flex w-full justify-center">
|
||||
<TextPreloader />
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<LoadingSpinner size={20} />
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
{adminsData && (
|
||||
<CreateAdmin
|
||||
{...{
|
||||
update: () => {
|
||||
setDataI(dataI + 1);
|
||||
},
|
||||
classId,
|
||||
pass,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function AdminProfileRow({
|
||||
adminId,
|
||||
pass,
|
||||
adminName,
|
||||
classId,
|
||||
setAdminFrId,
|
||||
adminLevel,
|
||||
update,
|
||||
}: {
|
||||
adminId: string;
|
||||
pass: string;
|
||||
adminName: string;
|
||||
classId: string;
|
||||
setAdminFrId: (v: string) => void;
|
||||
adminLevel: string;
|
||||
update: () => void;
|
||||
}) {
|
||||
return (
|
||||
<tr className="h-12">
|
||||
<td className="px-2">
|
||||
<DengiEditable
|
||||
value={adminName}
|
||||
onSubmit={async (v, i) => {
|
||||
i(true);
|
||||
const r = await AdminUpdateReq(pass, adminId, "name", v as string);
|
||||
if (r[1] === true) {
|
||||
setAdminFrId(v as string);
|
||||
}
|
||||
i(false);
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
<td className="px-2">
|
||||
<DengiEditable value={adminId} password={true} disabled />
|
||||
</td>
|
||||
<td className="text-center">
|
||||
<AdminLevelPicker
|
||||
{...{
|
||||
value: adminLevel,
|
||||
pass,
|
||||
adminId,
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
<td className="inline-flex gap-1 items-center justify-center">
|
||||
<CopyAdminLink {...{ classId, adminId }} />
|
||||
<RemoveAdminButton {...{ adminId, pass, adminName, update }} />
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
const AdminLevelPicker = ({
|
||||
adminId,
|
||||
pass,
|
||||
value,
|
||||
}: {
|
||||
adminId: string;
|
||||
pass: string;
|
||||
value: string;
|
||||
}) => {
|
||||
const [val, setVal] = useState(value);
|
||||
const [idle, setIdle] = useState(false);
|
||||
return (
|
||||
<form className="flex items-center justify-center">
|
||||
{!idle ? (
|
||||
<select
|
||||
className="bg-zinc-800 p-1.5 rounded-xl text-center"
|
||||
value={val}
|
||||
onChange={async (e) => {
|
||||
setIdle(true);
|
||||
const v = (e.target as HTMLSelectElement).value;
|
||||
const r = await AdminUpdateReq(pass, adminId, "level", v);
|
||||
if (r[1] === true) {
|
||||
setVal(v);
|
||||
}
|
||||
setIdle(false);
|
||||
}}
|
||||
>
|
||||
<option value="-1">-1</option>
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
</select>
|
||||
) : (
|
||||
<LoadingSpinner size={20} />
|
||||
)}
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
const RemoveAdminButton = ({
|
||||
adminId,
|
||||
pass,
|
||||
adminName,
|
||||
update,
|
||||
}: {
|
||||
adminId: string;
|
||||
pass: string;
|
||||
adminName: string;
|
||||
update: () => void;
|
||||
}) => {
|
||||
const [showDiag, setShowDiag] = useState(false);
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<DengiYesOrNoDialog
|
||||
show={showDiag}
|
||||
content={{
|
||||
//@ts-ignore
|
||||
message: (
|
||||
<p>
|
||||
вы точно хотите удалить админа <b>{adminName}</b>?
|
||||
</p>
|
||||
),
|
||||
yesBtn: "да",
|
||||
noBtn: "нет",
|
||||
yesIcon: <BiTrash />,
|
||||
noIcon: <BiX size={20} />,
|
||||
bgDissmis: true,
|
||||
yesBtnStyle: "bg-red-500! text-white! md:hover:bg-red-600!",
|
||||
}}
|
||||
onAnswer={async (answ: boolean) => {
|
||||
setShowDiag(false);
|
||||
if (answ) {
|
||||
setDeleting(true);
|
||||
const r = await AdminRemoveReq(pass, adminId);
|
||||
if (r[1] === true) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<DengiButton
|
||||
onClick={() => {
|
||||
if (deleting) return;
|
||||
setShowDiag(true);
|
||||
}}
|
||||
>
|
||||
{deleting ? <LoadingSpinner size={20} /> : <BiTrash />}
|
||||
</DengiButton>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const RemoveClassButton = ({
|
||||
pass,
|
||||
classId,
|
||||
setRoute,
|
||||
className,
|
||||
}: {
|
||||
pass: string;
|
||||
classId: string;
|
||||
setRoute: (r: string) => void;
|
||||
className: string;
|
||||
}) => {
|
||||
const [showDiag, setShowDiag] = useState(false);
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<DengiYesOrNoDialog
|
||||
show={showDiag}
|
||||
content={{
|
||||
//@ts-ignore
|
||||
message: (
|
||||
<p>
|
||||
вы точно хотите удалить класс{" "}
|
||||
<b>
|
||||
{classId} ({className})
|
||||
</b>
|
||||
?
|
||||
</p>
|
||||
),
|
||||
yesBtn: "да",
|
||||
noBtn: "нет",
|
||||
yesIcon: <BiTrash />,
|
||||
noIcon: <BiX size={20} />,
|
||||
bgDissmis: true,
|
||||
yesBtnStyle: "bg-red-500! text-white! md:hover:bg-red-600!",
|
||||
}}
|
||||
onAnswer={async (answ: boolean) => {
|
||||
setShowDiag(false);
|
||||
if (answ) {
|
||||
setDeleting(true);
|
||||
const r = await DELETEClassRequest(pass, classId);
|
||||
if (r[1] === true) {
|
||||
setRoute("/dash/class");
|
||||
}
|
||||
setDeleting(false);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<DengiButton
|
||||
onClick={() => {
|
||||
if (deleting) return;
|
||||
setShowDiag(true);
|
||||
}}
|
||||
>
|
||||
{deleting ? <LoadingSpinner size={20} /> : <BiTrash />}
|
||||
</DengiButton>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const CopyAdminLink = ({
|
||||
classId,
|
||||
adminId,
|
||||
}: {
|
||||
classId: string;
|
||||
adminId: string;
|
||||
}) => {
|
||||
const [linkCopied, setLinkCopied] = useState(false);
|
||||
const copy = () => {
|
||||
copyDXLink(classId, adminId).then((a) => {
|
||||
if (a) {
|
||||
setLinkCopied(true);
|
||||
setTimeout(() => {
|
||||
setLinkCopied(false);
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<DengiButton onClick={() => copy()}>
|
||||
{linkCopied ? <BiCheckCircle /> : <BiLink />}
|
||||
</DengiButton>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
function CreateAdmin({
|
||||
pass,
|
||||
classId,
|
||||
update,
|
||||
}: {
|
||||
pass: string;
|
||||
update: () => void;
|
||||
classId: string;
|
||||
}) {
|
||||
const [creating, setCreating] = useState(false);
|
||||
const [adminId, setAdminId] = useState("");
|
||||
const [adminName, setAdminName] = useState("");
|
||||
const [levelVal, setLevelVal] = useState("1");
|
||||
const [locked, setLocked] = useState(false);
|
||||
const form = useRef(null);
|
||||
return (
|
||||
<>
|
||||
<div className="flex w-full gap-1">
|
||||
<span className="w-full" />
|
||||
{creating && (
|
||||
<form
|
||||
className="flex gap-2 max-w-100"
|
||||
ref={form}
|
||||
onSubmit={async (e) => {
|
||||
e.preventDefault();
|
||||
if (locked || adminId.length < 5) return;
|
||||
setLocked(true);
|
||||
const c = await AdminCreateReq(
|
||||
pass,
|
||||
classId,
|
||||
adminId,
|
||||
adminName,
|
||||
levelVal
|
||||
);
|
||||
if (c[1] == true) {
|
||||
update();
|
||||
setCreating(false);
|
||||
}
|
||||
setLocked(false);
|
||||
}}
|
||||
>
|
||||
<input
|
||||
className="bg-zinc-900 rounded-2xl border border-zinc-500/50 px-2 max-w-35"
|
||||
placeholder="имя"
|
||||
required
|
||||
value={adminName}
|
||||
disabled={locked}
|
||||
maxLength={50}
|
||||
onInput={(e) =>
|
||||
setAdminName((e.target as HTMLInputElement).value.trimStart())
|
||||
}
|
||||
/>
|
||||
<input
|
||||
className="bg-zinc-900 rounded-2xl border border-zinc-500/50 px-2 max-w-35"
|
||||
placeholder="adminId"
|
||||
value={adminId}
|
||||
required
|
||||
disabled={locked}
|
||||
maxLength={20}
|
||||
minLength={5}
|
||||
min={5}
|
||||
onInput={(e) => {
|
||||
let val = (e.target as HTMLInputElement).value;
|
||||
let nval = "";
|
||||
val.split("").forEach((i) => {
|
||||
if (AvailableAdminSymbols.includes(i)) {
|
||||
nval = nval + i;
|
||||
}
|
||||
});
|
||||
(e.target as HTMLInputElement).value = nval;
|
||||
setAdminId(nval);
|
||||
}}
|
||||
/>
|
||||
<select
|
||||
className="bg-zinc-800 p-1.5 rounded-xl text-center"
|
||||
value={levelVal}
|
||||
required
|
||||
onChange={async (e) => {
|
||||
const v = (e.target as HTMLSelectElement).value;
|
||||
setLevelVal(v);
|
||||
}}
|
||||
>
|
||||
<option value="-1">-1</option>
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
</select>
|
||||
<button>
|
||||
<DengiButton>
|
||||
{locked ? <LoadingSpinner size={20} /> : <BiPlus />}
|
||||
</DengiButton>
|
||||
</button>
|
||||
</form>
|
||||
)}
|
||||
<DengiButton
|
||||
disabled={locked}
|
||||
onClick={() => {
|
||||
setCreating(!creating);
|
||||
setAdminName("");
|
||||
setAdminId(randomString(8, AvailableAdminSymbols));
|
||||
}}
|
||||
>
|
||||
<span className={`${creating ? "rotate-45" : ""} transition`}>
|
||||
<BiPlusCircle />
|
||||
</span>
|
||||
</DengiButton>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,548 @@
|
||||
import { useAtom } from "jotai";
|
||||
import {
|
||||
BiCheckCircle,
|
||||
BiEdit,
|
||||
BiExit,
|
||||
BiLeftArrow,
|
||||
BiLink,
|
||||
BiPlus,
|
||||
BiPlusCircle,
|
||||
} from "react-icons/bi";
|
||||
import Logo from "../assets/logo.svg";
|
||||
import type { ssroutetype } from "../types";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
AvailableSymbols,
|
||||
copyDXLink,
|
||||
randomString,
|
||||
secondPathSegment,
|
||||
} from "../stilltrash/trash";
|
||||
import { API_BASE_URL, CLIENT_FRONTEND_URL } from "../App";
|
||||
import {
|
||||
DengiButton,
|
||||
DengiEditable,
|
||||
Link,
|
||||
LoadingSpinner,
|
||||
Switch,
|
||||
TextPreloader,
|
||||
} from "../stilltrash/dengi_components";
|
||||
import {
|
||||
ClassesReq,
|
||||
CreateClassReq,
|
||||
ServerBlockReq,
|
||||
ServerMsgBlockReq,
|
||||
ServerReq,
|
||||
} from "../stilltrash/req_mgr";
|
||||
|
||||
export default function DashPage({
|
||||
passAtom,
|
||||
routeAtom,
|
||||
setsetRoute,
|
||||
}: {
|
||||
passAtom: any;
|
||||
routeAtom: any;
|
||||
setsetRoute: ssroutetype;
|
||||
}) {
|
||||
const [route, setRoute] = useAtom(routeAtom);
|
||||
const [pass, _setPass] = useAtom(passAtom);
|
||||
|
||||
const tabs: Record<string, string> = {
|
||||
class: "классы",
|
||||
admin: "админы",
|
||||
server: "сервер",
|
||||
};
|
||||
|
||||
let tab = secondPathSegment(route as string);
|
||||
if (!tab || tab == "") tab = Object.keys(tabs)[0];
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="w-full h-screen flex flex-col items-center justify-center gap-5 overflow-x-hidden z-2">
|
||||
<div className="w-screen h-screen flex items-center flex-col sm:max-w-125 sm:max-h-[90vh] gap-3">
|
||||
<Header {...{ setsetRoute, setRoute }} />
|
||||
<div className="bg-zinc-800/50 items-center justify-center rounded-2xl flex gap-2 w-full">
|
||||
{Object.keys(tabs).map((i, idx) => (
|
||||
<span
|
||||
className={
|
||||
"p-2 px-3 select-none hover:bg-zinc-200/50 rounded-2xl my-2 cursor-pointer border transition-colors " +
|
||||
(tab == i ? "border-zinc-100/50" : "border-transparent")
|
||||
}
|
||||
key={idx}
|
||||
onClick={() => setsetRoute(setRoute, "/dash/" + i)}
|
||||
>
|
||||
{tabs[i]}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
{/* {tab} */}
|
||||
<div className="bg-grain w-full bg-zinc-800/50 p-5 rounded-2xl not-md:w-[90%] flex flex-col gap-3">
|
||||
{(() => {
|
||||
switch (tab) {
|
||||
case "class":
|
||||
return (
|
||||
<ClassesMainEditor
|
||||
pass={pass as string}
|
||||
setRoute={(p: string) => setsetRoute(setRoute, p)}
|
||||
/>
|
||||
);
|
||||
case "admin":
|
||||
return <AdminsMainEditor pass={pass as string} />;
|
||||
case "server":
|
||||
return <ServerEditor pass={pass as string} />;
|
||||
}
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<CoolBg />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ClassesMainEditor({
|
||||
pass,
|
||||
setRoute,
|
||||
}: {
|
||||
pass: string;
|
||||
setRoute: (s: string) => void;
|
||||
}) {
|
||||
const [classesData, setClassesData] = useState<
|
||||
Record<string, string>[] | false
|
||||
>(false);
|
||||
const [updateId, setUpdateId] = useState(0);
|
||||
useEffect(() => {
|
||||
ClassesReq(pass).then((i) => {
|
||||
if (i[1]["ok"] == "da") {
|
||||
setClassesData(i[1]["data"]);
|
||||
}
|
||||
});
|
||||
}, [updateId]);
|
||||
return (
|
||||
<div className="flex flex-col w-full">
|
||||
{classesData ? (
|
||||
<>
|
||||
{classesData.map((i, idx) => (
|
||||
<div
|
||||
className="flex w-full items-center hover:bg-zinc-300/30 transition-colors rounded-xl py-3 px-2"
|
||||
key={idx}
|
||||
>
|
||||
<span className="w-full block text-center">{i.classid}</span>
|
||||
<span className="w-full block text-center">
|
||||
{i.userclassname}
|
||||
</span>
|
||||
<span className="flex gap-2">
|
||||
<CopyClassLink classId={i.classid} compact />
|
||||
<DengiButton onClick={() => setRoute("/class/" + i.classid)}>
|
||||
<BiEdit />
|
||||
</DengiButton>
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
<div className="mt-5">
|
||||
<CreateClass pass={pass} update={() => setUpdateId(updateId + 1)} />
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<LoadingSpinner size={20} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export const CopyClassLink = ({
|
||||
classId,
|
||||
compact = false,
|
||||
}: {
|
||||
classId: string;
|
||||
compact?: boolean;
|
||||
}) => {
|
||||
const [linkCopied, setLinkCopied] = useState(false);
|
||||
|
||||
return (
|
||||
<DengiButton
|
||||
onClick={() => {
|
||||
copyDXLink(classId).then((a) => {
|
||||
if (a) {
|
||||
setLinkCopied(true);
|
||||
setTimeout(() => {
|
||||
setLinkCopied(false);
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
{compact ? (
|
||||
<>{linkCopied ? <BiCheckCircle /> : <BiLink />}</>
|
||||
) : (
|
||||
<>
|
||||
<BiLink />
|
||||
<span>{linkCopied ? "скопировано" : "коп ссылку"}</span>
|
||||
</>
|
||||
)}
|
||||
</DengiButton>
|
||||
);
|
||||
};
|
||||
function AdminsMainEditor({ pass }: { pass: string }) {
|
||||
return (
|
||||
<div className="block">
|
||||
<img src="https://od.lk/s/MTBfMzQ0MTQ0Njg5Xw/admin1.webp" alt="" className="w-30 h-auto" draggable={false} onContextMenu={e=>e.preventDefault()} />
|
||||
{/* <img src="https://od.lk/s/MTBfMzQ0MTQ0NjkyXw/admin2.webp" alt="" className="w-30 h-auto" draggable={false} onContextMenu={e=>e.preventDefault()}/> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
function ServerEditor({ pass }: { pass: string }) {
|
||||
const [serverData, setServerData] = useState<Record<string, string> | false>(
|
||||
false
|
||||
);
|
||||
const [idle, setIdle] = useState(false);
|
||||
const [showL, setShowL] = useState(false);
|
||||
const [blockChecked, setBlockChecked] = useState(false);
|
||||
let update = 0;
|
||||
useEffect(() => {
|
||||
ServerReq(pass).then(async (i) => {
|
||||
if (i[0]) {
|
||||
setServerData(i[1]);
|
||||
setBlockChecked(!i[1]["STATUS"] as boolean);
|
||||
}
|
||||
});
|
||||
}, [update]);
|
||||
return (
|
||||
<>
|
||||
<h1 className="text-2xl py-5 block">настройки api сервера</h1>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th className="w-35">admin_api_path</th>
|
||||
<td>
|
||||
<Link className="underline" target="_blank">
|
||||
{API_BASE_URL}
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th className="w-35">client_api_path</th>
|
||||
<td>
|
||||
{serverData ? (
|
||||
<Link className="underline" target="_blank">
|
||||
{serverData["CLIENT_API"]}
|
||||
</Link>
|
||||
) : (
|
||||
<TextPreloader />
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th className="w-35">client_frontend</th>
|
||||
<td>
|
||||
<Link className="underline" target="_blank">
|
||||
{CLIENT_FRONTEND_URL}
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a
|
||||
href={API_BASE_URL + "?phpliteadmin"}
|
||||
target="_blank"
|
||||
className="flex p-2 w-50 items-center justify-center rounded hover:bg-zinc-700/50 transition-colors border border-zinc-500"
|
||||
>
|
||||
<img
|
||||
src="https://bitbucket.org/phpliteadmin/public/raw/3fa9fedad19dc407a1786f97ba2b18a3c7b803bc/icon/phpLiteAdmin_small.png"
|
||||
alt=""
|
||||
width={32}
|
||||
className="invert"
|
||||
/>
|
||||
open phpliteadmin
|
||||
</a>
|
||||
|
||||
<div className="flex flex-col gap-3 justify-center">
|
||||
<h4>блокировка api</h4>
|
||||
<div className="flex gap-2 items-center">
|
||||
{serverData && (
|
||||
<>
|
||||
<DengiEditable
|
||||
value={serverData ? serverData["BLOCKMSG"] : false}
|
||||
disabled={idle}
|
||||
placeholder="error block message"
|
||||
onSubmit={async (v, s) => {
|
||||
console.log(v);
|
||||
s(true);
|
||||
setIdle(true);
|
||||
const r = await ServerMsgBlockReq(pass, v as string);
|
||||
if (r[1] !== true) {
|
||||
alert(r[1]);
|
||||
} else {
|
||||
setServerData((prev) => ({
|
||||
...prev,
|
||||
BLOCKMSG: v as string,
|
||||
}));
|
||||
}
|
||||
s(false);
|
||||
setIdle(false);
|
||||
}}
|
||||
/>
|
||||
<Switch
|
||||
disabled={idle}
|
||||
checked={blockChecked}
|
||||
onChange={async (e) => {
|
||||
setBlockChecked(e);
|
||||
setIdle(true);
|
||||
setShowL(true);
|
||||
const r = await ServerBlockReq(pass, e);
|
||||
if (r[1] !== true) {
|
||||
alert(r[1]);
|
||||
setBlockChecked(!e);
|
||||
}
|
||||
setIdle(false);
|
||||
setShowL(false);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{(showL || !serverData) && <LoadingSpinner size={20} />}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function CreateClass({ pass, update }: { pass: string; update: () => void }) {
|
||||
const [creating, setCreating] = useState(false);
|
||||
const [classId, setClassId] = useState("");
|
||||
const [className, setClassName] = useState("");
|
||||
const [locked, setLocked] = useState(false);
|
||||
const form = useRef(null);
|
||||
return (
|
||||
<>
|
||||
<div className="flex w-full gap-1">
|
||||
<span className="w-full" />
|
||||
{creating && (
|
||||
<form
|
||||
className="flex gap-2 max-w-100"
|
||||
ref={form}
|
||||
onSubmit={async (e) => {
|
||||
e.preventDefault();
|
||||
if (locked || classId.length < 5) return;
|
||||
setLocked(true);
|
||||
const c = await CreateClassReq(pass, classId, className);
|
||||
if (c[1] == true) {
|
||||
update();
|
||||
setCreating(false);
|
||||
}
|
||||
setLocked(false);
|
||||
}}
|
||||
>
|
||||
<input
|
||||
className="bg-zinc-900 rounded-2xl border border-zinc-500/50 px-2 max-w-35"
|
||||
placeholder="название"
|
||||
required
|
||||
value={className}
|
||||
disabled={locked}
|
||||
maxLength={50}
|
||||
onInput={(e) =>
|
||||
setClassName((e.target as HTMLInputElement).value.trimStart())
|
||||
}
|
||||
/>
|
||||
<input
|
||||
className="bg-zinc-900 rounded-2xl border border-zinc-500/50 px-2 max-w-35"
|
||||
placeholder="classId"
|
||||
value={classId}
|
||||
required
|
||||
disabled={locked}
|
||||
maxLength={10}
|
||||
minLength={5}
|
||||
min={5}
|
||||
onInput={(e) => {
|
||||
let val = (e.target as HTMLInputElement).value.toUpperCase();
|
||||
let nval = "";
|
||||
val.split("").forEach((i) => {
|
||||
if (AvailableSymbols.includes(i)) {
|
||||
nval = nval + i;
|
||||
}
|
||||
});
|
||||
(e.target as HTMLInputElement).value = nval;
|
||||
setClassId(nval);
|
||||
}}
|
||||
/>
|
||||
<button>
|
||||
<DengiButton>
|
||||
{locked ? <LoadingSpinner size={20} /> : <BiPlus />}
|
||||
</DengiButton>
|
||||
</button>
|
||||
</form>
|
||||
)}
|
||||
<DengiButton
|
||||
disabled={locked}
|
||||
onClick={() => {
|
||||
setCreating(!creating);
|
||||
setClassName("");
|
||||
setClassId(randomString(8, AvailableSymbols).toUpperCase());
|
||||
}}
|
||||
>
|
||||
<span className={`${creating ? "rotate-45" : ""} transition`}>
|
||||
<BiPlusCircle />
|
||||
</span>
|
||||
</DengiButton>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// export function AdminProfileEditor({
|
||||
// adminFrId,
|
||||
// setAdminFrId,
|
||||
// adminId,
|
||||
// classId,
|
||||
// pickmeMode = false,
|
||||
// }) {
|
||||
// return (
|
||||
// <div className=" bg-grain bg-zinc-800/50 p-5 rounded-2xl not-md:w-[90%]">
|
||||
// <table className="">
|
||||
// <tbody className="*:*:w-10 *:*:h-10">
|
||||
// <tr>
|
||||
// <td className="">имя</td>
|
||||
// <td className="w-50!">
|
||||
// <DengiEditable
|
||||
// value={adminFrId}
|
||||
// pink={pickmeMode}
|
||||
// onSubmit={async (e) => {
|
||||
// e.setIdle(true);
|
||||
// const r = await AdminUpdateRequest(API_BASE_URL, adminId, {
|
||||
// action: "change_name",
|
||||
// value: e.value.trim(),
|
||||
// });
|
||||
// if (r[1] == true) setAdminFrId(e.value);
|
||||
// e.setIdle(false);
|
||||
// }}
|
||||
// />
|
||||
// </td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>id</td>
|
||||
// <td>
|
||||
// <DengiEditable
|
||||
// value={adminId}
|
||||
// password={true}
|
||||
// pink={pickmeMode}
|
||||
// disabled
|
||||
// />
|
||||
// </td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>class</td>
|
||||
// <td className="font-mono text-center select-all selectable">
|
||||
// {classId ? classId : <TextPreloader />}
|
||||
// </td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
// <CopyLink {...{ adminId, classId }} />
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
|
||||
// const CopyLink = ({ classId, adminId }) => {
|
||||
// const [showDiag, setShowDiag] = useState(false);
|
||||
// const [seenDiag, setSeenDiag] = useState(false);
|
||||
// const [linkCopied, setLinkCopied] = useState(false);
|
||||
// const copy = () => {
|
||||
// copyDXLink(classId, adminId).then((a) => {
|
||||
// if (a) {
|
||||
// setLinkCopied(true);
|
||||
// setTimeout(() => {
|
||||
// setLinkCopied(false);
|
||||
// }, 2000);
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
// return (
|
||||
// <div className="flex justify-end mt-2">
|
||||
// <DengiYesOrNoDialog
|
||||
// show={showDiag}
|
||||
// content={{
|
||||
// message: (
|
||||
// <p>
|
||||
// <b>любой</b>, кто получит ссылку,{" "}
|
||||
// <b>будет иметь доступ к админке</b>.<br /> вы желаете продолжить?
|
||||
// </p>
|
||||
// ),
|
||||
// yesBtn: "да",
|
||||
// noBtn: "нет",
|
||||
// yesIcon: <BiCopy />,
|
||||
// noIcon: <BiX size={20} />,
|
||||
// bgDissmis: true,
|
||||
// yesBtnStyle: "bg-orange-500! text-white! md:hover:bg-orange-600!",
|
||||
// }}
|
||||
// onAnswer={(answ) => {
|
||||
// if (answ) {
|
||||
// setSeenDiag(true);
|
||||
// copy();
|
||||
// }
|
||||
// setShowDiag(false);
|
||||
// }}
|
||||
// />
|
||||
// <DengiButton onClick={() => (seenDiag ? copy() : setShowDiag(true))}>
|
||||
// <BiLink /> <BiError color={"orange"} />
|
||||
// <span>{linkCopied ? "скопировано" : "коп ссылку на админку"}</span>
|
||||
// </DengiButton>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
export const CoolBg = ({}) => {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={`fixed top-0 left-0 w-full h-full -z-5 overflow-hidden bg-linear-to-tl to-black to-50% bg-fixed
|
||||
from-red-600/20`}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const Header = ({
|
||||
setsetRoute,
|
||||
setRoute,
|
||||
back = false,
|
||||
}: {
|
||||
setsetRoute: ssroutetype;
|
||||
setRoute: any;
|
||||
back?: boolean;
|
||||
}) => {
|
||||
return (
|
||||
<div className={"flex items-center w-full justify-between px-5"}>
|
||||
<span className="flex gap-2 items-center">
|
||||
{back && (
|
||||
<BiLeftArrow
|
||||
size={35}
|
||||
onClick={() => {
|
||||
setsetRoute(setRoute, "/dash/");
|
||||
}}
|
||||
className={
|
||||
"rounded-full " +
|
||||
"lg:hover:bg-white lg:hover:fill-black" +
|
||||
" lg:hover:scale-105 transition cursor-pointer"
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<img src={Logo} alt="logo" width={100} draggable={false} />
|
||||
</span>
|
||||
<BiExit
|
||||
size={35}
|
||||
onClick={() => {
|
||||
setsetRoute(setRoute, "/");
|
||||
}}
|
||||
onContextMenu={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
className={
|
||||
"rounded-full " +
|
||||
"lg:hover:bg-white lg:hover:fill-black" +
|
||||
" lg:hover:scale-105 transition cursor-pointer"
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,113 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { useRef, useState } from "react";
|
||||
import Logo from "../assets/logo.svg";
|
||||
|
||||
import { BiHide, BiShow } from "react-icons/bi";
|
||||
|
||||
import { LoginReq } from "../stilltrash/req_mgr";
|
||||
import { useAtom } from "jotai";
|
||||
import type { ssroutetype } from "../types";
|
||||
export default function LoginPage({
|
||||
passAtom,
|
||||
routeAtom,
|
||||
setsetRoute,
|
||||
}: {
|
||||
passAtom: any;
|
||||
routeAtom: any;
|
||||
setsetRoute: ssroutetype;
|
||||
}) {
|
||||
const [show, setShow] = useState(false);
|
||||
const [atomPass, setAtomPass] = useAtom(passAtom);
|
||||
const [_route, setRoute] = useAtom(routeAtom);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [pass, setPass] = useState("");
|
||||
return (
|
||||
<div className="bg-linear-to-br from-red-500 to-zinc-800 w-screen min-h-screen flex items-center justify-center">
|
||||
<div className="flex flex-col rounded-2xl w-[90vw] items-center justify-center py-3 max-w-150 focus-within:border-white/10 border border-transparent transition-colors relative bg-zinc-900/30 text-zinc-100">
|
||||
{atomPass != "" && (
|
||||
<div className="flex gap-3">
|
||||
<a
|
||||
href="#/dash"
|
||||
className="bg-linear-to-r from-neutral-900 to-zinc-900 p-2 rounded-xl not-disabled:cursor-pointer transition-colors duration-200 hover:from-white hover:to-zinc-400 not-disabled:hover:text-black"
|
||||
>
|
||||
go to dash
|
||||
</a>
|
||||
<button
|
||||
onClick={() => setAtomPass("")}
|
||||
className="bg-linear-to-l from-neutral-900 to-zinc-900 p-2 rounded-xl not-disabled:cursor-pointer transition-colors duration-200 hover:from-white hover:to-zinc-400 not-disabled:hover:text-black"
|
||||
>
|
||||
logoff
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<img src={Logo} alt="logo dengi" width={200} />
|
||||
<h1 className="text-zinc-200">dashboard</h1>
|
||||
<h2 className="text-3xl font-light">вход</h2>
|
||||
<form
|
||||
action="#"
|
||||
className="mt-2 flex flex-col gap-3 *:outline-none *:border *:border-transparent *:focus:border-white"
|
||||
onSubmit={async (e) => {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
const r = await LoginReq(pass);
|
||||
if (r[1]) {
|
||||
setAtomPass(pass);
|
||||
setsetRoute(setRoute, "/dash");
|
||||
}
|
||||
setLoading(false);
|
||||
}}
|
||||
>
|
||||
<span className="flex items-center">
|
||||
<input
|
||||
type={show ? "text" : "password"}
|
||||
autoComplete="off"
|
||||
className="bg-zinc-800/50 p-2 rounded-l-2xl w-full min-w-51.5"
|
||||
placeholder="password"
|
||||
minLength={3}
|
||||
maxLength={20}
|
||||
required
|
||||
value={pass}
|
||||
onInput={(e) => setPass((e.target as HTMLInputElement).value)}
|
||||
disabled={loading}
|
||||
/>
|
||||
<span
|
||||
className={"p-2 rounded-r-2xl border-l border-l-zinc-500 transition-colors" + (show ? " bg-white" : " bg-zinc-800/50")}
|
||||
onClick={() => {
|
||||
setShow(!show);
|
||||
}}
|
||||
>
|
||||
{!show ? (
|
||||
<BiShow color="#fff" size={23} />
|
||||
) : (
|
||||
<BiHide color="#000" size={23} />
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<CoolLoginButton disabled={loading} />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function CoolLoginButton({ disabled }: { disabled: boolean }) {
|
||||
const logbuttonRef = useRef(null);
|
||||
|
||||
return (
|
||||
<button
|
||||
ref={logbuttonRef}
|
||||
{...{ disabled }}
|
||||
onMouseMove={(e) => {
|
||||
const rect = (e.target as HTMLElement).getBoundingClientRect();
|
||||
(e.target as HTMLElement).style.setProperty(
|
||||
"--tw-gradient-via-position",
|
||||
`${((e.clientX - rect.left) / rect.width) * 100}%`
|
||||
);
|
||||
}}
|
||||
className="bg-linear-to-r from-neutral-900 to-zinc-900 p-2 rounded-xl not-disabled:cursor-pointer transition-colors duration-200 not-disabled:hover:via-white via-30% not-disabled:hover:text-black disabled:via-white disabled:via-0%! disabled:animate-pulse"
|
||||
>
|
||||
войти
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
import { useEffect, useState, type AnchorHTMLAttributes } from "react";
|
||||
import { BiCheck, BiHide, BiShow, BiX } from "react-icons/bi";
|
||||
|
||||
export function Link(props: AnchorHTMLAttributes<HTMLAnchorElement>) {
|
||||
let link = props.href;
|
||||
if (!link) {
|
||||
link = props.children as string;
|
||||
}
|
||||
return (
|
||||
<a {...props} href={link}>
|
||||
{link}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
export function Switch({
|
||||
checked,
|
||||
defaultChecked = false,
|
||||
onChange,
|
||||
disabled = false,
|
||||
ariaLabel,
|
||||
className = "",
|
||||
size = "md", // "sm" | "md" | "lg"
|
||||
}: {
|
||||
checked?: boolean;
|
||||
defaultChecked?: boolean;
|
||||
onChange?: (newState: boolean) => void;
|
||||
disabled?: boolean;
|
||||
ariaLabel?: string;
|
||||
className?: string;
|
||||
size?: "sm" | "md" | "lg";
|
||||
}) {
|
||||
const isControlled = checked !== undefined;
|
||||
const [internalChecked, setInternalChecked] = useState(defaultChecked);
|
||||
const current = isControlled ? checked : internalChecked;
|
||||
|
||||
useEffect(() => {
|
||||
if (!isControlled) return;
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
setInternalChecked(checked);
|
||||
}, [checked, isControlled]);
|
||||
|
||||
const sizes = {
|
||||
sm: { track: "w-9 h-5", thumb: "w-3 h-3", translate: "translate-x-4" },
|
||||
md: { track: "w-11 h-6", thumb: "w-4 h-4", translate: "translate-x-5" },
|
||||
lg: { track: "w-14 h-8", thumb: "w-6 h-6", translate: "translate-x-6" },
|
||||
};
|
||||
const s = sizes[size] || sizes.md;
|
||||
|
||||
const toggle = (next?: boolean) => {
|
||||
if (disabled) return;
|
||||
const newState = typeof next === "boolean" ? next : !current;
|
||||
if (!isControlled) setInternalChecked(newState);
|
||||
onChange?.(newState);
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
role="switch"
|
||||
aria-checked={current}
|
||||
aria-label={ariaLabel}
|
||||
disabled={disabled}
|
||||
tabIndex={disabled ? -1 : 0}
|
||||
onClick={() => toggle()}
|
||||
className={[
|
||||
"inline-flex items-center p-0 focus:outline-none",
|
||||
// focus-visible: shows ring only when focused by keyboard (better UX)
|
||||
"focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-offset-0.5 focus-visible:ring-offset-transparent",
|
||||
disabled ? "opacity-60" : "cursor-pointer",
|
||||
current ? "bg-zinc-500" : "bg-gray-300/10",
|
||||
"rounded-full transition-colors duration-150",
|
||||
s.track,
|
||||
className,
|
||||
].join(" ")}
|
||||
>
|
||||
<span
|
||||
className={[
|
||||
"relative block rounded-full bg-white shadow transform transition-transform ease-out duration-150",
|
||||
s.thumb,
|
||||
current ? s.translate : "",
|
||||
size === "sm" ? "m-1" : "m-1",
|
||||
].join(" ")}
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export function LoadingSpinner({ size }: { size: number }) {
|
||||
return (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="animate-spin ease-out text-zinc-600 fill-white"
|
||||
viewBox="0 0 100 101"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={size}
|
||||
height={size}
|
||||
>
|
||||
<path
|
||||
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
||||
fill="currentFill"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
export function DengiEditable({
|
||||
value,
|
||||
password = false,
|
||||
disWHidden = true,
|
||||
disabled = false,
|
||||
showLoading = true,
|
||||
minLenght = 1,
|
||||
placeholder,
|
||||
onSubmit = () => {},
|
||||
onInput = () => {},
|
||||
}: {
|
||||
value?: string | false;
|
||||
password?: boolean;
|
||||
disWHidden?: boolean;
|
||||
disabled?: boolean;
|
||||
placeholder?: string;
|
||||
showLoading?: boolean;
|
||||
minLenght?: number;
|
||||
onSubmit?: (
|
||||
value: string | false | undefined,
|
||||
setIdle: (v: boolean) => void
|
||||
) => void;
|
||||
onInput?: (
|
||||
value: string | false | undefined,
|
||||
setIdle: (v: boolean) => void
|
||||
) => void;
|
||||
}) {
|
||||
const [val, setVal] = useState(value);
|
||||
const [hid, setHid] = useState(true);
|
||||
const [idle, setIdle] = useState(false);
|
||||
useEffect(() => {
|
||||
setVal(value);
|
||||
}, [value]);
|
||||
return (
|
||||
<form
|
||||
action="#"
|
||||
className="flex rounded-xl overflow-hidden max-w-50 h-8 relative"
|
||||
onSubmit={(e) => {
|
||||
if (idle) return;
|
||||
e.preventDefault();
|
||||
onSubmit(val, setIdle);
|
||||
}}
|
||||
>
|
||||
{value !== false || !showLoading ? (
|
||||
<input
|
||||
type={hid && password ? "password" : "text"}
|
||||
value={val as any}
|
||||
placeholder={placeholder}
|
||||
minLength={minLenght}
|
||||
disabled={(disWHidden && password && hid) || disabled || idle}
|
||||
className={`bg-zinc-800 ${
|
||||
val === value && !password ? "rounded-r-xl" : ""
|
||||
} pl-2 rounded-l-xl w-full py-1 transition`}
|
||||
onInput={(e) => {
|
||||
const v = (e.target as HTMLInputElement).value;
|
||||
setVal(v);
|
||||
onInput(v, setIdle);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<span
|
||||
className={`w-full bg-zinc-800 py-1 flex items-center justify-center`}
|
||||
>
|
||||
<LoadingSpinner size={25} />
|
||||
</span>
|
||||
)}
|
||||
|
||||
{password && (
|
||||
<button
|
||||
className={`bg-zinc-600 hover:bg-zinc-700 cursor-pointer transition-colors ${
|
||||
val === value ? "rounded-r-xl" : ""
|
||||
} p-1 text-2xl `}
|
||||
onContextMenu={(e) => {
|
||||
e.preventDefault();
|
||||
if ((disWHidden && password && hid) || disabled || idle) return;
|
||||
setVal(value);
|
||||
}}
|
||||
onClick={() => {
|
||||
setHid(!hid);
|
||||
}}
|
||||
>
|
||||
{hid ? <BiShow /> : <BiHide />}
|
||||
</button>
|
||||
)}
|
||||
|
||||
{val !== value && (
|
||||
<button
|
||||
disabled={idle}
|
||||
className={`bg-zinc-600 disabled:bg-zinc-900 hover:bg-zinc-700
|
||||
p-1 text-2xl rounded-r-xl transition-colors not-disabled:cursor-pointer`}
|
||||
onContextMenu={(e) => {
|
||||
e.preventDefault();
|
||||
setVal(value);
|
||||
}}
|
||||
>
|
||||
{idle ? <LoadingSpinner size={24} /> : <BiCheck />}
|
||||
</button>
|
||||
)}
|
||||
</form>
|
||||
);
|
||||
}
|
||||
import trashcss from "./trash.module.css";
|
||||
export function TextPreloader({ width = "5rem" }) {
|
||||
return (
|
||||
<span
|
||||
className={"h-4 block bg-zinc-900 overflow-hidden rounded-full w-(--w)"}
|
||||
style={{ "--w": width } as Record<string, string>}
|
||||
>
|
||||
<span
|
||||
className={
|
||||
"block h-10 -translate-y-3 w-3 bg-zinc-300 relative blur-[7px] " +
|
||||
trashcss.anim_preloader
|
||||
}
|
||||
></span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export function DengiButton({
|
||||
onClick,
|
||||
children,
|
||||
disabled = false,
|
||||
className = "",
|
||||
}: {
|
||||
onClick?: () => void;
|
||||
children?: any;
|
||||
disabled?: boolean;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<span
|
||||
role="button"
|
||||
className={
|
||||
"flex bg-black items-center justify-center border p-1 gap-2 px-2 border-white " +
|
||||
(disabled
|
||||
? "cursor-not-allowed text-zinc-700 border-zinc-900 md:hover:border-red-950/50 "
|
||||
: "not-disabled:cursor-pointer md:not-hover:border-zinc-700 md:not-hover:text-zinc-400 text-white ") +
|
||||
"rounded-xl transition-colors h-10 min-w-10 not-md:p-2 " +
|
||||
(className ? className : "")
|
||||
}
|
||||
aria-disabled={disabled}
|
||||
onClick={disabled ? undefined : onClick}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
const defaultDialogContent = {
|
||||
message: "?",
|
||||
yesBtn: "da",
|
||||
noBtn: "net",
|
||||
bgDissmis: true,
|
||||
yesBlocked: false,
|
||||
yesIcon: <BiCheck />,
|
||||
noIcon: <BiX />,
|
||||
noBtnStyle: "",
|
||||
yesBtnStyle: "",
|
||||
};
|
||||
export function DengiYesOrNoDialog({
|
||||
content = defaultDialogContent,
|
||||
show = false,
|
||||
//@ts-ignore
|
||||
onAnswer,
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
{show && (
|
||||
<div
|
||||
className="fixed z-99 bg-black/50 backdrop-blur-xl top-0 left-0 w-full h-full overflow-hidden flex items-center justify-center"
|
||||
onClick={(e) => {
|
||||
if (e.target === e.currentTarget && content.bgDissmis)
|
||||
onAnswer(false);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="flex flex-col justify-center gap-4 p-4 border bg-black border-zinc-400 rounded-2xl"
|
||||
>
|
||||
<span>{content.message}</span>
|
||||
<div className="flex gap-2 justify-stretch">
|
||||
<DengiButton
|
||||
className={content.yesBtnStyle + " w-full"}
|
||||
onClick={() => onAnswer(true)}
|
||||
disabled={content.yesBlocked}
|
||||
>
|
||||
{content.yesIcon}
|
||||
{content.yesBtn}
|
||||
</DengiButton>
|
||||
<DengiButton
|
||||
className={content.noBtnStyle + " w-full"}
|
||||
onClick={() => onAnswer(false)}
|
||||
>
|
||||
{content.noIcon}
|
||||
{content.noBtn}
|
||||
</DengiButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
import { API_BASE_URL } from "../App";
|
||||
import { b64e } from "./trash";
|
||||
|
||||
export async function makeRequest(
|
||||
url: string,
|
||||
params?:
|
||||
| string
|
||||
| Record<string, string>
|
||||
| string[][]
|
||||
| URLSearchParams
|
||||
| undefined
|
||||
) {
|
||||
try {
|
||||
const req = await fetch(url, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
body: new URLSearchParams(params).toString(),
|
||||
});
|
||||
|
||||
return req.ok &&
|
||||
req.headers.get("Content-Type")?.includes("application/json")
|
||||
? [1, await req.json()]
|
||||
: [req.status, await req.text()];
|
||||
} catch (err) {
|
||||
return [-1, err];
|
||||
}
|
||||
}
|
||||
|
||||
export function LoginReq(pass: string) {
|
||||
return makeRequest(API_BASE_URL + "?login", { pass });
|
||||
}
|
||||
|
||||
export function ServerReq(pass: string) {
|
||||
return makeRequest(API_BASE_URL + "?server", { pass });
|
||||
}
|
||||
|
||||
export function ServerBlockReq(pass: string, block: boolean) {
|
||||
return makeRequest(API_BASE_URL + "?server", {
|
||||
pass,
|
||||
action: block ? "disable" : "enable",
|
||||
});
|
||||
}
|
||||
export function ServerMsgBlockReq(pass: string, value: string) {
|
||||
return makeRequest(API_BASE_URL + "?server", {
|
||||
pass,
|
||||
action: "update_block_message",
|
||||
value,
|
||||
});
|
||||
}
|
||||
|
||||
export function ClassesReq(pass: string) {
|
||||
return makeRequest(API_BASE_URL + "?class", { pass });
|
||||
}
|
||||
|
||||
export function ClassReq(pass: string, classId: string) {
|
||||
return makeRequest(API_BASE_URL + "?class", { pass, classId });
|
||||
}
|
||||
|
||||
export function ClassUpdateNameReq(
|
||||
pass: string,
|
||||
classId: string,
|
||||
value: string
|
||||
) {
|
||||
return makeRequest(API_BASE_URL + "?class", {
|
||||
pass,
|
||||
classId,
|
||||
action: "update_name",
|
||||
value,
|
||||
});
|
||||
}
|
||||
|
||||
export function CreateClassReq(
|
||||
pass: string,
|
||||
classId: string,
|
||||
className: string
|
||||
) {
|
||||
return makeRequest(API_BASE_URL + "?class", {
|
||||
pass,
|
||||
classId,
|
||||
action: "create",
|
||||
value: className,
|
||||
});
|
||||
}
|
||||
|
||||
export function DELETEClassRequest(pass: string, classId: string) {
|
||||
return makeRequest(API_BASE_URL + "?class", {
|
||||
pass,
|
||||
classId,
|
||||
action: "DELETE",
|
||||
});
|
||||
}
|
||||
|
||||
export function AdminUpdateReq(
|
||||
pass: string,
|
||||
adminId: string,
|
||||
action: "level" | "name",
|
||||
value: string
|
||||
) {
|
||||
return makeRequest(API_BASE_URL + "?admin", {
|
||||
pass,
|
||||
adminId,
|
||||
action: "update_" + action,
|
||||
value,
|
||||
});
|
||||
}
|
||||
|
||||
export function AdminRemoveReq(pass: string, adminId: string) {
|
||||
return makeRequest(API_BASE_URL + "?admin", {
|
||||
pass,
|
||||
adminId,
|
||||
action: "DELETE",
|
||||
});
|
||||
}
|
||||
|
||||
export function AdminCreateReq(
|
||||
pass: string,
|
||||
classId: string,
|
||||
adminId: string,
|
||||
adminName: string,
|
||||
adminPrems: string
|
||||
) {
|
||||
return makeRequest(API_BASE_URL + "?class", {
|
||||
pass,
|
||||
classId,
|
||||
action: "create_admin",
|
||||
value: `${adminId};${b64e(adminName)};${adminPrems}`,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
.anim_preloader {
|
||||
animation: anim-preloader 1s infinite linear;
|
||||
}
|
||||
@keyframes anim-preloader {
|
||||
from {
|
||||
transform: translateX(-50px) rotate(20deg);
|
||||
}
|
||||
to {
|
||||
transform: translateX(calc((var(--w, 50px)) + (50px))) rotate(20deg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import { CLIENT_FRONTEND_URL } from "../App";
|
||||
|
||||
export const secondPathSegment = (p: string) =>
|
||||
p.replace(/^\/?[^/]+/, "").replace(/^\/+/, "");
|
||||
|
||||
export function b64e(str: string) {
|
||||
return btoa(
|
||||
encodeURIComponent(str).replace(
|
||||
/%([0-9A-F]{2})/g,
|
||||
function toSolidBytes(_match, p1) {
|
||||
// @ts-ignore
|
||||
return String.fromCharCode("0x" + p1);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function b64d(str: string) {
|
||||
return decodeURIComponent(
|
||||
atob(str)
|
||||
.split("")
|
||||
.map(function (c) {
|
||||
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
||||
})
|
||||
.join("")
|
||||
);
|
||||
}
|
||||
|
||||
/** by claude
|
||||
* @param {string} text - The text to copy to clipboard
|
||||
* @returns {Promise<boolean>} - Returns true if successful, false otherwise
|
||||
*/
|
||||
export async function copyToClipboard(text: string) {
|
||||
// Method 1: Modern Clipboard API (preferred)
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.warn("Clipboard API failed, trying fallback:", err);
|
||||
}
|
||||
}
|
||||
// Method 2: Fallback for older browsers or non-secure contexts
|
||||
try {
|
||||
const textarea = document.createElement("textarea");
|
||||
textarea.value = text;
|
||||
textarea.style.position = "fixed";
|
||||
textarea.style.left = "-999999px";
|
||||
textarea.style.top = "-999999px";
|
||||
textarea.style.opacity = "0";
|
||||
textarea.setAttribute("readonly", "");
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
textarea.setSelectionRange(0, text.length);
|
||||
const success = document.execCommand("copy");
|
||||
document.body.removeChild(textarea);
|
||||
return success;
|
||||
} catch (err) {
|
||||
console.error("All copy methods failed:", err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// dx4 specific
|
||||
export async function copyDXLink(
|
||||
classId: string,
|
||||
adminId: string | undefined = undefined
|
||||
) {
|
||||
return copyToClipboard(
|
||||
CLIENT_FRONTEND_URL + "#//" + classId + (adminId ? ";" + b64e(adminId) : "")
|
||||
);
|
||||
}
|
||||
|
||||
export const randomString = (length: number, symbols: string[]) => {
|
||||
const len = symbols.length;
|
||||
return Array.from(
|
||||
{ length },
|
||||
() => symbols[Math.floor(Math.random() * len)]
|
||||
).join("");
|
||||
};
|
||||
|
||||
|
||||
export const AvailableSymbols = (() => {
|
||||
const a = "abcdefghijklmnopqrstuvwxyz"; // alphabet
|
||||
const A = a.toUpperCase(); // ALPHABET
|
||||
const n = "1234567890"; // numbers
|
||||
const s = "_-"; // specials
|
||||
return (a + n + A + s).split("");
|
||||
})();
|
||||
|
||||
export const AvailableAdminSymbols = [...AvailableSymbols, ..."$()*^%@!+=.".split("")];
|
||||
@@ -0,0 +1 @@
|
||||
export type ssroutetype = (setRoute: (e: string) => void, r: string) => void;
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"target": "ES2022",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"types": ["vite/client"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": false,
|
||||
"erasableSyntaxOnly": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.app.json" },
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"target": "ES2023",
|
||||
"lib": ["ES2023"],
|
||||
"module": "ESNext",
|
||||
"types": ["node"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"erasableSyntaxOnly": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
react({
|
||||
babel: {
|
||||
plugins: [["babel-plugin-react-compiler"]],
|
||||
},
|
||||
}),
|
||||
tailwindcss(),
|
||||
],
|
||||
base: "/dx4dashboard",
|
||||
});
|
||||
Reference in New Issue
Block a user