diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 45d93f8..e399209 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -18,7 +18,15 @@ jobs:
uses: actions/checkout@v3
with:
fetch-depth: 0
-
+ - name: Setup NodeJS
+ uses: actions/setup-node@v3
+ with:
+ node-version: '18.x'
+ cache: 'yarn'
+ cache-dependency-path: frontend
+ - name: Build Frontend
+ run: |
+ make assets
- name: Build Yggdrasil Server
uses: crazy-max/ghaction-xgo@v2
with:
diff --git a/.gitignore b/.gitignore
index a70cd10..46a031d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,7 @@
# Dependency directories (remove the comment below to include it)
# vendor/
+assets
yggdrasil
/*.pem
/*.db
diff --git a/Makefile b/Makefile
index 1dbd2d6..e3d6a10 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,12 @@ $(BINARY):
get:
$(GO_GET)
+assets:
+ mkdir -p assets
+ yarn --cwd frontend install --frozen-lockfile --non-interactive
+ yarn --cwd frontend build
+ cp -r frontend/dist/. assets/
+
package:$(BINARY)
tar -zcf $(PACKAGE_NAME) $(BINARY) config_example.ini
diff --git a/README.md b/README.md
index 04a99c1..4de07b8 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@
启动成功后在启动器(请使用第三方启动器)外置登录选项上填写运行的 URL 的根路径,比如 `http://localhost:8080`。
-注册地址在 `/profile/index.html`。
+注册地址在 `/profile/`。
## Docker
diff --git a/assets/index.html b/assets/index.html
deleted file mode 100644
index 3c41372..0000000
--- a/assets/index.html
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
-
-
-
-
-
- 注册
-
-
-
-
-
-
-
- You need to enable JavaScript to run this app.
-
-
-
-
-
-
-
-
-
diff --git a/assets/login.js b/assets/login.js
deleted file mode 100644
index ccc080e..0000000
--- a/assets/login.js
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2022. Gardel and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-const MDCSnackbar = mdc.snackbar.MDCSnackbar;
-const MDCTextField = mdc.textField.MDCTextField;
-const MDCRipple = mdc.ripple.MDCRipple;
-
-const snackbar = new MDCSnackbar(document.querySelector(".mdc-snackbar"));
-const username = new MDCTextField(document.querySelector(".username"));
-const password = new MDCTextField(document.querySelector(".password"));
-const profileName = new MDCTextField(document.querySelector(".profileName"));
-
-new MDCRipple(document.querySelector(".next"));
-
-snackbar.close();
-
-var login = false;
-
-$(".login").click(function (btn) {
- login = true;
- $(".profileName").hide();
- $("#profileName-input").removeAttr("required");
- $(".next").children(".mdc-button__label").text("登录");
- $(this).hide();
-});
-
-$("#reg-form").submit(function (e) {
- if (!login) {
- $.ajax({
- url: "/authserver/register",
- type: "POST",
- dataType: "JSON",
- contentType: "application/json",
- data: JSON.stringify({
- username: username.value,
- password: password.value,
- profileName: profileName.value
- }),
- success: function (data) {
- if (!data.id) {
- if (data.errorMessage) snackbar.labelText = data.errorMessage;
- snackbar.open();
- } else {
- login = true;
- $(".profileName").hide();
- $(".login").hide();
- $(".next").children(".mdc-button__label").text("登录");
- snackbar.timeoutMs = 10000;
- snackbar.labelText = "注册成功,uid:" + data.id;
- snackbar.open();
- localStorage.uuid = data.id;
- }
- },
- error: function (e) {
- let response = JSON.parse(e.responseText);
- if (response.errorMessage === "profileName exist") {
- snackbar.labelText = "注册失败: 角色名已存在";
- } else if (response.errorMessage === "profileName duplicate") {
- snackbar.labelText = "注册失败: 角色名与正版用户冲突";
- } else {
- snackbar.labelText = "注册失败: " + response.errorMessage;
- }
- snackbar.open();
- }
- });
- } else {
- $.ajax({
- url: "/authserver/authenticate",
- type: "POST",
- dataType: "JSON",
- contentType: "application/json",
- data: JSON.stringify({
- username: username.value,
- password: password.value
- }),
- success: function (data) {
- if (!data.accessToken) {
- snackbar.labelText = "登录失败:";
- if (data.errorMessage) snackbar.labelText += data.errorMessage;
- snackbar.open();
- } else {
- snackbar.timeoutMs = 5000;
- snackbar.labelText = "登录成功,accessToken:" + data.accessToken;
- snackbar.open();
- localStorage.accessToken = data.accessToken;
- localStorage.loginTime = new Date().getTime();
- localStorage.profileName = data.selectedProfile.name;
- if (data.selectedProfile) {
- localStorage.profileName = data.selectedProfile.name;
- localStorage.uuid = data.selectedProfile.id;
- }
- // localStorage.username = username.value;
- // localStorage.password = password.value;
- setTimeout(function () {
- window.location = "user.html";
- }, 3000);
- }
- },
- error: function (e) {
- let response = JSON.parse(e.responseText);
- snackbar.labelText = "登录失败: " + response.errorMessage;
- snackbar.open();
- }
- });
- }
-
- e.preventDefault();
-});
-
-$(document).ready(function () {
- if (!localStorage.accessToken && localStorage.loginTime !== undefined &&
- (new Date().getTime() - localStorage.loginTime) < 30 * 86400 * 1000) {
- window.location = "user.html";
- }
-});
diff --git a/assets/user.html b/assets/user.html
deleted file mode 100644
index 64cfceb..0000000
--- a/assets/user.html
+++ /dev/null
@@ -1,154 +0,0 @@
-
-
-
-
-
-
-
- 角色信息
-
-
-
-
-
-
-
-You need to enable JavaScript to run this app.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/user.js b/assets/user.js
deleted file mode 100644
index f88b1e8..0000000
--- a/assets/user.js
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2022. Gardel and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-const MDCSnackbar = mdc.snackbar.MDCSnackbar;
-const MDCTextField = mdc.textField.MDCTextField;
-const MDCFormField = mdc.formField.MDCFormField;
-const MDCRadio = mdc.radio.MDCRadio;
-//const MDCRipple = mdc.ripple.MDCRipple;
-
-const snackbar = new MDCSnackbar(document.querySelector('.mdc-snackbar'));
-const modelField = new MDCFormField(document.querySelector('.model'));
-const radio1 = new MDCRadio(document.querySelector('#radio-steve'));
-const radio2 = new MDCRadio(document.querySelector('#radio-alex'));
-const radio3 = new MDCRadio(document.querySelector('#radio-skin'));
-const radio4 = new MDCRadio(document.querySelector('#radio-cape'));
-modelField.input = {radio1, radio2};
-const url = new MDCTextField(document.querySelector('.url'));
-const file = new MDCTextField(document.querySelector('.file'));
-const changeTo = new MDCTextField(document.querySelector('.changeTo'));
-
-const modelTypeForm = document.querySelector('.mdc-form-field.model');
-
-snackbar.close()
-
-$("#file-input").change(function() {
- const path = this.value;
- if (!path) {
- $("#file-path").text("或选择一张图片");
- $(".url").show();
- } else {
- $("#file-path").text(path);
- url.value = '';
- $(".url").hide();
- }
-});
-
-const modelTypeChange = function () {
- if (radio3.checked) {
- $(modelTypeForm).show();
- } else {
- $(modelTypeForm).hide();
- }
-}
-$("#radio-3").change(modelTypeChange)
-$("#radio-4").change(modelTypeChange)
-
-$("#url-input").on("input", function() {
- const url = this.value;
- if (!url) {
- $(".file").show();
- } else {
- file.value = '';
- $(".file").hide();
- }
-});
-
-$(document).ready(function() {
- if (!localStorage.accessToken) {
- localStorage.loginTime = 1;
- window.location = "index.html";
- }
- $.ajax({
- url: '/authserver/validate',
- type: 'POST',
- dataType: "JSON",
- contentType: "application/json",
- data: JSON.stringify({
- accessToken: localStorage.accessToken,
- }),
- success: function(data) {
- //有效,啥也不整
- },
- error: function(e) {
- if (e.status == 403) {
- // 持续套娃
- $.ajax({
- url: '/authserver/refresh',
- type: 'POST',
- dataType: "JSON",
- contentType: "application/json",
- data: JSON.stringify({
- accessToken: localStorage.accessToken,
- }),
- success: function(data) {
- if (!data.accessToken) {
- localStorage.loginTime = 1;
- window.location = "index.html";
- } else {
- snackbar.timeoutMs = 5000;
- snackbar.labelText = "刷新token成功,accessToken:" + data.accessToken;
- snackbar.open();
- localStorage.accessToken = data.accessToken;
- localStorage.loginTime = new Date().getTime();
- if(data.selectedProfile) {
- localStorage.profileName = data.selectedProfile.name;
- localStorage.uuid = data.selectedProfile.id;
- }
- }
- },
- error: function(e) {
- if (e.status == 403) {
- localStorage.loginTime = 1;
- window.location = "index.html";
- }
- }
- });
- }
- }
- });
-});
-
-$("#upload-form").submit(function(e) {
- e.preventDefault();
- if (!url.value && !$("#file-input").val()) {
- snackbar.timeoutMs = 5000;
- snackbar.labelText = "没填信息";
- snackbar.open();
- return;
- }
- let textureType = 'skin'
- if (radio3.checked) {
- textureType = 'skin'
- } else if (radio4.checked) {
- textureType = 'cape'
- }
- if (!url.value) {
- const formData = new FormData();
- formData.append("model", radio1.checked ? radio1.value : radio2.value);
- formData.append("file", $("#file-input")[0].files[0]);
- //formData.contentType = "multipart/form-data";
- $.ajax({
- url: `/api/user/profile/${localStorage.uuid}/${textureType}`,
- type: 'PUT',
- processData: false,
- contentType: false,
- headers: {'Authorization':'Bearer ' + localStorage.accessToken},
- data: formData,
- success: function(data) {
- snackbar.timeoutMs = 5000;
- snackbar.labelText = "材质上传成功";
- snackbar.open();
- },
- error: function(e) {
- snackbar.timeoutMs = 5000;
- snackbar.labelText = "材质上传失败";
- snackbar.open();
- }
- });
- } else if (url.value) {
- $.ajax({
- url: `/api/user/profile/${localStorage.uuid}/${textureType}`,
- type: 'POST',
- dataType: "JSON",
- contentType: "application/json",
- headers: {'Authorization':'Bearer ' + localStorage.accessToken},
- data: JSON.stringify({
- model: radio1.checked ? radio1.value : radio2.value,
- url: url.value
- }),
- success: function(data) {
- snackbar.timeoutMs = 5000;
- snackbar.labelText = "材质上传成功";
- snackbar.open();
- },
- error: function(e) {
- snackbar.timeoutMs = 5000;
- snackbar.labelText = "材质上传失败";
- snackbar.open();
- }
- });
- }
-});
-
-$("#change-form").submit(function(e) {
- e.preventDefault();
- if (changeTo.value.length <= 1) {
- snackbar.timeoutMs = 5000;
- snackbar.labelText = "更改失败, 角色名格式不正确";
- snackbar.open();
- return;
- }
- $.ajax({
- url: '/authserver/change',
- type: 'POST',
- dataType: "JSON",
- contentType: "application/json",
- data: JSON.stringify({
- accessToken: localStorage.accessToken,
- changeTo: changeTo.value
- }),
- success: function(data) {
- snackbar.timeoutMs = 5000;
- snackbar.labelText = "更改成功";
- snackbar.open();
- localStorage.profileName = changeTo.value;
- },
- error: function(e) {
- snackbar.timeoutMs = 5000;
- snackbar.labelText = "更改失败, 可能是角色名已存在";
- snackbar.open();
- }
- });
-});
-
-$('#delete-btn').click(function () {
- let textureType = 'skin'
- if (radio3.checked) {
- textureType = 'skin'
- } else if (radio4.checked) {
- textureType = 'cape'
- }
- $.ajax({
- url: `/api/user/profile/${localStorage.uuid}/${textureType}`,
- type: 'DELETE',
- headers: {'Authorization':'Bearer ' + localStorage.accessToken},
- success: function(data) {
- snackbar.timeoutMs = 5000;
- snackbar.labelText = "恢复成功";
- snackbar.open();
- localStorage.profileName = changeTo.value;
- },
- error: function(e) {
- snackbar.timeoutMs = 5000;
- snackbar.labelText = "重置失败";
- snackbar.open();
- }
- });
-})
\ No newline at end of file
diff --git a/frontend/.gitignore b/frontend/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/frontend/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/frontend/index.html b/frontend/index.html
new file mode 100644
index 0000000..c01ce52
--- /dev/null
+++ b/frontend/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+ Yggdrasil Go
+
+
+You need to enable JavaScript to run this app.
+
+
+
+
diff --git a/frontend/package.json b/frontend/package.json
new file mode 100644
index 0000000..0803a0e
--- /dev/null
+++ b/frontend/package.json
@@ -0,0 +1,38 @@
+{
+ "name": "yggdrasil-go",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite --host",
+ "build": "tsc && vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@emotion/react": "^11.10.5",
+ "@emotion/styled": "^11.10.5",
+ "@fontsource/roboto": "^4.5.8",
+ "@mui/icons-material": "^5.11.0",
+ "@mui/material": "^5.11.6",
+ "@react-three/drei": "^9.56.12",
+ "@react-three/fiber": "^8.10.1",
+ "@react-three/postprocessing": "^2.7.0",
+ "axios": "^1.2.6",
+ "notistack": "^2.0.8",
+ "postprocessing": "^6.29.3",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-hook-form": "^7.43.0",
+ "three": "^0.148.0",
+ "three-stdlib": "^2.21.8"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.26",
+ "@types/react-dom": "^18.0.9",
+ "@types/three": "^0.148.0",
+ "@vitejs/plugin-react": "^3.0.0",
+ "typescript": "^4.9.3",
+ "vite": "^4.0.0",
+ "vite-plugin-mock-dev-server": "^0.3.16"
+ }
+}
diff --git a/frontend/src/app.css b/frontend/src/app.css
new file mode 100644
index 0000000..f48c0c0
--- /dev/null
+++ b/frontend/src/app.css
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2023. Gardel and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#root {
+ width: 100%;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
\ No newline at end of file
diff --git a/frontend/src/app.tsx b/frontend/src/app.tsx
new file mode 100644
index 0000000..cf723e2
--- /dev/null
+++ b/frontend/src/app.tsx
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2023. Gardel and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import React from 'react';
+import './app.css';
+import Login from './login';
+import {Container} from '@mui/material';
+import {AppState} from './types';
+import User from './user';
+import axios from 'axios';
+import {useSnackbar} from 'notistack';
+
+function App() {
+ const {enqueueSnackbar} = useSnackbar();
+ const [appData, setAppData] = React.useState(() => {
+ const saved = localStorage.getItem('appData');
+ return (saved ? JSON.parse(saved) : {
+ login: false,
+ accessToken: '',
+ tokenValid: false,
+ loginTime: 0,
+ profileName: '',
+ uuid: ''
+ }) as AppState;
+ });
+
+ React.useEffect(() => {
+ localStorage.setItem('appData', JSON.stringify(appData));
+ }, [appData]);
+
+ const setTokenValid = (tokenValid: boolean) => appData.tokenValid != tokenValid && setAppData((oldData: AppState) => {
+ return tokenValid ? {
+ ...oldData,
+ tokenValid: true
+ } : {
+ ...oldData,
+ tokenValid: false,
+ accessToken: '',
+ loginTime: 0
+ };
+ });
+
+ setTokenValid((appData.accessToken && Date.now() - appData.loginTime < 30 * 86400 * 1000) as boolean)
+
+ if (appData.tokenValid) {
+ let postData = {
+ accessToken: appData.accessToken,
+ };
+ axios.post('/authserver/validate', postData)
+ .catch(e => {
+ const response = e.response;
+ if (response && response.status == 403) {
+ axios.post('/authserver/refresh', postData)
+ .then(response => {
+ const data = response.data;
+ if (data && data.accessToken) {
+ setAppData({
+ ...appData,
+ accessToken: data.accessToken,
+ loginTime: Date.now(),
+ profileName: data.selectedProfile?.name,
+ uuid: data.selectedProfile?.id
+ });
+ enqueueSnackbar('刷新token成功,accessToken:' + data.accessToken, {variant: 'success'});
+ } else {
+ setTokenValid(false);
+ }
+ })
+ .catch(e => {
+ const response = e.response;
+ if (response && response.status == 403) {
+ enqueueSnackbar('登录已过期', {variant: 'warning'});
+ setTokenValid(false);
+ } else {
+ enqueueSnackbar('网络错误:' + e.message, {variant: 'error'});
+ }
+ });
+ } else {
+ enqueueSnackbar('网络错误:' + e.message, {variant: 'error'});
+ }
+ });
+ }
+
+ return (
+
+ {appData.tokenValid ? : }
+
+ );
+}
+
+export default App;
diff --git a/frontend/src/components.tsx b/frontend/src/components.tsx
new file mode 100644
index 0000000..b90b013
--- /dev/null
+++ b/frontend/src/components.tsx
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023. Gardel and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import {Collapse, FormHelperText, FormHelperTextProps, useFormControl} from '@mui/material';
+
+export function FocusedShowHelperText(props: FormHelperTextProps) {
+ const {focused} = useFormControl() || {};
+
+ return {props.children} ;
+}
\ No newline at end of file
diff --git a/frontend/src/index.css b/frontend/src/index.css
new file mode 100644
index 0000000..4397a57
--- /dev/null
+++ b/frontend/src/index.css
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023. Gardel and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
diff --git a/assets/user.css b/frontend/src/login.css
similarity index 72%
rename from assets/user.css
rename to frontend/src/login.css
index f9ba6ab..4111143 100644
--- a/assets/user.css
+++ b/frontend/src/login.css
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022. Gardel and contributors
+ * Copyright (C) 2023. Gardel and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -15,34 +15,30 @@
* along with this program. If not, see .
*/
-
.header {
- text-align: center;
+ text-align: center;
}
-.model,
-.textureType,
-.url,
-.changeTo {
- display: block;
- width: 300px;
- margin: 20px auto;
+.login-card {
+ padding: 14px 24px;
+ margin: auto;
}
-.file {
- display: flex;
- width: 300px;
+.username,
+.profileName,
+.password {
+ display: block;
+ width: 87%;
margin: 20px auto;
}
.button-container {
- display: flex;
- justify-content: flex-end;
- width: 300px;
- margin: auto;
+ display: flex;
+ justify-content: flex-end;
+ width: 87%;
+ margin: auto;
}
.button-container button {
- margin: 3px;
+ margin: 3px;
}
-
diff --git a/frontend/src/login.tsx b/frontend/src/login.tsx
new file mode 100644
index 0000000..a9aba80
--- /dev/null
+++ b/frontend/src/login.tsx
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2023. Gardel and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import React from 'react';
+import Button from '@mui/material/Button';
+import {
+ Box,
+ Collapse,
+ Container,
+ FilledInput,
+ FormControl,
+ IconButton,
+ InputAdornment,
+ InputLabel,
+ Paper,
+ TextField
+} from '@mui/material';
+import {Visibility, VisibilityOff} from '@mui/icons-material';
+import {AppState} from './types';
+import './login.css';
+import {SubmitHandler, useForm} from 'react-hook-form';
+import axios from 'axios';
+import {useSnackbar} from 'notistack';
+import {FocusedShowHelperText} from './components';
+
+type Inputs = {
+ username: string,
+ profileName: string,
+ password: string
+};
+
+function Login(props: { appData: AppState, setAppData: React.Dispatch> }) {
+ const {appData, setAppData} = props;
+ const {enqueueSnackbar} = useSnackbar();
+ const {register, handleSubmit, formState: {errors}} = useForm();
+ const [submitting, setSubmitting] = React.useState(false);
+ const onSubmit: SubmitHandler = data => {
+ setSubmitting(true)
+ if (appData.login) {
+ axios.post('/authserver/authenticate', {
+ username: data.username,
+ password: data.password
+ })
+ .then(response => {
+ let data = response.data
+ if (data && data.accessToken) {
+ enqueueSnackbar("登录成功,accessToken:" + data.accessToken, {variant: 'success'});
+ setAppData({
+ ...appData,
+ accessToken: data.accessToken,
+ tokenValid: true,
+ loginTime: Date.now(),
+ profileName: data.selectedProfile?.name,
+ uuid: data.selectedProfile?.id
+ });
+ } else {
+ enqueueSnackbar(data && data.errorMessage ? "登录失败: " + data.errorMessage: "登陆失败", {variant: 'error'});
+ }
+ })
+ .catch(e => {
+ const response = e.response;
+ if (response && response.status == 403) {
+ enqueueSnackbar('登录失败: ' + response.data.errorMessage, {variant: 'error'});
+ } else {
+ enqueueSnackbar('网络错误:' + e.message, {variant: 'error'});
+ }
+ })
+ .finally(() => setSubmitting(false))
+ } else {
+ axios.post('/authserver/register', {
+ username: data.username,
+ password: data.password,
+ profileName: data.profileName
+ })
+ .then(response => {
+ let data = response.data
+ if (data && data.id) {
+ enqueueSnackbar("注册成功,uuid:" + data.id, {variant: 'success'});
+ setLogin(true)
+ } else {
+ enqueueSnackbar(data && data.errorMessage ? "注册失败: " + data.errorMessage: "注册失败", {variant: 'error'});
+ }
+ })
+ .catch(e => {
+ const response = e.response;
+ if (response && response.data) {
+ let errorMessage = response.data.errorMessage;
+ let message = "注册失败: " + errorMessage;
+ if (errorMessage === "profileName exist") {
+ message = "注册失败: 角色名已存在";
+ } else if (errorMessage === "profileName duplicate") {
+ message = "注册失败: 角色名与正版用户冲突";
+ }
+ enqueueSnackbar(message, {variant: 'error'});
+ } else {
+ enqueueSnackbar('网络错误:' + e.message, {variant: 'error'});
+ }
+ })
+ .finally(() => setSubmitting(false))
+ }
+ };
+
+ const [showPassword, setShowPassword] = React.useState(false);
+
+ const handleClickShowPassword = () => setShowPassword((show) => !show);
+
+ const handleMouseDownPassword = (event: React.MouseEvent) => {
+ event.preventDefault();
+ };
+
+ const setLogin = (login: boolean) => setAppData((oldData: AppState) => {
+ return {
+ ...oldData,
+ login
+ };
+ });
+
+ return (
+
+
+
+
+
+
+
+
+
+ 角色名
+
+ 字母,数字或下划线
+
+
+
+
+ 密码
+
+
+ {showPassword ? : }
+
+
+ }
+ inputProps={{
+ minLength: '6',
+ ...register('password', {required: true, minLength: 6})
+ }}
+ />
+ 警告: 暂无重置密码接口,请妥善保管密码
+
+
+
+ setLogin(!appData.login)} disabled={submitting}>{appData.login ? '注册' : '已有帐号登录'}
+ {appData.login ? '登录' : '注册'}
+
+
+
+
+ );
+}
+
+export default Login;
\ No newline at end of file
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
new file mode 100644
index 0000000..3d3a053
--- /dev/null
+++ b/frontend/src/main.tsx
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023. Gardel and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import './index.css';
+import '@fontsource/roboto/300.css';
+import '@fontsource/roboto/400.css';
+import '@fontsource/roboto/500.css';
+import '@fontsource/roboto/700.css';
+import { SnackbarProvider } from 'notistack';
+import {CssBaseline} from '@mui/material';
+import App from './app';
+
+ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
+
+
+
+
+
+ ,
+);
diff --git a/frontend/src/skinrender/skin-render.tsx b/frontend/src/skinrender/skin-render.tsx
new file mode 100644
index 0000000..2402ce1
--- /dev/null
+++ b/frontend/src/skinrender/skin-render.tsx
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023. Gardel and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import {Box} from '@mui/material';
+import * as THREE from 'three';
+import {Canvas, RootState, useFrame, useLoader} from '@react-three/fiber';
+import React from 'react';
+import createPlayerModel from './utils';
+import {OrbitControls} from '@react-three/drei';
+import {EffectComposer, Vignette, SMAA, SSAO, SSR} from '@react-three/postprocessing';
+import {BlendFunction} from 'postprocessing';
+
+function PlayerModel(props: { skinUrl: string, capeUrl?: string, slim?: boolean }) {
+ const {skinUrl, capeUrl, slim} = props;
+ console.log(props);
+ const skinTexture: THREE.Texture = useLoader(THREE.TextureLoader, skinUrl);
+ skinTexture.magFilter = THREE.NearestFilter;
+ skinTexture.minFilter = THREE.NearestFilter;
+ skinTexture.anisotropy = 0;
+ skinTexture.needsUpdate = true;
+ let version = 0;
+ if (skinTexture.image.height > 32) {
+ version = 1;
+ }
+ let capeTexture: THREE.Texture | undefined = undefined;
+ if (capeUrl) {
+ capeTexture = useLoader(THREE.TextureLoader, capeUrl);
+ if (capeTexture) {
+ capeTexture.magFilter = THREE.NearestFilter;
+ capeTexture.minFilter = THREE.NearestFilter;
+ capeTexture.anisotropy = 0;
+ capeTexture.needsUpdate = true;
+ }
+ }
+ let playerModel = createPlayerModel(skinTexture, capeTexture, version, slim);
+ useFrame((state, delta) => {
+ playerModel.rotation.y += delta * 0.7;
+ });
+ return (
+
+ );
+}
+
+function SkinRender(props: { skinUrl: string, capeUrl?: string, slim?: boolean }) {
+ const onCanvasCreate = (state: RootState) => {
+ state.gl.shadowMap.enabled = true;
+ state.gl.shadowMap.type = THREE.PCFSoftShadowMap;
+ };
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default SkinRender;
\ No newline at end of file
diff --git a/frontend/src/skinrender/texture-positions.ts b/frontend/src/skinrender/texture-positions.ts
new file mode 100644
index 0000000..ca7b194
--- /dev/null
+++ b/frontend/src/skinrender/texture-positions.ts
@@ -0,0 +1,1105 @@
+/*
+ * Copyright (C) 2023. Gardel and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+export type TextureSurface = {
+ x: number
+ y: number
+ w: number
+ h: number
+ sx?: number
+ sw?: number
+ flipX?: boolean
+ flipY?: boolean
+}
+
+export type CubeTexture = {
+ left: TextureSurface
+ front: TextureSurface
+ right: TextureSurface
+ back: TextureSurface
+ top: TextureSurface
+ bottom: TextureSurface
+}
+
+export type PlayerTexturePosition = {
+ head: CubeTexture[]
+ body: CubeTexture[]
+ rightArm: CubeTexture[]
+ leftArm: CubeTexture[]
+ rightLeg: CubeTexture[]
+ leftLeg: CubeTexture[]
+ hat: CubeTexture[]
+ jacket: CubeTexture
+ rightSleeve: CubeTexture
+ leftSleeve: CubeTexture
+ rightTrousers: CubeTexture
+ leftTrousers: CubeTexture
+ cape: CubeTexture
+ capeRelative: CubeTexture
+ capeOptifineRelative: CubeTexture
+ capeOptifine: CubeTexture
+ capeLabymodRelative: CubeTexture
+}
+
+/**
+ * Texture positions for Minecraft's player model
+ */
+export const texturePositions: PlayerTexturePosition = {
+ head: [
+ {// 64x32
+ left: {
+ x: 0,
+ y: 16,
+ w: 8,
+ h: 8,
+ flipX: false
+ },
+ front: {
+ x: 8,
+ y: 16,
+ w: 8,
+ h: 8
+ },
+ right: {
+ x: 16,
+ y: 16,
+ w: 8,
+ h: 8,
+ flipX: false
+ },
+ back: {
+ x: 24,
+ y: 16,
+ w: 8,
+ h: 8
+ },
+ top: {
+ x: 8,
+ y: 24,
+ w: 8,
+ h: 8
+ },
+ bottom: {
+ x: 16,
+ y: 24,
+ w: 8,
+ h: 8,
+ flipX: true,
+ flipY: true
+ }
+ },
+ {// 64x64
+ left: {
+ x: 0,
+ y: 48,
+ w: 8,
+ h: 8,
+ flipX: false
+ },
+ front: {
+ x: 8,
+ y: 48,
+ w: 8,
+ h: 8
+ },
+ right: {
+ x: 16,
+ y: 48,
+ w: 8,
+ h: 8,
+ flipX: false
+ },
+ back: {
+ x: 24,
+ y: 48,
+ w: 8,
+ h: 8
+ },
+ top: {
+ x: 8,
+ y: 56,
+ w: 8,
+ h: 8
+ },
+ bottom: {
+ x: 16,
+ y: 56,
+ w: 8,
+ h: 8,
+ flipX: true,
+ flipY: true
+ }
+ }
+ ],
+ body: [
+ {// 64x32
+ left: {
+ x: 16,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: true
+ },
+ front: {
+ x: 20,
+ y: 0,
+ w: 8,
+ h: 12
+ },
+ right: {
+ x: 28,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: true
+ },
+ back: {
+ x: 32,
+ y: 0,
+ w: 8,
+ h: 12
+ },
+ top: {
+ x: 20,
+ y: 12,
+ w: 8,
+ h: 4
+ },
+ bottom: {
+ x: 28,
+ y: 12,
+ w: 8,
+ h: 4,
+ flipY: true,
+ flipX: true
+ }
+ },
+ {// 64x64
+ left: {
+ x: 16,
+ y: 32,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ front: {
+ x: 20,
+ y: 32,
+ w: 8,
+ h: 12
+ },
+ right: {
+ x: 28,
+ y: 32,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ back: {
+ x: 32,
+ y: 32,
+ w: 8,
+ h: 12
+ },
+ top: {
+ x: 20,
+ y: 44,
+ w: 8,
+ h: 4
+ },
+ bottom: {
+ x: 28,
+ y: 44,
+ w: 8,
+ h: 4,
+ flipY: true,
+ flipX: true
+ }
+ }
+ ],
+ rightArm: [
+ {// 64x32 - same as rightArm
+ left: {
+ x: 40,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ front: {
+ x: 44,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ right: {
+ x: 48,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ back: {
+ x: 52,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ top: {
+ x: 44,
+ y: 12,
+ w: 4,
+ h: 4,
+ flipX: false
+ },
+ bottom: {
+ x: 48,
+ y: 12,
+ w: 4,
+ h: 4,
+ flipX: true,
+ flipY: true
+ }
+ },
+ {// 64x64
+ left: {
+ x: 32,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ front: {
+ x: 36,
+ y: 0,
+ w: 4,
+ h: 12,
+ sw: 3,
+ flipX: false
+ },
+ right: {
+ x: 40,
+ y: 0,
+ w: 4,
+ h: 12,
+ sx: 39,
+ flipX: false
+ },
+ back: {
+ x: 44,
+ y: 0,
+ w: 4,
+ h: 12,
+ sx: 43,
+ sw: 3,
+ flipX: false
+ },
+ top: {
+ x: 36,
+ y: 12,
+ w: 4,
+ h: 4,
+ sw: 3,
+ flipX: false
+ },
+ bottom: {
+ x: 40,
+ y: 12,
+ w: 4,
+ h: 4,
+ sx: 39,
+ sw: 3,
+ flipY: true,
+ flipX: true
+ }
+ }
+ ],
+ leftArm: [
+ {// 64x32 - same as leftArm
+ left: {
+ x: 40,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ front: {
+ x: 44,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ right: {
+ x: 48,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ back: {
+ x: 52,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ top: {
+ x: 44,
+ y: 12,
+ w: 4,
+ h: 4,
+ flipX: false
+ },
+ bottom: {
+ x: 48,
+ y: 12,
+ w: 4,
+ h: 4,
+ flipX: true,
+ flipY: true
+ }
+ },
+ {// 64x64
+ left: {
+ x: 40,
+ y: 32,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ front: {
+ x: 44,
+ y: 32,
+ w: 4,
+ h: 12,
+ sw: 3,
+ flipX: false
+ },
+ right: {
+ x: 48,
+ y: 32,
+ w: 4,
+ h: 12,
+ sx: 47,
+ flipX: false
+ },
+ back: {
+ x: 52,
+ y: 32,
+ w: 4,
+ h: 12,
+ sx: 51,
+ sw: 3,
+ flipX: false
+ },
+ top: {
+ x: 44,
+ y: 44,
+ w: 4,
+ h: 4,
+ sw: 3,
+ flipX: false
+ },
+ bottom: {
+ x: 48,
+ y: 44,
+ w: 4,
+ h: 4,
+ sx: 47,
+ sw: 3,
+ flipY: true,
+ flipX: true
+ }
+ }
+ ],
+ rightLeg: [
+ {// 64x32 - same as rightLeg
+ left: {
+ x: 0,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ front: {
+ x: 4,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ right: {
+ x: 8,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ back: {
+ x: 12,
+ y: 0,
+ w: 4,
+ h: 12
+ },
+ top: {
+ x: 4,
+ y: 12,
+ w: 4,
+ h: 4,
+ flipX: false
+ },
+ bottom: {
+ x: 8,
+ y: 12,
+ w: 4,
+ h: 4,
+ flipX: true,
+ flipY: true
+ }
+ },
+ {// 64x64
+ left: {
+ x: 16,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ front: {
+ x: 20,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ right: {
+ x: 24,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ back: {
+ x: 28,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ top: {
+ x: 20,
+ y: 12,
+ w: 4,
+ h: 4,
+ flipX: false
+ },
+ bottom: {
+ x: 24,
+ y: 12,
+ w: 4,
+ h: 4,
+ flipY: true,
+ flipX: true
+ }
+ }
+ ],
+ leftLeg: [
+ {// 64x32 - same as leftLeg
+ left: {
+ x: 0,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ front: {
+ x: 4,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ right: {
+ x: 8,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ back: {
+ x: 12,
+ y: 0,
+ w: 4,
+ h: 12,
+ flipX: true
+ },
+ top: {
+ x: 4,
+ y: 12,
+ w: 4,
+ h: 4,
+ flipX: false
+ },
+ bottom: {
+ x: 8,
+ y: 12,
+ w: 4,
+ h: 4,
+ flipX: true,
+ flipY: true
+ }
+ },
+ {// 64x64
+ left: {
+ x: 0,
+ y: 32,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ front: {
+ x: 4,
+ y: 32,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ right: {
+ x: 8,
+ y: 32,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ back: {
+ x: 12,
+ y: 32,
+ w: 4,
+ h: 12,
+ flipX: false
+ },
+ top: {
+ x: 4,
+ y: 44,
+ w: 4,
+ h: 4,
+ flipX: false
+ },
+ bottom: {
+ x: 8,
+ y: 44,
+ w: 4,
+ h: 4,
+ flipY: true,
+ flipX: true
+ }
+ }
+ ],
+
+ hat: [
+ { // 64x32
+ left: {
+ x: 32,
+ y: 16,
+ w: 8,
+ h: 8
+ },
+ front: {
+ x: 40,
+ y: 16,
+ w: 8,
+ h: 8
+ },
+ right: {
+ x: 48,
+ y: 16,
+ w: 8,
+ h: 8
+ },
+ back: {
+ x: 56,
+ y: 16,
+ w: 8,
+ h: 8
+ },
+ top: {
+ x: 40,
+ y: 24,
+ w: 8,
+ h: 8,
+ flipX: false
+ },
+ bottom: {
+ x: 48,
+ y: 24,
+ w: 8,
+ h: 8,
+ flipY: true,
+ flipX: true
+ }
+ },
+ { // 64x64
+ left: {
+ x: 32,
+ y: 48,
+ w: 8,
+ h: 8
+ },
+ front: {
+ x: 40,
+ y: 48,
+ w: 8,
+ h: 8
+ },
+ right: {
+ x: 48,
+ y: 48,
+ w: 8,
+ h: 8
+ },
+ back: {
+ x: 56,
+ y: 48,
+ w: 8,
+ h: 8
+ },
+ top: {
+ x: 40,
+ y: 56,
+ w: 8,
+ h: 8,
+ flipX: false
+ },
+ bottom: {
+ x: 48,
+ y: 56,
+ w: 8,
+ h: 8,
+ flipY: true,
+ flipX: true
+ }
+ }
+ ],
+ jacket: {
+ left: {
+ x: 16,
+ y: 16,
+ w: 4,
+ h: 12
+ },
+ front: {
+ x: 20,
+ y: 16,
+ w: 8,
+ h: 12
+ },
+ right: {
+ x: 28,
+ y: 16,
+ w: 4,
+ h: 12
+ },
+ back: {
+ x: 32,
+ y: 16,
+ w: 8,
+ h: 12
+ },
+ top: {
+ x: 20,
+ y: 28,
+ w: 8,
+ h: 4
+ },
+ bottom: {
+ x: 28,
+ y: 28,
+ w: 8,
+ h: 4,
+ flipY: true,
+ flipX: true
+ }
+ },
+ rightSleeve: {
+ left: {
+ x: 48,
+ y: 0,
+ w: 4,
+ h: 12
+ },
+ front: {
+ x: 52,
+ y: 0,
+ w: 4,
+ h: 12,
+ sw: 3
+ },
+ right: {
+ x: 56,
+ y: 0,
+ w: 4,
+ h: 12,
+ sx: 55
+ },
+ back: {
+ x: 60,
+ y: 0,
+ w: 4,
+ h: 12,
+ sx: 59,
+ sw: 3
+ },
+ top: {
+ x: 52,
+ y: 12,
+ w: 4,
+ h: 4,
+ sw: 3
+ },
+ bottom: {
+ x: 56,
+ y: 12,
+ w: 4,
+ h: 4,
+ sx: 55,
+ sw: 3,
+ flipY: true,
+ flipX: true
+ }
+ },
+ leftSleeve: {
+ left: {
+ x: 40,
+ y: 16,
+ w: 4,
+ h: 12
+ },
+ front: {
+ x: 44,
+ y: 16,
+ w: 4,
+ h: 12,
+ sw: 3
+ },
+ right: {
+ x: 48,
+ y: 16,
+ w: 4,
+ h: 12,
+ sx: 47
+ },
+ back: {
+ x: 52,
+ y: 16,
+ w: 4,
+ h: 12,
+ sx: 51,
+ sw: 3
+ },
+ top: {
+ x: 44,
+ y: 28,
+ w: 4,
+ h: 4,
+ sw: 3
+ },
+ bottom: {
+ x: 48,
+ y: 28,
+ w: 4,
+ h: 4,
+ sx: 47,
+ sw: 3,
+ flipY: true,
+ flipX: true
+ }
+ },
+ rightTrousers: {
+ left: {
+ x: 0,
+ y: 0,
+ w: 4,
+ h: 12
+ },
+ front: {
+ x: 4,
+ y: 0,
+ w: 4,
+ h: 12
+ },
+ right: {
+ x: 8,
+ y: 0,
+ w: 4,
+ h: 12
+ },
+ back: {
+ x: 12,
+ y: 0,
+ w: 4,
+ h: 12
+ },
+ top: {
+ x: 4,
+ y: 12,
+ w: 4,
+ h: 4
+ },
+ bottom: {
+ x: 8,
+ y: 12,
+ w: 4,
+ h: 4,
+ flipY: true,
+ flipX: true
+ }
+ },
+ leftTrousers: {
+ left: {
+ x: 0,
+ y: 16,
+ w: 4,
+ h: 12
+ },
+ front: {
+ x: 4,
+ y: 16,
+ w: 4,
+ h: 12
+ },
+ right: {
+ x: 8,
+ y: 16,
+ w: 4,
+ h: 12
+ },
+ back: {
+ x: 12,
+ y: 16,
+ w: 4,
+ h: 12
+ },
+ top: {
+ x: 4,
+ y: 28,
+ w: 4,
+ h: 4
+ },
+ bottom: {
+ x: 8,
+ y: 28,
+ w: 4,
+ h: 4,
+ flipY: true,
+ flipX: true
+ }
+ },
+
+ cape: {
+ right: {
+ x: 0,
+ y: 5,
+ w: 1,
+ h: 16
+ },
+ front: {
+ x: 1,
+ y: 5,
+ w: 10,
+ h: 16
+ },
+ left: {
+ x: 11,
+ y: 5,
+ w: 1,
+ h: 16
+ },
+ back: {
+ x: 12,
+ y: 5,
+ w: 10,
+ h: 16
+ },
+ top: {
+ x: 1,
+ y: 21,
+ w: 10,
+ h: 1
+ },
+ bottom: {
+ x: 11,
+ y: 21,
+ w: 10,
+ h: 1
+ }
+ },
+ capeRelative: { // Cape coordinates relative to image dimensions, starting bottom-left
+ right: {
+ x: 0,
+ y: 15/32,
+ w: 1/64,
+ h: 16/32
+ },
+ front: {
+ x: 1/64,
+ y: 15/32,
+ w: 10/64,
+ h: 16/32
+ },
+ left: {
+ x: 11/64,
+ y: 15/32,
+ w: 1/64,
+ h: 16/32
+ },
+ back: {
+ x: 12/64,
+ y: 15/32,
+ w: 10/64,
+ h: 16/32
+ },
+ top: {
+ x: 1/64,
+ y: 31/32,
+ w: 10/64,
+ h: 1/32
+ },
+ bottom: {
+ x: 11/64,
+ y: 31/32,
+ w: 10/64,
+ h: 1/32
+ }
+ },
+ capeOptifineRelative: {
+ right: {
+ x: 0,
+ y: 10/44,
+ w: 2/92,
+ h: 32/44
+ },
+ front: {
+ x: 2/92,
+ y: 10/44,
+ w: 20/92,
+ h: 32/44
+ },
+ left: {
+ x: 22/92,
+ y: 10/44,
+ w: 2/92,
+ h: 32/44
+ },
+ back: {
+ x: 24/92,
+ y: 10/44,
+ w: 20/92,
+ h: 32/44
+ },
+ top: {
+ x: 2/92,
+ y: 42/44,
+ w: 20/92,
+ h: 2/44
+ },
+ bottom: {
+ x: 22/92,
+ y: 42/44,
+ w: 20/92,
+ h: 2/44
+ }
+ },
+ capeOptifine: {
+ right: {
+ x: 0,
+ y: 10,
+ w: 2,
+ h: 32
+ },
+ front: {
+ x: 2,
+ y: 10,
+ w: 20,
+ h: 32
+ },
+ left: {
+ x: 22,
+ y: 10,
+ w: 2,
+ h: 32
+ },
+ back: {
+ x: 24,
+ y: 10,
+ w: 20,
+ h: 32
+ },
+ top: {
+ x: 2,
+ y: 42,
+ w: 20,
+ h: 2
+ },
+ bottom: {
+ x: 22,
+ y: 42,
+ w: 20,
+ h: 2
+ }
+ },
+ capeLabymodRelative: {
+ right: {
+ x: 0,
+ y: 0,
+ w: 1/22,
+ h: 16/17
+ },
+ front: {
+ x: 1/22,
+ y: 0,
+ w: 10/22,
+ h: 16/17
+ },
+ left: {
+ x: 11/22,
+ y: 0,
+ w: 1/22,
+ h: 16/17
+ },
+ back: {
+ x: 12/22,
+ y: 0,
+ w: 10/22,
+ h: 16/17
+ },
+ top: {
+ x: 1/22,
+ y: 16/17,
+ w: 10/22,
+ h: 1/17
+ },
+ bottom: {
+ x: 11/22,
+ y: 16/17,
+ w: 10/22,
+ h: 1/17
+ }
+ },
+};
diff --git a/frontend/src/skinrender/utils.ts b/frontend/src/skinrender/utils.ts
new file mode 100644
index 0000000..58b10ca
--- /dev/null
+++ b/frontend/src/skinrender/utils.ts
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2023. Gardel and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import * as THREE from 'three';
+import {texturePositions} from './texture-positions';
+import {BufferAttribute} from 'three';
+
+function createCube(texture: THREE.Texture, width: number, height: number, depth: number, textures: any, slim: boolean, name: string, transparent: boolean = false) {
+ let textureWidth: number = texture.image.width;
+ let textureHeight: number = texture.image.height;
+
+ let geometry = new THREE.BoxGeometry(width, height, depth);
+ let material = new THREE.MeshStandardMaterial({
+ /*color: 0x00ff00,*/
+ map: texture,
+ transparent: transparent || false,
+ alphaTest: 0.1,
+ side: transparent ? THREE.DoubleSide : THREE.FrontSide
+ });
+
+ geometry.computeBoundingBox();
+
+ const uvAttribute = geometry.getAttribute('uv') as BufferAttribute;
+
+ let faceNames = ['right', 'left', 'top', 'bottom', 'front', 'back'];
+ let faceUvs = [];
+ for (let i = 0; i < faceNames.length; i++) {
+ let face = textures[faceNames[i]];
+ // if (faceNames[i] === 'back') {
+ // console.log(face)
+ // console.log("X: " + (slim && face.sx ? face.sx : face.x))
+ // console.log("W: " + (slim && face.sw ? face.sw : face.w))
+ // }
+ let w = textureWidth;
+ let h = textureHeight;
+ let tx1 = ((slim && face.sx ? face.sx : face.x) / w);
+ let ty1 = (face.y / h);
+ let tx2 = (((slim && face.sx ? face.sx : face.x) + (slim && face.sw ? face.sw : face.w)) / w);
+ let ty2 = ((face.y + face.h) / h);
+
+ faceUvs[i] = [
+ new THREE.Vector2(tx1, ty2),
+ new THREE.Vector2(tx1, ty1),
+ new THREE.Vector2(tx2, ty1),
+ new THREE.Vector2(tx2, ty2)
+ ];
+ // console.log(faceUvs[i])
+
+ let flipX = face.flipX;
+ let flipY = face.flipY;
+
+ let temp;
+ if (flipY) {
+ temp = faceUvs[i].slice(0);
+ faceUvs[i][0] = temp[2];
+ faceUvs[i][1] = temp[3];
+ faceUvs[i][2] = temp[0];
+ faceUvs[i][3] = temp[1];
+ }
+ if (flipX) {//flip x
+ temp = faceUvs[i].slice(0);
+ faceUvs[i][0] = temp[3];
+ faceUvs[i][1] = temp[2];
+ faceUvs[i][2] = temp[1];
+ faceUvs[i][3] = temp[0];
+ }
+ }
+
+ let j = 0;
+ for (let i = 0; i < faceUvs.length; i++) {
+ uvAttribute.setXY(j++, faceUvs[i][0].x, faceUvs[i][0].y);
+ uvAttribute.setXY(j++, faceUvs[i][3].x, faceUvs[i][3].y);
+ uvAttribute.setXY(j++, faceUvs[i][1].x, faceUvs[i][1].y);
+ uvAttribute.setXY(j++, faceUvs[i][2].x, faceUvs[i][2].y);
+ }
+ uvAttribute.needsUpdate = true;
+
+ let cube = new THREE.Mesh(geometry, material);
+ cube.name = name;
+ // cube.position.set(x, y, z);
+ cube.castShadow = true;
+ cube.receiveShadow = false;
+
+ return cube;
+}
+
+
+export default function createPlayerModel(skinTexture: THREE.Texture, capeTexture: THREE.Texture | null | undefined, v: number, slim: boolean = false, capeType?: string): THREE.Object3D {
+ let headGroup = new THREE.Object3D();
+ headGroup.name = 'headGroup';
+ headGroup.position.x = 0;
+ headGroup.position.y = 28;
+ headGroup.position.z = 0;
+ headGroup.translateOnAxis(new THREE.Vector3(0, 1, 0), -4);
+ let head = createCube(skinTexture,
+ 8, 8, 8,
+ texturePositions.head[v],
+ slim,
+ 'head'
+ );
+ head.translateOnAxis(new THREE.Vector3(0, 1, 0), 4);
+ headGroup.add(head);
+ let hat = createCube(skinTexture,
+ 8.667, 8.667, 8.667,
+ texturePositions.hat[v],
+ slim,
+ 'hat',
+ true
+ );
+ hat.translateOnAxis(new THREE.Vector3(0, 1, 0), 4);
+ headGroup.add(hat);
+
+ let bodyGroup = new THREE.Object3D();
+ bodyGroup.name = 'bodyGroup';
+ bodyGroup.position.x = 0;
+ bodyGroup.position.y = 18;
+ bodyGroup.position.z = 0;
+ let body = createCube(skinTexture,
+ 8, 12, 4,
+ texturePositions.body[v],
+ slim,
+ 'body'
+ );
+ bodyGroup.add(body);
+ if (v >= 1) {
+ let jacket = createCube(skinTexture,
+ 8.667, 12.667, 4.667,
+ texturePositions.jacket,
+ slim,
+ 'jacket',
+ true
+ );
+ bodyGroup.add(jacket);
+ }
+
+ let leftArmGroup = new THREE.Object3D();
+ leftArmGroup.name = 'leftArmGroup';
+ leftArmGroup.position.x = slim ? -5.5 : -6;
+ leftArmGroup.position.y = 18;
+ leftArmGroup.position.z = 0;
+ leftArmGroup.translateOnAxis(new THREE.Vector3(0, 1, 0), 4);
+ let leftArm = createCube(skinTexture,
+ slim ? 3 : 4, 12, 4,
+ texturePositions.leftArm[v],
+ slim,
+ 'leftArm'
+ );
+ leftArm.translateOnAxis(new THREE.Vector3(0, 1, 0), -4);
+ leftArmGroup.add(leftArm);
+ if (v >= 1) {
+ let leftSleeve = createCube(skinTexture,
+ slim ? 3.667 : 4.667, 12.667, 4.667,
+ texturePositions.leftSleeve,
+ slim,
+ 'leftSleeve',
+ true
+ );
+ leftSleeve.translateOnAxis(new THREE.Vector3(0, 1, 0), -4);
+ leftArmGroup.add(leftSleeve);
+ }
+
+ let rightArmGroup = new THREE.Object3D();
+ rightArmGroup.name = 'rightArmGroup';
+ rightArmGroup.position.x = slim ? 5.5 : 6;
+ rightArmGroup.position.y = 18;
+ rightArmGroup.position.z = 0;
+ rightArmGroup.translateOnAxis(new THREE.Vector3(0, 1, 0), 4);
+ let rightArm = createCube(skinTexture,
+ slim ? 3 : 4, 12, 4,
+ texturePositions.rightArm[v],
+ slim,
+ 'rightArm'
+ );
+ rightArm.translateOnAxis(new THREE.Vector3(0, 1, 0), -4);
+ rightArmGroup.add(rightArm);
+ if (v >= 1) {
+ let rightSleeve = createCube(skinTexture,
+ slim ? 3.667 : 4.667, 12.667, 4.667,
+ texturePositions.rightSleeve,
+ slim,
+ 'rightSleeve',
+ true
+ );
+ rightSleeve.translateOnAxis(new THREE.Vector3(0, 1, 0), -4);
+ rightArmGroup.add(rightSleeve);
+ }
+
+ let leftLegGroup = new THREE.Object3D();
+ leftLegGroup.name = 'leftLegGroup';
+ leftLegGroup.position.x = -2;
+ leftLegGroup.position.y = 6;
+ leftLegGroup.position.z = 0;
+ leftLegGroup.translateOnAxis(new THREE.Vector3(0, 1, 0), 4);
+ let leftLeg = createCube(skinTexture,
+ 4, 12, 4,
+ texturePositions.leftLeg[v],
+ slim,
+ 'leftLeg'
+ );
+ leftLeg.translateOnAxis(new THREE.Vector3(0, 1, 0), -4);
+ leftLegGroup.add(leftLeg);
+ if (v >= 1) {
+ let leftTrousers = createCube(skinTexture,
+ 4.667, 12.667, 4.667,
+ texturePositions.leftTrousers,
+ slim,
+ 'leftTrousers',
+ true
+ );
+ leftTrousers.translateOnAxis(new THREE.Vector3(0, 1, 0), -4);
+ leftLegGroup.add(leftTrousers);
+ }
+
+ let rightLegGroup = new THREE.Object3D();
+ rightLegGroup.name = 'rightLegGroup';
+ rightLegGroup.position.x = 2;
+ rightLegGroup.position.y = 6;
+ rightLegGroup.position.z = 0;
+ rightLegGroup.translateOnAxis(new THREE.Vector3(0, 1, 0), 4);
+ let rightLeg = createCube(skinTexture,
+ 4, 12, 4,
+ texturePositions.rightLeg[v],
+ slim,
+ 'rightLeg'
+ );
+ rightLeg.translateOnAxis(new THREE.Vector3(0, 1, 0), -4);
+ rightLegGroup.add(rightLeg);
+ if (v >= 1) {
+ let rightTrousers = createCube(skinTexture,
+ 4.667, 12.667, 4.667,
+ texturePositions.rightTrousers,
+ slim,
+ 'rightTrousers',
+ true
+ );
+ rightTrousers.translateOnAxis(new THREE.Vector3(0, 1, 0), -4);
+ rightLegGroup.add(rightTrousers);
+ }
+
+ let playerGroup = new THREE.Object3D();
+ playerGroup.add(headGroup);
+ playerGroup.add(bodyGroup);
+ playerGroup.add(leftArmGroup);
+ playerGroup.add(rightArmGroup);
+ playerGroup.add(leftLegGroup);
+ playerGroup.add(rightLegGroup);
+
+ if (capeTexture) {
+ console.log(texturePositions);
+ let capeTextureCoordinates = texturePositions.capeRelative;
+ if (capeType === 'optifine') {
+ capeTextureCoordinates = texturePositions.capeOptifineRelative;
+ }
+ if (capeType === 'labymod') {
+ capeTextureCoordinates = texturePositions.capeLabymodRelative;
+ }
+ capeTextureCoordinates = JSON.parse(JSON.stringify(capeTextureCoordinates)); // bad clone to keep the below scaling from affecting everything
+
+ console.log(capeTextureCoordinates);
+
+ type CubeTextureKey = 'left' | 'right' | 'front' | 'back' | 'top' | 'bottom'
+ // Multiply coordinates by image dimensions
+ for (let cord in capeTextureCoordinates) {
+ let key = cord as CubeTextureKey;
+ capeTextureCoordinates[key].x *= capeTexture.image.width;
+ capeTextureCoordinates[key].w *= capeTexture.image.width;
+ capeTextureCoordinates[key].y *= capeTexture.image.height;
+ capeTextureCoordinates[key].h *= capeTexture.image.height;
+ }
+
+ console.log(capeTextureCoordinates);
+
+ let capeGroup = new THREE.Object3D();
+ capeGroup.name = 'capeGroup';
+ capeGroup.position.x = 0;
+ capeGroup.position.y = 16;
+ capeGroup.position.z = -2.5;
+ capeGroup.translateOnAxis(new THREE.Vector3(0, 1, 0), 8);
+ capeGroup.translateOnAxis(new THREE.Vector3(0, 0, 1), 0.5);
+ let cape = createCube(capeTexture,
+ 10, 16, 1,
+ capeTextureCoordinates,
+ false,
+ 'cape');
+ cape.rotation.x = toRadians(10); // slight backward angle
+ cape.translateOnAxis(new THREE.Vector3(0, 1, 0), -8);
+ cape.translateOnAxis(new THREE.Vector3(0, 0, 1), -0.5);
+ cape.rotation.y = toRadians(180); // flip front&back to be correct
+ capeGroup.add(cape);
+
+ playerGroup.add(capeGroup);
+ }
+
+ return playerGroup;
+}
+
+
+function toRadians(angle: number) {
+ return angle * (Math.PI / 180);
+}
\ No newline at end of file
diff --git a/frontend/src/types.d.ts b/frontend/src/types.d.ts
new file mode 100644
index 0000000..307472b
--- /dev/null
+++ b/frontend/src/types.d.ts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023. Gardel and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+export type AppState = {
+ login: boolean
+ accessToken: string
+ tokenValid: boolean
+ loginTime: number
+ profileName: string
+ uuid: string
+}
\ No newline at end of file
diff --git a/assets/login.css b/frontend/src/user.css
similarity index 64%
rename from assets/login.css
rename to frontend/src/user.css
index 4ae0f49..27450aa 100644
--- a/assets/login.css
+++ b/frontend/src/user.css
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022. Gardel and contributors
+ * Copyright (C) 2023. Gardel and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -15,37 +15,39 @@
* along with this program. If not, see .
*/
-html, body {
- height: 100%;
-}
-
-body {
- font-family: 'Roboto';
- margin: 0;
- padding-top: 0.1px;
-}
.header {
- text-align: center;
+ text-align: center;
}
-.username,
-.profileName,
-.password,
-.profileName-helper,
-.password-helper {
- display: block;
- width: 300px;
- margin: 20px auto;
+.user-card {
+ padding: 14px 24px;
+ margin: auto;
+}
+
+.model,
+.textureType,
+.url,
+.changeTo {
+ display: block;
+ width: 87%;
+ margin: 20px auto;
+}
+
+.file {
+ display: flex;
+ width: 87%;
+ margin: 20px auto;
}
.button-container {
- display: flex;
- justify-content: flex-end;
- width: 300px;
- margin: auto;
+ display: flex;
+ justify-content: flex-end;
+ width: 87%;
+ margin: auto;
}
.button-container button {
- margin: 3px;
+ margin: 3px;
}
+
diff --git a/frontend/src/user.tsx b/frontend/src/user.tsx
new file mode 100644
index 0000000..eab94ef
--- /dev/null
+++ b/frontend/src/user.tsx
@@ -0,0 +1,474 @@
+/*
+ * Copyright (C) 2023. Gardel and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import React from 'react';
+import {
+ Box,
+ Collapse,
+ Container,
+ Fade,
+ FilledInput,
+ FormControl,
+ FormControlLabel,
+ FormLabel,
+ IconButton,
+ InputAdornment,
+ InputLabel,
+ Paper,
+ Radio,
+ RadioGroup,
+ TextField
+} from '@mui/material';
+import './user.css';
+import {AppState} from './types';
+import {Delete} from '@mui/icons-material';
+import Button from '@mui/material/Button';
+import {useSnackbar} from 'notistack';
+import {FocusedShowHelperText} from './components';
+import {SubmitHandler, useForm} from 'react-hook-form';
+import axios from 'axios';
+import SkinRender from './skinrender/skin-render';
+
+function handleMouseDown(event: React.MouseEvent) {
+ event.preventDefault();
+}
+
+function UploadTextureForm(props: {
+ appData: AppState,
+ setAppData: React.Dispatch>,
+ skinData: SkinData | null,
+ setSkinData: React.Dispatch>
+}) {
+ const {appData, skinData, setSkinData} = props;
+ const [submitting, setSubmitting] = React.useState(false);
+
+ const {enqueueSnackbar} = useSnackbar();
+
+ const fileInputElem = React.useRef(null);
+ const [filePath, setFilePath] = React.useState('');
+ const handleFilePathChange = (event: React.ChangeEvent) => {
+ setFilePath(event.target.value);
+
+ if (skinData) {
+ if (type == 'cape' && skinData.capeUrl?.startsWith('blob:')) {
+ URL.revokeObjectURL(skinData.capeUrl);
+ } else if (skinData.skinUrl.startsWith('blob:')) {
+ URL.revokeObjectURL(skinData.skinUrl);
+ }
+ }
+
+ const fileInput = event.target;
+ const fileBlob = fileInput.files?.length ? fileInput.files[0] : null;
+ if (fileBlob && skinData) {
+ let data: SkinData = {
+ ...skinData
+ }
+ const fakeUrl = URL.createObjectURL(fileBlob);
+ if (type == 'cape') {
+ data.capeUrl = fakeUrl;
+ } else {
+ data.slim = model == 'slim';
+ data.skinUrl = fakeUrl;
+ }
+ setSkinData(data);
+ }
+ };
+
+ const [url, setUrl] = React.useState('');
+ const handleUrlChange = (event: React.ChangeEvent) => {
+ setUrl(event.target.value);
+ };
+
+ const [type, setType] = React.useState('skin');
+ const handleTypeChange = (event: React.ChangeEvent) => {
+ setType(event.target.value);
+ };
+
+ const [model, setModel] = React.useState('default');
+ const handleModelChange = (event: React.ChangeEvent) => {
+ setModel(event.target.value);
+
+ if (skinData) {
+ setSkinData({
+ ...skinData,
+ slim: event.target.value == 'slim'
+ })
+ }
+ };
+
+ const uploadTexture = (event: React.FormEvent) => {
+ event.preventDefault();
+ const fileInput = fileInputElem.current;
+ if (fileInput == null) {
+ console.error('#file-input-real is not a valid element');
+ return;
+ }
+ setSubmitting(true);
+ const fileBlob = fileInput.files?.length ? fileInput.files[0] : null;
+ if (filePath && fileBlob) {
+ const formData = new FormData();
+ formData.append('model', model);
+ formData.append('file', fileBlob);
+ axios.put(`/api/user/profile/${appData.uuid}/${type}`, formData, {
+ headers: {
+ 'Authorization': 'Bearer ' + appData.accessToken
+ }
+ }).then(() => {
+ enqueueSnackbar('上传成功', {variant: 'success'});
+ }).catch(e => {
+ const response = e.response;
+ if (response && response.data) {
+ enqueueSnackbar(response.data.errorMessage, {variant: 'error'});
+ } else {
+ enqueueSnackbar('网络错误:' + e.message, {variant: 'error'});
+ }
+ }).finally(() => setSubmitting(false));
+ } else if (url) {
+ axios.post(`/api/user/profile/${appData.uuid}/${type}`, {model, url}, {
+ headers: {
+ 'Authorization': 'Bearer ' + appData.accessToken
+ }
+ }).then(() => {
+ enqueueSnackbar('上传成功', {variant: 'success'});
+ axios.get('/sessionserver/session/minecraft/profile/' + appData.uuid).then(response => {
+ let texturesProp = response.data.properties.find((v: any) => v.name == 'textures');
+ let profile: any = {};
+ if (texturesProp) {
+ profile = JSON.parse(window.atob(texturesProp.value));
+ }
+ if (profile.textures) {
+ let data: SkinData = {
+ skinUrl: ''
+ };
+ if (profile.textures.SKIN) {
+ data.skinUrl = profile.textures.SKIN.url;
+ data.slim = profile.textures.SKIN.metadata ? profile.textures.SKIN.metadata.model == 'slim' : false;
+ } else {
+ let index = getUUIDHashCode(appData.uuid) % DEFAULT_SKINS.length;
+ data.skinUrl = DEFAULT_SKINS[index].skinUrl;
+ data.slim = DEFAULT_SKINS[index].slim;
+ }
+ if (profile.textures.CAPE) {
+ data.capeUrl = profile.textures.CAPE.url;
+ }
+ setSkinData(data);
+ }
+ });
+ }).catch(e => {
+ const response = e.response;
+ if (response && response.data) {
+ enqueueSnackbar(response.data.errorMessage, {variant: 'error'});
+ } else {
+ enqueueSnackbar('网络错误:' + e.message, {variant: 'error'});
+ }
+ }).finally(() => setSubmitting(false));
+ } else {
+ enqueueSnackbar('未选择文件', {variant: 'warning'});
+ setSubmitting(false);
+ }
+ };
+
+ const deleteTexture = () => {
+ setSubmitting(true);
+ axios.delete(`/api/user/profile/${appData.uuid}/${type}`, {
+ headers: {
+ 'Authorization': 'Bearer ' + appData.accessToken
+ }
+ }).then(() => {
+ enqueueSnackbar('删除成功', {variant: 'success'});
+ if (skinData != null) {
+ if (type == 'cape') {
+ setSkinData({
+ ...skinData,
+ capeUrl: undefined
+ });
+ } else {
+ // 显示默认材质
+ let index = getUUIDHashCode(appData.uuid) % DEFAULT_SKINS.length;
+ setSkinData({
+ ...DEFAULT_SKINS[index],
+ capeUrl: skinData.capeUrl
+ });
+ }
+ }
+ }).catch(e => {
+ const response = e.response;
+ if (response && response.data) {
+ enqueueSnackbar(response.data.errorMessage, {variant: 'error'});
+ } else {
+ enqueueSnackbar('网络错误:' + e.message, {variant: 'error'});
+ }
+ }).finally(() => setSubmitting(false));
+ };
+
+ // noinspection JSUnusedGlobalSymbols
+ return (
+ <>
+
+
+
+
+
+ 材质类别:
+
+ } label="皮肤"/>
+ } label="披风"/>
+
+
+
+
+
+
+ 材质模型:
+
+ } label="Steve"/>
+ } label="Alex"/>
+
+
+
+
+
+
+
+
+
+ 或者选择一个图片
+
+ setFilePath('')}>
+
+
+
+ }
+ value={filePath}
+ inputProps={{
+ onClick: () => fileInputElem.current?.click()
+ }}
+ />
+
+
+
+
+ 上传
+ 删除材质
+
+
+ >
+ );
+}
+
+type ChangeProfileInputs = {
+ changeTo: string
+};
+
+function ChangeProfileForm(props: { appData: AppState, setAppData: React.Dispatch> }) {
+ const {appData, setAppData} = props;
+ const setProfileName = (profileName: string) => {
+ if (appData.profileName != profileName) {
+ setAppData(oldData => {
+ return {
+ ...oldData,
+ profileName
+ };
+ });
+ }
+ };
+
+ const [submitting, setSubmitting] = React.useState(false);
+
+ const {enqueueSnackbar} = useSnackbar();
+ const {register, handleSubmit, formState: {errors}} = useForm();
+ const onSubmit: SubmitHandler = data => {
+ setSubmitting(true);
+ axios.post('/authserver/change', {
+ accessToken: appData.accessToken,
+ changeTo: data.changeTo
+ }).then(() => {
+ enqueueSnackbar('更改成功', {variant: 'success'});
+ setProfileName(data.changeTo);
+ }).catch(e => {
+ const response = e.response;
+ if (response && response.data) {
+ let errorMessage = response.data.errorMessage;
+ let message = '更改失败: ' + errorMessage;
+ if (errorMessage === 'profileName exist') {
+ message = '更改失败: 角色名已存在';
+ } else if (errorMessage === 'profileName duplicate') {
+ message = '更改失败: 角色名与正版用户冲突';
+ }
+ enqueueSnackbar(message, {variant: 'error'});
+ } else {
+ enqueueSnackbar('网络错误:' + e.message, {variant: 'error'});
+ }
+ }).finally(() => setSubmitting(false));
+ };
+
+ return (
+ <>
+
+
+
+
+
+ 角色名
+
+ 字母,数字或下划线
+
+
+
+ 更改
+
+
+ >
+ );
+}
+
+type SkinData = {
+ skinUrl: string
+ capeUrl?: string
+ slim?: boolean
+}
+
+const DEFAULT_SKINS: SkinData[] = [
+ {skinUrl: 'player/slim/alex.png', slim: true},
+ {skinUrl: 'player/slim/ari.png', slim: true},
+ {skinUrl: 'player/slim/efe.png', slim: true},
+ {skinUrl: 'player/slim/kai.png', slim: true},
+ {skinUrl: 'player/slim/makena.png', slim: true},
+ {skinUrl: 'player/slim/noor.png', slim: true},
+ {skinUrl: 'player/slim/steve.png', slim: true},
+ {skinUrl: 'player/slim/sunny.png', slim: true},
+ {skinUrl: 'player/slim/zuri.png', slim: true},
+
+ {skinUrl: 'player/wide/alex.png'},
+ {skinUrl: 'player/wide/ari.png'},
+ {skinUrl: 'player/wide/efe.png'},
+ {skinUrl: 'player/wide/kai.png'},
+ {skinUrl: 'player/wide/makena.png'},
+ {skinUrl: 'player/wide/noor.png'},
+ {skinUrl: 'player/wide/steve.png'},
+ {skinUrl: 'player/wide/sunny.png'},
+ {skinUrl: 'player/wide/zuri.png'},
+];
+
+function User(props: { appData: AppState, setAppData: React.Dispatch> }) {
+ const {appData, setAppData} = props;
+
+ const [skinData, setSkinData] = React.useState(null);
+
+ React.useEffect(() => {
+ setSkinData(null);
+ axios.get('/sessionserver/session/minecraft/profile/' + appData.uuid).then(response => {
+ let texturesProp = response.data.properties.find((v: any) => v.name == 'textures');
+ let profile: any = {};
+ if (texturesProp) {
+ profile = JSON.parse(window.atob(texturesProp.value));
+ }
+ if (profile.textures && profile.textures.SKIN) {
+ let skinUrl = profile.textures.SKIN.url;
+ let slim = profile.textures.SKIN.metadata ? profile.textures.SKIN.metadata.model == 'slim' : false;
+ let capeUrl = undefined;
+ if (profile.textures.CAPE) {
+ capeUrl = profile.textures.CAPE.url;
+ }
+ setSkinData({
+ skinUrl,
+ capeUrl,
+ slim
+ });
+ } else if (profile.textures && profile.textures.CAPE) {
+ // 显示默认材质
+ let index = getUUIDHashCode(appData.uuid) % DEFAULT_SKINS.length;
+ setSkinData({
+ ...DEFAULT_SKINS[index],
+ capeUrl: profile.textures.CAPE.url
+ });
+ } else {
+ // 显示默认材质
+ let index = getUUIDHashCode(appData.uuid) % DEFAULT_SKINS.length;
+ setSkinData(DEFAULT_SKINS[index]);
+ }
+ });
+ }, [appData]);
+
+ return (
+
+
+
+
+
+
+ {skinData && }
+
+
+
+
+ );
+}
+
+function getUUIDHashCode(uuid: string) {
+ const uuidNoDash = uuid.replace(/-/g, '');
+ const mostMost = parseInt(uuidNoDash.substring(0, 8), 16);
+ const mostLeast = parseInt(uuidNoDash.substring(8, 16), 16);
+ const leastMost = parseInt(uuidNoDash.substring(16, 24), 16);
+ const leastLeast = parseInt(uuidNoDash.substring(24, 32), 16);
+ return mostMost ^ mostLeast ^ leastMost ^ leastLeast;
+}
+
+export default User;
\ No newline at end of file
diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts
new file mode 100644
index 0000000..fff48e3
--- /dev/null
+++ b/frontend/src/vite-env.d.ts
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2023. Gardel and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+///
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
new file mode 100644
index 0000000..3d0a51a
--- /dev/null
+++ b/frontend/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
+ "allowJs": false,
+ "skipLibCheck": true,
+ "esModuleInterop": false,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "module": "ESNext",
+ "moduleResolution": "Node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx"
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json
new file mode 100644
index 0000000..9d31e2a
--- /dev/null
+++ b/frontend/tsconfig.node.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "module": "ESNext",
+ "moduleResolution": "Node",
+ "allowSyntheticDefaultImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
new file mode 100644
index 0000000..ee92e0b
--- /dev/null
+++ b/frontend/vite.config.ts
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023. Gardel and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+import mockDevServerPlugin from 'vite-plugin-mock-dev-server'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react(), mockDevServerPlugin()],
+ server: {
+ proxy: {
+ '^/(authserver|users|sessionserver|textures|api|minecraftservices)': {
+ target: 'http://localhost:8080'
+ }
+ }
+ },
+ base: ''
+})
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
new file mode 100644
index 0000000..00ba248
--- /dev/null
+++ b/frontend/yarn.lock
@@ -0,0 +1,1981 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@ampproject/remapping@^2.1.0":
+ version "2.2.0"
+ resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz"
+ integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.1.0"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz"
+ integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==
+ dependencies:
+ "@babel/highlight" "^7.18.6"
+
+"@babel/compat-data@^7.20.5":
+ version "7.20.14"
+ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.14.tgz"
+ integrity sha512-0YpKHD6ImkWMEINCyDAD0HLLUH/lPCefG8ld9it8DJB2wnApraKuhgYTvTY1z7UFIfBTGy5LwncZ+5HWWGbhFw==
+
+"@babel/core@^7.20.7":
+ version "7.20.12"
+ resolved "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz"
+ integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==
+ dependencies:
+ "@ampproject/remapping" "^2.1.0"
+ "@babel/code-frame" "^7.18.6"
+ "@babel/generator" "^7.20.7"
+ "@babel/helper-compilation-targets" "^7.20.7"
+ "@babel/helper-module-transforms" "^7.20.11"
+ "@babel/helpers" "^7.20.7"
+ "@babel/parser" "^7.20.7"
+ "@babel/template" "^7.20.7"
+ "@babel/traverse" "^7.20.12"
+ "@babel/types" "^7.20.7"
+ convert-source-map "^1.7.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.2.2"
+ semver "^6.3.0"
+
+"@babel/generator@^7.20.7":
+ version "7.20.14"
+ resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.20.14.tgz"
+ integrity sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==
+ dependencies:
+ "@babel/types" "^7.20.7"
+ "@jridgewell/gen-mapping" "^0.3.2"
+ jsesc "^2.5.1"
+
+"@babel/helper-compilation-targets@^7.20.7":
+ version "7.20.7"
+ resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz"
+ integrity sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==
+ dependencies:
+ "@babel/compat-data" "^7.20.5"
+ "@babel/helper-validator-option" "^7.18.6"
+ browserslist "^4.21.3"
+ lru-cache "^5.1.1"
+ semver "^6.3.0"
+
+"@babel/helper-environment-visitor@^7.18.9":
+ version "7.18.9"
+ resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz"
+ integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
+
+"@babel/helper-function-name@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz"
+ integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==
+ dependencies:
+ "@babel/template" "^7.18.10"
+ "@babel/types" "^7.19.0"
+
+"@babel/helper-hoist-variables@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz"
+ integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==
+ dependencies:
+ "@babel/types" "^7.18.6"
+
+"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz"
+ integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==
+ dependencies:
+ "@babel/types" "^7.18.6"
+
+"@babel/helper-module-transforms@^7.20.11":
+ version "7.20.11"
+ resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz"
+ integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.18.9"
+ "@babel/helper-module-imports" "^7.18.6"
+ "@babel/helper-simple-access" "^7.20.2"
+ "@babel/helper-split-export-declaration" "^7.18.6"
+ "@babel/helper-validator-identifier" "^7.19.1"
+ "@babel/template" "^7.20.7"
+ "@babel/traverse" "^7.20.10"
+ "@babel/types" "^7.20.7"
+
+"@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.19.0":
+ version "7.20.2"
+ resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz"
+ integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==
+
+"@babel/helper-simple-access@^7.20.2":
+ version "7.20.2"
+ resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz"
+ integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==
+ dependencies:
+ "@babel/types" "^7.20.2"
+
+"@babel/helper-split-export-declaration@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz"
+ integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==
+ dependencies:
+ "@babel/types" "^7.18.6"
+
+"@babel/helper-string-parser@^7.19.4":
+ version "7.19.4"
+ resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz"
+ integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==
+
+"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1":
+ version "7.19.1"
+ resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz"
+ integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
+
+"@babel/helper-validator-option@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz"
+ integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==
+
+"@babel/helpers@^7.20.7":
+ version "7.20.13"
+ resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.13.tgz"
+ integrity sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg==
+ dependencies:
+ "@babel/template" "^7.20.7"
+ "@babel/traverse" "^7.20.13"
+ "@babel/types" "^7.20.7"
+
+"@babel/highlight@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz"
+ integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.18.6"
+ chalk "^2.0.0"
+ js-tokens "^4.0.0"
+
+"@babel/parser@^7.20.13", "@babel/parser@^7.20.7":
+ version "7.20.13"
+ resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.20.13.tgz"
+ integrity sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==
+
+"@babel/plugin-syntax-jsx@^7.17.12":
+ version "7.18.6"
+ resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz"
+ integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-react-jsx-self@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.18.6.tgz"
+ integrity sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-react-jsx-source@^7.19.6":
+ version "7.19.6"
+ resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.19.6.tgz"
+ integrity sha512-RpAi004QyMNisst/pvSanoRdJ4q+jMCWyk9zdw/CyLB9j8RXEahodR6l2GyttDRyEVWZtbN+TpLiHJ3t34LbsQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.19.0"
+
+"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.7", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.6", "@babel/runtime@^7.20.7", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
+ version "7.20.13"
+ resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz"
+ integrity sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==
+ dependencies:
+ regenerator-runtime "^0.13.11"
+
+"@babel/template@^7.18.10", "@babel/template@^7.20.7":
+ version "7.20.7"
+ resolved "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz"
+ integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==
+ dependencies:
+ "@babel/code-frame" "^7.18.6"
+ "@babel/parser" "^7.20.7"
+ "@babel/types" "^7.20.7"
+
+"@babel/traverse@^7.20.10", "@babel/traverse@^7.20.12", "@babel/traverse@^7.20.13":
+ version "7.20.13"
+ resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.13.tgz"
+ integrity sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==
+ dependencies:
+ "@babel/code-frame" "^7.18.6"
+ "@babel/generator" "^7.20.7"
+ "@babel/helper-environment-visitor" "^7.18.9"
+ "@babel/helper-function-name" "^7.19.0"
+ "@babel/helper-hoist-variables" "^7.18.6"
+ "@babel/helper-split-export-declaration" "^7.18.6"
+ "@babel/parser" "^7.20.13"
+ "@babel/types" "^7.20.7"
+ debug "^4.1.0"
+ globals "^11.1.0"
+
+"@babel/types@^7.18.6", "@babel/types@^7.19.0", "@babel/types@^7.20.2", "@babel/types@^7.20.7":
+ version "7.20.7"
+ resolved "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz"
+ integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==
+ dependencies:
+ "@babel/helper-string-parser" "^7.19.4"
+ "@babel/helper-validator-identifier" "^7.19.1"
+ to-fast-properties "^2.0.0"
+
+"@chevrotain/cst-dts-gen@10.4.2":
+ version "10.4.2"
+ resolved "https://registry.yarnpkg.com/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.4.2.tgz#a3426dba2c48cf6c90e49a0676aea750e8f43e88"
+ integrity sha512-0+4bNjlndNWMoVLH/+y4uHnf6GrTipsC+YTppJxelVJo+xeRVQ0s2PpkdDCVTsu7efyj+8r1gFiwVXsp6JZ0iQ==
+ dependencies:
+ "@chevrotain/gast" "10.4.2"
+ "@chevrotain/types" "10.4.2"
+ lodash "4.17.21"
+
+"@chevrotain/gast@10.4.2":
+ version "10.4.2"
+ resolved "https://registry.yarnpkg.com/@chevrotain/gast/-/gast-10.4.2.tgz#236dc48e54cba16260c03bece25d5a3b6e2f5dab"
+ integrity sha512-4ZAn8/mjkmYonilSJ60gGj1tAF0cVWYUMlIGA0e4ATAc3a648aCnvpBw7zlPHDQjFp50XC13iyWEgWAKiRKTOA==
+ dependencies:
+ "@chevrotain/types" "10.4.2"
+ lodash "4.17.21"
+
+"@chevrotain/types@10.4.2":
+ version "10.4.2"
+ resolved "https://registry.yarnpkg.com/@chevrotain/types/-/types-10.4.2.tgz#18be6b7a3226b121fccec08c2ba8433219a6813c"
+ integrity sha512-QzSCjg6G4MvIoLeIgOiMR0IgzkGEQqrNJJIr3T5ETRa7l4Av4AMIiEctV99mvDr57iXwwk0/kr3RJxiU36Nevw==
+
+"@chevrotain/utils@10.4.2":
+ version "10.4.2"
+ resolved "https://registry.yarnpkg.com/@chevrotain/utils/-/utils-10.4.2.tgz#87735732184cc5a2f8aad2f3454082294ef3c924"
+ integrity sha512-V34dacxWLwKcvcy32dx96ADJVdB7kOJLm7LyBkBQw5u5HC9WdEFw2G17zml+U3ivavGTrGPJHl8o9/UJm0PlUw==
+
+"@emotion/babel-plugin@^11.10.5":
+ version "11.10.5"
+ resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.5.tgz"
+ integrity sha512-xE7/hyLHJac7D2Ve9dKroBBZqBT7WuPQmWcq7HSGb84sUuP4mlOWoB8dvVfD9yk5DHkU1m6RW7xSoDtnQHNQeA==
+ dependencies:
+ "@babel/helper-module-imports" "^7.16.7"
+ "@babel/plugin-syntax-jsx" "^7.17.12"
+ "@babel/runtime" "^7.18.3"
+ "@emotion/hash" "^0.9.0"
+ "@emotion/memoize" "^0.8.0"
+ "@emotion/serialize" "^1.1.1"
+ babel-plugin-macros "^3.1.0"
+ convert-source-map "^1.5.0"
+ escape-string-regexp "^4.0.0"
+ find-root "^1.1.0"
+ source-map "^0.5.7"
+ stylis "4.1.3"
+
+"@emotion/cache@^11.10.5":
+ version "11.10.5"
+ resolved "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.5.tgz"
+ integrity sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA==
+ dependencies:
+ "@emotion/memoize" "^0.8.0"
+ "@emotion/sheet" "^1.2.1"
+ "@emotion/utils" "^1.2.0"
+ "@emotion/weak-memoize" "^0.3.0"
+ stylis "4.1.3"
+
+"@emotion/hash@^0.9.0":
+ version "0.9.0"
+ resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz"
+ integrity sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==
+
+"@emotion/is-prop-valid@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz"
+ integrity sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==
+ dependencies:
+ "@emotion/memoize" "^0.8.0"
+
+"@emotion/memoize@^0.8.0":
+ version "0.8.0"
+ resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz"
+ integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==
+
+"@emotion/react@^11.10.5":
+ version "11.10.5"
+ resolved "https://registry.npmjs.org/@emotion/react/-/react-11.10.5.tgz"
+ integrity sha512-TZs6235tCJ/7iF6/rvTaOH4oxQg2gMAcdHemjwLKIjKz4rRuYe1HJ2TQJKnAcRAfOUDdU8XoDadCe1rl72iv8A==
+ dependencies:
+ "@babel/runtime" "^7.18.3"
+ "@emotion/babel-plugin" "^11.10.5"
+ "@emotion/cache" "^11.10.5"
+ "@emotion/serialize" "^1.1.1"
+ "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0"
+ "@emotion/utils" "^1.2.0"
+ "@emotion/weak-memoize" "^0.3.0"
+ hoist-non-react-statics "^3.3.1"
+
+"@emotion/serialize@^1.1.1":
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz"
+ integrity sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==
+ dependencies:
+ "@emotion/hash" "^0.9.0"
+ "@emotion/memoize" "^0.8.0"
+ "@emotion/unitless" "^0.8.0"
+ "@emotion/utils" "^1.2.0"
+ csstype "^3.0.2"
+
+"@emotion/sheet@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz"
+ integrity sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==
+
+"@emotion/styled@^11.10.5":
+ version "11.10.5"
+ resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.5.tgz"
+ integrity sha512-8EP6dD7dMkdku2foLoruPCNkRevzdcBaY6q0l0OsbyJK+x8D9HWjX27ARiSIKNF634hY9Zdoedh8bJCiva8yZw==
+ dependencies:
+ "@babel/runtime" "^7.18.3"
+ "@emotion/babel-plugin" "^11.10.5"
+ "@emotion/is-prop-valid" "^1.2.0"
+ "@emotion/serialize" "^1.1.1"
+ "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0"
+ "@emotion/utils" "^1.2.0"
+
+"@emotion/unitless@^0.8.0":
+ version "0.8.0"
+ resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz"
+ integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==
+
+"@emotion/use-insertion-effect-with-fallbacks@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz"
+ integrity sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==
+
+"@emotion/utils@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz"
+ integrity sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==
+
+"@emotion/weak-memoize@^0.3.0":
+ version "0.3.0"
+ resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz"
+ integrity sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==
+
+"@esbuild/android-arm64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz#cf91e86df127aa3d141744edafcba0abdc577d23"
+ integrity sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==
+
+"@esbuild/android-arm@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.16.17.tgz#025b6246d3f68b7bbaa97069144fb5fb70f2fff2"
+ integrity sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==
+
+"@esbuild/android-x64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.16.17.tgz#c820e0fef982f99a85c4b8bfdd582835f04cd96e"
+ integrity sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==
+
+"@esbuild/darwin-arm64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz#edef4487af6b21afabba7be5132c26d22379b220"
+ integrity sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==
+
+"@esbuild/darwin-x64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz#42829168730071c41ef0d028d8319eea0e2904b4"
+ integrity sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==
+
+"@esbuild/freebsd-arm64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz#1f4af488bfc7e9ced04207034d398e793b570a27"
+ integrity sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==
+
+"@esbuild/freebsd-x64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz#636306f19e9bc981e06aa1d777302dad8fddaf72"
+ integrity sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==
+
+"@esbuild/linux-arm64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz#a003f7ff237c501e095d4f3a09e58fc7b25a4aca"
+ integrity sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==
+
+"@esbuild/linux-arm@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz#b591e6a59d9c4fe0eeadd4874b157ab78cf5f196"
+ integrity sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==
+
+"@esbuild/linux-ia32@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz#24333a11027ef46a18f57019450a5188918e2a54"
+ integrity sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==
+
+"@esbuild/linux-loong64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz#d5ad459d41ed42bbd4d005256b31882ec52227d8"
+ integrity sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==
+
+"@esbuild/linux-mips64el@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz#4e5967a665c38360b0a8205594377d4dcf9c3726"
+ integrity sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==
+
+"@esbuild/linux-ppc64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz#206443a02eb568f9fdf0b438fbd47d26e735afc8"
+ integrity sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==
+
+"@esbuild/linux-riscv64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz#c351e433d009bf256e798ad048152c8d76da2fc9"
+ integrity sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==
+
+"@esbuild/linux-s390x@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz#661f271e5d59615b84b6801d1c2123ad13d9bd87"
+ integrity sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==
+
+"@esbuild/linux-x64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz#e4ba18e8b149a89c982351443a377c723762b85f"
+ integrity sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==
+
+"@esbuild/netbsd-x64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz#7d4f4041e30c5c07dd24ffa295c73f06038ec775"
+ integrity sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==
+
+"@esbuild/openbsd-x64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz#970fa7f8470681f3e6b1db0cc421a4af8060ec35"
+ integrity sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==
+
+"@esbuild/sunos-x64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz#abc60e7c4abf8b89fb7a4fe69a1484132238022c"
+ integrity sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==
+
+"@esbuild/win32-arm64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz#7b0ff9e8c3265537a7a7b1fd9a24e7bd39fcd87a"
+ integrity sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==
+
+"@esbuild/win32-ia32@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz#e90fe5267d71a7b7567afdc403dfd198c292eb09"
+ integrity sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==
+
+"@esbuild/win32-x64@0.16.17":
+ version "0.16.17"
+ resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz"
+ integrity sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==
+
+"@fontsource/roboto@^4.5.8":
+ version "4.5.8"
+ resolved "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.8.tgz"
+ integrity sha512-CnD7zLItIzt86q4Sj3kZUiLcBk1dSk81qcqgMGaZe7SQ1P8hFNxhMl5AZthK1zrDM5m74VVhaOpuMGIL4gagaA==
+
+"@jridgewell/gen-mapping@^0.1.0":
+ version "0.1.1"
+ resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz"
+ integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==
+ dependencies:
+ "@jridgewell/set-array" "^1.0.0"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+
+"@jridgewell/gen-mapping@^0.3.2":
+ version "0.3.2"
+ resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz"
+ integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==
+ dependencies:
+ "@jridgewell/set-array" "^1.0.1"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/resolve-uri@3.1.0":
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz"
+ integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
+
+"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz"
+ integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
+
+"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13":
+ version "1.4.14"
+ resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz"
+ integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
+
+"@jridgewell/trace-mapping@^0.3.9":
+ version "0.3.17"
+ resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz"
+ integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==
+ dependencies:
+ "@jridgewell/resolve-uri" "3.1.0"
+ "@jridgewell/sourcemap-codec" "1.4.14"
+
+"@mui/base@5.0.0-alpha.115":
+ version "5.0.0-alpha.115"
+ resolved "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.115.tgz"
+ integrity sha512-OGQ84whT/yNYd6xKCGGS6MxqEfjVjk5esXM7HP6bB2Rim7QICUapxZt4nm8q39fpT08rNDkv3xPVqDDwRdRg1g==
+ dependencies:
+ "@babel/runtime" "^7.20.7"
+ "@emotion/is-prop-valid" "^1.2.0"
+ "@mui/types" "^7.2.3"
+ "@mui/utils" "^5.11.2"
+ "@popperjs/core" "^2.11.6"
+ clsx "^1.2.1"
+ prop-types "^15.8.1"
+ react-is "^18.2.0"
+
+"@mui/core-downloads-tracker@^5.11.6":
+ version "5.11.6"
+ resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.11.6.tgz"
+ integrity sha512-lbD3qdafBOf2dlqKhOcVRxaPAujX+9UlPC6v8iMugMeAXe0TCgU3QbGXY3zrJsu6ex64WYDpH4y1+WOOBmWMuA==
+
+"@mui/icons-material@^5.11.0":
+ version "5.11.0"
+ resolved "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.11.0.tgz"
+ integrity sha512-I2LaOKqO8a0xcLGtIozC9xoXjZAto5G5gh0FYUMAlbsIHNHIjn4Xrw9rvjY20vZonyiGrZNMAlAXYkY6JvhF6A==
+ dependencies:
+ "@babel/runtime" "^7.20.6"
+
+"@mui/material@^5.11.6":
+ version "5.11.6"
+ resolved "https://registry.npmjs.org/@mui/material/-/material-5.11.6.tgz"
+ integrity sha512-MzkkL5KC2PCkFiv8cLpkzgLUPXSrAtnvJBR0emV7mLVWbkwV3n5832vjBx154B6R032fHjFTziTh7YEb50nK6Q==
+ dependencies:
+ "@babel/runtime" "^7.20.7"
+ "@mui/base" "5.0.0-alpha.115"
+ "@mui/core-downloads-tracker" "^5.11.6"
+ "@mui/system" "^5.11.5"
+ "@mui/types" "^7.2.3"
+ "@mui/utils" "^5.11.2"
+ "@types/react-transition-group" "^4.4.5"
+ clsx "^1.2.1"
+ csstype "^3.1.1"
+ prop-types "^15.8.1"
+ react-is "^18.2.0"
+ react-transition-group "^4.4.5"
+
+"@mui/private-theming@^5.11.2":
+ version "5.11.2"
+ resolved "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.2.tgz"
+ integrity sha512-qZwMaqRFPwlYmqwVKblKBGKtIjJRAj3nsvX93pOmatsXyorW7N/0IPE/swPgz1VwChXhHO75DwBEx8tB+aRMNg==
+ dependencies:
+ "@babel/runtime" "^7.20.7"
+ "@mui/utils" "^5.11.2"
+ prop-types "^15.8.1"
+
+"@mui/styled-engine@^5.11.0":
+ version "5.11.0"
+ resolved "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.11.0.tgz"
+ integrity sha512-AF06K60Zc58qf0f7X+Y/QjaHaZq16znliLnGc9iVrV/+s8Ln/FCoeNuFvhlCbZZQ5WQcJvcy59zp0nXrklGGPQ==
+ dependencies:
+ "@babel/runtime" "^7.20.6"
+ "@emotion/cache" "^11.10.5"
+ csstype "^3.1.1"
+ prop-types "^15.8.1"
+
+"@mui/system@^5.11.5":
+ version "5.11.5"
+ resolved "https://registry.npmjs.org/@mui/system/-/system-5.11.5.tgz"
+ integrity sha512-KNVsJ0sgRRp2XBqhh4wPS5aacteqjwxgiYTVwVnll2fgkgunZKo3DsDiGMrFlCg25ZHA3Ax58txWGE9w58zp0w==
+ dependencies:
+ "@babel/runtime" "^7.20.7"
+ "@mui/private-theming" "^5.11.2"
+ "@mui/styled-engine" "^5.11.0"
+ "@mui/types" "^7.2.3"
+ "@mui/utils" "^5.11.2"
+ clsx "^1.2.1"
+ csstype "^3.1.1"
+ prop-types "^15.8.1"
+
+"@mui/types@^7.2.3":
+ version "7.2.3"
+ resolved "https://registry.npmjs.org/@mui/types/-/types-7.2.3.tgz"
+ integrity sha512-tZ+CQggbe9Ol7e/Fs5RcKwg/woU+o8DCtOnccX6KmbBc7YrfqMYEYuaIcXHuhpT880QwNkZZ3wQwvtlDFA2yOw==
+
+"@mui/utils@^5.11.2":
+ version "5.11.2"
+ resolved "https://registry.npmjs.org/@mui/utils/-/utils-5.11.2.tgz"
+ integrity sha512-AyizuHHlGdAtH5hOOXBW3kriuIwUIKUIgg0P7LzMvzf6jPhoQbENYqY6zJqfoZ7fAWMNNYT8mgN5EftNGzwE2w==
+ dependencies:
+ "@babel/runtime" "^7.20.7"
+ "@types/prop-types" "^15.7.5"
+ "@types/react-is" "^16.7.1 || ^17.0.0"
+ prop-types "^15.8.1"
+ react-is "^18.2.0"
+
+"@nodelib/fs.scandir@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.5"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.walk@^1.2.3":
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
+"@popperjs/core@^2.11.6":
+ version "2.11.6"
+ resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz"
+ integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==
+
+"@react-spring/animated@~9.6.1":
+ version "9.6.1"
+ resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.6.1.tgz#ccc626d847cbe346f5f8815d0928183c647eb425"
+ integrity sha512-ls/rJBrAqiAYozjLo5EPPLLOb1LM0lNVQcXODTC1SMtS6DbuBCPaKco5svFUQFMP2dso3O+qcC4k9FsKc0KxMQ==
+ dependencies:
+ "@react-spring/shared" "~9.6.1"
+ "@react-spring/types" "~9.6.1"
+
+"@react-spring/core@~9.6.1":
+ version "9.6.1"
+ resolved "https://registry.yarnpkg.com/@react-spring/core/-/core-9.6.1.tgz#ebe07c20682b360b06af116ea24e2b609e778c10"
+ integrity sha512-3HAAinAyCPessyQNNXe5W0OHzRfa8Yo5P748paPcmMowZ/4sMfaZ2ZB6e5x5khQI8NusOHj8nquoutd6FRY5WQ==
+ dependencies:
+ "@react-spring/animated" "~9.6.1"
+ "@react-spring/rafz" "~9.6.1"
+ "@react-spring/shared" "~9.6.1"
+ "@react-spring/types" "~9.6.1"
+
+"@react-spring/rafz@~9.6.1":
+ version "9.6.1"
+ resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.6.1.tgz#d71aafb92b78b24e4ff84639f52745afc285c38d"
+ integrity sha512-v6qbgNRpztJFFfSE3e2W1Uz+g8KnIBs6SmzCzcVVF61GdGfGOuBrbjIcp+nUz301awVmREKi4eMQb2Ab2gGgyQ==
+
+"@react-spring/shared@~9.6.1":
+ version "9.6.1"
+ resolved "https://registry.yarnpkg.com/@react-spring/shared/-/shared-9.6.1.tgz#4e2e4296910656c02bd9fd54c559702bc836ac4e"
+ integrity sha512-PBFBXabxFEuF8enNLkVqMC9h5uLRBo6GQhRMQT/nRTnemVENimgRd+0ZT4yFnAQ0AxWNiJfX3qux+bW2LbG6Bw==
+ dependencies:
+ "@react-spring/rafz" "~9.6.1"
+ "@react-spring/types" "~9.6.1"
+
+"@react-spring/three@^9.3.1":
+ version "9.6.1"
+ resolved "https://registry.yarnpkg.com/@react-spring/three/-/three-9.6.1.tgz#095fcd1dc6509127c33c14486d88289b89baeb9d"
+ integrity sha512-Tyw2YhZPKJAX3t2FcqvpLRb71CyTe1GvT3V+i+xJzfALgpk10uPGdGaQQ5Xrzmok1340DAeg2pR/MCfaW7b8AA==
+ dependencies:
+ "@react-spring/animated" "~9.6.1"
+ "@react-spring/core" "~9.6.1"
+ "@react-spring/shared" "~9.6.1"
+ "@react-spring/types" "~9.6.1"
+
+"@react-spring/types@~9.6.1":
+ version "9.6.1"
+ resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.6.1.tgz#913d3a68c5cbc1124fdb18eff919432f7b6abdde"
+ integrity sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q==
+
+"@react-three/drei@^9.56.12":
+ version "9.56.12"
+ resolved "https://registry.yarnpkg.com/@react-three/drei/-/drei-9.56.12.tgz#aa86cdc92359fdbd1f462ecc2d3d8c76c064cdf5"
+ integrity sha512-MkFBQnrBwZPIx3OmBSvdbhmLTJIbyyGQW2o6k5f+mBbSa/Nhtqlx7P8j+iucvlUgE98j4k8LcB1l+GUAz+9/vg==
+ dependencies:
+ "@babel/runtime" "^7.11.2"
+ "@react-spring/three" "^9.3.1"
+ "@use-gesture/react" "^10.2.24"
+ camera-controls "^2.0.1"
+ detect-gpu "^5.0.9"
+ glsl-noise "^0.0.0"
+ lodash.clamp "^4.0.3"
+ lodash.omit "^4.5.0"
+ lodash.pick "^4.4.0"
+ maath "^0.5.2"
+ meshline "^3.1.6"
+ react-composer "^5.0.3"
+ react-merge-refs "^1.1.0"
+ stats.js "^0.17.0"
+ suspend-react "^0.0.8"
+ three-mesh-bvh "^0.5.22"
+ three-stdlib "^2.21.8"
+ troika-three-text "^0.47.1"
+ utility-types "^3.10.0"
+ zustand "^3.5.13"
+
+"@react-three/fiber@^8.10.1":
+ version "8.10.1"
+ resolved "https://registry.yarnpkg.com/@react-three/fiber/-/fiber-8.10.1.tgz#598dacebd2563302650280f13e1e29d0ccde7982"
+ integrity sha512-TuI+Re6oOSwuR8XGBLdR3KgmUetVblRKM68ex4ArcvJJrFqrKFAyiQNIWkYA4T600VeE+dn1CHAmXH6X8YgJkg==
+ dependencies:
+ "@babel/runtime" "^7.17.8"
+ "@types/react-reconciler" "^0.26.7"
+ its-fine "^1.0.6"
+ react-reconciler "^0.27.0"
+ react-use-measure "^2.1.1"
+ scheduler "^0.21.0"
+ suspend-react "^0.0.8"
+ zustand "^3.7.1"
+
+"@react-three/postprocessing@^2.7.0":
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/@react-three/postprocessing/-/postprocessing-2.7.0.tgz#bae6be248bdb43cbab3d125b23ba5b0de4d934d2"
+ integrity sha512-lJfV8GYp+L1SlGRcl8QPUg9QMdO+8ojW2kfaEc/MuvoI4rX3TRhVd3qFjjF++0bBmzt8LeQpDHCOHFAaT3MNYA==
+ dependencies:
+ postprocessing "^6.29.0"
+ react-merge-refs "^1.1.0"
+ screen-space-reflections "2.5.0"
+ three-stdlib "^2.8.11"
+
+"@types/offscreencanvas@^2019.6.4":
+ version "2019.7.0"
+ resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz#e4a932069db47bb3eabeb0b305502d01586fa90d"
+ integrity sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==
+
+"@types/parse-json@^4.0.0":
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz"
+ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
+
+"@types/prop-types@*", "@types/prop-types@^15.7.5":
+ version "15.7.5"
+ resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz"
+ integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
+
+"@types/react-dom@^18.0.9":
+ version "18.0.10"
+ resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz"
+ integrity sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react-is@^16.7.1 || ^17.0.0":
+ version "17.0.3"
+ resolved "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.3.tgz"
+ integrity sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react-reconciler@^0.26.7":
+ version "0.26.7"
+ resolved "https://registry.yarnpkg.com/@types/react-reconciler/-/react-reconciler-0.26.7.tgz#0c4643f30821ae057e401b0d9037e03e8e9b2a36"
+ integrity sha512-mBDYl8x+oyPX/VBb3E638N0B7xG+SPk/EAMcVPeexqus/5aTpTphQi0curhhshOqRrc9t6OPoJfEUkbymse/lQ==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react-reconciler@^0.28.0":
+ version "0.28.2"
+ resolved "https://registry.yarnpkg.com/@types/react-reconciler/-/react-reconciler-0.28.2.tgz#f16b0e8cc4748af70ca975eaaace0d79582c71fa"
+ integrity sha512-8tu6lHzEgYPlfDf/J6GOQdIc+gs+S2yAqlby3zTsB3SP2svlqTYe5fwZNtZyfactP74ShooP2vvi1BOp9ZemWw==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react-transition-group@^4.4.5":
+ version "4.4.5"
+ resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz"
+ integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react@*", "@types/react@^18.0.26":
+ version "18.0.27"
+ resolved "https://registry.npmjs.org/@types/react/-/react-18.0.27.tgz"
+ integrity sha512-3vtRKHgVxu3Jp9t718R9BuzoD4NcQ8YJ5XRzsSKxNDiDonD2MXIT1TmSkenxuCycZJoQT5d2vE8LwWJxBC1gmA==
+ dependencies:
+ "@types/prop-types" "*"
+ "@types/scheduler" "*"
+ csstype "^3.0.2"
+
+"@types/scheduler@*":
+ version "0.16.2"
+ resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz"
+ integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
+
+"@types/three@^0.148.0":
+ version "0.148.1"
+ resolved "https://registry.yarnpkg.com/@types/three/-/three-0.148.1.tgz#e999a1a4840c12da8723187c315d8c8781d1066b"
+ integrity sha512-gZwIyTBMxKXqJHXmZ0dzvDieuQ4hz8MPNHtkRrAwER/xPlAh9eP2WIfaolvQY+wJAzlNV5a9ceS4JT+i/jybsw==
+ dependencies:
+ "@types/webxr" "*"
+
+"@types/webxr@*":
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/@types/webxr/-/webxr-0.5.1.tgz#4908349419104bd476a4252d04e4c3abb496748d"
+ integrity sha512-xlFXPfgJR5vIuDefhaHuUM9uUgvPaXB6GKdXy2gdEh8gBWQZ2ul24AJz3foUd8NNKlSTQuWYJpCb1/pL81m1KQ==
+
+"@use-gesture/core@10.2.24":
+ version "10.2.24"
+ resolved "https://registry.yarnpkg.com/@use-gesture/core/-/core-10.2.24.tgz#88d13a60954ba62463c774acb92d12bf7b3d810c"
+ integrity sha512-ZL7F9mgOn3Qlnp6QLI9jaOfcvqrx6JPE/BkdVSd8imveaFTm/a3udoO6f5Us/1XtqnL4347PsIiK6AtCvMHk2Q==
+
+"@use-gesture/react@^10.2.24":
+ version "10.2.24"
+ resolved "https://registry.yarnpkg.com/@use-gesture/react/-/react-10.2.24.tgz#bc13780381e786b286f099f69ea3801bb9ed27a5"
+ integrity sha512-rAZ8Nnpu1g4eFzqCPlaq+TppJpMy0dTpYOQx5KpfoBF4P3aWnCqwj7eKxcmdIb1NJKpIJj50DPugUH4mq5cpBg==
+ dependencies:
+ "@use-gesture/core" "10.2.24"
+
+"@vitejs/plugin-react@^3.0.0":
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-3.0.1.tgz"
+ integrity sha512-mx+QvYwIbbpOIJw+hypjnW1lAbKDHtWK5ibkF/V1/oMBu8HU/chb+SnqJDAsLq1+7rGqjktCEomMTM5KShzUKQ==
+ dependencies:
+ "@babel/core" "^7.20.7"
+ "@babel/plugin-transform-react-jsx-self" "^7.18.6"
+ "@babel/plugin-transform-react-jsx-source" "^7.19.6"
+ magic-string "^0.27.0"
+ react-refresh "^0.14.0"
+
+"@webgpu/glslang@^0.0.15":
+ version "0.0.15"
+ resolved "https://registry.yarnpkg.com/@webgpu/glslang/-/glslang-0.0.15.tgz#f5ccaf6015241e6175f4b90906b053f88483d1f2"
+ integrity sha512-niT+Prh3Aff8Uf1MVBVUsaNjFj9rJAKDXuoHIKiQbB+6IUP/3J3JIhBNyZ7lDhytvXxw6ppgnwKZdDJ08UMj4Q==
+
+ansi-styles@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz"
+ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+ dependencies:
+ color-convert "^1.9.0"
+
+anymatch@~3.1.2:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+ integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+asap@^2.0.0:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
+ integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
+axios@^1.2.6:
+ version "1.2.6"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-1.2.6.tgz#eacb6d065baa11bad5959e7ffa0cb6745c65f392"
+ integrity sha512-rC/7F08XxZwjMV4iuWv+JpD3E0Ksqg9nac4IIg6RwNuF0JTeWoCo/mBNG54+tNhhI11G3/VDRbdDQTs9hGp4pQ==
+ dependencies:
+ follow-redirects "^1.15.0"
+ form-data "^4.0.0"
+ proxy-from-env "^1.1.0"
+
+babel-plugin-macros@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz"
+ integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+ cosmiconfig "^7.0.0"
+ resolve "^1.19.0"
+
+bidi-js@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/bidi-js/-/bidi-js-1.0.2.tgz#1a497a762c2ddea377429d2649c9ce0f8a91527f"
+ integrity sha512-rzSy/k7WdX5zOyeHHCOixGXbCHkyogkxPKL2r8QtzHmVQDiWCXUWa18bLdMWT9CYMLOYTjWpTHawuev2ouYJVw==
+ dependencies:
+ require-from-string "^2.0.2"
+
+binary-extensions@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
+ integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
+
+braces@^3.0.2, braces@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ dependencies:
+ fill-range "^7.0.1"
+
+browserslist@^4.21.3:
+ version "4.21.4"
+ resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz"
+ integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==
+ dependencies:
+ caniuse-lite "^1.0.30001400"
+ electron-to-chromium "^1.4.251"
+ node-releases "^2.0.6"
+ update-browserslist-db "^1.0.9"
+
+bytes@3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
+ integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
+
+call-bind@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
+ integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
+ dependencies:
+ function-bind "^1.1.1"
+ get-intrinsic "^1.0.2"
+
+callsites@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
+ integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+
+camera-controls@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/camera-controls/-/camera-controls-2.0.1.tgz#051f6f5c9c2ea515250bf23b7e5bc0f0f12282c5"
+ integrity sha512-KYzlahxCFap5y+M3nkkzCYKAT1Rjh5jL7AOzFoDrygxrBiF+ffYzOridEywQBhqcUYU8hDErgqZNqFNUkkAzbQ==
+
+caniuse-lite@^1.0.30001400:
+ version "1.0.30001449"
+ resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001449.tgz"
+ integrity sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==
+
+chalk@^2.0.0:
+ version "2.4.2"
+ resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
+chevrotain@^10.1.2:
+ version "10.4.2"
+ resolved "https://registry.yarnpkg.com/chevrotain/-/chevrotain-10.4.2.tgz#9abeac6a60134931c0a0788b206400e5f7a3daba"
+ integrity sha512-gzF5GxE0Ckti5kZVuKEZycLntB5X2aj9RVY0r4/220GwQjdnljU+/t3kP74/FMWC7IzCDDEjQ9wsFUf0WCdSHg==
+ dependencies:
+ "@chevrotain/cst-dts-gen" "10.4.2"
+ "@chevrotain/gast" "10.4.2"
+ "@chevrotain/types" "10.4.2"
+ "@chevrotain/utils" "10.4.2"
+ lodash "4.17.21"
+ regexp-to-ast "0.5.0"
+
+chokidar@^3.5.3:
+ version "3.5.3"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
+ integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
+ dependencies:
+ anymatch "~3.1.2"
+ braces "~3.0.2"
+ glob-parent "~5.1.2"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.6.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+clsx@^1.1.0, clsx@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz"
+ integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
+
+co-body@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/co-body/-/co-body-6.1.0.tgz#d87a8efc3564f9bfe3aced8ef5cd04c7a8766547"
+ integrity sha512-m7pOT6CdLN7FuXUcpuz/8lfQ/L77x8SchHCF4G0RBTJO20Wzmhn5Sp4/5WsKy8OSpifBSUrmg83qEqaDHdyFuQ==
+ dependencies:
+ inflation "^2.0.0"
+ qs "^6.5.2"
+ raw-body "^2.3.3"
+ type-is "^1.6.16"
+
+color-convert@^1.9.0:
+ version "1.9.3"
+ resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz"
+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+ dependencies:
+ color-name "1.1.3"
+
+color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
+ integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
+
+combined-stream@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
+convert-source-map@^1.5.0, convert-source-map@^1.7.0:
+ version "1.9.0"
+ resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz"
+ integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
+
+cosmiconfig@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz"
+ integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==
+ dependencies:
+ "@types/parse-json" "^4.0.0"
+ import-fresh "^3.2.1"
+ parse-json "^5.0.0"
+ path-type "^4.0.0"
+ yaml "^1.10.0"
+
+csstype@^3.0.2, csstype@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz"
+ integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==
+
+debounce@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5"
+ integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==
+
+debug@^4.1.0, debug@^4.3.4:
+ version "4.3.4"
+ resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
+depd@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
+ integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
+
+detect-gpu@^5.0.9:
+ version "5.0.9"
+ resolved "https://registry.yarnpkg.com/detect-gpu/-/detect-gpu-5.0.9.tgz#bbaee58085a2e5765aade3df2f49c9393e70b39f"
+ integrity sha512-3wFHiw8OJjZqxQCbluNP8JNmoDEJuWf1LaLJRvOPC+X1aBQyHhS4R67BINQVoq2vuSrUnpMNIHQ+JXwKd3UhfA==
+ dependencies:
+ webgl-constants "^1.1.1"
+
+dezalgo@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81"
+ integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==
+ dependencies:
+ asap "^2.0.0"
+ wrappy "1"
+
+dom-helpers@^5.0.1:
+ version "5.2.1"
+ resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz"
+ integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
+ dependencies:
+ "@babel/runtime" "^7.8.7"
+ csstype "^3.0.2"
+
+draco3d@^1.4.1:
+ version "1.5.5"
+ resolved "https://registry.yarnpkg.com/draco3d/-/draco3d-1.5.5.tgz#6bf4bbdd65950e6153e991cb0dcb8a10323f610e"
+ integrity sha512-JVuNV0EJzD3LBYhGyIXJLeBID/EVtmFO1ZNhAYflTgiMiAJlbhXQmRRda/azjc8MRVMHh0gqGhiqHUo5dIXM8Q==
+
+electron-to-chromium@^1.4.251:
+ version "1.4.284"
+ resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz"
+ integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==
+
+error-ex@^1.3.1:
+ version "1.3.2"
+ resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz"
+ integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
+ dependencies:
+ is-arrayish "^0.2.1"
+
+esbuild@^0.16.3, esbuild@^0.16.9:
+ version "0.16.17"
+ resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz"
+ integrity sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==
+ optionalDependencies:
+ "@esbuild/android-arm" "0.16.17"
+ "@esbuild/android-arm64" "0.16.17"
+ "@esbuild/android-x64" "0.16.17"
+ "@esbuild/darwin-arm64" "0.16.17"
+ "@esbuild/darwin-x64" "0.16.17"
+ "@esbuild/freebsd-arm64" "0.16.17"
+ "@esbuild/freebsd-x64" "0.16.17"
+ "@esbuild/linux-arm" "0.16.17"
+ "@esbuild/linux-arm64" "0.16.17"
+ "@esbuild/linux-ia32" "0.16.17"
+ "@esbuild/linux-loong64" "0.16.17"
+ "@esbuild/linux-mips64el" "0.16.17"
+ "@esbuild/linux-ppc64" "0.16.17"
+ "@esbuild/linux-riscv64" "0.16.17"
+ "@esbuild/linux-s390x" "0.16.17"
+ "@esbuild/linux-x64" "0.16.17"
+ "@esbuild/netbsd-x64" "0.16.17"
+ "@esbuild/openbsd-x64" "0.16.17"
+ "@esbuild/sunos-x64" "0.16.17"
+ "@esbuild/win32-arm64" "0.16.17"
+ "@esbuild/win32-ia32" "0.16.17"
+ "@esbuild/win32-x64" "0.16.17"
+
+escalade@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz"
+ integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
+
+escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
+ integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
+
+escape-string-regexp@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
+ integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+
+fast-glob@^3.2.12:
+ version "3.2.12"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
+ integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.4"
+
+fastq@^1.6.0:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
+ integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==
+ dependencies:
+ reusify "^1.0.4"
+
+fflate@^0.6.9:
+ version "0.6.10"
+ resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.6.10.tgz#5f40f9659205936a2d18abf88b2e7781662b6d43"
+ integrity sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==
+
+fill-range@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+find-root@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz"
+ integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
+
+follow-redirects@^1.15.0:
+ version "1.15.2"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
+ integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
+
+form-data@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
+ integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
+formidable@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.1.1.tgz#81269cbea1a613240049f5f61a9d97731517414f"
+ integrity sha512-0EcS9wCFEzLvfiks7omJ+SiYJAiD+TzK4Pcw1UlUoGnhUxDcMKjt0P7x8wEb0u6OHu8Nb98WG3nxtlF5C7bvUQ==
+ dependencies:
+ dezalgo "^1.0.4"
+ hexoid "^1.0.0"
+ once "^1.4.0"
+ qs "^6.11.0"
+
+fsevents@~2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+ integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
+function-bind@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
+ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+gensync@^1.0.0-beta.2:
+ version "1.0.0-beta.2"
+ resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz"
+ integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
+
+get-intrinsic@^1.0.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f"
+ integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==
+ dependencies:
+ function-bind "^1.1.1"
+ has "^1.0.3"
+ has-symbols "^1.0.3"
+
+glob-parent@^5.1.2, glob-parent@~5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+globals@^11.1.0:
+ version "11.12.0"
+ resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz"
+ integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+
+glsl-noise@^0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/glsl-noise/-/glsl-noise-0.0.0.tgz#367745f3a33382c0eeec4cb54b7e99cfc1d7670b"
+ integrity sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w==
+
+has-flag@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz"
+ integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
+
+has-symbols@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
+ integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
+
+has@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz"
+ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+ dependencies:
+ function-bind "^1.1.1"
+
+hexoid@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18"
+ integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==
+
+hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1:
+ version "3.3.2"
+ resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz"
+ integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
+ dependencies:
+ react-is "^16.7.0"
+
+http-errors@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
+ integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
+ dependencies:
+ depd "2.0.0"
+ inherits "2.0.4"
+ setprototypeof "1.2.0"
+ statuses "2.0.1"
+ toidentifier "1.0.1"
+
+iconv-lite@0.4.24:
+ version "0.4.24"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+ integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3"
+
+import-fresh@^3.2.1:
+ version "3.3.0"
+ resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz"
+ integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
+ dependencies:
+ parent-module "^1.0.0"
+ resolve-from "^4.0.0"
+
+inflation@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/inflation/-/inflation-2.0.0.tgz#8b417e47c28f925a45133d914ca1fd389107f30f"
+ integrity sha512-m3xv4hJYR2oXw4o4Y5l6P5P16WYmazYof+el6Al3f+YlggGj6qT9kImBAnzDelRALnP5d3h4jGBPKzYCizjZZw==
+
+inherits@2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz"
+ integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
+
+is-binary-path@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+ integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+ dependencies:
+ binary-extensions "^2.0.0"
+
+is-core-module@^2.9.0:
+ version "2.11.0"
+ resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz"
+ integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==
+ dependencies:
+ has "^1.0.3"
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-glob@^4.0.1, is-glob@~4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+its-fine@^1.0.6:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/its-fine/-/its-fine-1.0.8.tgz#de55d8e5ed8e03f53de3e6fdb3147577bc86b077"
+ integrity sha512-MagTA9/J6kN3aEQsQu6by3nyrttCm0whCOYo4SfiNzOfYgcr1cb29mJ3zgluaJboaWOL/lHzJeMXi/QGSCfX1Q==
+ dependencies:
+ "@types/react-reconciler" "^0.28.0"
+
+"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz"
+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+jsesc@^2.5.1:
+ version "2.5.2"
+ resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz"
+ integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+
+json-parse-even-better-errors@^2.3.0:
+ version "2.3.1"
+ resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz"
+ integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+
+json5@^2.2.2:
+ version "2.2.3"
+ resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz"
+ integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
+
+ktx-parse@^0.4.5:
+ version "0.4.5"
+ resolved "https://registry.yarnpkg.com/ktx-parse/-/ktx-parse-0.4.5.tgz#79905e22281a9d3e602b2ff522df1ee7d1813aa6"
+ integrity sha512-MK3FOody4TXbFf8Yqv7EBbySw7aPvEcPX++Ipt6Sox+/YMFvR5xaTyhfNSk1AEmMy+RYIw81ctN4IMxCB8OAlg==
+
+lines-and-columns@^1.1.6:
+ version "1.2.4"
+ resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz"
+ integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+
+lodash.clamp@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/lodash.clamp/-/lodash.clamp-4.0.3.tgz#5c24bedeeeef0753560dc2b4cb4671f90a6ddfaa"
+ integrity sha512-HvzRFWjtcguTW7yd8NJBshuNaCa8aqNFtnswdT7f/cMd/1YKy5Zzoq4W/Oxvnx9l7aeY258uSdDfM793+eLsVg==
+
+lodash.omit@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-4.5.0.tgz#6eb19ae5a1ee1dd9df0b969e66ce0b7fa30b5e60"
+ integrity sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==
+
+lodash.pick@^4.4.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
+ integrity sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==
+
+lodash@4.17.21:
+ version "4.17.21"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+ integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+
+loose-envify@^1.1.0, loose-envify@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
+ integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
+ dependencies:
+ js-tokens "^3.0.0 || ^4.0.0"
+
+lru-cache@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz"
+ integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
+ dependencies:
+ yallist "^3.0.2"
+
+maath@^0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/maath/-/maath-0.5.2.tgz#b1adc883360e45eff3041a2bce45f8cdc0cd6d43"
+ integrity sha512-MFjfnXF5CzZaVnBuKc9y1FJh/BiPGqf19NH8Jm4o/jKTxuQ3RyPkcSIpuwdDhXrWROVKAxi3KjmHFUNMuIndbg==
+
+magic-string@^0.27.0:
+ version "0.27.0"
+ resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz"
+ integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==
+ dependencies:
+ "@jridgewell/sourcemap-codec" "^1.4.13"
+
+media-typer@0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+ integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
+
+merge2@^1.3.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+meshline@^3.1.6:
+ version "3.1.6"
+ resolved "https://registry.yarnpkg.com/meshline/-/meshline-3.1.6.tgz#eee67d9b0fd9841652cc1dc2d3833093ae8e68ca"
+ integrity sha512-8JZJOdaL5oz3PI/upG8JvP/5FfzYUOhrkJ8np/WKvXzl0/PZ2V9pqTvCIjSKv+w9ccg2xb+yyBhXAwt6ier3ug==
+
+micromatch@^4.0.4:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
+ integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
+ dependencies:
+ braces "^3.0.2"
+ picomatch "^2.3.1"
+
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.12, mime-types@~2.1.24:
+ version "2.1.35"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
+mmd-parser@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/mmd-parser/-/mmd-parser-1.0.4.tgz#87cc05782cb5974ca854f0303fc5147bc9d690e7"
+ integrity sha512-Qi0VCU46t2IwfGv5KF0+D/t9cizcDug7qnNoy9Ggk7aucp0tssV8IwTMkBlDbm+VqAf3cdQHTCARKSsuS2MYFg==
+
+ms@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+nanoid@^3.3.4:
+ version "3.3.4"
+ resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz"
+ integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
+
+node-releases@^2.0.6:
+ version "2.0.8"
+ resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz"
+ integrity sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+notistack@^2.0.8:
+ version "2.0.8"
+ resolved "https://registry.yarnpkg.com/notistack/-/notistack-2.0.8.tgz#78cdf34c64e311bf1d1d71c2123396bcdea5e95b"
+ integrity sha512-/IY14wkFp5qjPgKNvAdfL5Jp6q90+MjgKTPh4c81r/lW70KeuX6b9pE/4f8L4FG31cNudbN9siiFS5ql1aSLRw==
+ dependencies:
+ clsx "^1.1.0"
+ hoist-non-react-statics "^3.3.0"
+
+object-assign@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"
+ integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
+
+object-inspect@^1.9.0:
+ version "1.12.3"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9"
+ integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==
+
+once@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+ dependencies:
+ wrappy "1"
+
+opentype.js@^1.3.3:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/opentype.js/-/opentype.js-1.3.4.tgz#1c0e72e46288473cc4a4c6a2dc60fd7fe6020d77"
+ integrity sha512-d2JE9RP/6uagpQAVtJoF0pJJA/fgai89Cc50Yp0EJHk+eLp6QQ7gBoblsnubRULNY132I0J1QKMJ+JTbMqz4sw==
+ dependencies:
+ string.prototype.codepointat "^0.2.1"
+ tiny-inflate "^1.0.3"
+
+parent-module@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz"
+ integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
+ dependencies:
+ callsites "^3.0.0"
+
+parse-json@^5.0.0:
+ version "5.2.0"
+ resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz"
+ integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ error-ex "^1.3.1"
+ json-parse-even-better-errors "^2.3.0"
+ lines-and-columns "^1.1.6"
+
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+path-to-regexp@^6.2.1:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5"
+ integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==
+
+path-type@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz"
+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
+picocolors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz"
+ integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
+
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+postcss@^8.4.20:
+ version "8.4.21"
+ resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz"
+ integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==
+ dependencies:
+ nanoid "^3.3.4"
+ picocolors "^1.0.0"
+ source-map-js "^1.0.2"
+
+postprocessing@^6.29.0, postprocessing@^6.29.3:
+ version "6.29.3"
+ resolved "https://registry.yarnpkg.com/postprocessing/-/postprocessing-6.29.3.tgz#a878b2e60ef0402193e782e9580e90516a10f1f8"
+ integrity sha512-gxXC6LKLRwI4eSySdmxqEfQBMKEdQtxg5aYrdvJ/tPHDOS4aZAb/bY4ulQnL5YGKqCC6SmgNmU4dNIc68TTVMw==
+
+potpack@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.2.tgz#23b99e64eb74f5741ffe7656b5b5c4ddce8dfc14"
+ integrity sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==
+
+prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.8.1:
+ version "15.8.1"
+ resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
+ integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
+ dependencies:
+ loose-envify "^1.4.0"
+ object-assign "^4.1.1"
+ react-is "^16.13.1"
+
+proxy-from-env@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
+ integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
+
+qs@^6.11.0, qs@^6.5.2:
+ version "6.11.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
+ integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
+ dependencies:
+ side-channel "^1.0.4"
+
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+raw-body@^2.3.3:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
+ integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
+ dependencies:
+ bytes "3.1.2"
+ http-errors "2.0.0"
+ iconv-lite "0.4.24"
+ unpipe "1.0.0"
+
+react-composer@^5.0.3:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/react-composer/-/react-composer-5.0.3.tgz#7beb9513da5e8687f4f434ea1333ef36a4f3091b"
+ integrity sha512-1uWd07EME6XZvMfapwZmc7NgCZqDemcvicRi3wMJzXsQLvZ3L7fTHVyPy1bZdnWXM4iPjYuNE+uJ41MLKeTtnA==
+ dependencies:
+ prop-types "^15.6.0"
+
+react-dom@^18.2.0:
+ version "18.2.0"
+ resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz"
+ integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
+ dependencies:
+ loose-envify "^1.1.0"
+ scheduler "^0.23.0"
+
+react-hook-form@^7.43.0:
+ version "7.43.0"
+ resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.43.0.tgz"
+ integrity sha512-/rVEz7T0gLdSFwPqutJ1kn2e0sQNyb9ci/hmwEYr2YG0KF/LSuRLvNrf9QWJM+gj88CjDpDW5Bh/1AD7B2+z9Q==
+
+react-is@^16.13.1, react-is@^16.7.0:
+ version "16.13.1"
+ resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
+ integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+
+react-is@^18.2.0:
+ version "18.2.0"
+ resolved "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz"
+ integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
+
+react-merge-refs@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/react-merge-refs/-/react-merge-refs-1.1.0.tgz#73d88b892c6c68cbb7a66e0800faa374f4c38b06"
+ integrity sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ==
+
+react-reconciler@^0.27.0:
+ version "0.27.0"
+ resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.27.0.tgz#360124fdf2d76447c7491ee5f0e04503ed9acf5b"
+ integrity sha512-HmMDKciQjYmBRGuuhIaKA1ba/7a+UsM5FzOZsMO2JYHt9Jh8reCb7j1eDC95NOyUlKM9KRyvdx0flBuDvYSBoA==
+ dependencies:
+ loose-envify "^1.1.0"
+ scheduler "^0.21.0"
+
+react-refresh@^0.14.0:
+ version "0.14.0"
+ resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz"
+ integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==
+
+react-transition-group@^4.4.5:
+ version "4.4.5"
+ resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz"
+ integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==
+ dependencies:
+ "@babel/runtime" "^7.5.5"
+ dom-helpers "^5.0.1"
+ loose-envify "^1.4.0"
+ prop-types "^15.6.2"
+
+react-use-measure@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/react-use-measure/-/react-use-measure-2.1.1.tgz#5824537f4ee01c9469c45d5f7a8446177c6cc4ba"
+ integrity sha512-nocZhN26cproIiIduswYpV5y5lQpSQS1y/4KuvUCjSKmw7ZWIS/+g3aFnX3WdBkyuGUtTLif3UTqnLLhbDoQig==
+ dependencies:
+ debounce "^1.2.1"
+
+react@^18.2.0:
+ version "18.2.0"
+ resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
+ integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
+ dependencies:
+ loose-envify "^1.1.0"
+
+readdirp@~3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+ integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+ dependencies:
+ picomatch "^2.2.1"
+
+regenerator-runtime@^0.13.11:
+ version "0.13.11"
+ resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz"
+ integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
+
+regexp-to-ast@0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz#56c73856bee5e1fef7f73a00f1473452ab712a24"
+ integrity sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==
+
+require-from-string@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
+ integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+
+resolve-from@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz"
+ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
+resolve@^1.19.0, resolve@^1.22.1:
+ version "1.22.1"
+ resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz"
+ integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
+ dependencies:
+ is-core-module "^2.9.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+rollup@^3.7.0:
+ version "3.12.0"
+ resolved "https://registry.npmjs.org/rollup/-/rollup-3.12.0.tgz"
+ integrity sha512-4MZ8kA2HNYahIjz63rzrMMRvDqQDeS9LoriJvMuV0V6zIGysP36e9t4yObUfwdT9h/szXoHQideICftcdZklWg==
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
+"safer-buffer@>= 2.1.2 < 3":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+ integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+scheduler@^0.21.0:
+ version "0.21.0"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.21.0.tgz#6fd2532ff5a6d877b6edb12f00d8ab7e8f308820"
+ integrity sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==
+ dependencies:
+ loose-envify "^1.1.0"
+
+scheduler@^0.23.0:
+ version "0.23.0"
+ resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz"
+ integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
+ dependencies:
+ loose-envify "^1.1.0"
+
+screen-space-reflections@2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/screen-space-reflections/-/screen-space-reflections-2.5.0.tgz#2a6ea982da96f9c35f34a361b2555439f9fbb1f6"
+ integrity sha512-fWSDMhJS0xwD3LTxRRch7Lb9NzxsR66sCmtDmAA7i+OGnghUrBBsrha85ng7StnCBaLq/BKmZ97dLxWd1XgWdQ==
+
+semver@^6.3.0:
+ version "6.3.0"
+ resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz"
+ integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+
+setprototypeof@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
+ integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
+
+side-channel@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
+ integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
+ dependencies:
+ call-bind "^1.0.0"
+ get-intrinsic "^1.0.2"
+ object-inspect "^1.9.0"
+
+source-map-js@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz"
+ integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
+
+source-map@^0.5.7:
+ version "0.5.7"
+ resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz"
+ integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
+
+stats.js@^0.17.0:
+ version "0.17.0"
+ resolved "https://registry.yarnpkg.com/stats.js/-/stats.js-0.17.0.tgz#b1c3dc46d94498b578b7fd3985b81ace7131cc7d"
+ integrity sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==
+
+statuses@2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
+ integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
+
+string.prototype.codepointat@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz#004ad44c8afc727527b108cd462b4d971cd469bc"
+ integrity sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==
+
+stylis@4.1.3:
+ version "4.1.3"
+ resolved "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz"
+ integrity sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==
+
+supports-color@^5.3.0:
+ version "5.5.0"
+ resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
+ integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+ dependencies:
+ has-flag "^3.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+suspend-react@^0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/suspend-react/-/suspend-react-0.0.8.tgz#b0740c1386b4eb652f17affe4339915ee268bd31"
+ integrity sha512-ZC3r8Hu1y0dIThzsGw0RLZplnX9yXwfItcvaIzJc2VQVi8TGyGDlu92syMB5ulybfvGLHAI5Ghzlk23UBPF8xg==
+
+three-mesh-bvh@^0.5.22:
+ version "0.5.22"
+ resolved "https://registry.yarnpkg.com/three-mesh-bvh/-/three-mesh-bvh-0.5.22.tgz#9c20fbaba1f55c7afe3fe769a90c4605e3bd53ee"
+ integrity sha512-vi9X78CoEz1VVfkKRpUZQa34SEc0QGDd9Hmyis0aeBRAmjp4BpHQ2URcirBsOvFMNBXqB9Klp8sQ9NCRsUEW0w==
+
+three-stdlib@^2.21.8, three-stdlib@^2.8.11:
+ version "2.21.8"
+ resolved "https://registry.yarnpkg.com/three-stdlib/-/three-stdlib-2.21.8.tgz#37b11b7f62d07b10742c212153b14db21433b3c6"
+ integrity sha512-kqisiKvO4mSy59v5vWqBQSH8famLxp7Z51LxpMJI9GwDxqODaW02rhIwmjYDEzZWNFpjZpoDHVGbdpeHf8h3SA==
+ dependencies:
+ "@babel/runtime" "^7.16.7"
+ "@types/offscreencanvas" "^2019.6.4"
+ "@webgpu/glslang" "^0.0.15"
+ chevrotain "^10.1.2"
+ draco3d "^1.4.1"
+ fflate "^0.6.9"
+ ktx-parse "^0.4.5"
+ mmd-parser "^1.0.4"
+ opentype.js "^1.3.3"
+ potpack "^1.0.1"
+ zstddec "^0.0.2"
+
+three@^0.148.0:
+ version "0.148.0"
+ resolved "https://registry.yarnpkg.com/three/-/three-0.148.0.tgz#b6f62f9c84227f8d51c151bf17b67984ded8e4d7"
+ integrity sha512-8uzVV+qhTPi0bOFs/3te3RW6hb3urL8jYEl6irjCWo/l6sr8MPNMcClFev/MMYeIxr0gmDcoXTy/8LXh/LXkfw==
+
+tiny-inflate@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4"
+ integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==
+
+to-fast-properties@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz"
+ integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+toidentifier@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
+ integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
+
+troika-three-text@^0.47.1:
+ version "0.47.1"
+ resolved "https://registry.yarnpkg.com/troika-three-text/-/troika-three-text-0.47.1.tgz#4a239b122242d7ea93dbbf66a9f1863eca83d979"
+ integrity sha512-/fPRUmxCkXxyUT8k6REC/aWeFzKbNr37ivrkrplSJNb3JcBUXvVt8MT0Ac5wTUvFsYTviYWprYS4/8Laen08WA==
+ dependencies:
+ bidi-js "^1.0.2"
+ troika-three-utils "^0.47.0"
+ troika-worker-utils "^0.47.0"
+ webgl-sdf-generator "1.1.1"
+
+troika-three-utils@^0.47.0:
+ version "0.47.0"
+ resolved "https://registry.yarnpkg.com/troika-three-utils/-/troika-three-utils-0.47.0.tgz#4749334ad2ae043767916f79bcc365cbb5ea64b5"
+ integrity sha512-yoVTQxVbpQX3a55giIwqwq6hyJA6oYvq7kaNGwFTeicoWmTZCqqTbytafx1gcuL5umrtw5MYgsxYUSOha+xp5w==
+
+troika-worker-utils@^0.47.0:
+ version "0.47.0"
+ resolved "https://registry.yarnpkg.com/troika-worker-utils/-/troika-worker-utils-0.47.0.tgz#bea382fee55333e177955e7ba6497d64b9d9388d"
+ integrity sha512-PSUc9vunDEkbE23jpgXD3PcF96jQHKjgMjS+4o5g6DEK/ZAPTnldb+FNddhppawfUcuraMFrslo0GmIC8UpEmA==
+
+type-is@^1.6.16:
+ version "1.6.18"
+ resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
+ integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
+ dependencies:
+ media-typer "0.3.0"
+ mime-types "~2.1.24"
+
+typescript@^4.9.3:
+ version "4.9.4"
+ resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz"
+ integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==
+
+unpipe@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+ integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
+
+update-browserslist-db@^1.0.9:
+ version "1.0.10"
+ resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz"
+ integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==
+ dependencies:
+ escalade "^3.1.1"
+ picocolors "^1.0.0"
+
+utility-types@^3.10.0:
+ version "3.10.0"
+ resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b"
+ integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==
+
+vite-plugin-mock-dev-server@^0.3.16:
+ version "0.3.16"
+ resolved "https://registry.yarnpkg.com/vite-plugin-mock-dev-server/-/vite-plugin-mock-dev-server-0.3.16.tgz#75ba29abd6b6a05d759ec115ed428cbcf5e2871b"
+ integrity sha512-88oCTZNXtQplWTMaHW94Nxm9vg3lzPVyEbMaGXvpwG5GHdGz4K9DrgJXpFha2Ca+K+lMyySGMfo1HoRV6MMMJQ==
+ dependencies:
+ chokidar "^3.5.3"
+ co-body "^6.1.0"
+ debug "^4.3.4"
+ esbuild "^0.16.9"
+ fast-glob "^3.2.12"
+ formidable "^2.1.1"
+ json5 "^2.2.2"
+ path-to-regexp "^6.2.1"
+
+vite@^4.0.0:
+ version "4.0.4"
+ resolved "https://registry.npmjs.org/vite/-/vite-4.0.4.tgz"
+ integrity sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==
+ dependencies:
+ esbuild "^0.16.3"
+ postcss "^8.4.20"
+ resolve "^1.22.1"
+ rollup "^3.7.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+webgl-constants@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/webgl-constants/-/webgl-constants-1.1.1.tgz#f9633ee87fea56647a60b9ce735cbdfb891c6855"
+ integrity sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg==
+
+webgl-sdf-generator@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz#3e1b422b3d87cd3cc77f2602c9db63bc0f6accbd"
+ integrity sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA==
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+
+yallist@^3.0.2:
+ version "3.1.1"
+ resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz"
+ integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
+
+yaml@^1.10.0:
+ version "1.10.2"
+ resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
+ integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
+
+zstddec@^0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/zstddec/-/zstddec-0.0.2.tgz#57e2f28dd1ff56b750e07d158a43f0611ad9eeb4"
+ integrity sha512-DCo0oxvcvOTGP/f5FA6tz2Z6wF+FIcEApSTu0zV5sQgn9hoT5lZ9YRAKUraxt9oP7l4e8TnNdi8IZTCX6WCkwA==
+
+zustand@^3.5.13, zustand@^3.7.1:
+ version "3.7.2"
+ resolved "https://registry.yarnpkg.com/zustand/-/zustand-3.7.2.tgz#7b44c4f4a5bfd7a8296a3957b13e1c346f42514d"
+ integrity sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==
diff --git a/go.sum b/go.sum
index f5702b3..e5d3e2b 100644
--- a/go.sum
+++ b/go.sum
@@ -2,35 +2,26 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/gin-contrib/cors v1.3.1 h1:doAsuITavI4IOcd0Y19U4B+O0dNWihRyX//nn4sEmgA=
-github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk=
github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0g=
github.com/gin-contrib/cors v1.4.0/go.mod h1:bs9pNM0x/UsmHPBWT2xZz9ROh8xYjYkiURUfmBoMlcs=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
-github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
-github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
-github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
-github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw=
-github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
-github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM=
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
-github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -44,7 +35,6 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
-github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -55,28 +45,20 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
-github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
-github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
-github.com/mattn/go-sqlite3 v1.14.13 h1:1tj15ngiFfcZzii7yd82foL+ks+ouQcj8j/TPq3fk1I=
-github.com/mattn/go-sqlite3 v1.14.13/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
-github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw=
-github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI=
github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
@@ -88,41 +70,29 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
-github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
-github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
-golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8=
-golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
-golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d h1:Zu/JngovGLVi6t2J3nmAf3AoTDwuzw85YZ3b9o4yU7s=
-golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 h1:ohgcoMbSofXygzo6AD2I1kz3BFmW1QArPYTtwEM3UXc=
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -132,15 +102,12 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U=
-golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
@@ -149,31 +116,19 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
-gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
-gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
-gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
-gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gorm.io/driver/mysql v1.3.5 h1:iWBTVW/8Ij5AG4e0G/zqzaJblYkBI1VIL1LG2HUGsvY=
-gorm.io/driver/mysql v1.3.5/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c=
gorm.io/driver/mysql v1.3.6 h1:BhX1Y/RyALb+T9bZ3t07wLnPZBukt+IRkMn8UZSNbGM=
gorm.io/driver/mysql v1.3.6/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c=
-gorm.io/driver/sqlite v1.3.4 h1:NnFOPVfzi4CPsJPH4wXr6rMkPb4ElHEqKMvrsx9c9Fk=
-gorm.io/driver/sqlite v1.3.4/go.mod h1:B+8GyC9K7VgzJAcrcXMRPdnMcck+8FgJynEehEPM16U=
gorm.io/driver/sqlite v1.3.6 h1:Fi8xNYCUplOqWiPa3/GuCeowRNBRGTf62DEmhMDHeQQ=
gorm.io/driver/sqlite v1.3.6/go.mod h1:Sg1/pvnKtbQ7jLXxfZa+jSHvoX8hoZA8cn4xllOMTgE=
gorm.io/gorm v1.23.4/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
-gorm.io/gorm v1.23.6 h1:KFLdNgri4ExFFGTRGGFWON2P1ZN28+9SJRN8voOoYe0=
-gorm.io/gorm v1.23.6/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
-gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE=
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.23.9 h1:NSHG021i+MCznokeXR3udGaNyFyBQJW8MbjrJMVCfGw=
gorm.io/gorm v1.23.9/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
diff --git a/main.go b/main.go
index 0ebfa7c..6fa89f7 100644
--- a/main.go
+++ b/main.go
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022. Gardel and contributors
+ * Copyright (C) 2022-2023. Gardel and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -129,8 +129,8 @@ func main() {
serverMeta.Meta.ImplementationVersion = meta.ImplementationVersion
serverMeta.Meta.FeatureNoMojangNamespace = true
serverMeta.Meta.FeatureEnableProfileKey = true
- serverMeta.Meta.Links.Homepage = meta.SkinRootUrl + "/profile/user.html"
- serverMeta.Meta.Links.Register = meta.SkinRootUrl + "/profile/index.html"
+ serverMeta.Meta.Links.Homepage = meta.SkinRootUrl + "/profile/"
+ serverMeta.Meta.Links.Register = meta.SkinRootUrl + "/profile/"
serverMeta.SkinDomains = meta.SkinDomains
serverMeta.SignaturePublickey = string(publicKeyContent)
r := gin.Default()