From c69b23f4e062cbfac719b4373fb0073fe86f4440 Mon Sep 17 00:00:00 2001
From: thehrz
Date: Sat, 16 Nov 2024 13:41:20 +0800
Subject: [PATCH] pref: test
---
frontend/package.json | 39 +-
frontend/pnpm-lock.yaml | 1130 +++++++++++++++------
frontend/src/App.css | 42 -
frontend/src/App.tsx | 7 +-
frontend/src/Route.tsx | 58 ++
frontend/src/apis/apis.ts | 156 +++
frontend/src/apis/error.ts | 8 +
frontend/src/apis/model.ts | 66 ++
frontend/src/apis/utils.ts | 10 +
frontend/src/assets/react.svg | 1 -
frontend/src/components/CaptchaWidget.tsx | 65 ++
frontend/src/components/CheckInput.tsx | 65 ++
frontend/src/components/Loading.tsx | 15 +
frontend/src/components/NeedLogin.tsx | 41 +
frontend/src/components/SkinViewUUID.tsx | 89 ++
frontend/src/components/Skinview3d.tsx | 101 ++
frontend/src/hooks/useTitle.ts | 16 +
frontend/src/index.css | 68 --
frontend/src/main.tsx | 13 +-
frontend/src/store/store.ts | 10 +
frontend/src/utils/email.ts | 3 +
frontend/src/utils/root.ts | 6 +
frontend/src/utils/skin.ts | 17 +
frontend/src/views/Forgot.tsx | 120 +++
frontend/src/views/Index.tsx | 9 +
frontend/src/views/Layout.tsx | 291 ++++++
frontend/src/views/Login.tsx | 169 +++
frontend/src/views/Register.tsx | 225 ++++
frontend/src/views/SendEmail.tsx | 181 ++++
frontend/src/views/admin/UserAdmin.tsx | 237 +++++
frontend/src/views/profile/Profile.tsx | 69 ++
frontend/src/views/profile/Security.tsx | 202 ++++
frontend/src/views/profile/Textures.tsx | 133 +++
frontend/vite.config.ts | 27 +-
34 files changed, 3238 insertions(+), 451 deletions(-)
delete mode 100644 frontend/src/App.css
create mode 100644 frontend/src/Route.tsx
create mode 100644 frontend/src/apis/apis.ts
create mode 100644 frontend/src/apis/error.ts
create mode 100644 frontend/src/apis/model.ts
create mode 100644 frontend/src/apis/utils.ts
delete mode 100644 frontend/src/assets/react.svg
create mode 100644 frontend/src/components/CaptchaWidget.tsx
create mode 100644 frontend/src/components/CheckInput.tsx
create mode 100644 frontend/src/components/Loading.tsx
create mode 100644 frontend/src/components/NeedLogin.tsx
create mode 100644 frontend/src/components/SkinViewUUID.tsx
create mode 100644 frontend/src/components/Skinview3d.tsx
create mode 100644 frontend/src/hooks/useTitle.ts
delete mode 100644 frontend/src/index.css
create mode 100644 frontend/src/store/store.ts
create mode 100644 frontend/src/utils/email.ts
create mode 100644 frontend/src/utils/root.ts
create mode 100644 frontend/src/utils/skin.ts
create mode 100644 frontend/src/views/Forgot.tsx
create mode 100644 frontend/src/views/Index.tsx
create mode 100644 frontend/src/views/Layout.tsx
create mode 100644 frontend/src/views/Login.tsx
create mode 100644 frontend/src/views/Register.tsx
create mode 100644 frontend/src/views/SendEmail.tsx
create mode 100644 frontend/src/views/admin/UserAdmin.tsx
create mode 100644 frontend/src/views/profile/Profile.tsx
create mode 100644 frontend/src/views/profile/Security.tsx
create mode 100644 frontend/src/views/profile/Textures.tsx
diff --git a/frontend/package.json b/frontend/package.json
index ab777d4..6a85373 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,32 +1,43 @@
{
- "name": "test",
+ "name": "authlib-skin",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
- "build": "tsc -b && vite build",
- "lint": "eslint .",
+ "build": "tsc && vite build",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
- "@mui/material": "^6.1.7",
+ "@marsidev/react-turnstile": "^0.3.2",
+ "@mui/icons-material": "^5.16.7",
+ "@mui/material": "^5.16.7",
+ "ahooks": "^3.8.1",
+ "immer": "^10.1.1",
+ "jotai": "^2.10.1",
+ "mui-file-input": "^3.0.2",
"react": "^18.3.1",
- "react-dom": "^18.3.1"
+ "react-dom": "^18.3.1",
+ "react-router-dom": "^6.28.0",
+ "skinview3d": "^3.1.0",
+ "tilg": "^0.1.1"
},
"devDependencies": {
- "@eslint/js": "^9.13.0",
+ "@types/node": "^20.17.6",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
- "@vitejs/plugin-react-swc": "^3.5.0",
- "eslint": "^9.13.0",
- "eslint-plugin-react-hooks": "^5.0.0",
+ "@typescript-eslint/eslint-plugin": "^6.21.0",
+ "@typescript-eslint/parser": "^6.21.0",
+ "@vitejs/plugin-react-swc": "^3.7.1",
+ "eslint": "^8.57.1",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.14",
- "globals": "^15.11.0",
- "typescript": "~5.6.2",
- "typescript-eslint": "^8.11.0",
- "vite": "^5.4.10"
+ "rollup-plugin-visualizer": "^5.12.0",
+ "typescript": "^5.6.3",
+ "vite": "^5.4.11"
}
-}
+}
\ No newline at end of file
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
index 8f6df62..c95fedd 100644
--- a/frontend/pnpm-lock.yaml
+++ b/frontend/pnpm-lock.yaml
@@ -14,49 +14,82 @@ importers:
'@emotion/styled':
specifier: ^11.13.0
version: 11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
+ '@marsidev/react-turnstile':
+ specifier: ^0.3.2
+ version: 0.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@mui/icons-material':
+ specifier: ^5.16.7
+ version: 5.16.7(@mui/material@5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
'@mui/material':
- specifier: ^6.1.7
- version: 6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ specifier: ^5.16.7
+ version: 5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ ahooks:
+ specifier: ^3.8.1
+ version: 3.8.1(react@18.3.1)
+ immer:
+ specifier: ^10.1.1
+ version: 10.1.1
+ jotai:
+ specifier: ^2.10.1
+ version: 2.10.2(@types/react@18.3.12)(react@18.3.1)
+ mui-file-input:
+ specifier: ^3.0.2
+ version: 3.0.2(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@mui/icons-material@5.16.7(@mui/material@5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@mui/material@5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react:
specifier: ^18.3.1
version: 18.3.1
react-dom:
specifier: ^18.3.1
version: 18.3.1(react@18.3.1)
+ react-router-dom:
+ specifier: ^6.28.0
+ version: 6.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ skinview3d:
+ specifier: ^3.1.0
+ version: 3.1.0
+ tilg:
+ specifier: ^0.1.1
+ version: 0.1.1(react@18.3.1)
devDependencies:
- '@eslint/js':
- specifier: ^9.13.0
- version: 9.15.0
+ '@types/node':
+ specifier: ^20.17.6
+ version: 20.17.6
'@types/react':
specifier: ^18.3.12
version: 18.3.12
'@types/react-dom':
specifier: ^18.3.1
version: 18.3.1
+ '@typescript-eslint/eslint-plugin':
+ specifier: ^6.21.0
+ version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3)
+ '@typescript-eslint/parser':
+ specifier: ^6.21.0
+ version: 6.21.0(eslint@8.57.1)(typescript@5.6.3)
'@vitejs/plugin-react-swc':
- specifier: ^3.5.0
- version: 3.7.1(vite@5.4.11)
+ specifier: ^3.7.1
+ version: 3.7.1(vite@5.4.11(@types/node@20.17.6))
eslint:
- specifier: ^9.13.0
- version: 9.15.0
+ specifier: ^8.57.1
+ version: 8.57.1
+ eslint-config-prettier:
+ specifier: ^9.1.0
+ version: 9.1.0(eslint@8.57.1)
eslint-plugin-react-hooks:
- specifier: ^5.0.0
- version: 5.0.0(eslint@9.15.0)
+ specifier: ^4.6.2
+ version: 4.6.2(eslint@8.57.1)
eslint-plugin-react-refresh:
specifier: ^0.4.14
- version: 0.4.14(eslint@9.15.0)
- globals:
- specifier: ^15.11.0
- version: 15.12.0
+ version: 0.4.14(eslint@8.57.1)
+ rollup-plugin-visualizer:
+ specifier: ^5.12.0
+ version: 5.12.0(rollup@4.27.2)
typescript:
- specifier: ~5.6.2
+ specifier: ^5.6.3
version: 5.6.3
- typescript-eslint:
- specifier: ^8.11.0
- version: 8.14.0(eslint@9.15.0)(typescript@5.6.3)
vite:
- specifier: ^5.4.10
- version: 5.4.11
+ specifier: ^5.4.11
+ version: 5.4.11(@types/node@20.17.6)
packages:
@@ -303,49 +336,26 @@ packages:
resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
- '@eslint/config-array@0.19.0':
- resolution: {integrity: sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@eslint/eslintrc@2.1.4':
+ resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- '@eslint/core@0.9.0':
- resolution: {integrity: sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@eslint/js@8.57.1':
+ resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- '@eslint/eslintrc@3.2.0':
- resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/js@9.15.0':
- resolution: {integrity: sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/object-schema@2.1.4':
- resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/plugin-kit@0.2.3':
- resolution: {integrity: sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@humanfs/core@0.19.1':
- resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
- engines: {node: '>=18.18.0'}
-
- '@humanfs/node@0.16.6':
- resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==}
- engines: {node: '>=18.18.0'}
+ '@humanwhocodes/config-array@0.13.0':
+ resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==}
+ engines: {node: '>=10.10.0'}
+ deprecated: Use @eslint/config-array instead
'@humanwhocodes/module-importer@1.0.1':
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
engines: {node: '>=12.22'}
- '@humanwhocodes/retry@0.3.1':
- resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==}
- engines: {node: '>=18.18'}
-
- '@humanwhocodes/retry@0.4.1':
- resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==}
- engines: {node: '>=18.18'}
+ '@humanwhocodes/object-schema@2.0.3':
+ resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
+ deprecated: Use @eslint/object-schema instead
'@jridgewell/gen-mapping@0.3.5':
resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
@@ -365,60 +375,74 @@ packages:
'@jridgewell/trace-mapping@0.3.25':
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
- '@mui/core-downloads-tracker@6.1.7':
- resolution: {integrity: sha512-POuIBi80BZBogQkG4PQKIGwy4QFwB+kOr+OI4k7Znh7LqMAIhwB9OC00l6M+w1GrZJYj3T8R5WX8G6QAIvoVEw==}
+ '@marsidev/react-turnstile@0.3.2':
+ resolution: {integrity: sha512-NTTmQdVgSFTHZlFRw/6RwG2kveT6J57U8JdjhbSdKcSBEbhqoe9L3wPMbq8g31KCDOm2cYTu/LNavAPbCY1vgA==}
+ peerDependencies:
+ react: '>=16.8.0'
+ react-dom: '>=16.8.0'
- '@mui/material@6.1.7':
- resolution: {integrity: sha512-KsjujQL/A2hLd1PV3QboF+W6SSL5QqH6ZlSuQoeYz9r69+TnyBFIevbYLxdjJcJmGBjigL5pfpn7hTGop+vhSg==}
- engines: {node: '>=14.0.0'}
+ '@mui/core-downloads-tracker@5.16.7':
+ resolution: {integrity: sha512-RtsCt4Geed2/v74sbihWzzRs+HsIQCfclHeORh5Ynu2fS4icIKozcSubwuG7vtzq2uW3fOR1zITSP84TNt2GoQ==}
+
+ '@mui/icons-material@5.16.7':
+ resolution: {integrity: sha512-UrGwDJCXEszbDI7yV047BYU5A28eGJ79keTCP4cc74WyncuVrnurlmIRxaHL8YK+LI1Kzq+/JM52IAkNnv4u+Q==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ '@mui/material': ^5.0.0
+ '@types/react': ^17.0.0 || ^18.0.0
+ react: ^17.0.0 || ^18.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@mui/material@5.16.7':
+ resolution: {integrity: sha512-cwwVQxBhK60OIOqZOVLFt55t01zmarKJiJUWbk0+8s/Ix5IaUzAShqlJchxsIQ4mSrWqgcKCCXKtIlG5H+/Jmg==}
+ engines: {node: '>=12.0.0'}
peerDependencies:
'@emotion/react': ^11.5.0
'@emotion/styled': ^11.3.0
- '@mui/material-pigment-css': ^6.1.7
- '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
- react: ^17.0.0 || ^18.0.0 || ^19.0.0
- react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0
+ '@types/react': ^17.0.0 || ^18.0.0
+ react: ^17.0.0 || ^18.0.0
+ react-dom: ^17.0.0 || ^18.0.0
peerDependenciesMeta:
'@emotion/react':
optional: true
'@emotion/styled':
optional: true
- '@mui/material-pigment-css':
- optional: true
'@types/react':
optional: true
- '@mui/private-theming@6.1.7':
- resolution: {integrity: sha512-uLbfUSsug5K0LVkv0PI6Flste3le8+6WSL2omdTiYde93P89Qr7pKr8TA6d2yXfr+Bm+SvD8/fGnkaRwFkryuQ==}
- engines: {node: '>=14.0.0'}
+ '@mui/private-theming@5.16.6':
+ resolution: {integrity: sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==}
+ engines: {node: '>=12.0.0'}
peerDependencies:
- '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
- react: ^17.0.0 || ^18.0.0 || ^19.0.0
+ '@types/react': ^17.0.0 || ^18.0.0
+ react: ^17.0.0 || ^18.0.0
peerDependenciesMeta:
'@types/react':
optional: true
- '@mui/styled-engine@6.1.7':
- resolution: {integrity: sha512-Ou4CxN7MQmwrfG1Pu6EYjPgPChQXxPDJrwgizLXlRPOad5qAq4gYXRuzrGQ2DfGjjwmJhjI8T6A0SeapAZPGig==}
- engines: {node: '>=14.0.0'}
+ '@mui/styled-engine@5.16.6':
+ resolution: {integrity: sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==}
+ engines: {node: '>=12.0.0'}
peerDependencies:
'@emotion/react': ^11.4.1
'@emotion/styled': ^11.3.0
- react: ^17.0.0 || ^18.0.0 || ^19.0.0
+ react: ^17.0.0 || ^18.0.0
peerDependenciesMeta:
'@emotion/react':
optional: true
'@emotion/styled':
optional: true
- '@mui/system@6.1.7':
- resolution: {integrity: sha512-qbMGgcC/FodpuRSfjXlEDdbNQaW++eATh0vNBcPUv2/YXSpReoOpoT9FhogxEBNks+aQViDXBRZKh6HX2fVmwg==}
- engines: {node: '>=14.0.0'}
+ '@mui/system@5.16.7':
+ resolution: {integrity: sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==}
+ engines: {node: '>=12.0.0'}
peerDependencies:
'@emotion/react': ^11.5.0
'@emotion/styled': ^11.3.0
- '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
- react: ^17.0.0 || ^18.0.0 || ^19.0.0
+ '@types/react': ^17.0.0 || ^18.0.0
+ react: ^17.0.0 || ^18.0.0
peerDependenciesMeta:
'@emotion/react':
optional: true
@@ -435,12 +459,12 @@ packages:
'@types/react':
optional: true
- '@mui/utils@6.1.7':
- resolution: {integrity: sha512-Gr7cRZxBoZ0BIa3Xqf/2YaUrBLyNPJvXPQH3OsD9WMZukI/TutibbQBVqLYpgqJn8pKSjbD50Yq2auG0wI1xOw==}
- engines: {node: '>=14.0.0'}
+ '@mui/utils@5.16.6':
+ resolution: {integrity: sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==}
+ engines: {node: '>=12.0.0'}
peerDependencies:
- '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
- react: ^17.0.0 || ^18.0.0 || ^19.0.0
+ '@types/react': ^17.0.0 || ^18.0.0
+ react: ^17.0.0 || ^18.0.0
peerDependenciesMeta:
'@types/react':
optional: true
@@ -460,6 +484,10 @@ packages:
'@popperjs/core@2.11.8':
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
+ '@remix-run/router@1.21.0':
+ resolution: {integrity: sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==}
+ engines: {node: '>=14.0.0'}
+
'@rollup/rollup-android-arm-eabi@4.27.2':
resolution: {integrity: sha512-Tj+j7Pyzd15wAdSJswvs5CJzJNV+qqSUcr/aCD+jpQSBtXvGnV0pnrjoc8zFTe9fcKCatkpFpOO7yAzpO998HA==}
cpu: [arm]
@@ -631,6 +659,9 @@ packages:
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+ '@types/node@20.17.6':
+ resolution: {integrity: sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ==}
+
'@types/parse-json@4.0.2':
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
@@ -646,62 +677,78 @@ packages:
'@types/react@18.3.12':
resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==}
- '@typescript-eslint/eslint-plugin@8.14.0':
- resolution: {integrity: sha512-tqp8H7UWFaZj0yNO6bycd5YjMwxa6wIHOLZvWPkidwbgLCsBMetQoGj7DPuAlWa2yGO3H48xmPwjhsSPPCGU5w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@types/semver@7.5.8':
+ resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
+
+ '@types/stats.js@0.17.3':
+ resolution: {integrity: sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==}
+
+ '@types/three@0.156.0':
+ resolution: {integrity: sha512-733bXDSRdlrxqOmQuOmfC1UBRuJ2pREPk8sWnx9MtIJEVDQMx8U0NQO5MVVaOrjzDPyLI+cFPim2X/ss9v0+LQ==}
+
+ '@types/webxr@0.5.20':
+ resolution: {integrity: sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==}
+
+ '@typescript-eslint/eslint-plugin@6.21.0':
+ resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==}
+ engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
- '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
- eslint: ^8.57.0 || ^9.0.0
+ '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
+ eslint: ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
- '@typescript-eslint/parser@8.14.0':
- resolution: {integrity: sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@typescript-eslint/parser@6.21.0':
+ resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==}
+ engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
+ eslint: ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
- '@typescript-eslint/scope-manager@8.14.0':
- resolution: {integrity: sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@typescript-eslint/scope-manager@6.21.0':
+ resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==}
+ engines: {node: ^16.0.0 || >=18.0.0}
- '@typescript-eslint/type-utils@8.14.0':
- resolution: {integrity: sha512-Xcz9qOtZuGusVOH5Uk07NGs39wrKkf3AxlkK79RBK6aJC1l03CobXjJbwBPSidetAOV+5rEVuiT1VSBUOAsanQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@typescript-eslint/type-utils@6.21.0':
+ resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ peerDependencies:
+ eslint: ^7.0.0 || ^8.0.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ '@typescript-eslint/types@6.21.0':
+ resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+
+ '@typescript-eslint/typescript-estree@6.21.0':
+ resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==}
+ engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
- '@typescript-eslint/types@8.14.0':
- resolution: {integrity: sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@typescript-eslint/typescript-estree@8.14.0':
- resolution: {integrity: sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@typescript-eslint/utils@6.21.0':
+ resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==}
+ engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
+ eslint: ^7.0.0 || ^8.0.0
- '@typescript-eslint/utils@8.14.0':
- resolution: {integrity: sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
+ '@typescript-eslint/visitor-keys@6.21.0':
+ resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==}
+ engines: {node: ^16.0.0 || >=18.0.0}
- '@typescript-eslint/visitor-keys@8.14.0':
- resolution: {integrity: sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@ungap/structured-clone@1.2.0':
+ resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
'@vitejs/plugin-react-swc@3.7.1':
resolution: {integrity: sha512-vgWOY0i1EROUK0Ctg1hwhtC3SdcDjZcdit4Ups4aPkDcB1jYhmo+RMYWY87cmXMhvtD5uf8lV89j2w16vkdSVg==}
@@ -718,9 +765,19 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
+ ahooks@3.8.1:
+ resolution: {integrity: sha512-JoP9+/RWO7MnI/uSKdvQ8WB10Y3oo1PjLv+4Sv4Vpm19Z86VUMdXh+RhWvMGxZZs06sq2p0xVtFk8Oh5ZObsoA==}
+ engines: {node: '>=8.0.0'}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+
ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
@@ -728,6 +785,10 @@ packages:
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ array-union@2.1.0:
+ resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
+ engines: {node: '>=8'}
+
babel-plugin-macros@3.1.0:
resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==}
engines: {node: '>=10', npm: '>=6'}
@@ -753,6 +814,10 @@ packages:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
+ cliui@8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+
clsx@2.1.1:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
@@ -781,6 +846,9 @@ packages:
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+ dayjs@1.11.13:
+ resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
+
debug@4.3.7:
resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
engines: {node: '>=6.0'}
@@ -793,9 +861,24 @@ packages:
deep-is@0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+ define-lazy-prop@2.0.0:
+ resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
+ engines: {node: '>=8'}
+
+ dir-glob@3.0.1:
+ resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+ engines: {node: '>=8'}
+
+ doctrine@3.0.0:
+ resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+ engines: {node: '>=6.0.0'}
+
dom-helpers@5.2.1:
resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
+ emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
error-ex@1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
@@ -804,46 +887,48 @@ packages:
engines: {node: '>=12'}
hasBin: true
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+
escape-string-regexp@4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
- eslint-plugin-react-hooks@5.0.0:
- resolution: {integrity: sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==}
+ eslint-config-prettier@9.1.0:
+ resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==}
+ hasBin: true
+ peerDependencies:
+ eslint: '>=7.0.0'
+
+ eslint-plugin-react-hooks@4.6.2:
+ resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==}
engines: {node: '>=10'}
peerDependencies:
- eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
eslint-plugin-react-refresh@0.4.14:
resolution: {integrity: sha512-aXvzCTK7ZBv1e7fahFuR3Z/fyQQSIQ711yPgYRj+Oj64tyTgO4iQIDmYXDBqvSWQ/FA4OSCsXOStlF+noU0/NA==}
peerDependencies:
eslint: '>=7'
- eslint-scope@8.2.0:
- resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ eslint-scope@7.2.2:
+ resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
eslint-visitor-keys@3.4.3:
resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- eslint-visitor-keys@4.2.0:
- resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- eslint@9.15.0:
- resolution: {integrity: sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ eslint@8.57.1:
+ resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
hasBin: true
- peerDependencies:
- jiti: '*'
- peerDependenciesMeta:
- jiti:
- optional: true
- espree@10.3.0:
- resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ espree@9.6.1:
+ resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
esquery@1.6.0:
resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
@@ -877,9 +962,12 @@ packages:
fastq@1.17.1:
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
- file-entry-cache@8.0.0:
- resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
- engines: {node: '>=16.0.0'}
+ fflate@0.6.10:
+ resolution: {integrity: sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==}
+
+ file-entry-cache@6.0.1:
+ resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
+ engines: {node: ^10.12.0 || >=12.0.0}
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
@@ -892,13 +980,16 @@ packages:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'}
- flat-cache@4.0.1:
- resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
- engines: {node: '>=16'}
+ flat-cache@3.2.0:
+ resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
+ engines: {node: ^10.12.0 || >=12.0.0}
flatted@3.3.1:
resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
+ fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -907,6 +998,10 @@ packages:
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+ get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@@ -915,17 +1010,21 @@ packages:
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
engines: {node: '>=10.13.0'}
+ glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ deprecated: Glob versions prior to v9 are no longer supported
+
globals@11.12.0:
resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
engines: {node: '>=4'}
- globals@14.0.0:
- resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
- engines: {node: '>=18'}
+ globals@13.24.0:
+ resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
+ engines: {node: '>=8'}
- globals@15.12.0:
- resolution: {integrity: sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==}
- engines: {node: '>=18'}
+ globby@11.1.0:
+ resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
+ engines: {node: '>=10'}
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
@@ -945,6 +1044,9 @@ packages:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
+ immer@10.1.1:
+ resolution: {integrity: sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==}
+
import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'}
@@ -953,6 +1055,16 @@ packages:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
+ inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+ intersection-observer@0.12.2:
+ resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==}
+
is-arrayish@0.2.1:
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
@@ -960,10 +1072,19 @@ packages:
resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==}
engines: {node: '>= 0.4'}
+ is-docker@2.2.1:
+ resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
+ engines: {node: '>=8'}
+ hasBin: true
+
is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
+ is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+
is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
@@ -972,9 +1093,33 @@ packages:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
+ is-path-inside@3.0.3:
+ resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+ engines: {node: '>=8'}
+
+ is-wsl@2.2.0:
+ resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
+ engines: {node: '>=8'}
+
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ jotai@2.10.2:
+ resolution: {integrity: sha512-DqsBTlRglIBviuJLfK6JxZzpd6vKfbuJ4IqRCz70RFEDeZf46Fcteb/FXxNr1UnoxR5oUy3oq7IE8BrEq0G5DQ==}
+ engines: {node: '>=12.20.0'}
+ peerDependencies:
+ '@types/react': '>=17.0.0'
+ react: '>=17.0.0'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ react:
+ optional: true
+
+ js-cookie@3.0.5:
+ resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==}
+ engines: {node: '>=14'}
+
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -1016,6 +1161,9 @@ packages:
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ lodash@4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+
loose-envify@1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
@@ -1024,6 +1172,9 @@ packages:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
+ meshoptimizer@0.18.1:
+ resolution: {integrity: sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==}
+
micromatch@4.0.8:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
@@ -1031,13 +1182,27 @@ packages:
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
- minimatch@9.0.5:
- resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
+ minimatch@9.0.3:
+ resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==}
engines: {node: '>=16 || 14 >=14.17'}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ mui-file-input@3.0.2:
+ resolution: {integrity: sha512-58Jp3+f5MUXjhZjlLfYFOEOBICnLoFC4x0G1+y411JsGBjZQ1lgICv7KQVgP5aF+IRvhJ1vfI6KpbnmqwRKXoA==}
+ peerDependencies:
+ '@emotion/react': ^11.5.0
+ '@emotion/styled': ^11.3.0
+ '@mui/icons-material': ^5.0.0
+ '@mui/material': ^5.0.0
+ '@types/react': ^18.0.0
+ react: ^18.0.0
+ react-dom: ^18.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
nanoid@3.3.7:
resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -1050,6 +1215,13 @@ packages:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+ open@8.4.2:
+ resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==}
+ engines: {node: '>=12'}
+
optionator@0.9.4:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
@@ -1074,6 +1246,10 @@ packages:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
+ path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+
path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
@@ -1100,6 +1276,10 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
+ pretty-bytes@6.1.1:
+ resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
+ engines: {node: ^14.13.1 || >=16.0.0}
+
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
@@ -1115,12 +1295,28 @@ packages:
peerDependencies:
react: ^18.3.1
+ react-fast-compare@3.2.2:
+ resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
+
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
react-is@18.3.1:
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+ react-router-dom@6.28.0:
+ resolution: {integrity: sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ react: '>=16.8'
+ react-dom: '>=16.8'
+
+ react-router@6.28.0:
+ resolution: {integrity: sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ react: '>=16.8'
+
react-transition-group@4.4.5:
resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==}
peerDependencies:
@@ -1134,6 +1330,13 @@ packages:
regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
+ require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+
+ resize-observer-polyfill@1.5.1:
+ resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
+
resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
@@ -1146,6 +1349,21 @@ packages:
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ rimraf@3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ deprecated: Rimraf versions prior to v4 are no longer supported
+ hasBin: true
+
+ rollup-plugin-visualizer@5.12.0:
+ resolution: {integrity: sha512-8/NU9jXcHRs7Nnj07PF2o4gjxmm9lXIrZ8r175bT9dK8qoLlvKTwRMArRCMgpMGlq8CTLugRvEmyMeMXIU2pNQ==}
+ engines: {node: '>=14'}
+ hasBin: true
+ peerDependencies:
+ rollup: 2.x || 3.x || 4.x
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
rollup@4.27.2:
resolution: {integrity: sha512-KreA+PzWmk2yaFmZVwe6GB2uBD86nXl86OsDkt1bJS9p3vqWuEQ6HnJJ+j/mZi/q0920P99/MVRlB4L3crpF5w==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -1157,6 +1375,10 @@ packages:
scheduler@0.23.2:
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
+ screenfull@5.2.0:
+ resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==}
+ engines: {node: '>=0.10.0'}
+
semver@7.6.3:
resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
engines: {node: '>=10'}
@@ -1170,6 +1392,16 @@ packages:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
+ skinview-utils@0.7.1:
+ resolution: {integrity: sha512-4eLrMqR526ehlZbsd8SuZ/CHpS9GiH0xUMoV+PYlJVi95ZFz5HJu7Spt5XYa72DRS7wgt5qquvHZf0XZJgmu9Q==}
+
+ skinview3d@3.1.0:
+ resolution: {integrity: sha512-L+HXXAP4qYjLcY3YHasXKie9KXQpv/mPTMxgLOEd+hVQRdQkPs5xdWaKuOmlZY8UnyZzecQM7yrWRzgT/e7HZw==}
+
+ slash@3.0.0:
+ resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
+ engines: {node: '>=8'}
+
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
@@ -1178,6 +1410,18 @@ packages:
resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
engines: {node: '>=0.10.0'}
+ source-map@0.7.4:
+ resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
+ engines: {node: '>= 8'}
+
+ string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+
+ strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+
strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
@@ -1193,6 +1437,17 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
+ text-table@0.2.0:
+ resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+
+ three@0.156.1:
+ resolution: {integrity: sha512-kP7H0FK9d/k6t/XvQ9FO6i+QrePoDcNhwl0I02+wmUJRNSLCUIDMcfObnzQvxb37/0Uc9TDT0T1HgsRRrO6SYQ==}
+
+ tilg@0.1.1:
+ resolution: {integrity: sha512-0uHyTAUM0tJL792LeviRPFkJtCbF6Za3/hbbnRmWGUaicOhbJ0IpvBViXiXTF7nk6R0L6vve2XLesQzn5jEVng==}
+ peerDependencies:
+ react: ^18.0.0 || ^17.0.0
+
to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
@@ -1203,24 +1458,25 @@ packages:
peerDependencies:
typescript: '>=4.2.0'
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
- typescript-eslint@8.14.0:
- resolution: {integrity: sha512-K8fBJHxVL3kxMmwByvz8hNdBJ8a0YqKzKDX6jRlrjMuNXyd5T2V02HIq37+OiWXvUUOXgOOGiSSOh26Mh8pC3w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
+ type-fest@0.20.2:
+ resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
+ engines: {node: '>=10'}
typescript@5.6.3:
resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==}
engines: {node: '>=14.17'}
hasBin: true
+ undici-types@6.19.8:
+ resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
+
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
@@ -1264,10 +1520,29 @@ packages:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
+ wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+ y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+
yaml@1.10.2:
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
engines: {node: '>= 6'}
+ yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+
+ yargs@17.7.2:
+ resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+ engines: {node: '>=12'}
+
yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
@@ -1482,29 +1757,19 @@ snapshots:
'@esbuild/win32-x64@0.21.5':
optional: true
- '@eslint-community/eslint-utils@4.4.1(eslint@9.15.0)':
+ '@eslint-community/eslint-utils@4.4.1(eslint@8.57.1)':
dependencies:
- eslint: 9.15.0
+ eslint: 8.57.1
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.1': {}
- '@eslint/config-array@0.19.0':
- dependencies:
- '@eslint/object-schema': 2.1.4
- debug: 4.3.7
- minimatch: 3.1.2
- transitivePeerDependencies:
- - supports-color
-
- '@eslint/core@0.9.0': {}
-
- '@eslint/eslintrc@3.2.0':
+ '@eslint/eslintrc@2.1.4':
dependencies:
ajv: 6.12.6
debug: 4.3.7
- espree: 10.3.0
- globals: 14.0.0
+ espree: 9.6.1
+ globals: 13.24.0
ignore: 5.3.2
import-fresh: 3.3.0
js-yaml: 4.1.0
@@ -1513,26 +1778,19 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@eslint/js@9.15.0': {}
+ '@eslint/js@8.57.1': {}
- '@eslint/object-schema@2.1.4': {}
-
- '@eslint/plugin-kit@0.2.3':
+ '@humanwhocodes/config-array@0.13.0':
dependencies:
- levn: 0.4.1
-
- '@humanfs/core@0.19.1': {}
-
- '@humanfs/node@0.16.6':
- dependencies:
- '@humanfs/core': 0.19.1
- '@humanwhocodes/retry': 0.3.1
+ '@humanwhocodes/object-schema': 2.0.3
+ debug: 4.3.7
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
'@humanwhocodes/module-importer@1.0.1': {}
- '@humanwhocodes/retry@0.3.1': {}
-
- '@humanwhocodes/retry@0.4.1': {}
+ '@humanwhocodes/object-schema@2.0.3': {}
'@jridgewell/gen-mapping@0.3.5':
dependencies:
@@ -1551,15 +1809,28 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
- '@mui/core-downloads-tracker@6.1.7': {}
+ '@marsidev/react-turnstile@0.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
- '@mui/material@6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ '@mui/core-downloads-tracker@5.16.7': {}
+
+ '@mui/icons-material@5.16.7(@mui/material@5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)':
dependencies:
'@babel/runtime': 7.26.0
- '@mui/core-downloads-tracker': 6.1.7
- '@mui/system': 6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
+ '@mui/material': 5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.12
+
+ '@mui/material@5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@babel/runtime': 7.26.0
+ '@mui/core-downloads-tracker': 5.16.7
+ '@mui/system': 5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
'@mui/types': 7.2.19(@types/react@18.3.12)
- '@mui/utils': 6.1.7(@types/react@18.3.12)(react@18.3.1)
+ '@mui/utils': 5.16.6(@types/react@18.3.12)(react@18.3.1)
'@popperjs/core': 2.11.8
'@types/react-transition-group': 4.4.11
clsx: 2.1.1
@@ -1574,21 +1845,19 @@ snapshots:
'@emotion/styled': 11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
'@types/react': 18.3.12
- '@mui/private-theming@6.1.7(@types/react@18.3.12)(react@18.3.1)':
+ '@mui/private-theming@5.16.6(@types/react@18.3.12)(react@18.3.1)':
dependencies:
'@babel/runtime': 7.26.0
- '@mui/utils': 6.1.7(@types/react@18.3.12)(react@18.3.1)
+ '@mui/utils': 5.16.6(@types/react@18.3.12)(react@18.3.1)
prop-types: 15.8.1
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
- '@mui/styled-engine@6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1)':
+ '@mui/styled-engine@5.16.6(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1)':
dependencies:
'@babel/runtime': 7.26.0
'@emotion/cache': 11.13.1
- '@emotion/serialize': 1.3.2
- '@emotion/sheet': 1.4.0
csstype: 3.1.3
prop-types: 15.8.1
react: 18.3.1
@@ -1596,13 +1865,13 @@ snapshots:
'@emotion/react': 11.13.3(@types/react@18.3.12)(react@18.3.1)
'@emotion/styled': 11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
- '@mui/system@6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)':
+ '@mui/system@5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)':
dependencies:
'@babel/runtime': 7.26.0
- '@mui/private-theming': 6.1.7(@types/react@18.3.12)(react@18.3.1)
- '@mui/styled-engine': 6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1)
+ '@mui/private-theming': 5.16.6(@types/react@18.3.12)(react@18.3.1)
+ '@mui/styled-engine': 5.16.6(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1)
'@mui/types': 7.2.19(@types/react@18.3.12)
- '@mui/utils': 6.1.7(@types/react@18.3.12)(react@18.3.1)
+ '@mui/utils': 5.16.6(@types/react@18.3.12)(react@18.3.1)
clsx: 2.1.1
csstype: 3.1.3
prop-types: 15.8.1
@@ -1616,7 +1885,7 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.12
- '@mui/utils@6.1.7(@types/react@18.3.12)(react@18.3.1)':
+ '@mui/utils@5.16.6(@types/react@18.3.12)(react@18.3.1)':
dependencies:
'@babel/runtime': 7.26.0
'@mui/types': 7.2.19(@types/react@18.3.12)
@@ -1642,6 +1911,8 @@ snapshots:
'@popperjs/core@2.11.8': {}
+ '@remix-run/router@1.21.0': {}
+
'@rollup/rollup-android-arm-eabi@4.27.2':
optional: true
@@ -1752,6 +2023,10 @@ snapshots:
'@types/json-schema@7.0.15': {}
+ '@types/node@20.17.6':
+ dependencies:
+ undici-types: 6.19.8
+
'@types/parse-json@4.0.2': {}
'@types/prop-types@15.7.13': {}
@@ -1769,64 +2044,32 @@ snapshots:
'@types/prop-types': 15.7.13
csstype: 3.1.3
- '@typescript-eslint/eslint-plugin@8.14.0(@typescript-eslint/parser@8.14.0(eslint@9.15.0)(typescript@5.6.3))(eslint@9.15.0)(typescript@5.6.3)':
+ '@types/semver@7.5.8': {}
+
+ '@types/stats.js@0.17.3': {}
+
+ '@types/three@0.156.0':
+ dependencies:
+ '@types/stats.js': 0.17.3
+ '@types/webxr': 0.5.20
+ fflate: 0.6.10
+ meshoptimizer: 0.18.1
+
+ '@types/webxr@0.5.20': {}
+
+ '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.14.0(eslint@9.15.0)(typescript@5.6.3)
- '@typescript-eslint/scope-manager': 8.14.0
- '@typescript-eslint/type-utils': 8.14.0(eslint@9.15.0)(typescript@5.6.3)
- '@typescript-eslint/utils': 8.14.0(eslint@9.15.0)(typescript@5.6.3)
- '@typescript-eslint/visitor-keys': 8.14.0
- eslint: 9.15.0
+ '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.6.3)
+ '@typescript-eslint/scope-manager': 6.21.0
+ '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.1)(typescript@5.6.3)
+ '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.6.3)
+ '@typescript-eslint/visitor-keys': 6.21.0
+ debug: 4.3.7
+ eslint: 8.57.1
graphemer: 1.4.0
ignore: 5.3.2
natural-compare: 1.4.0
- ts-api-utils: 1.4.0(typescript@5.6.3)
- optionalDependencies:
- typescript: 5.6.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/parser@8.14.0(eslint@9.15.0)(typescript@5.6.3)':
- dependencies:
- '@typescript-eslint/scope-manager': 8.14.0
- '@typescript-eslint/types': 8.14.0
- '@typescript-eslint/typescript-estree': 8.14.0(typescript@5.6.3)
- '@typescript-eslint/visitor-keys': 8.14.0
- debug: 4.3.7
- eslint: 9.15.0
- optionalDependencies:
- typescript: 5.6.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/scope-manager@8.14.0':
- dependencies:
- '@typescript-eslint/types': 8.14.0
- '@typescript-eslint/visitor-keys': 8.14.0
-
- '@typescript-eslint/type-utils@8.14.0(eslint@9.15.0)(typescript@5.6.3)':
- dependencies:
- '@typescript-eslint/typescript-estree': 8.14.0(typescript@5.6.3)
- '@typescript-eslint/utils': 8.14.0(eslint@9.15.0)(typescript@5.6.3)
- debug: 4.3.7
- ts-api-utils: 1.4.0(typescript@5.6.3)
- optionalDependencies:
- typescript: 5.6.3
- transitivePeerDependencies:
- - eslint
- - supports-color
-
- '@typescript-eslint/types@8.14.0': {}
-
- '@typescript-eslint/typescript-estree@8.14.0(typescript@5.6.3)':
- dependencies:
- '@typescript-eslint/types': 8.14.0
- '@typescript-eslint/visitor-keys': 8.14.0
- debug: 4.3.7
- fast-glob: 3.3.2
- is-glob: 4.0.3
- minimatch: 9.0.5
semver: 7.6.3
ts-api-utils: 1.4.0(typescript@5.6.3)
optionalDependencies:
@@ -1834,26 +2077,78 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.14.0(eslint@9.15.0)(typescript@5.6.3)':
+ '@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0)
- '@typescript-eslint/scope-manager': 8.14.0
- '@typescript-eslint/types': 8.14.0
- '@typescript-eslint/typescript-estree': 8.14.0(typescript@5.6.3)
- eslint: 9.15.0
+ '@typescript-eslint/scope-manager': 6.21.0
+ '@typescript-eslint/types': 6.21.0
+ '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.6.3)
+ '@typescript-eslint/visitor-keys': 6.21.0
+ debug: 4.3.7
+ eslint: 8.57.1
+ optionalDependencies:
+ typescript: 5.6.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/scope-manager@6.21.0':
+ dependencies:
+ '@typescript-eslint/types': 6.21.0
+ '@typescript-eslint/visitor-keys': 6.21.0
+
+ '@typescript-eslint/type-utils@6.21.0(eslint@8.57.1)(typescript@5.6.3)':
+ dependencies:
+ '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.6.3)
+ '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.6.3)
+ debug: 4.3.7
+ eslint: 8.57.1
+ ts-api-utils: 1.4.0(typescript@5.6.3)
+ optionalDependencies:
+ typescript: 5.6.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/types@6.21.0': {}
+
+ '@typescript-eslint/typescript-estree@6.21.0(typescript@5.6.3)':
+ dependencies:
+ '@typescript-eslint/types': 6.21.0
+ '@typescript-eslint/visitor-keys': 6.21.0
+ debug: 4.3.7
+ globby: 11.1.0
+ is-glob: 4.0.3
+ minimatch: 9.0.3
+ semver: 7.6.3
+ ts-api-utils: 1.4.0(typescript@5.6.3)
+ optionalDependencies:
+ typescript: 5.6.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/utils@6.21.0(eslint@8.57.1)(typescript@5.6.3)':
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1)
+ '@types/json-schema': 7.0.15
+ '@types/semver': 7.5.8
+ '@typescript-eslint/scope-manager': 6.21.0
+ '@typescript-eslint/types': 6.21.0
+ '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.6.3)
+ eslint: 8.57.1
+ semver: 7.6.3
transitivePeerDependencies:
- supports-color
- typescript
- '@typescript-eslint/visitor-keys@8.14.0':
+ '@typescript-eslint/visitor-keys@6.21.0':
dependencies:
- '@typescript-eslint/types': 8.14.0
+ '@typescript-eslint/types': 6.21.0
eslint-visitor-keys: 3.4.3
- '@vitejs/plugin-react-swc@3.7.1(vite@5.4.11)':
+ '@ungap/structured-clone@1.2.0': {}
+
+ '@vitejs/plugin-react-swc@3.7.1(vite@5.4.11(@types/node@20.17.6))':
dependencies:
'@swc/core': 1.9.2
- vite: 5.4.11
+ vite: 5.4.11(@types/node@20.17.6)
transitivePeerDependencies:
- '@swc/helpers'
@@ -1863,6 +2158,19 @@ snapshots:
acorn@8.14.0: {}
+ ahooks@3.8.1(react@18.3.1):
+ dependencies:
+ '@babel/runtime': 7.26.0
+ dayjs: 1.11.13
+ intersection-observer: 0.12.2
+ js-cookie: 3.0.5
+ lodash: 4.17.21
+ react: 18.3.1
+ react-fast-compare: 3.2.2
+ resize-observer-polyfill: 1.5.1
+ screenfull: 5.2.0
+ tslib: 2.8.1
+
ajv@6.12.6:
dependencies:
fast-deep-equal: 3.1.3
@@ -1870,12 +2178,16 @@ snapshots:
json-schema-traverse: 0.4.1
uri-js: 4.4.1
+ ansi-regex@5.0.1: {}
+
ansi-styles@4.3.0:
dependencies:
color-convert: 2.0.1
argparse@2.0.1: {}
+ array-union@2.1.0: {}
+
babel-plugin-macros@3.1.0:
dependencies:
'@babel/runtime': 7.26.0
@@ -1904,6 +2216,12 @@ snapshots:
ansi-styles: 4.3.0
supports-color: 7.2.0
+ cliui@8.0.1:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+
clsx@2.1.1: {}
color-convert@2.0.1:
@@ -1932,17 +2250,31 @@ snapshots:
csstype@3.1.3: {}
+ dayjs@1.11.13: {}
+
debug@4.3.7:
dependencies:
ms: 2.1.3
deep-is@0.1.4: {}
+ define-lazy-prop@2.0.0: {}
+
+ dir-glob@3.0.1:
+ dependencies:
+ path-type: 4.0.0
+
+ doctrine@3.0.0:
+ dependencies:
+ esutils: 2.0.3
+
dom-helpers@5.2.1:
dependencies:
'@babel/runtime': 7.26.0
csstype: 3.1.3
+ emoji-regex@8.0.0: {}
+
error-ex@1.3.2:
dependencies:
is-arrayish: 0.2.1
@@ -1973,69 +2305,77 @@ snapshots:
'@esbuild/win32-ia32': 0.21.5
'@esbuild/win32-x64': 0.21.5
+ escalade@3.2.0: {}
+
escape-string-regexp@4.0.0: {}
- eslint-plugin-react-hooks@5.0.0(eslint@9.15.0):
+ eslint-config-prettier@9.1.0(eslint@8.57.1):
dependencies:
- eslint: 9.15.0
+ eslint: 8.57.1
- eslint-plugin-react-refresh@0.4.14(eslint@9.15.0):
+ eslint-plugin-react-hooks@4.6.2(eslint@8.57.1):
dependencies:
- eslint: 9.15.0
+ eslint: 8.57.1
- eslint-scope@8.2.0:
+ eslint-plugin-react-refresh@0.4.14(eslint@8.57.1):
+ dependencies:
+ eslint: 8.57.1
+
+ eslint-scope@7.2.2:
dependencies:
esrecurse: 4.3.0
estraverse: 5.3.0
eslint-visitor-keys@3.4.3: {}
- eslint-visitor-keys@4.2.0: {}
-
- eslint@9.15.0:
+ eslint@8.57.1:
dependencies:
- '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0)
+ '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1)
'@eslint-community/regexpp': 4.12.1
- '@eslint/config-array': 0.19.0
- '@eslint/core': 0.9.0
- '@eslint/eslintrc': 3.2.0
- '@eslint/js': 9.15.0
- '@eslint/plugin-kit': 0.2.3
- '@humanfs/node': 0.16.6
+ '@eslint/eslintrc': 2.1.4
+ '@eslint/js': 8.57.1
+ '@humanwhocodes/config-array': 0.13.0
'@humanwhocodes/module-importer': 1.0.1
- '@humanwhocodes/retry': 0.4.1
- '@types/estree': 1.0.6
- '@types/json-schema': 7.0.15
+ '@nodelib/fs.walk': 1.2.8
+ '@ungap/structured-clone': 1.2.0
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.5
debug: 4.3.7
+ doctrine: 3.0.0
escape-string-regexp: 4.0.0
- eslint-scope: 8.2.0
- eslint-visitor-keys: 4.2.0
- espree: 10.3.0
+ eslint-scope: 7.2.2
+ eslint-visitor-keys: 3.4.3
+ espree: 9.6.1
esquery: 1.6.0
esutils: 2.0.3
fast-deep-equal: 3.1.3
- file-entry-cache: 8.0.0
+ file-entry-cache: 6.0.1
find-up: 5.0.0
glob-parent: 6.0.2
+ globals: 13.24.0
+ graphemer: 1.4.0
ignore: 5.3.2
imurmurhash: 0.1.4
is-glob: 4.0.3
+ is-path-inside: 3.0.3
+ js-yaml: 4.1.0
json-stable-stringify-without-jsonify: 1.0.1
+ levn: 0.4.1
lodash.merge: 4.6.2
minimatch: 3.1.2
natural-compare: 1.4.0
optionator: 0.9.4
+ strip-ansi: 6.0.1
+ text-table: 0.2.0
transitivePeerDependencies:
- supports-color
- espree@10.3.0:
+ espree@9.6.1:
dependencies:
acorn: 8.14.0
acorn-jsx: 5.3.2(acorn@8.14.0)
- eslint-visitor-keys: 4.2.0
+ eslint-visitor-keys: 3.4.3
esquery@1.6.0:
dependencies:
@@ -2067,9 +2407,11 @@ snapshots:
dependencies:
reusify: 1.0.4
- file-entry-cache@8.0.0:
+ fflate@0.6.10: {}
+
+ file-entry-cache@6.0.1:
dependencies:
- flat-cache: 4.0.1
+ flat-cache: 3.2.0
fill-range@7.1.1:
dependencies:
@@ -2082,18 +2424,23 @@ snapshots:
locate-path: 6.0.0
path-exists: 4.0.0
- flat-cache@4.0.1:
+ flat-cache@3.2.0:
dependencies:
flatted: 3.3.1
keyv: 4.5.4
+ rimraf: 3.0.2
flatted@3.3.1: {}
+ fs.realpath@1.0.0: {}
+
fsevents@2.3.3:
optional: true
function-bind@1.1.2: {}
+ get-caller-file@2.0.5: {}
+
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
@@ -2102,11 +2449,29 @@ snapshots:
dependencies:
is-glob: 4.0.3
+ glob@7.2.3:
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+
globals@11.12.0: {}
- globals@14.0.0: {}
+ globals@13.24.0:
+ dependencies:
+ type-fest: 0.20.2
- globals@15.12.0: {}
+ globby@11.1.0:
+ dependencies:
+ array-union: 2.1.0
+ dir-glob: 3.0.1
+ fast-glob: 3.3.2
+ ignore: 5.3.2
+ merge2: 1.4.1
+ slash: 3.0.0
graphemer@1.4.0: {}
@@ -2122,6 +2487,8 @@ snapshots:
ignore@5.3.2: {}
+ immer@10.1.1: {}
+
import-fresh@3.3.0:
dependencies:
parent-module: 1.0.1
@@ -2129,22 +2496,48 @@ snapshots:
imurmurhash@0.1.4: {}
+ inflight@1.0.6:
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+
+ inherits@2.0.4: {}
+
+ intersection-observer@0.12.2: {}
+
is-arrayish@0.2.1: {}
is-core-module@2.15.1:
dependencies:
hasown: 2.0.2
+ is-docker@2.2.1: {}
+
is-extglob@2.1.1: {}
+ is-fullwidth-code-point@3.0.0: {}
+
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
is-number@7.0.0: {}
+ is-path-inside@3.0.3: {}
+
+ is-wsl@2.2.0:
+ dependencies:
+ is-docker: 2.2.1
+
isexe@2.0.0: {}
+ jotai@2.10.2(@types/react@18.3.12)(react@18.3.1):
+ optionalDependencies:
+ '@types/react': 18.3.12
+ react: 18.3.1
+
+ js-cookie@3.0.5: {}
+
js-tokens@4.0.0: {}
js-yaml@4.1.0:
@@ -2178,12 +2571,16 @@ snapshots:
lodash.merge@4.6.2: {}
+ lodash@4.17.21: {}
+
loose-envify@1.4.0:
dependencies:
js-tokens: 4.0.0
merge2@1.4.1: {}
+ meshoptimizer@0.18.1: {}
+
micromatch@4.0.8:
dependencies:
braces: 3.0.3
@@ -2193,18 +2590,40 @@ snapshots:
dependencies:
brace-expansion: 1.1.11
- minimatch@9.0.5:
+ minimatch@9.0.3:
dependencies:
brace-expansion: 2.0.1
ms@2.1.3: {}
+ mui-file-input@3.0.2(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@mui/icons-material@5.16.7(@mui/material@5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@mui/material@5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@emotion/react': 11.13.3(@types/react@18.3.12)(react@18.3.1)
+ '@emotion/styled': 11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
+ '@mui/icons-material': 5.16.7(@mui/material@5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
+ '@mui/material': 5.16.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ pretty-bytes: 6.1.1
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.12
+
nanoid@3.3.7: {}
natural-compare@1.4.0: {}
object-assign@4.1.1: {}
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
+ open@8.4.2:
+ dependencies:
+ define-lazy-prop: 2.0.0
+ is-docker: 2.2.1
+ is-wsl: 2.2.0
+
optionator@0.9.4:
dependencies:
deep-is: 0.1.4
@@ -2235,6 +2654,8 @@ snapshots:
path-exists@4.0.0: {}
+ path-is-absolute@1.0.1: {}
+
path-key@3.1.1: {}
path-parse@1.0.7: {}
@@ -2253,6 +2674,8 @@ snapshots:
prelude-ls@1.2.1: {}
+ pretty-bytes@6.1.1: {}
+
prop-types@15.8.1:
dependencies:
loose-envify: 1.4.0
@@ -2269,10 +2692,24 @@ snapshots:
react: 18.3.1
scheduler: 0.23.2
+ react-fast-compare@3.2.2: {}
+
react-is@16.13.1: {}
react-is@18.3.1: {}
+ react-router-dom@6.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@remix-run/router': 1.21.0
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-router: 6.28.0(react@18.3.1)
+
+ react-router@6.28.0(react@18.3.1):
+ dependencies:
+ '@remix-run/router': 1.21.0
+ react: 18.3.1
+
react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@babel/runtime': 7.26.0
@@ -2288,6 +2725,10 @@ snapshots:
regenerator-runtime@0.14.1: {}
+ require-directory@2.1.1: {}
+
+ resize-observer-polyfill@1.5.1: {}
+
resolve-from@4.0.0: {}
resolve@1.22.8:
@@ -2298,6 +2739,19 @@ snapshots:
reusify@1.0.4: {}
+ rimraf@3.0.2:
+ dependencies:
+ glob: 7.2.3
+
+ rollup-plugin-visualizer@5.12.0(rollup@4.27.2):
+ dependencies:
+ open: 8.4.2
+ picomatch: 2.3.1
+ source-map: 0.7.4
+ yargs: 17.7.2
+ optionalDependencies:
+ rollup: 4.27.2
+
rollup@4.27.2:
dependencies:
'@types/estree': 1.0.6
@@ -2330,6 +2784,8 @@ snapshots:
dependencies:
loose-envify: 1.4.0
+ screenfull@5.2.0: {}
+
semver@7.6.3: {}
shebang-command@2.0.0:
@@ -2338,10 +2794,32 @@ snapshots:
shebang-regex@3.0.0: {}
+ skinview-utils@0.7.1: {}
+
+ skinview3d@3.1.0:
+ dependencies:
+ '@types/three': 0.156.0
+ skinview-utils: 0.7.1
+ three: 0.156.1
+
+ slash@3.0.0: {}
+
source-map-js@1.2.1: {}
source-map@0.5.7: {}
+ source-map@0.7.4: {}
+
+ string-width@4.2.3:
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+
+ strip-ansi@6.0.1:
+ dependencies:
+ ansi-regex: 5.0.1
+
strip-json-comments@3.1.1: {}
stylis@4.2.0: {}
@@ -2352,6 +2830,14 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
+ text-table@0.2.0: {}
+
+ three@0.156.1: {}
+
+ tilg@0.1.1(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+
to-regex-range@5.0.1:
dependencies:
is-number: 7.0.0
@@ -2360,33 +2846,29 @@ snapshots:
dependencies:
typescript: 5.6.3
+ tslib@2.8.1: {}
+
type-check@0.4.0:
dependencies:
prelude-ls: 1.2.1
- typescript-eslint@8.14.0(eslint@9.15.0)(typescript@5.6.3):
- dependencies:
- '@typescript-eslint/eslint-plugin': 8.14.0(@typescript-eslint/parser@8.14.0(eslint@9.15.0)(typescript@5.6.3))(eslint@9.15.0)(typescript@5.6.3)
- '@typescript-eslint/parser': 8.14.0(eslint@9.15.0)(typescript@5.6.3)
- '@typescript-eslint/utils': 8.14.0(eslint@9.15.0)(typescript@5.6.3)
- optionalDependencies:
- typescript: 5.6.3
- transitivePeerDependencies:
- - eslint
- - supports-color
+ type-fest@0.20.2: {}
typescript@5.6.3: {}
+ undici-types@6.19.8: {}
+
uri-js@4.4.1:
dependencies:
punycode: 2.3.1
- vite@5.4.11:
+ vite@5.4.11(@types/node@20.17.6):
dependencies:
esbuild: 0.21.5
postcss: 8.4.49
rollup: 4.27.2
optionalDependencies:
+ '@types/node': 20.17.6
fsevents: 2.3.3
which@2.0.2:
@@ -2395,6 +2877,28 @@ snapshots:
word-wrap@1.2.5: {}
+ wrap-ansi@7.0.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ wrappy@1.0.2: {}
+
+ y18n@5.0.8: {}
+
yaml@1.10.2: {}
+ yargs-parser@21.1.1: {}
+
+ yargs@17.7.2:
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.2.0
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
+
yocto-queue@0.1.0: {}
diff --git a/frontend/src/App.css b/frontend/src/App.css
deleted file mode 100644
index b9d355d..0000000
--- a/frontend/src/App.css
+++ /dev/null
@@ -1,42 +0,0 @@
-#root {
- max-width: 1280px;
- margin: 0 auto;
- padding: 2rem;
- text-align: center;
-}
-
-.logo {
- height: 6em;
- padding: 1.5em;
- will-change: filter;
- transition: filter 300ms;
-}
-.logo:hover {
- filter: drop-shadow(0 0 2em #646cffaa);
-}
-.logo.react:hover {
- filter: drop-shadow(0 0 2em #61dafbaa);
-}
-
-@keyframes logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
-
-@media (prefers-reduced-motion: no-preference) {
- a:nth-of-type(2) .logo {
- animation: logo-spin infinite 20s linear;
- }
-}
-
-.card {
- padding: 2em;
-}
-
-.read-the-docs {
- color: #888;
-}
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index ef79242..b25320c 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,14 +1,13 @@
-
-import './App.css'
-import { Button } from '@mui/material'
+import { PageRoute } from '@/Route'
function App() {
return (
<>
- ;
+
>
)
}
+
export default App
diff --git a/frontend/src/Route.tsx b/frontend/src/Route.tsx
new file mode 100644
index 0000000..83a2f18
--- /dev/null
+++ b/frontend/src/Route.tsx
@@ -0,0 +1,58 @@
+import { Routes, Route, createBrowserRouter, RouterProvider, Outlet } from "react-router-dom";
+import { ScrollRestoration } from "react-router-dom";
+import Login from '@/views/Login'
+import Register from '@/views/Register'
+import Profile from '@/views/profile/Profile'
+import Textures from '@/views/profile/Textures'
+import Security from '@/views/profile/Security'
+import Layout from '@/views/Layout'
+import UserAdmin from "@/views/admin/UserAdmin";
+import NeedLogin from "@/components/NeedLogin";
+import Index from "@/views/Index";
+import SendEmail from "@/views/SendEmail";
+import { sendForgotEmail, sendRegEmail } from "@/apis/apis";
+import Forgot from "@/views/Forgot";
+
+const router = createBrowserRouter([
+ { path: "*", Component: Root },
+])
+
+function Root() {
+ return (
+ <>
+
+ }>
+ } />
+ 404
} />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+ }>
+ } />
+ } />
+ } />
+
+
+ }>
+ } />
+
+
+
+
+
+ >
+ )
+}
+
+
+export function PageRoute() {
+ return (
+ <>
+
+ >
+ )
+}
+
diff --git a/frontend/src/apis/apis.ts b/frontend/src/apis/apis.ts
new file mode 100644
index 0000000..b996595
--- /dev/null
+++ b/frontend/src/apis/apis.ts
@@ -0,0 +1,156 @@
+import type { tokenData, ApiUser, YggProfile, ApiConfig, List, UserInfo, EditUser } from '@/apis/model'
+import { apiGet } from '@/apis/utils'
+import root from '@/utils/root'
+
+export async function login(email: string, password: string, captchaToken: string) {
+ const v = await fetch(root() + "/api/v1/user/login", {
+ method: "POST",
+ body: JSON.stringify({
+ "email": email,
+ "password": password,
+ "CaptchaToken": captchaToken
+ })
+ })
+ return await apiGet(v)
+}
+
+export async function register(email: string, username: string, password: string, captchaToken: string, code: string) {
+ const v = await fetch(root() + "/api/v1/user/reg", {
+ method: "POST",
+ body: JSON.stringify({
+ "Email": email,
+ "Password": password,
+ "Name": username,
+ "CaptchaToken": captchaToken,
+ "EmailJwt": code,
+ })
+ })
+ return await apiGet(v)
+}
+
+export async function userInfo(token: string) {
+ if (token == "") return
+ const v = await fetch(root() + "/api/v1/user", {
+ headers: {
+ "Authorization": "Bearer " + token
+ }
+ })
+ return await apiGet(v)
+}
+
+export async function yggProfile(uuid: string) {
+ if (uuid == "") return
+ const v = await fetch(root() + "/api/yggdrasil/sessionserver/session/minecraft/profile/" + uuid)
+ const data = await v.json()
+ if (!v.ok) {
+ throw new Error(data?.errorMessage)
+ }
+ return data as YggProfile
+}
+
+export async function upTextures(token: string, textureType: 'skin' | 'cape', model: 'slim' | '', file: File) {
+ const f = new FormData()
+ f.set("file", file)
+ f.set("model", model)
+
+ const r = await fetch(root() + "/api/v1/user/skin/" + textureType, {
+ method: "PUT",
+ body: f,
+ headers: {
+ "Authorization": "Bearer " + token
+ }
+ })
+ return await apiGet(r)
+}
+
+export async function changePasswd(old: string, newpa: string, token: string) {
+ const r = await fetch(root() + "/api/v1/user/password", {
+ method: "POST",
+ body: JSON.stringify({
+ "old": old,
+ "new": newpa
+ }),
+ headers: {
+ "Authorization": "Bearer " + token
+ }
+ })
+ return await apiGet(r)
+}
+
+export async function getConfig() {
+ const r = await fetch(root() + "/api/v1/config")
+ return await apiGet(r)
+}
+
+export async function changeName(name: string, token: string) {
+ const r = await fetch(root() + "/api/v1/user/name", {
+ method: "POST",
+ body: JSON.stringify({
+ "name": name,
+ }),
+ headers: {
+ "Authorization": "Bearer " + token
+ }
+ })
+ return await apiGet(r)
+}
+
+export async function ListUser(page: number, token: string, email: string, name: string) {
+ const u = new URL(root() + "/api/v1/admin/users")
+ u.searchParams.set("page", String(page))
+ u.searchParams.set("email", email)
+ u.searchParams.set("name", name)
+ const r = await fetch(u.toString(), {
+ method: "GET",
+ headers: {
+ "Authorization": "Bearer " + token
+ }
+ })
+ return await apiGet>(r)
+}
+
+export async function editUser(u: EditUser, token: string, uid: string) {
+ const r = await fetch(root() + "/api/v1/admin/user/" + uid, {
+ method: "PATCH",
+ headers: {
+ "Authorization": "Bearer " + token
+ },
+ body: JSON.stringify(u)
+ })
+ return await apiGet(r)
+}
+
+export async function sendRegEmail(email: string, captchaToken: string) {
+ const r = await fetch(root() + "/api/v1/user/reg_email", {
+ method: "POST",
+ body: JSON.stringify({
+ "email": email,
+ "captchaToken": captchaToken
+ })
+ })
+ return await apiGet(r)
+}
+
+export async function sendForgotEmail(email: string, captchaToken: string) {
+ const r = await fetch(root() + "/api/v1/user/forgot_email", {
+ method: "POST",
+ body: JSON.stringify({
+ "email": email,
+ "captchaToken": captchaToken
+ })
+ })
+ return await apiGet(r)
+}
+
+
+export async function forgotPassWord(email: string, emailJwt: string, password: string) {
+ const r = await fetch(root() + "/api/v1/user/forgot", {
+ method: "POST",
+ body: JSON.stringify({
+ "email": email,
+ "emailJwt": emailJwt,
+ "passWord": password,
+ })
+ })
+ return await apiGet(r)
+}
\ No newline at end of file
diff --git a/frontend/src/apis/error.ts b/frontend/src/apis/error.ts
new file mode 100644
index 0000000..58c962b
--- /dev/null
+++ b/frontend/src/apis/error.ts
@@ -0,0 +1,8 @@
+export class ApiErr extends Error {
+ readonly code: number
+
+ constructor(code: number, msg: string) {
+ super(msg)
+ this.code = code
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/apis/model.ts b/frontend/src/apis/model.ts
new file mode 100644
index 0000000..5dc0828
--- /dev/null
+++ b/frontend/src/apis/model.ts
@@ -0,0 +1,66 @@
+export interface tokenData {
+ token: string
+ name: string
+ uuid: string
+}
+
+export interface Api {
+ code: number
+ msg: string
+ data: T
+}
+
+export interface List {
+ total: number
+ list: T[]
+}
+
+
+interface captcha {
+ type: string
+ siteKey: string
+}
+
+
+export interface ApiUser {
+ uid: string
+ uuid: string
+ is_admin: boolean
+}
+
+export interface YggProfile {
+ name: string
+ properties: {
+ name: string
+ value: string
+ }[]
+}
+
+export interface ApiConfig {
+ captcha: captcha
+ AllowChangeName: boolean
+ serverName: string
+ NeedEmail: boolean
+ AllowDomain: string[]
+ EmailReg: string
+ EmailRegMsg: string
+}
+
+export interface UserInfo {
+ uid: number
+ uuid: string
+ is_admin: boolean
+ is_disable: boolean
+ email: string
+ reg_ip: string
+ name: string
+}
+
+export interface EditUser {
+ email?: string
+ name?: string
+ password?: string
+ is_admin?: boolean
+ is_disable?: boolean
+ del_textures?: boolean
+}
\ No newline at end of file
diff --git a/frontend/src/apis/utils.ts b/frontend/src/apis/utils.ts
new file mode 100644
index 0000000..be66411
--- /dev/null
+++ b/frontend/src/apis/utils.ts
@@ -0,0 +1,10 @@
+import { ApiErr } from "./error"
+
+export async function apiGet(v: Response) {
+ type api = { data: T, msg: string, code: number }
+ const data = await v.json() as api
+ if (!v.ok) {
+ throw new ApiErr(data.code, data.msg)
+ }
+ return data.data
+}
diff --git a/frontend/src/assets/react.svg b/frontend/src/assets/react.svg
deleted file mode 100644
index 6c87de9..0000000
--- a/frontend/src/assets/react.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/frontend/src/components/CaptchaWidget.tsx b/frontend/src/components/CaptchaWidget.tsx
new file mode 100644
index 0000000..c24cfcc
--- /dev/null
+++ b/frontend/src/components/CaptchaWidget.tsx
@@ -0,0 +1,65 @@
+import { Turnstile } from '@marsidev/react-turnstile'
+import Button from '@mui/material/Button'
+import { useRef, useState, memo, forwardRef, useImperativeHandle, useEffect } from 'react'
+import type { TurnstileInstance } from '@marsidev/react-turnstile'
+import Alert from '@mui/material/Alert';
+import Skeleton from '@mui/material/Skeleton';
+import { useRequest } from 'ahooks';
+import { getConfig } from '@/apis/apis';
+
+interface prop {
+ onSuccess: ((token: string) => void)
+}
+
+export type refType = {
+ reload: () => void
+}
+
+
+const CaptchaWidget = forwardRef(({ onSuccess }, ref) => {
+ const Turnstileref = useRef(null)
+ const [key, setKey] = useState(1)
+ const { data, error, loading } = useRequest(getConfig, {
+ cacheKey: "/api/v1/config",
+ staleTime: 600000,
+ loadingDelay: 200
+ })
+
+ useImperativeHandle(ref, () => {
+ return {
+ reload: () => {
+ setKey(key + 1)
+ }
+ }
+ })
+ useEffect(() => {
+ if (data?.captcha?.type != "turnstile") {
+ onSuccess("ok")
+ return
+ }
+ }, [data?.captcha?.type, onSuccess])
+
+
+ if (error) {
+ console.warn(error)
+ return {String(error)}
+ }
+ if (!data && loading) {
+ return
+ }
+
+ if (data?.captcha.type == "") {
+ return <>>
+ }
+
+ return (
+ <>
+
+
+ >
+ )
+})
+
+const CaptchaWidgetMemo = memo(CaptchaWidget)
+
+export default CaptchaWidgetMemo
\ No newline at end of file
diff --git a/frontend/src/components/CheckInput.tsx b/frontend/src/components/CheckInput.tsx
new file mode 100644
index 0000000..e323714
--- /dev/null
+++ b/frontend/src/components/CheckInput.tsx
@@ -0,0 +1,65 @@
+import TextField from '@mui/material/TextField';
+import { useState, useImperativeHandle, forwardRef } from 'react';
+import type { TextFieldProps } from '@mui/material/TextField';
+import { useControllableValue } from 'ahooks';
+
+export type refType = {
+ verify: () => boolean
+}
+
+type prop = {
+ checkList: {
+ errMsg: string
+ reg: RegExp
+ }[]
+} & Omit, 'helperText'>
+
+export const CheckInput = forwardRef(({ required, checkList, ...textFied }, ref) => {
+ const [err, setErr] = useState("");
+ const [value, setValue] = useControllableValue(textFied);
+
+
+ const check = (value: string) => {
+ if (required && (!value || value == "")) {
+ setErr("此项必填")
+ return false
+ }
+ for (const v of checkList) {
+ if (!v.reg.test(value)) {
+ setErr(v.errMsg)
+ return false
+ }
+ }
+ setErr("")
+ return true
+ }
+
+ const verify = () => {
+ return check(value)
+ }
+
+ useImperativeHandle(ref, () => {
+ return {
+ verify
+ }
+ })
+
+ const onChange = (event: React.ChangeEvent) => {
+ const value = event.target.value
+ setValue(value)
+ check(value)
+ }
+
+
+
+ return
+})
+
+export default CheckInput
\ No newline at end of file
diff --git a/frontend/src/components/Loading.tsx b/frontend/src/components/Loading.tsx
new file mode 100644
index 0000000..9b09deb
--- /dev/null
+++ b/frontend/src/components/Loading.tsx
@@ -0,0 +1,15 @@
+import Backdrop from "@mui/material/Backdrop";
+import CircularProgress from "@mui/material/CircularProgress";
+
+export default function Loading() {
+ return (
+ <>
+ theme.zIndex.modal + 1 }}
+ open={true}
+ >
+
+
+ >
+ )
+}
diff --git a/frontend/src/components/NeedLogin.tsx b/frontend/src/components/NeedLogin.tsx
new file mode 100644
index 0000000..b7b38b9
--- /dev/null
+++ b/frontend/src/components/NeedLogin.tsx
@@ -0,0 +1,41 @@
+import { userInfo } from "@/apis/apis";
+import { ApiErr } from "@/apis/error";
+import { token } from "@/store/store";
+import { useRequest } from "ahooks";
+import { useAtomValue } from "jotai";
+import { useEffect } from "react";
+import { useNavigate, Navigate } from "react-router-dom";
+
+
+export default function NeedLogin({ children, needAdmin = false }: { children: JSX.Element, needAdmin?: boolean }) {
+ const t = useAtomValue(token)
+ const navigate = useNavigate();
+ const u = useRequest(() => userInfo(t), {
+ refreshDeps: [t],
+ cacheKey: "/api/v1/user" + t,
+ staleTime: 60000,
+ onError: e => {
+ if (e instanceof ApiErr && e.code == 5) {
+ navigate("/login")
+ }
+ console.warn(e)
+ }
+ })
+
+ useEffect(() => {
+ if (!u.data) return
+ if (!u.data.is_admin && needAdmin) {
+ navigate("/login")
+ }
+ if (u.data.uuid == "") {
+ navigate("/login")
+ }
+ }, [navigate, needAdmin, u.data])
+
+ if (!localStorage.getItem("token") || localStorage.getItem("token") == '""') {
+ return
+ }
+
+
+ return <> {children}>
+}
\ No newline at end of file
diff --git a/frontend/src/components/SkinViewUUID.tsx b/frontend/src/components/SkinViewUUID.tsx
new file mode 100644
index 0000000..d68b300
--- /dev/null
+++ b/frontend/src/components/SkinViewUUID.tsx
@@ -0,0 +1,89 @@
+import { yggProfile } from "@/apis/apis";
+import { decodeSkin } from "@/utils/skin";
+import Skeleton from "@mui/material/Skeleton";
+import { useHover, useMemoizedFn, useRequest, useUnmount } from "ahooks";
+import { memo, useEffect, useRef, useState } from "react";
+import ReactSkinview3d, { ReactSkinview3dOptions } from "@/components/Skinview3d";
+import { SkinViewer, WalkingAnimation } from "skinview3d";
+import Box from "@mui/material/Box";
+import Typography from "@mui/material/Typography";
+
+interface prop {
+ uuid: string
+ width: number
+ height: number
+}
+
+const SkinViewUUID = memo(function SkinViewUUID({ uuid, width, height }: prop) {
+ const [textures, setTextures] = useState({ skin: "", cape: "", model: "default" })
+ const [err, setErr] = useState("")
+
+ const SkinInfo = useRequest(() => yggProfile(uuid), {
+ cacheKey: "/api/yggdrasil/sessionserver/session/minecraft/profile/" + uuid,
+ onError: e => {
+ console.warn(e)
+ setErr(String(e))
+ },
+ refreshDeps: [uuid],
+ })
+
+ useEffect(() => {
+ if (!SkinInfo.data) return
+ const [skin, cape, model] = decodeSkin(SkinInfo.data)
+ setTextures({ cape: cape, skin: skin, model: model })
+ }, [SkinInfo.data])
+
+ if (err != "") {
+ return {err}
+ }
+ return (<>
+ {
+ (SkinInfo.loading && !SkinInfo.data) ?
+ : (textures.skin != "" || textures.cape != "") ? (
+ ) :
+ 还没有设置皮肤
+
+ }
+ >)
+})
+
+
+const MySkin = function MySkin(p: ReactSkinview3dOptions) {
+ const refSkinview3d = useRef(null);
+ const skinisHovering = useHover(refSkinview3d);
+ const skinview3dView = useRef(null);
+
+ useEffect(() => {
+ if (skinview3dView.current) {
+ skinview3dView.current.autoRotate = !skinisHovering
+ }
+ if (skinview3dView.current?.animation) {
+ skinview3dView.current.animation.paused = skinisHovering
+ }
+ }, [skinisHovering])
+
+ useUnmount(() => {
+ skinview3dView.current?.dispose()
+ })
+
+ const handelOnReady = useMemoizedFn(v => {
+ v.viewer.animation = new WalkingAnimation()
+ v.viewer.autoRotate = true
+ skinview3dView.current = v.viewer
+ })
+
+ return
+
+
+}
+
+export default SkinViewUUID
\ No newline at end of file
diff --git a/frontend/src/components/Skinview3d.tsx b/frontend/src/components/Skinview3d.tsx
new file mode 100644
index 0000000..b4fdcc8
--- /dev/null
+++ b/frontend/src/components/Skinview3d.tsx
@@ -0,0 +1,101 @@
+import { memo, useEffect, useRef } from "react";
+import { SkinViewer, SkinViewerOptions } from "skinview3d";
+
+// https://github.com/Hacksore/react-skinview3d/blob/master/src/index.tsx
+
+/**
+ * This is the interface that describes the parameter in `onReady`
+ */
+export interface ViewerReadyCallbackOptions {
+ /**
+ * The instance of the skinview3d
+ */
+ viewer: SkinViewer;
+ /**
+ * The ref to the canvas element
+ */
+ canvasRef: HTMLCanvasElement;
+}
+
+export interface ReactSkinview3dOptions {
+ /**
+ * The class names to apply to the canvas
+ */
+ className?: string;
+ /**
+ * The width of the canvas
+ */
+ width: number | string;
+ /**
+ * The height of the canvas
+ */
+ height: number | string;
+ /**
+ * The skin to load in the canvas
+ */
+ skinUrl: string;
+ /**
+ * The cape to load in the canvas
+ */
+ capeUrl?: string;
+ /**
+ * A function that is called when the skin viewer is ready
+ * @param {SkinViewer} instance callback function to execute when the viewer is loaded {@link SkinViewer}
+ * @example
+ * onReady((instance) => {
+ * console.log(instance)
+ * })
+ */
+ onReady?: ({ viewer, canvasRef }: ViewerReadyCallbackOptions) => void;
+ /**
+ * Parameters passed to the skinview3d constructor allowing you to override or add extra features
+ * @notes please take a look at the upstream repo for more info
+ * [bs-community/skinview3d](https://bs-community.github.io/skinview3d/)
+ */
+ options?: SkinViewerOptions;
+}
+
+/**
+ * A skinview3d component
+ */
+const ReactSkinview3d = memo(function ReactSkinview3d({
+ className,
+ width,
+ height,
+ skinUrl,
+ capeUrl,
+ onReady,
+ options,
+}: ReactSkinview3dOptions) {
+ const canvasRef = useRef(null);
+ const skinviewRef = useRef();
+
+ useEffect(() => {
+ if (!canvasRef.current) return
+
+ const viewer = new SkinViewer({
+ canvas: canvasRef.current,
+ width: Number(width),
+ height: Number(height),
+ ...options,
+ });
+
+ // handle cape/skin load initially
+ skinUrl && viewer.loadSkin(skinUrl, { model: options?.model ?? "auto-detect" });
+ capeUrl && viewer.loadCape(capeUrl);
+
+ skinviewRef.current = viewer;
+
+ // call onReady with the viewer instance
+ if (onReady) {
+ onReady({ viewer: skinviewRef.current, canvasRef: canvasRef.current });
+ }
+
+ return () => viewer.dispose()
+ }, [capeUrl, height, onReady, options, skinUrl, width]);
+
+
+ return ;
+})
+
+export default ReactSkinview3d;
\ No newline at end of file
diff --git a/frontend/src/hooks/useTitle.ts b/frontend/src/hooks/useTitle.ts
new file mode 100644
index 0000000..2ec60da
--- /dev/null
+++ b/frontend/src/hooks/useTitle.ts
@@ -0,0 +1,16 @@
+import { getConfig } from '@/apis/apis'
+import { useTitle as auseTitle, useRequest } from 'ahooks'
+import { useEffect } from 'react'
+
+export default function useTitle(title: string) {
+ const { data, error } = useRequest(getConfig, {
+ cacheKey: "/api/v1/config",
+ staleTime: 60000,
+ })
+ useEffect(() => {
+ error && console.warn(error)
+ }, [error])
+ auseTitle(title + " - " + data?.serverName, {
+ restoreOnUnmount: true
+ })
+}
\ No newline at end of file
diff --git a/frontend/src/index.css b/frontend/src/index.css
deleted file mode 100644
index 6119ad9..0000000
--- a/frontend/src/index.css
+++ /dev/null
@@ -1,68 +0,0 @@
-:root {
- font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
- line-height: 1.5;
- font-weight: 400;
-
- color-scheme: light dark;
- color: rgba(255, 255, 255, 0.87);
- background-color: #242424;
-
- font-synthesis: none;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-a {
- font-weight: 500;
- color: #646cff;
- text-decoration: inherit;
-}
-a:hover {
- color: #535bf2;
-}
-
-body {
- margin: 0;
- display: flex;
- place-items: center;
- min-width: 320px;
- min-height: 100vh;
-}
-
-h1 {
- font-size: 3.2em;
- line-height: 1.1;
-}
-
-button {
- border-radius: 8px;
- border: 1px solid transparent;
- padding: 0.6em 1.2em;
- font-size: 1em;
- font-weight: 500;
- font-family: inherit;
- background-color: #1a1a1a;
- cursor: pointer;
- transition: border-color 0.25s;
-}
-button:hover {
- border-color: #646cff;
-}
-button:focus,
-button:focus-visible {
- outline: 4px auto -webkit-focus-ring-color;
-}
-
-@media (prefers-color-scheme: light) {
- :root {
- color: #213547;
- background-color: #ffffff;
- }
- a:hover {
- color: #747bff;
- }
- button {
- background-color: #f9f9f9;
- }
-}
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
index bef5202..30c9a76 100644
--- a/frontend/src/main.tsx
+++ b/frontend/src/main.tsx
@@ -1,10 +1,11 @@
-import { StrictMode } from 'react'
-import { createRoot } from 'react-dom/client'
-import './index.css'
+import React from 'react'
+import ReactDOM from 'react-dom/client'
import App from './App.tsx'
+import CssBaseline from '@mui/material/CssBaseline';
-createRoot(document.getElementById('root')!).render(
-
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
- ,
+
)
diff --git a/frontend/src/store/store.ts b/frontend/src/store/store.ts
new file mode 100644
index 0000000..00bc090
--- /dev/null
+++ b/frontend/src/store/store.ts
@@ -0,0 +1,10 @@
+import { atom } from 'jotai'
+import { atomWithStorage } from 'jotai/utils'
+
+export const token = atomWithStorage("token", "")
+export const user = atomWithStorage("username", {
+ name: "",
+ uuid: ""
+})
+
+export const LayoutAlertErr = atom("")
\ No newline at end of file
diff --git a/frontend/src/utils/email.ts b/frontend/src/utils/email.ts
new file mode 100644
index 0000000..2d88b7d
--- /dev/null
+++ b/frontend/src/utils/email.ts
@@ -0,0 +1,3 @@
+export function checkEmail(email: string) {
+ return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email);
+}
\ No newline at end of file
diff --git a/frontend/src/utils/root.ts b/frontend/src/utils/root.ts
new file mode 100644
index 0000000..d5d67a1
--- /dev/null
+++ b/frontend/src/utils/root.ts
@@ -0,0 +1,6 @@
+export default function root() {
+ if (import.meta.env.VITE_APIADDR != "") {
+ return import.meta.env.VITE_APIADDR
+ }
+ return location.origin
+}
\ No newline at end of file
diff --git a/frontend/src/utils/skin.ts b/frontend/src/utils/skin.ts
new file mode 100644
index 0000000..53b9295
--- /dev/null
+++ b/frontend/src/utils/skin.ts
@@ -0,0 +1,17 @@
+import { YggProfile } from "@/apis/model";
+
+export function decodeSkin(y: YggProfile) {
+ if (y.properties.length == 0) {
+ return ["", "", ""]
+ }
+ const p = y.properties.find(v => v.name == "textures")
+ if (!p?.value || p?.value == "") {
+ return ["", "", ""]
+ }
+ const textures = JSON.parse(atob(p.value))
+
+ const skin = textures?.textures?.SKIN?.url as string ?? ""
+ const cape = textures?.textures?.CAPE?.url as string ?? ""
+ const model = textures?.textures?.SKIN?.metadata?.model as string ?? "default"
+ return [skin, cape, model]
+}
\ No newline at end of file
diff --git a/frontend/src/views/Forgot.tsx b/frontend/src/views/Forgot.tsx
new file mode 100644
index 0000000..65ad9ec
--- /dev/null
+++ b/frontend/src/views/Forgot.tsx
@@ -0,0 +1,120 @@
+import Avatar from '@mui/material/Avatar';
+import Button from '@mui/material/Button';
+import CssBaseline from '@mui/material/CssBaseline';
+import Grid from '@mui/material/Grid';
+import Box from '@mui/material/Box';
+import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
+import Typography from '@mui/material/Typography';
+import Container from '@mui/material/Container';
+import TextField from '@mui/material/TextField';
+import { useTitle } from 'ahooks';
+import { useEffect, useState } from 'react';
+import Snackbar from '@mui/material/Snackbar';
+import Alert from '@mui/material/Alert';
+import Loading from '@/components/Loading';
+import { produce } from 'immer';
+import { forgotPassWord } from '@/apis/apis';
+import { useNavigate } from 'react-router-dom';
+
+export default function Forgot() {
+ const [err, setErr] = useState("")
+ useTitle("重设密码")
+ const [passerr, setPasserr] = useState("")
+ const [pass, setPass] = useState({
+ pass1: "",
+ pass2: "",
+ })
+ const [load, setLoad] = useState(false)
+ const [email, setEmail] = useState("")
+ const [code, setCode] = useState("")
+ const navigate = useNavigate();
+
+ useEffect(() => {
+ if (pass.pass1 != pass.pass2 && pass.pass2 != "") {
+ setPasserr("密码不相等")
+ return
+ }
+ setPasserr("")
+ }, [pass.pass1, pass.pass2])
+
+ const u = new URL(location.href)
+
+ useEffect(() => {
+ setEmail(u.searchParams.get("email") ?? "")
+ setCode(u.searchParams.get("code") ?? "")
+ }, [u.searchParams])
+
+
+ const onSubmit = (e: React.FormEvent) => {
+ e.preventDefault()
+ setLoad(true)
+ forgotPassWord(email, code, pass.pass1).then(() => {
+ navigate("/")
+ }).catch(e => {
+ setErr(String(e))
+ }).finally(() => { setLoad(false) })
+ }
+
+
+ return (
+
+
+
+
+
+
+
+ 找回密码
+
+
+
+
+ setPass(produce(v => { v.pass1 = p.target.value }))}
+ autoComplete="new-password"
+ />
+
+
+ setPass(produce(v => { v.pass2 = p.target.value }))}
+ autoComplete="new-password"
+ />
+
+
+
+
+
+
+ setErr("")} severity="error">{err}
+
+
+ {load && }
+
+ )
+}
\ No newline at end of file
diff --git a/frontend/src/views/Index.tsx b/frontend/src/views/Index.tsx
new file mode 100644
index 0000000..cc1cccc
--- /dev/null
+++ b/frontend/src/views/Index.tsx
@@ -0,0 +1,9 @@
+import Profile from "@/views/profile/Profile"
+import Login from "@/views/Login"
+
+export default function Index() {
+ if (localStorage.getItem("token") && localStorage.getItem("token") != '""') {
+ return
+ }
+ return
+}
\ No newline at end of file
diff --git a/frontend/src/views/Layout.tsx b/frontend/src/views/Layout.tsx
new file mode 100644
index 0000000..87555b8
--- /dev/null
+++ b/frontend/src/views/Layout.tsx
@@ -0,0 +1,291 @@
+import * as React from 'react';
+import { styled, useTheme } from '@mui/material/styles';
+import Box from '@mui/material/Box';
+import Drawer from '@mui/material/Drawer';
+import Toolbar from '@mui/material/Toolbar';
+import List from '@mui/material/List';
+import Divider from '@mui/material/Divider';
+import IconButton from '@mui/material/IconButton';
+import MenuIcon from '@mui/icons-material/Menu';
+import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
+import ChevronRightIcon from '@mui/icons-material/ChevronRight';
+import ListItem from '@mui/material/ListItem';
+import ListItemButton from '@mui/material/ListItemButton';
+import ListItemIcon from '@mui/material/ListItemIcon';
+import ListItemText from '@mui/material/ListItemText';
+import AppBar from '@mui/material/AppBar';
+import { Outlet } from 'react-router-dom';
+import { AccountCircle } from '@mui/icons-material';
+import Menu from '@mui/material/Menu';
+import MenuItem from '@mui/material/MenuItem';
+import { LayoutAlertErr, token, user } from '@/store/store';
+import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
+import Button from '@mui/material/Button';
+import { useNavigate } from "react-router-dom";
+import { useRequest, useMemoizedFn } from 'ahooks';
+import { getConfig, userInfo } from '@/apis/apis'
+import Snackbar from '@mui/material/Snackbar';
+import Alert from '@mui/material/Alert';
+import { memo } from 'react';
+import useMediaQuery from '@mui/material/useMediaQuery';
+import Typography from '@mui/material/Typography';
+import Container from '@mui/material/Container';
+import PersonIcon from '@mui/icons-material/Person';
+import SecurityIcon from '@mui/icons-material/Security';
+import SettingsIcon from '@mui/icons-material/Settings';
+import { Link } from "react-router-dom";
+import GroupIcon from '@mui/icons-material/Group';
+import { ApiErr } from '@/apis/error';
+
+const drawerWidth = 240;
+const DrawerOpen = atom(false)
+
+const DrawerHeader = styled('div')(({ theme }) => ({
+ display: 'flex',
+ alignItems: 'center',
+ padding: theme.spacing(0, 1),
+ // necessary for content to be below app bar
+ ...theme.mixins.toolbar,
+ justifyContent: 'flex-end',
+}));
+
+interface ListItem {
+ icon: JSX.Element
+ title: string
+ link: string
+}
+
+const Layout = memo(function Layout() {
+ const theme = useTheme();
+ const [err, setErr] = useAtom(LayoutAlertErr)
+
+ return (<>
+
+
+
+
+
+
+ setErr("")} severity="error">{err}
+
+
+
+
+
+
+
+
+ >)
+})
+
+const MyToolbar = memo(function MyToolbar() {
+ const [nowUser, setNowUser] = useAtom(user)
+ const [anchorEl, setAnchorEl] = React.useState(null);
+ const navigate = useNavigate();
+ const setToken = useSetAtom(token)
+ const setErr = useSetAtom(LayoutAlertErr)
+ const setOpen = useSetAtom(DrawerOpen)
+
+ const server = useRequest(getConfig, {
+ cacheKey: "/api/v1/config",
+ staleTime: 60000,
+ onError: e => {
+ console.warn(e)
+ setErr(String(e))
+ }
+ })
+
+
+ const handleLogOut = useMemoizedFn(() => {
+ setAnchorEl(null);
+ setNowUser({ name: "", uuid: "" })
+ setToken("")
+ navigate("/login")
+ })
+
+
+
+ return (
+ <>
+
+ {nowUser.name != "" && (<>
+ setOpen(true)}
+ >
+
+
+ >)
+ }
+
+
+ {server.data?.serverName ?? "皮肤站"}
+
+
+ {nowUser.name != "" && (
+
+
setAnchorEl(event.currentTarget)}
+ color="inherit"
+ >
+
+
+
+
+ )}
+ {nowUser.name == "" && (
+
+ )}
+
+ >)
+})
+
+const MyList = memo(function MyList(p: { list: ListItem[] }) {
+
+
+ return (
+ <>
+
+ {p.list.map(item =>
+
+ )}
+
+ >
+ )
+})
+
+const MyListItem = function MyListItem(p: ListItem) {
+ const navigate = useNavigate();
+
+ const handleClick = () => {
+ navigate(p.link)
+ }
+
+ return (
+
+
+
+ {p.icon}
+
+
+
+
+ )
+}
+
+const MyDrawer = function MyDrawer() {
+ const nowToken = useAtomValue(token)
+ const setErr = useSetAtom(LayoutAlertErr)
+ const theme = useTheme();
+ const isLg = useMediaQuery(theme.breakpoints.up('lg'))
+ const [open, setOpen] = useAtom(DrawerOpen)
+ const navigate = useNavigate();
+
+ const userinfo = useRequest(() => userInfo(nowToken), {
+ refreshDeps: [nowToken],
+ cacheKey: "/api/v1/user" + nowToken,
+ staleTime: 60000,
+ onError: e => {
+ if (e instanceof ApiErr && e.code == 5) {
+ navigate("/login")
+ }
+ console.warn(e)
+ setErr(String(e))
+ },
+ })
+
+ const userDrawerList = React.useMemo(() => [
+ {
+ icon: ,
+ title: '个人信息',
+ link: '/profile'
+ },
+ {
+ icon: ,
+ title: '皮肤设置',
+ link: '/textures'
+ },
+ {
+ icon: ,
+ title: '账号设置',
+ link: '/security'
+ }
+ ] as ListItem[], [])
+
+ const adminDrawerList = React.useMemo(() => [
+ {
+ icon: ,
+ title: '用户管理',
+ link: '/admin/user'
+ }
+ ] as ListItem[], [])
+
+
+
+ return (<>
+ {userinfo.data && (
+ setOpen(false)}
+ >
+
+ setOpen(false)}>
+ {theme.direction === 'ltr' ? : }
+
+
+
+
+ {userinfo.data?.is_admin && (
+ <>
+
+
+ >)}
+
+ )}
+ >)
+}
+
+export default Layout
\ No newline at end of file
diff --git a/frontend/src/views/Login.tsx b/frontend/src/views/Login.tsx
new file mode 100644
index 0000000..8d1127d
--- /dev/null
+++ b/frontend/src/views/Login.tsx
@@ -0,0 +1,169 @@
+import * as React from 'react';
+import { useState } from 'react';
+import Avatar from '@mui/material/Avatar';
+import Button from '@mui/material/Button';
+import TextField from '@mui/material/TextField';
+import Link from '@mui/material/Link';
+import Grid from '@mui/material/Grid';
+import Box from '@mui/material/Box';
+import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
+import Typography from '@mui/material/Typography';
+import Container from '@mui/material/Container';
+import Snackbar from '@mui/material/Snackbar';
+import Alert from '@mui/material/Alert';
+import { useSetAtom } from 'jotai';
+import { token, user } from '@/store/store'
+import { getConfig, login } from '@/apis/apis'
+import { Link as RouterLink, useNavigate } from "react-router-dom";
+import Loading from '@/components/Loading'
+import CheckInput, { refType } from '@/components/CheckInput'
+import useTitle from '@/hooks/useTitle';
+import CaptchaWidget from '@/components/CaptchaWidget';
+import type { refType as CaptchaWidgetRef } from '@/components/CaptchaWidget'
+import { ApiErr } from '@/apis/error';
+import { useRequest } from 'ahooks';
+
+
+
+export default function SignIn() {
+ const [err, setErr] = useState("");
+ const [loading, setLoading] = useState(false);
+ const setToken = useSetAtom(token)
+ const setUserInfo = useSetAtom(user)
+ const checkList = React.useRef