diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml
index 5e188901889..db457fc7885 100644
--- a/.github/workflows/test-deploy.yml
+++ b/.github/workflows/test-deploy.yml
@@ -10,15 +10,17 @@ on:
jobs:
test-deploy:
name: Test deployment
- runs-on: ubuntu-latest
+ runs-on: [self-hosted, unicorn]
steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-node@v3
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ - uses: actions/setup-node@v4
with:
node-version: 22
cache: yarn
- name: Install dependencies
run: yarn install
- - name: Test build website
- run: yarn build
+ - name: Build website
+ run: DOCUSAURUS_IGNORE_SSG_WARNINGS=true yarn build
diff --git a/docusaurus.config.js b/docusaurus.config.js
index a4f33679c52..b3d22b9d587 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -132,20 +132,10 @@ const config = {
type: 'localeDropdown',
position: 'right',
},
- {
- label: 'GitHub',
- position: 'right',
- href: 'https://github.com/DocsaidLab',
- },
- {
- label: '支持我們',
- position: 'right',
- href: 'https://buymeacoffee.com/docsaid',
- },
{
label: '關於我們',
href: '/aboutus',
- position: 'right',
+ position: 'left',
},
],
@@ -196,11 +186,7 @@ const config = {
{
label: '工作日誌',
href: '/worklog',
- },
- {
- label: '支持我們',
- href: 'https://buymeacoffee.com/docsaid',
- },
+ }
],
copyright: `Copyright © ${new Date().getFullYear()} DOCSAID.`,
},
diff --git a/package.json b/package.json
index c69ffd06477..76071c9ecea 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,9 @@
},
"dependencies": {
"@algolia/client-search": "^4.9.1",
+ "@ant-design/charts": "^2.2.6",
+ "@ant-design/pro-card": "^2.9.6",
+ "@ant-design/pro-layout": "^7.22.3",
"@docsearch/react": "^3.6.0",
"@docusaurus/core": "^3.7.0",
"@docusaurus/faster": "^3.7.0",
@@ -32,15 +35,17 @@
"antd": "^5.22.2",
"apexcharts": "^4.2.0",
"axios": "^1.6.8",
- "chart.js": "4.4.6",
+ "chart.js": "4.4.8",
"clsx": "^2.0.0",
"d3": "^7.9.0",
"fft-js": "^0.0.12",
"fourier-transform": "^1.1.2",
"framer-motion": "^12.4.7",
"gh-pages": "^6.1.0",
+ "hull.js": "^1.0.6",
"i18next": "^23.15.1",
"mathjs": "^14.0.1",
+ "moment": "^2.30.1",
"prism-react-renderer": "^2.3.0",
"react": "^19.0.0",
"react-apexcharts": "^1.7.0",
@@ -56,7 +61,8 @@
"remark-math": "6",
"search-insights": "^1",
"simple-git": "^3.27.0",
- "typescript": "^5.6.3"
+ "typescript": "^5.6.3",
+ "zxcvbn": "^4.4.2"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.7.0",
diff --git a/src/components/AuthModal.js b/src/components/AuthModal.js
new file mode 100644
index 00000000000..1174f5aeb0f
--- /dev/null
+++ b/src/components/AuthModal.js
@@ -0,0 +1,115 @@
+// /src/components/AuthModal.js
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Divider, Modal, Tabs, Typography } from "antd";
+import React, { useEffect, useState } from "react";
+import useAuthHandler from "../hooks/useAuthHandler";
+import ForgotPasswordForm from "./forms/ForgotPasswordForm";
+import LoginForm from "./forms/LoginForm";
+import RegisterForm from "./forms/RegisterForm";
+
+/**
+ * 簡易字典,可根據專案需求擴充
+ */
+const i18nTexts = {
+ "zh-hant": {
+ modalTitle: "會員中心",
+ loginTab: "登入",
+ registerTab: "註冊",
+ backToLogin: "回到登入",
+ },
+ en: {
+ modalTitle: "Member Center",
+ loginTab: "Login",
+ registerTab: "Register",
+ backToLogin: "Back to Login",
+ },
+ ja: {
+ modalTitle: "会員センター",
+ loginTab: "ログイン",
+ registerTab: "新規登録",
+ backToLogin: "ログインに戻る",
+ },
+};
+
+export default function AuthModal({ visible, onCancel }) {
+ const { login, register, loading } = useAuthHandler();
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const lang = currentLocale;
+ const texts = i18nTexts[lang] || i18nTexts.en; // 預設英語
+ const [mode, setMode] = useState("login");
+
+ // 當 modal 關閉時,自動重置模式為 "login"
+ useEffect(() => {
+ if (!visible) {
+ setMode("login");
+ }
+ }, [visible]);
+
+ const goToForgotPassword = () => setMode("forgotPassword");
+ const goToLogin = () => setMode("login");
+ const goToRegister = () => setMode("register");
+
+ const renderLoginContent = () => (
+
+ );
+
+ const renderRegisterContent = () => (
+
+ );
+
+ const renderForgotPasswordContent = () => (
+ <>
+
+
+
+ {texts.backToLogin}
+
+ >
+ );
+
+ return (
+
+ {/* 若當前是忘記密碼模式,就不使用 Tabs */}
+ {mode === "forgotPassword" ? (
+ renderForgotPasswordContent()
+ ) : (
+ setMode(key)}
+ items={[
+ {
+ key: "login",
+ label: texts.loginTab, // 動態顯示「登入」
+ children: renderLoginContent(),
+ },
+ {
+ key: "register",
+ label: texts.registerTab, // 動態顯示「註冊」
+ children: renderRegisterContent(),
+ },
+ ]}
+ />
+ )}
+
+ );
+}
diff --git a/src/components/Dashboard/ApiDocs/ApiUsageExamples.js b/src/components/Dashboard/ApiDocs/ApiUsageExamples.js
new file mode 100644
index 00000000000..116724474ec
--- /dev/null
+++ b/src/components/Dashboard/ApiDocs/ApiUsageExamples.js
@@ -0,0 +1,48 @@
+// src/components/Dashboard/ApiDocs/ApiUsageExamples.jsx
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Card, Collapse, Divider, Tabs, Tag, Typography } from "antd";
+import React from "react";
+import DocAligner from "./apis/DocAligner";
+import MrzScanner from "./apis/MrzScanner";
+import styles from "./index.module.css"; // 確保引入新的 CSS
+import ParamList from "./ParamList";
+
+const { Panel } = Collapse;
+const { Paragraph, Text } = Typography;
+
+export default function ApiUsageExamples() {
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+
+ // 從各個 API 檔案根據當前語系取得定義
+ const apiDefinitions = [DocAligner(currentLocale), MrzScanner(currentLocale)];
+
+ return (
+
+ {apiDefinitions.map((apiDef) => (
+
+ {apiDef.title}
+ {apiDef.route}
+
+ }
+ >
+
+ {apiDef.overview}
+
+ {apiDef.text.parameters}
+
+
+
+ {apiDef.text.codeExamples}
+
+
+
+
+ ))}
+
+ );
+}
diff --git a/src/components/Dashboard/ApiDocs/CodeBlock.js b/src/components/Dashboard/ApiDocs/CodeBlock.js
new file mode 100644
index 00000000000..d071d34e845
--- /dev/null
+++ b/src/components/Dashboard/ApiDocs/CodeBlock.js
@@ -0,0 +1,55 @@
+// src/components/Dashboard/ApiDocs/CodeBlock.jsx
+import { CopyOutlined } from "@ant-design/icons";
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Button, Tooltip } from "antd";
+import React, { useState } from "react";
+import styles from "./index.module.css";
+
+const i18n = {
+ "zh-hant": {
+ copy: "複製程式碼",
+ copied: "已複製",
+ },
+ en: {
+ copy: "Copy Code",
+ copied: "Copied",
+ },
+ ja: {
+ copy: "コードをコピー",
+ copied: "コピー済み",
+ },
+};
+
+export default function CodeBlock({ codeStr }) {
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const localeText = i18n[currentLocale] || i18n.en;
+ const [copied, setCopied] = useState(false);
+
+ const handleCopy = async () => {
+ try {
+ await navigator.clipboard.writeText(codeStr);
+ setCopied(true);
+ setTimeout(() => setCopied(false), 2000);
+ } catch (error) {
+ console.error("複製失敗", error);
+ }
+ };
+
+ return (
+
+
+ }
+ onClick={handleCopy}
+ />
+
+
+ {codeStr}
+
+
+ );
+}
diff --git a/src/components/Dashboard/ApiDocs/ParamList.js b/src/components/Dashboard/ApiDocs/ParamList.js
new file mode 100644
index 00000000000..fe7c6128ae4
--- /dev/null
+++ b/src/components/Dashboard/ApiDocs/ParamList.js
@@ -0,0 +1,38 @@
+// src/components/Dashboard/ApiDocs/ParamList.jsx
+import { List, Tag, Typography } from "antd";
+import React from "react";
+import styles from "./index.module.css";
+
+const { Text } = Typography;
+
+export default function ParamList({ data, text }) {
+ return (
+ {
+ const { name, type, required, default: defaultVal, desc } = item;
+ return (
+
+
+ {name} {" "}
+ {type && {type} }
+ {required && {text.requiredLabel} }
+ {defaultVal && defaultVal !== "-" && (
+
+ {text.defaultLabel}: {defaultVal}
+
+ )}
+
+ }
+ description={{desc} }
+ />
+
+ );
+ }}
+ />
+ );
+}
diff --git a/src/components/Dashboard/ApiDocs/apis/DocAligner.js b/src/components/Dashboard/ApiDocs/apis/DocAligner.js
new file mode 100644
index 00000000000..1413375c83a
--- /dev/null
+++ b/src/components/Dashboard/ApiDocs/apis/DocAligner.js
@@ -0,0 +1,261 @@
+// src/components/Dashboard/ApiDocs/apis/DocAligner.jsx
+import React from "react";
+import CodeBlock from "../CodeBlock";
+
+const DocAlignerI18n = {
+ "zh-hant": {
+ docAlignerTitle: "DocAligner",
+ docAlignerPath: "POST /docaligner-public-predict",
+ docAlignerOverview: `
+ 這個 API 用於身分證、證件等影像的自動裁切與修正,可選擇是否進行中心裁切(do_center_crop)。
+ `,
+ parameters: "參數說明",
+ codeExamples: "程式碼範例",
+ requiredLabel: "必填",
+ defaultLabel: "預設值",
+ curlLabel: "cURL",
+ pythonLabel: "Python",
+ nodeLabel: "Node.js",
+ jsLabel: "JavaScript",
+ javaLabel: "Java",
+ rubyLabel: "Ruby",
+ docAlignerParams: [
+ {
+ name: "file",
+ type: "File",
+ required: true,
+ default: "-",
+ desc: "要上傳的影像檔 (jpg, png 等)。"
+ },
+ {
+ name: "do_center_crop",
+ type: "bool",
+ required: false,
+ default: "false",
+ desc: "是否進行中心裁切。"
+ }
+ ]
+ },
+ en: {
+ docAlignerTitle: "DocAligner",
+ docAlignerPath: "POST /docaligner-public-predict",
+ docAlignerOverview: `
+ This API automatically crops and aligns document images (e.g., ID cards).
+ Optionally apply center cropping (do_center_crop).
+ `,
+ parameters: "Parameters",
+ codeExamples: "Code Examples",
+ requiredLabel: "Required",
+ defaultLabel: "Default",
+ curlLabel: "cURL",
+ pythonLabel: "Python",
+ nodeLabel: "Node.js",
+ jsLabel: "JavaScript",
+ javaLabel: "Java",
+ rubyLabel: "Ruby",
+ docAlignerParams: [
+ {
+ name: "file",
+ type: "File",
+ required: true,
+ default: "-",
+ desc: "Uploaded image file (jpg, png, etc.)."
+ },
+ {
+ name: "do_center_crop",
+ type: "bool",
+ required: false,
+ default: "false",
+ desc: "Whether to apply center cropping."
+ }
+ ]
+ },
+ ja: {
+ docAlignerTitle: "DocAligner",
+ docAlignerPath: "POST /docaligner-public-predict",
+ docAlignerOverview: `
+ このAPIはIDカードやパスポートなどの画像を自動トリミング・補正します。
+ 必要に応じて中心部分のトリミング(do_center_crop)を行います。
+ `,
+ parameters: "パラメータ",
+ codeExamples: "コード例",
+ requiredLabel: "必須",
+ defaultLabel: "デフォルト",
+ curlLabel: "cURL",
+ pythonLabel: "Python",
+ nodeLabel: "Node.js",
+ jsLabel: "JavaScript",
+ javaLabel: "Java",
+ rubyLabel: "Ruby",
+ docAlignerParams: [
+ {
+ name: "file",
+ type: "File",
+ required: true,
+ default: "-",
+ desc: "アップロードする画像ファイル(jpg, pngなど)。"
+ },
+ {
+ name: "do_center_crop",
+ type: "bool",
+ required: false,
+ default: "false",
+ desc: "中心部分のトリミングを行うかどうか。"
+ }
+ ]
+ }
+};
+
+export default function DocAligner(locale = "en") {
+ const text = DocAlignerI18n[locale] || DocAlignerI18n.en;
+ return {
+ key: "docaligner",
+ text,
+ title: text.docAlignerTitle,
+ route: text.docAlignerPath,
+ overview: text.docAlignerOverview,
+ params: text.docAlignerParams,
+ codeExamples: [
+ {
+ label: text.curlLabel,
+ key: "curl",
+ children: (
+ " \\
+ -F "file=@/path/to/your/document.jpg" \\
+ -F "do_center_crop=true"
+`}
+ />
+ )
+ },
+ {
+ label: text.pythonLabel,
+ key: "python",
+ children: (
+ "}
+files = {"file": open("/path/to/your/document.jpg", "rb")}
+data = {"do_center_crop": "true"}
+
+res = requests.post(url, headers=headers, files=files, data=data)
+print(res.json())
+`}
+ />
+ )
+ },
+ {
+ label: text.nodeLabel,
+ key: "node",
+ children: (
+ '
+ }
+}).then(res => {
+ console.log(res.data);
+}).catch(err => {
+ console.error(err);
+});
+`}
+ />
+ )
+ },
+ {
+ label: text.jsLabel,
+ key: "js",
+ children: (
+ "
+ },
+ body: form
+})
+ .then(r => r.json())
+ .then(data => console.log(data))
+ .catch(err => console.error(err));
+`}
+ />
+ )
+ },
+ {
+ label: text.javaLabel,
+ key: "java",
+ children: (
+ ")
+ .build();
+
+try (Response response = client.newCall(request).execute()) {
+ System.out.println(response.body().string());
+}
+`}
+ />
+ )
+ },
+ {
+ label: text.rubyLabel,
+ key: "ruby",
+ children: (
+ "
+
+form_data = [
+ ["file", File.open("/path/to/your/document.jpg")],
+ ["do_center_crop", "true"]
+]
+req.set_form form_data, "multipart/form-data"
+
+res = Net::HTTP.start(url.hostname, url.port, use_ssl: url.scheme == "https") do |http|
+ http.request(req)
+end
+
+puts res.body
+`}
+ />
+ )
+ }
+ ]
+ };
+}
diff --git a/src/components/Dashboard/ApiDocs/apis/MrzScanner.js b/src/components/Dashboard/ApiDocs/apis/MrzScanner.js
new file mode 100644
index 00000000000..54a650ad1d5
--- /dev/null
+++ b/src/components/Dashboard/ApiDocs/apis/MrzScanner.js
@@ -0,0 +1,317 @@
+// src/components/Dashboard/ApiDocs/apis/MrzScanner.jsx
+import React from "react";
+import CodeBlock from "../CodeBlock";
+
+const MrzScannerI18n = {
+ "zh-hant": {
+ mrzScannerTitle: "MRZScanner",
+ mrzScannerPath: "POST /mrzscanner-public-predict",
+ mrzScannerOverview: `
+ 這個 API 用於掃描並解析 MRZ 區域,可選擇先對齊影像 (do_doc_align),再決定是否後處理 (do_postprocess)、中心裁切等。
+ `,
+ parameters: "參數說明",
+ codeExamples: "程式碼範例",
+ requiredLabel: "必填",
+ defaultLabel: "預設值",
+ curlLabel: "cURL",
+ pythonLabel: "Python",
+ nodeLabel: "Node.js",
+ jsLabel: "JavaScript",
+ javaLabel: "Java",
+ rubyLabel: "Ruby",
+ mrzScannerParams: [
+ {
+ name: "file",
+ type: "File",
+ required: true,
+ default: "-",
+ desc: "要上傳的影像檔 (jpg, png 等)。"
+ },
+ {
+ name: "do_doc_align",
+ type: "bool",
+ required: false,
+ default: "false",
+ desc: "是否先使用 DocAligner 對齊影像。"
+ },
+ {
+ name: "do_postprocess",
+ type: "bool",
+ required: false,
+ default: "false",
+ desc: "是否在辨識後進行後處理 (去雜訊)。"
+ },
+ {
+ name: "do_center_crop",
+ type: "bool",
+ required: false,
+ default: "true",
+ desc: "是否在掃描前做中心裁切。"
+ }
+ ]
+ },
+ en: {
+ mrzScannerTitle: "MRZScanner",
+ mrzScannerPath: "POST /mrzscanner-public-predict",
+ mrzScannerOverview: `
+ This API scans and parses the MRZ zone, optionally aligns the document first (do_doc_align),
+ then you can decide whether to post-process (do_postprocess) or center-crop.
+ `,
+ parameters: "Parameters",
+ codeExamples: "Code Examples",
+ requiredLabel: "Required",
+ defaultLabel: "Default",
+ curlLabel: "cURL",
+ pythonLabel: "Python",
+ nodeLabel: "Node.js",
+ jsLabel: "JavaScript",
+ javaLabel: "Java",
+ rubyLabel: "Ruby",
+ mrzScannerParams: [
+ {
+ name: "file",
+ type: "File",
+ required: true,
+ default: "-",
+ desc: "Uploaded image file (jpg, png, etc.)."
+ },
+ {
+ name: "do_doc_align",
+ type: "bool",
+ required: false,
+ default: "false",
+ desc: "Whether to align the document first."
+ },
+ {
+ name: "do_postprocess",
+ type: "bool",
+ required: false,
+ default: "false",
+ desc: "Whether to apply post-processing (noise removal)."
+ },
+ {
+ name: "do_center_crop",
+ type: "bool",
+ required: false,
+ default: "true",
+ desc: "Whether to apply center cropping before scanning."
+ }
+ ]
+ },
+ ja: {
+ mrzScannerTitle: "MRZScanner",
+ mrzScannerPath: "POST /mrzscanner-public-predict",
+ mrzScannerOverview: `
+ このAPIはMRZ領域をスキャンして解析します。事前にドキュメントアライメント(do_doc_align)を
+ 行うことも可能で、後処理(do_postprocess)や中心トリミング(do_center_crop)なども選択できます。
+ `,
+ parameters: "パラメータ",
+ codeExamples: "コード例",
+ requiredLabel: "必須",
+ defaultLabel: "デフォルト",
+ curlLabel: "cURL",
+ pythonLabel: "Python",
+ nodeLabel: "Node.js",
+ jsLabel: "JavaScript",
+ javaLabel: "Java",
+ rubyLabel: "Ruby",
+ mrzScannerParams: [
+ {
+ name: "file",
+ type: "File",
+ required: true,
+ default: "-",
+ desc: "アップロードする画像ファイル(jpg, pngなど)。"
+ },
+ {
+ name: "do_doc_align",
+ type: "bool",
+ required: false,
+ default: "false",
+ desc: "先にDocAlignerで画像を整列させるかどうか。"
+ },
+ {
+ name: "do_postprocess",
+ type: "bool",
+ required: false,
+ default: "false",
+ desc: "スキャン後にノイズ除去などの後処理を行うかどうか。"
+ },
+ {
+ name: "do_center_crop",
+ type: "bool",
+ required: false,
+ default: "true",
+ desc: "スキャン前に中心部分のトリミングを行うかどうか。"
+ }
+ ]
+ }
+};
+
+export default function MrzScanner(locale = "en") {
+ const text = MrzScannerI18n[locale] || MrzScannerI18n.en;
+ return {
+ key: "mrzscanner",
+ text,
+ title: text.mrzScannerTitle,
+ route: text.mrzScannerPath,
+ overview: text.mrzScannerOverview,
+ params: text.mrzScannerParams,
+ codeExamples: [
+ {
+ label: text.curlLabel,
+ key: "curl",
+ children: (
+ " \\
+ -F "file=@/path/to/your/document.jpg" \\
+ -F "do_doc_align=true" \\
+ -F "do_postprocess=false" \\
+ -F "do_center_crop=true"
+`}
+ />
+ )
+ },
+ {
+ label: text.pythonLabel,
+ key: "python",
+ children: (
+ "}
+files = {"file": open("/path/to/your/document.jpg", "rb")}
+data = {
+ "do_doc_align": "true",
+ "do_postprocess": "false",
+ "do_center_crop": "true"
+}
+
+res = requests.post(url, headers=headers, files=files, data=data)
+print(res.json())
+`}
+ />
+ )
+ },
+ {
+ label: text.nodeLabel,
+ key: "node",
+ children: (
+ '
+ }
+}).then(res => {
+ console.log(res.data);
+}).catch(err => {
+ console.error(err);
+});
+`}
+ />
+ )
+ },
+ {
+ label: text.jsLabel,
+ key: "js",
+ children: (
+ "
+ },
+ body: form
+})
+ .then(r => r.json())
+ .then(data => console.log(data))
+ .catch(err => console.error(err));
+`}
+ />
+ )
+ },
+ {
+ label: text.javaLabel,
+ key: "java",
+ children: (
+ ")
+ .build();
+
+try (Response response = client.newCall(request).execute()) {
+ System.out.println(response.body().string());
+}
+`}
+ />
+ )
+ },
+ {
+ label: text.rubyLabel,
+ key: "ruby",
+ children: (
+ "
+
+form_data = [
+ ["file", File.open("/path/to/your/document.jpg")],
+ ["do_doc_align", "true"],
+ ["do_postprocess", "false"],
+ ["do_center_crop", "true"]
+]
+req.set_form form_data, "multipart/form-data"
+
+res = Net::HTTP.start(url.hostname, url.port, use_ssl: url.scheme == "https") do |http|
+ http.request(req)
+end
+
+puts res.body
+`}
+ />
+ )
+ }
+ ]
+ };
+}
diff --git a/src/components/Dashboard/ApiDocs/index.js b/src/components/Dashboard/ApiDocs/index.js
new file mode 100644
index 00000000000..8aeb4f74c44
--- /dev/null
+++ b/src/components/Dashboard/ApiDocs/index.js
@@ -0,0 +1,94 @@
+// src/components/Dashboard/ApiDocs/index.js
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Spin } from "antd";
+import React, { useEffect, useState } from "react";
+import { useAuth } from "../../../context/AuthContext";
+import ApiUsageExamples from "./ApiUsageExamples";
+import styles from "./index.module.css";
+
+const locales = {
+ "zh-hant": {
+ title: "API 使用說明",
+ description: "這裡是各種 API 的技術文件與使用範例介紹頁。",
+ pleaseVerifyEmailTitle: "請先驗證電子郵件",
+ pleaseVerifyEmailDesc:
+ "您尚未完成電子郵件驗證,無法使用 API 文件功能。請前往 我的資訊 頁面完成驗證。",
+ loadingProfile: "載入個人資料...",
+ },
+ en: {
+ title: "API Documents",
+ description:
+ "This page provides technical documentation and usage examples for various APIs.",
+ pleaseVerifyEmailTitle: "Please verify your email",
+ pleaseVerifyEmailDesc:
+ "You have not verified your email, and cannot use the API Documentation feature. Please go to My Info page to complete verification.",
+ loadingProfile: "Loading profile...",
+ },
+ ja: {
+ title: "APIドキュメント",
+ description: "ここでは、各種APIの技術文書と使用例を紹介しています。",
+ pleaseVerifyEmailTitle: "メール認証をしてください",
+ pleaseVerifyEmailDesc:
+ "メール認証が完了していないため、APIドキュメント機能が利用できません。マイ情報ページに移動して認証を完了してください。",
+ loadingProfile: "プロファイルを読み込み中...",
+ },
+};
+
+export default function DashboardApiDocs() {
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const text = locales[currentLocale] || locales.en;
+
+ const { token: userToken } = useAuth();
+ const [userProfile, setUserProfile] = useState(null);
+ const [loadingProfile, setLoadingProfile] = useState(false);
+
+ useEffect(() => {
+ if (userToken) {
+ const fetchUserProfile = async () => {
+ setLoadingProfile(true);
+ try {
+ const res = await fetch("https://api.docsaid.org/auth/me", {
+ headers: { Authorization: `Bearer ${userToken}` },
+ });
+ if (!res.ok) {
+ throw new Error("Failed to fetch profile");
+ }
+ const data = await res.json();
+ setUserProfile(data);
+ } catch (err) {
+ console.error(err);
+ } finally {
+ setLoadingProfile(false);
+ }
+ };
+ fetchUserProfile();
+ }
+ }, [userToken]);
+
+ if (loadingProfile && !userProfile) {
+ return (
+
+
+
+ );
+ }
+
+ if (userProfile && !userProfile.is_email_verified) {
+ return (
+
+
{text.pleaseVerifyEmailTitle}
+
{text.pleaseVerifyEmailDesc}
+
+ );
+ }
+
+ return (
+
+
{text.title}
+
{text.description}
+
+
+ );
+}
diff --git a/src/components/Dashboard/ApiDocs/index.module.css b/src/components/Dashboard/ApiDocs/index.module.css
new file mode 100644
index 00000000000..862668b5537
--- /dev/null
+++ b/src/components/Dashboard/ApiDocs/index.module.css
@@ -0,0 +1,175 @@
+/* src/components/Dashboard/ApiDocs/index.module.css */
+
+/* 容器 (與 APIKey 保持一致) */
+.apiKeyContainer {
+ max-width: 900px;
+ margin: 0 auto;
+ padding: 32px 24px;
+ background-color: #fafafa;
+ border-radius: 8px;
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
+}
+
+/* 頁面標題 */
+.header {
+ margin-bottom: 32px;
+ text-align: center;
+}
+.header h2 {
+ font-size: 2.5rem;
+ margin: 0 0 12px;
+ color: #333;
+ font-weight: 600;
+ white-space: nowrap; /* 不換行 */
+ overflow: hidden; /* 超出隱藏 */
+ text-overflow: ellipsis; /* 超出部分以省略號顯示 */
+}
+.header p {
+ font-size: 1.125rem;
+ color: #666;
+ margin: 0;
+ line-height: 1.5;
+}
+
+/* 折疊面板外框 */
+.collapseRoot {
+ background-color: #fff;
+ border: 1px solid #e8e8e8;
+ border-radius: 8px;
+ margin-bottom: 32px;
+}
+
+/* API 詳細卡片 */
+.apiCard {
+ background-color: #fff;
+ border-radius: 8px;
+ padding: 20px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
+ margin: 16px 0;
+}
+.apiCard:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+}
+
+/* 參數列表 */
+.paramListItem {
+ padding: 12px 0;
+ border-bottom: 1px solid #eee;
+}
+.paramListItem:last-child {
+ border-bottom: none;
+}
+.paramTitle {
+ font-size: 1rem;
+ color: #333;
+ margin-bottom: 0;
+}
+.paramTitle code {
+ font-size: 0.95rem;
+ margin-right: 4px;
+ background: #e8e8e8;
+ padding: 2px 4px;
+ border-radius: 4px;
+}
+.paramDesc {
+ font-size: 0.9rem;
+ color: #444;
+ margin-left: 4px;
+ line-height: 1.5;
+}
+
+/* 區隔線 */
+.divider {
+ margin: 32px 0 20px;
+ border: none;
+ border-top: 1px solid #e8e8e8;
+}
+
+/* 程式碼區塊 */
+.codeBlock {
+ background: #f5f5f5;
+ border-radius: 4px;
+ padding: 16px;
+ white-space: pre-wrap;
+ font-family: Consolas, Menlo, monospace;
+ margin-top: 12px;
+ overflow-x: auto;
+}
+
+/* Collapse Panel header 文字 */
+.panelHeader {
+ font-weight: 600;
+ color: #333;
+}
+
+/* CodeBlock 相關樣式 */
+.codeBlockContainer {
+ position: relative;
+}
+.copyButton {
+ position: absolute;
+ top: 8px;
+ right: 8px;
+ z-index: 10;
+}
+
+/* 手機裝置調整 */
+@media (max-width: 576px) {
+ .apiKeyContainer {
+ padding: 16px;
+ }
+ .header h2 {
+ font-size: 1.75rem;
+ }
+ .header p {
+ font-size: 1rem;
+ }
+ .apiCard {
+ padding: 16px;
+ margin: 12px 0;
+ }
+ .divider {
+ margin: 24px 0 16px;
+ }
+ .paramListItem {
+ padding: 10px 0;
+ }
+}
+
+/* 平板裝置調整 */
+@media (min-width: 768px) and (max-width: 991px) {
+ .apiKeyContainer {
+ padding: 24px;
+ }
+ .header h2 {
+ font-size: 2rem;
+ }
+ .header p {
+ font-size: 1.05rem;
+ }
+}
+
+/* 新增:Panel header wrapper,讓標題和路由可以換行 */
+.panelHeaderWrapper {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ align-items: center;
+ white-space: normal;
+}
+
+/* 如果需要,可調整 .panelHeader 原有樣式 */
+.panelHeader {
+ font-weight: 600;
+ color: #333;
+}
+
+/* 新增:Panel header 的 wrapper */
+.panelHeaderWrapper {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+}
diff --git a/src/components/Dashboard/ApiKey/ApiUsageExamples.js b/src/components/Dashboard/ApiKey/ApiUsageExamples.js
new file mode 100644
index 00000000000..e208aa6d226
--- /dev/null
+++ b/src/components/Dashboard/ApiKey/ApiUsageExamples.js
@@ -0,0 +1,264 @@
+// src/components/Dashboard/ApiKey/ApiUsageExamples.jsx
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Card, Tabs } from "antd";
+import React from "react";
+
+const { TabPane } = Tabs;
+
+const apiKeyLocale = {
+ "zh-hant": {
+ apiUsageExampleTitle: "API 使用範例",
+ },
+ en: {
+ apiUsageExampleTitle: "API Usage Examples",
+ },
+ ja: {
+ apiUsageExampleTitle: "API利用例",
+ },
+};
+
+export default function ApiUsageExamples() {
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const text = apiKeyLocale[currentLocale] || apiKeyLocale.en;
+
+ const examples = {
+ docaligner: {
+ curl: `curl -X POST https://api.docsaid.org/docaligner-public-predict \\
+ -H "Authorization: Bearer " \\
+ -F "file=@/path/to/your/document.jpg"`,
+ python: `import requests
+
+url = "https://api.docsaid.org/docaligner-public-predict"
+headers = {"Authorization": "Bearer "}
+files = {"file": open("/path/to/your/document.jpg", "rb")}
+response = requests.post(url, headers=headers, files=files)
+print(response.json())`,
+ node: `const axios = require('axios');
+const FormData = require('form-data');
+const fs = require('fs');
+
+const form = new FormData();
+form.append('file', fs.createReadStream('/path/to/your/document.jpg'));
+
+axios.post('https://api.docsaid.org/docaligner-public-predict', form, {
+ headers: {
+ ...form.getHeaders(),
+ 'Authorization': 'Bearer '
+ }
+})
+.then(response => {
+ console.log(response.data);
+})
+.catch(error => {
+ console.error(error);
+});`,
+ javascript: `fetch("https://api.docsaid.org/docaligner-public-predict", {
+ method: "POST",
+ headers: {
+ "Authorization": "Bearer "
+ },
+ body: new FormData(document.getElementById("uploadForm"))
+})
+.then(response => response.json())
+.then(data => console.log(data))
+.catch(error => console.error(error));`,
+ java: `OkHttpClient client = new OkHttpClient();
+
+MediaType mediaType = MediaType.parse("multipart/form-data");
+RequestBody body = new MultipartBody.Builder()
+ .setType(MultipartBody.FORM)
+ .addFormDataPart("file", "/path/to/your/document.jpg",
+ RequestBody.create(new File("/path/to/your/document.jpg"), MediaType.parse("image/jpeg")))
+ .build();
+
+Request request = new Request.Builder()
+ .url("https://api.docsaid.org/docaligner-public-predict")
+ .post(body)
+ .addHeader("Authorization", "Bearer ")
+ .build();
+
+Response response = client.newCall(request).execute();
+System.out.println(response.body().string());`,
+ ruby: `require 'net/http'
+require 'uri'
+
+uri = URI.parse("https://api.docsaid.org/docaligner-public-predict")
+request = Net::HTTP::Post.new(uri)
+request["Authorization"] = "Bearer "
+form_data = [['file', File.open('/path/to/your/document.jpg')]]
+request.set_form form_data, 'multipart/form-data'
+
+response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
+ http.request(request)
+end
+
+puts response.body`,
+ },
+ mrzscanner: {
+ curl: `curl -X POST https://api.docsaid.org/mrzscanner-public-predict \\
+ -H "Authorization: Bearer " \\
+ -F "file=@/path/to/your/document.jpg"`,
+ python: `import requests
+
+url = "https://api.docsaid.org/mrzscanner-public-predict"
+headers = {"Authorization": "Bearer "}
+files = {"file": open("/path/to/your/document.jpg", "rb")}
+response = requests.post(url, headers=headers, files=files)
+print(response.json())`,
+ node: `const axios = require('axios');
+const FormData = require('form-data');
+const fs = require('fs');
+
+const form = new FormData();
+form.append('file', fs.createReadStream('/path/to/your/document.jpg'));
+
+axios.post('https://api.docsaid.org/mrzscanner-public-predict', form, {
+ headers: {
+ ...form.getHeaders(),
+ 'Authorization': 'Bearer '
+ }
+})
+.then(response => {
+ console.log(response.data);
+})
+.catch(error => {
+ console.error(error);
+});`,
+ javascript: `fetch("https://api.docsaid.org/mrzscanner-public-predict", {
+ method: "POST",
+ headers: {
+ "Authorization": "Bearer "
+ },
+ body: new FormData(document.getElementById("uploadForm"))
+})
+.then(response => response.json())
+.then(data => console.log(data))
+.catch(error => console.error(error));`,
+ java: `OkHttpClient client = new OkHttpClient();
+
+MediaType mediaType = MediaType.parse("multipart/form-data");
+RequestBody body = new MultipartBody.Builder()
+ .setType(MultipartBody.FORM)
+ .addFormDataPart("file", "/path/to/your/document.jpg",
+ RequestBody.create(new File("/path/to/your/document.jpg"), MediaType.parse("image/jpeg")))
+ .build();
+
+Request request = new Request.Builder()
+ .url("https://api.docsaid.org/mrzscanner-public-predict")
+ .post(body)
+ .addHeader("Authorization", "Bearer ")
+ .build();
+
+Response response = client.newCall(request).execute();
+System.out.println(response.body().string());`,
+ ruby: `require 'net/http'
+require 'uri'
+
+uri = URI.parse("https://api.docsaid.org/mrzscanner-public-predict")
+request = Net::HTTP::Post.new(uri)
+request["Authorization"] = "Bearer "
+form_data = [['file', File.open('/path/to/your/document.jpg')]]
+request.set_form form_data, 'multipart/form-data'
+
+response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
+ http.request(request)
+end
+
+puts response.body`,
+ },
+ };
+
+ // 建立「第二層 Tabs」的 items - 例如 DocAligner
+ const makeInnerTabs = (dataObj) => {
+ // dataObj: examples.docaligner 或 examples.mrzscanner
+ return [
+ {
+ label: "cURL",
+ key: "curl",
+ children: (
+
+ {dataObj.curl}
+
+ ),
+ },
+ {
+ label: "Python",
+ key: "python",
+ children: (
+
+ {dataObj.python}
+
+ ),
+ },
+ {
+ label: "Node.js",
+ key: "node",
+ children: (
+
+ {dataObj.node}
+
+ ),
+ },
+ {
+ label: "JavaScript",
+ key: "javascript",
+ children: (
+
+ {dataObj.javascript}
+
+ ),
+ },
+ {
+ label: "Java",
+ key: "java",
+ children: (
+
+ {dataObj.java}
+
+ ),
+ },
+ {
+ label: "Ruby",
+ key: "ruby",
+ children: (
+
+ {dataObj.ruby}
+
+ ),
+ },
+ ];
+ };
+
+ // 第一層 Tabs items
+ const topItems = [
+ {
+ label: "DocAligner",
+ key: "docaligner",
+ children: (
+
+ ),
+ },
+ {
+ label: "MRZ Scanner",
+ key: "mrzscanner",
+ children: (
+
+ ),
+ },
+ ];
+
+ return (
+
+
+
+ );
+}
+
+// 也可另行定義
+const preStyle = {
+ background: "#f5f5f5",
+ padding: 12,
+ whiteSpace: "pre-wrap",
+};
\ No newline at end of file
diff --git a/src/components/Dashboard/ApiKey/CreateTokenModal.js b/src/components/Dashboard/ApiKey/CreateTokenModal.js
new file mode 100644
index 00000000000..dc6aec26489
--- /dev/null
+++ b/src/components/Dashboard/ApiKey/CreateTokenModal.js
@@ -0,0 +1,133 @@
+// src/components/Dashboard/ApiKey/CreateTokenModal.js
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Button, Checkbox, Form, Input, InputNumber, Modal, Space } from "antd";
+import PropTypes from "prop-types";
+import React, { useEffect } from "react";
+
+const apiKeyLocale = {
+ "zh-hant": {
+ createModalTitle: "建立新的公開 Token",
+ formTokenNameLabel: "Token 名稱",
+ formTokenNameTooltip: "可給 Token 一個易識別的名稱",
+ formTokenNamePlaceholder: "如:My DocAligner Key",
+ formIsLongTermLabel: "申請一年效期",
+ formIsLongTermCheckbox: "勾選後自動設定 1 年效期 (525600 分鐘)",
+ formExpiryLabel: "有效期 (分鐘)",
+ formExpiryValidationMessage: "請輸入有效期",
+ cancelButton: "取消",
+ createButton: "建立",
+ },
+ en: {
+ createModalTitle: "Create New Public Token",
+ formTokenNameLabel: "Token Name",
+ formTokenNameTooltip: "Give the token an easily recognizable name",
+ formTokenNamePlaceholder: "e.g., My DocAligner Key",
+ formIsLongTermLabel: "Apply for a one-year term",
+ formIsLongTermCheckbox: "Check to automatically set a 1-year term (525600 minutes)",
+ formExpiryLabel: "Expiry (minutes)",
+ formExpiryValidationMessage: "Please enter the expiration time",
+ cancelButton: "Cancel",
+ createButton: "Create",
+ },
+ ja: {
+ createModalTitle: "新しい公開トークンを作成",
+ formTokenNameLabel: "トークン名",
+ formTokenNameTooltip: "トークンにわかりやすい名前を付けることができます",
+ formTokenNamePlaceholder: "例:My DocAligner Key",
+ formIsLongTermLabel: "一年間の有効期限を申請",
+ formIsLongTermCheckbox: "チェックすると、自動的に1年間の有効期限(525600分)を設定します",
+ formExpiryLabel: "有効期限(分)",
+ formExpiryValidationMessage: "有効期限を入力してください",
+ cancelButton: "キャンセル",
+ createButton: "作成",
+ },
+};
+
+export default function CreateTokenModal({
+ visible,
+ onCancel,
+ onSubmit,
+ loading = false,
+ defaultValues = {
+ expires_minutes: 60,
+ isLongTerm: false,
+ },
+}) {
+ const [form] = Form.useForm();
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const text = apiKeyLocale[currentLocale] || apiKeyLocale.en;
+
+ useEffect(() => {
+ if (visible) {
+ form.setFieldsValue(defaultValues);
+ }
+ }, [defaultValues, form, visible]);
+
+ return (
+ form.resetFields()}
+ >
+
+
+
+
+
+ {text.formIsLongTermCheckbox}
+
+
+
+
+
+
+
+
+ {text.cancelButton}
+
+ {text.createButton}
+
+
+
+
+
+ );
+}
+
+CreateTokenModal.propTypes = {
+ visible: PropTypes.bool.isRequired,
+ onCancel: PropTypes.func.isRequired,
+ onSubmit: PropTypes.func.isRequired,
+ loading: PropTypes.bool,
+ defaultValues: PropTypes.shape({
+ expires_minutes: PropTypes.number,
+ isLongTerm: PropTypes.bool,
+ name: PropTypes.string,
+ }),
+};
diff --git a/src/components/Dashboard/ApiKey/TokenCard.js b/src/components/Dashboard/ApiKey/TokenCard.js
new file mode 100644
index 00000000000..53ff07c7bc4
--- /dev/null
+++ b/src/components/Dashboard/ApiKey/TokenCard.js
@@ -0,0 +1,139 @@
+// src/components/Dashboard/ApiKey/TokenCard.js
+import { DeleteOutlined, ExclamationCircleOutlined } from "@ant-design/icons";
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Button, Card, Popconfirm } from "antd";
+import PropTypes from "prop-types";
+import React from "react";
+import styles from "./index.module.css";
+
+const apiKeyLocale = {
+ "zh-hant": {
+ active: "有效",
+ expired: "已過期",
+ revoked: "已撤銷",
+ popconfirmRevokeTitle: "確定撤銷這個 Token 嗎?",
+ popconfirmDeleteTitle: "確定刪除這個 Token 嗎?",
+ revokeButton: "撤銷",
+ deleteButton: "刪除",
+ defaultTokenName: "My Token",
+ tokenIdLabel: "Token (ID):",
+ expiryLabel: "到期時間:",
+ statusLabel: "狀態:",
+ },
+ en: {
+ active: "Active",
+ expired: "Expired",
+ revoked: "Revoked",
+ popconfirmRevokeTitle: "Are you sure you want to revoke this token?",
+ popconfirmDeleteTitle: "Are you sure you want to delete this token?",
+ revokeButton: "Revoke",
+ deleteButton: "Delete",
+ defaultTokenName: "My Token",
+ tokenIdLabel: "Token (ID):",
+ expiryLabel: "Expiry:",
+ statusLabel: "Status:",
+ },
+ ja: {
+ active: "有効",
+ expired: "期限切れ",
+ revoked: "無効",
+ popconfirmRevokeTitle: "このトークンを取り消してもよろしいですか?",
+ popconfirmDeleteTitle: "このトークンを削除してもよろしいですか?",
+ revokeButton: "取り消し",
+ deleteButton: "削除",
+ defaultTokenName: "My Token",
+ tokenIdLabel: "トークン (ID):",
+ expiryLabel: "有効期限:",
+ statusLabel: "状態:",
+ },
+};
+
+/**
+ * 單一 Token 卡片組件
+ */
+export default function TokenCard({
+ item,
+ onRevokeOrDelete,
+ maskToken,
+}) {
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const text = apiKeyLocale[currentLocale] || apiKeyLocale.en;
+
+ const {
+ name,
+ is_active,
+ expires_local, // 前端轉換後的當地時區時間
+ jti,
+ __frontend_expired, // 若前端判定該 token 已自然過期
+ } = item;
+
+ // 狀態
+ // 1) 已過期 => 顯示「已過期」
+ // 2) 已撤銷 => 顯示「已撤銷」
+ // 3) 否則 => 顯示「有效」
+ let statusText = text.active;
+ if (!is_active) {
+ statusText = __frontend_expired ? text.expired : text.revoked;
+ }
+
+ // Popconfirm
+ const popConfirmTitle = is_active
+ ? text.popconfirmRevokeTitle
+ : text.popconfirmDeleteTitle;
+ const buttonText = is_active ? text.revokeButton : text.deleteButton;
+
+ return (
+
+ {/* 卡片 Header */}
+
+
+ {name || text.defaultTokenName}
+
+
}
+ onConfirm={() => onRevokeOrDelete(item)}
+ >
+
}
+ >
+ {buttonText}
+
+
+
+
+ {/* 主要資訊 Rows */}
+
+ {text.tokenIdLabel}
+ {maskToken(jti)}
+
+
+
+ {text.expiryLabel}
+ {expires_local || "-"}
+
+
+
+ {text.statusLabel}
+ {statusText}
+
+
+ );
+}
+
+TokenCard.propTypes = {
+ item: PropTypes.shape({
+ name: PropTypes.string,
+ is_active: PropTypes.bool.isRequired,
+ expires_local: PropTypes.string,
+ jti: PropTypes.string.isRequired,
+ __frontend_expired: PropTypes.bool,
+ }).isRequired,
+ onRevokeOrDelete: PropTypes.func.isRequired,
+ maskToken: PropTypes.func.isRequired,
+};
diff --git a/src/components/Dashboard/ApiKey/UsageOverview.js b/src/components/Dashboard/ApiKey/UsageOverview.js
new file mode 100644
index 00000000000..375e2d0c9ab
--- /dev/null
+++ b/src/components/Dashboard/ApiKey/UsageOverview.js
@@ -0,0 +1,199 @@
+import { ReloadOutlined } from "@ant-design/icons";
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Button, Card, Divider, Progress } from "antd";
+import PropTypes from "prop-types";
+import React from "react";
+import {
+ CartesianGrid,
+ Line,
+ LineChart,
+ ResponsiveContainer,
+ Tooltip,
+ XAxis,
+ YAxis,
+} from "recharts";
+import styles from "./UsageOverview.module.css";
+
+const apiKeyLocale = {
+ "zh-hant": {
+ loadingUsage: "載入使用情況...",
+ usageOverviewTitle: "用量概覽",
+ usageHistoryTitle: "歷史使用趨勢",
+ usageThisHourLabel: "本小時用量:",
+ remainingLabel: "剩餘:",
+ refreshButton: "更新用量",
+ },
+ en: {
+ loadingUsage: "Loading usage...",
+ usageOverviewTitle: "Usage Overview",
+ usageHistoryTitle: "Historical Usage Trends",
+ usageThisHourLabel: "Usage this hour:",
+ remainingLabel: "Remaining:",
+ refreshButton: "Refresh",
+ },
+ ja: {
+ loadingUsage: "使用状況を読み込み中...",
+ usageOverviewTitle: "使用状況概観",
+ usageHistoryTitle: "過去の使用傾向",
+ usageThisHourLabel: "今時間の使用量:",
+ remainingLabel: "残り:",
+ refreshButton: "リフレッシュ",
+ },
+};
+
+export default function UsageOverview({ userUsage, usageHistory, onRefresh }) {
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const text = apiKeyLocale[currentLocale] || apiKeyLocale.en;
+
+ // 若後端尚未回傳 userUsage,顯示 loading 狀態
+ if (!userUsage) {
+ return (
+
+ {text.loadingUsage}
+
+ );
+ }
+
+ const { billing_type, used_this_hour, limit_per_hour, remaining } = userUsage;
+
+ // 計算當前用量的百分比,避免 division by zero
+ const percent =
+ billing_type === "rate_limit" && limit_per_hour > 0
+ ? Math.min(100, (used_this_hour / limit_per_hour) * 100)
+ : 0;
+
+ // 點擊刷新按鈕時,若沒有傳入 onRefresh 回呼,預設使用 console.log
+ const handleRefreshClick = () => {
+ if (onRefresh) {
+ onRefresh();
+ } else {
+ console.log("No onRefresh callback provided.");
+ }
+ };
+
+ // 你也可以在父元件就把時間轉好,再給 usageHistory
+ // 如果此處仍是 UTC,可用 tickFormatter 轉為當地時間
+ const formatLocalTime = (val) => {
+ // 若父層已是 local time string,可直接回傳 val
+ // 若 val 仍是 UTC 格式,如 "2025-03-14T12:00:00Z",則可自行轉換
+ const dt = new Date(val);
+ if (Number.isNaN(dt.getTime())) {
+ return val; // 無法轉換就直接回傳原字串
+ }
+ // 回傳當地時區的 HH:MM (或更完整格式)
+ return dt.toLocaleString();
+ };
+
+ return (
+
+ {/*
+ 1) 刷新按鈕放在最上方,使用 primary 樣式使其更顯眼
+ */}
+
+
{text.usageOverviewTitle}
+ }
+ onClick={handleRefreshClick}
+ className={styles.refreshButton}
+ >
+ {text.refreshButton}
+
+
+
+ {/* 2) 用量進度顯示區 */}
+ {billing_type === "rate_limit" ? (
+
+
= limit_per_hour ? "exception" : "normal"}
+ size={80}
+ format={() => `${used_this_hour}/${limit_per_hour}`}
+ className={styles.progressCircle}
+ />
+
+
+ {text.usageThisHourLabel} {used_this_hour}/{limit_per_hour}
+ •
+ {text.remainingLabel} {remaining}
+
+
+
+ ) : billing_type === "pay_per_use" ? (
+
+
`${used_this_hour}`}
+ className={styles.progressCircle}
+ />
+
+
+ {text.usageThisHourLabel} {used_this_hour} (Pay-As-You-Go)
+
+
+
+ ) : (
+ Unknown billing type
+ )}
+
+ {/* 3) 歷史用量折線圖 */}
+ {usageHistory && usageHistory.length > 0 && (
+ <>
+
+ {text.usageHistoryTitle}
+
+
+
+
+
+ {
+ // ToolTip 也做本地時間顯示
+ return formatLocalTime(label);
+ }}
+ />
+
+
+
+ >
+ )}
+
+ );
+}
+
+UsageOverview.propTypes = {
+ userUsage: PropTypes.shape({
+ billing_type: PropTypes.string.isRequired,
+ used_this_hour: PropTypes.number.isRequired,
+ limit_per_hour: PropTypes.number,
+ remaining: PropTypes.number,
+ }),
+ usageHistory: PropTypes.arrayOf(
+ PropTypes.shape({
+ time: PropTypes.string.isRequired, // 從父層拿到的時間字串
+ used: PropTypes.number.isRequired,
+ })
+ ),
+ onRefresh: PropTypes.func,
+};
+
+UsageOverview.defaultProps = {
+ userUsage: null,
+ usageHistory: [],
+ onRefresh: null,
+};
diff --git a/src/components/Dashboard/ApiKey/UsageOverview.module.css b/src/components/Dashboard/ApiKey/UsageOverview.module.css
new file mode 100644
index 00000000000..9f0f97cb2a9
--- /dev/null
+++ b/src/components/Dashboard/ApiKey/UsageOverview.module.css
@@ -0,0 +1,69 @@
+.usageCard {
+ margin-bottom: 24px;
+ border-radius: 8px;
+ padding: 16px;
+ background-color: #fff;
+ /* 視需要可加陰影:box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); */
+}
+
+/* 最上方區域(標題與刷新按鈕) */
+.topBar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 16px;
+}
+
+.mainTitle {
+ margin: 0;
+ font-size: 1.5rem;
+ color: #333;
+}
+
+.refreshButton {
+ /* 讓刷新按鈕更醒目 */
+ margin-left: 12px;
+}
+
+/* 進度與用量區域 */
+.usageHeader {
+ display: flex;
+ align-items: center;
+ gap: 24px;
+ margin-bottom: 16px;
+}
+
+.progressCircle {
+ flex-shrink: 0;
+}
+
+.usageDetails {
+ flex-grow: 1;
+}
+
+.usageText {
+ margin: 0;
+ font-size: 1rem;
+ color: #555;
+}
+
+.divider {
+ margin: 0 8px;
+ font-size: 1rem;
+ color: #999;
+}
+
+/* 歷史圖表區 */
+.dividerStyle {
+ margin: 16px 0;
+}
+
+.historyTitle {
+ margin-bottom: 16px;
+ font-size: 1.2rem;
+ color: #333;
+}
+
+.errorText {
+ color: red;
+}
diff --git a/src/components/Dashboard/ApiKey/index.js b/src/components/Dashboard/ApiKey/index.js
new file mode 100644
index 00000000000..1285fff850b
--- /dev/null
+++ b/src/components/Dashboard/ApiKey/index.js
@@ -0,0 +1,595 @@
+// src/components/Dashboard/ApiKey/index.js
+import {
+ CopyOutlined,
+ EyeInvisibleOutlined,
+ EyeOutlined,
+ PlusOutlined,
+} from "@ant-design/icons";
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Button, List, message, Modal, Spin, Tabs } from "antd";
+import React, { useCallback, useEffect, useState } from "react";
+import { useAuth } from "../../../context/AuthContext";
+
+import { Tooltip } from "antd";
+import CreateTokenModal from "./CreateTokenModal";
+import TokenCard from "./TokenCard";
+import UsageOverview from "./UsageOverview";
+import styles from "./index.module.css";
+
+const apiKeyLocale = {
+ "zh-hant": {
+ headerTitle: "我的 API Keys",
+ headerDescription: "管理、檢視、撤銷與刪除你的公開 Token",
+ currentPlanLabel: "目前方案",
+ toggleShowTokens: "顯示全部",
+ toggleHideTokens: "隱藏全部",
+ createTokenButton: "建立新 Token",
+ collapseHeader: "我的 Token 列表",
+ // apiUsageExampleTitle: "API 使用範例", // 已移除,交由新頁面負責
+ newTokenModalTitle: "以下是您的新 Token",
+ newTokenModalDesc: "請複製並保存,關閉後無法再次查看。",
+ copyTokenButton: "複製 Token",
+ closeButton: "關閉",
+ notLoggedIn: "尚未登入,無法申請 Token",
+ tokenRevoked: "Token 已撤銷",
+ tokenDeleted: "Token 已刪除",
+ createTokenSuccessTitle: "Token 建立成功",
+ copyFailure: "複製失敗",
+ copySuccess: "已複製",
+ emailNotVerified: "尚未驗證電子郵件,無法申請 API Token。",
+ loadingProfile: "載入個人資料...",
+ pleaseVerifyEmailTitle: "請先驗證電子郵件",
+ pleaseVerifyEmailDesc: "您尚未完成電子郵件驗證,無法使用 API Token 功能。請前往 {0} 頁面完成驗證。",
+ myInfoPage: "我的資訊",
+ fetchUserProfileFailed: "載入個人資料失敗: {0}",
+ fetchTokensFailed: "取得 Token 列表失敗: {0}",
+ fetchUserUsageFailed: "取得用量失敗: {0}",
+ createTokenFailed: "建立 Token 失敗: {0}",
+ operationFailed: "操作失敗: {0}",
+ notAvailable: "N/A",
+ basicPlan: "基本 (免費)",
+ payPerUsePlan: "隨用隨付",
+ unknownPlan: "未知方案",
+ },
+ en: {
+ headerTitle: "My API Keys",
+ headerDescription: "Manage, view, revoke, and delete your public tokens",
+ currentPlanLabel: "Current Plan",
+ toggleShowTokens: "Show All",
+ toggleHideTokens: "Hide All",
+ createTokenButton: "Create New Token",
+ collapseHeader: "My Token List",
+ // apiUsageExampleTitle: "API Usage Examples",
+ newTokenModalTitle: "Your New Token",
+ newTokenModalDesc: "Please copy and save it. It will not be shown again after closing.",
+ copyTokenButton: "Copy Token",
+ closeButton: "Close",
+ notLoggedIn: "Not logged in, unable to create Token",
+ tokenRevoked: "Token Revoked",
+ tokenDeleted: "Token Deleted",
+ createTokenSuccessTitle: "Token Created Successfully",
+ copyFailure: "Copy failed",
+ copySuccess: "Copied",
+ emailNotVerified: "Email not verified, unable to create API Token.",
+ loadingProfile: "Loading Profile...",
+ pleaseVerifyEmailTitle: "Please verify your email",
+ pleaseVerifyEmailDesc: "You have not verified your email, and cannot use the API Token feature. Please go to the {0} page to complete verification.",
+ myInfoPage: "My Info",
+ fetchUserProfileFailed: "Failed to load profile: {0}",
+ fetchTokensFailed: "Failed to fetch tokens: {0}",
+ fetchUserUsageFailed: "Failed to fetch usage: {0}",
+ createTokenFailed: "Failed to create token: {0}",
+ operationFailed: "Operation failed: {0}",
+ notAvailable: "N/A",
+ basicPlan: "Basic (Free)",
+ payPerUsePlan: "Pay-As-You-Go",
+ unknownPlan: "Unknown Plan",
+ },
+ ja: {
+ headerTitle: "マイAPIキー",
+ headerDescription: "公開トークンの管理、確認、取り消し、削除",
+ currentPlanLabel: "Current Plan",
+ toggleShowTokens: "すべて表示",
+ toggleHideTokens: "すべて非表示",
+ createTokenButton: "新規トークン作成",
+ collapseHeader: "マイトークン一覧",
+ // apiUsageExampleTitle: "API利用例",
+ newTokenModalTitle: "あなたの新しいトークン",
+ newTokenModalDesc: "コピーして保存してください。閉じると再表示されません。",
+ copyTokenButton: "トークンをコピー",
+ closeButton: "閉じる",
+ notLoggedIn: "未ログインのため、Token を作成できません",
+ tokenRevoked: "Token は取り消されました",
+ tokenDeleted: "Token は削除されました",
+ createTokenSuccessTitle: "Token 作成成功",
+ copyFailure: "コピー失敗",
+ copySuccess: "コピーしました",
+ emailNotVerified: "メールが認証されていないため、API Token を作成できません。",
+ loadingProfile: "プロファイルを読み込み中...",
+ pleaseVerifyEmailTitle: "メール認証をしてください",
+ pleaseVerifyEmailDesc: "メール認証が完了していないため、API Token 機能を利用できません。{0} ページに進んで認証を完了してください。",
+ myInfoPage: "マイ情報",
+ fetchUserProfileFailed: "プロファイルの読み込みに失敗しました: {0}",
+ fetchTokensFailed: "トークン一覧の取得に失敗しました: {0}",
+ fetchUserUsageFailed: "使用状況の取得に失敗しました: {0}",
+ createTokenFailed: "トークンの作成に失敗しました: {0}",
+ operationFailed: "操作に失敗しました: {0}",
+ notAvailable: "N/A",
+ basicPlan: "ベーシック (無料)",
+ payPerUsePlan: "従量課金",
+ unknownPlan: "不明なプラン",
+ },
+};
+
+/** 解析 JWT 中的 jti(供新建 Token 時使用) */
+function parseJti(jwtStr) {
+ try {
+ const parts = jwtStr.split(".");
+ if (parts.length !== 3) return null;
+ const payloadRaw = atob(parts[1]);
+ const payload = JSON.parse(payloadRaw);
+ return payload.jti;
+ } catch {
+ return null;
+ }
+}
+
+function CopyTokenButton({ tokenStr, text }) {
+ const [tooltipTitle, setTooltipTitle] = useState(text.copyTokenButton);
+ const [visible, setVisible] = useState(false);
+
+ // 點擊複製
+ const handleCopy = async () => {
+ if (!tokenStr) return;
+ try {
+ await navigator.clipboard.writeText(tokenStr);
+ setTooltipTitle(text.copySuccess); // 設為「已複製」
+ setVisible(true);
+
+ // 1 秒後自動隱藏 tooltip,回復初始狀態
+ setTimeout(() => {
+ setVisible(false);
+ setTooltipTitle(text.copyTokenButton);
+ }, 1000);
+ } catch {
+ console.error("Failed to copy token");
+ }
+ };
+
+ return (
+ setVisible(v)}
+ >
+ }
+ onClick={handleCopy}
+ style={{ marginRight: 8 }}
+ >
+ {text.copyTokenButton}
+
+
+ );
+}
+
+/** 將 UTC 時間字串轉成本地時間 */
+function formatToLocalTime(utcString) {
+ if (!utcString) return "";
+ const dt = new Date(utcString);
+ if (Number.isNaN(dt.getTime())) return utcString;
+ return dt.toLocaleString();
+}
+
+export default function DashboardApiKey() {
+ const { token: userToken } = useAuth();
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const text = apiKeyLocale[currentLocale] || apiKeyLocale.en;
+
+ // ========================
+ // State
+ // ========================
+ const [userProfile, setUserProfile] = useState(null);
+ const [loadingProfile, setLoadingProfile] = useState(false);
+ const [apiKeys, setApiKeys] = useState([]);
+ const [userUsage, setUserUsage] = useState(null);
+ const [usageHistory, setUsageHistory] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [createModalVisible, setCreateModalVisible] = useState(false);
+ const [newTokenModalVisible, setNewTokenModalVisible] = useState(false);
+ const [latestCreatedToken, setLatestCreatedToken] = useState("");
+ const [showTokenPlain, setShowTokenPlain] = useState(false);
+
+ // ========================
+ // 抓取使用者檔案 /auth/me
+ // ========================
+ const fetchUserProfile = useCallback(async () => {
+ if (!userToken) return;
+ setLoadingProfile(true);
+ try {
+ const res = await fetch("https://api.docsaid.org/auth/me", {
+ headers: { Authorization: `Bearer ${userToken}` },
+ });
+ if (!res.ok) {
+ throw new Error(text.fetchUserProfileFailed.replace("{0}", res.status));
+ }
+ const data = await res.json();
+ setUserProfile(data);
+ } catch (err) {
+ message.error(err.message);
+ } finally {
+ setLoadingProfile(false);
+ }
+ }, [userToken, text]);
+
+ // ========================
+ // 抓取 token 列表 /my-tokens
+ // ========================
+ const fetchTokens = useCallback(async () => {
+ if (!userToken) return;
+ setLoading(true);
+ try {
+ const res = await fetch("https://api.docsaid.org/public/token/my-tokens", {
+ headers: { Authorization: `Bearer ${userToken}` },
+ });
+ if (!res.ok) {
+ throw new Error(text.fetchTokensFailed.replace("{0}", res.status));
+ }
+ let data = await res.json();
+ const now = new Date();
+ data = data.map((tk) => {
+ if (tk.expires_at) {
+ const dt = new Date(tk.expires_at);
+ if (dt <= now) {
+ return { ...tk, is_active: false, __frontend_expired: true };
+ }
+ }
+ return tk;
+ });
+ setApiKeys(data);
+ } catch (err) {
+ message.error(err.message);
+ } finally {
+ setLoading(false);
+ }
+ }, [userToken, text]);
+
+ // ========================
+ // 抓取用量 /user-usage
+ // ========================
+ const fetchUserUsage = useCallback(async () => {
+ if (!userToken) return;
+ try {
+ const res = await fetch("https://api.docsaid.org/public/token/user-usage", {
+ headers: { Authorization: `Bearer ${userToken}` },
+ });
+ if (!res.ok) {
+ const e = await res.json().catch(() => ({}));
+ throw new Error(e.detail || text.fetchUserUsageFailed.replace("{0}", res.status));
+ }
+ const usage = await res.json();
+ setUserUsage(usage);
+ } catch (err) {
+ console.error(err);
+ }
+ }, [userToken, text]);
+
+ // ========================
+ // 新增:抓取歷史用量資料
+ // ========================
+ const fetchUsageHistory = useCallback(async () => {
+ if (!userToken) return;
+ try {
+ const res = await fetch("https://api.docsaid.org/public/token/usage-history-minute", {
+ headers: { Authorization: `Bearer ${userToken}` },
+ });
+ if (!res.ok) {
+ throw new Error("Failed to fetch usage history");
+ }
+ const historyData = await res.json();
+
+ // 轉換 UTC+0 時間為使用者當地時區時間
+ const localHistory = historyData.map((item) => {
+ const dt = new Date(item.time + "Z");
+ const localTimeStr = dt.toLocaleString(undefined, {
+ timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
+ year: "numeric",
+ month: "2-digit",
+ day: "2-digit",
+ hour: "2-digit",
+ minute: "2-digit",
+ second: "2-digit",
+ hour12: false,
+ });
+ return {
+ ...item,
+ time: localTimeStr,
+ };
+ });
+
+ setUsageHistory(localHistory);
+ } catch (err) {
+ console.error(err);
+ }
+ }, [userToken]);
+
+ // 同時抓取 user-usage 與 usage-history-minute
+ const refreshUsageData = useCallback(async () => {
+ await fetchUserUsage();
+ await fetchUsageHistory();
+ }, [fetchUserUsage, fetchUsageHistory]);
+
+ // 頁面初始載入
+ useEffect(() => {
+ fetchUserProfile();
+ fetchTokens();
+ refreshUsageData();
+ }, [fetchUserProfile, fetchTokens, refreshUsageData]);
+
+ // 申請新 Token
+ const handleCreateToken = async (formValues) => {
+ if (!userProfile) return;
+ if (!userProfile.is_email_verified) {
+ message.error(text.emailNotVerified);
+ return;
+ }
+ const { isLongTerm, expires_minutes, name } = formValues;
+ const finalExpires = isLongTerm ? 525600 : expires_minutes;
+
+ if (!userToken) {
+ message.error(text.notLoggedIn);
+ return;
+ }
+
+ setLoading(true);
+ try {
+ const params = new URLSearchParams({
+ expires_minutes: finalExpires,
+ name: name || "",
+ });
+ const res = await fetch(
+ `https://api.docsaid.org/public/token/?${params.toString()}`,
+ {
+ method: "POST",
+ headers: {
+ Authorization: `Bearer ${userToken}`,
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ if (!res.ok) {
+ const e = await res.json().catch(() => ({}));
+ throw new Error(e.detail || text.createTokenFailed.replace("{0}", res.status));
+ }
+ const data = await res.json();
+ message.success(text.createTokenSuccessTitle);
+
+ const newAccessToken = data.access_token;
+ const jti = parseJti(newAccessToken) || `temp-${Date.now()}`;
+
+ let newItem = {
+ jti,
+ is_active: true,
+ expires_at: data.expires_at,
+ name: name || "",
+ };
+
+ if (newItem.expires_at) {
+ const now = new Date();
+ const dt = new Date(newItem.expires_at);
+ if (dt <= now) {
+ newItem.is_active = false;
+ newItem.__frontend_expired = true;
+ }
+ }
+
+ setApiKeys((prev) => [newItem, ...prev]);
+ setTimeout(async () => {
+ await fetchTokens();
+ }, 1000);
+
+ setLatestCreatedToken(newAccessToken);
+ setNewTokenModalVisible(true);
+ setCreateModalVisible(false);
+ } catch (err) {
+ message.error(err.message || text.createTokenFailed.replace("{0}", ""));
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ // Revoke / Remove Token
+ const handleRevokeOrDelete = async (tokenItem) => {
+ if (!userToken) return;
+
+ setLoading(true);
+ const endpoint = tokenItem.is_active ? "revoke" : "remove";
+
+ try {
+ const res = await fetch(`https://api.docsaid.org/public/token/${endpoint}`, {
+ method: "POST",
+ headers: {
+ Authorization: `Bearer ${userToken}`,
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ jti: tokenItem.jti }),
+ });
+ if (!res.ok) {
+ const e = await res.json().catch(() => ({}));
+ throw new Error(e.detail || text.operationFailed.replace("{0}", res.status));
+ }
+ message.success(tokenItem.is_active ? text.tokenRevoked : text.tokenDeleted);
+ await fetchTokens();
+ } catch (err) {
+ message.error(err.message);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ // 複製 Token(新建後 Modal 使用)
+ const copyToken = async (tokenStr) => {
+ if (!tokenStr) {
+ message.error(text.copyFailure);
+ return;
+ }
+ try {
+ await navigator.clipboard.writeText(tokenStr);
+ message.success(text.copySuccess);
+ } catch {
+ message.error(text.copyFailure);
+ }
+ };
+
+ // 遮罩 jti(若未顯示明碼)
+ const maskToken = (val) => {
+ if (!val) return text.notAvailable;
+ if (showTokenPlain) return val;
+ if (val.length < 10) {
+ return val.slice(0, 2) + "****" + val.slice(-2);
+ }
+ return val.slice(0, 6) + "****" + val.slice(-4);
+ };
+
+ // 顯示計費方案
+ function getPlanLabel(billingType) {
+ switch (billingType) {
+ case "rate_limit":
+ return text.basicPlan;
+ case "pay_per_use":
+ return text.payPerUsePlan;
+ default:
+ return text.unknownPlan;
+ }
+ }
+ const renderPlanBox = () => {
+ if (!userUsage) return null;
+ const planLabel = getPlanLabel(userUsage.billing_type);
+ return (
+
+ {text.currentPlanLabel}: {planLabel}
+
+ );
+ };
+
+ if (loadingProfile && !userProfile) {
+ return (
+
+
+
+ );
+ }
+
+ if (userProfile && !userProfile.is_email_verified) {
+ return (
+
+
{text.pleaseVerifyEmailTitle}
+
{text.pleaseVerifyEmailDesc.replace("{0}", text.myInfoPage)}
+
+ );
+ }
+
+ return (
+
+ {/* Header */}
+
+ {text.headerTitle}
+ {text.headerDescription}
+
+
+ {/* 顯示方案 & 用量 */}
+ {renderPlanBox()}
+
+
+ {/* 操作按鈕 */}
+
+ }
+ onClick={() => setCreateModalVisible(true)}
+ className={styles.createButton}
+ >
+ {text.createTokenButton}
+
+ setShowTokenPlain(!showTokenPlain)}>
+ {showTokenPlain ? : }
+ {showTokenPlain ? text.toggleHideTokens : text.toggleShowTokens}
+
+
+
+ {/* 只剩一個 Tab:Token 列表 */}
+
item.jti}
+ renderItem={(item) => {
+ const localExpires = item.expires_at ? formatToLocalTime(item.expires_at) : "";
+ return (
+
+
+
+ );
+ }}
+ />
+ ),
+ },
+ ]}
+ />
+
+ {/* 建立 Token 的 Modal */}
+ setCreateModalVisible(false)}
+ onSubmit={handleCreateToken}
+ loading={loading}
+ />
+
+ {/* 新建 Token 後一次性顯示 */}
+ setNewTokenModalVisible(false)}
+ footer={null}
+ destroyOnClose
+ >
+ {text.newTokenModalDesc}
+
+ {latestCreatedToken}
+
+
+
+
+ setNewTokenModalVisible(false)}>
+ {text.closeButton}
+
+
+
+ );
+}
diff --git a/src/components/Dashboard/ApiKey/index.module.css b/src/components/Dashboard/ApiKey/index.module.css
new file mode 100644
index 00000000000..73bd568e146
--- /dev/null
+++ b/src/components/Dashboard/ApiKey/index.module.css
@@ -0,0 +1,108 @@
+/* src/components/Dashboard/ApiKey/index.module.css */
+
+/* 容器 */
+.apiKeyContainer {
+ max-width: 900px;
+ margin: 0 auto;
+ padding: 24px;
+ background-color: #fafafa;
+ border-radius: 8px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+}
+
+/* 頁面標題 */
+.header {
+ margin-bottom: 24px;
+ text-align: left;
+}
+.header h2 {
+ font-size: 2rem;
+ margin: 0 0 8px 0;
+ color: #333;
+}
+.header p {
+ font-size: 1rem;
+ color: #555;
+ margin: 0;
+}
+
+/* 操作按鈕列 */
+.actions {
+ margin-bottom: 24px;
+ display: flex;
+ gap: 12px;
+}
+
+/* 用於顯示建立完成後的 Token */
+.tokenBox {
+ background: #fff;
+ padding: 12px;
+ word-break: break-all;
+ font-family: monospace;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
+}
+
+/* Collapse 外框 */
+.collapseRoot {
+ background-color: #fff;
+ border: 1px solid #e8e8e8;
+ border-radius: 8px;
+ margin-bottom: 24px;
+}
+
+/* List.Item */
+.tokenListItem {
+ border: none !important;
+ margin-bottom: 16px;
+}
+
+/* Token 卡片 */
+.tokenCard {
+ width: 100%;
+ background-color: #fff;
+ border-radius: 8px;
+ padding: 16px;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
+}
+.tokenCard:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+}
+
+/* 卡片頂部區域 */
+.tokenCardHeader {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 12px;
+}
+
+/* Token 名稱 */
+.tokenName {
+ font-weight: 600;
+ font-size: 1.1rem;
+ margin-bottom: 4px;
+ color: #333;
+}
+
+/* 方案標籤 */
+.planLabel {
+ font-size: 0.9rem;
+ color: #888;
+}
+
+/* 一般欄位 */
+.tokenRow {
+ margin: 6px 0;
+ line-height: 1.8;
+ font-size: 0.95rem;
+ color: #444;
+}
+.label {
+ font-weight: 500;
+ color: #666;
+ margin-right: 4px;
+}
diff --git a/src/components/Dashboard/MyInfo/index.js b/src/components/Dashboard/MyInfo/index.js
new file mode 100644
index 00000000000..ebf08809708
--- /dev/null
+++ b/src/components/Dashboard/MyInfo/index.js
@@ -0,0 +1,595 @@
+// src/components/Dashboard/MyInfo/index.js
+import { UploadOutlined, UserOutlined } from "@ant-design/icons";
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import {
+ Alert,
+ Avatar,
+ Button,
+ Col,
+ DatePicker,
+ Divider,
+ Form,
+ Input,
+ message,
+ Modal,
+ Row,
+ Spin,
+ Typography,
+ Upload,
+} from "antd";
+import moment from "moment";
+import React, { useCallback, useEffect, useState } from "react";
+import PasswordInput from "../../../components/PasswordInput";
+import { useAuth } from "../../../context/AuthContext";
+import styles from "./index.module.css";
+import { changePasswordLocale, dashboardLocale, deleteAccountLocale } from "./locales";
+
+const { Text } = Typography;
+
+export default function DashboardMyInfo() {
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const text = dashboardLocale[currentLocale] || dashboardLocale.en;
+
+ const {
+ token,
+ user,
+ setUser,
+ updateProfile,
+ sendVerificationEmail,
+ changePassword,
+ deleteAccount,
+ } = useAuth();
+
+ const [infoLoading, setInfoLoading] = useState(false);
+ const [editing, setEditing] = useState(false);
+ const [pwdModalVisible, setPwdModalVisible] = useState(false);
+ const [deleteModalVisible, setDeleteModalVisible] = useState(false);
+ const [verificationModalVisible, setVerificationModalVisible] = useState(false);
+ const [profileForm] = Form.useForm();
+ const [pwdForm] = Form.useForm();
+ const [uploadLoading, setUploadLoading] = useState(false);
+ const [showEmailAlert, setShowEmailAlert] = useState(false);
+
+ // 禁用未來日期
+ const disabledFutureDates = useCallback(
+ (current) => current && current.isAfter(moment(), "day"),
+ []
+ );
+
+ // 上次登入資訊
+ const lastLoginTime = user?.last_login_at
+ ? moment(user.last_login_at).format("YYYY-MM-DD HH:mm") + " (UTC+0)"
+ : text.notSet;
+ const lastLoginIp = user?.last_login_ip || text.notSet;
+
+ // =========== 1. 取得使用者資訊 ===========
+ const refreshUserInfo = async () => {
+ if (!token) return;
+ setInfoLoading(true);
+ try {
+ const res = await fetch("https://api.docsaid.org/auth/me", {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ });
+ if (!res.ok) {
+ throw new Error(text.fetchUserInfoFailure);
+ }
+ const data = await res.json();
+ setUser(data);
+ // 若 email 存在但未驗證,顯示警示
+ setShowEmailAlert(data.email && data.is_email_verified === false);
+ } catch (err) {
+ message.error(err.message || text.fetchUserInfoFailure);
+ } finally {
+ setInfoLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ refreshUserInfo();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [token]);
+
+ // 若 user 存在但尚未設定 email,自動切換至編輯模式
+ useEffect(() => {
+ if (user && !user.email) {
+ setEditing(true);
+ }
+ }, [user]);
+
+ // =========== 2. 編輯個人資料 ===========
+ const onEditProfile = () => {
+ setEditing(true);
+ if (user) {
+ profileForm.setFieldsValue({
+ username: user.username,
+ email: user.email,
+ phone: user.phone,
+ birth: user.birth ? moment(user.birth, "YYYY-MM-DD") : null,
+ });
+ }
+ };
+
+ // =========== 3. 儲存個人資料 ===========
+ const onSaveProfile = async (values) => {
+ try {
+ const birthString = values.birth
+ ? moment(values.birth).format("YYYY-MM-DD")
+ : null;
+ const payload = { ...values, birth: birthString };
+ const updatedUser = await updateProfile(payload);
+ message.success(text.successMsg);
+ setUser(updatedUser);
+ setShowEmailAlert(
+ updatedUser.email && updatedUser.is_email_verified === false
+ );
+ setEditing(false);
+ } catch (err) {
+ if (err.message.includes("Email already exists")) {
+ profileForm.setFields([{ name: "email", errors: [err.message] }]);
+ }
+ message.error(err.message || text.fetchUserInfoFailure);
+ }
+ };
+
+ // =========== 4. 上傳頭像 ===========
+ const onUploadAvatar = async ({ file }) => {
+ if (!token) return;
+ setUploadLoading(true);
+ try {
+ const formData = new FormData();
+ formData.append("file", file);
+
+ const res = await fetch("https://api.docsaid.org/auth/avatar", {
+ method: "PUT",
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ body: formData,
+ });
+ if (!res.ok) {
+ const errData = await res.json().catch(() => ({}));
+ throw new Error(errData.detail || text.avatarUploadFailure);
+ }
+ const result = await res.json();
+ message.success(text.avatarUploadSuccess);
+ setUser((prev) => ({
+ ...prev,
+ avatar: result.avatar,
+ }));
+ } catch (err) {
+ message.error(err.message || text.avatarUploadFailure);
+ } finally {
+ setUploadLoading(false);
+ }
+ };
+
+ // =========== 5. 變更密碼 ===========
+ const openChangePwdModal = () => {
+ setPwdModalVisible(true);
+ };
+
+ const [errorModalVisible, setErrorModalVisible] = useState(false);
+ const [errorMessage, setErrorMessage] = useState("");
+
+ const onChangePassword = async (values) => {
+ if (values.newPassword !== values.confirmPassword) {
+ setErrorMessage(text.passwordMismatch);
+ setErrorModalVisible(true);
+ return;
+ }
+ try {
+ await changePassword(values.oldPassword, values.newPassword);
+ message.success(text.changePasswordSuccess);
+ setPwdModalVisible(false);
+ pwdForm.resetFields();
+ } catch (err) {
+ console.error("變更密碼錯誤:", err);
+ const errorMsg =
+ err.response?.data?.detail || err.message || text.changePasswordFailureTitle;
+ setErrorMessage(errorMsg);
+ setErrorModalVisible(true);
+ }
+ };
+
+ // =========== 6. 重新寄送驗證信 ===========
+ const onResendVerification = () => {
+ if (!user?.email) return;
+ setVerificationModalVisible(true);
+ };
+
+ const handleVerificationOk = async () => {
+ try {
+ await sendVerificationEmail(user.email);
+ message.success(
+ text.verificationModalSent || "驗證信已寄出,請檢查信箱"
+ );
+ setVerificationModalVisible(false);
+ } catch (err) {
+ message.error(err.message || "寄送驗證信失敗");
+ }
+ };
+
+ // =========== 7. 刪除帳號 ===========
+ const onDeleteAccount = async () => {
+ try {
+ await deleteAccount();
+ message.success(text.deleteAccountSuccess);
+ setDeleteModalVisible(false);
+ window.location.href = "/";
+ } catch (err) {
+ message.error(err.message || "刪除帳號失敗");
+ }
+ };
+
+ if (infoLoading) {
+ return ;
+ }
+
+ // 修正 Alert 中替換字串的問題
+ const renderNoEmailAlertDescription = () => {
+ const parts = text.noEmailAlertDesc.split("{editLink}");
+ return (
+ <>
+ {parts[0]}
+
+ {text.editButton}
+
+ {parts[1]}
+ >
+ );
+ };
+
+ const renderEmailStatus = () => {
+ if (!user?.email) {
+ return {text.notSet} ;
+ }
+ if (user.is_email_verified) {
+ return {text.verified} ;
+ }
+ return (
+
+ {text.notVerified}
+
+ {text.resendVerification}
+
+
+ );
+ };
+
+ return (
+
+
+
+ {showEmailAlert && user?.email && !user.is_email_verified && (
+
+ )}
+
+ {!user?.email && !editing && (
+
+ )}
+
+
+
+
+
}
+ alt="User Avatar"
+ onError={() => false}
+ />
+
+
+ } className={styles.uploadButton}>
+ {uploadLoading
+ ? text.uploadAvatarButtonUploading
+ : text.uploadAvatarButton}
+
+
+
+
+
+
+ {editing ? (
+
+
+
+
+ {user?.is_email_verified === false ? : }
+
+
+
+
+ ({
+ value: value ? moment(value, "YYYY-MM-DD").startOf("day") : null,
+ })}
+ getValueFromEvent={(date) =>
+ date ? date.format("YYYY-MM-DD") : null
+ }
+ >
+ {
+ if (open) {
+ profileForm.setFieldsValue({ birth: null });
+ }
+ }}
+ />
+
+
+
+ {text.saveButton || "儲存"}
+
+ setEditing(false)} className={styles.cancelButton}>
+ {text.cancelButton || "取消"}
+
+
+
+ ) : (
+
+
+ {text.accountLabel}:{user?.username || text.notSet}
+
+
+ {text.emailLabel}:{user?.email || text.notSet}
+ {user?.email && (
+
+ ({text.statusLabel}:{renderEmailStatus()})
+
+ )}
+
+
+ {text.phoneLabel}:{user?.phone || text.notSet}
+
+
+ {text.birthLabel}:
+ {user?.birth
+ ? moment(user.birth).format("YYYY-MM-DD")
+ : text.notSet}
+
+
+
+ {text.lastLoginTimeLabel}
+ {lastLoginTime}
+
+ {text.lastLoginIpLabel}
+ {lastLoginIp}
+
+
+ {text.editButton}
+
+
+ )}
+
+
+
+
+
+
+
+
+ {text.changePasswordButton}
+
+
+
+ setDeleteModalVisible(true)}>
+ {text.deleteAccountButton}
+
+
+
+
+
{
+ setPwdModalVisible(false);
+ pwdForm.resetFields();
+ }}
+ onSubmit={onChangePassword}
+ form={pwdForm}
+ />
+
+ setDeleteModalVisible(false)}
+ onDelete={onDeleteAccount}
+ />
+
+ {/* 驗證信 Modal */}
+ document.body}
+ onOk={handleVerificationOk}
+ onCancel={() => setVerificationModalVisible(false)}
+ okText={text.verificationModalOk}
+ cancelText={text.verificationModalCancel}
+ okButtonProps={{ disabled: /@example\.com$/i.test(user?.email) }}
+ >
+ {/@example\.com$/i.test(user?.email) ? (
+ {text.verificationModalExampleEmail}
+ ) : (
+ {text.verificationModalDesc.replace("{email}", user?.email)}
+ )}
+
+
+ setErrorModalVisible(false)}
+ footer={[
+ setErrorModalVisible(false)}>
+ {text.changePasswordModalOk}
+ ,
+ ]}
+ >
+ {errorMessage}
+
+
+ );
+}
+
+function ChangePasswordModal({ visible, onCancel, onSubmit, form }) {
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const text = changePasswordLocale[currentLocale] || changePasswordLocale.en;
+
+ const [passwordStrength, setPasswordStrength] = useState("");
+
+ const onFinish = (values) => {
+ onSubmit(values);
+ setPasswordStrength("");
+ };
+
+ const handlePasswordChange = (e) => {
+ const pwd = e.target.value;
+ if (pwd.length < 6) {
+ setPasswordStrength("弱");
+ } else if (pwd.length < 10) {
+ setPasswordStrength("中");
+ } else {
+ setPasswordStrength("強");
+ }
+ };
+
+ return (
+ {
+ onCancel();
+ form.resetFields();
+ setPasswordStrength("");
+ }}
+ onOk={() => form.submit()}
+ okText={text.okText}
+ cancelText={text.cancelText}
+ >
+
+
+
+
+ {text.newPasswordLabel}
+ {passwordStrength && (
+
+ (強度:{passwordStrength})
+
+ )}
+ >
+ }
+ name="newPassword"
+ rules={[
+ { required: true, message: text.newPasswordRequired },
+ {
+ validator: async (_, value) => {
+ if (!value) {
+ return Promise.reject(new Error(text.newPasswordRequired));
+ }
+ if (value.length < 8) {
+ return Promise.reject(new Error(text.newPasswordTooShort));
+ }
+ return Promise.resolve();
+ },
+ },
+ ]}
+ >
+
+
+ ({
+ validator(_, value) {
+ if (!value || getFieldValue("newPassword") === value) {
+ return Promise.resolve();
+ }
+ return Promise.reject(text.passwordMismatch);
+ },
+ }),
+ ]}
+ >
+
+
+
+
+ );
+}
+
+function DeleteAccountModal({ visible, onCancel, onDelete }) {
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const text = deleteAccountLocale[currentLocale] || deleteAccountLocale.en;
+
+ return (
+
+ {text.modalContent}
+
+ );
+}
diff --git a/src/components/Dashboard/MyInfo/index.module.css b/src/components/Dashboard/MyInfo/index.module.css
new file mode 100644
index 00000000000..ffa76f77971
--- /dev/null
+++ b/src/components/Dashboard/MyInfo/index.module.css
@@ -0,0 +1,96 @@
+/* src/components/Dashboard/MyInfo/index.module.css */
+
+.container {
+ max-width: 900px;
+ margin: 0 auto;
+ padding: 24px;
+ background-color: #fafafa;
+ border-radius: 8px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+ }
+
+ /* 統一頁面標題 */
+ .header {
+ margin-bottom: 24px;
+ text-align: left;
+ }
+
+ .header h2 {
+ font-size: 2rem;
+ margin: 0;
+ color: #333;
+ }
+
+ /* 針對手機、平板調整容器間距 */
+ @media (max-width: 576px) {
+ .container {
+ padding: 16px;
+ }
+ .header h2 {
+ font-size: 1.5rem;
+ }
+ }
+
+ /* Alert 設定 */
+ .alert {
+ margin-bottom: 16px;
+ }
+
+ /* Avatar 與上傳按鈕 */
+ .avatarContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .uploadButton {
+ margin-top: 8px;
+ }
+
+ /* 調整 Avatar 尺寸於小裝置 */
+ @media (max-width: 576px) {
+ .avatarContainer .ant-avatar {
+ width: 120px;
+ height: 120px;
+ font-size: 1rem;
+ }
+ }
+
+ /* 表單與個人資訊區塊 */
+ .profileInfo {
+ font-size: 1rem;
+ color: #333;
+ }
+
+ .profileInfo p {
+ margin-bottom: 8px;
+ }
+
+ /* Email 狀態提示 */
+ .emailStatus {
+ margin-left: 8px;
+ }
+
+ /* 編輯按鈕樣式 */
+ .editButton {
+ padding: 0;
+ font-size: 1rem;
+ text-decoration: underline;
+ }
+
+ /* 按鈕間距調整 */
+ .saveButton {
+ margin-right: 8px;
+ }
+
+
+ /* 平板與桌面,進一步優化間距 */
+ @media (min-width: 768px) and (max-width: 991px) {
+ .container {
+ padding: 20px;
+ }
+ .header h2 {
+ font-size: 1.75rem;
+ }
+ }
diff --git a/src/components/Dashboard/MyInfo/locales.js b/src/components/Dashboard/MyInfo/locales.js
new file mode 100644
index 00000000000..d92ef72ceae
--- /dev/null
+++ b/src/components/Dashboard/MyInfo/locales.js
@@ -0,0 +1,192 @@
+export const dashboardLocale = {
+ "zh-hant": {
+ myInfoTitle: "我的資訊",
+ emailNotVerifiedAlertTitle: "您的 Email 尚未驗證",
+ emailNotVerifiedAlertDesc:
+ "我們將定期清除未驗證電子郵件的帳號。若您希望長期保留此帳號,請點擊下方按鈕寄送驗證信,並檢查您的信箱完成驗證。",
+ noEmailAlertTitle: "尚未填寫 Email",
+ noEmailAlertDesc: "您尚未綁定 Email,請點 {editLink} 補上 Email。",
+ uploadAvatarButtonUploading: "上傳中...",
+ uploadAvatarButton: "上傳頭像",
+ accountLabel: "帳號",
+ emailLabel: "Email",
+ phoneLabel: "電話",
+ birthLabel: "生日",
+ notSet: "(未設定)",
+ lastLoginTimeLabel: "上次登入時間:",
+ lastLoginIpLabel: "上次登入 IP:",
+ statusLabel: "狀態",
+ editButton: "編輯",
+ changePasswordButton: "變更密碼",
+ deleteAccountButton: "刪除帳號",
+ successMsg: "個人資料更新成功",
+ fetchUserInfoFailure: "取得使用者資訊失敗",
+ avatarUploadFailure: "頭像上傳失敗",
+ avatarUploadSuccess: "頭像已更新",
+ verified: "已驗證",
+ notVerified: "未驗證",
+ resendVerification: "寄送驗證信",
+ changePasswordSuccess: "密碼變更成功!",
+ passwordMismatch: "兩次輸入的密碼不一致",
+ changePasswordFailureTitle: "變更密碼失敗",
+ verificationModalTitle: "寄送驗證信",
+ verificationModalOk: "確定",
+ verificationModalCancel: "取消",
+ verificationModalExampleEmail:
+ "預設信箱 (example.com) 無法用於驗證,請更換為有效的 Email。",
+ verificationModalDesc:
+ "系統將發送驗證信至:{email}\n請確認此 Email 是否正確?",
+ deleteAccountSuccess: "帳號已刪除,將導回首頁",
+ saveButton: "儲存",
+ cancelButton: "取消",
+ changePasswordModalOk: "確定",
+ },
+ en: {
+ myInfoTitle: "My Information",
+ emailNotVerifiedAlertTitle: "Your Email is not verified",
+ emailNotVerifiedAlertDesc:
+ "We regularly remove accounts with unverified email addresses. If you wish to keep your account, please click the button below to send a verification email and check your inbox to complete the verification process.",
+ noEmailAlertTitle: "Email not set",
+ noEmailAlertDesc: "You have not bound an Email. Please click {editLink} to add an Email.",
+ uploadAvatarButtonUploading: "Uploading...",
+ uploadAvatarButton: "Upload Avatar",
+ accountLabel: "Account",
+ emailLabel: "Email",
+ phoneLabel: "Phone",
+ birthLabel: "Birth",
+ notSet: "(Not set)",
+ lastLoginTimeLabel: "Last Login Time: ",
+ lastLoginIpLabel: "Last Login IP: ",
+ statusLabel: "Status",
+ editButton: "Edit",
+ changePasswordButton: "Change Password",
+ deleteAccountButton: "Delete Account",
+ successMsg: "Profile updated successfully",
+ fetchUserInfoFailure: "Failed to fetch user information",
+ avatarUploadFailure: "Avatar upload failed",
+ avatarUploadSuccess: "Avatar updated",
+ verified: "Verified",
+ notVerified: "Not verified",
+ resendVerification: "Resend Verification",
+ changePasswordSuccess: "Password changed successfully!",
+ passwordMismatch: "Passwords do not match",
+ changePasswordFailureTitle: "Change Password Failed",
+ verificationModalTitle: "Resend Verification Email",
+ verificationModalOk: "Confirm",
+ verificationModalCancel: "Cancel",
+ verificationModalExampleEmail:
+ "Default email (example.com) cannot be used for verification. Please change to a valid Email.",
+ verificationModalDesc:
+ "The system will send a verification email to: {email}\nPlease confirm if this Email is correct.",
+ deleteAccountSuccess: "Account deleted, redirecting to homepage",
+ saveButton: "Save",
+ cancelButton: "Cancel",
+ changePasswordModalOk: "Confirm",
+ },
+ ja: {
+ myInfoTitle: "私の情報",
+ emailNotVerifiedAlertTitle: "メールが未認証です",
+ emailNotVerifiedAlertDesc:
+ "未確認のメールアドレスのアカウントは定期的に削除されます。引き続きアカウントを保持したい場合は、下のボタンをクリックして確認メールを送信し、受信箱をチェックして認証を完了してください。",
+ noEmailAlertTitle: "メール未設定",
+ noEmailAlertDesc: "メールが登録されていません。{editLink} をクリックしてメールを追加してください。",
+ uploadAvatarButtonUploading: "アップロード中...",
+ uploadAvatarButton: "アバターをアップロード",
+ accountLabel: "アカウント",
+ emailLabel: "メール",
+ phoneLabel: "電話",
+ birthLabel: "生年月日",
+ notSet: "(未設定)",
+ lastLoginTimeLabel: "最終ログイン時間:",
+ lastLoginIpLabel: "最終ログイン IP:",
+ statusLabel: "状態",
+ editButton: "編集",
+ changePasswordButton: "パスワード変更",
+ deleteAccountButton: "アカウント削除",
+ successMsg: "プロフィール更新成功",
+ fetchUserInfoFailure: "ユーザー情報の取得に失敗しました",
+ avatarUploadFailure: "アバターのアップロードに失敗しました",
+ avatarUploadSuccess: "アバターが更新されました",
+ verified: "認証済み",
+ notVerified: "未認証",
+ resendVerification: "認証メール再送信",
+ changePasswordSuccess: "パスワード変更成功!",
+ passwordMismatch: "入力したパスワードが一致しません",
+ changePasswordFailureTitle: "パスワード変更失敗",
+ verificationModalTitle: "認証メール再送信",
+ verificationModalOk: "確定",
+ verificationModalCancel: "キャンセル",
+ verificationModalExampleEmail:
+ "デフォルトのメール (example.com) は認証に使用できません。有効なメールに変更してください。",
+ verificationModalDesc:
+ "システムは以下のメールに認証メールを送信します:{email}\nこのメールが正しいか確認してください。",
+ deleteAccountSuccess: "アカウントが削除されました。ホームページにリダイレクトします。",
+ saveButton: "保存",
+ cancelButton: "キャンセル",
+ changePasswordModalOk: "確定",
+ },
+};
+
+export const changePasswordLocale = {
+ "zh-hant": {
+ modalTitle: "變更密碼",
+ oldPasswordLabel: "舊密碼",
+ oldPasswordRequired: "請輸入舊密碼",
+ newPasswordLabel: "新密碼",
+ newPasswordRequired: "請輸入新密碼",
+ newPasswordTooShort: "至少 8 碼",
+ confirmNewPasswordLabel: "確認新密碼",
+ confirmNewPasswordRequired: "請再次輸入新密碼",
+ passwordMismatch: "兩次輸入的密碼不一致",
+ okText: "儲存",
+ cancelText: "取消",
+ },
+ en: {
+ modalTitle: "Change Password",
+ oldPasswordLabel: "Old Password",
+ oldPasswordRequired: "Please enter your old password",
+ newPasswordLabel: "New Password",
+ newPasswordRequired: "Please enter your new password",
+ newPasswordTooShort: "At least 8 characters",
+ confirmNewPasswordLabel: "Confirm New Password",
+ confirmNewPasswordRequired: "Please re-enter your new password",
+ passwordMismatch: "Passwords do not match",
+ okText: "Save",
+ cancelText: "Cancel",
+ },
+ ja: {
+ modalTitle: "パスワード変更",
+ oldPasswordLabel: "旧パスワード",
+ oldPasswordRequired: "旧パスワードを入力してください",
+ newPasswordLabel: "新パスワード",
+ newPasswordRequired: "新パスワードを入力してください",
+ newPasswordTooShort: "8文字以上である必要があります",
+ confirmNewPasswordLabel: "新パスワード確認",
+ confirmNewPasswordRequired: "新パスワードを再入力してください",
+ passwordMismatch: "入力したパスワードが一致しません",
+ okText: "保存",
+ cancelText: "キャンセル",
+ },
+};
+
+export const deleteAccountLocale = {
+ "zh-hant": {
+ modalTitle: "刪除帳號",
+ modalContent: "您確定要刪除帳號嗎?此操作無法復原!",
+ okText: "確定刪除",
+ cancelText: "取消",
+ },
+ en: {
+ modalTitle: "Delete Account",
+ modalContent:
+ "Are you sure you want to delete your account? This action cannot be undone!",
+ okText: "Confirm Delete",
+ cancelText: "Cancel",
+ },
+ ja: {
+ modalTitle: "アカウント削除",
+ modalContent: "本当にアカウントを削除しますか?この操作は元に戻せません!",
+ okText: "削除を確定",
+ cancelText: "キャンセル",
+ },
+};
diff --git a/src/components/PasswordInput.js b/src/components/PasswordInput.js
new file mode 100644
index 00000000000..c0eefb4448d
--- /dev/null
+++ b/src/components/PasswordInput.js
@@ -0,0 +1,57 @@
+// /src/components/PasswordInput.js
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Input, Progress, Typography } from "antd";
+import React, { useState } from "react";
+import zxcvbn from "zxcvbn";
+
+const { Text } = Typography;
+
+export default function PasswordInput({ onChange, hideStrength = false,...rest }) {
+ const { i18n: { currentLocale } } = useDocusaurusContext();
+
+ const localeText = {
+ "zh-hant": {
+ passwordStrengthTitle: "密碼強度:",
+ strengthTexts: ["非常弱", "弱", "中等", "強", "非常強"],
+ },
+ en: {
+ passwordStrengthTitle: "Password Strength: ",
+ strengthTexts: ["Very Weak", "Weak", "Medium", "Strong", "Very Strong"],
+ },
+ ja: {
+ passwordStrengthTitle: "パスワードの強度:",
+ strengthTexts: ["非常に弱い", "弱い", "普通", "強い", "非常に強い"],
+ },
+ };
+
+ const text = localeText[currentLocale] || localeText.en;
+
+ const [score, setScore] = useState(0);
+ const progressPercent = score * 25;
+ const strokeColor = [
+ "#ff4d4f", // 非常弱 / Very Weak
+ "#ff7a45", // 弱 / Weak
+ "#faad14", // 中等 / Medium
+ "#52c41a", // 強 / Strong
+ "#1677ff", // 非常強 / Very Strong
+ ][score] || "#ff4d4f";
+
+ const handleChange = (e) => {
+ const value = e.target.value;
+ const result = zxcvbn(value);
+ setScore(result.score);
+ if (onChange) onChange(e);
+ };
+
+ return (
+
+
+ {!hideStrength && (
+
+
{`${text.passwordStrengthTitle}${text.strengthTexts[score]}`}
+
+
+ )}
+
+ );
+}
diff --git a/src/components/forms/ForgotPasswordForm.js b/src/components/forms/ForgotPasswordForm.js
new file mode 100644
index 00000000000..32ab2b41408
--- /dev/null
+++ b/src/components/forms/ForgotPasswordForm.js
@@ -0,0 +1,107 @@
+// /components/forms/ForgotPasswordForm.js
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Alert, Button, Form, Input } from "antd";
+import React, { useState } from "react";
+
+const localeText = {
+ "zh-hant": {
+ emailLabel: "Email",
+ emailRequired: "請輸入經過驗證的 Email",
+ submitBtn: "發送重設密碼信",
+ successMsg: "重設密碼信已寄出,請檢查您的信箱!",
+ errorMsg: "寄送失敗,請稍後再試",
+ },
+ en: {
+ emailLabel: "Email",
+ emailRequired: "Please enter your verified email",
+ submitBtn: "Send Reset Password Email",
+ successMsg: "Reset password email sent, please check your inbox!",
+ errorMsg: "Failed to send, please try again later",
+ },
+ ja: {
+ emailLabel: "メールアドレス",
+ emailRequired: "確認済みのメールアドレスを入力してください",
+ submitBtn: "パスワードリセットメールを送信する",
+ successMsg: "パスワードリセットメールを送信しました。受信トレイを確認してください!",
+ errorMsg: "送信に失敗しました。後でもう一度お試しください",
+ },
+};
+
+export default function ForgotPasswordForm({ onSuccess }) {
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const text = localeText[currentLocale] || localeText.en;
+ const [form] = Form.useForm();
+ const [submitError, setSubmitError] = useState("");
+ const [successMessage, setSuccessMessage] = useState("");
+ const [loading, setLoading] = useState(false);
+ const languageHeader = currentLocale;
+
+ const onFinish = async (values) => {
+ setSubmitError("");
+ setSuccessMessage("");
+ setLoading(true);
+ try {
+ const res = await fetch("https://api.docsaid.org/auth/forgot-password", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ "Accept-Language": languageHeader,
+ },
+ body: JSON.stringify({ email: values.email }),
+ });
+ if (!res.ok) {
+ const data = await res.json();
+ const errorMsg =
+ (data.detail &&
+ typeof data.detail === "object" &&
+ data.detail.error) ||
+ data.detail ||
+ text.errorMsg;
+ throw new Error(errorMsg);
+ }
+ await res.json();
+ setSuccessMessage(text.successMsg);
+ form.resetFields();
+ if (onSuccess) {
+ onSuccess();
+ }
+ } catch (error) {
+ setSubmitError(error.message || text.errorMsg);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+
+
+
+
+ {text.submitBtn}
+
+
+
+ );
+}
diff --git a/src/components/forms/LoginForm.js b/src/components/forms/LoginForm.js
new file mode 100644
index 00000000000..949c48a37ca
--- /dev/null
+++ b/src/components/forms/LoginForm.js
@@ -0,0 +1,221 @@
+// /components/forms/LoginForm.js
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Alert, Button, Form, Input, Typography } from "antd";
+import React, { useEffect, useState } from "react";
+
+const localeText = {
+ "zh-hant": {
+ usernameLabel: "帳號",
+ usernameError: "請輸入帳號",
+ passwordLabel: "密碼",
+ passwordRequired: "請輸入密碼",
+ loginBtn: "登入",
+ forgotPassword: "忘記密碼?",
+ loginSuccessMsg: "登入成功!",
+ loginRequestTooFrequent: "登入請求過於頻繁,請稍後再試",
+ maxAttemptsReached: "已達最大嘗試次數,請稍後再試",
+ wrongCredentials: "密碼錯誤,剩餘嘗試次數:",
+ userNotFound: "使用者不存在",
+ countdownMessage: "請等待 {lockCountdown} 秒後再試",
+ },
+ en: {
+ usernameLabel: "Username",
+ usernameError: "Please enter your username",
+ passwordLabel: "Password",
+ passwordRequired: "Please enter your password",
+ loginBtn: "Login",
+ forgotPassword: "Forgot password?",
+ loginSuccessMsg: "Login successful!",
+ loginRequestTooFrequent: "Too many login attempts, please try again later.",
+ maxAttemptsReached: "Maximum attempts reached, please try again later.",
+ wrongCredentials: "Incorrect password, remaining attempts: ",
+ userNotFound: "User does not exist",
+ countdownMessage: "Please wait {lockCountdown} seconds before trying again.",
+ },
+ ja: {
+ usernameLabel: "ユーザー名",
+ usernameError: "ユーザー名を入力してください",
+ passwordLabel: "パスワード",
+ passwordRequired: "パスワードを入力してください",
+ loginBtn: "ログイン",
+ forgotPassword: "パスワードをお忘れですか?",
+ loginSuccessMsg: "ログイン成功!",
+ loginRequestTooFrequent:
+ "ログインリクエストが頻繁すぎます。後でもう一度お試しください。",
+ maxAttemptsReached: "最大試行回数に達しました。後でもう一度お試しください。",
+ wrongCredentials: "ユーザー名またはパスワードが正しくありません。残り試行回数:",
+ userNotFound: "ユーザーが存在しません",
+ countdownMessage: "{lockCountdown} 秒後に再試行してください。",
+ },
+};
+
+export default function LoginForm({
+ onLogin, // 從 useAuthHandler 傳進來, { success, errorMessage, status, userNotFound, remainingAttempts? }
+ onSuccess,
+ loading,
+ onToggleForgotPassword,
+}) {
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const text = localeText[currentLocale] || localeText.en;
+
+ const [form] = Form.useForm();
+ const [submitError, setSubmitError] = useState("");
+ const [successMessage, setSuccessMessage] = useState("");
+
+ // 錯誤嘗試計數 & 鎖定
+ const [failedAttempts, setFailedAttempts] = useState(0);
+ const [isLocked, setIsLocked] = useState(false);
+
+ const MAX_ATTEMPTS = 5; // 自訂最大嘗試次數
+ const LOCK_DURATION = 900; // 鎖定秒數
+ const [lockCountdown, setLockCountdown] = useState(0);
+
+ useEffect(() => {
+ let timer;
+ if (isLocked) {
+ setLockCountdown(LOCK_DURATION);
+ timer = setInterval(() => {
+ setLockCountdown((prev) => {
+ if (prev <= 1) {
+ clearInterval(timer);
+ setIsLocked(false);
+ setFailedAttempts(0);
+ return 0;
+ }
+ return prev - 1;
+ });
+ }, 1000);
+ }
+ return () => {
+ if (timer) clearInterval(timer);
+ };
+ }, [isLocked]);
+
+ const onFinish = async (values) => {
+ if (isLocked) return; // 已鎖定,不允許登入
+
+ setSubmitError("");
+ setSuccessMessage("");
+
+ const result = await onLogin(values.username, values.password);
+ if (result.success) {
+ setSuccessMessage(text.loginSuccessMsg);
+ setFailedAttempts(0);
+ onSuccess?.();
+ } else {
+ // 先檢查是否為 429 => 後端封鎖
+ if (result.status === 429) {
+ setIsLocked(true);
+ setSubmitError(text.loginRequestTooFrequent);
+ return;
+ }
+
+ // 檢查是否使用者不存在
+ if (result.userNotFound) {
+ // 不進行失敗次數紀錄,直接顯示「使用者不存在」
+ setSubmitError(text.userNotFound);
+ return;
+ }
+
+ // 其餘錯誤 (包含密碼錯誤)
+ // 如果後端帶有 remainingAttempts,則跟著更新
+ if (typeof result.remainingAttempts === "number") {
+ const rem = result.remainingAttempts;
+ if (rem <= 0) {
+ // 若後端表示剩餘次數0 => 也視為封鎖
+ setIsLocked(true);
+ setSubmitError(text.maxAttemptsReached);
+ } else {
+ setSubmitError(`${text.wrongCredentials}${rem}`);
+ }
+ } else {
+ // 若後端沒有帶 remainingAttempts,則用本地邏輯做簡單累計
+ const newCount = failedAttempts + 1;
+ setFailedAttempts(newCount);
+
+ if (newCount >= MAX_ATTEMPTS) {
+ setIsLocked(true);
+ setSubmitError(text.maxAttemptsReached);
+ } else {
+ setSubmitError(`${text.wrongCredentials}${MAX_ATTEMPTS - newCount}`);
+ }
+ }
+ }
+ };
+
+ return (
+
+
+
+
+
+
+
+
+ {successMessage && (
+
+ )}
+ {submitError && (
+
+ )}
+ {isLocked && (
+
+ )}
+
+
+
+ {text.loginBtn}
+
+
+
+ {onToggleForgotPassword && (
+
+ {text.forgotPassword}
+
+ )}
+
+ );
+}
diff --git a/src/components/forms/RegisterForm.js b/src/components/forms/RegisterForm.js
new file mode 100644
index 00000000000..ba536d717c8
--- /dev/null
+++ b/src/components/forms/RegisterForm.js
@@ -0,0 +1,194 @@
+// /components/forms/RegisterForm.js
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Alert, Button, Form, Input } from "antd";
+import React, { useState } from "react";
+import { useAuth } from "../../context/AuthContext";
+import PasswordInput from "../PasswordInput";
+
+const localeText = {
+ "zh-hant": {
+ usernameLabel: "帳號",
+ usernameRequired: "請輸入帳號",
+ passwordLabel: "密碼",
+ passwordRequired: "請輸入密碼",
+ confirmPasswordLabel: "確認密碼",
+ confirmPasswordRequired: "請再次輸入密碼",
+ passwordMismatch: "兩次輸入的密碼不一致",
+ registerBtn: "註冊",
+ passphraseHint: "建議使用可記憶的長密碼(如短語)提升安全性。",
+ successMsg: "註冊成功!",
+ pwnedWarning: "此密碼曾出現在外洩紀錄中,請使用更安全的密碼。",
+ passwordTooShort: "密碼長度需至少 8 碼",
+ },
+ en: {
+ usernameLabel: "Username",
+ usernameRequired: "Please enter your username",
+ passwordLabel: "Password",
+ passwordRequired: "Please enter your password",
+ confirmPasswordLabel: "Confirm Password",
+ confirmPasswordRequired: "Please confirm your password",
+ passwordMismatch: "The two passwords that you entered do not match",
+ registerBtn: "Register",
+ passphraseHint: "Consider using a memorable passphrase for better security.",
+ successMsg: "Registration successful!",
+ pwnedWarning: "This password has appeared in data breaches. Please use a more secure one.",
+ passwordTooShort: "Password must be at least 8 characters",
+ },
+ ja: {
+ usernameLabel: "ユーザー名",
+ usernameRequired: "ユーザー名を入力してください",
+ passwordLabel: "パスワード",
+ passwordRequired: "パスワードを入力してください",
+ confirmPasswordLabel: "パスワードを再入力",
+ confirmPasswordRequired: "パスワードをもう一度入力してください",
+ passwordMismatch: "入力された2つのパスワードが一致しません",
+ registerBtn: "登録",
+ passphraseHint: "覚えやすいパスフレーズを使用してセキュリティを向上させましょう。",
+ successMsg: "登録が完了しました!",
+ pwnedWarning: "このパスワードは漏洩した履歴があります。より安全なものを使用してください。",
+ passwordTooShort: "パスワードは8文字以上である必要があります",
+ },
+};
+
+export default function RegisterForm({ onLogin, onSuccess, onRegister, loading }) {
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const text = localeText[currentLocale] || localeText.en;
+ const { loginSuccess } = useAuth();
+ const [form] = Form.useForm();
+
+ // 狀態
+ const [submitError, setSubmitError] = useState("");
+ const [successMessage, setSuccessMessage] = useState("");
+
+ const onFinish = async (values) => {
+ setSubmitError("");
+ setSuccessMessage("");
+
+ // 這裡的 values 會包含 username, password, confirmPassword
+ const result = await onRegister({
+ username: values.username,
+ password: values.password,
+ });
+
+ if (!result) {
+ setSubmitError("Unknown error");
+ return;
+ }
+
+ if (result.success) {
+ finishRegisterSuccess(result);
+ const ok = await onLogin(values.username, values.password);
+ if (ok) {
+ onSuccess?.();
+ }
+
+ let dashboardPath = "/dashboard";
+ if (currentLocale === "en") {
+ dashboardPath = "/en/dashboard";
+ } else if (currentLocale === "ja") {
+ dashboardPath = "/ja/dashboard";
+ }
+ window.location.href = dashboardPath;
+ } else {
+ if (result.pwned) {
+ setSubmitError(text.pwnedWarning);
+ } else {
+ setSubmitError(result.error || "Registration failed");
+ }
+ }
+ };
+
+ const finishRegisterSuccess = (result) => {
+ setSuccessMessage(text.successMsg);
+ form.resetFields();
+ if (result.token) {
+ loginSuccess(result.token);
+ }
+ };
+
+ // 密碼欄位的基本規則
+ const passwordRules = [
+ {
+ required: true,
+ message: text.passwordRequired,
+ },
+ {
+ validator: async (_, value) => {
+ if (!value) {
+ return Promise.reject(new Error(text.passwordRequired));
+ }
+ if (value.length < 8) {
+ return Promise.reject(new Error(text.passwordTooShort));
+ }
+ return Promise.resolve();
+ },
+ },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
+ {/* 新增:確認密碼欄位 */}
+ ({
+ validator(_, value) {
+ if (!value || getFieldValue("password") === value) {
+ return Promise.resolve();
+ }
+ return Promise.reject(new Error(text.passwordMismatch));
+ },
+ }),
+ ]}
+ >
+
+
+
+
+
+ {successMessage && (
+
+ )}
+ {submitError && (
+
+ )}
+
+
+
+ {text.registerBtn}
+
+
+
+ );
+}
diff --git a/src/components/forms/ResetPasswordForm.js b/src/components/forms/ResetPasswordForm.js
new file mode 100644
index 00000000000..9394208ab22
--- /dev/null
+++ b/src/components/forms/ResetPasswordForm.js
@@ -0,0 +1,237 @@
+// /src/components/forms/ResetPasswordForm.js
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { Alert, Button, Form, Modal, Typography } from "antd";
+import React, { useEffect, useState } from "react";
+import PasswordInput from "../PasswordInput";
+
+const { Text } = Typography;
+
+const localeText = {
+ "zh-hant": {
+ newPasswordLabel: "新密碼",
+ newPasswordRequired: "請輸入新密碼",
+ confirmPasswordLabel: "確認新密碼",
+ confirmPasswordRequired: "請再次輸入新密碼",
+ passwordMismatch: "兩次輸入的密碼不一致",
+ passwordTooShort: "密碼長度需至少 8 碼",
+ resetBtn: "重設密碼",
+ successMsg: "密碼重設成功!",
+ errorMsg: "密碼重設失敗,請稍後再試",
+ missingToken: "無效或缺少重設密碼 token",
+ errorModalTitle: "密碼重設失敗",
+ errorModalOk: "確定",
+ passwordStrengthLabel: "密碼強度:",
+ strengthTexts: ["非常弱", "弱", "中等", "強", "非常強"],
+ },
+ en: {
+ newPasswordLabel: "New Password",
+ newPasswordRequired: "Please enter your new password",
+ confirmPasswordLabel: "Confirm New Password",
+ confirmPasswordRequired: "Please confirm your new password",
+ passwordMismatch: "The two passwords do not match",
+ passwordTooShort: "Password must be at least 8 characters",
+ resetBtn: "Reset Password",
+ successMsg: "Password reset successfully!",
+ errorMsg: "Failed to reset password, please try again later",
+ missingToken: "Missing or invalid reset token",
+ errorModalTitle: "Reset Password Failed",
+ errorModalOk: "OK",
+ passwordStrengthLabel: "Password Strength: ",
+ strengthTexts: ["Very Weak", "Weak", "Medium", "Strong", "Very Strong"],
+ },
+ ja: {
+ newPasswordLabel: "新しいパスワード",
+ newPasswordRequired: "新しいパスワードを入力してください",
+ confirmPasswordLabel: "新しいパスワードの確認",
+ confirmPasswordRequired: "もう一度新しいパスワードを入力してください",
+ passwordMismatch: "入力されたパスワードが一致しません",
+ passwordTooShort: "パスワードは8文字以上である必要があります",
+ resetBtn: "パスワードをリセット",
+ successMsg: "パスワードのリセットに成功しました!",
+ errorMsg: "パスワードのリセットに失敗しました。後でもう一度お試しください",
+ missingToken: "リセットトークンが無効か不足しています",
+ errorModalTitle: "パスワードリセット失敗",
+ errorModalOk: "確定",
+ passwordStrengthLabel: "Password Strength: ",
+ strengthTexts: ["Very Weak", "Weak", "Medium", "Strong", "Very Strong"],
+ },
+};
+
+export default function ResetPasswordForm({ onSuccess }) {
+ const { i18n: { currentLocale } } = useDocusaurusContext();
+ const text = localeText[currentLocale] || localeText.en;
+ const [form] = Form.useForm();
+ const [loading, setLoading] = useState(false);
+ const [successMessage, setSuccessMessage] = useState("");
+ // 錯誤訊息以 Modal 呈現
+ const [errorModalVisible, setErrorModalVisible] = useState(false);
+ const [errorMessage, setErrorMessage] = useState("");
+ // 從 URL 提取 token
+ const [token, setToken] = useState(null);
+ // 密碼強度分數,僅用於新密碼欄位
+ const [passwordScore, setPasswordScore] = useState(0);
+
+ useEffect(() => {
+ const params = new URLSearchParams(window.location.search);
+ const tokenFromUrl = params.get("token");
+ setToken(tokenFromUrl);
+ }, []);
+
+ // 新密碼欄位 onChange 以計算密碼強度
+ const handlePasswordChange = (e) => {
+ const value = e.target.value;
+ if (!value) {
+ setPasswordScore(0);
+ } else if (value.length < 6) {
+ setPasswordScore(1);
+ } else if (value.length < 10) {
+ setPasswordScore(2);
+ } else if (value.length < 14) {
+ setPasswordScore(3);
+ } else {
+ setPasswordScore(4);
+ }
+ };
+
+ // 客戶端密碼驗證規則
+ const passwordRules = [
+ {
+ required: true,
+ message: text.newPasswordRequired,
+ },
+ {
+ validator: async (_, value) => {
+ if (value && value.length < 8) {
+ return Promise.reject(new Error(text.passwordTooShort));
+ }
+ return Promise.resolve();
+ },
+ },
+ ];
+
+ const onFinish = async (values) => {
+ setSuccessMessage("");
+ setErrorMessage("");
+ if (!token) {
+ setErrorMessage(text.missingToken);
+ setErrorModalVisible(true);
+ return;
+ }
+ setLoading(true);
+ try {
+ const res = await fetch("https://api.docsaid.org/auth/reset-password", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ "Accept-Language": currentLocale,
+ },
+ body: JSON.stringify({
+ token: token,
+ new_password: values.newPassword,
+ }),
+ });
+ if (!res.ok) {
+ const data = await res.json();
+ console.log("Error response:", data);
+ const errMsg =
+ data.error ||
+ (data.detail && typeof data.detail === "object" ? data.detail.error : data.detail) ||
+ text.errorMsg;
+ throw new Error(errMsg);
+ }
+ await res.json();
+ setSuccessMessage(text.successMsg);
+ form.resetFields();
+ if (onSuccess) {
+ onSuccess();
+ }
+
+ // 根據語系決定首頁路徑
+ let homePath = '/';
+ if (currentLocale === 'en') {
+ homePath = '/en';
+ } else if (currentLocale === 'ja') {
+ homePath = '/ja';
+ }
+
+ setTimeout(() => {
+ window.location.href = homePath;
+ }, 1500);
+ } catch (error) {
+ console.error("Reset password error:", error);
+ setErrorMessage(error.message || text.errorMsg);
+ setErrorModalVisible(true);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+ <>
+
+
+
+ {passwordScore > 0 && (
+
+ {text.passwordStrengthLabel}{text.strengthTexts[passwordScore]}
+
+ )}
+ ({
+ validator(_, value) {
+ if (!value || getFieldValue("newPassword") === value) {
+ return Promise.resolve();
+ }
+ return Promise.reject(new Error(text.passwordMismatch));
+ },
+ }),
+ ]}
+ >
+
+
+
+
+ {text.resetBtn}
+
+
+
+
+ {/* 錯誤訊息 Modal */}
+ setErrorModalVisible(false)}
+ footer={[
+ setErrorModalVisible(false)}>
+ {text.errorModalOk}
+ ,
+ ]}
+ >
+ {errorMessage}
+
+ >
+ );
+}
diff --git a/src/context/AuthContext.js b/src/context/AuthContext.js
new file mode 100644
index 00000000000..8214405f929
--- /dev/null
+++ b/src/context/AuthContext.js
@@ -0,0 +1,213 @@
+// /src/context/AuthContext.js
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import React, { createContext, useContext, useEffect, useMemo, useState } from "react";
+
+const AuthContext = createContext({
+ token: null,
+ user: null,
+ loading: true,
+ loginSuccess: () => {},
+ logout: () => {},
+ setUser: () => {},
+ updateProfile: () => {},
+ verifyEmail: () => {},
+ sendVerificationEmail: () => {},
+ changePassword: () => {},
+ deleteAccount: () => {},
+});
+
+// 後端 API 網址
+const API_BASE = "https://api.docsaid.org";
+
+
+export function AuthProvider({ children }) {
+ const [token, setToken] = useState(null);
+ const [user, setUser] = useState(null);
+ const [loading, setLoading] = useState(true);
+
+ // 取得 Docusaurus 的 currentLocale
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+
+ // 根據 currentLocale,取得後端所需語言代碼
+ const serverLang = currentLocale;
+
+ /**
+ * 通用 API 請求工具
+ * @param {string} endpoint API 路徑 (例如 /auth/me)
+ * @param {string} method HTTP 方法
+ * @param {string|null} token 若有 token 則自動加入 Authorization header
+ * @param {object|FormData|null} body 若為物件則轉成 JSON;若為 FormData 則直接傳送
+ */
+ async function apiRequest(endpoint, method = "GET", tokenArg = null, body = null) {
+ const headers = {};
+ if (tokenArg) {
+ headers.Authorization = `Bearer ${tokenArg}`;
+ }
+ headers["Accept-Language"] = serverLang;
+
+ const isFormData = body instanceof FormData;
+ if (body && !isFormData) {
+ headers["Content-Type"] = "application/json";
+ body = JSON.stringify(body);
+ }
+
+ let res;
+ try {
+ res = await fetch(`${API_BASE}${endpoint}`, {
+ method,
+ headers,
+ body: body || undefined,
+ // 可根據需求明確設定 redirect 選項,預設為 follow
+ redirect: "follow",
+ });
+ } catch (networkError) {
+ console.error(`Network error during ${method} ${endpoint}:`, networkError);
+ throw new Error("網路錯誤,請稍後再試");
+ }
+
+ const contentType = res.headers.get("Content-Type");
+ let data = {};
+ if (contentType && contentType.includes("application/json")) {
+ data = await res.json();
+ } else {
+ data = await res.text();
+ }
+
+ if (!res.ok) {
+ const errorMsg = data?.error || data?.detail || data || "請求失敗";
+ if (process.env.NODE_ENV !== "production") {
+ console.error(`API Request Failed [${method} ${endpoint}]:`, data);
+ }
+ const err = new Error(errorMsg);
+ if (data?.remaining_attempts !== undefined) {
+ err.remaining_attempts = data.remaining_attempts;
+ }
+ throw err;
+ }
+ return data;
+ }
+
+ // App 啟動時從 localStorage 取得 token 並拉取用戶資料
+ useEffect(() => {
+ const initAuth = async () => {
+ const savedToken = localStorage.getItem("token");
+ if (!savedToken) {
+ setLoading(false);
+ return;
+ }
+ setToken(savedToken);
+ try {
+ const data = await apiRequest("/auth/me", "GET", savedToken);
+ setUser(data);
+ } catch (error) {
+ // Token 失效,清空 token
+ setToken(null);
+ localStorage.removeItem("token");
+ } finally {
+ setLoading(false);
+ }
+ };
+ initAuth();
+ }, []);
+
+ // 登入成功後,儲存 token 並刷新使用者資料
+ const loginSuccess = async (loginToken) => {
+ try {
+ const userData = await apiRequest("/auth/me", "GET", loginToken);
+ setToken(loginToken);
+ setUser(userData);
+ localStorage.setItem("token", loginToken);
+ } catch (error) {
+ if (process.env.NODE_ENV !== "production") {
+ console.error("登入失敗", error);
+ }
+ }
+ };
+
+ // 根據語系決定首頁路徑
+ let homePath = "/";
+ if (currentLocale === "en") {
+ homePath = "/en";
+ } else if (currentLocale === "ja") {
+ homePath = "/ja";
+ }
+
+ // 登出:清除 token 與 user,並重導至首頁
+ const logout = () => {
+ setToken(null);
+ setUser(null);
+ localStorage.removeItem("token");
+ window.location.href = homePath;
+ };
+
+ // 更新個人資料
+ const updateProfile = async (payload) => {
+ if (!token) throw new Error("尚未登入");
+ const newUser = await apiRequest("/auth/profile", "PUT", token, payload);
+ setUser(newUser);
+ return newUser;
+ };
+
+ // 寄送驗證信
+ const sendVerificationEmail = async (email) => {
+ if (!token) throw new Error("尚未登入");
+ return apiRequest("/auth/send-verification-email", "POST", token, { email });
+ };
+
+ // 驗證 Email
+ const verifyEmail = async (verifyToken) => {
+ const data = await apiRequest(`/auth/verify-email?token=${verifyToken}`, "GET", null, null);
+ // 驗證成功後更新用戶資料
+ if (token) {
+ const updatedUser = await apiRequest("/auth/me", "GET", token);
+ setUser(updatedUser);
+ }
+ return data;
+ };
+
+ // 變更密碼
+ const changePassword = async (oldPassword, newPassword) => {
+ if (!token) throw new Error("尚未登入");
+ return apiRequest("/auth/change-password", "POST", token, {
+ old_password: oldPassword,
+ new_password: newPassword,
+ });
+ };
+
+ // 刪除帳號
+ const deleteAccount = async () => {
+ if (!token) throw new Error("尚未登入");
+ await apiRequest("/auth/delete", "DELETE", token);
+ logout();
+ return { message: "帳號已刪除" };
+ };
+
+ const value = useMemo(
+ () => ({
+ token,
+ user,
+ loading,
+ loginSuccess,
+ logout,
+ setUser,
+ updateProfile,
+ verifyEmail,
+ sendVerificationEmail,
+ changePassword,
+ deleteAccount,
+ }),
+ [token, user, loading]
+ );
+
+ return {children} ;
+}
+
+export function useAuth() {
+ const context = useContext(AuthContext);
+ if (!context) {
+ throw new Error("useAuth 必須在 AuthProvider 內使用");
+ }
+ return context;
+}
diff --git a/src/hooks/useAuthHandler.js b/src/hooks/useAuthHandler.js
new file mode 100644
index 00000000000..991a15a6c3f
--- /dev/null
+++ b/src/hooks/useAuthHandler.js
@@ -0,0 +1,174 @@
+// /src/hooks/useAuthHandler.js
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { useState } from "react";
+import { useAuth } from "../context/AuthContext";
+
+export default function useAuthHandler() {
+ const { loginSuccess } = useAuth();
+ const [loading, setLoading] = useState(false);
+
+ // 從 Docusaurus 取得當前語系
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+
+ // 後端所需語系
+ const serverLang = currentLocale;
+
+ /**
+ * 登入
+ * @param {string} username
+ * @param {string} password
+ * @returns {Promise<{
+ * success: boolean;
+ * errorMessage?: string;
+ * status?: number;
+ * userNotFound?: boolean;
+ * remainingAttempts?: number;
+ * }>}
+ */
+ const login = async (username, password) => {
+ setLoading(true);
+ try {
+ const res = await fetch("https://api.docsaid.org/auth/login", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ "Accept-Language": serverLang,
+ },
+ body: JSON.stringify({ username, password }),
+ });
+
+ let data;
+ try {
+ data = await res.json();
+ } catch {
+ data = {};
+ }
+
+ if (!res.ok) {
+ const errorMsg = data?.error || "登入失敗";
+ console.error(`Error ${res.status}:`, data);
+ switch (res.status) {
+ case 404:
+ return {
+ success: false,
+ status: 404,
+ userNotFound: true,
+ errorMessage: errorMsg,
+ };
+ case 429:
+ return {
+ success: false,
+ status: 429,
+ errorMessage: errorMsg,
+ remainingAttempts: data.remaining_attempts ?? 0,
+ };
+ case 401:
+ return {
+ success: false,
+ status: 401,
+ errorMessage: errorMsg,
+ remainingAttempts: data.remaining_attempts,
+ };
+ default:
+ return {
+ success: false,
+ status: res.status,
+ errorMessage: errorMsg,
+ };
+ }
+ }
+
+ // 成功情況:回傳 access_token
+ if (data.access_token) {
+ await loginSuccess(data.access_token);
+ return { success: true, status: res.status };
+ }
+
+ return {
+ success: false,
+ status: res.status,
+ errorMessage: "登入失敗: token 不存在",
+ };
+ } catch (error) {
+ console.error("login error:", error);
+ return {
+ success: false,
+ status: 500,
+ errorMessage: error.message || "登入請求失敗",
+ };
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ /**
+ * 註冊
+ * @param {object} param0 包含 username 與 password
+ * @returns {Promise<{ success: boolean; error?: string; pwned?: boolean; }>}
+ */
+ const register = async ({ username, password }) => {
+ setLoading(true);
+ try {
+ const fakeEmail = `${username}@example.com`; // 後端 register 必填 email
+ const res = await fetch("https://api.docsaid.org/auth/register", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ "Accept-Language": serverLang,
+ },
+ body: JSON.stringify({
+ username,
+ password,
+ email: fakeEmail,
+ phone: null,
+ birth: null,
+ avatar: null,
+ }),
+ });
+
+ let data = {};
+ try {
+ data = await res.json();
+ } catch (parseError) {
+ console.error("parse error:", parseError);
+ }
+
+ if (!res.ok) {
+ let errorMsg = data?.error || "Registration failed";
+ if (Array.isArray(data.detail)) {
+ const msgs = data.detail.map((d) => d.msg).join("; ");
+ errorMsg = msgs || errorMsg;
+ }
+ return {
+ success: false,
+ error: errorMsg,
+ };
+ }
+
+ // 後端 register 回傳 RegisterResponse,不含 token
+ // 前端可以提示使用者註冊成功,請進行登入
+ return {
+ success: !data.pwned,
+ pwned: data.pwned || false,
+ // 可回傳註冊後的使用者資料,例如 data.id 等
+ userId: data.id,
+ };
+ } catch (error) {
+ console.error("register error:", error);
+ return {
+ success: false,
+ error: error.message || "Network error",
+ };
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return {
+ login,
+ register,
+ loading,
+ };
+}
diff --git a/src/pages/DashboardPage.module.css b/src/pages/DashboardPage.module.css
new file mode 100644
index 00000000000..3029a7c042d
--- /dev/null
+++ b/src/pages/DashboardPage.module.css
@@ -0,0 +1,67 @@
+/* DashboardPage.module.css */
+
+/* 整個 Dashboard 的主容器 */
+.dashboardLayout {
+ min-height: calc(100vh - 60px);
+ }
+
+ /* 側邊欄的自訂樣式 */
+ .customSider {
+ transition: all 0.3s ease;
+ border-right: 1px solid #ddd !important;
+ }
+
+ /* 側邊欄標題部分 */
+ .siderTitle {
+ padding: 16px;
+ font-weight: bold;
+ text-align: center;
+ border-bottom: 1px solid #eee;
+ transition: all 0.3s ease;
+ font-size: 1rem;
+ }
+
+ /* 右側主要區域的布局 */
+ .rightSideLayout {
+ background-color: #f0f2f5;
+ }
+
+ /* 頂部 Header */
+ .header {
+ border-bottom: 1px solid #ccc;
+ padding: 0 16px;
+ transition: background 0.3s ease;
+ }
+
+ /* 使用者下拉選單文字 */
+ .userMenuText {
+ cursor: pointer;
+ font-weight: 500;
+ }
+
+ /* 中間內容區 */
+ .contentArea {
+ padding: 16px;
+ background-color: #f5f5f5;
+ min-height: 280px;
+ }
+
+ /* 內容容器,帶有陰影與圓角 */
+ .contentBox {
+ padding: 24px;
+ background: #fff;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+ border-radius: 8px;
+ }
+
+ /* 載入中時的 Spinner */
+ .loadingSpin {
+ margin: 50px auto;
+ display: block;
+ }
+
+ /* 尚未登入時的提示容器 */
+ .notLoggedInContainer {
+ text-align: center;
+ margin: 50px;
+ }
diff --git a/src/pages/dashboard.js b/src/pages/dashboard.js
new file mode 100644
index 00000000000..ea9a0382330
--- /dev/null
+++ b/src/pages/dashboard.js
@@ -0,0 +1,280 @@
+// src/pages/dashboard.js
+import {
+ BookOutlined,
+ HomeOutlined,
+ KeyOutlined,
+ MenuFoldOutlined,
+ MenuUnfoldOutlined,
+ PoweroffOutlined,
+ UserOutlined,
+} from "@ant-design/icons";
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import Layout from "@theme/Layout";
+import {
+ Layout as AntLayout,
+ Breadcrumb,
+ Button,
+ Col,
+ Dropdown,
+ Menu,
+ Row,
+ Spin,
+ theme as antdTheme,
+ message,
+} from "antd";
+import React, { useEffect, useMemo, useState } from "react";
+import DashboardApiDocs from "../components/Dashboard/ApiDocs"; // 引入新的 API Docs 頁面
+import DashboardApiKey from "../components/Dashboard/ApiKey";
+import DashboardMyInfo from "../components/Dashboard/MyInfo";
+import { useAuth } from "../context/AuthContext";
+import styles from "./DashboardPage.module.css";
+
+const { Header: AntHeader, Sider, Content } = AntLayout;
+
+const localeText = {
+ "zh-hant": {
+ dashboardTitle: "我的後台",
+ loginWarning: "請先登入",
+ notLoggedIn: "尚未登入",
+ sider: {
+ collapsed: "後台",
+ expanded: "我的後台",
+ menu: {
+ myinfo: "我的資訊",
+ apikey: "我的 API Key",
+ apidocs: "API 使用說明",
+ },
+ },
+ breadcrumb: {
+ dashboard: "我的後台",
+ myinfo: "我的資訊",
+ apikey: "我的 API Key",
+ apidocs: "API 使用說明",
+ undefined: "未定義",
+ },
+ userMenu: {
+ backHome: "回主站",
+ logout: "登出",
+ },
+ },
+ en: {
+ dashboardTitle: "Dashboard",
+ loginWarning: "Please log in first",
+ notLoggedIn: "Not logged in",
+ sider: {
+ collapsed: "Dashboard",
+ expanded: "My Dashboard",
+ menu: {
+ myinfo: "My Information",
+ apikey: "My API Key",
+ apidocs: "API Documentation",
+ },
+ },
+ breadcrumb: {
+ dashboard: "Dashboard",
+ myinfo: "My Information",
+ apikey: "My API Key",
+ apidocs: "API Documentation",
+ undefined: "Undefined",
+ },
+ userMenu: {
+ backHome: "Back to Site",
+ logout: "Logout",
+ },
+ },
+ ja: {
+ dashboardTitle: "ダッシュボード",
+ loginWarning: "まずログインしてください",
+ notLoggedIn: "ログインしていません",
+ sider: {
+ collapsed: "ダッシュボード",
+ expanded: "マイダッシュボード",
+ menu: {
+ myinfo: "マイ情報",
+ apikey: "マイAPIキー",
+ apidocs: "API利用ガイド",
+ },
+ },
+ breadcrumb: {
+ dashboard: "ダッシュボード",
+ myinfo: "マイ情報",
+ apikey: "マイAPIキー",
+ apidocs: "API利用ガイド",
+ undefined: "未定義",
+ },
+ userMenu: {
+ backHome: "サイトへ戻る",
+ logout: "ログアウト",
+ },
+ },
+};
+
+
+export default function DashboardPage() {
+ const {
+ i18n: { currentLocale },
+ } = useDocusaurusContext();
+ const text = localeText[currentLocale] || localeText.en;
+ const { token, user, loading, logout } = useAuth();
+ const [selectedKey, setSelectedKey] = useState("myinfo");
+ const [collapsed, setCollapsed] = useState(false);
+ const { token: designToken } = antdTheme.useToken();
+
+ useEffect(() => {
+ if (!loading && !token) {
+ message.warning(text.loginWarning);
+ // 可根據需求導向登入頁面
+ }
+ }, [loading, token, text.loginWarning]);
+
+ // 依選單項目切換對應內容
+ const contentComponent = useMemo(() => {
+ switch (selectedKey) {
+ case "myinfo":
+ return ;
+ case "apikey":
+ return ;
+ case "apidocs":
+ return ;
+ default:
+ return null;
+ }
+ }, [selectedKey]);
+
+ // 面包屑標題
+ const pageTitle = useMemo(() => {
+ switch (selectedKey) {
+ case "myinfo":
+ return text.breadcrumb.myinfo;
+ case "apikey":
+ return text.breadcrumb.apikey;
+ case "apidocs":
+ return text.breadcrumb.apidocs;
+ default:
+ return text.breadcrumb.undefined;
+ }
+ }, [selectedKey, text.breadcrumb]);
+
+ // 根據語系決定首頁路徑
+ let homePath = "/";
+ if (currentLocale === "en") {
+ homePath = "/en";
+ } else if (currentLocale === "ja") {
+ homePath = "/ja";
+ }
+
+ const userMenuItems = [
+ {
+ key: "backHome",
+ icon: ,
+ label: text.userMenu.backHome,
+ onClick: () => {
+ window.location.href = homePath;
+ },
+ },
+ {
+ key: "logout",
+ icon: ,
+ label: text.userMenu.logout,
+ onClick: logout,
+ },
+ ];
+
+ const breadcrumbItems = [
+ { title: text.breadcrumb.dashboard },
+ { title: pageTitle },
+ ];
+
+ if (loading) {
+ return (
+
+
+
+ );
+ }
+
+ if (!token) {
+ return (
+
+
+
{text.notLoggedIn}
+
+
+ );
+ }
+
+ return (
+
+
+ setCollapsed(broken)}
+ className={styles.customSider}
+ >
+
+ {collapsed ? text.sider.collapsed : text.sider.expanded}
+
+ setSelectedKey(e.key)}
+ items={[
+ {
+ key: "myinfo",
+ icon: ,
+ label: text.sider.menu.myinfo,
+ },
+ {
+ key: "apikey",
+ icon: ,
+ label: text.sider.menu.apikey,
+ },
+ {
+ key: "apidocs",
+ icon: ,
+ label: text.sider.menu.apidocs,
+ },
+ ]}
+ />
+
+
+
+
+
+
+
+ : }
+ onClick={() => setCollapsed(!collapsed)}
+ />
+
+
+
+
+
+
+
+
+
+ Hi, {user?.username || "User"}!
+
+
+
+
+
+
+ {contentComponent}
+
+
+
+
+ );
+}
diff --git a/src/pages/email-verified-failed.js b/src/pages/email-verified-failed.js
new file mode 100644
index 00000000000..4352d7d518e
--- /dev/null
+++ b/src/pages/email-verified-failed.js
@@ -0,0 +1,85 @@
+// src/pages/email-verified-failed.js
+import { useHistory } from '@docusaurus/router';
+import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
+import Layout from '@theme/Layout';
+import { Button, Card, Typography } from 'antd';
+import React from 'react';
+
+const { Title, Paragraph } = Typography;
+
+const localeText = {
+ "zh-hant": {
+ title: "驗證失敗",
+ subtitle: "您的 Email 驗證未成功",
+ description: "可能原因包括驗證連結已過期或無效。請嘗試重新寄送驗證信,或聯繫客服以獲得協助。",
+ homeButton: "返回首頁",
+ resendButton: "重新寄送驗證信",
+ },
+ en: {
+ title: "Email Verification Failed",
+ subtitle: "Your email verification was not successful",
+ description: "This may be due to an expired or invalid verification link. Please try resending the verification email or contact support for assistance.",
+ homeButton: "Return to Homepage",
+ resendButton: "Resend Verification Email",
+ },
+ ja: {
+ title: "メール認証に失敗しました",
+ subtitle: "メール認証が正常に完了しませんでした",
+ description: "リンクの有効期限が切れているか、無効な可能性があります。認証メールの再送信を試すか、サポートにお問い合わせください。",
+ homeButton: "ホームへ戻る",
+ resendButton: "認証メールを再送信",
+ },
+};
+
+export default function EmailVerifiedFailed() {
+ const { i18n: { currentLocale } } = useDocusaurusContext();
+ const text = localeText[currentLocale] || localeText.en;
+ const history = useHistory();
+
+ // 根據語系設定首頁導向路徑
+ let homePath = '/';
+ if (currentLocale === 'en') {
+ homePath = '/en';
+ } else if (currentLocale === 'ja') {
+ homePath = '/ja';
+ }
+
+ const handleGoHome = () => {
+ history.push(homePath);
+ };
+
+ return (
+
+
+
+ {text.title}
+ {text.subtitle}
+
+ {text.description}
+
+
+
+ {text.homeButton}
+
+
+
+
+
+ );
+}
diff --git a/src/pages/email-verified-success.js b/src/pages/email-verified-success.js
new file mode 100644
index 00000000000..48464bc7c2e
--- /dev/null
+++ b/src/pages/email-verified-success.js
@@ -0,0 +1,83 @@
+// src/pages/email-verified-success.js
+import { useHistory } from '@docusaurus/router';
+import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
+import Layout from '@theme/Layout';
+import { Button, Card, Typography } from 'antd';
+import React from 'react';
+
+const { Title, Paragraph } = Typography;
+
+const localeText = {
+ "zh-hant": {
+ title: "驗證成功!",
+ subtitle: "您的 Email 已成功驗證",
+ description: "現在您可以安全登入並享受我們提供的各項服務。",
+ buttonText: "返回首頁",
+ },
+ en: {
+ title: "Email Verified Successfully",
+ subtitle: "Your email has been successfully verified",
+ description: "You can now safely log in and enjoy our services.",
+ buttonText: "Return to Homepage",
+ },
+ ja: {
+ title: "メール認証に成功しました!",
+ subtitle: "あなたのメールは正常に認証されました",
+ description: "今すぐ安全にログインして、私たちのサービスをお楽しみください。",
+ buttonText: "ホームへ戻る",
+ },
+};
+
+export default function EmailVerifiedSuccess() {
+ const { i18n: { currentLocale } } = useDocusaurusContext();
+ const text = localeText[currentLocale] || localeText.en;
+ const history = useHistory();
+
+ // 根據語系決定首頁路徑
+ let homePath = '/';
+ if (currentLocale === 'en') {
+ homePath = '/en';
+ } else if (currentLocale === 'ja') {
+ homePath = '/ja';
+ }
+
+ const handleGoHome = () => {
+ history.push(homePath);
+ };
+
+ return (
+
+
+
+ {text.title}
+
+ {text.subtitle}
+
+
+ {text.description}
+
+
+ {text.buttonText}
+
+
+
+
+ );
+}
diff --git a/src/pages/reset-password.js b/src/pages/reset-password.js
new file mode 100644
index 00000000000..403d5d1eb40
--- /dev/null
+++ b/src/pages/reset-password.js
@@ -0,0 +1,14 @@
+// src/pages/reset-password.js
+import Layout from '@theme/Layout';
+import React from "react";
+import ResetPasswordForm from "../components/forms/ResetPasswordForm";
+
+export default function ResetPasswordPage() {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/src/theme/Navbar/ColorModeToggle/index.js b/src/theme/Navbar/ColorModeToggle/index.js
new file mode 100644
index 00000000000..a506863c68a
--- /dev/null
+++ b/src/theme/Navbar/ColorModeToggle/index.js
@@ -0,0 +1,22 @@
+import React from 'react';
+import {useColorMode, useThemeConfig} from '@docusaurus/theme-common';
+import ColorModeToggle from '@theme/ColorModeToggle';
+import styles from './styles.module.css';
+export default function NavbarColorModeToggle({className}) {
+ const navbarStyle = useThemeConfig().navbar.style;
+ const disabled = useThemeConfig().colorMode.disableSwitch;
+ const {colorMode, setColorMode} = useColorMode();
+ if (disabled) {
+ return null;
+ }
+ return (
+
+ );
+}
diff --git a/src/theme/Navbar/ColorModeToggle/styles.module.css b/src/theme/Navbar/ColorModeToggle/styles.module.css
new file mode 100644
index 00000000000..7bd077a6bfd
--- /dev/null
+++ b/src/theme/Navbar/ColorModeToggle/styles.module.css
@@ -0,0 +1,3 @@
+.darkNavbarColorModeToggle:hover {
+ background: var(--ifm-color-gray-800);
+}
diff --git a/src/theme/Navbar/Content/index.js b/src/theme/Navbar/Content/index.js
new file mode 100644
index 00000000000..42b6a811f33
--- /dev/null
+++ b/src/theme/Navbar/Content/index.js
@@ -0,0 +1,122 @@
+import { UserOutlined } from '@ant-design/icons';
+import Link from "@docusaurus/Link";
+import { Avatar, Button, Dropdown, message } from 'antd';
+import React, { useState } from 'react';
+import { useAuth } from '../../../context/AuthContext';
+
+import { ErrorCauseBoundary, useThemeConfig } from '@docusaurus/theme-common';
+import {
+ splitNavbarItems,
+ useNavbarMobileSidebar,
+} from '@docusaurus/theme-common/internal';
+
+import NavbarColorModeToggle from '@theme/Navbar/ColorModeToggle';
+import NavbarLogo from '@theme/Navbar/Logo';
+import NavbarMobileSidebarToggle from '@theme/Navbar/MobileSidebar/Toggle';
+import NavbarSearch from '@theme/Navbar/Search';
+import NavbarItem from '@theme/NavbarItem';
+import SearchBar from '@theme/SearchBar';
+import styles from './styles.module.css';
+
+import AuthModal from '../../../components/AuthModal';
+
+function useNavbarItems() {
+ return useThemeConfig().navbar.items;
+}
+
+function NavbarItems({items}) {
+ return (
+ <>
+ {items.map((item, i) => (
+
+
+
+ ))}
+ >
+ );
+}
+
+function NavbarContentLayout({left, right}) {
+ return (
+
+ );
+}
+
+export default function NavbarContent() {
+ const mobileSidebar = useNavbarMobileSidebar();
+ const items = useNavbarItems();
+ const [leftItems, rightItems] = splitNavbarItems(items);
+ const searchBarItem = items.find((item) => item.type === 'search');
+
+ const { token, user, logout } = useAuth();
+ const [authVisible, setAuthVisible] = useState(false);
+
+ const userMenuItems = [
+ {
+ key: 'dashboard',
+ label: (
+
+ 儀表板
+
+ ),
+ },
+ {
+ key: 'logout',
+ label: (
+ {
+ logout();
+ message.success('已登出');
+ }}
+ >
+ 登出
+
+ ),
+ },
+ ];
+
+ return (
+ <>
+
+ {!mobileSidebar.disabled && }
+
+
+ >
+ }
+ right={
+ <>
+
+
+ {!searchBarItem && (
+
+
+
+ )}
+ {token ? (
+
+ : undefined}
+ style={{ cursor: 'pointer', backgroundColor: '#87d068' }}
+ />
+
+ ) : (
+ }
+ onClick={() => setAuthVisible(true)}
+ />
+ )}
+ >
+ }
+ />
+
+ setAuthVisible(false)} />
+ >
+ );
+}
diff --git a/src/theme/Navbar/Content/styles.module.css b/src/theme/Navbar/Content/styles.module.css
new file mode 100644
index 00000000000..bfbce789a52
--- /dev/null
+++ b/src/theme/Navbar/Content/styles.module.css
@@ -0,0 +1,15 @@
+/*
+Hide color mode toggle in small viewports
+ */
+@media (max-width: 996px) {
+ .colorModeToggle {
+ display: none;
+ }
+}
+
+.navbar__items--right {
+ display: flex;
+ flex-wrap: wrap; /* 允許換行 */
+ align-items: center;
+ justify-content: flex-end;
+}
\ No newline at end of file
diff --git a/src/theme/Navbar/Layout/index.js b/src/theme/Navbar/Layout/index.js
new file mode 100644
index 00000000000..492a92909f8
--- /dev/null
+++ b/src/theme/Navbar/Layout/index.js
@@ -0,0 +1,52 @@
+import React from 'react';
+import clsx from 'clsx';
+import {useThemeConfig} from '@docusaurus/theme-common';
+import {
+ useHideableNavbar,
+ useNavbarMobileSidebar,
+} from '@docusaurus/theme-common/internal';
+import {translate} from '@docusaurus/Translate';
+import NavbarMobileSidebar from '@theme/Navbar/MobileSidebar';
+import styles from './styles.module.css';
+function NavbarBackdrop(props) {
+ return (
+
+ );
+}
+export default function NavbarLayout({children}) {
+ const {
+ navbar: {hideOnScroll, style},
+ } = useThemeConfig();
+ const mobileSidebar = useNavbarMobileSidebar();
+ const {navbarRef, isNavbarVisible} = useHideableNavbar(hideOnScroll);
+ return (
+
+ {children}
+
+
+
+ );
+}
diff --git a/src/theme/Navbar/Layout/styles.module.css b/src/theme/Navbar/Layout/styles.module.css
new file mode 100644
index 00000000000..e72891a44ff
--- /dev/null
+++ b/src/theme/Navbar/Layout/styles.module.css
@@ -0,0 +1,7 @@
+.navbarHideable {
+ transition: transform var(--ifm-transition-fast) ease;
+}
+
+.navbarHidden {
+ transform: translate3d(0, calc(-100% - 2px), 0);
+}
diff --git a/src/theme/Navbar/Logo/index.js b/src/theme/Navbar/Logo/index.js
new file mode 100644
index 00000000000..f0fa51ffad3
--- /dev/null
+++ b/src/theme/Navbar/Logo/index.js
@@ -0,0 +1,11 @@
+import React from 'react';
+import Logo from '@theme/Logo';
+export default function NavbarLogo() {
+ return (
+
+ );
+}
diff --git a/src/theme/Navbar/MobileSidebar/Header/index.js b/src/theme/Navbar/MobileSidebar/Header/index.js
new file mode 100644
index 00000000000..67e9e4431d9
--- /dev/null
+++ b/src/theme/Navbar/MobileSidebar/Header/index.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import {useNavbarMobileSidebar} from '@docusaurus/theme-common/internal';
+import {translate} from '@docusaurus/Translate';
+import NavbarColorModeToggle from '@theme/Navbar/ColorModeToggle';
+import IconClose from '@theme/Icon/Close';
+import NavbarLogo from '@theme/Navbar/Logo';
+function CloseButton() {
+ const mobileSidebar = useNavbarMobileSidebar();
+ return (
+ mobileSidebar.toggle()}>
+
+
+ );
+}
+export default function NavbarMobileSidebarHeader() {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/src/theme/Navbar/MobileSidebar/Layout/index.js b/src/theme/Navbar/MobileSidebar/Layout/index.js
new file mode 100644
index 00000000000..b19eb2f962a
--- /dev/null
+++ b/src/theme/Navbar/MobileSidebar/Layout/index.js
@@ -0,0 +1,22 @@
+import React from 'react';
+import clsx from 'clsx';
+import {useNavbarSecondaryMenu} from '@docusaurus/theme-common/internal';
+export default function NavbarMobileSidebarLayout({
+ header,
+ primaryMenu,
+ secondaryMenu,
+}) {
+ const {shown: secondaryMenuShown} = useNavbarSecondaryMenu();
+ return (
+
+ {header}
+
+
{primaryMenu}
+
{secondaryMenu}
+
+
+ );
+}
diff --git a/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.js b/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.js
new file mode 100644
index 00000000000..9c5d0ec0674
--- /dev/null
+++ b/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.js
@@ -0,0 +1,27 @@
+import React from 'react';
+import {useThemeConfig} from '@docusaurus/theme-common';
+import {useNavbarMobileSidebar} from '@docusaurus/theme-common/internal';
+import NavbarItem from '@theme/NavbarItem';
+function useNavbarItems() {
+ // TODO temporary casting until ThemeConfig type is improved
+ return useThemeConfig().navbar.items;
+}
+// The primary menu displays the navbar items
+export default function NavbarMobilePrimaryMenu() {
+ const mobileSidebar = useNavbarMobileSidebar();
+ // TODO how can the order be defined for mobile?
+ // Should we allow providing a different list of items?
+ const items = useNavbarItems();
+ return (
+
+ {items.map((item, i) => (
+ mobileSidebar.toggle()}
+ key={i}
+ />
+ ))}
+
+ );
+}
diff --git a/src/theme/Navbar/MobileSidebar/SecondaryMenu/index.js b/src/theme/Navbar/MobileSidebar/SecondaryMenu/index.js
new file mode 100644
index 00000000000..dd71af856ae
--- /dev/null
+++ b/src/theme/Navbar/MobileSidebar/SecondaryMenu/index.js
@@ -0,0 +1,30 @@
+import React from 'react';
+import {useThemeConfig} from '@docusaurus/theme-common';
+import {useNavbarSecondaryMenu} from '@docusaurus/theme-common/internal';
+import Translate from '@docusaurus/Translate';
+function SecondaryMenuBackButton(props) {
+ return (
+
+
+
+ );
+}
+// The secondary menu slides from the right and shows contextual information
+// such as the docs sidebar
+export default function NavbarMobileSidebarSecondaryMenu() {
+ const isPrimaryMenuEmpty = useThemeConfig().navbar.items.length === 0;
+ const secondaryMenu = useNavbarSecondaryMenu();
+ return (
+ <>
+ {/* edge-case: prevent returning to the primaryMenu when it's empty */}
+ {!isPrimaryMenuEmpty && (
+ secondaryMenu.hide()} />
+ )}
+ {secondaryMenu.content}
+ >
+ );
+}
diff --git a/src/theme/Navbar/MobileSidebar/Toggle/index.js b/src/theme/Navbar/MobileSidebar/Toggle/index.js
new file mode 100644
index 00000000000..bfe298891b9
--- /dev/null
+++ b/src/theme/Navbar/MobileSidebar/Toggle/index.js
@@ -0,0 +1,22 @@
+import React from 'react';
+import {useNavbarMobileSidebar} from '@docusaurus/theme-common/internal';
+import {translate} from '@docusaurus/Translate';
+import IconMenu from '@theme/Icon/Menu';
+export default function MobileSidebarToggle() {
+ const {toggle, shown} = useNavbarMobileSidebar();
+ return (
+
+
+
+ );
+}
diff --git a/src/theme/Navbar/MobileSidebar/index.js b/src/theme/Navbar/MobileSidebar/index.js
new file mode 100644
index 00000000000..5db3cc7a28c
--- /dev/null
+++ b/src/theme/Navbar/MobileSidebar/index.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import {
+ useLockBodyScroll,
+ useNavbarMobileSidebar,
+} from '@docusaurus/theme-common/internal';
+import NavbarMobileSidebarLayout from '@theme/Navbar/MobileSidebar/Layout';
+import NavbarMobileSidebarHeader from '@theme/Navbar/MobileSidebar/Header';
+import NavbarMobileSidebarPrimaryMenu from '@theme/Navbar/MobileSidebar/PrimaryMenu';
+import NavbarMobileSidebarSecondaryMenu from '@theme/Navbar/MobileSidebar/SecondaryMenu';
+export default function NavbarMobileSidebar() {
+ const mobileSidebar = useNavbarMobileSidebar();
+ useLockBodyScroll(mobileSidebar.shown);
+ if (!mobileSidebar.shouldRender) {
+ return null;
+ }
+ return (
+ }
+ primaryMenu={ }
+ secondaryMenu={ }
+ />
+ );
+}
diff --git a/src/theme/Navbar/Search/index.js b/src/theme/Navbar/Search/index.js
new file mode 100644
index 00000000000..686f73b8d81
--- /dev/null
+++ b/src/theme/Navbar/Search/index.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import clsx from 'clsx';
+import styles from './styles.module.css';
+export default function NavbarSearch({children, className}) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/theme/Navbar/Search/styles.module.css b/src/theme/Navbar/Search/styles.module.css
new file mode 100644
index 00000000000..e6bbbd24c3d
--- /dev/null
+++ b/src/theme/Navbar/Search/styles.module.css
@@ -0,0 +1,21 @@
+/*
+Workaround to avoid rendering empty search container
+See https://github.com/facebook/docusaurus/pull/9385
+*/
+.navbarSearchContainer:empty {
+ display: none;
+}
+
+@media (max-width: 996px) {
+ .navbarSearchContainer {
+ position: relative;
+ right: var(--ifm-navbar-padding-horizontal);
+ }
+}
+
+@media (min-width: 997px) {
+ .navbarSearchContainer {
+ padding: var(--ifm-navbar-item-padding-vertical)
+ var(--ifm-navbar-item-padding-horizontal);
+ }
+}
diff --git a/src/theme/Navbar/index.js b/src/theme/Navbar/index.js
new file mode 100644
index 00000000000..d18a258ca9a
--- /dev/null
+++ b/src/theme/Navbar/index.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import NavbarLayout from '@theme/Navbar/Layout';
+import NavbarContent from '@theme/Navbar/Content';
+export default function Navbar() {
+ return (
+
+
+
+ );
+}
diff --git a/src/theme/Root/index.js b/src/theme/Root/index.js
new file mode 100644
index 00000000000..2fb50921b40
--- /dev/null
+++ b/src/theme/Root/index.js
@@ -0,0 +1,6 @@
+import React from "react";
+import { AuthProvider } from "../../context/AuthContext";
+
+export default function Root({ children }) {
+ return {children} ;
+}
diff --git a/yarn.lock b/yarn.lock
index 2e06116dde7..1ed62f4511a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -199,6 +199,24 @@
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.24"
+"@ant-design/charts-util@0.0.1-alpha.7":
+ version "0.0.1-alpha.7"
+ resolved "https://registry.yarnpkg.com/@ant-design/charts-util/-/charts-util-0.0.1-alpha.7.tgz#39152b7106970faa226ba857fae64a0eb32f30b9"
+ integrity sha512-Yh0o6EdO6SvdSnStFZMbnUzjyymkVzV+TQ9ymVW9hlVgO/fUkUII3JYSdV+UVcFnYwUF0YiDKuSTLCZNAzg2bQ==
+ dependencies:
+ lodash "^4.17.21"
+
+"@ant-design/charts@^2.2.6":
+ version "2.2.6"
+ resolved "https://registry.yarnpkg.com/@ant-design/charts/-/charts-2.2.6.tgz#2e294335399407f14eba5e10d4caf8bb790c80d5"
+ integrity sha512-pkzdIkc+TdHejOkjnizIXleCQ3psqNQSStllhHul4Ep82IU/qfTbGZ9iaVGJoFOc0+uHBO9Y65RVS47TPMBerQ==
+ dependencies:
+ "@ant-design/graphs" "^2.0.4"
+ "@ant-design/plots" "^2.3.2"
+ lodash "^4.17.21"
+ react "^18.3.1"
+ react-dom "^18.3.1"
+
"@ant-design/colors@^7.0.0", "@ant-design/colors@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@ant-design/colors/-/colors-7.2.0.tgz#80d7325d20463f09c7839d28da630043dd5c263a"
@@ -228,6 +246,19 @@
rc-util "^5.35.0"
stylis "^4.3.4"
+"@ant-design/cssinjs@^1.21.1":
+ version "1.23.0"
+ resolved "https://registry.yarnpkg.com/@ant-design/cssinjs/-/cssinjs-1.23.0.tgz#492efba9b15d64f42a4cb5d568cab0607d0c2b16"
+ integrity sha512-7GAg9bD/iC9ikWatU9ym+P9ugJhi/WbsTWzcKN6T4gU0aehsprtke1UAaaSxxkjjmkJb3llet/rbUSLPgwlY4w==
+ dependencies:
+ "@babel/runtime" "^7.11.1"
+ "@emotion/hash" "^0.8.0"
+ "@emotion/unitless" "^0.7.5"
+ classnames "^2.3.1"
+ csstype "^3.1.3"
+ rc-util "^5.35.0"
+ stylis "^4.3.4"
+
"@ant-design/fast-color@^2.0.6":
version "2.0.6"
resolved "https://registry.yarnpkg.com/@ant-design/fast-color/-/fast-color-2.0.6.tgz#ab4d4455c1542c9017d367c2fa8ca3e4215d0ba2"
@@ -235,11 +266,36 @@
dependencies:
"@babel/runtime" "^7.24.7"
+"@ant-design/graphs@^2.0.4":
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/@ant-design/graphs/-/graphs-2.0.4.tgz#49f52a4bf2b616070b505f06ecce47d65451381f"
+ integrity sha512-8Os7/it/auQt7NWUA+Ml+NjVYz2VsRjaGJYGxlUnfT4w0KiW6A9aYgixjVqWYjsdNBK0J3lHtrlME5RLiJ5DTw==
+ dependencies:
+ "@ant-design/charts-util" "0.0.1-alpha.7"
+ "@antv/g6" "^5.0.38"
+ "@antv/g6-extension-react" "^0.1.13"
+ "@antv/graphin" "^3.0.4"
+ lodash "^4.17.21"
+ react "^18.3.1"
+ react-dom "^18.3.1"
+ styled-components "^6.1.13"
+
"@ant-design/icons-svg@^4.4.0":
version "4.4.2"
resolved "https://registry.yarnpkg.com/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz#ed2be7fb4d82ac7e1d45a54a5b06d6cecf8be6f6"
integrity sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==
+"@ant-design/icons@^5.0.0":
+ version "5.6.1"
+ resolved "https://registry.yarnpkg.com/@ant-design/icons/-/icons-5.6.1.tgz#7290fcdc3d96ff3fca793ed399053cd29ad5dbd3"
+ integrity sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==
+ dependencies:
+ "@ant-design/colors" "^7.0.0"
+ "@ant-design/icons-svg" "^4.4.0"
+ "@babel/runtime" "^7.24.8"
+ classnames "^2.2.6"
+ rc-util "^5.31.1"
+
"@ant-design/icons@^5.5.2":
version "5.5.2"
resolved "https://registry.yarnpkg.com/@ant-design/icons/-/icons-5.5.2.tgz#c4567943cc2b7c6dbe9cae68c06ffa35f755dc0d"
@@ -251,6 +307,83 @@
classnames "^2.2.6"
rc-util "^5.31.1"
+"@ant-design/plots@^2.3.2":
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/@ant-design/plots/-/plots-2.3.3.tgz#5f004973c16937f0a5019f290a0234ac15251639"
+ integrity sha512-t+pMXuCNEnbrPsRsIMyPSVMYKnFuVYeqHwtjg3ImfTTBdUAfqnJfCBnyPVakPRoMRV2y9+uVL8YWrOQiEvc6rg==
+ dependencies:
+ "@ant-design/charts-util" "0.0.1-alpha.7"
+ "@antv/event-emitter" "^0.1.3"
+ "@antv/g" "^6.1.7"
+ "@antv/g2" "^5.2.7"
+ "@antv/g2-extension-plot" "^0.2.1"
+ lodash "^4.17.21"
+ react "^18.3.1"
+ react-dom "^18.3.1"
+
+"@ant-design/pro-card@^2.9.6":
+ version "2.9.6"
+ resolved "https://registry.yarnpkg.com/@ant-design/pro-card/-/pro-card-2.9.6.tgz#b3bda5bbd6732e889eb4a4056cc31be5e40b7857"
+ integrity sha512-boUvowODMhc1l55ZZj/08YwnaggL50fAio2NaA7uXsgpbLduSPL2OE0RyiI24NCqFhPRZMZQHbPOmcHw4Bf3yQ==
+ dependencies:
+ "@ant-design/cssinjs" "^1.21.1"
+ "@ant-design/icons" "^5.0.0"
+ "@ant-design/pro-provider" "2.15.3"
+ "@ant-design/pro-utils" "2.16.4"
+ "@babel/runtime" "^7.18.0"
+ classnames "^2.3.2"
+ rc-resize-observer "^1.0.0"
+ rc-util "^5.4.0"
+
+"@ant-design/pro-layout@^7.22.3":
+ version "7.22.3"
+ resolved "https://registry.yarnpkg.com/@ant-design/pro-layout/-/pro-layout-7.22.3.tgz#0b4b93f16674f59ac0214a65362857968a3e2f92"
+ integrity sha512-di/EOMDuoMDRjBweqesYyCxEYr2LCmO82y6A4bSwmmJ6ehxN7HGC73Wx4RuBkzDR7kHLTOXt7WxI6875ENT8mg==
+ dependencies:
+ "@ant-design/cssinjs" "^1.21.1"
+ "@ant-design/icons" "^5.0.0"
+ "@ant-design/pro-provider" "2.15.3"
+ "@ant-design/pro-utils" "2.16.4"
+ "@babel/runtime" "^7.18.0"
+ "@umijs/route-utils" "^4.0.0"
+ "@umijs/use-params" "^1.0.9"
+ classnames "^2.3.2"
+ lodash "^4.17.21"
+ lodash-es "^4.17.21"
+ path-to-regexp "8.2.0"
+ rc-resize-observer "^1.1.0"
+ rc-util "^5.0.6"
+ swr "^2.0.0"
+ warning "^4.0.3"
+
+"@ant-design/pro-provider@2.15.3":
+ version "2.15.3"
+ resolved "https://registry.yarnpkg.com/@ant-design/pro-provider/-/pro-provider-2.15.3.tgz#f0cc4272a2170ce6b9dcb69bf209fb5c4ee5446b"
+ integrity sha512-jUBCuRrhAXNMumSZ++704/zEg/7U1k2N3jMVBgtirvVaCAk5O9iZQKK4W3O3LRFc+D8yO16sXjsxhawvdGL4cA==
+ dependencies:
+ "@ant-design/cssinjs" "^1.21.1"
+ "@babel/runtime" "^7.18.0"
+ "@ctrl/tinycolor" "^3.4.0"
+ dayjs "^1.11.10"
+ rc-util "^5.0.1"
+ swr "^2.0.0"
+
+"@ant-design/pro-utils@2.16.4":
+ version "2.16.4"
+ resolved "https://registry.yarnpkg.com/@ant-design/pro-utils/-/pro-utils-2.16.4.tgz#d6d93e85d52f481965a8d704f7785c6c529aba7c"
+ integrity sha512-PFxqF0fsUsLj8ORvJSuMgVv9NDHwAxZaglzPN/u3jZX7rWYcrHD04EMJEXooZaSyT6Q4+j7SqXDx6oBsdb9zNw==
+ dependencies:
+ "@ant-design/icons" "^5.0.0"
+ "@ant-design/pro-provider" "2.15.3"
+ "@babel/runtime" "^7.18.0"
+ classnames "^2.3.2"
+ dayjs "^1.11.10"
+ lodash "^4.17.21"
+ lodash-es "^4.17.21"
+ rc-util "^5.0.6"
+ safe-stable-stringify "^2.4.3"
+ swr "^2.0.0"
+
"@ant-design/react-slick@~1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@ant-design/react-slick/-/react-slick-1.1.2.tgz#f84ce3e4d0dc941f02b16f1d1d6d7a371ffbb4f1"
@@ -262,6 +395,448 @@
resize-observer-polyfill "^1.5.1"
throttle-debounce "^5.0.0"
+"@antv/algorithm@^0.1.26":
+ version "0.1.26"
+ resolved "https://registry.yarnpkg.com/@antv/algorithm/-/algorithm-0.1.26.tgz#e3f5e7f1d8db5b415c3f31e32b119cbcafc8f5de"
+ integrity sha512-DVhcFSQ8YQnMNW34Mk8BSsfc61iC1sAnmcfYoXTAshYHuU50p/6b7x3QYaGctDNKWGvi1ub7mPcSY0bK+aN0qg==
+ dependencies:
+ "@antv/util" "^2.0.13"
+ tslib "^2.0.0"
+
+"@antv/component@^2.1.2":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/@antv/component/-/component-2.1.2.tgz#578a08abc1e70755dd2a2bad85ad7015dcfecf84"
+ integrity sha512-5nC9i9lh5rBHE+pk4TNnerLe4mn5874YHHhvv6EdL618UkgpdKJL0hJu4l7uAYjZ3g46VBK+IYT7md0FYv8f4w==
+ dependencies:
+ "@antv/g" "^6.1.11"
+ "@antv/scale" "^0.4.16"
+ "@antv/util" "^3.3.10"
+ svg-path-parser "^1.1.0"
+
+"@antv/coord@^0.4.7":
+ version "0.4.7"
+ resolved "https://registry.yarnpkg.com/@antv/coord/-/coord-0.4.7.tgz#3ef6c6e3f9ca0f024b90888549946061f35df77a"
+ integrity sha512-UTbrMLhwJUkKzqJx5KFnSRpU3BqrdLORJbwUbHK2zHSCT3q3bjcFA//ZYLVfIlwqFDXp/hzfMyRtp0c77A9ZVA==
+ dependencies:
+ "@antv/scale" "^0.4.12"
+ "@antv/util" "^2.0.13"
+ gl-matrix "^3.4.3"
+
+"@antv/event-emitter@^0.1.3":
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/@antv/event-emitter/-/event-emitter-0.1.3.tgz#3e06323b9dcd55a3241ddc7c5458cfabd2095164"
+ integrity sha512-4ddpsiHN9Pd4UIlWuKVK1C4IiZIdbwQvy9i7DUSI3xNJ89FPUFt8lxDYj8GzzfdllV0NkJTRxnG+FvLk0llidg==
+
+"@antv/g-camera-api@2.0.35":
+ version "2.0.35"
+ resolved "https://registry.yarnpkg.com/@antv/g-camera-api/-/g-camera-api-2.0.35.tgz#0c8f5824f4525b2fed9941170aa9e668b9c5734f"
+ integrity sha512-z4WKmB6yN2fFi9EnapjuHbFVF0ilhMrWo2eZCxYXcb0dV5MiflU/WZi/bjs4WqVMJPNtYKx+yZhTyROncEiglw==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@antv/util" "^3.3.5"
+ "@babel/runtime" "^7.25.6"
+ gl-matrix "^3.4.3"
+ tslib "^2.5.3"
+
+"@antv/g-canvas@^2.0.29", "@antv/g-canvas@^2.0.32":
+ version "2.0.40"
+ resolved "https://registry.yarnpkg.com/@antv/g-canvas/-/g-canvas-2.0.40.tgz#4d550e891c6bc2e51acc42eb877c21e722add68d"
+ integrity sha512-Starh5g+ydOFKzfK/GpwnLwz+o6UZNHkyWBXdHx2ax/AJWHVXwjyCadt/6kkc2non0ts2ow/hpJaW7X3dgdDxQ==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@antv/g-plugin-canvas-path-generator" "2.1.16"
+ "@antv/g-plugin-canvas-picker" "2.1.19"
+ "@antv/g-plugin-canvas-renderer" "2.2.19"
+ "@antv/g-plugin-dom-interaction" "2.1.21"
+ "@antv/g-plugin-html-renderer" "2.1.21"
+ "@antv/g-plugin-image-loader" "2.1.19"
+ "@antv/util" "^3.3.5"
+ "@babel/runtime" "^7.25.6"
+ tslib "^2.5.3"
+
+"@antv/g-dom-mutation-observer-api@2.0.32":
+ version "2.0.32"
+ resolved "https://registry.yarnpkg.com/@antv/g-dom-mutation-observer-api/-/g-dom-mutation-observer-api-2.0.32.tgz#171361ff66970c620fd5320b51dd79e4add3631f"
+ integrity sha512-50r7en1+doUtR9uXmFJk8YtENQ/+DFcj2g3a4XKu9xp58kmF2qBgtdst9n1deqGcL5s0ufX/Ck9rUhtHwka+Ow==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@babel/runtime" "^7.25.6"
+
+"@antv/g-lite@2.2.16":
+ version "2.2.16"
+ resolved "https://registry.yarnpkg.com/@antv/g-lite/-/g-lite-2.2.16.tgz#3aad1e45c7dca71d536ec7874d5dfb8a9ed4fdcb"
+ integrity sha512-473r6S5srkxUiUxI3ZkrM74HMkgyO9+2HR1xtJ75yDOOuT8F6osdXDgy0Or5cWqOlsVjiN3L3DaPnQLHlUGO5A==
+ dependencies:
+ "@antv/g-math" "3.0.0"
+ "@antv/util" "^3.3.5"
+ "@antv/vendor" "^1.0.3"
+ "@babel/runtime" "^7.25.6"
+ eventemitter3 "^5.0.1"
+ gl-matrix "^3.4.3"
+ rbush "^3.0.1"
+ tslib "^2.5.3"
+
+"@antv/g-math@3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@antv/g-math/-/g-math-3.0.0.tgz#834d993391546e39ae5a30452572fdc49a7c57ec"
+ integrity sha512-AkmiNIEL1vgqTPeGY2wtsMdBBqKFwF7SKSgs+D1iOS/rqYMsXdhp/HvtuQ5tx/HdawE/ZzTiicIYopc520ADZw==
+ dependencies:
+ "@antv/util" "^3.3.5"
+ gl-matrix "^3.4.3"
+ tslib "^2.5.3"
+
+"@antv/g-plugin-canvas-path-generator@2.1.16":
+ version "2.1.16"
+ resolved "https://registry.yarnpkg.com/@antv/g-plugin-canvas-path-generator/-/g-plugin-canvas-path-generator-2.1.16.tgz#f60dfa687027aba12aed90d64839b97b2c3c3be0"
+ integrity sha512-E3/HUzWRv1/5QyKHLcXIgFJff0JBxDHz4NfHwYp6IOy5P/A1mbISsUjwafSl8JIVqx0J81CzgqpwU7pWHeXlaQ==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@antv/g-math" "3.0.0"
+ "@antv/util" "^3.3.5"
+ "@babel/runtime" "^7.25.6"
+ tslib "^2.5.3"
+
+"@antv/g-plugin-canvas-picker@2.1.19":
+ version "2.1.19"
+ resolved "https://registry.yarnpkg.com/@antv/g-plugin-canvas-picker/-/g-plugin-canvas-picker-2.1.19.tgz#d4503b1819808703c765a51b0e3bccef5de4e4cd"
+ integrity sha512-69G0m2v09FimmYSU+hO1wjft1FqM467Cf1jDpjBz6Y3caQ98Hrqpz/7Prko1hMOALCo92MDo65yTTnz/LhBiQA==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@antv/g-math" "3.0.0"
+ "@antv/g-plugin-canvas-path-generator" "2.1.16"
+ "@antv/g-plugin-canvas-renderer" "2.2.19"
+ "@antv/util" "^3.3.5"
+ "@babel/runtime" "^7.25.6"
+ gl-matrix "^3.4.3"
+ tslib "^2.5.3"
+
+"@antv/g-plugin-canvas-renderer@2.2.19":
+ version "2.2.19"
+ resolved "https://registry.yarnpkg.com/@antv/g-plugin-canvas-renderer/-/g-plugin-canvas-renderer-2.2.19.tgz#90911b38ec15edbbc946f7201ce9090bd22a43cd"
+ integrity sha512-3Ac0pjU0NAafu0rwTnthwWV/CV5kV9CpTf96v1CCXX0P3iPWtW72SatQNOt/v2aQ2NjYB34YuwYy9i0U1oS8rg==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@antv/g-math" "3.0.0"
+ "@antv/g-plugin-canvas-path-generator" "2.1.16"
+ "@antv/g-plugin-image-loader" "2.1.19"
+ "@antv/util" "^3.3.5"
+ "@babel/runtime" "^7.25.6"
+ gl-matrix "^3.4.3"
+ tslib "^2.5.3"
+
+"@antv/g-plugin-dom-interaction@2.1.21":
+ version "2.1.21"
+ resolved "https://registry.yarnpkg.com/@antv/g-plugin-dom-interaction/-/g-plugin-dom-interaction-2.1.21.tgz#7a764b270a2da8fc367a763231071f38d5ac49cf"
+ integrity sha512-Vm8yeNjZ2aNgNH3LwDRExRChpuVv0Wv2zOblUGy5rgyRIh2Fkm8R89pKLmd3GlLo4AF1ZqAGWHiY2WOeMHEEIA==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@babel/runtime" "^7.25.6"
+ tslib "^2.5.3"
+
+"@antv/g-plugin-dragndrop@^2.0.22", "@antv/g-plugin-dragndrop@^2.0.25":
+ version "2.0.32"
+ resolved "https://registry.yarnpkg.com/@antv/g-plugin-dragndrop/-/g-plugin-dragndrop-2.0.32.tgz#31559d38c5401a5116a6a8b7c64ba8c939208186"
+ integrity sha512-0Y9S/jx6Z7O3hEQhqrXGWNIcV1dBoRpokSP9gIMqTxOjCLzVUFYv8pFoI+Uyeow6PAWe+gdBQu+EJgVi223lJQ==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@antv/util" "^3.3.5"
+ "@babel/runtime" "^7.25.6"
+ tslib "^2.5.3"
+
+"@antv/g-plugin-html-renderer@2.1.21":
+ version "2.1.21"
+ resolved "https://registry.yarnpkg.com/@antv/g-plugin-html-renderer/-/g-plugin-html-renderer-2.1.21.tgz#2077e5eae60c818962f275f3cf73044a0c8aaa88"
+ integrity sha512-1PR9rYt4BgSx8LFnVPF+cPlcBYKfI7iWK/xPipEa3jZ4j/xftELQ5EEyZpfPnrTqu2PtKeMurx7oaM/HPsgaiQ==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@antv/util" "^3.3.5"
+ "@babel/runtime" "^7.25.6"
+ gl-matrix "^3.4.3"
+ tslib "^2.5.3"
+
+"@antv/g-plugin-image-loader@2.1.19":
+ version "2.1.19"
+ resolved "https://registry.yarnpkg.com/@antv/g-plugin-image-loader/-/g-plugin-image-loader-2.1.19.tgz#c94e63de91b99c7384ecd758687e78a21b1a202b"
+ integrity sha512-ZjNs08RkzdDMLlEWGabJG1Lu1Q71afStSlhcIRhrDOLB4tH0UdYlq/f72tlzJ6KjtLnril/xQH3D7znPlfAoig==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@antv/util" "^3.3.5"
+ "@babel/runtime" "^7.25.6"
+ gl-matrix "^3.4.3"
+ tslib "^2.5.3"
+
+"@antv/g-plugin-svg-picker@2.0.34":
+ version "2.0.34"
+ resolved "https://registry.yarnpkg.com/@antv/g-plugin-svg-picker/-/g-plugin-svg-picker-2.0.34.tgz#3bedaa9b4cad522e06c133614f8b9f1b6df1a510"
+ integrity sha512-++TjTwG832tvqjP3wlEJwkZvWH/lVHxMZQDG/3knUrkUAQfNNGiEQDIjDhwzUgkYd+J48cTZiVNHzmIZM9rbrQ==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@antv/g-plugin-svg-renderer" "2.2.16"
+ "@babel/runtime" "^7.25.6"
+ tslib "^2.5.3"
+
+"@antv/g-plugin-svg-renderer@2.2.16":
+ version "2.2.16"
+ resolved "https://registry.yarnpkg.com/@antv/g-plugin-svg-renderer/-/g-plugin-svg-renderer-2.2.16.tgz#c27a73a39cb593c32e6fe06d10f4eba130b6df2c"
+ integrity sha512-d/zZV+af8e1p1kEvRGtC57dXPZbHKKlyJ12jfnUlEFT+GhKpX3LNehc0LiO81dbpEsiZK9ffqJZMQrqsVAPWZg==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@antv/util" "^3.3.5"
+ "@babel/runtime" "^7.25.6"
+ gl-matrix "^3.4.3"
+ tslib "^2.5.3"
+
+"@antv/g-svg@^2.0.27":
+ version "2.0.34"
+ resolved "https://registry.yarnpkg.com/@antv/g-svg/-/g-svg-2.0.34.tgz#7de602342f5eb75239a3d97854816be7d656f3f2"
+ integrity sha512-jx8BGZ1cNugbI8YMvJXabVauAj++Agzj6YUomTLjz7EE6K9rYwgqRb2YSV7NoRGGTfMqfIcYu+qMCoBWWsNEPg==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@antv/g-plugin-dom-interaction" "2.1.21"
+ "@antv/g-plugin-svg-picker" "2.0.34"
+ "@antv/g-plugin-svg-renderer" "2.2.16"
+ "@antv/util" "^3.3.5"
+ "@babel/runtime" "^7.25.6"
+ tslib "^2.5.3"
+
+"@antv/g-web-animations-api@2.1.21":
+ version "2.1.21"
+ resolved "https://registry.yarnpkg.com/@antv/g-web-animations-api/-/g-web-animations-api-2.1.21.tgz#4f8fc78d766a0dc4d51d4e37a917a91c59eb02fb"
+ integrity sha512-EkIjeEH3QzHkDJn3sz1Mk83PqVQXGe5440mJV42QmnxuFuFcxGVJMi9vS8Te7kCUJl4eSb/eqnNi5AWfDMWm+w==
+ dependencies:
+ "@antv/g-lite" "2.2.16"
+ "@antv/util" "^3.3.5"
+ "@babel/runtime" "^7.25.6"
+ tslib "^2.5.3"
+
+"@antv/g2-extension-plot@^0.2.1":
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/@antv/g2-extension-plot/-/g2-extension-plot-0.2.1.tgz#664a3cdf2d4d708ed1231ee90d984812b6226d29"
+ integrity sha512-WNv/LIUNJLwlfG8XXmKUbje9PbImtJqh36UDvuOk/uu+kmP/uMyHAXsBuu0yCOWdQgBVTVwoxszxJOCnY4mVfg==
+ dependencies:
+ "@antv/g2" "^5.1.8"
+ "@antv/util" "^3.3.5"
+ d3-array "^3.2.4"
+ d3-hierarchy "^3.1.2"
+
+"@antv/g2@^5.1.8", "@antv/g2@^5.2.7":
+ version "5.2.11"
+ resolved "https://registry.yarnpkg.com/@antv/g2/-/g2-5.2.11.tgz#e79300383a8cc837aa1a94ebde6c29b5521d2d63"
+ integrity sha512-MRoiUwC6BMuxQ+or0BpWhIVjXoAsreUVp7PKpr/c0b0mNA7uzsM+rZfczDxZbJZ6k+zyQgyagjagfamS88w66g==
+ dependencies:
+ "@antv/component" "^2.1.2"
+ "@antv/coord" "^0.4.7"
+ "@antv/event-emitter" "^0.1.3"
+ "@antv/g" "^6.1.11"
+ "@antv/g-canvas" "^2.0.29"
+ "@antv/g-plugin-dragndrop" "^2.0.22"
+ "@antv/scale" "^0.4.16"
+ "@antv/util" "^3.3.10"
+ "@antv/vendor" "1.0.6"
+ flru "^1.0.2"
+ fmin "0.0.2"
+ pdfast "^0.2.0"
+
+"@antv/g6-extension-react@^0.1.13":
+ version "0.1.18"
+ resolved "https://registry.yarnpkg.com/@antv/g6-extension-react/-/g6-extension-react-0.1.18.tgz#0dbf93d7297eef4db0c2aac0067f13c3624545ff"
+ integrity sha512-p1hkm6gc6gPp//6alRr6gcERUX0mZQ5KxxErJWy8pCGnuSHr5oDo2Pqq7ugyK6hhH5i/zxebNTnM9uXDvMUiJA==
+ dependencies:
+ "@antv/g" "^6.1.14"
+ "@antv/g-svg" "^2.0.27"
+ "@antv/react-g" "^2.0.30"
+
+"@antv/g6@^5.0.28", "@antv/g6@^5.0.38":
+ version "5.0.43"
+ resolved "https://registry.yarnpkg.com/@antv/g6/-/g6-5.0.43.tgz#a73c19805f533393f7e50abc4612e26b7863d6ff"
+ integrity sha512-xlx3P5G74gMhQII44RrWHtu+RIXIwxRRGxeozkd0iqteBdbcpGfGHCRH6TH8Qd084i6GIXc9C1Z1n0XOJlz/uQ==
+ dependencies:
+ "@antv/algorithm" "^0.1.26"
+ "@antv/component" "^2.1.2"
+ "@antv/event-emitter" "^0.1.3"
+ "@antv/g" "^6.1.14"
+ "@antv/g-canvas" "^2.0.32"
+ "@antv/g-plugin-dragndrop" "^2.0.25"
+ "@antv/graphlib" "^2.0.4"
+ "@antv/hierarchy" "^0.6.14"
+ "@antv/layout" "1.2.14-beta.9"
+ "@antv/util" "^3.3.10"
+ bubblesets-js "^2.3.4"
+ hull.js "^1.0.6"
+
+"@antv/g@6.1.21", "@antv/g@^6.1.11", "@antv/g@^6.1.14", "@antv/g@^6.1.7":
+ version "6.1.21"
+ resolved "https://registry.yarnpkg.com/@antv/g/-/g-6.1.21.tgz#d64e5dc8ab07a9ec6b14ed671923b7dfe4b4fc05"
+ integrity sha512-3cWmsY1bYwDmVzsFmBeqN1tWVt+3JaWL6Uu54C1oF7qn1VXXa3V3KuXGEYCxuei8E8BMriN3D7fZosY5d+MQqw==
+ dependencies:
+ "@antv/g-camera-api" "2.0.35"
+ "@antv/g-dom-mutation-observer-api" "2.0.32"
+ "@antv/g-lite" "2.2.16"
+ "@antv/g-web-animations-api" "2.1.21"
+ "@babel/runtime" "^7.25.6"
+
+"@antv/graphin@^3.0.4":
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/@antv/graphin/-/graphin-3.0.4.tgz#33f4ead798d8f1fa1bf885247c68ca94d18e17c4"
+ integrity sha512-7ce6RDI5Z6ud93yiyS7b+mmFrHJhlkwwNo53kb7P7KoCsnV7ioMONDE6Gw0ROeMSR6TwHtxGZUhHw9wxnPp82Q==
+ dependencies:
+ "@antv/g6" "^5.0.28"
+
+"@antv/graphlib@^2.0.0", "@antv/graphlib@^2.0.4":
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/@antv/graphlib/-/graphlib-2.0.4.tgz#7cc4352c91125f1a3ec13852220286fe590568ee"
+ integrity sha512-zc/5oQlsdk42Z0ib1mGklwzhJ5vczLFiPa1v7DgJkTbgJ2YxRh9xdarf86zI49sKVJmgbweRpJs7Nu5bIiwv4w==
+ dependencies:
+ "@antv/event-emitter" "^0.1.3"
+
+"@antv/hierarchy@^0.6.14":
+ version "0.6.14"
+ resolved "https://registry.yarnpkg.com/@antv/hierarchy/-/hierarchy-0.6.14.tgz#4e8b4966c9c2a44aaa6f9da7008c4bd44d490385"
+ integrity sha512-V3uknf7bhynOqQDw2sg+9r9DwZ9pc6k/EcqyTFdfXB1+ydr7urisP0MipIuimucvQKN+Qkd+d6w601r1UIroqQ==
+
+"@antv/layout@1.2.14-beta.9":
+ version "1.2.14-beta.9"
+ resolved "https://registry.yarnpkg.com/@antv/layout/-/layout-1.2.14-beta.9.tgz#5c66a0f22158c545aabd1654a50bfc8c3bf93f98"
+ integrity sha512-wPlwBFMtq2lWZFc89/7Lzb8fjHnyKVZZ9zBb2h+zZIP0YWmVmHRE8+dqCiPKOyOGUXEdDtn813f1g107dCHZlg==
+ dependencies:
+ "@antv/event-emitter" "^0.1.3"
+ "@antv/graphlib" "^2.0.0"
+ "@antv/util" "^3.3.2"
+ "@naoak/workerize-transferable" "^0.1.0"
+ comlink "^4.4.1"
+ d3-force "^3.0.0"
+ d3-force-3d "^3.0.5"
+ d3-octree "^1.0.2"
+ d3-quadtree "^3.0.1"
+ dagre "^0.8.5"
+ ml-matrix "^6.10.4"
+ tslib "^2.5.0"
+
+"@antv/react-g@^2.0.30":
+ version "2.0.37"
+ resolved "https://registry.yarnpkg.com/@antv/react-g/-/react-g-2.0.37.tgz#a856e1c219631311267b5be469e4ae8458a5ce0f"
+ integrity sha512-qXued1ZtJHdf8d6aApMLCMHFCZI0lLTjpv6vEpbUWHOGjHolwDTilQy/207UXu2nFd8VbJvnPNnvVyicWFmiKw==
+ dependencies:
+ "@antv/g" "6.1.21"
+ "@antv/util" "^3.3.5"
+ "@babel/runtime" "^7.25.6"
+ gl-matrix "^3.4.3"
+ react-reconciler "^0.26.2"
+ scheduler "^0.20.2"
+ tslib "^2.5.3"
+
+"@antv/scale@^0.4.12", "@antv/scale@^0.4.16":
+ version "0.4.16"
+ resolved "https://registry.yarnpkg.com/@antv/scale/-/scale-0.4.16.tgz#60557470668ccfe5217e482a01f05c0cbb706b62"
+ integrity sha512-5wg/zB5kXHxpTV5OYwJD3ja6R8yTiqIOkjOhmpEJiowkzRlbEC/BOyMvNUq5fqFIHnMCE9woO7+c3zxEQCKPjw==
+ dependencies:
+ "@antv/util" "^3.3.7"
+ color-string "^1.5.5"
+ fecha "^4.2.1"
+
+"@antv/util@^2.0.13":
+ version "2.0.17"
+ resolved "https://registry.yarnpkg.com/@antv/util/-/util-2.0.17.tgz#e8ef42aca7892815b229269f3dd10c6b3c7597a9"
+ integrity sha512-o6I9hi5CIUvLGDhth0RxNSFDRwXeywmt6ExR4+RmVAzIi48ps6HUy+svxOCayvrPBN37uE6TAc2KDofRo0nK9Q==
+ dependencies:
+ csstype "^3.0.8"
+ tslib "^2.0.3"
+
+"@antv/util@^3.3.10", "@antv/util@^3.3.2", "@antv/util@^3.3.5", "@antv/util@^3.3.7":
+ version "3.3.10"
+ resolved "https://registry.yarnpkg.com/@antv/util/-/util-3.3.10.tgz#6fb2560c0f42df61f824e1f995a1ed1bdb00eb9a"
+ integrity sha512-basGML3DFA3O87INnzvDStjzS+n0JLEhRnRsDzP9keiXz8gT1z/fTdmJAZFOzMMWxy+HKbi7NbSt0+8vz/OsBQ==
+ dependencies:
+ fast-deep-equal "^3.1.3"
+ gl-matrix "^3.3.0"
+ tslib "^2.3.1"
+
+"@antv/vendor@1.0.6":
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/@antv/vendor/-/vendor-1.0.6.tgz#0148d7dbfdf06c43e063dab19f84409a8a79fef0"
+ integrity sha512-4WXnLPkbOip6b+dDTzDt5Flvoo7UG2xLTP6M3X3iinWfhKPFpuEVCM5ICXnl7KTTrTe796Uz4Jh7Gfq1DU8xLA==
+ dependencies:
+ "@types/d3-array" "3.0.5"
+ "@types/d3-color" "^3.1.3"
+ "@types/d3-dispatch" "^3.0.6"
+ "@types/d3-dsv" "^3.0.7"
+ "@types/d3-fetch" "^3.0.7"
+ "@types/d3-force" "^3.0.10"
+ "@types/d3-format" "^3.0.4"
+ "@types/d3-geo" "^3.1.0"
+ "@types/d3-hierarchy" "^3.1.7"
+ "@types/d3-interpolate" "^3.0.4"
+ "@types/d3-path" "^3.1.0"
+ "@types/d3-quadtree" "^3.0.6"
+ "@types/d3-random" "^3.0.3"
+ "@types/d3-scale-chromatic" "^3.1.0"
+ "@types/d3-shape" "^3.1.7"
+ "@types/d3-timer" "^3.0.2"
+ d3-array "^3.2.4"
+ d3-color "^3.1.0"
+ d3-dispatch "^3.0.1"
+ d3-dsv "^3.0.1"
+ d3-fetch "^3.0.1"
+ d3-force "^3.0.0"
+ d3-force-3d "^3.0.5"
+ d3-format "^3.1.0"
+ d3-geo "^3.1.1"
+ d3-geo-projection "^4.0.0"
+ d3-hierarchy "^3.1.2"
+ d3-interpolate "^3.0.1"
+ d3-path "^3.1.0"
+ d3-quadtree "^3.0.1"
+ d3-random "^3.0.1"
+ d3-regression "^1.3.10"
+ d3-scale-chromatic "^3.1.0"
+ d3-shape "^3.2.0"
+ d3-timer "^3.0.1"
+
+"@antv/vendor@^1.0.3":
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/@antv/vendor/-/vendor-1.0.10.tgz#e0d7ab6ed25946f4b6ad1b5da481182639faea41"
+ integrity sha512-/llNfo0gyUAi+ZY3TAtkNPS66eXTMbNdaKd8qllyJUuXnpRHYd/LGU69ix6olGJEFBi61hO4f9eTY0zzNOlFlw==
+ dependencies:
+ "@types/d3-array" "^3.2.1"
+ "@types/d3-color" "^3.1.3"
+ "@types/d3-dispatch" "^3.0.6"
+ "@types/d3-dsv" "^3.0.7"
+ "@types/d3-fetch" "^3.0.7"
+ "@types/d3-force" "^3.0.10"
+ "@types/d3-format" "^3.0.4"
+ "@types/d3-geo" "^3.1.0"
+ "@types/d3-hierarchy" "^3.1.7"
+ "@types/d3-interpolate" "^3.0.4"
+ "@types/d3-path" "^3.1.0"
+ "@types/d3-quadtree" "^3.0.6"
+ "@types/d3-random" "^3.0.3"
+ "@types/d3-scale" "^4.0.9"
+ "@types/d3-scale-chromatic" "^3.1.0"
+ "@types/d3-shape" "^3.1.7"
+ "@types/d3-time" "^3.0.4"
+ "@types/d3-timer" "^3.0.2"
+ d3-array "^3.2.4"
+ d3-color "^3.1.0"
+ d3-dispatch "^3.0.1"
+ d3-dsv "^3.0.1"
+ d3-fetch "^3.0.1"
+ d3-force "^3.0.0"
+ d3-force-3d "^3.0.5"
+ d3-format "^3.1.0"
+ d3-geo "^3.1.1"
+ d3-geo-projection "^4.0.0"
+ d3-hierarchy "^3.1.2"
+ d3-interpolate "^3.0.1"
+ d3-path "^3.1.0"
+ d3-quadtree "^3.0.1"
+ d3-random "^3.0.1"
+ d3-regression "^1.3.10"
+ d3-scale "^4.0.2"
+ d3-scale-chromatic "^3.1.0"
+ d3-shape "^3.2.0"
+ d3-time "^3.1.0"
+ d3-timer "^3.0.1"
+
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0", "@babel/code-frame@^7.26.2", "@babel/code-frame@^7.8.3":
version "7.26.2"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85"
@@ -1120,6 +1695,13 @@
dependencies:
regenerator-runtime "^0.14.0"
+"@babel/runtime@^7.25.6":
+ version "7.26.9"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.9.tgz#aa4c6facc65b9cb3f87d75125ffd47781b475433"
+ integrity sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==
+ dependencies:
+ regenerator-runtime "^0.14.0"
+
"@babel/template@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016"
@@ -1477,6 +2059,11 @@
resolved "https://registry.yarnpkg.com/@csstools/utilities/-/utilities-2.0.0.tgz#f7ff0fee38c9ffb5646d47b6906e0bc8868bde60"
integrity sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ==
+"@ctrl/tinycolor@^3.4.0":
+ version "3.6.1"
+ resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz#b6c75a56a1947cc916ea058772d666a2c8932f31"
+ integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==
+
"@discoveryjs/json-ext@0.5.7":
version "0.5.7"
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
@@ -2007,6 +2594,13 @@
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b"
integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==
+"@emotion/is-prop-valid@1.2.2":
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz#d4175076679c6a26faa92b03bb786f9e52612337"
+ integrity sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==
+ dependencies:
+ "@emotion/memoize" "^0.8.1"
+
"@emotion/is-prop-valid@^1.3.0":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz#8d5cf1132f836d7adbe42cf0b49df7816fc88240"
@@ -2014,6 +2608,11 @@
dependencies:
"@emotion/memoize" "^0.9.0"
+"@emotion/memoize@^0.8.1":
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17"
+ integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==
+
"@emotion/memoize@^0.9.0":
version "0.9.0"
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102"
@@ -2061,6 +2660,11 @@
"@emotion/use-insertion-effect-with-fallbacks" "^1.2.0"
"@emotion/utils" "^1.4.2"
+"@emotion/unitless@0.8.1":
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3"
+ integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==
+
"@emotion/unitless@^0.10.0":
version "0.10.0"
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.10.0.tgz#2af2f7c7e5150f497bdabd848ce7b218a27cf745"
@@ -2218,6 +2822,20 @@
dependencies:
"@lit-labs/ssr-dom-shim" "^1.2.0"
+"@ljharb/resumer@~0.0.1":
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/@ljharb/resumer/-/resumer-0.0.1.tgz#8a940a9192dd31f6a1df17564bbd26dc6ad3e68d"
+ integrity sha512-skQiAOrCfO7vRTq53cxznMpks7wS1va95UCidALlOVWqvBAzwPVErwizDwoMqNVMEn1mDq0utxZd02eIrvF1lw==
+ dependencies:
+ "@ljharb/through" "^2.3.9"
+
+"@ljharb/through@^2.3.9", "@ljharb/through@~2.3.9":
+ version "2.3.14"
+ resolved "https://registry.yarnpkg.com/@ljharb/through/-/through-2.3.14.tgz#a5df44295f44dc23bfe106af59426dd0677760b1"
+ integrity sha512-ajBvlKpWucBB17FuQYUShqpqy8GRgYEpJW0vWJbUu1CV9lWyrDCapy0lScU8T8Z6qn49sSwJB3+M+evYIdGg+A==
+ dependencies:
+ call-bind "^1.0.8"
+
"@mdx-js/mdx@^3.0.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-3.1.0.tgz#10235cab8ad7d356c262e8c21c68df5850a97dc3"
@@ -2364,6 +2982,11 @@
prop-types "^15.8.1"
react-is "^19.0.0"
+"@naoak/workerize-transferable@^0.1.0":
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/@naoak/workerize-transferable/-/workerize-transferable-0.1.0.tgz#864cc8241b977bffd8661c0be1441da9b4bfb633"
+ integrity sha512-fDLfuP71IPNP5+zSfxFb52OHgtjZvauRJWbVnpzQ7G7BjcbLjTny0OW1d3ZO806XKpLWNKmeeW3MhE0sy8iwYQ==
+
"@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"
@@ -2945,22 +3568,66 @@
dependencies:
"@types/node" "*"
-"@types/d3-array@^3.0.3":
+"@types/d3-array@3.0.5":
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.5.tgz#857c1afffd3f51319bbc5b301956aca68acaa7b8"
+ integrity sha512-Qk7fpJ6qFp+26VeQ47WY0mkwXaiq8+76RJcncDEfMc2ocRzXLO67bLFRNI4OX1aGBoPzsM5Y2T+/m1pldOgD+A==
+
+"@types/d3-array@^3.0.3", "@types/d3-array@^3.2.1":
version "3.2.1"
resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5"
integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==
-"@types/d3-color@*":
+"@types/d3-color@*", "@types/d3-color@^3.1.3":
version "3.1.3"
resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2"
integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==
+"@types/d3-dispatch@^3.0.6":
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz#096efdf55eb97480e3f5621ff9a8da552f0961e7"
+ integrity sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==
+
+"@types/d3-dsv@*", "@types/d3-dsv@^3.0.7":
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.7.tgz#0a351f996dc99b37f4fa58b492c2d1c04e3dac17"
+ integrity sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==
+
"@types/d3-ease@^3.0.0":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b"
integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==
-"@types/d3-interpolate@^3.0.1":
+"@types/d3-fetch@^3.0.7":
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.7.tgz#c04a2b4f23181aa376f30af0283dbc7b3b569980"
+ integrity sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==
+ dependencies:
+ "@types/d3-dsv" "*"
+
+"@types/d3-force@^3.0.10":
+ version "3.0.10"
+ resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.10.tgz#6dc8fc6e1f35704f3b057090beeeb7ac674bff1a"
+ integrity sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==
+
+"@types/d3-format@^3.0.4":
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.4.tgz#b1e4465644ddb3fdf3a263febb240a6cd616de90"
+ integrity sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==
+
+"@types/d3-geo@^3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.1.0.tgz#b9e56a079449174f0a2c8684a9a4df3f60522440"
+ integrity sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==
+ dependencies:
+ "@types/geojson" "*"
+
+"@types/d3-hierarchy@^3.1.7":
+ version "3.1.7"
+ resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz#6023fb3b2d463229f2d680f9ac4b47466f71f17b"
+ integrity sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==
+
+"@types/d3-interpolate@^3.0.1", "@types/d3-interpolate@^3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c"
integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==
@@ -2972,6 +3639,26 @@
resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.1.0.tgz#2b907adce762a78e98828f0b438eaca339ae410a"
integrity sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==
+"@types/d3-path@^3.1.0":
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.1.1.tgz#f632b380c3aca1dba8e34aa049bcd6a4af23df8a"
+ integrity sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==
+
+"@types/d3-quadtree@^3.0.6":
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz#d4740b0fe35b1c58b66e1488f4e7ed02952f570f"
+ integrity sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==
+
+"@types/d3-random@^3.0.3":
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.3.tgz#ed995c71ecb15e0cd31e22d9d5d23942e3300cfb"
+ integrity sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==
+
+"@types/d3-scale-chromatic@^3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#dc6d4f9a98376f18ea50bad6c39537f1b5463c39"
+ integrity sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==
+
"@types/d3-scale@^4.0.2":
version "4.0.8"
resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb"
@@ -2979,19 +3666,26 @@
dependencies:
"@types/d3-time" "*"
-"@types/d3-shape@^3.1.0":
+"@types/d3-scale@^4.0.9":
+ version "4.0.9"
+ resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.9.tgz#57a2f707242e6fe1de81ad7bfcccaaf606179afb"
+ integrity sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==
+ dependencies:
+ "@types/d3-time" "*"
+
+"@types/d3-shape@^3.1.0", "@types/d3-shape@^3.1.7":
version "3.1.7"
resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.7.tgz#2b7b423dc2dfe69c8c93596e673e37443348c555"
integrity sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==
dependencies:
"@types/d3-path" "*"
-"@types/d3-time@*", "@types/d3-time@^3.0.0":
+"@types/d3-time@*", "@types/d3-time@^3.0.0", "@types/d3-time@^3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.4.tgz#8472feecd639691450dd8000eb33edd444e1323f"
integrity sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==
-"@types/d3-timer@^3.0.0":
+"@types/d3-timer@^3.0.0", "@types/d3-timer@^3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70"
integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==
@@ -3071,6 +3765,11 @@
"@types/qs" "*"
"@types/serve-static" "*"
+"@types/geojson@*":
+ version "7946.0.16"
+ resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.16.tgz#8ebe53d69efada7044454e3305c19017d97ced2a"
+ integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==
+
"@types/gtag.js@^0.0.12":
version "0.0.12"
resolved "https://registry.yarnpkg.com/@types/gtag.js/-/gtag.js-0.0.12.tgz#095122edca896689bdfcdd73b057e23064d23572"
@@ -3300,6 +3999,11 @@
dependencies:
"@types/node" "*"
+"@types/stylis@4.2.5":
+ version "4.2.5"
+ resolved "https://registry.yarnpkg.com/@types/stylis/-/stylis-4.2.5.tgz#1daa6456f40959d06157698a653a9ab0a70281df"
+ integrity sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==
+
"@types/trusted-types@^2.0.2":
version "2.0.7"
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11"
@@ -3334,6 +4038,16 @@
dependencies:
"@types/yargs-parser" "*"
+"@umijs/route-utils@^4.0.0":
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/@umijs/route-utils/-/route-utils-4.0.1.tgz#156df5b3f2328059722d3ee7dd8f65e18c3cde8b"
+ integrity sha512-+1ixf1BTOLuH+ORb4x8vYMPeIt38n9q0fJDwhv9nSxrV46mxbLF0nmELIo9CKQB2gHfuC4+hww6xejJ6VYnBHQ==
+
+"@umijs/use-params@^1.0.9":
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/@umijs/use-params/-/use-params-1.0.9.tgz#0ae4a87f4922d8e8e3fb4495b0f8f4de9ca38c52"
+ integrity sha512-QlN0RJSBVQBwLRNxbxjQ5qzqYIGn+K7USppMoIOVlf7fxXHsnQZ2bEsa6Pm74bt6DVQxpUE8HqvdStn6Y9FV1w==
+
"@ungap/structured-clone@^1.0.0":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.1.tgz#28fa185f67daaf7b7a1a8c1d445132c5d979f8bd"
@@ -3578,6 +4292,20 @@ algoliasearch@^5.14.2, algoliasearch@^5.17.1:
"@algolia/requester-fetch" "5.18.0"
"@algolia/requester-node-http" "5.18.0"
+align-text@^0.1.1, align-text@^0.1.3:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
+ integrity sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==
+ dependencies:
+ kind-of "^3.0.2"
+ longest "^1.0.1"
+ repeat-string "^1.5.2"
+
+amdefine@>=0.0.4:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+ integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==
+
ansi-align@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59"
@@ -3597,6 +4325,11 @@ ansi-html-community@^0.0.8:
resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41"
integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==
+ansi-regex@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+ integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==
+
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
@@ -3607,6 +4340,11 @@ ansi-regex@^6.0.1:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654"
integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==
+ansi-styles@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+ integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==
+
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
@@ -3711,6 +4449,14 @@ argparse@^2.0.1:
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz#384d12a37295aec3769ab022ad323a18a51ccf8b"
+ integrity sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==
+ dependencies:
+ call-bound "^1.0.3"
+ is-array-buffer "^3.0.5"
+
array-flatten@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
@@ -3721,11 +4467,29 @@ array-union@^2.1.0:
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+arraybuffer.prototype.slice@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c"
+ integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==
+ dependencies:
+ array-buffer-byte-length "^1.0.1"
+ call-bind "^1.0.8"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.5"
+ es-errors "^1.3.0"
+ get-intrinsic "^1.2.6"
+ is-array-buffer "^3.0.4"
+
astring@^1.8.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/astring/-/astring-1.9.0.tgz#cc73e6062a7eb03e7d19c22d8b0b3451fd9bfeef"
integrity sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==
+async-function@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b"
+ integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==
+
async@^3.2.4:
version "3.2.6"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce"
@@ -3753,6 +4517,13 @@ autoprefixer@^10.4.19:
picocolors "^1.0.1"
postcss-value-parser "^4.2.0"
+available-typed-arrays@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846"
+ integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==
+ dependencies:
+ possible-typed-array-names "^1.0.0"
+
axios@^1.6.8:
version "1.7.9"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a"
@@ -3931,6 +4702,11 @@ browserslist@^4.0.0, browserslist@^4.18.1, browserslist@^4.23.0, browserslist@^4
node-releases "^2.0.19"
update-browserslist-db "^1.1.1"
+bubblesets-js@^2.3.4:
+ version "2.3.4"
+ resolved "https://registry.yarnpkg.com/bubblesets-js/-/bubblesets-js-2.3.4.tgz#8e1230b29c309e3327a05630fe02df3d96596ab6"
+ integrity sha512-DyMjHmpkS2+xcFNtyN00apJYL3ESdp9fTrkDr5+9Qg/GPqFmcWgGsK1akZnttE1XFxJ/VMy4DNNGMGYtmFp1Sg==
+
buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
@@ -3972,7 +4748,15 @@ call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1:
es-errors "^1.3.0"
function-bind "^1.1.2"
-call-bind@^1.0.8:
+call-bind-apply-helpers@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6"
+ integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==
+ dependencies:
+ es-errors "^1.3.0"
+ function-bind "^1.1.2"
+
+call-bind@^1.0.2, call-bind@^1.0.7, call-bind@^1.0.8, call-bind@~1.0.2:
version "1.0.8"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c"
integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==
@@ -4003,6 +4787,11 @@ camel-case@^4.1.2:
pascal-case "^3.1.2"
tslib "^2.0.3"
+camelcase@^1.0.2:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
+ integrity sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==
+
camelcase@^6.2.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
@@ -4013,6 +4802,11 @@ camelcase@^7.0.1:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-7.0.1.tgz#f02e50af9fd7782bc8b88a3558c32fd3a388f048"
integrity sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==
+camelize@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3"
+ integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==
+
caniuse-api@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
@@ -4033,6 +4827,25 @@ ccount@^2.0.0:
resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5"
integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==
+center-align@^0.1.1:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
+ integrity sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==
+ dependencies:
+ align-text "^0.1.3"
+ lazy-cache "^1.0.3"
+
+chalk@^1.1.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+ integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==
+ dependencies:
+ ansi-styles "^2.2.1"
+ escape-string-regexp "^1.0.2"
+ has-ansi "^2.0.0"
+ strip-ansi "^3.0.0"
+ supports-color "^2.0.0"
+
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
@@ -4071,10 +4884,10 @@ character-reference-invalid@^2.0.0:
resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz#85c66b041e43b47210faf401278abf808ac45cb9"
integrity sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==
-chart.js@4.4.6:
- version "4.4.6"
- resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-4.4.6.tgz#da39b84ca752298270d4c0519675c7659936abec"
- integrity sha512-8Y406zevUPbbIBA/HRk33khEmQPk5+cxeflWE/2rx1NJsjVWMPw/9mSP9rxHP5eqi6LNoPBVMfZHxbwLSgldYA==
+chart.js@4.4.8:
+ version "4.4.8"
+ resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-4.4.8.tgz#54645b638e9d585099bc16b892947b5e6cd2a552"
+ integrity sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==
dependencies:
"@kurkle/color" "^0.3.0"
@@ -4159,6 +4972,15 @@ cli-table3@^0.6.3:
optionalDependencies:
"@colors/colors" "1.5.0"
+cliui@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
+ integrity sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==
+ dependencies:
+ center-align "^0.1.1"
+ right-align "^0.1.1"
+ wordwrap "0.0.2"
+
clone-deep@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
@@ -4185,11 +5007,19 @@ color-convert@^2.0.1:
dependencies:
color-name "~1.1.4"
-color-name@~1.1.4:
+color-name@^1.0.0, color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+color-string@^1.5.5:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4"
+ integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
+ dependencies:
+ color-name "^1.0.0"
+ simple-swizzle "^0.2.2"
+
colord@^2.9.3:
version "2.9.3"
resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43"
@@ -4212,6 +5042,11 @@ combined-stream@^1.0.8:
dependencies:
delayed-stream "~1.0.0"
+comlink@^4.4.1:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/comlink/-/comlink-4.4.2.tgz#cbbcd82742fbebc06489c28a183eedc5c60a2bca"
+ integrity sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g==
+
comma-separated-tokens@^2.0.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee"
@@ -4345,6 +5180,11 @@ content-type@~1.0.4, content-type@~1.0.5:
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
+contour_plot@^0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/contour_plot/-/contour_plot-0.0.1.tgz#475870f032b8e338412aa5fc507880f0bf495c77"
+ integrity sha512-Nil2HI76Xux6sVGORvhSS8v66m+/h5CwFkBJDO+U5vWaMdNC0yXNCsGDPbzPhvqOEU5koebhdEvD372LI+IyLw==
+
convert-source-map@^1.5.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f"
@@ -4466,6 +5306,11 @@ css-blank-pseudo@^7.0.1:
dependencies:
postcss-selector-parser "^7.0.0"
+css-color-keywords@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
+ integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==
+
css-declaration-sorter@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz#6dec1c9523bc4a643e088aab8f09e67a54961024"
@@ -4533,6 +5378,15 @@ css-select@^5.1.0:
domutils "^3.0.1"
nth-check "^2.0.1"
+css-to-react-native@3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.2.0.tgz#cdd8099f71024e149e4f6fe17a7d46ecd55f1e32"
+ integrity sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==
+ dependencies:
+ camelize "^1.0.0"
+ css-color-keywords "^1.0.0"
+ postcss-value-parser "^4.0.2"
+
css-tree@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.3.1.tgz#10264ce1e5442e8572fc82fbe490644ff54b5c20"
@@ -4633,12 +5487,12 @@ csso@^5.0.5:
dependencies:
css-tree "~2.2.0"
-csstype@^3.0.2, csstype@^3.1.3:
+csstype@3.1.3, csstype@^3.0.2, csstype@^3.0.8, csstype@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
-"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.1.6, d3-array@^3.2.0:
+"d3-array@1 - 3", "d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.1.6, d3-array@^3.2.0, d3-array@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5"
integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==
@@ -4650,6 +5504,11 @@ d3-axis@3:
resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322"
integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==
+d3-binarytree@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/d3-binarytree/-/d3-binarytree-1.0.2.tgz#ed43ebc13c70fbabfdd62df17480bc5a425753cc"
+ integrity sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==
+
d3-brush@3:
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c"
@@ -4668,7 +5527,7 @@ d3-chord@3:
dependencies:
d3-path "1 - 3"
-"d3-color@1 - 3", d3-color@3:
+"d3-color@1 - 3", d3-color@3, d3-color@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2"
integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==
@@ -4687,7 +5546,7 @@ d3-delaunay@6:
dependencies:
delaunator "5"
-"d3-dispatch@1 - 3", d3-dispatch@3:
+"d3-dispatch@1 - 3", d3-dispatch@3, d3-dispatch@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e"
integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==
@@ -4700,7 +5559,7 @@ d3-delaunay@6:
d3-dispatch "1 - 3"
d3-selection "3"
-"d3-dsv@1 - 3", d3-dsv@3:
+"d3-dsv@1 - 3", d3-dsv@3, d3-dsv@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73"
integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==
@@ -4714,14 +5573,25 @@ d3-delaunay@6:
resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4"
integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==
-d3-fetch@3:
+d3-fetch@3, d3-fetch@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22"
integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==
dependencies:
d3-dsv "1 - 3"
-d3-force@3:
+d3-force-3d@^3.0.5:
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/d3-force-3d/-/d3-force-3d-3.0.5.tgz#9c8931b49acc3554f9110e128bc580cd3ab830f2"
+ integrity sha512-tdwhAhoTYZY/a6eo9nR7HP3xSW/C6XvJTbeRpR92nlPzH6OiE+4MliN9feuSFd0tPtEUo+191qOhCTWx3NYifg==
+ dependencies:
+ d3-binarytree "1"
+ d3-dispatch "1 - 3"
+ d3-octree "1"
+ d3-quadtree "1 - 3"
+ d3-timer "1 - 3"
+
+d3-force@3, d3-force@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4"
integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==
@@ -4730,19 +5600,28 @@ d3-force@3:
d3-quadtree "1 - 3"
d3-timer "1 - 3"
-"d3-format@1 - 3", d3-format@3:
+"d3-format@1 - 3", d3-format@3, d3-format@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641"
integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==
-d3-geo@3:
+d3-geo-projection@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/d3-geo-projection/-/d3-geo-projection-4.0.0.tgz#dc229e5ead78d31869a4e87cf1f45bd2716c48ca"
+ integrity sha512-p0bK60CEzph1iqmnxut7d/1kyTmm3UWtPlwdkM31AU+LW+BXazd5zJdoCn7VFxNCHXRngPHRnsNn5uGjLRGndg==
+ dependencies:
+ commander "7"
+ d3-array "1 - 3"
+ d3-geo "1.12.0 - 3"
+
+"d3-geo@1.12.0 - 3", d3-geo@3, d3-geo@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.1.tgz#6027cf51246f9b2ebd64f99e01dc7c3364033a4d"
integrity sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==
dependencies:
d3-array "2.5.0 - 3"
-d3-hierarchy@3:
+d3-hierarchy@3, d3-hierarchy@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6"
integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==
@@ -4754,6 +5633,11 @@ d3-hierarchy@3:
dependencies:
d3-color "1 - 3"
+d3-octree@1, d3-octree@^1.0.2:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/d3-octree/-/d3-octree-1.1.0.tgz#f07e353b76df872644e7130ab1a74c5ef2f4287e"
+ integrity sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==
+
"d3-path@1 - 3", d3-path@3, d3-path@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526"
@@ -4764,17 +5648,22 @@ d3-polygon@3:
resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398"
integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==
-"d3-quadtree@1 - 3", d3-quadtree@3:
+"d3-quadtree@1 - 3", d3-quadtree@3, d3-quadtree@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f"
integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==
-d3-random@3:
+d3-random@3, d3-random@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4"
integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==
-d3-scale-chromatic@3:
+d3-regression@^1.3.10:
+ version "1.3.10"
+ resolved "https://registry.yarnpkg.com/d3-regression/-/d3-regression-1.3.10.tgz#d1a411ab45044d9e8d5b8aec05f2e598e1a621c9"
+ integrity sha512-PF8GWEL70cHHWpx2jUQXc68r1pyPHIA+St16muk/XRokETzlegj5LriNKg7o4LR0TySug4nHYPJNNRz/W+/Niw==
+
+d3-scale-chromatic@3, d3-scale-chromatic@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#34c39da298b23c20e02f1a4b239bd0f22e7f1314"
integrity sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==
@@ -4798,7 +5687,7 @@ d3-scale@4, d3-scale@^4.0.2:
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31"
integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==
-d3-shape@3, d3-shape@^3.1.0:
+d3-shape@3, d3-shape@^3.1.0, d3-shape@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5"
integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==
@@ -4812,7 +5701,7 @@ d3-shape@3, d3-shape@^3.1.0:
dependencies:
d3-time "1 - 3"
-"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3, d3-time@^3.0.0:
+"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3, d3-time@^3.0.0, d3-time@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7"
integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==
@@ -4882,7 +5771,42 @@ d3@^7.9.0:
d3-transition "3"
d3-zoom "3"
-dayjs@^1.11.11:
+dagre@^0.8.5:
+ version "0.8.5"
+ resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee"
+ integrity sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==
+ dependencies:
+ graphlib "^2.1.8"
+ lodash "^4.17.15"
+
+data-view-buffer@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570"
+ integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==
+ dependencies:
+ call-bound "^1.0.3"
+ es-errors "^1.3.0"
+ is-data-view "^1.0.2"
+
+data-view-byte-length@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz#9e80f7ca52453ce3e93d25a35318767ea7704735"
+ integrity sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==
+ dependencies:
+ call-bound "^1.0.3"
+ es-errors "^1.3.0"
+ is-data-view "^1.0.2"
+
+data-view-byte-offset@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz#068307f9b71ab76dbbe10291389e020856606191"
+ integrity sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==
+ dependencies:
+ call-bound "^1.0.2"
+ es-errors "^1.3.0"
+ is-data-view "^1.0.1"
+
+dayjs@^1.11.10, dayjs@^1.11.11:
version "1.11.13"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c"
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
@@ -4906,6 +5830,11 @@ debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.5:
dependencies:
ms "^2.1.3"
+decamelize@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+ integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
+
decimal.js-light@^2.4.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934"
@@ -4930,6 +5859,18 @@ decompress-response@^6.0.0:
dependencies:
mimic-response "^3.1.0"
+deep-equal@~1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.2.tgz#78a561b7830eef3134c7f6f3a3d6af272a678761"
+ integrity sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==
+ dependencies:
+ is-arguments "^1.1.1"
+ is-date-object "^1.0.5"
+ is-regex "^1.1.4"
+ object-is "^1.1.5"
+ object-keys "^1.1.1"
+ regexp.prototype.flags "^1.5.1"
+
deep-extend@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
@@ -4952,7 +5893,7 @@ defer-to-connect@^2.0.1:
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587"
integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==
-define-data-property@^1.0.1, define-data-property@^1.1.4:
+define-data-property@^1.0.1, define-data-property@^1.1.1, define-data-property@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
@@ -4975,6 +5916,11 @@ define-properties@^1.2.1:
has-property-descriptors "^1.0.0"
object-keys "^1.1.1"
+defined@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf"
+ integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==
+
del@^6.1.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a"
@@ -5011,7 +5957,7 @@ depd@~1.1.2:
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==
-dequal@^2.0.0:
+dequal@^2.0.0, dequal@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
@@ -5153,7 +6099,14 @@ dot-prop@^6.0.1:
dependencies:
is-obj "^2.0.0"
-dunder-proto@^1.0.1:
+dotignore@~0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905"
+ integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==
+ dependencies:
+ minimatch "^3.0.4"
+
+dunder-proto@^1.0.0, dunder-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==
@@ -5247,6 +6200,63 @@ error-ex@^1.3.1:
dependencies:
is-arrayish "^0.2.1"
+es-abstract@^1.23.5, es-abstract@^1.23.9:
+ version "1.23.9"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.9.tgz#5b45994b7de78dada5c1bebf1379646b32b9d606"
+ integrity sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==
+ dependencies:
+ array-buffer-byte-length "^1.0.2"
+ arraybuffer.prototype.slice "^1.0.4"
+ available-typed-arrays "^1.0.7"
+ call-bind "^1.0.8"
+ call-bound "^1.0.3"
+ data-view-buffer "^1.0.2"
+ data-view-byte-length "^1.0.2"
+ data-view-byte-offset "^1.0.1"
+ es-define-property "^1.0.1"
+ es-errors "^1.3.0"
+ es-object-atoms "^1.0.0"
+ es-set-tostringtag "^2.1.0"
+ es-to-primitive "^1.3.0"
+ function.prototype.name "^1.1.8"
+ get-intrinsic "^1.2.7"
+ get-proto "^1.0.0"
+ get-symbol-description "^1.1.0"
+ globalthis "^1.0.4"
+ gopd "^1.2.0"
+ has-property-descriptors "^1.0.2"
+ has-proto "^1.2.0"
+ has-symbols "^1.1.0"
+ hasown "^2.0.2"
+ internal-slot "^1.1.0"
+ is-array-buffer "^3.0.5"
+ is-callable "^1.2.7"
+ is-data-view "^1.0.2"
+ is-regex "^1.2.1"
+ is-shared-array-buffer "^1.0.4"
+ is-string "^1.1.1"
+ is-typed-array "^1.1.15"
+ is-weakref "^1.1.0"
+ math-intrinsics "^1.1.0"
+ object-inspect "^1.13.3"
+ object-keys "^1.1.1"
+ object.assign "^4.1.7"
+ own-keys "^1.0.1"
+ regexp.prototype.flags "^1.5.3"
+ safe-array-concat "^1.1.3"
+ safe-push-apply "^1.0.0"
+ safe-regex-test "^1.1.0"
+ set-proto "^1.0.0"
+ string.prototype.trim "^1.2.10"
+ string.prototype.trimend "^1.0.9"
+ string.prototype.trimstart "^1.0.8"
+ typed-array-buffer "^1.0.3"
+ typed-array-byte-length "^1.0.3"
+ typed-array-byte-offset "^1.0.4"
+ typed-array-length "^1.0.7"
+ unbox-primitive "^1.1.0"
+ which-typed-array "^1.1.18"
+
es-define-property@^1.0.0, es-define-property@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa"
@@ -5269,17 +6279,43 @@ es-object-atoms@^1.0.0:
dependencies:
es-errors "^1.3.0"
-esast-util-from-estree@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz#8d1cfb51ad534d2f159dc250e604f3478a79f1ad"
- integrity sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==
+es-object-atoms@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1"
+ integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==
dependencies:
- "@types/estree-jsx" "^1.0.0"
- devlop "^1.0.0"
- estree-util-visit "^2.0.0"
- unist-util-position-from-estree "^2.0.0"
+ es-errors "^1.3.0"
-esast-util-from-js@^2.0.0:
+es-set-tostringtag@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d"
+ integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==
+ dependencies:
+ es-errors "^1.3.0"
+ get-intrinsic "^1.2.6"
+ has-tostringtag "^1.0.2"
+ hasown "^2.0.2"
+
+es-to-primitive@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18"
+ integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==
+ dependencies:
+ is-callable "^1.2.7"
+ is-date-object "^1.0.5"
+ is-symbol "^1.0.4"
+
+esast-util-from-estree@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz#8d1cfb51ad534d2f159dc250e604f3478a79f1ad"
+ integrity sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==
+ dependencies:
+ "@types/estree-jsx" "^1.0.0"
+ devlop "^1.0.0"
+ estree-util-visit "^2.0.0"
+ unist-util-position-from-estree "^2.0.0"
+
+esast-util-from-js@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz#5147bec34cc9da44accf52f87f239a40ac3e8225"
integrity sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==
@@ -5443,6 +6479,11 @@ eventemitter3@^4.0.0, eventemitter3@^4.0.1:
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
+eventemitter3@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4"
+ integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
+
events@^3.2.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
@@ -5564,6 +6605,11 @@ faye-websocket@^0.11.3:
dependencies:
websocket-driver ">=0.5.1"
+fecha@^4.2.1:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd"
+ integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==
+
feed@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/feed/-/feed-4.2.2.tgz#865783ef6ed12579e2c44bbef3c9113bc4956a7e"
@@ -5691,11 +6737,34 @@ flat@^5.0.2:
resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
+flru@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/flru/-/flru-1.0.2.tgz#1ae514c62b8b035ffff9ca9e4563ddcc817f4845"
+ integrity sha512-kWyh8ADvHBFz6ua5xYOPnUroZTT/bwWfrCeL0Wj1dzG4/YOmOcfJ99W8dOVyyynJN35rZ9aCOtHChqQovV7yog==
+
+fmin@0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/fmin/-/fmin-0.0.2.tgz#59bbb40d43ffdc1c94cd00a568c41f95f1973017"
+ integrity sha512-sSi6DzInhl9d8yqssDfGZejChO8d2bAGIpysPsvYsxFe898z89XhCZg6CPNV3nhUhFefeC/AXZK2bAJxlBjN6A==
+ dependencies:
+ contour_plot "^0.0.1"
+ json2module "^0.0.3"
+ rollup "^0.25.8"
+ tape "^4.5.1"
+ uglify-js "^2.6.2"
+
follow-redirects@^1.0.0, follow-redirects@^1.15.6:
version "1.15.9"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1"
integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==
+for-each@^0.3.3, for-each@~0.3.3:
+ version "0.3.5"
+ resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47"
+ integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==
+ dependencies:
+ is-callable "^1.2.7"
+
fork-ts-checker-webpack-plugin@^6.5.0:
version "6.5.3"
resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz#eda2eff6e22476a2688d10661688c47f611b37f3"
@@ -5802,6 +6871,23 @@ function-bind@^1.1.2:
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
+function.prototype.name@^1.1.6, function.prototype.name@^1.1.8:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78"
+ integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==
+ dependencies:
+ call-bind "^1.0.8"
+ call-bound "^1.0.3"
+ define-properties "^1.2.1"
+ functions-have-names "^1.2.3"
+ hasown "^2.0.2"
+ is-callable "^1.2.7"
+
+functions-have-names@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
+ integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
+
gensync@^1.0.0-beta.2:
version "1.0.0-beta.2"
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
@@ -5823,12 +6909,28 @@ get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6:
hasown "^2.0.2"
math-intrinsics "^1.1.0"
+get-intrinsic@^1.2.7:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01"
+ integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==
+ dependencies:
+ call-bind-apply-helpers "^1.0.2"
+ es-define-property "^1.0.1"
+ es-errors "^1.3.0"
+ es-object-atoms "^1.1.1"
+ function-bind "^1.1.2"
+ get-proto "^1.0.1"
+ gopd "^1.2.0"
+ has-symbols "^1.1.0"
+ hasown "^2.0.2"
+ math-intrinsics "^1.1.0"
+
get-own-enumerable-property-symbols@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664"
integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==
-get-proto@^1.0.0:
+get-proto@^1.0.0, get-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==
@@ -5841,6 +6943,15 @@ get-stream@^6.0.0, get-stream@^6.0.1:
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
+get-symbol-description@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee"
+ integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==
+ dependencies:
+ call-bound "^1.0.3"
+ es-errors "^1.3.0"
+ get-intrinsic "^1.2.6"
+
gh-pages@^6.1.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/gh-pages/-/gh-pages-6.3.0.tgz#a5b9476dd4385ceaf85c6467b2e05397093e7613"
@@ -5866,6 +6977,11 @@ github-slugger@^1.5.0:
resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.5.0.tgz#17891bbc73232051474d68bd867a34625c955f7d"
integrity sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==
+gl-matrix@^3.3.0, gl-matrix@^3.4.3:
+ version "3.4.3"
+ resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.4.3.tgz#fc1191e8320009fd4d20e9339595c6041ddc22c9"
+ integrity sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==
+
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"
@@ -5885,7 +7001,7 @@ glob-to-regexp@^0.4.1:
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
-glob@^7.0.0, glob@^7.1.6, glob@^9, glob@^9.2.0:
+glob@^7.0.0, glob@^7.1.6, glob@^9, glob@^9.2.0, glob@~7.2.3:
version "9.3.5"
resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21"
integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==
@@ -5923,6 +7039,14 @@ globals@^11.1.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+globalthis@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236"
+ integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==
+ dependencies:
+ define-properties "^1.2.1"
+ gopd "^1.0.1"
+
globby@^11.0.1, globby@^11.0.4, globby@^11.1.0:
version "11.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
@@ -5983,6 +7107,13 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11,
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
integrity sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==
+graphlib@^2.1.8:
+ version "2.1.8"
+ resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da"
+ integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==
+ dependencies:
+ lodash "^4.17.15"
+
gray-matter@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798"
@@ -6005,6 +7136,18 @@ handle-thing@^2.0.0:
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e"
integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==
+has-ansi@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+ integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==
+ dependencies:
+ ansi-regex "^2.0.0"
+
+has-bigints@^1.0.2:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe"
+ integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==
+
has-flag@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
@@ -6017,17 +7160,36 @@ has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2:
dependencies:
es-define-property "^1.0.0"
-has-symbols@^1.1.0:
+has-proto@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5"
+ integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==
+ dependencies:
+ dunder-proto "^1.0.0"
+
+has-symbols@^1.0.3, has-symbols@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==
+has-tostringtag@^1.0.0, has-tostringtag@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc"
+ integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==
+ dependencies:
+ has-symbols "^1.0.3"
+
has-yarn@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-3.0.0.tgz#c3c21e559730d1d3b57e28af1f30d06fac38147d"
integrity sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==
-hasown@^2.0.2:
+has@~1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6"
+ integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==
+
+hasown@^2.0.0, hasown@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
@@ -6378,6 +7540,11 @@ http2-wrapper@^2.1.10:
quick-lru "^5.1.1"
resolve-alpn "^1.2.0"
+hull.js@^1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/hull.js/-/hull.js-1.0.6.tgz#75f013e8171eb9a871b4a94887e89eb555461d0e"
+ integrity sha512-TC7e9sHYOaCVms0sn2hN7buxnaGfcl9h5EPVoVX9DTPoMpqQiS9bf3tmGDgiNaMVHBD91RAvWjCxrJ5Jx8BI5A==
+
human-signals@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
@@ -6468,7 +7635,7 @@ inherits@2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==
-inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3:
+inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3, 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==
@@ -6488,6 +7655,15 @@ inline-style-parser@0.2.4:
resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.4.tgz#f4af5fe72e612839fcd453d989a586566d695f22"
integrity sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==
+internal-slot@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961"
+ integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==
+ dependencies:
+ es-errors "^1.3.0"
+ hasown "^2.0.2"
+ side-channel "^1.1.0"
+
"internmap@1 - 2":
version "2.0.3"
resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009"
@@ -6528,11 +7704,56 @@ is-alphanumerical@^2.0.0:
is-alphabetical "^2.0.0"
is-decimal "^2.0.0"
+is-any-array@^2.0.0, is-any-array@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-any-array/-/is-any-array-2.0.1.tgz#9233242a9c098220290aa2ec28f82ca7fa79899e"
+ integrity sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ==
+
+is-arguments@^1.1.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.2.0.tgz#ad58c6aecf563b78ef2bf04df540da8f5d7d8e1b"
+ integrity sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==
+ dependencies:
+ call-bound "^1.0.2"
+ has-tostringtag "^1.0.2"
+
+is-array-buffer@^3.0.4, is-array-buffer@^3.0.5:
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280"
+ integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==
+ dependencies:
+ call-bind "^1.0.8"
+ call-bound "^1.0.3"
+ get-intrinsic "^1.2.6"
+
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
+is-arrayish@^0.3.1:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
+ integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
+
+is-async-function@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.1.1.tgz#3e69018c8e04e73b738793d020bfe884b9fd3523"
+ integrity sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==
+ dependencies:
+ async-function "^1.0.0"
+ call-bound "^1.0.3"
+ get-proto "^1.0.1"
+ has-tostringtag "^1.0.2"
+ safe-regex-test "^1.1.0"
+
+is-bigint@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672"
+ integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==
+ dependencies:
+ has-bigints "^1.0.2"
+
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"
@@ -6540,6 +7761,24 @@ is-binary-path@~2.1.0:
dependencies:
binary-extensions "^2.0.0"
+is-boolean-object@^1.2.1:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.2.tgz#7067f47709809a393c71ff5bb3e135d8a9215d9e"
+ integrity sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==
+ dependencies:
+ call-bound "^1.0.3"
+ has-tostringtag "^1.0.2"
+
+is-buffer@^1.1.5:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
+ integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
+
+is-callable@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
+ integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
+
is-ci@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867"
@@ -6554,6 +7793,23 @@ is-core-module@^2.16.0:
dependencies:
hasown "^2.0.2"
+is-data-view@^1.0.1, is-data-view@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e"
+ integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==
+ dependencies:
+ call-bound "^1.0.2"
+ get-intrinsic "^1.2.6"
+ is-typed-array "^1.1.13"
+
+is-date-object@^1.0.5, is-date-object@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7"
+ integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==
+ dependencies:
+ call-bound "^1.0.2"
+ has-tostringtag "^1.0.2"
+
is-decimal@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-2.0.1.tgz#9469d2dc190d0214fd87d78b78caecc0cc14eef7"
@@ -6574,11 +7830,28 @@ is-extglob@^2.1.1:
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+is-finalizationregistry@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz#eefdcdc6c94ddd0674d9c85887bf93f944a97c90"
+ integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==
+ dependencies:
+ call-bound "^1.0.3"
+
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+is-generator-function@^1.0.10:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca"
+ integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==
+ dependencies:
+ call-bound "^1.0.3"
+ get-proto "^1.0.0"
+ has-tostringtag "^1.0.2"
+ safe-regex-test "^1.1.0"
+
is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
@@ -6599,11 +7872,24 @@ is-installed-globally@^0.4.0:
global-dirs "^3.0.0"
is-path-inside "^3.0.2"
+is-map@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e"
+ integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==
+
is-npm@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-6.0.0.tgz#b59e75e8915543ca5d881ecff864077cba095261"
integrity sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==
+is-number-object@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541"
+ integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==
+ dependencies:
+ call-bound "^1.0.3"
+ has-tostringtag "^1.0.2"
+
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
@@ -6646,6 +7932,24 @@ is-plain-object@^2.0.4:
dependencies:
isobject "^3.0.1"
+is-regex@^1.1.4, is-regex@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22"
+ integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==
+ dependencies:
+ call-bound "^1.0.2"
+ gopd "^1.2.0"
+ has-tostringtag "^1.0.2"
+ hasown "^2.0.2"
+
+is-regex@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
+ integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
is-regexp@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
@@ -6656,16 +7960,72 @@ is-root@^2.1.0:
resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c"
integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==
+is-set@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d"
+ integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==
+
+is-shared-array-buffer@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz#9b67844bd9b7f246ba0708c3a93e34269c774f6f"
+ integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==
+ dependencies:
+ call-bound "^1.0.3"
+
is-stream@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
+is-string@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9"
+ integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==
+ dependencies:
+ call-bound "^1.0.3"
+ has-tostringtag "^1.0.2"
+
+is-symbol@^1.0.4, is-symbol@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634"
+ integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==
+ dependencies:
+ call-bound "^1.0.2"
+ has-symbols "^1.1.0"
+ safe-regex-test "^1.1.0"
+
+is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15:
+ version "1.1.15"
+ resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b"
+ integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==
+ dependencies:
+ which-typed-array "^1.1.16"
+
is-typedarray@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==
+is-weakmap@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd"
+ integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==
+
+is-weakref@^1.0.2, is-weakref@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.1.tgz#eea430182be8d64174bd96bffbc46f21bf3f9293"
+ integrity sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==
+ dependencies:
+ call-bound "^1.0.3"
+
+is-weakset@^2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.4.tgz#c9f5deb0bc1906c6d6f1027f284ddf459249daca"
+ integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==
+ dependencies:
+ call-bound "^1.0.3"
+ get-intrinsic "^1.2.6"
+
is-wsl@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
@@ -6683,6 +8043,11 @@ isarray@0.0.1:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==
+isarray@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
+ integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
+
isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@@ -6805,6 +8170,13 @@ json-schema-traverse@^1.0.0:
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+json2module@^0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/json2module/-/json2module-0.0.3.tgz#00fb5f4a9b7adfc3f0647c29cb17bcd1979be9b2"
+ integrity sha512-qYGxqrRrt4GbB8IEOy1jJGypkNsjWoIMlZt4bAsmUScCA507Hbc2p1JOhBzqn45u3PWafUgH2OnzyNU7udO/GA==
+ dependencies:
+ rw "^1.3.2"
+
json2mq@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/json2mq/-/json2mq-0.2.0.tgz#b637bd3ba9eabe122c83e9720483aeb10d2c904a"
@@ -6840,6 +8212,13 @@ keyv@^4.5.3:
dependencies:
json-buffer "3.0.1"
+kind-of@^3.0.2:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
+ integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==
+ dependencies:
+ is-buffer "^1.1.5"
+
kind-of@^6.0.0, kind-of@^6.0.2:
version "6.0.3"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
@@ -6865,6 +8244,11 @@ launch-editor@^2.6.0:
picocolors "^1.0.0"
shell-quote "^1.8.1"
+lazy-cache@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
+ integrity sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==
+
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
@@ -7021,6 +8405,11 @@ locate-path@^7.1.0:
dependencies:
p-locate "^6.0.0"
+lodash-es@^4.17.21:
+ version "4.17.21"
+ resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
+ integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
+
lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
@@ -7036,7 +8425,7 @@ lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==
-lodash@^4.17.20, lodash@^4.17.21:
+lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -7046,7 +8435,12 @@ longest-streak@^3.0.0:
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4"
integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==
-loose-envify@^1.0.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
+longest@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
+ integrity sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==
+
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@@ -7911,7 +9305,7 @@ minimatch@^8.0.2:
dependencies:
brace-expansion "^2.0.1"
-minimist@^1.2.0:
+minimist@^1.2.0, minimist@~1.2.8:
version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
@@ -7926,6 +9320,54 @@ minipass@^4.2.4:
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707"
integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
+ml-array-max@^1.2.4:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/ml-array-max/-/ml-array-max-1.2.4.tgz#2373e2b7e51c8807e456cc0ef364c5863713623b"
+ integrity sha512-BlEeg80jI0tW6WaPyGxf5Sa4sqvcyY6lbSn5Vcv44lp1I2GR6AWojfUvLnGTNsIXrZ8uqWmo8VcG1WpkI2ONMQ==
+ dependencies:
+ is-any-array "^2.0.0"
+
+ml-array-min@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/ml-array-min/-/ml-array-min-1.2.3.tgz#662f027c400105816b849cc3cd786915d0801495"
+ integrity sha512-VcZ5f3VZ1iihtrGvgfh/q0XlMobG6GQ8FsNyQXD3T+IlstDv85g8kfV0xUG1QPRO/t21aukaJowDzMTc7j5V6Q==
+ dependencies:
+ is-any-array "^2.0.0"
+
+ml-array-rescale@^1.3.7:
+ version "1.3.7"
+ resolved "https://registry.yarnpkg.com/ml-array-rescale/-/ml-array-rescale-1.3.7.tgz#c4d129320d113a732e62dd963dc1695bba9a5340"
+ integrity sha512-48NGChTouvEo9KBctDfHC3udWnQKNKEWN0ziELvY3KG25GR5cA8K8wNVzracsqSW1QEkAXjTNx+ycgAv06/1mQ==
+ dependencies:
+ is-any-array "^2.0.0"
+ ml-array-max "^1.2.4"
+ ml-array-min "^1.2.3"
+
+ml-matrix@^6.10.4:
+ version "6.12.0"
+ resolved "https://registry.yarnpkg.com/ml-matrix/-/ml-matrix-6.12.0.tgz#def6a0574b5fdc54a753033830e784a17399e270"
+ integrity sha512-AGfR+pWaC0GmzjUnB6BfwhndPEUGz0i7QUYdqNuw1zhTov/vSRJ9pP2hs6BoGpaSbtXgrKjZz2zjD1M0xuur6A==
+ dependencies:
+ is-any-array "^2.0.1"
+ ml-array-rescale "^1.3.7"
+
+mock-property@~1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/mock-property/-/mock-property-1.0.3.tgz#3e37c50a56609d548cabd56559fde3dd8767b10c"
+ integrity sha512-2emPTb1reeLLYwHxyVx993iYyCHEiRRO+y8NFXFPL5kl5q14sgTK76cXyEKkeKCHeRw35SfdkUJ10Q1KfHuiIQ==
+ dependencies:
+ define-data-property "^1.1.1"
+ functions-have-names "^1.2.3"
+ gopd "^1.0.1"
+ has-property-descriptors "^1.0.0"
+ hasown "^2.0.0"
+ isarray "^2.0.5"
+
+moment@^2.30.1:
+ version "2.30.1"
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae"
+ integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
+
motion-dom@^12.4.5:
version "12.4.5"
resolved "https://registry.yarnpkg.com/motion-dom/-/motion-dom-12.4.5.tgz#06116b5a091496654da0d67e40555abbd26068f6"
@@ -8061,12 +9503,25 @@ object-inspect@^1.13.3:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a"
integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==
+object-inspect@~1.12.3:
+ version "1.12.3"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9"
+ integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==
+
+object-is@^1.1.5:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07"
+ integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+
object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
-object.assign@^4.1.0:
+object.assign@^4.1.0, object.assign@^4.1.7:
version "4.1.7"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d"
integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==
@@ -8116,6 +9571,15 @@ opener@^1.5.2:
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==
+own-keys@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358"
+ integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==
+ dependencies:
+ get-intrinsic "^1.2.6"
+ object-keys "^1.1.1"
+ safe-push-apply "^1.0.0"
+
p-cancelable@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050"
@@ -8319,6 +9783,11 @@ path-to-regexp@3.3.0:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-3.3.0.tgz#f7f31d32e8518c2660862b644414b6d5c63a611b"
integrity sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==
+path-to-regexp@8.2.0:
+ version "8.2.0"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.2.0.tgz#73990cc29e57a3ff2a0d914095156df5db79e8b4"
+ integrity sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==
+
path-to-regexp@^1.7.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24"
@@ -8331,6 +9800,11 @@ path-type@^4.0.0:
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+pdfast@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/pdfast/-/pdfast-0.2.0.tgz#8cbc556e1bf2522177787c0de2e0d4373ba885c9"
+ integrity sha512-cq6TTu6qKSFUHwEahi68k/kqN2mfepjkGrG9Un70cgdRRKLKY6Rf8P8uvP2NvZktaQZNF3YE7agEkLj0vGK9bA==
+
picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.0, picocolors@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
@@ -8362,6 +9836,11 @@ pkg-up@^3.1.0:
dependencies:
find-up "^3.0.0"
+possible-typed-array-names@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae"
+ integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==
+
postcss-attribute-case-insensitive@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-7.0.1.tgz#0c4500e3bcb2141848e89382c05b5a31c23033a3"
@@ -8899,7 +10378,7 @@ postcss-unique-selectors@^6.0.4:
dependencies:
postcss-selector-parser "^6.0.16"
-postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
+postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
@@ -8909,7 +10388,7 @@ postcss-zindex@^6.0.2:
resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-6.0.2.tgz#e498304b83a8b165755f53db40e2ea65a99b56e1"
integrity sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg==
-postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.26, postcss@^8.4.33, postcss@^8.4.38:
+postcss@8.4.49, postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.26, postcss@^8.4.33, postcss@^8.4.38:
version "8.4.49"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.49.tgz#4ea479048ab059ab3ae61d082190fabfd994fe19"
integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==
@@ -9025,6 +10504,11 @@ quick-lru@^5.1.1:
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
+quickselect@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-2.0.0.tgz#f19680a486a5eefb581303e023e98faaf25dd018"
+ integrity sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==
+
randombytes@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@@ -9052,6 +10536,13 @@ raw-body@2.5.2:
iconv-lite "0.4.24"
unpipe "1.0.0"
+rbush@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/rbush/-/rbush-3.0.1.tgz#5fafa8a79b3b9afdfe5008403a720cc1de882ecf"
+ integrity sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==
+ dependencies:
+ quickselect "^2.0.0"
+
rc-cascader@~3.32.0:
version "3.32.0"
resolved "https://registry.yarnpkg.com/rc-cascader/-/rc-cascader-3.32.0.tgz#75bb53b1592a7067a789122c026c48c9e863d531"
@@ -9392,6 +10883,14 @@ rc-util@^5.0.1, rc-util@^5.16.1, rc-util@^5.17.0, rc-util@^5.18.1, rc-util@^5.2.
"@babel/runtime" "^7.18.3"
react-is "^18.2.0"
+rc-util@^5.0.6, rc-util@^5.4.0:
+ version "5.44.4"
+ resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.44.4.tgz#89ee9037683cca01cd60f1a6bbda761457dd6ba5"
+ integrity sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==
+ dependencies:
+ "@babel/runtime" "^7.18.3"
+ react-is "^18.2.0"
+
rc-virtual-list@^3.14.2, rc-virtual-list@^3.5.1, rc-virtual-list@^3.5.2:
version "3.17.0"
resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.17.0.tgz#669e29277040c20b6913bbb76f49ea0a92c1136f"
@@ -9454,6 +10953,14 @@ react-dev-utils@^12.0.1:
strip-ansi "^6.0.1"
text-table "^0.2.0"
+react-dom@^18.3.1:
+ version "18.3.1"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4"
+ integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
+ dependencies:
+ loose-envify "^1.1.0"
+ scheduler "^0.23.2"
+
react-dom@^19.0.0:
version "19.0.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.0.0.tgz#43446f1f01c65a4cd7f7588083e686a6726cfb57"
@@ -9546,6 +11053,15 @@ react-masonry-css@^1.0.16:
resolved "https://registry.yarnpkg.com/react-masonry-css/-/react-masonry-css-1.0.16.tgz#72b28b4ae3484e250534700860597553a10f1a2c"
integrity sha512-KSW0hR2VQmltt/qAa3eXOctQDyOu7+ZBevtKgpNDSzT7k5LA/0XntNa9z9HKCdz3QlxmJHglTZ18e4sX4V8zZQ==
+react-reconciler@^0.26.2:
+ version "0.26.2"
+ resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.26.2.tgz#bbad0e2d1309423f76cf3c3309ac6c96e05e9d91"
+ integrity sha512-nK6kgY28HwrMNwDnMui3dvm3rCFjZrcGiuwLc5COUipBK5hWHLOxMJhSnSomirqWwjPBJKV1QcbkI0VJr7Gl1Q==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+ scheduler "^0.20.2"
+
react-router-config@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988"
@@ -9600,6 +11116,13 @@ react-transition-group@^4.4.5:
loose-envify "^1.4.0"
prop-types "^15.6.2"
+react@^18.3.1:
+ version "18.3.1"
+ resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
+ integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
+ dependencies:
+ loose-envify "^1.1.0"
+
react@^19.0.0:
version "19.0.0"
resolved "https://registry.yarnpkg.com/react/-/react-19.0.0.tgz#6e1969251b9f108870aa4bff37a0ce9ddfaaabdd"
@@ -9714,6 +11237,20 @@ recursive-readdir@^2.2.2:
dependencies:
minimatch "^3.0.5"
+reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9"
+ integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==
+ dependencies:
+ call-bind "^1.0.8"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.9"
+ es-errors "^1.3.0"
+ es-object-atoms "^1.0.0"
+ get-intrinsic "^1.2.7"
+ get-proto "^1.0.1"
+ which-builtin-type "^1.2.1"
+
regenerate-unicode-properties@^10.2.0:
version "10.2.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz#626e39df8c372338ea9b8028d1f99dc3fd9c3db0"
@@ -9738,6 +11275,18 @@ regenerator-transform@^0.15.2:
dependencies:
"@babel/runtime" "^7.8.4"
+regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.3:
+ version "1.5.4"
+ resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz#1ad6c62d44a259007e55b3970e00f746efbcaa19"
+ integrity sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==
+ dependencies:
+ call-bind "^1.0.8"
+ define-properties "^1.2.1"
+ es-errors "^1.3.0"
+ get-proto "^1.0.1"
+ gopd "^1.2.0"
+ set-function-name "^2.0.2"
+
regexpu-core@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.2.0.tgz#0e5190d79e542bf294955dccabae04d3c7d53826"
@@ -9914,7 +11463,7 @@ renderkid@^3.0.0:
lodash "^4.17.21"
strip-ansi "^6.0.1"
-repeat-string@^1.0.0:
+repeat-string@^1.0.0, repeat-string@^1.5.2:
version "1.6.1"
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==
@@ -9954,7 +11503,7 @@ resolve-pathname@^3.0.0:
resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd"
integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==
-resolve@^1.1.6, resolve@^1.14.2, resolve@^1.19.0:
+resolve@^1.1.6, resolve@^1.14.2, resolve@^1.19.0, resolve@~1.22.6:
version "1.22.10"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39"
integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==
@@ -9980,6 +11529,13 @@ reusify@^1.0.4:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+right-align@^0.1.1:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
+ integrity sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==
+ dependencies:
+ align-text "^0.1.1"
+
rimraf@^3.0.2, rimraf@^4:
version "4.4.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-4.4.1.tgz#bd33364f67021c5b79e93d7f4fa0568c7c21b755"
@@ -9992,6 +11548,15 @@ robust-predicates@^3.0.2:
resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771"
integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==
+rollup@^0.25.8:
+ version "0.25.8"
+ resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.25.8.tgz#bf6ce83b87510d163446eeaa577ed6a6fc5835e0"
+ integrity sha512-a2S4Bh3bgrdO4BhKr2E4nZkjTvrJ2m2bWjMTzVYtoqSCn0HnuxosXnaJUHrMEziOWr3CzL9GjilQQKcyCQpJoA==
+ dependencies:
+ chalk "^1.1.1"
+ minimist "^1.2.0"
+ source-map-support "^0.3.2"
+
rtlcss@^4.1.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-4.3.0.tgz#f8efd4d5b64f640ec4af8fa25b65bacd9e07cc97"
@@ -10009,11 +11574,22 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"
-rw@1:
+rw@1, rw@^1.3.2:
version "1.3.3"
resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==
+safe-array-concat@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3"
+ integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==
+ dependencies:
+ call-bind "^1.0.8"
+ call-bound "^1.0.2"
+ get-intrinsic "^1.2.6"
+ has-symbols "^1.1.0"
+ isarray "^2.0.5"
+
safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
@@ -10024,6 +11600,28 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+safe-push-apply@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5"
+ integrity sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==
+ dependencies:
+ es-errors "^1.3.0"
+ isarray "^2.0.5"
+
+safe-regex-test@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1"
+ integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==
+ dependencies:
+ call-bound "^1.0.2"
+ es-errors "^1.3.0"
+ is-regex "^1.2.1"
+
+safe-stable-stringify@^2.4.3:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd"
+ integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==
+
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
@@ -10034,6 +11632,21 @@ sax@^1.2.4:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f"
integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==
+scheduler@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
+ integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+
+scheduler@^0.23.2:
+ version "0.23.2"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3"
+ integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==
+ dependencies:
+ loose-envify "^1.1.0"
+
scheduler@^0.25.0:
version "0.25.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015"
@@ -10196,6 +11809,25 @@ set-function-length@^1.2.2:
gopd "^1.0.1"
has-property-descriptors "^1.0.2"
+set-function-name@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985"
+ integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==
+ dependencies:
+ define-data-property "^1.1.4"
+ es-errors "^1.3.0"
+ functions-have-names "^1.2.3"
+ has-property-descriptors "^1.0.2"
+
+set-proto@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/set-proto/-/set-proto-1.0.0.tgz#0760dbcff30b2d7e801fd6e19983e56da337565e"
+ integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==
+ dependencies:
+ dunder-proto "^1.0.1"
+ es-errors "^1.3.0"
+ es-object-atoms "^1.0.0"
+
setprototypeof@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
@@ -10213,7 +11845,7 @@ shallow-clone@^3.0.0:
dependencies:
kind-of "^6.0.2"
-shallowequal@^1.1.0:
+shallowequal@1.1.0, shallowequal@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
@@ -10273,7 +11905,7 @@ side-channel-weakmap@^1.0.2:
object-inspect "^1.13.3"
side-channel-map "^1.0.1"
-side-channel@^1.0.6:
+side-channel@^1.0.6, side-channel@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9"
integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==
@@ -10298,6 +11930,13 @@ simple-git@^3.27.0:
"@kwsites/promise-deferred" "^1.1.1"
debug "^4.3.5"
+simple-swizzle@^0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
+ integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==
+ dependencies:
+ is-arrayish "^0.3.1"
+
sirv@^2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.4.tgz#5dd9a725c578e34e449f332703eb2a74e46a29b0"
@@ -10366,6 +12005,13 @@ source-map-js@^1.0.1, source-map-js@^1.2.1:
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
+source-map-support@^0.3.2:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.3.3.tgz#34900977d5ba3f07c7757ee72e73bb1a9b53754f"
+ integrity sha512-9O4+y9n64RewmFoKUZ/5Tx9IHIcXM6Q+RTSw6ehnqybUz4a7iwR3Eaw80uLtqqQ5D0C+5H03D4KKGo9PdP33Gg==
+ dependencies:
+ source-map "0.1.32"
+
source-map-support@~0.5.20:
version "0.5.21"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
@@ -10374,7 +12020,14 @@ source-map-support@~0.5.20:
buffer-from "^1.0.0"
source-map "^0.6.0"
-source-map@^0.5.7:
+source-map@0.1.32:
+ version "0.1.32"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.32.tgz#c8b6c167797ba4740a8ea33252162ff08591b266"
+ integrity sha512-htQyLrrRLkQ87Zfrir4/yN+vAUd6DNjVayEjTSHXu29AYQJw57I4/xEL/M6p6E/woPNJwvZt6rVlzc7gFEJccQ==
+ dependencies:
+ amdefine ">=0.0.4"
+
+source-map@^0.5.7, source-map@~0.5.1:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
@@ -10465,6 +12118,38 @@ string-width@^5.0.1, string-width@^5.1.2:
emoji-regex "^9.2.2"
strip-ansi "^7.0.1"
+string.prototype.trim@^1.2.10, string.prototype.trim@~1.2.8:
+ version "1.2.10"
+ resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81"
+ integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==
+ dependencies:
+ call-bind "^1.0.8"
+ call-bound "^1.0.2"
+ define-data-property "^1.1.4"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.5"
+ es-object-atoms "^1.0.0"
+ has-property-descriptors "^1.0.2"
+
+string.prototype.trimend@^1.0.9:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942"
+ integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==
+ dependencies:
+ call-bind "^1.0.8"
+ call-bound "^1.0.2"
+ define-properties "^1.2.1"
+ es-object-atoms "^1.0.0"
+
+string.prototype.trimstart@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde"
+ integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-object-atoms "^1.0.0"
+
string_decoder@^1.1.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
@@ -10496,6 +12181,13 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
+strip-ansi@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+ integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==
+ dependencies:
+ ansi-regex "^2.0.0"
+
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
@@ -10544,6 +12236,21 @@ style-to-object@^1.0.0:
dependencies:
inline-style-parser "0.2.4"
+styled-components@^6.1.13:
+ version "6.1.15"
+ resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-6.1.15.tgz#7651904d5424d08c1046056eb39024cc23c72ab7"
+ integrity sha512-PpOTEztW87Ua2xbmLa7yssjNyUF9vE7wdldRfn1I2E6RTkqknkBYpj771OxM/xrvRGinLy2oysa7GOd7NcZZIA==
+ dependencies:
+ "@emotion/is-prop-valid" "1.2.2"
+ "@emotion/unitless" "0.8.1"
+ "@types/stylis" "4.2.5"
+ css-to-react-native "3.2.0"
+ csstype "3.1.3"
+ postcss "8.4.49"
+ shallowequal "1.1.0"
+ stylis "4.3.2"
+ tslib "2.6.2"
+
stylehacks@^6.1.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-6.1.1.tgz#543f91c10d17d00a440430362d419f79c25545a6"
@@ -10557,11 +12264,21 @@ stylis@4.2.0:
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51"
integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==
+stylis@4.3.2:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.2.tgz#8f76b70777dd53eb669c6f58c997bf0a9972e444"
+ integrity sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==
+
stylis@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.4.tgz#ca5c6c4a35c4784e4e93a2a24dc4e9fa075250a4"
integrity sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==
+supports-color@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+ integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==
+
supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
@@ -10586,6 +12303,11 @@ svg-parser@^2.0.4:
resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5"
integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==
+svg-path-parser@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/svg-path-parser/-/svg-path-parser-1.1.0.tgz#e16b4b39df0d2b0d39e8347db79fdda1453a6046"
+ integrity sha512-jGCUqcQyXpfe38R7RFfhrMyfXcBmpMNJI/B+4CE9/Unkh98UporAc461GTthv+TVDuZXsBx7/WiwJb1Oh4tt4A==
+
svgo@^3.0.2, svgo@^3.2.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.3.2.tgz#ad58002652dffbb5986fc9716afe52d869ecbda8"
@@ -10606,6 +12328,14 @@ swc-loader@^0.2.6:
dependencies:
"@swc/counter" "^0.1.3"
+swr@^2.0.0:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/swr/-/swr-2.3.2.tgz#e7c4eb7115e7ff734e445ad0036e97812dd95191"
+ integrity sha512-RosxFpiabojs75IwQ316DGoDRmOqtiAj0tg8wCcbEu4CiLZBs/a9QNtHV7TUfDXmmlgqij/NqzKq/eLelyv9xA==
+ dependencies:
+ dequal "^2.0.3"
+ use-sync-external-store "^1.4.0"
+
tapable@^1.0.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
@@ -10616,6 +12346,28 @@ tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1:
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
+tape@^4.5.1:
+ version "4.17.0"
+ resolved "https://registry.yarnpkg.com/tape/-/tape-4.17.0.tgz#de89f3671ddc5dad178d04c28dc6b0183f42268e"
+ integrity sha512-KCuXjYxCZ3ru40dmND+oCLsXyuA8hoseu2SS404Px5ouyS0A99v8X/mdiLqsR5MTAyamMBN7PRwt2Dv3+xGIxw==
+ dependencies:
+ "@ljharb/resumer" "~0.0.1"
+ "@ljharb/through" "~2.3.9"
+ call-bind "~1.0.2"
+ deep-equal "~1.1.1"
+ defined "~1.0.1"
+ dotignore "~0.1.2"
+ for-each "~0.3.3"
+ glob "~7.2.3"
+ has "~1.0.3"
+ inherits "~2.0.4"
+ is-regex "~1.1.4"
+ minimist "~1.2.8"
+ mock-property "~1.0.0"
+ object-inspect "~1.12.3"
+ resolve "~1.22.6"
+ string.prototype.trim "~1.2.8"
+
terser-webpack-plugin@^5.3.10, terser-webpack-plugin@^5.3.9:
version "5.3.11"
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz#93c21f44ca86634257cac176f884f942b7ba3832"
@@ -10716,7 +12468,12 @@ trough@^2.0.0:
resolved "https://registry.yarnpkg.com/trough/-/trough-2.2.0.tgz#94a60bd6bd375c152c1df911a4b11d5b0256f50f"
integrity sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==
-tslib@^2.0.0, tslib@^2.0.3, tslib@^2.4.0, tslib@^2.6.0:
+tslib@2.6.2:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
+ integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
+
+tslib@^2.0.0, tslib@^2.0.3, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.5.0, tslib@^2.5.3, tslib@^2.6.0:
version "2.8.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
@@ -10744,6 +12501,51 @@ type-is@~1.6.18:
media-typer "0.3.0"
mime-types "~2.1.24"
+typed-array-buffer@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536"
+ integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==
+ dependencies:
+ call-bound "^1.0.3"
+ es-errors "^1.3.0"
+ is-typed-array "^1.1.14"
+
+typed-array-byte-length@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz#8407a04f7d78684f3d252aa1a143d2b77b4160ce"
+ integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==
+ dependencies:
+ call-bind "^1.0.8"
+ for-each "^0.3.3"
+ gopd "^1.2.0"
+ has-proto "^1.2.0"
+ is-typed-array "^1.1.14"
+
+typed-array-byte-offset@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz#ae3698b8ec91a8ab945016108aef00d5bff12355"
+ integrity sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==
+ dependencies:
+ available-typed-arrays "^1.0.7"
+ call-bind "^1.0.8"
+ for-each "^0.3.3"
+ gopd "^1.2.0"
+ has-proto "^1.2.0"
+ is-typed-array "^1.1.15"
+ reflect.getprototypeof "^1.0.9"
+
+typed-array-length@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d"
+ integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==
+ dependencies:
+ call-bind "^1.0.7"
+ for-each "^0.3.3"
+ gopd "^1.0.1"
+ is-typed-array "^1.1.13"
+ possible-typed-array-names "^1.0.0"
+ reflect.getprototypeof "^1.0.6"
+
typed-function@^4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-4.2.1.tgz#19aa51847aa2dea9ef5e7fb7641c060179a74426"
@@ -10761,6 +12563,31 @@ typescript@^5.6.3:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6"
integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==
+uglify-js@^2.6.2:
+ version "2.8.29"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
+ integrity sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==
+ dependencies:
+ source-map "~0.5.1"
+ yargs "~3.10.0"
+ optionalDependencies:
+ uglify-to-browserify "~1.0.0"
+
+uglify-to-browserify@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
+ integrity sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==
+
+unbox-primitive@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2"
+ integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==
+ dependencies:
+ call-bound "^1.0.3"
+ has-bigints "^1.0.2"
+ has-symbols "^1.1.0"
+ which-boxed-primitive "^1.1.1"
+
undici-types@~6.20.0:
version "6.20.0"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"
@@ -10929,6 +12756,11 @@ url-loader@^4.1.1:
mime-types "^2.1.27"
schema-utils "^3.0.0"
+use-sync-external-store@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc"
+ integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==
+
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
@@ -11013,6 +12845,13 @@ void-elements@3.1.0:
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09"
integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==
+warning@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
+ integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
+ dependencies:
+ loose-envify "^1.0.0"
+
watchpack@^2.4.1:
version "2.4.2"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da"
@@ -11178,6 +13017,58 @@ websocket-extensions@>=0.1.1:
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
+which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e"
+ integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==
+ dependencies:
+ is-bigint "^1.1.0"
+ is-boolean-object "^1.2.1"
+ is-number-object "^1.1.1"
+ is-string "^1.1.1"
+ is-symbol "^1.1.1"
+
+which-builtin-type@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e"
+ integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==
+ dependencies:
+ call-bound "^1.0.2"
+ function.prototype.name "^1.1.6"
+ has-tostringtag "^1.0.2"
+ is-async-function "^2.0.0"
+ is-date-object "^1.1.0"
+ is-finalizationregistry "^1.1.0"
+ is-generator-function "^1.0.10"
+ is-regex "^1.2.1"
+ is-weakref "^1.0.2"
+ isarray "^2.0.5"
+ which-boxed-primitive "^1.1.0"
+ which-collection "^1.0.2"
+ which-typed-array "^1.1.16"
+
+which-collection@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0"
+ integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==
+ dependencies:
+ is-map "^2.0.3"
+ is-set "^2.0.3"
+ is-weakmap "^2.0.2"
+ is-weakset "^2.0.3"
+
+which-typed-array@^1.1.16, which-typed-array@^1.1.18:
+ version "1.1.18"
+ resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.18.tgz#df2389ebf3fbb246a71390e90730a9edb6ce17ad"
+ integrity sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==
+ dependencies:
+ available-typed-arrays "^1.0.7"
+ call-bind "^1.0.8"
+ call-bound "^1.0.3"
+ for-each "^0.3.3"
+ gopd "^1.2.0"
+ has-tostringtag "^1.0.2"
+
which@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
@@ -11204,6 +13095,16 @@ wildcard@^2.0.0, wildcard@^2.0.1:
resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67"
integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==
+window-size@0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
+ integrity sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==
+
+wordwrap@0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
+ integrity sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==
+
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
@@ -11264,6 +13165,16 @@ yaml@^1.10.0, yaml@^1.7.2:
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
+yargs@~3.10.0:
+ version "3.10.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
+ integrity sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==
+ dependencies:
+ camelcase "^1.0.2"
+ cliui "^2.1.0"
+ decamelize "^1.0.0"
+ window-size "0.1.0"
+
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
@@ -11278,3 +13189,8 @@ zwitch@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7"
integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==
+
+zxcvbn@^4.4.2:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30"
+ integrity sha512-Bq0B+ixT/DMyG8kgX2xWcI5jUvCwqrMxSFam7m0lAf78nf04hv6lNCsyLYdyYTrCVMqNDY/206K7eExYCeSyUQ==