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 ( +
+ +
+ ); +} 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: ( + + ) + } + ] + }; +} 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: ( + + ) + } + ] + }; +} 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} + + + + + + + + + + + + +
+
+ ); +} + +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)} + > + + +
+ + {/* 主要資訊 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}

+ +
+ + {/* 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)} + > + + + ); +} + +/** 將 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()} + + + {/* 操作按鈕 */} +
+ + +
+ + {/* 只剩一個 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} +
+ + + + +
+
+ ); +} 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]} + + {parts[1]} + + ); + }; + + const renderEmailStatus = () => { + if (!user?.email) { + return {text.notSet}; + } + if (user.is_email_verified) { + return {text.verified}; + } + return ( + + {text.notVerified} + + + ); + }; + + return ( +
+
+

{text.myInfoTitle}

+
+ + {showEmailAlert && user?.email && !user.is_email_verified && ( + + )} + + {!user?.email && !editing && ( + + )} + + + +
+ } + alt="User Avatar" + onError={() => false} + /> +
+ + + +
+ + + + {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.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} +

+ +
+ )} + +
+ + + + + + + + + + + + + { + 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={[ + , + ]} + > +

{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 ( +
+ {submitError && ( + + )} + {successMessage && ( + + )} + + + + + + + + ); +} 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 && ( + + )} + + + + + + {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 && ( + + )} + + + + + + ); +} 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 ( + <> +
+ {successMessage && ( + + )} + + + + {passwordScore > 0 && ( + + {text.passwordStrengthLabel}{text.strengthTexts[passwordScore]} + + )} + ({ + validator(_, value) { + if (!value || getFieldValue("newPassword") === value) { + return Promise.resolve(); + } + return Promise.reject(new Error(text.passwordMismatch)); + }, + }), + ]} + > + + + + + + + + {/* 錯誤訊息 Modal */} + setErrorModalVisible(false)} + footer={[ + , + ]} + > +

{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, + }, + ]} + /> + + + + + + + + + + + + + ); +} 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} + + + +
+
+ ); +} 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 ( +
+
{left}
+
{right}
+
+ ); +} + +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' }} + /> + + ) : ( + + ); +} +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==