From acf3b6b57f639fc3c006728e4eda227d502b5c6c Mon Sep 17 00:00:00 2001 From: dushixiang Date: Wed, 12 Aug 2026 20:00:48 +0800 Subject: [PATCH] refactor: split default theme into standalone repository --- .dockerignore | 4 +- .github/default-theme.ref | 1 + .github/workflows/build-test-ghcr.yml | 13 +- .github/workflows/docker-publish.yml | 13 +- .gitignore | 3 +- Dockerfile | 1 + Makefile | 30 +- internal/app.go | 8 +- internal/assets/paths.go | 11 +- internal/handler/web_handler.go | 24 +- internal/handler/web_handler_test.go | 11 +- internal/service/theme.go | 4 +- internal/service/theme_service_test.go | 8 +- internal/service/theme_util.go | 8 +- portal/.gitignore | 6 - portal/eslint.config.js | 14 - portal/index.html | 15 - portal/package-lock.json | 3618 ------------------------ portal/package.json | 36 - portal/pika-theme.json | 14 - portal/public/logo.png | Bin 231226 -> 0 bytes portal/src/App.tsx | 28 - portal/src/api.ts | 76 - portal/src/components.tsx | 768 ----- portal/src/constants.ts | 49 - portal/src/contexts/ColorMode.tsx | 55 - portal/src/hooks/index.ts | 128 - portal/src/index.css | 169 -- portal/src/lib/utils.ts | 71 - portal/src/main.tsx | 51 - portal/src/pages/MonitorDetail.tsx | 795 ------ portal/src/pages/MonitorList.tsx | 431 --- portal/src/pages/PublicLayout.tsx | 39 - portal/src/pages/ServerDetail.tsx | 2057 -------------- portal/src/pages/ServerList.tsx | 848 ------ portal/src/types.ts | 255 -- portal/tsconfig.app.json | 28 - portal/tsconfig.json | 18 - portal/tsconfig.node.json | 18 - portal/vite.config.ts | 20 - portal/yarn.lock | 1384 --------- web/README.md | 21 +- web/vite.config.ts | 2 +- 43 files changed, 116 insertions(+), 11037 deletions(-) create mode 100644 .github/default-theme.ref delete mode 100644 portal/.gitignore delete mode 100644 portal/eslint.config.js delete mode 100644 portal/index.html delete mode 100644 portal/package-lock.json delete mode 100644 portal/package.json delete mode 100644 portal/pika-theme.json delete mode 100644 portal/public/logo.png delete mode 100644 portal/src/App.tsx delete mode 100644 portal/src/api.ts delete mode 100644 portal/src/components.tsx delete mode 100644 portal/src/constants.ts delete mode 100644 portal/src/contexts/ColorMode.tsx delete mode 100644 portal/src/hooks/index.ts delete mode 100644 portal/src/index.css delete mode 100644 portal/src/lib/utils.ts delete mode 100644 portal/src/main.tsx delete mode 100644 portal/src/pages/MonitorDetail.tsx delete mode 100644 portal/src/pages/MonitorList.tsx delete mode 100644 portal/src/pages/PublicLayout.tsx delete mode 100644 portal/src/pages/ServerDetail.tsx delete mode 100644 portal/src/pages/ServerList.tsx delete mode 100644 portal/src/types.ts delete mode 100644 portal/tsconfig.app.json delete mode 100644 portal/tsconfig.json delete mode 100644 portal/tsconfig.node.json delete mode 100644 portal/vite.config.ts delete mode 100644 portal/yarn.lock diff --git a/.dockerignore b/.dockerignore index e15009e..07a1ae9 100644 --- a/.dockerignore +++ b/.dockerignore @@ -14,8 +14,10 @@ *~ # 构建产物 -# bin/agents/ 和 web/dist/ 不能忽略,运行时从本地文件加载 +# bin/agents/、web/dist/ 和 themes/ 不能忽略,运行时从本地文件加载 web/node_modules/ +# CI 仅使用该 checkout 构建 themes/default,不应进入镜像上下文 +pika-default-theme # 数据目录 data/ diff --git a/.github/default-theme.ref b/.github/default-theme.ref new file mode 100644 index 0000000..689f51d --- /dev/null +++ b/.github/default-theme.ref @@ -0,0 +1 @@ +04ff9915a411debd851bfadba9e28f7294ec910c diff --git a/.github/workflows/build-test-ghcr.yml b/.github/workflows/build-test-ghcr.yml index b22b14f..910281c 100644 --- a/.github/workflows/build-test-ghcr.yml +++ b/.github/workflows/build-test-ghcr.yml @@ -23,6 +23,17 @@ jobs: - name: 检出代码 uses: actions/checkout@v4 + - name: 读取默认主题锁定版本 + run: echo "DEFAULT_THEME_REF=$(tr -d '\r\n' < .github/default-theme.ref)" >> "$GITHUB_ENV" + + # 默认主题作为独立源码仓库参与 Pika 发布构建 + - name: 检出官方默认主题 + uses: actions/checkout@v4 + with: + repository: pika-monitor/pika-default-theme + ref: ${{ env.DEFAULT_THEME_REF }} + path: pika-default-theme + # 安装 make 和 upx - name: 安装 make 和 upx run: | @@ -44,7 +55,7 @@ jobs: # 构建所有组件(前端、agents、服务端) - name: 构建所有组件 run: | - make build-web + make DEFAULT_THEME_DIR=pika-default-theme build-web make build-agents make build-servers diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index fe87d4a..829a527 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -31,6 +31,17 @@ jobs: - name: 检出代码 uses: actions/checkout@v4 + - name: 读取默认主题锁定版本 + run: echo "DEFAULT_THEME_REF=$(tr -d '\r\n' < .github/default-theme.ref)" >> "$GITHUB_ENV" + + # 默认主题作为独立源码仓库参与 Pika 发布构建 + - name: 检出官方默认主题 + uses: actions/checkout@v4 + with: + repository: pika-monitor/pika-default-theme + ref: ${{ env.DEFAULT_THEME_REF }} + path: pika-default-theme + # 安装 make 和 upx - name: 安装 make 和 upx run: | @@ -52,7 +63,7 @@ jobs: # 构建所有组件(前端、agents、服务端) - name: 构建所有组件 run: | - make build-release + make DEFAULT_THEME_DIR=pika-default-theme build-release # 列出编译产物 - name: 列出编译产物 diff --git a/.gitignore b/.gitignore index caedb3f..c97aa99 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,5 @@ agent.yaml playground web/node_modules web/dist -deploy.sh \ No newline at end of file +themes/default +deploy.sh diff --git a/Dockerfile b/Dockerfile index c343803..e586104 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,7 @@ ARG TARGETARCH COPY ./bin/pika-linux-${TARGETARCH} ./pika COPY ./bin/agents ./bin/agents COPY ./web/dist ./web/dist +COPY ./themes ./themes # 暴露端口 EXPOSE 8080 diff --git a/Makefile b/Makefile index 993263c..71013ae 100644 --- a/Makefile +++ b/Makefile @@ -17,12 +17,27 @@ LDFLAGS=-s -w -X 'github.com/pika-monitor/pika/pkg/version.Version=$(VERSION)' - AGENT_LDFLAGS=-s -w -X 'github.com/pika-monitor/pika/pkg/version.Version=$(VERSION)' -X 'github.com/pika-monitor/pika/pkg/version.AgentVersion=$(AGENT_VERSION)' GOFLAGS=CGO_ENABLED=0 -# 构建前端 +# 默认主题已拆分到独立仓库。本地默认使用同级目录,CI 会显式传入 checkout 目录。 +DEFAULT_THEME_DIR ?= ../pika-default-theme +DEFAULT_THEME_OUTPUT_DIR ?= themes/default + +.PHONY: build-web build-default-theme + +# 构建官方管理前端和独立的默认主题,并组装到统一发布目录。 build-web: npm ci --prefix web npm run build --prefix web - npm ci --prefix portal - npm run build --prefix portal + $(MAKE) build-default-theme + +build-default-theme: + test -f "$(DEFAULT_THEME_DIR)/package-lock.json" + test -f "$(DEFAULT_THEME_DIR)/pika-theme.json" + npm ci --prefix "$(DEFAULT_THEME_DIR)" + npm run build --prefix "$(DEFAULT_THEME_DIR)" + rm -rf "$(DEFAULT_THEME_OUTPUT_DIR)" + mkdir -p "$(DEFAULT_THEME_OUTPUT_DIR)" + cp "$(DEFAULT_THEME_DIR)/pika-theme.json" "$(DEFAULT_THEME_OUTPUT_DIR)/pika-theme.json" + cp -R "$(DEFAULT_THEME_DIR)/dist" "$(DEFAULT_THEME_OUTPUT_DIR)/dist" # 构建服务端(开发) build-server: @@ -67,14 +82,15 @@ build-agents: # 构建所有(release版本) build-release: - make build-web - make build-agents - make build-servers + $(MAKE) build-web + $(MAKE) build-agents + $(MAKE) build-servers # 清理编译产物 clean: rm -rf bin/* - rm -rf web/dist portal/dist + rm -rf web/dist + rm -rf themes/default # 运行测试 test: diff --git a/internal/app.go b/internal/app.go index 310bf87..d94f61b 100644 --- a/internal/app.go +++ b/internal/app.go @@ -4,9 +4,11 @@ import ( "context" "log" "net/http" + "path/filepath" "time" "github.com/google/uuid" + "github.com/pika-monitor/pika/internal/assets" "github.com/pika-monitor/pika/internal/config" "github.com/pika-monitor/pika/internal/handler" "github.com/pika-monitor/pika/internal/migrate" @@ -275,9 +277,9 @@ func setupApi(app *orz.App, components *AppComponents) error { // GitHub 认证路由(如果启用) publicApi.POST("/auth/github/callback", components.AccountHandler.GitHubLogin) - // 官方管理 SPA 与活动公开主题使用互不重叠的资源前缀。 - e.GET("/admin/assets/*", components.WebHandler.ServeAdminAsset) - e.GET("/theme-assets/*", components.WebHandler.ServeThemeAsset) + // 管理前端从 web/dist 由 Echo 直接加载;活动公开主题由主题服务选择独立目录。 + e.Static("/admin/assets/", filepath.Join(assets.WebDir(), "assets"), handler.ImmutableStaticHeaders) + e.GET("/t/*", components.WebHandler.ServeThemeAsset) e.GET("/*", components.WebHandler.ServeSPA) return nil diff --git a/internal/assets/paths.go b/internal/assets/paths.go index 130aad4..ebed8cb 100644 --- a/internal/assets/paths.go +++ b/internal/assets/paths.go @@ -8,8 +8,8 @@ import ( const ( defaultWebDir = "web/dist" + defaultThemeDir = "themes/default" defaultAgentDir = "bin/agents" - defaultLogoPath = "portal/public/logo.png" ) func WebDir() string { @@ -19,6 +19,13 @@ func WebDir() string { return defaultWebDir } +func DefaultThemeDir() string { + if dir := os.Getenv("PIKA_DEFAULT_THEME_DIR"); dir != "" { + return dir + } + return defaultThemeDir +} + func AgentDir() string { if dir := os.Getenv("PIKA_AGENT_DIR"); dir != "" { return dir @@ -33,7 +40,7 @@ func AgentPath(filename string) string { func DefaultLogoBase64() string { for _, path := range []string{ os.Getenv("PIKA_DEFAULT_LOGO_PATH"), - defaultLogoPath, + filepath.Join(DefaultThemeDir(), "dist", "logo.png"), filepath.Join(WebDir(), "logo.png"), } { if path == "" { diff --git a/internal/handler/web_handler.go b/internal/handler/web_handler.go index 7c20f38..40ce29d 100644 --- a/internal/handler/web_handler.go +++ b/internal/handler/web_handler.go @@ -31,16 +31,12 @@ func (h *WebHandler) PublicConfig(c *echo.Context) error { return orz.Ok(c, runtime) } -func (h *WebHandler) ServeAdminAsset(c *echo.Context) error { - return serveStaticFile(c, filepath.Join(assets.WebDir(), "admin", "assets"), c.Param("*"), true) -} - func (h *WebHandler) ServeThemeAsset(c *echo.Context) error { _, dist, err := h.themeService.ActiveDistDir(c.Request().Context()) if err != nil { return err } - return serveStaticFile(c, dist, c.Param("*"), true) + return serveStaticFile(c, dist, c.Param("*"), false) } func (h *WebHandler) ServeSPA(c *echo.Context) error { @@ -74,13 +70,23 @@ func isAdminPage(path string) bool { } func (h *WebHandler) serveAdminIndex(c *echo.Context) error { - path := filepath.Join(assets.WebDir(), "admin", "index.html") - data, err := os.ReadFile(path) - if err != nil { + root := assets.WebDir() + path := filepath.Join(root, "index.html") + if stat, err := os.Stat(path); err != nil || !stat.Mode().IsRegular() { return echo.NewHTTPError(http.StatusInternalServerError, "官方管理前端缺失") } setHTMLHeaders(c) - return c.Blob(http.StatusOK, "text/html; charset=utf-8", data) + return c.FileFS("index.html", os.DirFS(root)) +} + +// ImmutableStaticHeaders 为带内容摘要文件名的前端构建产物设置长期缓存和安全响应头。 +func ImmutableStaticHeaders(next echo.HandlerFunc) echo.HandlerFunc { + return func(c *echo.Context) error { + c.Response().Header().Set("Cache-Control", "public, max-age=31536000, immutable") + c.Response().Header().Set("X-Content-Type-Options", "nosniff") + c.Response().Header().Set("Referrer-Policy", "strict-origin-when-cross-origin") + return next(c) + } } func (h *WebHandler) serveThemeIndex(c *echo.Context) error { diff --git a/internal/handler/web_handler_test.go b/internal/handler/web_handler_test.go index 48fafbd..82a3866 100644 --- a/internal/handler/web_handler_test.go +++ b/internal/handler/web_handler_test.go @@ -91,20 +91,20 @@ func TestResolveStaticPathAndHeaders(t *testing.T) { func TestEchoWildcardRoutesKeepAdminAndAPISeparated(t *testing.T) { webRoot := t.TempDir() - if err := os.MkdirAll(filepath.Join(webRoot, "admin", "assets"), 0o755); err != nil { + if err := os.MkdirAll(filepath.Join(webRoot, "assets"), 0o755); err != nil { t.Fatal(err) } - if err := os.WriteFile(filepath.Join(webRoot, "admin", "assets", "app.js"), []byte("admin"), 0o644); err != nil { + if err := os.WriteFile(filepath.Join(webRoot, "assets", "app.js"), []byte("admin"), 0o644); err != nil { t.Fatal(err) } - if err := os.WriteFile(filepath.Join(webRoot, "admin", "index.html"), []byte("admin"), 0o644); err != nil { + if err := os.WriteFile(filepath.Join(webRoot, "index.html"), []byte("admin"), 0o644); err != nil { t.Fatal(err) } t.Setenv("PIKA_WEB_DIR", webRoot) e := echo.New() handler := &WebHandler{} - e.GET("/admin/assets/*", handler.ServeAdminAsset) + e.Static("/admin/assets/", filepath.Join(webRoot, "assets"), ImmutableStaticHeaders) e.GET("/*", handler.ServeSPA) assetRecorder := httptest.NewRecorder() @@ -112,6 +112,9 @@ func TestEchoWildcardRoutesKeepAdminAndAPISeparated(t *testing.T) { if assetRecorder.Code != http.StatusOK || assetRecorder.Body.String() != "admin" { t.Fatalf("wildcard asset route failed: status=%d body=%q", assetRecorder.Code, assetRecorder.Body.String()) } + if assetRecorder.Header().Get("Cache-Control") != "public, max-age=31536000, immutable" { + t.Fatalf("admin asset missing immutable cache header: %#v", assetRecorder.Header()) + } adminRecorder := httptest.NewRecorder() e.ServeHTTP(adminRecorder, httptest.NewRequest(http.MethodGet, "/admin/agents", nil)) diff --git a/internal/service/theme.go b/internal/service/theme.go index 72e95c4..69d98c0 100644 --- a/internal/service/theme.go +++ b/internal/service/theme.go @@ -83,7 +83,7 @@ var ( themeIDPattern = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$`) reservedThemeIDs = map[string]struct{}{ "default": {}, "admin": {}, "official": {}, "system": {}, - "api": {}, "assets": {}, "theme-assets": {}, + "api": {}, "assets": {}, "t": {}, "theme-assets": {}, } requiredThemeCaps = []string{"server-list", "server-detail", "monitor-list", "monitor-detail"} titleElement = regexp.MustCompile(`(?is)]*)?>.*?`) @@ -123,7 +123,7 @@ func NewThemeService(logger *zap.Logger, propertyService *PropertyService, cfg * logger: logger, propertyService: propertyService, themeDir: themeDir, - defaultThemeDir: "portal", + defaultThemeDir: assets.DefaultThemeDir(), } if err := os.MkdirAll(filepath.Join(themeDir, ".staging"), 0755); err != nil { return nil, fmt.Errorf("创建主题目录失败: %w", err) diff --git a/internal/service/theme_service_test.go b/internal/service/theme_service_test.go index 21e20ef..bf8c674 100644 --- a/internal/service/theme_service_test.go +++ b/internal/service/theme_service_test.go @@ -168,6 +168,7 @@ func TestThemeInstallActivateDeleteLifecycle(t *testing.T) { webRoot := t.TempDir() writeOfficialWebBuild(t, webRoot) t.Setenv("PIKA_WEB_DIR", webRoot) + t.Setenv("PIKA_DEFAULT_THEME_DIR", filepath.Join(webRoot, "default-theme")) themeDir := filepath.Join(t.TempDir(), "themes") database, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) @@ -267,13 +268,10 @@ func makeInstallableThemeZIP(t *testing.T, manifest ThemeManifest) []byte { func writeOfficialWebBuild(t *testing.T, webRoot string) { t.Helper() - if err := os.MkdirAll(filepath.Join(webRoot, "admin", "assets"), 0o755); err != nil { + if err := os.MkdirAll(filepath.Join(webRoot, "assets"), 0o755); err != nil { t.Fatal(err) } - if err := os.MkdirAll(filepath.Join(webRoot, "admin"), 0o755); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(webRoot, "admin", "index.html"), []byte("admin"), 0o644); err != nil { + if err := os.WriteFile(filepath.Join(webRoot, "index.html"), []byte("admin"), 0o644); err != nil { t.Fatal(err) } writeThemeRoot(t, filepath.Join(webRoot, "default-theme"), validTestManifest(DefaultThemeID)) diff --git a/internal/service/theme_util.go b/internal/service/theme_util.go index 10ce42d..eb83790 100644 --- a/internal/service/theme_util.go +++ b/internal/service/theme_util.go @@ -18,13 +18,13 @@ import ( "golang.org/x/text/unicode/norm" ) -// validateOfficialWebBuild 启动时验证官方 web/dist 完整性。 +// validateOfficialWebBuild 启动时验证官方管理前端和默认主题的发布产物完整性。 func validateOfficialWebBuild(webDir, defaultThemeDir string) error { if version.GetVersion() == "dev" && strings.TrimSpace(os.Getenv("PIKA_WEB_DIR")) == "" { return nil } requiredFiles := []string{ - filepath.Join(webDir, "admin", "index.html"), + filepath.Join(webDir, "index.html"), filepath.Join(defaultThemeDir, "pika-theme.json"), filepath.Join(defaultThemeDir, "dist", "index.html"), } @@ -34,9 +34,9 @@ func validateOfficialWebBuild(webDir, defaultThemeDir string) error { return fmt.Errorf("官方 Web 构建缺失: %s", path) } } - assetStat, err := os.Stat(filepath.Join(webDir, "admin", "assets")) + assetStat, err := os.Stat(filepath.Join(webDir, "assets")) if err != nil || !assetStat.IsDir() { - return fmt.Errorf("官方管理静态资源目录缺失: %s", filepath.Join(webDir, "admin", "assets")) + return fmt.Errorf("官方管理静态资源目录缺失: %s", filepath.Join(webDir, "assets")) } manifest, err := loadThemeManifest(filepath.Join(defaultThemeDir, "pika-theme.json")) if err != nil { diff --git a/portal/.gitignore b/portal/.gitignore deleted file mode 100644 index 0e8e171..0000000 --- a/portal/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -node_modules -dist -dist-ssr -*.local -.DS_Store -yarn.lock diff --git a/portal/eslint.config.js b/portal/eslint.config.js deleted file mode 100644 index d9b4352..0000000 --- a/portal/eslint.config.js +++ /dev/null @@ -1,14 +0,0 @@ -import globals from 'globals'; -import tseslint from 'typescript-eslint'; - -export default [ - {ignores: ['dist', 'node_modules']}, - { - files: ['src/**/*.{ts,tsx}'], - languageOptions: { - parser: tseslint.parser, - parserOptions: {ecmaVersion: 'latest', sourceType: 'module', ecmaFeatures: {jsx: true}}, - globals: {...globals.browser, ...globals.es2022}, - }, - }, -]; diff --git a/portal/index.html b/portal/index.html deleted file mode 100644 index 02bcbc6..0000000 --- a/portal/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - Pika Monitor - - - -
- - - - diff --git a/portal/package-lock.json b/portal/package-lock.json deleted file mode 100644 index 141c3e7..0000000 --- a/portal/package-lock.json +++ /dev/null @@ -1,3618 +0,0 @@ -{ - "name": "@pika/default-theme", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@pika/default-theme", - "version": "1.0.0", - "dependencies": { - "@radix-ui/react-tooltip": "^1.2.12", - "@tanstack/react-query": "^5.101.2", - "clsx": "^2.1.1", - "dayjs": "^1.11.21", - "lucide-react": "^1.24.0", - "react": "^19.2.7", - "react-dom": "^19.2.7", - "react-router-dom": "^7.18.1", - "recharts": "^3.9.2", - "tailwind-merge": "^3.6.0", - "tw-animate-css": "^1.4.0" - }, - "devDependencies": { - "@tailwindcss/vite": "^4.3.2", - "@types/node": "^26.1.1", - "@types/react": "^19.2.17", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.3", - "eslint": "^10.7.0", - "globals": "^17.7.0", - "typescript": "~6.0.3", - "typescript-eslint": "^8.63.0", - "vite": "8.1.4" - } - }, - "../theme-sdk": { - "name": "@pika-monitor/theme-sdk", - "version": "1.0.0", - "extraneous": true, - "devDependencies": { - "typescript": "~6.0.3" - }, - "peerDependencies": { - "typescript": ">=5.0.0" - } - }, - "node_modules/@emnapi/core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", - "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.2", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", - "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", - "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", - "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.23.5", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", - "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^3.0.5", - "debug": "^4.3.1", - "minimatch": "^10.2.4" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", - "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^1.2.1" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - } - }, - "node_modules/@eslint/core": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", - "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - } - }, - "node_modules/@eslint/object-schema": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", - "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz", - "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^1.2.1", - "levn": "^0.4.1" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - } - }, - "node_modules/@floating-ui/core": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz", - "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==", - "license": "MIT", - "dependencies": { - "@floating-ui/utils": "^0.2.12" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz", - "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==", - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.8.0", - "@floating-ui/utils": "^0.2.12" - } - }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.9.tgz", - "integrity": "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==", - "license": "MIT", - "dependencies": { - "@floating-ui/dom": "^1.8.0" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz", - "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==", - "license": "MIT" - }, - "node_modules/@humanfs/core": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", - "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/types": "^0.15.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", - "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.2", - "@humanfs/types": "^0.15.0", - "@humanwhocodes/retry": "^0.4.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/types": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", - "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.2.tgz", - "integrity": "sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.3" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=23.5.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.3", - "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.3" - } - }, - "node_modules/@oxc-project/types": { - "version": "0.139.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz", - "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" - } - }, - "node_modules/@radix-ui/primitive": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.7.tgz", - "integrity": "sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q==", - "license": "MIT" - }, - "node_modules/@radix-ui/react-arrow": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.15.tgz", - "integrity": "sha512-v4zggRcjadnI+ClKDuijlQEW4tw3NoaeHc/PwpKnLoLLKNUG4InLegkstooLcRIUWCs+8L22dGURCVuFfOKfnA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.10" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.5.tgz", - "integrity": "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-context": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.2.2.tgz", - "integrity": "sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.19.tgz", - "integrity": "sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.5", - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-use-callback-ref": "1.1.4", - "@radix-ui/react-use-effect-event": "0.0.5" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-id": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.4.tgz", - "integrity": "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popper": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.3.7.tgz", - "integrity": "sha512-UsJrrd7w4wuKKTdvd/DNERVlwSlUcyXzjhyDwBk+3aPOsCjOY6ZSbxuw8E6lZTjjfP8Cpd0J8VVkrYUWyGYXyg==", - "license": "MIT", - "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.15", - "@radix-ui/react-compose-refs": "1.1.5", - "@radix-ui/react-context": "1.2.2", - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-use-callback-ref": "1.1.4", - "@radix-ui/react-use-layout-effect": "1.1.4", - "@radix-ui/react-use-rect": "1.1.4", - "@radix-ui/react-use-size": "1.1.4", - "@radix-ui/rect": "1.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-portal": { - "version": "1.1.17", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.17.tgz", - "integrity": "sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-presence": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.10.tgz", - "integrity": "sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-primitive": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.10.tgz", - "integrity": "sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.3.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-slot": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.3.3.tgz", - "integrity": "sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.5" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tooltip": { - "version": "1.2.16", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.16.tgz", - "integrity": "sha512-6EamKFRRnlpdadndbZ6LMwycfwkwPte1B42hs6QA0gYhjaOKqW4PZ4pjaW9UrlDX5eVt/OjncE7BFTPL5nmZhg==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.5", - "@radix-ui/react-context": "1.2.2", - "@radix-ui/react-dismissable-layer": "1.1.19", - "@radix-ui/react-id": "1.1.4", - "@radix-ui/react-popper": "1.3.7", - "@radix-ui/react-portal": "1.1.17", - "@radix-ui/react-presence": "1.1.10", - "@radix-ui/react-primitive": "2.1.10", - "@radix-ui/react-slot": "1.3.3", - "@radix-ui/react-use-controllable-state": "1.2.6", - "@radix-ui/react-use-layout-effect": "1.1.4", - "@radix-ui/react-visually-hidden": "1.2.11" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.4.tgz", - "integrity": "sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.6.tgz", - "integrity": "sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-use-effect-event": "0.0.5", - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-effect-event": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.5.tgz", - "integrity": "sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.4.tgz", - "integrity": "sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.4.tgz", - "integrity": "sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/rect": "1.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-size": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.4.tgz", - "integrity": "sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.11.tgz", - "integrity": "sha512-NFS86RYYZb4/exihaESBGOpMJFz8MGLAfu3mOBSGByVnVPC9JPASfYubxd/8KbkQK0sYAv8lVQDEQukDX/qXvQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.10" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/rect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.3.tgz", - "integrity": "sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw==", - "license": "MIT" - }, - "node_modules/@reduxjs/toolkit": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.12.0.tgz", - "integrity": "sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw==", - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@standard-schema/utils": "^0.3.0", - "immer": "^11.0.0", - "redux": "^5.0.1", - "redux-thunk": "^3.1.0", - "reselect": "^5.1.0" - }, - "peerDependencies": { - "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", - "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-redux": { - "optional": true - } - } - }, - "node_modules/@rolldown/binding-android-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", - "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz", - "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz", - "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz", - "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz", - "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz", - "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz", - "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz", - "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz", - "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==", - "cpu": [ - "s390x" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz", - "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz", - "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz", - "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz", - "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.11.1", - "@emnapi/runtime": "1.11.1", - "@napi-rs/wasm-runtime": "^1.1.6" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz", - "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz", - "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", - "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "license": "MIT" - }, - "node_modules/@standard-schema/utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", - "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", - "license": "MIT" - }, - "node_modules/@tailwindcss/node": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", - "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "^5.24.1", - "jiti": "^2.7.0", - "lightningcss": "1.32.0", - "magic-string": "^0.30.21", - "source-map-js": "^1.2.1", - "tailwindcss": "4.3.3" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", - "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.3.3", - "@tailwindcss/oxide-darwin-arm64": "4.3.3", - "@tailwindcss/oxide-darwin-x64": "4.3.3", - "@tailwindcss/oxide-freebsd-x64": "4.3.3", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", - "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", - "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", - "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", - "@tailwindcss/oxide-linux-x64-musl": "4.3.3", - "@tailwindcss/oxide-wasm32-wasi": "4.3.3", - "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", - "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", - "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", - "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", - "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", - "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", - "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", - "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", - "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", - "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", - "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", - "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.11.1", - "@emnapi/runtime": "^1.11.1", - "@emnapi/wasi-threads": "^1.2.2", - "@napi-rs/wasm-runtime": "^1.1.4", - "@tybys/wasm-util": "^0.10.2", - "tslib": "^2.8.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { - "version": "1.11.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.2", - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { - "version": "1.11.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", - "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { - "version": "0.10.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "inBundle": true, - "license": "0BSD", - "optional": true - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", - "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", - "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/vite": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.3.tgz", - "integrity": "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tailwindcss/node": "4.3.3", - "@tailwindcss/oxide": "4.3.3", - "tailwindcss": "4.3.3" - }, - "peerDependencies": { - "vite": "^5.2.0 || ^6 || ^7 || ^8" - } - }, - "node_modules/@tanstack/query-core": { - "version": "5.101.4", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.101.4.tgz", - "integrity": "sha512-gNwcvOJcRbLWPOLG/2OBm+zM+Yv+MKsXKEOWC57USuZDEsI71hEErQsiEGx5wX9rzWWkfwM0fVSPoiIFSsxfiw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/react-query": { - "version": "5.101.4", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.101.4.tgz", - "integrity": "sha512-yRg2pfOCxIs4ZJW3XYYHU/WgtD04FHSnfHlpRT7h7pR77hwkdRG4wxbKe4aq6P0RvXUTBSQpQeadS1SUYUe+KA==", - "license": "MIT", - "dependencies": { - "@tanstack/query-core": "5.101.4" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^18 || ^19" - } - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", - "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/d3-array": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", - "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", - "license": "MIT" - }, - "node_modules/@types/d3-color": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", - "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", - "license": "MIT" - }, - "node_modules/@types/d3-ease": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", - "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", - "license": "MIT" - }, - "node_modules/@types/d3-interpolate": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", - "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", - "license": "MIT", - "dependencies": { - "@types/d3-color": "*" - } - }, - "node_modules/@types/d3-path": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", - "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", - "license": "MIT" - }, - "node_modules/@types/d3-scale": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", - "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", - "license": "MIT", - "dependencies": { - "@types/d3-time": "*" - } - }, - "node_modules/@types/d3-shape": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", - "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", - "license": "MIT", - "dependencies": { - "@types/d3-path": "*" - } - }, - "node_modules/@types/d3-time": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", - "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", - "license": "MIT" - }, - "node_modules/@types/d3-timer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", - "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", - "license": "MIT" - }, - "node_modules/@types/esrecurse": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", - "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", - "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "26.1.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.2.tgz", - "integrity": "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~8.3.0" - } - }, - "node_modules/@types/react": { - "version": "19.2.18", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz", - "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.4.tgz", - "integrity": "sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw==", - "devOptional": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.2.0" - } - }, - "node_modules/@types/use-sync-external-store": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", - "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.65.0.tgz", - "integrity": "sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.65.0", - "@typescript-eslint/type-utils": "8.65.0", - "@typescript-eslint/utils": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.65.0", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", - "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.65.0.tgz", - "integrity": "sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.65.0", - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.65.0.tgz", - "integrity": "sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.65.0", - "@typescript-eslint/types": "^8.65.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.65.0.tgz", - "integrity": "sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.65.0.tgz", - "integrity": "sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.65.0.tgz", - "integrity": "sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0", - "@typescript-eslint/utils": "8.65.0", - "debug": "^4.4.3", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.65.0.tgz", - "integrity": "sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.65.0.tgz", - "integrity": "sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.65.0", - "@typescript-eslint/tsconfig-utils": "8.65.0", - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.65.0.tgz", - "integrity": "sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.65.0", - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.65.0.tgz", - "integrity": "sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.65.0", - "eslint-visitor-keys": "^5.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.5.tgz", - "integrity": "sha512-BOVzne/NL162sMdResB25mUv+vWMF5NoAjNf09TeGlE7ZpszZWSD3winycicLJw72yeVsoCn/2kOhEuCvEShMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rolldown/pluginutils": "^1.0.1" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", - "babel-plugin-react-compiler": "^1.0.0", - "vite": "^8.0.0" - }, - "peerDependenciesMeta": { - "@rolldown/plugin-babel": { - "optional": true - }, - "babel-plugin-react-compiler": { - "optional": true - } - } - }, - "node_modules/acorn": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", - "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", - "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/brace-expansion": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", - "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cookie": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", - "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "license": "ISC", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", - "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "license": "ISC", - "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-shape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", - "license": "ISC", - "dependencies": { - "d3-path": "^3.1.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "license": "ISC", - "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/dayjs": { - "version": "1.11.21", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", - "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decimal.js-light": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", - "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", - "license": "MIT" - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.24.5", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", - "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/es-toolkit": { - "version": "1.50.0", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.50.0.tgz", - "integrity": "sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w==", - "license": "MIT", - "workspaces": [ - "docs", - "benchmarks", - "tests/types" - ] - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "10.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.0.tgz", - "integrity": "sha512-nuKKvN+oIBO0koN7Tm7dlkmnkc21mtt0QJLwAKzjLq14y6lRTdVG36MZHJ8eQHwdJMwZbQNMlPOYedMq/oVJvQ==", - "dev": true, - "license": "MIT", - "workspaces": [ - "packages/*" - ], - "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.2", - "@eslint/config-array": "^0.23.5", - "@eslint/config-helpers": "^0.7.0", - "@eslint/core": "^1.2.1", - "@eslint/plugin-kit": "^0.7.2", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "ajv": "^6.14.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^9.1.2", - "eslint-visitor-keys": "^5.0.1", - "espree": "^11.2.0", - "esquery": "^1.7.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "minimatch": "^10.2.5", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", - "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@types/esrecurse": "^4.3.1", - "@types/estree": "^1.0.8", - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", - "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.16.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^5.0.1" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", - "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", - "dev": true, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "17.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.8.0.tgz", - "integrity": "sha512-Zz/LMDZScFmkakeL2cTHzf+PbWKdpU3uclqkZT7TjDG58j5WPt0PpA+n9uPI24fZtlw07q0OtEi84K+umsRzqQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/immer": { - "version": "11.1.15", - "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.15.tgz", - "integrity": "sha512-VrNANlmnWQnh5COXIIOQXM9oOJw7naGKlBT74ZOOR6lpVXc3gFEu9FJLDFcpCJ2j+NWr8TIwtWD//T6ZX6TKiQ==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/jiti": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", - "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" - } - }, - "node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", - "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lucide-react": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.28.0.tgz", - "integrity": "sha512-fARAFJULsGuDDydjp6+6blekG/sBIM29TerzLjc9bQUKAcEfrSc4ZQKb25KRz4OMKd87cZTb5dgq0w/T6KufVg==", - "license": "ISC", - "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/minimatch": { - "version": "10.2.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", - "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.8" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.16", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", - "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.25", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz", - "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.16", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/react": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", - "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", - "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", - "license": "MIT", - "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.8" - } - }, - "node_modules/react-is": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.8.tgz", - "integrity": "sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ==", - "license": "MIT", - "peer": true - }, - "node_modules/react-redux": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz", - "integrity": "sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g==", - "license": "MIT", - "dependencies": { - "@types/use-sync-external-store": "^0.0.6", - "use-sync-external-store": "^1.4.0" - }, - "peerDependencies": { - "@types/react": "^18.2.25 || ^19", - "react": "^18.0 || ^19", - "redux": "^5.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "redux": { - "optional": true - } - } - }, - "node_modules/react-router": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.2.tgz", - "integrity": "sha512-aUVMjFm3GAPTTZL7oYr5E7ETiqfQCHRLH+B+5afnICvf0r7kkK4eR6SMuwbSTJw/7t+12khT/Kahij49fqOCIg==", - "license": "MIT", - "dependencies": { - "cookie": "^1.0.1", - "set-cookie-parser": "^2.6.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - } - } - }, - "node_modules/react-router-dom": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.2.tgz", - "integrity": "sha512-AIKJ/jgGlFb3EbfCXk5Gzshiwt+l3mqbCrNjmEWMMjqQxNJ3svBa6bgzFyCC2Sw3RA0VWF1kg3uQf2OFhxb8hw==", - "license": "MIT", - "dependencies": { - "react-router": "7.18.2" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - } - }, - "node_modules/recharts": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.10.1.tgz", - "integrity": "sha512-QXFrvt6IVcw7eeZCoyXTwkIJAX3Dv1nyVhMicXJ47GsGDDpcN8z6o644DibE9XjpBTThtsomLKnTV6lc+cVFUA==", - "license": "MIT", - "workspaces": [ - "www" - ], - "dependencies": { - "@reduxjs/toolkit": "^1.9.0 || 2.x.x", - "clsx": "^2.1.1", - "decimal.js-light": "^2.5.1", - "es-toolkit": "^1.39.3", - "eventemitter3": "^5.0.1", - "immer": "^11.1.8", - "react-redux": "8.x.x || 9.x.x", - "reselect": "5.2.0", - "tiny-invariant": "^1.3.3", - "use-sync-external-store": "^1.2.2", - "victory-vendor": "^37.0.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/redux": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", - "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT" - }, - "node_modules/redux-thunk": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", - "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", - "license": "MIT", - "peerDependencies": { - "redux": "^5.0.0" - } - }, - "node_modules/reselect": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.2.0.tgz", - "integrity": "sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==", - "license": "MIT" - }, - "node_modules/rolldown": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", - "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@oxc-project/types": "=0.139.0", - "@rolldown/pluginutils": "^1.0.0" - }, - "bin": { - "rolldown": "bin/cli.mjs" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.1.5", - "@rolldown/binding-darwin-arm64": "1.1.5", - "@rolldown/binding-darwin-x64": "1.1.5", - "@rolldown/binding-freebsd-x64": "1.1.5", - "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", - "@rolldown/binding-linux-arm64-gnu": "1.1.5", - "@rolldown/binding-linux-arm64-musl": "1.1.5", - "@rolldown/binding-linux-ppc64-gnu": "1.1.5", - "@rolldown/binding-linux-s390x-gnu": "1.1.5", - "@rolldown/binding-linux-x64-gnu": "1.1.5", - "@rolldown/binding-linux-x64-musl": "1.1.5", - "@rolldown/binding-openharmony-arm64": "1.1.5", - "@rolldown/binding-wasm32-wasi": "1.1.5", - "@rolldown/binding-win32-arm64-msvc": "1.1.5", - "@rolldown/binding-win32-x64-msvc": "1.1.5" - } - }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/set-cookie-parser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", - "license": "MIT" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tailwind-merge": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz", - "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/dcastil" - } - }, - "node_modules/tailwindcss": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", - "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/tapable": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", - "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", - "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/ts-api-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", - "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "optional": true - }, - "node_modules/tw-animate-css": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz", - "integrity": "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Wombosvideo" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/typescript": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", - "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.65.0.tgz", - "integrity": "sha512-/ggrHAwyjENDusvyxbuqxAC2dTnZg/Z8F+fgQtYIz+L6n/9HfSlEZcFGV/NsMNa6CkGk0xUjUAFwC0vHOflvIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.65.0", - "@typescript-eslint/parser": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0", - "@typescript-eslint/utils": "8.65.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/undici-types": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", - "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/use-sync-external-store": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", - "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/victory-vendor": { - "version": "37.3.6", - "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz", - "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==", - "license": "MIT AND ISC", - "dependencies": { - "@types/d3-array": "^3.0.3", - "@types/d3-ease": "^3.0.0", - "@types/d3-interpolate": "^3.0.1", - "@types/d3-scale": "^4.0.2", - "@types/d3-shape": "^3.1.0", - "@types/d3-time": "^3.0.0", - "@types/d3-timer": "^3.0.0", - "d3-array": "^3.1.6", - "d3-ease": "^3.0.1", - "d3-interpolate": "^3.0.1", - "d3-scale": "^4.0.2", - "d3-shape": "^3.1.0", - "d3-time": "^3.0.0", - "d3-timer": "^3.0.1" - } - }, - "node_modules/vite": { - "version": "8.1.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.4.tgz", - "integrity": "sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "lightningcss": "^1.32.0", - "picomatch": "^4.0.5", - "postcss": "^8.5.16", - "rolldown": "~1.1.4", - "tinyglobby": "^0.2.17" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.3.0", - "esbuild": "^0.27.0 || ^0.28.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "@vitejs/devtools": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/portal/package.json b/portal/package.json deleted file mode 100644 index 7375a3f..0000000 --- a/portal/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "@pika/default-theme", - "private": true, - "version": "1.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc -b && vite build", - "lint": "eslint src" - }, - "dependencies": { - "@radix-ui/react-tooltip": "^1.2.12", - "@tanstack/react-query": "^5.101.2", - "clsx": "^2.1.1", - "dayjs": "^1.11.21", - "lucide-react": "^1.24.0", - "react": "^19.2.7", - "react-dom": "^19.2.7", - "react-router-dom": "^7.18.1", - "recharts": "^3.9.2", - "tailwind-merge": "^3.6.0", - "tw-animate-css": "^1.4.0" - }, - "devDependencies": { - "@tailwindcss/vite": "^4.3.2", - "@types/node": "^26.1.1", - "@types/react": "^19.2.17", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.3", - "eslint": "^10.7.0", - "globals": "^17.7.0", - "typescript": "~6.0.3", - "typescript-eslint": "^8.63.0", - "vite": "8.1.4" - } -} diff --git a/portal/pika-theme.json b/portal/pika-theme.json deleted file mode 100644 index 8fcf07a..0000000 --- a/portal/pika-theme.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "schemaVersion": 1, - "id": "default", - "name": "Pika Official", - "description": "Pika 官方默认公开主题", - "version": "1.0.0", - "author": "dushixiang", - "homepage": "https://github.com/dushixiang/pika", - "license": "MIT", - "preview": "dist/logo.png", - "entry": "dist/index.html", - "apiVersion": "v1", - "capabilities": ["server-list", "server-detail", "monitor-list", "monitor-detail"] -} diff --git a/portal/public/logo.png b/portal/public/logo.png deleted file mode 100644 index 0e3c2fde92b217009fe50aa371bcf92eebc9c3c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 231226 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 f{}xlmWX5-(B diff --git a/portal/src/App.tsx b/portal/src/App.tsx deleted file mode 100644 index 5ee5a49..0000000 --- a/portal/src/App.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import {lazy, Suspense} from 'react'; -import {BrowserRouter, Route, Routes} from 'react-router-dom'; -import {ColorModeProvider} from './contexts/ColorMode'; - -const PublicLayout = lazy(() => import('./pages/PublicLayout')); -const ServerList = lazy(() => import('./pages/ServerList')); -const ServerDetail = lazy(() => import('./pages/ServerDetail')); -const MonitorList = lazy(() => import('./pages/MonitorList')); -const MonitorDetail = lazy(() => import('./pages/MonitorDetail')); - -export default function PortalApp() { - return ( - - - 页面加载中...}> - - }> - }/> - }/> - }/> - }/> - - - - - - ); -} diff --git a/portal/src/api.ts b/portal/src/api.ts deleted file mode 100644 index 4cef8b9..0000000 --- a/portal/src/api.ts +++ /dev/null @@ -1,76 +0,0 @@ -/* Pika 公开 API 客户端。自动拼接 /api 前缀并从 localStorage 读取登录 token。 */ - -import type { - PikaRuntimeConfig, ColorMode, - Agent, LatestMetrics, PublicMonitor, AgentMonitorStat, - MetricsResponse, MetricsParams, HistoryParams, - TagsResponse, NetworkInterfacesResponse, ListAgentParams, CurrentUser, -} from './types'; - -export class PikaAPIError extends Error { - constructor(public status: number, message: string, public data?: unknown) { - super(message); - this.name = 'PikaAPIError'; - } -} - -type Query = Record; - -const request = async (path: string, query?: Query): Promise => { - const search = new URLSearchParams(); - for (const [key, value] of Object.entries(query || {})) { - if (value !== undefined) search.set(key, String(value)); - } - const token = typeof localStorage === 'undefined' ? null : localStorage.getItem('token'); - const response = await fetch('/api' + path + (search.size ? '?' + search : ''), { - headers: token ? {Authorization: 'Bearer ' + token} : {}, - }); - const contentType = response.headers.get('content-type') || ''; - const data: unknown = contentType.includes('application/json') ? await response.json() : await response.text(); - if (!response.ok) { - const message = typeof data === 'object' && data !== null && 'message' in data && typeof data.message === 'string' - ? data.message - : 'Pika API 请求失败'; - throw new PikaAPIError(response.status, message, data); - } - return data as T; -}; - -export const pika = { - getConfig: () => request('/config'), - listAgents: (params: ListAgentParams = {}) => request('/agents', params), - getAgent: (id: string) => request('/agents/' + encodeURIComponent(id)), - getLatestMetrics: (id: string) => - request('/agents/' + encodeURIComponent(id) + '/metrics/latest'), - getMetrics: (id: string, params: MetricsParams = {}) => - request('/agents/' + encodeURIComponent(id) + '/metrics', params), - getTags: () => request('/agents/tags'), - getNetworkInterfaces: (id: string) => - request('/agents/' + encodeURIComponent(id) + '/network-interfaces'), - listMonitors: () => request('/monitors'), - getMonitorStats: >(id: string) => - request('/monitors/' + encodeURIComponent(id) + '/stats'), - getMonitorAgents: (id: string) => - request('/monitors/' + encodeURIComponent(id) + '/agents'), - getMonitorHistory: (id: string, params: HistoryParams = {}) => - request('/monitors/' + encodeURIComponent(id) + '/history', params), - getCurrentUser: () => request('/admin/account/info'), -}; - -/* 运行时配置(后端在入口 HTML 注入 window.PikaRuntime) */ - -declare global { - interface Window {PikaRuntime?: PikaRuntimeConfig} -} - -export const getRuntimeConfig = (): PikaRuntimeConfig => { - if (typeof window === 'undefined' || !window.PikaRuntime) { - throw new Error('PikaRuntime 尚未注入'); - } - return window.PikaRuntime; -}; - -export const resolveColorMode = (mode: ColorMode): Exclude => { - if (mode !== 'system') return mode; - return typeof matchMedia !== 'undefined' && matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; -}; diff --git a/portal/src/components.tsx b/portal/src/components.tsx deleted file mode 100644 index 557eda4..0000000 --- a/portal/src/components.tsx +++ /dev/null @@ -1,768 +0,0 @@ -import {type ReactNode, useEffect, useState} from 'react'; -import {Activity, AlertCircle, Heart, Loader2, LogIn, Menu, Moon, ServerIcon, Settings, Sun, TrendingUp, X} from 'lucide-react'; -import {Link, useLocation} from 'react-router-dom'; -import dayjs from 'dayjs'; -import type {TimeRangeOption} from './types'; -import {getRuntimeConfig, pika} from './api'; -import {cn} from './lib/utils'; -import {useColorMode} from './contexts/ColorMode'; - -/* ========================================== Card ========================================== */ - -interface CardProps { - title?: ReactNode; - description?: ReactNode; - action?: ReactNode; - children: ReactNode; - className?: string; - interactive?: boolean; -} - -export const Card = ({title, description, action, children, className, interactive}: CardProps) => { - const hasHeader = title || description || action; - - return ( -
- - - - - {interactive && ( - - )} - -
- {hasHeader && ( -
-
- {title &&

{title}

} - {description &&

{description}

} -
- {action &&
{action}
} -
- )} -
- {children} -
-
-
- ); -}; - -/* ========================================== ChartPlaceholder ========================================== */ - -interface ChartPlaceholderProps { - icon?: typeof TrendingUp; - title?: string; - subtitle?: string; - heightClass?: string; - className?: string; -} - -export const ChartPlaceholder = ({ - icon: Icon = TrendingUp, - title = '暂无数据', - subtitle = '等待采集新数据后展示图表', - heightClass = 'h-52', - className, - }: ChartPlaceholderProps) => { - return ( -
-
- -

{title}

- {subtitle && ( -

- {subtitle} -

- )} -
-
- ); -}; - -/* ========================================== CustomTooltip ========================================== */ - -type CustomTooltipProps = { - active?: boolean; - payload?: Array<{ - name?: string; - value?: number; - color?: string; - dataKey?: string; - payload?: { - timestamp?: number | string; - [key: string]: unknown; - }; - }>; - label?: string | number; - unit?: string; - className?: string; - timeFormat?: string; -}; - -export const CustomTooltip = ({active, payload, label, unit = '%', className, timeFormat = 'MM-DD HH:mm'}: CustomTooltipProps) => { - if (!active || !payload || payload.length === 0) { - return null; - } - - // 从 payload 中获取完整的时间戳信息(如果有的话) - const fullTimestamp = payload[0]?.payload?.timestamp; - const displayLabel = fullTimestamp - ? dayjs(fullTimestamp).format(timeFormat) - : label; - - return ( -
-

- {displayLabel} -

-
- {payload.map((entry, index) => { - if (!entry) { - return null; - } - - const dotColor = entry.color ?? '#6366f1'; - const title = entry.name ?? entry.dataKey ?? `系列 ${index + 1}`; - const value = typeof entry.value === 'number' - ? Number.isFinite(entry.value) - ? entry.value.toFixed(2) - : '-' - : entry.value; - - return ( -

- - - {title}: {value}{unit} - -

- ); - })} -
-
- ); -}; - -/* ========================================== EmptyState ========================================== */ - -interface EmptyStateProps { - message?: string; - showBackButton?: boolean; - className?: string; -} - -export const EmptyState = ({message = '监控数据不存在', showBackButton = false, className}: EmptyStateProps) => { - return ( -
-
-
- -
-

- {message} -

- {showBackButton && ( - - )} -
-
- ); -}; - -/* ========================================== LoadingSpinner ========================================== */ - -interface LoadingSpinnerProps { - message?: string; -} - -export const LoadingSpinner = ({message}: LoadingSpinnerProps) => { - - return ( -
-
- -

- {message || '数据加载中,请稍候...'} -

-
-
- ); -}; - -/* ========================================== MetricItem ========================================== */ - -// 统计卡片组件 -export const MetricItem = ({ - label, - value, - }: { - label: string; - value: string | number; -}) => ( -
-

{label}

-

{value}

-
-); - -/* ========================================== StatBlock ========================================== */ - -// 统计卡片组件 -interface StatBlockProps { - title: string; - value: any; - unit?: string - icon: any; - color: string; - alert?: boolean, - glow?: boolean, -} - -export const StatBlock = ({title, value, unit, icon: Icon, color, alert, glow}: StatBlockProps) => { - - const colorMap = { - cyan: 'dark:text-cyan-400 dark:border-cyan-500/30 dark:bg-cyan-500/5', - emerald: 'dark:text-emerald-400 dark:border-emerald-500/30 dark:bg-emerald-500/5', - rose: 'dark:text-rose-400 dark:border-rose-500/30 dark:bg-rose-500/5', - purple: 'dark:text-purple-400 dark:border-purple-500/30 dark:bg-purple-500/5' - }; - const style = colorMap[color] || colorMap.cyan; - - const iconColor = { - cyan: 'text-cyan-400', - emerald: 'text-emerald-400', - rose: 'text-rose-400', - purple: 'text-purple-400' - } - let iconStyle = iconColor[color] || colorMap.cyan; - - return ( -
-
-
-
-
{title}
-
{value}{unit && - {unit}}
-
-
- -
-
-
- ); -}; - -/* ========================================== StatusBadge ========================================== */ - -interface StatusBadgeProps { - status: string; -} - -export const StatusBadge = ({status}: StatusBadgeProps) => { - const styles = { - up: "bg-emerald-500/10 dark:bg-emerald-500/10 text-emerald-400 dark:text-emerald-400 border-emerald-500/80", - down: "bg-rose-500/10 dark:bg-rose-500/10 text-rose-400 dark:text-rose-400 border-rose-500/80", - unknown: "bg-slate-100 dark:bg-slate-800 text-slate-400 dark:text-slate-300 border-slate-200 dark:border-slate-700", - }; - - const labels = { - up: "正常", - down: "异常", - unknown: "未知", - }; - - const style = styles[status as keyof typeof styles] || styles.unknown; - const label = labels[status as keyof typeof labels] || labels.unknown; - - - return ( - - - {label} - - - - ); -}; - -/* ========================================== PublicHeader ========================================== */ - -export const PublicHeader = () => { - const [isLoggedIn, setIsLoggedIn] = useState(false); - const [currentTime, setCurrentTime] = useState(new Date()); - const [mobileMenuOpen, setMobileMenuOpen] = useState(false); - const {resolvedColorMode: appliedTheme, setColorMode: setTheme} = useColorMode(); - let location = useLocation(); - - - useEffect(() => { - // 检查本地是否有 token - const token = localStorage.getItem('token'); - const userInfo = localStorage.getItem('userInfo'); - - if (!token || !userInfo) { - setIsLoggedIn(false); - return; - } - - // 调用后端接口验证 token 是否有效 - pika.getCurrentUser() - .then(() => { - setIsLoggedIn(true); - }) - .catch(() => { - // token 无效,清除本地存储 - localStorage.removeItem('token'); - localStorage.removeItem('userInfo'); - setIsLoggedIn(false); - }); - }, []); - - // 时钟特效 - useEffect(() => { - const t = setInterval(() => setCurrentTime(new Date()), 1000); - return () => clearInterval(t); - }, []); - - // 判断导航是否激活 - const currentPath = location.pathname; - - let activeTab = 'servers'; - - if (currentPath.startsWith('/monitors')) { - activeTab = 'monitors'; - } - - const runtime = getRuntimeConfig(); - let systemName = runtime.system.nameEn; - - let leftName = ''; - let rightName = ''; - - if (systemName) { - // 优先在空格处分割 - const spaceIndex = systemName.indexOf(' '); - if (spaceIndex > 0) { - leftName = systemName.substring(0, spaceIndex); - rightName = systemName.substring(spaceIndex); // 保留空格 - } else { - // 如果没有空格,从中间分割 - const mid = Math.floor(systemName.length / 2); - leftName = systemName.substring(0, mid); - rightName = systemName.substring(mid); - } - } - - return ( - <> -
- - {/* Mobile Menu */} - {mobileMenuOpen && ( -
-
- {/* Mobile Navigation */} - {[ - {id: 'servers', icon: ServerIcon, label: '设备监控', to: '/'}, - {id: 'monitors', icon: Activity, label: '服务监控', to: '/monitors'} - ].map(tab => ( - setMobileMenuOpen(false)} - className={` - flex items-center gap-3 p-4 rounded-lg border transition-all - ${activeTab === tab.id - ? 'bg-blue-50 dark:bg-cyan-500/20 border-blue-500 dark:border-cyan-500/80 text-blue-600 dark:text-cyan-500' - : 'bg-slate-50/50 dark:bg-cyan-500/5 border-slate-200 dark:border-cyan-500/30 text-slate-600 dark:text-slate-400 hover:bg-blue-50 dark:hover:bg-cyan-500/10 hover:border-blue-300 dark:hover:border-cyan-500/50' - } - `} - > - - {tab.label} - - ))} - - {/* Divider */} -
- - {/* Mobile Theme Toggle Button */} - - - {/* Mobile Login/Admin Button */} - {isLoggedIn ? ( - - - 管理后台 - - ) : ( - - - 登录 - - )} -
-
- )} - - ); -}; - -/* ========================================== PublicFooter ========================================== */ - -export const PublicFooter = () => { - const currentYear = new Date().getFullYear(); - const runtime = getRuntimeConfig(); - const icpCode = runtime.system.icpCode; - - return ( -
-
-
-
-
- © {currentYear} - | - {/* GitHub 链接 */} - - Pika Monitor - - {runtime.system.version} - {/* ICP 备案号 */} - {icpCode && ( - <> - | - - {icpCode} - - - )} -
-
- 用 - - 构建 -
-
-
-
-
-
- ); -}; - -/* ========================================== TimeRangeSelector ========================================== */ - -interface CustomRange { - start: number; - end: number; -} - -interface TimeRangeSelectorProps { - value: string; - onChange: (value: string) => void; - options: readonly TimeRangeOption[]; - enableCustom?: boolean; - customRange?: CustomRange | null; - onCustomRangeApply?: (range: CustomRange) => void; - className?: string; -} - -const parseDateTimeLocal = (value: string): number | null => { - if (!value) return null; - const timestamp = new Date(value).getTime(); - if (Number.isNaN(timestamp)) { - return null; - } - return timestamp; -}; - -const toDateTimeLocal = (timestamp: number): string => { - const date = new Date(timestamp); - const offsetMs = date.getTimezoneOffset() * 60000; - return new Date(timestamp - offsetMs).toISOString().slice(0, 16); -}; - -export const TimeRangeSelector = ({ - value, - onChange, - options, - enableCustom = false, - customRange, - onCustomRangeApply, - className, - }: TimeRangeSelectorProps) => { - const [customStart, setCustomStart] = useState(''); - const [customEnd, setCustomEnd] = useState(''); - - useEffect(() => { - if (customRange?.start) { - setCustomStart(toDateTimeLocal(customRange.start)); - } - if (customRange?.end) { - setCustomEnd(toDateTimeLocal(customRange.end)); - } - }, [customRange]); - - const startMs = parseDateTimeLocal(customStart); - const endMs = parseDateTimeLocal(customEnd); - const canApply = startMs !== null && endMs !== null && startMs < endMs; - const showCustomOption = enableCustom && value === 'custom'; - - return ( -
- - {enableCustom && ( -
- - 自定义 - - setCustomStart(event.target.value)} - className="rounded-lg border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-200 focus:border-blue-400 dark:focus:border-blue-500 focus:ring-2 focus:ring-blue-200 dark:focus:ring-blue-500/30 px-2 py-1 text-xs font-medium" - /> - - 至 - - setCustomEnd(event.target.value)} - className="rounded-lg border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-200 focus:border-blue-400 dark:focus:border-blue-500 focus:ring-2 focus:ring-blue-200 dark:focus:ring-blue-500/30 px-2 py-1 text-xs font-medium" - /> - -
- )} -
- ); -}; diff --git a/portal/src/constants.ts b/portal/src/constants.ts deleted file mode 100644 index 406f60e..0000000 --- a/portal/src/constants.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type {TimeRangeOption} from './types'; - -export const LIVE_RANGE = 'live'; -export const LIVE_INITIAL_RANGE = '2m'; -export const LIVE_WINDOW_MS = 2 * 60 * 1000; - -export const SERVER_TIME_RANGE_OPTIONS: TimeRangeOption[] = [ - {label: '实时', value: LIVE_RANGE}, - {label: '15分钟', value: '15m'}, - {label: '30分钟', value: '30m'}, - {label: '1小时', value: '1h'}, - {label: '3小时', value: '3h'}, - {label: '6小时', value: '6h'}, - {label: '12小时', value: '12h'}, - {label: '1天', value: '1d'}, - {label: '3天', value: '3d'}, - {label: '7天', value: '7d'}, -]; - -export const MONITOR_TIME_RANGE_OPTIONS: TimeRangeOption[] = [ - {label: '12小时', value: '12h'}, - {label: '1天', value: '1d'}, - {label: '3天', value: '3d'}, - {label: '7天', value: '7d'}, -]; - -export const AGENT_COLORS = [ - '#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ec4899', '#06b6d4', '#f97316', '#14b8a6', -]; - -export const INTERFACE_COLORS = [ - {upload: '#6FD598', download: '#2C70F6'}, - {upload: '#f59e0b', download: '#8b5cf6'}, - {upload: '#ec4899', download: '#06b6d4'}, - {upload: '#10b981', download: '#f97316'}, - {upload: '#14b8a6', download: '#2563eb'}, -]; - -export const TEMPERATURE_COLORS: Record = { - 'CPU': '#f97316', 'GPU': '#8b5cf6', 'DISK': '#06b6d4', 'BATTERY': '#10b981', - 'CHIPSET': '#f59e0b', 'SYSTEM': '#6366f1', 'PSU': '#ec4899', -}; - -export const ACCENT_THEMES: Record<'blue' | 'emerald' | 'purple' | 'amber', { icon: string; badge: string; highlight: string }> = { - blue: {icon: 'text-blue-400', badge: 'text-blue-400', highlight: 'text-blue-400'}, - emerald: {icon: 'text-emerald-400', badge: 'text-emerald-400', highlight: 'text-emerald-400'}, - purple: {icon: 'text-purple-400', badge: 'text-purple-400', highlight: 'text-purple-400'}, - amber: {icon: 'text-amber-400', badge: 'text-amber-400', highlight: 'text-amber-400'}, -}; diff --git a/portal/src/contexts/ColorMode.tsx b/portal/src/contexts/ColorMode.tsx deleted file mode 100644 index 676fc8d..0000000 --- a/portal/src/contexts/ColorMode.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import {createContext, useContext, useEffect, useState, type ReactNode} from 'react'; -import {getRuntimeConfig, resolveColorMode} from '../api'; -import type {ColorMode} from '../types'; - -export type ResolvedColorMode = 'light' | 'dark'; - -interface ColorModeContextValue { - colorMode: ColorMode; - resolvedColorMode: ResolvedColorMode; - setColorMode: (mode: ColorMode) => void; -} - -const ColorModeContext = createContext(undefined); - -export const ColorModeProvider = ({children}: {children: ReactNode}) => { - const [colorMode, setColorModeState] = useState(() => { - const saved = localStorage.getItem('colorMode') || localStorage.getItem('theme'); - if (saved === 'auto') return 'system'; - if (saved === 'light' || saved === 'dark' || saved === 'system') return saved; - return getRuntimeConfig().system.defaultColorMode; - }); - const [resolvedColorMode, setResolvedColorMode] = useState('dark'); - - const setColorMode = (mode: ColorMode) => { - setColorModeState(mode); - localStorage.setItem('colorMode', mode); - localStorage.removeItem('theme'); - }; - - useEffect(() => { - const apply = () => { - const resolved = resolveColorMode(colorMode); - setResolvedColorMode(resolved); - document.documentElement.classList.toggle('dark', resolved === 'dark'); - document.documentElement.dataset.colorMode = resolved; - }; - apply(); - if (colorMode !== 'system') return; - const media = window.matchMedia('(prefers-color-scheme: dark)'); - media.addEventListener('change', apply); - return () => media.removeEventListener('change', apply); - }, [colorMode]); - - return ( - - {children} - - ); -}; - -export const useColorMode = () => { - const value = useContext(ColorModeContext); - if (!value) throw new Error('useColorMode must be used within ColorModeProvider'); - return value; -}; diff --git a/portal/src/hooks/index.ts b/portal/src/hooks/index.ts deleted file mode 100644 index 2fada52..0000000 --- a/portal/src/hooks/index.ts +++ /dev/null @@ -1,128 +0,0 @@ -import {useEffect, useRef, useState} from 'react'; -import {useQuery} from '@tanstack/react-query'; -import {pika} from '../api'; -import type {Agent, LatestMetrics, MetricsAggregation, MetricsParams, MetricsResponse} from '../types'; - -interface UseMetricsQueryOptions { - agentId: string; - type: MetricsParams['type']; - range?: string; - start?: number; - end?: number; - interfaceName?: string; - aggregation?: MetricsAggregation; - refetchIntervalMs?: number; -} - -export const useAgentQuery = (agentId?: string) => { - return useQuery({ - queryKey: ['agent', agentId], - queryFn: () => pika.getAgent(agentId!), - enabled: !!agentId, - staleTime: 60000, - }); -}; - -export const useLatestMetricsQuery = (agentId?: string, intervalMs: number = 5000) => { - return useQuery({ - queryKey: ['agent', agentId, 'metrics', 'latest'], - queryFn: () => pika.getLatestMetrics(agentId!), - enabled: !!agentId, - refetchInterval: intervalMs > 0 ? intervalMs : false, - }); -}; - -export const useMetricsQuery = ({agentId, type, range, start, end, interfaceName, aggregation, refetchIntervalMs}: UseMetricsQueryOptions) => { - return useQuery({ - queryKey: ['agent', agentId, 'metrics', type, range, start, end, interfaceName, aggregation], - queryFn: () => - pika.getMetrics(agentId, { - type, - range: start !== undefined && end !== undefined ? undefined : range, - start, - end, - interface: interfaceName, - aggregation, - }), - enabled: !!agentId, - refetchInterval: refetchIntervalMs && refetchIntervalMs > 0 ? refetchIntervalMs : false, - }); -}; - -export const useNetworkInterfacesQuery = (agentId?: string) => { - return useQuery({ - queryKey: ['agent', agentId, 'network-interfaces'], - queryFn: () => pika.getNetworkInterfaces(agentId!), - enabled: !!agentId, - }); -}; - -export function useLiveBuffer( - initial: T[], - isLive: boolean, - livePoint: T | null, - windowMs: number, - resetKey?: unknown, -): T[] { - const [buffer, setBuffer] = useState([]); - const lastTsRef = useRef(0); - const seededRef = useRef(false); - - useEffect(() => { - seededRef.current = false; - lastTsRef.current = 0; - setBuffer([]); - }, [isLive, resetKey]); - - useEffect(() => { - if (!isLive) return; - if (seededRef.current) return; - if (!initial || initial.length === 0) return; - seededRef.current = true; - - const initLastTs = initial[initial.length - 1].timestamp; - setBuffer(prev => { - if (prev.length === 0) { - return initial.slice(); - } - const earliestExisting = prev[0].timestamp; - const olderHistory = initial.filter(p => p.timestamp < earliestExisting); - return olderHistory.length > 0 ? [...olderHistory, ...prev] : prev; - }); - if (initLastTs > lastTsRef.current) { - lastTsRef.current = initLastTs; - } - }, [isLive, initial, resetKey]); - - useEffect(() => { - if (!isLive || !livePoint) return; - const ts = livePoint.timestamp; - if (!Number.isFinite(ts) || ts <= 0) return; - if (ts <= lastTsRef.current) return; - lastTsRef.current = ts; - - setBuffer(prev => { - const next = prev.length === 0 ? [livePoint] : [...prev, livePoint]; - const cutoff = ts - windowMs; - let drop = 0; - while (drop < next.length && next[drop].timestamp < cutoff) drop++; - return drop > 0 ? next.slice(drop) : next; - }); - }, [livePoint, isLive, windowMs]); - - return isLive ? buffer : initial; -} - -const MOBILE_BREAKPOINT = 768; - -export function useIsMobile() { - const [isMobile, setIsMobile] = useState(undefined); - useEffect(() => { - const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); - const onChange = () => setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); - mql.addEventListener('change', onChange); - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); - return () => mql.removeEventListener('change', onChange); - }, []); - return !!isMobile; -} diff --git a/portal/src/index.css b/portal/src/index.css deleted file mode 100644 index 7f04aa2..0000000 --- a/portal/src/index.css +++ /dev/null @@ -1,169 +0,0 @@ -@import "tailwindcss"; -@import "tw-animate-css"; - -@custom-variant dark (&:is(.dark *)); - -/* Tailwind v4 暗色模式配置 */ -@variant dark (&:where(.dark, .dark *)); - -/* 标签过滤器滚动条样式 */ -.tag-filter-scrollbar { - scrollbar-width: thin; - scrollbar-color: rgb(203, 213, 225) transparent; - scrollbar-gutter: stable; -} - -.tag-filter-scrollbar::-webkit-scrollbar { - height: 6px; -} - -.tag-filter-scrollbar::-webkit-scrollbar-track { - background: rgb(241, 245, 249); - border-radius: 9999px; -} - -.tag-filter-scrollbar::-webkit-scrollbar-thumb { - background: rgb(203, 213, 225); - border-radius: 9999px; - transition: background-color 0.2s; -} - -.tag-filter-scrollbar::-webkit-scrollbar-thumb:hover { - background: rgb(148, 163, 184); -} - -/* 暗色模式标签过滤器滚动条 */ -.dark .tag-filter-scrollbar { - scrollbar-color: rgb(71, 85, 105) transparent; -} - -.dark .tag-filter-scrollbar::-webkit-scrollbar-track { - background: rgb(30, 41, 59); -} - -.dark .tag-filter-scrollbar::-webkit-scrollbar-thumb { - background: rgb(71, 85, 105); -} - -.dark .tag-filter-scrollbar::-webkit-scrollbar-thumb:hover { - background: rgb(100, 116, 139); -} - -@theme inline { - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); - --radius-2xl: calc(var(--radius) + 8px); - --radius-3xl: calc(var(--radius) + 12px); - --radius-4xl: calc(var(--radius) + 16px); - --color-background: var(--background); - --color-foreground: var(--foreground); - --color-card: var(--card); - --color-card-foreground: var(--card-foreground); - --color-popover: var(--popover); - --color-popover-foreground: var(--popover-foreground); - --color-primary: var(--primary); - --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); - --color-secondary-foreground: var(--secondary-foreground); - --color-muted: var(--muted); - --color-muted-foreground: var(--muted-foreground); - --color-accent: var(--accent); - --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); - --color-border: var(--border); - --color-input: var(--input); - --color-ring: var(--ring); - --color-chart-1: var(--chart-1); - --color-chart-2: var(--chart-2); - --color-chart-3: var(--chart-3); - --color-chart-4: var(--chart-4); - --color-chart-5: var(--chart-5); - --color-sidebar: var(--sidebar); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-ring: var(--sidebar-ring); -} - -:root { - --radius: 0.625rem; - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.205 0 0); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.97 0 0); - --sidebar-accent-foreground: oklch(0.205 0 0); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); -} - -.dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.556 0 0); -} - -@layer base { - * { - @apply border-border outline-ring/50; - } - body { - @apply bg-background text-foreground; - } -} \ No newline at end of file diff --git a/portal/src/lib/utils.ts b/portal/src/lib/utils.ts deleted file mode 100644 index 8974321..0000000 --- a/portal/src/lib/utils.ts +++ /dev/null @@ -1,71 +0,0 @@ -import {type ClassValue, clsx} from 'clsx'; -import {twMerge} from 'tailwind-merge'; - -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} - -export const formatBytes = (value: number | undefined | null, precision = 2): string => { - if (value === undefined || value === null || !Number.isFinite(value) || value <= 0) return '0 B'; - const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; - const index = Math.min(Math.floor(Math.log(value) / Math.log(1024)), units.length - 1); - return `${(value / 1024 ** index).toFixed(precision)} ${units[index]}`; -}; - -export const formatSpeed = (bytesPerSecond: number): string => { - if (!Number.isFinite(bytesPerSecond) || bytesPerSecond <= 0) return '0 B/s'; - const units = ['B/s', 'K/s', 'M/s', 'G/s', 'T/s']; - const index = Math.min(Math.floor(Math.log(bytesPerSecond) / Math.log(1024)), units.length - 1); - const value = bytesPerSecond / 1024 ** index; - const decimals = value >= 100 ? 0 : value >= 10 ? 1 : 2; - return `${value.toFixed(decimals)} ${units[index]}`; -}; - -export const formatTime = (milliseconds: number): string => { - if (!Number.isFinite(milliseconds) || milliseconds <= 0) return '0 ms'; - if (milliseconds < 1000) return `${milliseconds.toFixed(0)} ms`; - return `${(milliseconds / 1000).toFixed(2)} s`; -}; - -export const formatDateTime = (value: string | number | undefined | null): string => { - if (value === undefined || value === null || value === '') return '-'; - const date = new Date(value); - if (Number.isNaN(date.getTime())) return '-'; - const pad = (part: number) => String(part).padStart(2, '0'); - return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`; -}; - -export const formatPercentValue = (value: number | undefined | null): string => { - if (value === undefined || value === null || Number.isNaN(value)) return '0.0'; - return value.toFixed(1); -}; - -export const formatUptime = (seconds: number | undefined | null): string => { - if (seconds === undefined || seconds === null) return '-'; - if (seconds <= 0) return '0 秒'; - const days = Math.floor(seconds / 86400); - const hours = Math.floor((seconds % 86400) / 3600); - const minutes = Math.floor((seconds % 3600) / 60); - if (days > 0) return `${days} 天${hours > 0 ? ` ${hours} 小时` : ''}`; - if (hours > 0) return `${hours} 小时${minutes > 0 ? ` ${minutes} 分钟` : ''}`; - return minutes > 0 ? `${minutes} 分钟` : '不到 1 分钟'; -}; - -export const formatChartTime = (timestamp: number, timeRange: string, rangeMs?: number): string => { - const date = new Date(timestamp); - if (timeRange === 'live') { - return date.toLocaleTimeString('zh-CN', {hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false}); - } - const isLongRange = rangeMs !== undefined - ? rangeMs >= 24 * 60 * 60 * 1000 - : timeRange === '1d' || timeRange === '24h' || (timeRange.endsWith('d') && Number.parseInt(timeRange) > 1); - if (isLongRange) { - const pad = (part: number) => String(part).padStart(2, '0'); - return `${pad(date.getMonth() + 1)}/${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`; - } - return date.toLocaleTimeString('zh-CN', {hour: '2-digit', minute: '2-digit'}); -}; - -export const isExpired = (expireTime?: number) => { - return Boolean(expireTime && expireTime > 0 && expireTime - Date.now() < 30 * 24 * 60 * 60 * 1000); -}; diff --git a/portal/src/main.tsx b/portal/src/main.tsx deleted file mode 100644 index 23ad142..0000000 --- a/portal/src/main.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import {StrictMode} from 'react'; -import {createRoot} from 'react-dom/client'; -import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; -import {pika} from './api'; -import type {PikaRuntimeConfig} from './types'; -import PortalApp from './App'; -import './index.css'; - -const fallbackRuntime: PikaRuntimeConfig = { - apiVersion: 'v1', - system: { - nameZh: '皮卡监控', - nameEn: 'Pika Monitor', - logo: '/api/logo', - icpCode: '', - version: '', - defaultView: 'grid', - defaultColorMode: 'system', - }, - theme: {id: 'default', version: '1.0.0'}, - features: { - serverList: true, - serverDetail: true, - monitorList: true, - monitorDetail: true, - }, -}; - -const start = async () => { - if (!window.PikaRuntime) { - try { - window.PikaRuntime = await pika.getConfig(); - } catch (error) { - window.PikaRuntime = fallbackRuntime; - console.error(error); - } - } - - const queryClient = new QueryClient({ - defaultOptions: {queries: {refetchOnWindowFocus: false, retry: 1}}, - }); - createRoot(document.getElementById('root')!).render( - - - - - , - ); -}; - -start().catch(console.error); diff --git a/portal/src/pages/MonitorDetail.tsx b/portal/src/pages/MonitorDetail.tsx deleted file mode 100644 index 41377b9..0000000 --- a/portal/src/pages/MonitorDetail.tsx +++ /dev/null @@ -1,795 +0,0 @@ -import {useEffect, useMemo, useState} from 'react'; -import {useNavigate, useParams} from 'react-router-dom'; -import {useQuery} from '@tanstack/react-query'; -import {Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis} from 'recharts'; -import {AlertCircle, ArrowLeft, ChevronDown, ChevronUp, Clock, Globe, MapPin, RotateCcw, Server, ShieldCheck, Wifi} from 'lucide-react'; -import {pika} from '../api'; -import type {AgentMonitorStat, MetricsResponse, PublicMonitor} from '../types'; -import {AGENT_COLORS, MONITOR_TIME_RANGE_OPTIONS} from '../constants'; -import {cn, formatChartTime, formatDateTime, formatTime} from '../lib/utils'; -import {useIsMobile} from '../hooks'; -import { - Card, - ChartPlaceholder, - CustomTooltip, - EmptyState, - LoadingSpinner, - MetricItem, - StatusBadge, - TimeRangeSelector -} from '../components'; - -/* ========================================== TypeIcon ========================================== */ - -const TypeIcon = ({type}: {type: string}) => { - switch (type.toLowerCase()) { - case 'https': - return ; - case 'http': - return ; - case 'tcp': - return ; - case 'icmp': - case 'ping': - return ; - default: - return ; - } -}; - -/* ========================================== CertBadge ========================================== */ - -const CertBadge = ({expiryTime, daysLeft}: {expiryTime: number; daysLeft: number}) => { - if (!expiryTime || daysLeft === undefined) return null; - - const isExpired = daysLeft < 0; - let colorClass = "text-emerald-600 dark:text-emerald-400 bg-emerald-50 dark:bg-emerald-500/10 border-emerald-200 dark:border-emerald-500/20"; - - if (isExpired) { - colorClass = "text-rose-600 dark:text-rose-400 bg-rose-50 dark:bg-rose-500/10 border-rose-200 dark:border-rose-500/20"; - } else if (daysLeft < 30) { - colorClass = "text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-500/10 border-amber-200 dark:border-amber-500/20"; - } - - return ( -
- - {isExpired ? "已过期" : `${daysLeft} 天后过期`} -
- ); -}; - -/* ========================================== MonitorHero ========================================== */ - -interface MonitorHeroProps { - monitor: PublicMonitor; - onBack: () => void; -} - -const MonitorHero = ({monitor, onBack}: MonitorHeroProps) => { - return ( - - {/* 返回按钮 */} - - - {/* 监控信息 */} -
-
-
- -
-
-
-

{monitor.name}

- -
-

- {monitor.showTargetPublic ? monitor.target : '******'} -

-
-
- - {/* 统计卡片 */} -
- - - - -
-
- - {/* 证书信息(如果存在证书数据)*/} - {monitor.certExpiryTime > 0 && ( -
- SSL 证书: -
- - - 到期时间: {formatDateTime(monitor.certExpiryTime)} - -
-
- )} -
- ); -}; - -/* ========================================== AgentStatsTable ========================================== */ - -interface AgentStatsTableProps { - monitorStats: AgentMonitorStat[]; - monitorType: string; -} - -const AgentStatsTable = ({monitorStats, monitorType}: AgentStatsTableProps) => { - if (monitorStats.length === 0) { - return ( -
-

暂无探针数据

-
- ); - } - - return ( - -
-

探针监控详情

-

各探针的当前状态和统计数据

-
- - {/* 移动端卡片布局 */} -
- {monitorStats.map((stat, index) => { - const color = AGENT_COLORS[index % AGENT_COLORS.length]; - return ( -
- {/* 探针名称和状态 */} -
-
- - - - {stat.agentName || stat.agentId.substring(0, 8)} - -
- -
- - {/* 响应时间和最后检测 */} -
-
- - - {formatTime(stat.responseTime)} - -
- - {formatDateTime(stat.checkedAt)} - -
- - {/* 证书信息 */} - {monitorType === 'https' && stat.certExpiryTime && ( -
-
- 证书: - -
-
- )} - - {/* 错误信息 */} - {stat.status === 'down' && stat.message && ( -
-
- - - {stat.message} - -
-
- )} -
- ); - })} -
- - {/* 桌面端表格布局 */} -
- - - - - - - - {monitorType === 'https' && ( - - )} - - - - - {monitorStats.map((stat, index) => { - const color = AGENT_COLORS[index % AGENT_COLORS.length]; - return ( - - - - - - {monitorType === 'https' && ( - - )} - - - ); - })} - -
- 探针名称 - - 状态 - - 响应时间 - - 最后检测 - - 证书信息 - - 错误信息 -
-
- -
- - - {stat.agentName || stat.agentId.substring(0, 8)} - -
-
-
- - -
- - - {formatTime(stat.responseTime)} - -
-
- {formatDateTime(stat.checkedAt)} - - {stat.certExpiryTime ? ( - - ) : ( - - - )} - - {stat.status === 'down' && stat.message ? ( -
- - - {stat.message} - -
- ) : ( - - - )} -
-
-
- ); -}; - -/* ========================================== ResponseTimeChart ========================================== */ - -/** - * 根据时间范围确定最大数据点数 - */ -const getMaxDataPoints = (timeRange: string): number => { - switch (timeRange) { - case '15m': - case '1h': - return 200; // 短时间:详细数据 - case '12h': - return 300; - case '24h': - return 400; - case '7d': - return 500; - case '30d': - return 600; - default: - return 400; - } -}; - -/** - * 生成不重复的颜色 - * 使用 HSL 色轮均匀分布,支持无限数量的探针 - */ -const generateColors = (count: number): string[] => { - const colors: string[] = []; - const hueStep = 360 / count; - - for (let i = 0; i < count; i++) { - const hue = (i * hueStep) % 360; - const saturation = 65 + (i % 3) * 10; - const lightness = 45 + (i % 2) * 10; - colors.push(`hsl(${hue}, ${saturation}%, ${lightness}%)`); - } - - return colors; -}; - -/** - * 自定义图例组件 - */ -const CustomLegend = ({onClick, selectedAgents, allAgents, colors, collapsed}: any) => { - if (!allAgents || allAgents.length === 0) return null; - - if (collapsed) return null; - - return ( -
- {allAgents.map((agent: {id: string; name: string}, index: number) => { - const isSelected = selectedAgents.has(agent.id); - const color = colors[index]; - - return ( -
onClick(agent.id)} - className="flex items-center gap-2 cursor-pointer transition-opacity" - style={{ - opacity: isSelected ? 1 : 0.4, - }} - > - - - - - {agent.name} - -
- ); - })} -
- ); -}; - -interface ResponseTimeChartProps { - monitorId: string; - monitorStats: AgentMonitorStat[]; -} - -const ResponseTimeChart = ({monitorId, monitorStats}: ResponseTimeChartProps) => { - const [selectedAgents, setSelectedAgents] = useState>(new Set()); - const [timeRange, setTimeRange] = useState('12h'); - const [customRange, setCustomRange] = useState<{start: number; end: number} | null>(null); - const [legendCollapsed, setLegendCollapsed] = useState(true); // 移动端默认收起 - const isMobile = useIsMobile(); - const customStart = timeRange === 'custom' ? customRange?.start : undefined; - const customEnd = timeRange === 'custom' ? customRange?.end : undefined; - const rangeMs = customStart !== undefined && customEnd !== undefined ? customEnd - customStart : undefined; - - // 获取历史数据 - const {data: historyData} = useQuery({ - queryKey: ['monitorHistory', monitorId, timeRange, customStart, customEnd], - queryFn: async () => { - if (!monitorId) throw new Error('Monitor ID is required'); - return pika.getMonitorHistory(monitorId, { - range: timeRange, - start: customStart, - end: customEnd, - }); - }, - refetchInterval: 30000, - enabled: !!monitorId, - }); - - // 获取所有可用的探针列表 - const availableAgents = useMemo(() => { - if (monitorStats.length === 0) return []; - return monitorStats.map(stat => ({ - id: stat.agentId, - name: stat.agentName || stat.agentId.substring(0, 8), - })); - }, [monitorStats]); - - // 初始化选中所有探针 - useEffect(() => { - if (availableAgents.length > 0 && selectedAgents.size === 0) { - setSelectedAgents(new Set(availableAgents.map(a => a.id))); - } - }, [availableAgents, selectedAgents.size]); - - // 动态生成颜色 - const colors = useMemo(() => { - return generateColors(availableAgents.length); - }, [availableAgents.length]); - - const toggleAgent = (agentId: string) => { - setSelectedAgents((current) => { - if (current.size === availableAgents.length) return new Set([agentId]); - const next = new Set(current); - if (next.has(agentId)) next.delete(agentId); - else next.add(agentId); - return next; - }); - }; - - const handleAreaClick = (data: unknown) => { - const key = (data as {dataKey?: string})?.dataKey; - if (key) toggleAgent(key.replace('agent_', '')); - }; - - // 恢复全选 - const handleSelectAll = () => { - setSelectedAgents(new Set(availableAgents.map(a => a.id))); - }; - - // 是否有探针未选中 - const hasUnselected = selectedAgents.size < availableAgents.length; - - // 切换图例显示/隐藏(仅移动端) - const toggleLegend = () => setLegendCollapsed((collapsed) => !collapsed); - - // 生成图表数据 - 使用统一时间网格对齐 - const chartData = useMemo(() => { - if (!historyData?.series) return []; - - const seriesList = historyData.series.filter(s => s.name === 'response_time'); - if (seriesList.length === 0) return []; - - // 收集所有选中探针的数据 - const selectedSeriesData: Array<{key: string; data: Array<{timestamp: number; value: number}>}> = []; - - seriesList.forEach((s) => { - const agentId = s.labels?.agent_id || 'unknown'; - if (!selectedAgents.has(agentId)) return; - if (!s.data || s.data.length === 0) return; - - selectedSeriesData.push({ - key: `agent_${agentId}`, - data: [...s.data].sort((a, b) => a.timestamp - b.timestamp) - }); - }); - - if (selectedSeriesData.length === 0) return []; - - // 确定全局时间范围 - let minTime = Infinity, maxTime = -Infinity; - selectedSeriesData.forEach(s => { - minTime = Math.min(minTime, s.data[0].timestamp); - maxTime = Math.max(maxTime, s.data[s.data.length - 1].timestamp); - }); - - if (minTime >= maxTime) return []; - - // 生成均匀的目标时间点 - const maxPoints = getMaxDataPoints(timeRange); - const timeStep = (maxTime - minTime) / (maxPoints - 1); - const targetTimestamps: number[] = []; - for (let i = 0; i < maxPoints; i++) { - targetTimestamps.push(minTime + i * timeStep); - } - - // 线性插值函数 - const interpolate = (data: Array<{timestamp: number; value: number}>, targetTime: number): number | null => { - if (data.length === 0) return null; - if (data.length === 1) return data[0].timestamp === targetTime ? data[0].value : null; - - // 超出范围不插值(防止产生虚假连线) - if (targetTime < data[0].timestamp || targetTime > data[data.length - 1].timestamp) { - // 如果距离最近的点足够近(比如小于两个采样间隔),可以考虑保留,否则返回null - return null; - } - - // 二分查找 - let left = 0, right = data.length - 1; - while (right - left > 1) { - const mid = Math.floor((left + right) / 2); - if (data[mid].timestamp <= targetTime) { - left = mid; - } else { - right = mid; - } - } - - const leftPoint = data[left]; - const rightPoint = data[right]; - const ratio = (targetTime - leftPoint.timestamp) / (rightPoint.timestamp - leftPoint.timestamp); - return leftPoint.value + ratio * (rightPoint.value - leftPoint.value); - }; - - // 对齐所有探针数据 - return targetTimestamps.map(timestamp => { - const dataPoint: any = {timestamp}; - selectedSeriesData.forEach(s => { - const value = interpolate(s.data, timestamp); - if (value !== null) { - dataPoint[s.key] = Number(value.toFixed(2)); - } - }); - return dataPoint; - }); - }, [historyData, selectedAgents, timeRange, customStart, customEnd]); - - return ( - -
-
-

响应时间趋势

-

监控各探针的响应时间变化

-
-
- { - setCustomRange(range); - }} - /> -
-
- - {/* 使用提示和恢复按钮 */} - {availableAgents.length > 0 && ( -
-
- 💡 点击图表线条或图例切换显示 -
- {hasUnselected && ( - - )} -
- )} - - {chartData.length > 0 ? ( -
- - - - {Array.from(selectedAgents).map((agentId, index) => { - const originalIndex = availableAgents.findIndex(a => a.id === agentId); - const agentKey = `agent_${agentId}`; - return ( - - - - - ); - })} - - - formatChartTime(Number(value), timeRange, rangeMs)} - className="text-xs text-gray-600 dark:text-cyan-500 font-mono" - stroke="currentColor" - tickLine={false} - axisLine={false} - angle={-15} - textAnchor="end" - /> - `${value}ms`} - /> - } - wrapperStyle={{zIndex: 9999}} - /> - {Array.from(selectedAgents).map((agentId) => { - const originalIndex = availableAgents.findIndex(a => a.id === agentId); - const agentKey = `agent_${agentId}`; - const agent = availableAgents.find(a => a.id === agentId); - return ( - - ); - })} - - - - {/* 桌面端:直接显示图例 */} - {!isMobile && availableAgents.length > 0 && ( - - )} - - {/* 移动端:可折叠图例 */} - {isMobile && availableAgents.length > 0 && ( -
- - -
- )} -
- ) : ( - - )} -
- ); -}; - -/* ========================================== MonitorDetail ========================================== */ - -/** - * 监控详情页面 - * 显示监控的详细信息、响应时间趋势和各探针统计 - */ -const MonitorDetail = () => { - const navigate = useNavigate(); - const {id} = useParams<{id: string}>(); - - // 获取监控详情(聚合数据) - const {data: monitorDetail, isLoading} = useQuery({ - queryKey: ['monitorDetail', id], - queryFn: async () => { - if (!id) throw new Error('Monitor ID is required'); - return pika.getMonitorStats(id); - }, - refetchInterval: 30000, - enabled: !!id, - }); - - // 获取各探针的统计数据 - const {data: monitorStats = []} = useQuery({ - queryKey: ['monitorAgentStats', id], - queryFn: async () => { - if (!id) return []; - return pika.getMonitorAgents(id); - }, - refetchInterval: 30000, - enabled: !!id, - }); - - if (isLoading) { - return ; - } - - if (!monitorDetail) { - return ; - } - - return ( -
-
- {/* 头部区域 */} - navigate('/monitors')} - /> - - {/* 主内容区 */} -
- {/* 响应时间趋势图表 */} - - - {/* 各探针详细数据 */} - -
-
-
- ); -}; - -export default MonitorDetail; diff --git a/portal/src/pages/MonitorList.tsx b/portal/src/pages/MonitorList.tsx deleted file mode 100644 index c258027..0000000 --- a/portal/src/pages/MonitorList.tsx +++ /dev/null @@ -1,431 +0,0 @@ -import {useEffect, useMemo, useState} from 'react'; -import {Link} from 'react-router-dom'; -import {useQuery} from '@tanstack/react-query'; -import {AlertTriangle, BarChart3, CheckCircle2, Globe, Loader2, Maximize2, Search, Server, Shield, ShieldCheck, Wifi, Zap} from 'lucide-react'; -import {Area, AreaChart, ResponsiveContainer} from 'recharts'; -import {pika} from '../api'; -import type {MetricsResponse, PublicMonitor} from '../types'; -import {cn, formatDateTime} from '../lib/utils'; -import {Card, StatBlock, StatusBadge} from '../components'; - -/* ========================================== TypeIcon ========================================== */ - -const TypeIcon = ({type}: {type: string}) => { - switch (type.toLowerCase()) { - case 'https': - return ; - case 'http': - return ; - case 'tcp': - return ; - case 'icmp': - case 'ping': - return ; - default: - return ; - } -}; - -/* ========================================== CertBadge ========================================== */ - -const CertBadge = ({expiryTime, daysLeft}: {expiryTime: number; daysLeft: number}) => { - if (!expiryTime || daysLeft === undefined) return null; - - const isExpired = daysLeft < 0; - let colorClass = "text-emerald-600 dark:text-emerald-400 bg-emerald-50 dark:bg-emerald-500/10 border-emerald-200 dark:border-emerald-500/20"; - - if (isExpired) { - colorClass = "text-rose-600 dark:text-rose-400 bg-rose-50 dark:bg-rose-500/10 border-rose-200 dark:border-rose-500/20"; - } else if (daysLeft < 30) { - colorClass = "text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-500/10 border-amber-200 dark:border-amber-500/20"; - } - - return ( -
- - {isExpired ? "已过期" : `${daysLeft} 天后过期`} -
- ); -}; - -/* ========================================== MonitorCard ========================================== */ - -export type DisplayMode = 'avg' | 'max'; - -const MiniChart = ({data, lastValue, id}: { - data: Array<{timestamp: number; value: number}>; - lastValue?: number; - id: string; -}) => { - const chartData = useMemo(() => [...data].sort((a, b) => a.timestamp - b.timestamp), [data]); - if (chartData.length === 0) { - return
暂无数据
; - } - - const color = lastValue && lastValue <= 200 ? '#22d3ee' : '#fbbf24'; - return ( -
- - - - - - - - - - - - - - - - - - -
- ); -}; - -const MonitorCard = ({monitor, displayMode}: { - monitor: PublicMonitor; - displayMode: DisplayMode; -}) => { - // 为每个监控卡片查询历史数据 - const {data: historyData} = useQuery({ - queryKey: ['monitorHistory', monitor.id, '12h'], // 对应后端 60 秒步长 - queryFn: async () => { - return pika.getMonitorHistory(monitor.id, {range: '1h'}); - }, - refetchInterval: 60000, - staleTime: 30000, - }); - - // 转换时序数据为图表数据 - 使用统一格点对该对齐多探针数据 - const chartData = useMemo(() => { - if (!historyData?.series || historyData.series.length === 0) { - return []; - } - - const validSeries = historyData.series.filter(s => s.data && s.data.length > 0); - if (validSeries.length === 0) return []; - - // 确定全局时间范围 - let minTime = Infinity, maxTime = -Infinity; - validSeries.forEach(s => { - minTime = Math.min(minTime, s.data![0].timestamp); - maxTime = Math.max(maxTime, s.data![s.data!.length - 1].timestamp); - }); - - if (minTime >= maxTime) return []; - - // 定义目标采集点 (1小时数据,建议 60 个采集点) - const maxPoints = 60; - const timeStep = (maxTime - minTime) / (maxPoints - 1); - const targetTimestamps: number[] = []; - for (let i = 0; i < maxPoints; i++) { - targetTimestamps.push(minTime + i * timeStep); - } - - // 线性插值函数 - const interpolate = (data: Array<{ timestamp: number; value: number }>, targetTime: number): number | null => { - if (data.length === 0) return null; - if (data.length === 1) return data[0].timestamp === targetTime ? data[0].value : null; - if (targetTime < data[0].timestamp || targetTime > data[data.length - 1].timestamp) return null; - - let left = 0, right = data.length - 1; - while (right - left > 1) { - const mid = Math.floor((left + right) / 2); - if (data[mid].timestamp <= targetTime) left = mid; - else right = mid; - } - const leftPoint = data[left]; - const rightPoint = data[right]; - const ratio = (targetTime - leftPoint.timestamp) / (rightPoint.timestamp - leftPoint.timestamp); - return leftPoint.value + ratio * (rightPoint.value - leftPoint.value); - }; - - // 对每个目标时间点,计算所有探针的聚合值 - return targetTimestamps.map(timestamp => { - const values: number[] = []; - validSeries.forEach(s => { - const val = interpolate(s.data!, timestamp); - if (val !== null) values.push(val); - }); - - if (values.length === 0) return { timestamp, value: 0 }; - - return { - timestamp, - value: displayMode === 'avg' - ? Math.round(values.reduce((a, b) => a + b, 0) / values.length) - : Math.max(...values), - }; - }); - }, [historyData, displayMode]); - - const displayValue = displayMode === 'avg' ? monitor.responseTime : monitor.responseTimeMax; - const displayLabel = displayMode === 'avg' ? '平均延迟' : '最差节点延迟'; - - return ( - - {/* 头部 */} -
-
-
- -
-
-

- {monitor.name} -

-
- {monitor.target} -
-
-
-
- -
-
- - {/* 指标信息 */} -
-
-

- {displayLabel} - {monitor.agentCount > 0 && ( - - {monitor.agentCount} 节点 - - )} -

-
200 ? 'text-amber-600 dark:text-amber-400 drop-shadow-[0_0_8px_rgba(251,191,36,0.3)] dark:drop-shadow-[0_0_8px_rgba(251,191,36,0.5)]' : 'text-slate-800 dark:text-white drop-shadow-none dark:drop-shadow-[0_0_8px_rgba(34,211,238,0.5)]'}`}> - {displayValue}ms -
-
-
- {monitor.type === 'https' && monitor.certExpiryTime ? ( - <> -

SSL 证书

- - - ) : ( - <> -

上次检测

-

- {formatDateTime(monitor.lastCheckTime)} -

- - )} -
-
- - {/* 迷你走势图 */} - -
- ); -}; - -/* ========================================== MonitorList 本地组件 ========================================== */ - -const MonitorListSpinner = () => ( -
-
- - 加载监控数据中... -
-
-); - -const MonitorListEmpty = () => ( -
- -

暂无监控数据

-

请先在管理后台添加监控任务

-
-); - - -interface Stats { - total: number; - online: number; - issues: number; - avgLatency: number; -} - -/* ========================================== MonitorList ========================================== */ - -const MonitorList = () => { - const [searchKeyword, setSearchKeyword] = useState(''); - const [displayMode, setDisplayMode] = useState('max'); - - const {data: monitors = [], isLoading} = useQuery({ - queryKey: ['publicMonitors'], - queryFn: () => pika.listMonitors(), - refetchInterval: 30000, - }); - - let [stats, setStats] = useState(); - - // 过滤和搜索 - const filteredMonitors = useMemo(() => { - let result = [...monitors]; - - // 搜索过滤 - if (searchKeyword.trim()) { - const keyword = searchKeyword.toLowerCase(); - result = result.filter(m => - m.name.toLowerCase().includes(keyword) || - m.target.toLowerCase().includes(keyword) - ); - } - - return result.sort((a, b) => Number(a.status !== 'up') - Number(b.status !== 'up')); - }, [monitors, searchKeyword]); - - // 统计信息 - const calculateStats = (monitors: PublicMonitor[]) => { - const total = monitors.length; - const online = monitors.filter(m => m.status === 'up').length; - const issues = total - online; - const avgLatency = total > 0 - ? Math.round(monitors.reduce((acc, curr) => acc + curr.responseTime, 0) / total) - : 0; - return {total, online, issues, avgLatency}; - } - - useEffect(() => { - let stats = calculateStats(monitors); - setStats(stats); - }, [monitors]); - - if (isLoading) { - return ( -
- -
- ); - } - - return ( -
- {/* 统计卡片 */} -
- - - 0} - /> - -
- - {/* 过滤和搜索 */} -
-
- {/* 显示模式切换 */} -
- 卡片指标: - - -
-
- - {/* 搜索框 */} -
-
-
- - setSearchKeyword(e.target.value)} - className="w-full bg-transparent border-none text-xs text-gray-800 dark:text-cyan-100 p-2.5 focus:ring-0 placeholder-gray-400 dark:placeholder-cyan-600 font-mono focus:outline-none" - /> -
-
-
- - {/* 监控卡片列表 */} - {filteredMonitors.length === 0 ? ( - - ) : ( -
- {filteredMonitors.map(monitor => ( - - - - ))} -
- )} -
- ); -}; - -export default MonitorList; diff --git a/portal/src/pages/PublicLayout.tsx b/portal/src/pages/PublicLayout.tsx deleted file mode 100644 index 754cbb4..0000000 --- a/portal/src/pages/PublicLayout.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import {Outlet} from 'react-router-dom'; -import {PublicHeader, PublicFooter} from '../components'; - -const PublicLayout = () => { - return ( -
- {/* 背景网格效果 */} -
- {/* 暗色模式网格 */} -
- {/* 顶部发光效果 */} -
- - -
-
- -
- -
-
- ); -}; - -export default PublicLayout; diff --git a/portal/src/pages/ServerDetail.tsx b/portal/src/pages/ServerDetail.tsx deleted file mode 100644 index ca64ea6..0000000 --- a/portal/src/pages/ServerDetail.tsx +++ /dev/null @@ -1,2057 +0,0 @@ -import {memo, type ReactNode, useEffect, useMemo, useState} from 'react'; -import {useNavigate, useParams} from 'react-router-dom'; -import {Area, AreaChart, CartesianGrid, Legend, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis} from 'recharts'; -import { - Activity, - ArrowLeft, - ChevronDown, - ChevronUp, - Cpu, - HardDrive, - MemoryStick, - Network, - RotateCcw, - Thermometer, - Zap -} from 'lucide-react'; -import type {LucideIcon} from 'lucide-react'; -import type {Agent, LatestMetrics} from '../types'; -import { - INTERFACE_COLORS, - LIVE_INITIAL_RANGE, - LIVE_RANGE, - LIVE_WINDOW_MS, - SERVER_TIME_RANGE_OPTIONS, - TEMPERATURE_COLORS, -} from '../constants'; -import { - cn, - formatBytes, - formatChartTime, - formatDateTime, - formatPercentValue, - formatUptime, -} from '../lib/utils'; -import { - useAgentQuery, - useLatestMetricsQuery, - useLiveBuffer, - useMetricsQuery, - useIsMobile, - useNetworkInterfacesQuery, -} from '../hooks'; -import { - Card, - ChartPlaceholder, - CustomTooltip, - EmptyState, - LoadingSpinner, - MetricItem, - StatusBadge, - TimeRangeSelector -} from '../components'; - -/* ========================================== 共享工具 ========================================== */ - -const toMB = (bytes: number) => Number((bytes / 1024 / 1024).toFixed(2)); - -/* ========================================== ChartContainer ========================================== */ - -interface ChartContainerProps { - title: string; - icon: LucideIcon; - children: ReactNode; - action?: ReactNode; -} - -const ChartContainer = ({title, icon: Icon, children, action}: ChartContainerProps) => { - return ( -
-
-

- - - - {title} -

- {action} -
- {children} -
- ); -}; - -/* ========================================== ServerHero ========================================== */ - -interface ServerHeroProps { - agent: Agent; - latestMetrics: LatestMetrics | null; - onBack: () => void; -} - -const ServerHero = ({agent, latestMetrics, onBack}: ServerHeroProps) => { - const displayName = agent?.name?.trim() ? agent.name : '未命名探针'; - const isOnline = agent?.status === 1; - const statusDotStyles = isOnline ? 'bg-emerald-500' : 'bg-rose-500'; - const statusText = isOnline ? '在线' : '离线'; - - const platformDisplay = latestMetrics?.host?.platform - ? `${latestMetrics.host.platform} ${latestMetrics.host.platformVersion || ''}`.trim() - : agent?.os || '-'; - const architectureDisplay = latestMetrics?.host?.kernelArch || agent?.arch || '-'; - const uptimeDisplay = formatUptime(latestMetrics?.host?.uptime); - const lastSeenDisplay = agent ? formatDateTime(agent.lastSeenAt) : '-'; - - const networkSummary = latestMetrics?.network - ? `${formatBytes(latestMetrics.network.totalBytesSentTotal)} ↑ / ${formatBytes( - latestMetrics.network.totalBytesRecvTotal, - )} ↓` - : '—'; - - const heroStats = [ - {label: '运行系统', value: platformDisplay || '-'}, - {label: '硬件架构', value: architectureDisplay || '-'}, - {label: '系统进程', value: latestMetrics?.host?.procs || '-'}, - {label: '运行时长', value: uptimeDisplay}, - ]; - - return ( - -
-
-
- -
-
-
-

{displayName}

- -
-

- {[agent.hostname].filter(Boolean).join(' · ') || '-'} -

-
-
-
- -
- {heroStats.map((stat) => ( - - ))} -
-
-
- 探针 ID:{agent.id} - - 版本:{agent.version || '-'} - - 网络累计:{networkSummary} -
-
-
- ); -}; - -/* ========================================== SystemInfoSection ========================================== */ - -interface SystemInfoSectionProps { - agent: Agent; - latestMetrics: LatestMetrics | null; -} - -const InfoGrid = ({items}: {items: Array<{label: string; value: ReactNode}>}) => ( -
- {items.map((item) => ( -
-
{item.label}
-
{item.value}
-
- ))} -
-); - -type SnapshotCardData = { - key: string; - icon: LucideIcon; - title: string; - usagePercent: string; - accent: 'blue' | 'emerald' | 'purple' | 'amber'; - metrics: Array<{label: string; value: ReactNode}>; -}; - -const snapshotColors = { - blue: 'text-blue-400', - emerald: 'text-emerald-400', - purple: 'text-purple-400', - amber: 'text-amber-400', -}; - -const SnapshotGrid = ({cards}: {cards: SnapshotCardData[]}) => ( -
- {cards.map((card) => ( -
-
-
- - - -

{card.title}

-
- {card.usagePercent} -
-
- {card.metrics.map((metric) => ( -
- {metric.label} - {metric.value} -
- ))} -
-
- ))} -
-); - -const SystemInfoSection = ({agent, latestMetrics}: SystemInfoSectionProps) => { - // 环境信息 - const platformDisplay = latestMetrics?.host?.platform - ? `${latestMetrics.host.platform} ${latestMetrics.host.platformVersion || ''}`.trim() - : agent?.os || '-'; - const architectureDisplay = latestMetrics?.host?.kernelArch || agent?.arch || '-'; - - const environmentInfo = [ - {label: '操作系统', value: platformDisplay || '-'}, - {label: '内核版本', value: latestMetrics?.host?.kernelVersion || '-'}, - {label: '硬件架构', value: architectureDisplay || '-'}, - {label: 'CPU 型号', value: latestMetrics?.cpu?.modelName || '-'}, - {label: '逻辑核心', value: latestMetrics?.cpu?.logicalCores ?? '-'}, - {label: '物理核心', value: latestMetrics?.cpu?.physicalCores ?? '-'}, - ]; - - // 状态信息 - const uptimeDisplay = formatUptime(latestMetrics?.host?.uptime); - const bootTimeDisplay = latestMetrics?.host?.bootTime - ? formatDateTime(latestMetrics.host.bootTime * 1000) - : '-'; - const lastSeenDisplay = agent ? formatDateTime(agent.lastSeenAt) : '-'; - - const networkSummary = latestMetrics?.network - ? `${formatBytes(latestMetrics.network.totalBytesSentTotal)} ↑ / ${formatBytes( - latestMetrics.network.totalBytesRecvTotal, - )} ↓` - : '—'; - - const statusInfo = [ - {label: '启动时间', value: bootTimeDisplay}, - {label: '运行时间', value: uptimeDisplay}, - {label: '最近心跳', value: lastSeenDisplay}, - {label: '进程数', value: latestMetrics?.host?.procs ?? '-'}, - {label: '网络累计', value: networkSummary}, - {label: 'Load', value: `${latestMetrics?.host?.load1?.toFixed(2)} / ${latestMetrics?.host?.load5?.toFixed(2)} / ${latestMetrics?.host?.load15?.toFixed(2)}`}, - ]; - - // 快照卡片 - const snapshotCards: SnapshotCardData[] = []; - - if (latestMetrics) { - snapshotCards.push({ - key: 'cpu', - icon: Cpu, - title: 'CPU 使用', - usagePercent: `${formatPercentValue(latestMetrics.cpu?.usagePercent)}%`, - accent: 'blue', - metrics: [ - {label: '当前使用', value: `${formatPercentValue(latestMetrics.cpu?.usagePercent)}%`}, - ], - }); - - snapshotCards.push({ - key: 'memory', - icon: MemoryStick, - title: '内存使用', - usagePercent: `${formatPercentValue(latestMetrics.memory?.usagePercent)}%`, - accent: 'emerald', - metrics: [ - { - label: '已用 / 总量', - value: `${formatBytes(latestMetrics.memory?.used)} / ${formatBytes(latestMetrics.memory?.total)}` - }, - { - label: 'Swap 已用', - value: `${formatBytes(latestMetrics.memory?.swapUsed)} / ${formatBytes(latestMetrics.memory?.swapTotal)}` - }, - ], - }); - - snapshotCards.push({ - key: 'disk', - icon: HardDrive, - title: '磁盘使用', - usagePercent: latestMetrics.disk - ? `${formatPercentValue(latestMetrics.disk.usagePercent)}%` - : '—', - accent: 'purple', - metrics: [ - { - label: '已用 / 总量', - value: `${formatBytes(latestMetrics.disk?.used, 1)} / ${formatBytes(latestMetrics.disk?.total, 1)}` - }, - {label: '磁盘数量', value: latestMetrics.disk?.totalDisks ?? '-'}, - ], - }); - - // 网络流量卡片 - 整合流量统计信息 - const networkMetrics = [ - { - label: '上行 / 下行', - value: `${formatBytes(latestMetrics.network?.totalBytesSentRate, 1)}/s ↑ / ${formatBytes( - latestMetrics.network?.totalBytesRecvRate, 1, - )}/s ↓`, - }, - { - label: '网络累计', - value: `${formatBytes(latestMetrics.network?.totalBytesSentTotal, 1)} ↑ / ${formatBytes( - latestMetrics.network?.totalBytesRecvTotal, 1, - )} ↓`, - }, - ]; - - // 如果配置了流量限额,添加流量统计信息到网络卡片 - if (agent?.trafficStats?.enabled && agent.trafficStats.limit > 0) { - const trafficUsedPercent = (agent.trafficStats.used / agent.trafficStats.limit) * 100; - - networkMetrics.push({ - label: '流量限额', - value: `${formatBytes(agent.trafficStats.used, 1)} / ${formatBytes(agent.trafficStats.limit, 1)} (${formatPercentValue(trafficUsedPercent)}%)`, - }); - - if (agent.trafficStats.resetDay > 0) { - networkMetrics.push({ - label: '重置日期', - value: `每月${agent.trafficStats.resetDay}号`, - }); - } - } - - snapshotCards.push({ - key: 'network', - icon: Network, - title: '网络流量', - usagePercent: latestMetrics.network - ? `${formatBytes(latestMetrics.network.totalBytesSentRate)}/s` - : '—', - accent: 'amber', - metrics: networkMetrics, - }); - } - - return ( -
-
-
- -

运行环境

-

来自最近一次探针上报的硬件与系统信息

-
- -
-
- -

运行状态

-

关键时间与网络指标,帮助快速判断主机健康状况

-
- -
-
-
- {snapshotCards.length > 0 && ( - -

- 资源快照 -

- -
- )} -
-
- ); -}; - -/* ========================================== ServerDetailSections ========================================== */ - -const NetworkAddressSection = ({ipv4, ipv6, deviceIpInterfaces}: { - ipv4?: string; - ipv6?: string; - deviceIpInterfaces: Array<{name: string; addrs: string[]}>; -}) => { - if (!ipv4 && !ipv6 && deviceIpInterfaces.length === 0) return null; - - return ( - -
- {(ipv4 || ipv6) && ( -
-
公网地址
-
- {[["IPv4", ipv4], ["IPv6", ipv6]].map(([label, value]) => ( -
-
{label}
-
{value || '-'}
-
- ))} -
-
- )} - - {(ipv4 || ipv6) && deviceIpInterfaces.length > 0 &&
} - - {deviceIpInterfaces.length > 0 && ( -
-
网卡地址
-
- {deviceIpInterfaces.map((networkInterface) => ( -
-
{networkInterface.name}
-
- {networkInterface.addrs.map((address) => ( - - {address} - - ))} -
-
- ))} -
-
- )} -
- - ); -}; - -const NetworkConnectionSection = ({latestMetrics}: {latestMetrics: LatestMetrics | null}) => { - const metrics = latestMetrics?.networkConnection; - if (!metrics) return null; - const items = [ - {label: 'Total', value: metrics.total, color: 'text-slate-800 dark:text-cyan-100'}, - {label: 'ESTABLISHED', value: metrics.established, color: 'text-emerald-600 dark:text-emerald-400'}, - {label: 'TIME_WAIT', value: metrics.timeWait, color: 'text-amber-600 dark:text-amber-400'}, - {label: 'LISTEN', value: metrics.listen, color: 'text-blue-600 dark:text-blue-400'}, - {label: 'CLOSE_WAIT', value: metrics.closeWait, color: 'text-rose-600 dark:text-rose-400'}, - { - label: 'OTHER', - value: metrics.synSent + metrics.synRecv + metrics.finWait1 + metrics.finWait2 + metrics.close + metrics.lastAck + metrics.closing, - color: 'text-gray-700 dark:text-cyan-500', - }, - ]; - - return ( - -
- {items.map((item) => ( -
-
{item.label}
-
{item.value}
-
- ))} -
-
- ); -}; - -const GpuMonitorSection = ({latestMetrics}: {latestMetrics: LatestMetrics | null}) => { - if (!latestMetrics?.gpu?.length) return null; - - return ( - -
- {latestMetrics.gpu.map((gpu) => ( -
-
-
- -
-

GPU {gpu.index}

-

{gpu.name}

-
-
- {gpu.utilization?.toFixed(1) ?? 0}% -
-
- {[ - ['温度', `${gpu.temperature?.toFixed(1)}°C`], - ['显存', `${formatBytes(gpu.memoryUsed)} / ${formatBytes(gpu.memoryTotal)}`], - ['功耗', `${gpu.powerUsage?.toFixed(1)}W`], - ['风扇转速', `${gpu.fanSpeed?.toFixed(0)}%`], - ].map(([label, value]) => ( -
- {label} - {value} -
- ))} -
-
- ))} -
-
- ); -}; - -const TemperatureMonitorSection = ({latestMetrics}: {latestMetrics: LatestMetrics | null}) => { - if (!latestMetrics?.temperature?.length) return null; - - return ( - -
- {[...latestMetrics.temperature].sort((a, b) => a.sensorKey.localeCompare(b.sensorKey)).map((temperature) => ( -
-
- -

{temperature.type}

-
-

{temperature.temperature.toFixed(1)}°C

-
- ))} -
-
- ); -}; - -/* ========================================== CpuChart ========================================== */ - -interface ChartPropsBase { - agentId: string; - timeRange: string; - start?: number; - end?: number; - isLive?: boolean; - latestMetrics?: LatestMetrics | null; -} - -interface CpuChartProps extends ChartPropsBase { -} - -interface CpuPoint { - timestamp: number; - usage: number; -} - -const CpuChart = ({agentId, timeRange, start, end, isLive, latestMetrics}: CpuChartProps) => { - const rangeMs = start !== undefined && end !== undefined ? end - start : undefined; - const effectiveRange = isLive ? LIVE_INITIAL_RANGE : timeRange; - // 数据查询 - const {data: metricsResponse, isLoading} = useMetricsQuery({ - agentId, - type: 'cpu', - range: start !== undefined && end !== undefined ? undefined : effectiveRange, - start, - end, - }); - - // 历史数据 - const initialData = useMemo(() => { - const cpuSeries = metricsResponse?.series?.find(s => s.name === 'usage'); - if (!cpuSeries) return []; - return cpuSeries.data.map((point) => ({ - usage: Number(point.value.toFixed(2)), - timestamp: point.timestamp, - })); - }, [metricsResponse]); - - // 实时点 - const livePoint = useMemo(() => { - if (!isLive || !latestMetrics?.cpu || !latestMetrics.timestamp) return null; - const usage = latestMetrics.cpu.usagePercent; - if (typeof usage !== 'number' || !Number.isFinite(usage)) return null; - return {timestamp: latestMetrics.timestamp, usage: Number(usage.toFixed(2))}; - }, [isLive, latestMetrics]); - - const chartData = useLiveBuffer(initialData, !!isLive, livePoint, LIVE_WINDOW_MS, agentId); - - // 渲染 - if (isLoading) { - return ( - - - - ); - } - - return ( - - {chartData.length > 0 ? ( - - - - - - - - - - formatChartTime(Number(value), timeRange, rangeMs)} - stroke="currentColor" - angle={-15} - textAnchor="end" - className="text-xs text-gray-600 dark:text-cyan-500 font-mono" - /> - `${value}%`} - /> - }/> - - - - ) : ( - - )} - - ); -}; - -/* ========================================== MemoryChart ========================================== */ - -interface MemoryPoint { - timestamp: number; - usage: number; -} - -const MemoryChart = ({agentId, timeRange, start, end, isLive, latestMetrics}: ChartPropsBase) => { - const rangeMs = start !== undefined && end !== undefined ? end - start : undefined; - const effectiveRange = isLive ? LIVE_INITIAL_RANGE : timeRange; - // 数据查询 - const {data: metricsResponse, isLoading} = useMetricsQuery({ - agentId, - type: 'memory', - range: start !== undefined && end !== undefined ? undefined : effectiveRange, - start, - end, - }); - - // 历史数据 - const initialData = useMemo(() => { - const memorySeries = metricsResponse?.series?.find(s => s.name === 'usage'); - if (!memorySeries) return []; - return memorySeries.data.map((point) => ({ - usage: Number(point.value.toFixed(2)), - timestamp: point.timestamp, - })); - }, [metricsResponse]); - - // 实时点 - const livePoint = useMemo(() => { - if (!isLive || !latestMetrics?.memory || !latestMetrics.timestamp) return null; - const usage = latestMetrics.memory.usagePercent; - if (typeof usage !== 'number' || !Number.isFinite(usage)) return null; - return {timestamp: latestMetrics.timestamp, usage: Number(usage.toFixed(2))}; - }, [isLive, latestMetrics]); - - const chartData = useLiveBuffer(initialData, !!isLive, livePoint, LIVE_WINDOW_MS, agentId); - - // 渲染 - if (isLoading) { - return ( - - - - ); - } - - return ( - - {chartData.length > 0 ? ( - - - - - - - - - - formatChartTime(Number(value), timeRange, rangeMs)} - stroke="currentColor" - angle={-15} - textAnchor="end" - className="text-xs text-gray-600 dark:text-cyan-500 font-mono" - /> - `${value}%`} - /> - }/> - - - - ) : ( - - )} - - ); -}; - -/* ========================================== DiskIOChart ========================================== */ - -interface DiskIOPoint { - timestamp: number; - read: number; - write: number; -} - -const DiskIOChart = ({agentId, timeRange, start, end, isLive, latestMetrics}: ChartPropsBase) => { - const rangeMs = start !== undefined && end !== undefined ? end - start : undefined; - const effectiveRange = isLive ? LIVE_INITIAL_RANGE : timeRange; - // 数据查询 - const {data: metricsResponse, isLoading} = useMetricsQuery({ - agentId, - type: 'disk_io', - range: start !== undefined && end !== undefined ? undefined : effectiveRange, - start, - end, - }); - - // 历史数据 - const initialData = useMemo(() => { - if (!metricsResponse?.series || metricsResponse.series.length === 0) return []; - - const readSeries = metricsResponse.series.find(s => s.name === 'read'); - const writeSeries = metricsResponse.series.find(s => s.name === 'write'); - - if (!readSeries || !writeSeries) return []; - - const timeMap = new Map(); - - readSeries.data.forEach(point => { - timeMap.set(point.timestamp, { - timestamp: point.timestamp, - read: toMB(point.value), - write: 0, - }); - }); - - writeSeries.data.forEach(point => { - const existing = timeMap.get(point.timestamp); - if (existing) { - existing.write = toMB(point.value); - } else { - timeMap.set(point.timestamp, { - timestamp: point.timestamp, - read: 0, - write: toMB(point.value), - }); - } - }); - - return Array.from(timeMap.values()).sort((a, b) => a.timestamp - b.timestamp); - }, [metricsResponse]); - - // 实时点:用 latestMetrics.timestamp 作为同批次时间锚 - const livePoint = useMemo(() => { - if (!isLive || !latestMetrics?.diskIO || !latestMetrics.timestamp) return null; - return { - timestamp: latestMetrics.timestamp, - read: toMB(latestMetrics.diskIO.totalReadBytesRate), - write: toMB(latestMetrics.diskIO.totalWriteBytesRate), - }; - }, [isLive, latestMetrics]); - - const chartData = useLiveBuffer(initialData, !!isLive, livePoint, LIVE_WINDOW_MS, agentId); - - // 渲染 - if (isLoading) { - return ( - - - - ); - } - - return ( - - {chartData.length > 0 ? ( - - - - - - - - - - - - - - formatChartTime(Number(value), timeRange, rangeMs)} - stroke="currentColor" - angle={-15} - textAnchor="end" - className="text-xs text-gray-600 dark:text-cyan-500 font-mono" - height={45} - /> - `${value} MB`} - /> - }/> - - - - - - ) : ( - - )} - - ); -}; - -/* ========================================== NetworkChart ========================================== */ - -interface NetworkPoint { - timestamp: number; - upload: number; - download: number; -} - -const NetworkChart = ({agentId, timeRange, start, end, isLive, latestMetrics}: ChartPropsBase) => { - const [selectedInterface, setSelectedInterface] = useState('all'); - const rangeMs = start !== undefined && end !== undefined ? end - start : undefined; - const effectiveRange = isLive ? LIVE_INITIAL_RANGE : timeRange; - - // 查询网卡列表 - const {data: interfacesData} = useNetworkInterfacesQuery(agentId); - const availableInterfaces = interfacesData?.interfaces || []; - - // 当网卡列表变化时,验证选中的网卡 - useEffect(() => { - if (selectedInterface !== 'all' && availableInterfaces.length > 0) { - if (!availableInterfaces.includes(selectedInterface)) { - setSelectedInterface('all'); - } - } - }, [availableInterfaces, selectedInterface]); - - // 查询网络数据 - const {data: metricsResponse, isLoading} = useMetricsQuery({ - agentId, - type: 'network', - range: start !== undefined && end !== undefined ? undefined : effectiveRange, - start, - end, - interfaceName: selectedInterface !== 'all' ? selectedInterface : undefined, - }); - - // 历史数据 - const initialData = useMemo(() => { - if (!metricsResponse?.series || metricsResponse.series.length === 0) return []; - - const uploadSeries = metricsResponse.series.find(s => s.name === 'upload'); - const downloadSeries = metricsResponse.series.find(s => s.name === 'download'); - - if (!uploadSeries || !downloadSeries) return []; - - const timeMap = new Map(); - - uploadSeries.data.forEach(point => { - timeMap.set(point.timestamp, { - timestamp: point.timestamp, - upload: toMB(point.value), - download: 0, - }); - }); - - downloadSeries.data.forEach(point => { - const existing = timeMap.get(point.timestamp); - if (existing) { - existing.download = toMB(point.value); - } else { - timeMap.set(point.timestamp, { - timestamp: point.timestamp, - upload: 0, - download: toMB(point.value), - }); - } - }); - - return Array.from(timeMap.values()).sort((a, b) => a.timestamp - b.timestamp); - }, [metricsResponse]); - - // 实时点:用 latestMetrics.timestamp 作为采集批次时间锚点 - const livePoint = useMemo(() => { - if (!isLive || !latestMetrics?.timestamp) return null; - - let sentRate = 0; - let recvRate = 0; - if (selectedInterface === 'all') { - const summary = latestMetrics.network; - if (!summary) return null; - sentRate = summary.totalBytesSentRate; - recvRate = summary.totalBytesRecvRate; - } else { - const iface = latestMetrics.networkInterfaces?.find(i => i.interface === selectedInterface); - if (!iface) return null; - sentRate = iface.bytesSentRate; - recvRate = iface.bytesRecvRate; - } - return { - timestamp: latestMetrics.timestamp, - upload: toMB(sentRate), - download: toMB(recvRate), - }; - }, [isLive, latestMetrics, selectedInterface]); - - const chartData = useLiveBuffer(initialData, !!isLive, livePoint, LIVE_WINDOW_MS, `${agentId}|${selectedInterface}`); - - // 网卡选择器 - const interfaceSelector = availableInterfaces.length > 0 && ( - - ); - - // 渲染 - if (isLoading) { - return ( - - - - ); - } - - return ( - - {chartData.length > 0 ? ( - - - - - - - - - - - - - - formatChartTime(Number(value), timeRange, rangeMs)} - stroke="currentColor" - angle={-15} - textAnchor="end" - className="text-xs text-gray-600 dark:text-cyan-500 font-mono" - height={45} - /> - `${value} MB`} - /> - }/> - - - - - - ) : ( - - )} - - ); -}; - -/* ========================================== NetworkConnectionChart ========================================== */ - -interface ConnPoint { - timestamp: number; - established: number; - time_wait: number; - close_wait: number; - listen: number; -} - -const NetworkConnectionChart = ({agentId, timeRange, start, end, isLive, latestMetrics}: ChartPropsBase) => { - const rangeMs = start !== undefined && end !== undefined ? end - start : undefined; - const effectiveRange = isLive ? LIVE_INITIAL_RANGE : timeRange; - const {data: metricsResponse, isLoading} = useMetricsQuery({ - agentId, - type: 'network_connection', - range: start !== undefined && end !== undefined ? undefined : effectiveRange, - start, - end, - }); - - // 历史数据 - const initialData = useMemo(() => { - if (!metricsResponse?.series || metricsResponse.series.length === 0) return []; - - const timeMap = new Map(); - - metricsResponse.series.forEach(series => { - const stateName = series.name; - series.data.forEach(point => { - if (!timeMap.has(point.timestamp)) { - timeMap.set(point.timestamp, { - timestamp: point.timestamp, - established: 0, - time_wait: 0, - close_wait: 0, - listen: 0, - }); - } - const existing = timeMap.get(point.timestamp)!; - if (stateName === 'established' || stateName === 'time_wait' || stateName === 'close_wait' || stateName === 'listen') { - existing[stateName] = Number(point.value.toFixed(0)); - } - }); - }); - - return Array.from(timeMap.values()).sort((a, b) => a.timestamp - b.timestamp); - }, [metricsResponse]); - - // 实时点 - const livePoint = useMemo(() => { - if (!isLive || !latestMetrics?.networkConnection || !latestMetrics.timestamp) return null; - const c = latestMetrics.networkConnection; - return { - timestamp: latestMetrics.timestamp, - established: c.established ?? 0, - time_wait: c.timeWait ?? 0, - close_wait: c.closeWait ?? 0, - listen: c.listen ?? 0, - }; - }, [isLive, latestMetrics]); - - const chartData = useLiveBuffer(initialData, !!isLive, livePoint, LIVE_WINDOW_MS, agentId); - - // 渲染 - if (isLoading) { - return ( - - - - ); - } - - return ( - - {chartData.length > 0 ? ( - - - - formatChartTime(Number(value), timeRange, rangeMs)} - stroke="currentColor" - angle={-15} - textAnchor="end" - className="text-xs text-gray-600 dark:text-cyan-500 font-mono" - height={45} - /> - - }/> - - - - - - - - ) : ( - - )} - - ); -}; - -/* ========================================== GpuChart ========================================== */ - -const GpuChartImpl = ({agentId, timeRange, start, end, isLive}: ChartPropsBase) => { - const rangeMs = start !== undefined && end !== undefined ? end - start : undefined; - const effectiveRange = isLive ? LIVE_INITIAL_RANGE : timeRange; - // 数据查询 - const {data: metricsResponse, isLoading} = useMetricsQuery({ - agentId, - type: 'gpu', - range: start !== undefined && end !== undefined ? undefined : effectiveRange, - start, - end, - refetchIntervalMs: isLive ? 5000 : undefined, - }); - - // 数据转换 - const chartData = useMemo(() => { - if (!metricsResponse?.series || metricsResponse.series.length === 0) return []; - - const timeMap = new Map(); - - const utilizationSeries = metricsResponse.series.find(s => s.name === 'utilization'); - const temperatureSeries = metricsResponse.series.find(s => s.name === 'temperature'); - - utilizationSeries?.data.forEach(point => { - const existing = timeMap.get(point.timestamp); - if (existing) { - existing.utilization = Number(point.value.toFixed(2)); - } else { - timeMap.set(point.timestamp, { - timestamp: point.timestamp, - utilization: Number(point.value.toFixed(2)), - }); - } - }); - - temperatureSeries?.data.forEach(point => { - const existing = timeMap.get(point.timestamp); - if (existing) { - existing.temperature = Number(point.value.toFixed(2)); - } else { - timeMap.set(point.timestamp, { - timestamp: point.timestamp, - temperature: Number(point.value.toFixed(2)), - }); - } - }); - - return Array.from(timeMap.values()).sort((a, b) => a.timestamp - b.timestamp); - }, [metricsResponse]); - - // 渲染 - if (isLoading) { - return ( - - - - ); - } - - // 如果没有 GPU 数据,不渲染组件 - if (chartData.length === 0) { - return null; - } - - return ( - - - - - formatChartTime(Number(value), timeRange, rangeMs)} - stroke="currentColor" - className="stroke-gray-400 dark:stroke-cyan-600" - style={{fontSize: '12px'}} - /> - `${value}%`} - /> - `${value}°C`} - /> - }/> - - - - - - - ); -}; - -const GpuChart = memo(GpuChartImpl); - -/* ========================================== TemperatureChart ========================================== */ - -const TemperatureChartImpl = ({agentId, timeRange, start, end, isLive}: ChartPropsBase) => { - const [selectedTempType, setSelectedTempType] = useState('all'); - const rangeMs = start !== undefined && end !== undefined ? end - start : undefined; - const effectiveRange = isLive ? LIVE_INITIAL_RANGE : timeRange; - - // 数据查询:温度采集 5s 一次,实时模式 5s 重查 - const {data: metricsResponse, isLoading} = useMetricsQuery({ - agentId, - type: 'temperature', - range: start !== undefined && end !== undefined ? undefined : effectiveRange, - start, - end, - refetchIntervalMs: isLive ? 5000 : undefined, - }); - - // 数据转换 - const chartData = useMemo(() => { - if (!metricsResponse?.series || metricsResponse.series.length === 0) return []; - - const timeMap = new Map(); - - metricsResponse.series.forEach(series => { - const sensorName = series.name; - series.data.forEach(point => { - if (!timeMap.has(point.timestamp)) { - timeMap.set(point.timestamp, {timestamp: point.timestamp}); - } - - const existing = timeMap.get(point.timestamp)!; - existing[sensorName] = Number(point.value.toFixed(2)); - }); - }); - - return Array.from(timeMap.values()); - }, [metricsResponse]); - - // 提取所有唯一的温度类型 - const temperatureTypes = useMemo(() => { - return metricsResponse?.series?.map(s => s.name).sort() || []; - }, [metricsResponse]); - - // 根据选中的类型过滤温度数据 - const filteredTemperatureTypes = useMemo(() => { - if (selectedTempType === 'all') { - return temperatureTypes; - } - return temperatureTypes.filter(type => type === selectedTempType); - }, [temperatureTypes, selectedTempType]); - - // 当温度类型列表变化时,如果当前选中的类型不在列表中,重置为 'all' - useEffect(() => { - if (selectedTempType !== 'all' && temperatureTypes.length > 0) { - if (!temperatureTypes.includes(selectedTempType)) { - setSelectedTempType('all'); - } - } - }, [temperatureTypes, selectedTempType]); - - // 温度类型选择器 - const tempTypeSelector = temperatureTypes.length > 1 && ( - - ); - - // 渲染 - if (isLoading) { - return ( - - - - ); - } - - // 如果没有温度数据,不渲染组件 - if (chartData.length === 0 || temperatureTypes.length === 0) { - return null; - } - - return ( - - - - - formatChartTime(Number(value), timeRange, rangeMs)} - stroke="currentColor" - angle={-15} - textAnchor="end" - className="text-xs text-gray-600 dark:text-cyan-500 font-mono" - height={45} - /> - `${value}°C`} - /> - }/> - - {/* 为选中的温度类型渲染线条 */} - {filteredTemperatureTypes.map((type, index) => { - const color = TEMPERATURE_COLORS[type] || `hsl(${(index * 60) % 360}, 70%, 50%)`; - return ( - - ); - })} - - - - ); -}; - -const TemperatureChart = memo(TemperatureChartImpl); - -/* ========================================== MonitorChart ========================================== */ - -/** - * 降采样算法 - 使用LTTB (Largest Triangle Three Buckets) - * 确保输出精确的maxPoints个点,保留关键特征 - */ -const downsampleData = (data: any[], maxPoints: number): any[] => { - // 边界检查 - if (!data || data.length === 0) return []; - if (maxPoints < 2) maxPoints = 2; - if (data.length <= maxPoints) return [...data]; - - const result: any[] = [data[0]]; // 保留第一个点 - - // 桶大小 - const bucketSize = (data.length - 2) / (maxPoints - 2); - - for (let i = 0; i < maxPoints - 2; i++) { - // 计算当前桶的范围 - const start = Math.floor((i + 0) * bucketSize) + 1; - const end = Math.floor((i + 1) * bucketSize) + 1; - - // 计算前一个点和后一个点 - const previousPoint = result[result.length - 1]; - const nextPoint = data[Math.min(end, data.length - 1)]; - - // 在桶中选择与前后点形成的三角形面积最大的点 - let maxArea = -1; - let selectedPoint = data[start]; - - for (let j = start; j < end && j < data.length - 1; j++) { - // 计算三角形面积 - const area = Math.abs( - (previousPoint.timestamp - nextPoint.timestamp) * (data[j].value - previousPoint.value) - - (previousPoint.timestamp - data[j].timestamp) * (nextPoint.value - previousPoint.value) - ); - - if (area > maxArea) { - maxArea = area; - selectedPoint = data[j]; - } - } - - result.push(selectedPoint); - } - - result.push(data[data.length - 1]); // 保留最后一个点 - - return result; -}; - -/** - * 根据时间范围确定最大数据点数 - */ -const getMaxDataPoints = (timeRange: string): number => { - switch (timeRange) { - case '15m': - case '1h': - return 200; // 短时间:详细数据 - case '12h': - return 300; - case '24h': - return 400; - case '7d': - return 500; - case '30d': - return 600; - default: - return 400; - } -}; - -/** - * 生成不重复的颜色 - * 使用 HSL 色轮均匀分布,支持无限数量的监控项 - */ -const generateColors = (count: number): string[] => { - const colors: string[] = []; - const hueStep = 360 / count; // 色相间隔 - - for (let i = 0; i < count; i++) { - const hue = (i * hueStep) % 360; - const saturation = 65 + (i % 3) * 10; // 65%, 75%, 85% 循环 - const lightness = 45 + (i % 2) * 10; // 45%, 55% 循环 - colors.push(`hsl(${hue}, ${saturation}%, ${lightness}%)`); - } - - return colors; -}; - -/** - * 自定义图例组件 - */ -const CustomLegend = ({ onClick, selectedMonitors, allMonitorKeys, colors, collapsed }: any) => { - if (!allMonitorKeys || allMonitorKeys.length === 0) return null; - - if (collapsed) return null; - - return ( -
- {allMonitorKeys.map((monitorKey: string, index: number) => { - const isSelected = selectedMonitors.has(monitorKey); - const color = colors[index]; - - return ( -
onClick({ value: monitorKey })} - className="flex items-center gap-2 cursor-pointer transition-opacity" - style={{ - opacity: isSelected ? 1 : 0.4, - }} - > - - - - - {monitorKey} - -
- ); - })} -
- ); -}; - -const MonitorChartImpl = ({agentId, timeRange, start, end, isLive}: ChartPropsBase) => { - const isMobile = useIsMobile(); - const rangeMs = start !== undefined && end !== undefined ? end - start : undefined; - const [selectedMonitors, setSelectedMonitors] = useState>(new Set()); - const [legendCollapsed, setLegendCollapsed] = useState(true); // 移动端默认收起 - // 监控任务由探针自定义周期上报,实时模式下保留 15m 视图,10s 重查 - const effectiveRange = isLive ? '15m' : timeRange; - - // 数据查询 - const {data: metricsResponse, isLoading} = useMetricsQuery({ - agentId, - type: 'monitor', - range: start !== undefined && end !== undefined ? undefined : effectiveRange, - start, - end, - refetchIntervalMs: isLive ? 10000 : undefined, - }); - - // 获取所有监控任务的列表(使用名称) - const allMonitorKeys = useMemo(() => { - const series = metricsResponse?.series || []; - return series.map(s => s.labels?.monitor_name || s.labels?.monitor_id || s.name); - }, [metricsResponse]); - - // 初始化选中所有监控任务 - useEffect(() => { - if (allMonitorKeys.length > 0 && selectedMonitors.size === 0) { - setSelectedMonitors(new Set(allMonitorKeys)); - } - }, [allMonitorKeys, selectedMonitors.size]); - - // 过滤后的监控任务列表 - const monitorKeys = useMemo(() => { - return allMonitorKeys.filter(key => selectedMonitors.has(key)); - }, [allMonitorKeys, selectedMonitors]); - - // 数据转换 - 支持多个监控任务(统一时间轴 + 线性插值) - const chartData = useMemo(() => { - const series = metricsResponse?.series || []; - if (series.length === 0) return []; - - // 收集所有监控任务的数据 - const seriesDataArray: Array<{ key: string; data: Array<{ timestamp: number; value: number }> }> = []; - - series.forEach((s) => { - const monitorKey = s.labels?.monitor_name || s.labels?.monitor_id || s.name; - if (!selectedMonitors.has(monitorKey)) return; - if (!s.data || s.data.length === 0) return; - - seriesDataArray.push({ - key: monitorKey, - data: [...s.data].sort((a, b) => a.timestamp - b.timestamp) - }); - }); - - if (seriesDataArray.length === 0) return []; - - // 取所有监控任务时间范围的交集,确保每个时间点所有任务都有数据 - let minTime = -Infinity, maxTime = Infinity; - seriesDataArray.forEach(s => { - if (s.data.length > 0) { - minTime = Math.max(minTime, s.data[0].timestamp); - maxTime = Math.min(maxTime, s.data[s.data.length - 1].timestamp); - } - }); - - // 如果没有交集,返回空数组 - if (minTime >= maxTime) return []; - - // 均匀生成目标时间点 - const maxPoints = getMaxDataPoints(timeRange); - const timeStep = (maxTime - minTime) / (maxPoints - 1); - const targetTimestamps: number[] = []; - for (let i = 0; i < maxPoints; i++) { - targetTimestamps.push(minTime + i * timeStep); - } - - // 线性插值函数 - const interpolate = (data: Array<{ timestamp: number; value: number }>, targetTime: number): number | null => { - if (data.length === 0) return null; - if (data.length === 1) { - // 单点数据,只有精确匹配才返回 - return data[0].timestamp === targetTime ? data[0].value : null; - } - - // 如果目标时间在数据范围外,返回 null(断开折线) - if (targetTime < data[0].timestamp || targetTime > data[data.length - 1].timestamp) { - return null; - } - - // 二分查找找到 targetTime 前后两个点 - let left = 0, right = data.length - 1; - while (right - left > 1) { - const mid = Math.floor((left + right) / 2); - if (data[mid].timestamp <= targetTime) { - left = mid; - } else { - right = mid; - } - } - - // 线性插值 - const leftPoint = data[left]; - const rightPoint = data[right]; - const ratio = (targetTime - leftPoint.timestamp) / (rightPoint.timestamp - leftPoint.timestamp); - return leftPoint.value + ratio * (rightPoint.value - leftPoint.value); - }; - - // 对每个时间点,从每个监控任务中插值获取值 - return targetTimestamps.map(timestamp => { - const dataPoint: any = { timestamp }; - seriesDataArray.forEach(s => { - const value = interpolate(s.data, timestamp); - if (value !== null) { - dataPoint[s.key] = Number(value.toFixed(2)); - } - }); - return dataPoint; - }); - }, [metricsResponse, selectedMonitors, timeRange, start, end]); - - // 动态生成颜色(根据监控项数量) - const colors = useMemo(() => { - return generateColors(allMonitorKeys.length); - }, [allMonitorKeys.length]); - - const toggleMonitor = (monitorKey: string) => { - setSelectedMonitors((current) => { - if (current.size === allMonitorKeys.length) return new Set([monitorKey]); - const next = new Set(current); - if (next.has(monitorKey)) next.delete(monitorKey); - else next.add(monitorKey); - return next; - }); - }; - - const handleAreaClick = (data: unknown) => { - const key = (data as {dataKey?: string})?.dataKey; - if (key) toggleMonitor(key); - }; - - const handleLegendClick = (data: {value?: string}) => { - if (data?.value) toggleMonitor(data.value); - }; - - // 恢复全选 - const handleSelectAll = () => { - setSelectedMonitors(new Set(allMonitorKeys)); - }; - - // 是否有监控项未选中(用于显示恢复按钮) - const hasUnselected = selectedMonitors.size < allMonitorKeys.length; - - // 切换图例显示/隐藏(仅移动端) - const toggleLegend = () => setLegendCollapsed((collapsed) => !collapsed); - - // 如果没有数据且不是加载中,不渲染组件 - if (!isLoading && chartData.length === 0) { - return null; - } - - // 渲染 - if (isLoading) { - return ( - - - - ); - } - - return ( - - {chartData.length > 0 ? ( - <> - {/* 使用提示和恢复按钮 */} - {allMonitorKeys.length > 1 && ( -
-
- 💡 点击图表线条或图例切换显示 -
- {hasUnselected && ( - - )} -
- )} - - - - - {monitorKeys.map((key, index) => { - const originalIndex = allMonitorKeys.indexOf(key); - return ( - - - - - ); - })} - - - formatChartTime(Number(value), timeRange, rangeMs)} - stroke="currentColor" - angle={-15} - textAnchor="end" - className="text-xs text-gray-600 dark:text-cyan-500 font-mono" - height={45} - /> - `${value}ms`} - /> - } - wrapperStyle={{zIndex: 9999,}} - /> - {monitorKeys.map((key, index) => { - const originalIndex = allMonitorKeys.indexOf(key); - return ( - - ); - })} - - - - {/* 桌面端:直接显示图例 */} - {!isMobile && allMonitorKeys.length > 0 && ( - - )} - - {/* 移动端:可折叠图例 */} - {isMobile && allMonitorKeys.length > 0 && ( -
- - -
- )} - - ) : ( - - )} -
- ); -}; - -const MonitorChart = memo(MonitorChartImpl); - -/* ========================================== ServerDetail ========================================== */ - -/** - * 服务器详情页面 - * 显示服务器的详细信息、实时指标和历史趋势图表 - */ -const ServerDetail = () => { - const {id} = useParams<{ id: string }>(); - const navigate = useNavigate(); - const [timeRange, setTimeRange] = useState(LIVE_RANGE); - const [customRange, setCustomRange] = useState<{ start: number; end: number } | null>(null); - - const handleCustomRangeApply = (range: { start: number; end: number }) => { - setCustomRange(range); - }; - - const isLive = timeRange === LIVE_RANGE; - const customStart = timeRange === 'custom' ? customRange?.start : undefined; - const customEnd = timeRange === 'custom' ? customRange?.end : undefined; - - // 查询基础数据(用于页面头部和系统信息) - // 实时模式 1s 拉取最新指标,其余 5s - const {data: agentResponse, isLoading} = useAgentQuery(id); - const {data: latestMetricsResponse} = useLatestMetricsQuery(id, isLive ? 1000 : 5000); - - const agent = agentResponse; - const latestMetrics = latestMetricsResponse || null; - - const deviceIpInterfaces = (latestMetrics?.networkInterfaces || []) - .map((netInterface) => ({ - name: netInterface.interface, - addrs: Array.from(new Set((netInterface.addrs || []).map((addr) => addr.trim()).filter(Boolean))), - })) - .filter((netInterface) => netInterface.addrs.length > 0); - - if (isLoading) { - return ; - } - - if (!agent) { - return ; - } - - return ( -
-
- {/* 头部区域 */} - navigate('/')} - /> - - {/* 主内容区 */} -
- {/* 网络地址信息 */} - {(agent.ipv4 || agent.ipv6 || deviceIpInterfaces?.length > 0) && ( - - )} - - {/* 系统信息 */} - - - {/* 历史趋势图表 */} - - -
- } - > -
- {/* 核心指标:大屏 2 列,小屏 1 列 */} -
- - -
- - {/* 网络相关:大屏 2 列,中屏 1 列 */} -
- - -
- - {/* 进阶指标:单列全宽 */} -
- -
- - {/* 硬件指标:条件渲染,单列全宽 */} -
- - -
- - {/* 监控指标:单列全宽 */} -
- -
-
- - - {/* 网络连接统计 */} - - - {/* GPU 监控 */} - - - {/* 温度监控 */} - - -
-
- ); -}; - -export default ServerDetail; diff --git a/portal/src/pages/ServerList.tsx b/portal/src/pages/ServerList.tsx deleted file mode 100644 index 9223973..0000000 --- a/portal/src/pages/ServerList.tsx +++ /dev/null @@ -1,848 +0,0 @@ -import {type FC, type ReactNode, useMemo, useState} from 'react'; -import {Link, useNavigate} from 'react-router-dom'; -import {useQuery} from '@tanstack/react-query'; -import * as Tooltip from '@radix-ui/react-tooltip'; -import { - Activity, - AlertTriangle, - ArrowDown, - ArrowUp, - Calendar, - Clock, - Cpu, - Filter, - Globe, - HardDrive, - LinkIcon, - MemoryStick, - Network, - Thermometer, - UnlinkIcon -} from 'lucide-react'; -import {pika} from '../api'; -import type {Agent, LatestMetrics, TagsResponse} from '../types'; -import {cn, formatBytes, formatSpeed, formatTime, formatUptime, isExpired} from '../lib/utils'; -import {Card, LoadingSpinner, StatBlock} from '../components'; - -interface AgentWithMetrics extends Agent { - metrics?: LatestMetrics; -} - -/* ========================================== CompactResourceBar ========================================== */ - -// 紧凑型资源条组件 -const CompactResourceBar = ({value, label, subtext, icon: Icon, color = "bg-cyan-500"}: { - value: number; - label: string; - subtext?: string; - icon: any; - color?: string; -}) => { - const isCritical = value > 90; - const isWarning = value > 75; - - // 颜色定义 (Hex codes for precise control) - let barColor = ""; - let iconClass = ""; - let textClass = "dark:text-cyan-50"; // 默认高亮白/青 - - if (isCritical) { - barColor = "bg-rose-500"; - iconClass = "text-rose-600 dark:text-rose-500"; - textClass = "text-rose-400"; - } else if (isWarning) { - barColor = "bg-amber-500"; - iconClass = "text-amber-600 dark:text-amber-400"; - textClass = "text-amber-400"; - } else if (color.includes("purple")) { - barColor = "bg-purple-500"; - iconClass = "text-purple-600 dark:text-purple-400"; - } else if (color.includes("blue")) { - barColor = "bg-blue-500"; - iconClass = "text-blue-600 dark:text-blue-400"; - } else { - barColor = "bg-cyan-500"; - iconClass = "text-cyan-600 dark:text-cyan-400"; - } - - return ( -
- - - -
- {/* Icon & Label */} -
- - {label} -
- - {/* Track Container */} -
- - {/* Scale Marks Background (The "Ruler" effect) */} -
- -
-
-
-
-
- {value.toFixed(1)}% -
-
-
- - - {subtext} - - - -
-
-
- ); -}; - -/* ========================================== 共享辅助函数 ========================================== */ - -const calculateNetworkSpeed = (metrics?: LatestMetrics) => { - if (!metrics?.network) { - return {upload: 0, download: 0}; - } - return { - upload: metrics.network.totalBytesSentRate, - download: metrics.network.totalBytesRecvRate - }; -}; - -const calculateDiskUsage = (metrics?: LatestMetrics) => { - if (!metrics?.disk) { - return 0; - } - return metrics.disk.usagePercent; -}; - -const getTemperatures = (metrics?: LatestMetrics) => { - if (!metrics?.temperature || metrics.temperature.length === 0) { - return []; - } - // 返回所有温度数据 - return metrics.temperature.sort((a, b) => a.type.localeCompare(b.type)); -}; - -const getTrafficProgressColor = (percent: number) => { - if (percent >= 100) return 'bg-red-500'; - if (percent >= 90) return 'bg-orange-500'; - if (percent >= 80) return 'bg-yellow-500'; - return 'bg-emerald-500'; -}; - -/* ========================================== ServerCard ========================================== */ - -interface ServerCardProps { - server: AgentWithMetrics; -} - -const ServerCard: FC = ({server}) => { - const isOnline = server.status === 1; - const cpuUsage = server.metrics?.cpu?.usagePercent ?? 0; - const memoryUsage = server.metrics?.memory?.usagePercent ?? 0; - const memoryTotal = server.metrics?.memory?.total ?? 0; - const memoryUsed = server.metrics?.memory?.used ?? 0; - const diskUsage = calculateDiskUsage(server.metrics); - const diskTotal = server.metrics?.disk?.total ?? 0; - const diskUsed = server.metrics?.disk?.used ?? 0; - const {upload, download} = calculateNetworkSpeed(server.metrics); - const temperatures = getTemperatures(server.metrics); - const netConn = server.metrics?.networkConnection; - const traffic = server.trafficStats; - const trafficUsagePercent = traffic?.enabled && traffic.limit > 0 - ? Math.min(100, (traffic.used / traffic.limit) * 100) - : 0; - - return ( - - -
- {/* 顶部:名称和状态 */} -
-
-
- {server.name || server.hostname} -
-
- {server.os} - - {server.arch} -
-
- {server.tags && server.tags.length > 0 && ( -
- {server.tags.slice(0, 2).map(tag => ( - - #{tag} - - ))} - {server.tags.length > 2 && ( - - +{server.tags.length - 2} - - )} -
- )} -
- - {isOnline && server.metrics?.host && ( -
-
- - {formatUptime(server.metrics.host.uptime)} -
- -
- - {server.metrics.host.procs} 进程 -
-
- )} - - {/* 资源使用情况 */} - {isOnline ? ( -
- - - - {temperatures.length > 0 && ( -
- - {temperatures.map((temp, index) => ( - - {temp.temperature?.toFixed(1)}°C - {temp.type} - {index < temperatures.length - 1 && - |} - - ))} -
- )} -
- ) : ( -
- - 离线 -
- )} - - {/* 网络和流量 */} -
-
-
- - - {formatSpeed(download)} - - - - {formatSpeed(upload)} - -
- {server.expireTime > 0 && ( -
- - {new Date(server.expireTime).toLocaleDateString('zh-CN')} -
- )} -
- {isOnline && netConn && ( -
- - - {netConn.established || 0} - ESTABLISHED - - - - {netConn.listen || 0} - LISTEN - - - - {netConn.closeWait || 0} - CLOSE_WAIT - -
- )} - {traffic?.enabled && ( -
-
- - {traffic.type === 'recv' ? '进站' : traffic.type === 'send' ? '出站' : '全部'}流量 -
- {traffic.limit > 0 ? ( - <> -
- - {formatBytes(traffic.used, 1)} / {formatBytes(traffic.limit, 1)} - - - {trafficUsagePercent.toFixed(1)}% - -
-
-
-
-
- 重置日期: 每月 {traffic.resetDay} 号 -
- - ) : ( -
- 已使用: {formatBytes(traffic.used, 1)} -
仅统计模式
-
- )} -
- )} -
-
- - - ); -}; - -/* ========================================== ServerList 本地组件 ========================================== */ - -const NetworkStatCard = ({uploadRate, downloadRate, uploadTotal, downloadTotal}: { - uploadRate: number; - downloadRate: number; - uploadTotal: number; - downloadTotal: number; -}) => ( -
- -
-
-
网络统计
-
-
- - {formatSpeed(uploadRate)} - ({formatBytes(uploadTotal)}) -
-
- - {formatSpeed(downloadRate)} - ({formatBytes(downloadTotal)}) -
-
-
- -
-
-); - -interface ServerListEmptyProps { - title: string; - description: string; - extra?: ReactNode; -} - -const ServerListEmpty = ({title, description, extra}: ServerListEmptyProps) => ( -
-
- -
-

{title}

-

{description}

- {extra ?
{extra}
: null} -
-); - -/* ========================================== ServerList ========================================== */ - -const ServerList = () => { - const navigate = useNavigate(); - const [selectedTag, setSelectedTag] = useState(''); - - const {data: agents = [], isLoading} = useQuery({ - queryKey: ['agents', 'online'], - queryFn: () => pika.listAgents(), - refetchInterval: 3000, - }); - - // 获取标签列表 - const {data: tagsData} = useQuery({ - queryKey: ['tags', 'public'], - queryFn: async () => { - const response = await pika.getTags(); - return response.tags || []; - }, - refetchInterval: 30000, - }); - - // 计算所有标签(包括ALL和ONLINE/OFFLINE) - const allTags = useMemo(() => { - const tags = ['ALL', 'ONLINE', 'OFFLINE']; - if (tagsData && tagsData.length > 0) { - tagsData.forEach((tag: string) => { - if (!tags.includes(tag.toUpperCase())) { - tags.push(tag.toUpperCase()); - } - }); - } - return tags; - }, [tagsData]); - - // 过滤逻辑 - const displayAgents = useMemo(() => { - if (selectedTag === 'ONLINE') { - return agents.filter(a => a.status === 1); - } else if (selectedTag === 'OFFLINE') { - return agents.filter(a => a.status !== 1); - } else if (selectedTag && selectedTag !== 'ALL') { - return agents.filter(a => a.tags?.map(t => t.toUpperCase()).includes(selectedTag)); - } - return agents; - }, [agents, selectedTag]); - - // 计算统计数据(基于过滤后的 displayAgents) - const stats = useMemo(() => { - const total = displayAgents.length; - const online = displayAgents.filter(a => a.status === 1).length; - const offline = total - online; - - // 计算网络统计 - let totalUploadRate = 0; - let totalDownloadRate = 0; - let totalUploadTotal = 0; - let totalDownloadTotal = 0; - - displayAgents.forEach(agent => { - if (agent.status === 1 && agent.metrics?.network) { - totalUploadRate += agent.metrics.network.totalBytesSentRate || 0; - totalDownloadRate += agent.metrics.network.totalBytesRecvRate || 0; - totalUploadTotal += agent.metrics.network.totalBytesSentTotal || 0; - totalDownloadTotal += agent.metrics.network.totalBytesRecvTotal || 0; - } - }); - - return { - total, - online, - offline, - uploadRate: totalUploadRate, - downloadRate: totalDownloadRate, - uploadTotal: totalUploadTotal, - downloadTotal: totalDownloadTotal - }; - }, [displayAgents]); - - const handleNavigate = (agentId: string) => { - navigate(`/servers/${agentId.substring(0, 8)}`); - }; - - if (isLoading) { - return ; - } - - // debug - // displayAgents = Array.from({length:10}, ()=>displayAgents).flat(); - - return ( -
- {/* 统计卡片 */} -
- - - 0} - /> - -
- - {/* 标签过滤器 */} - {allTags.length > 1 && ( -
-
- - FILTERS: -
- {allTags.map(tag => { - const tagKey = tag === 'ALL' ? '' : tag; - let count = 0; - if (tag === 'ALL') count = agents.length; - else if (tag === 'ONLINE') count = agents?.filter(a => a.status === 1).length; - else if (tag === 'OFFLINE') count = agents?.filter(a => a.status !== 1).length; - else count = agents?.filter(a => a.tags?.map(t => t.toUpperCase()).includes(tag)).length; - - if (count === 0 && tag !== 'ALL') return null; - - return ( - - ); - })} -
- )} - - {/* 服务器列表 */} - {displayAgents.length === 0 ? ( - - ) : ( - <> - {/* 桌面端表格布局 */} -
- - - - - - - - - - - - - {displayAgents.map(server => { - const isOnline = server.status === 1; - const cpuUsage = server.metrics?.cpu?.usagePercent ?? 0; - const memoryUsage = server.metrics?.memory?.usagePercent ?? 0; - const memoryTotal = server.metrics?.memory?.total ?? 0; - const memoryUsed = server.metrics?.memory?.used ?? 0; - const diskUsage = calculateDiskUsage(server.metrics); - const diskTotal = server.metrics?.disk?.total ?? 0; - const diskUsed = server.metrics?.disk?.used ?? 0; - const {upload, download} = calculateNetworkSpeed(server.metrics); - const temperatures = getTemperatures(server.metrics); - const netConn = server.metrics?.networkConnection; - const traffic = server.trafficStats; - const trafficUsagePercent = traffic?.enabled && traffic.limit > 0 - ? Math.min(100, (traffic.used / traffic.limit) * 100) - : 0; - - return ( - handleNavigate(server.id)} - onKeyDown={(event) => { - if (event.key === 'Enter' || event.key === ' ') { - event.preventDefault(); - handleNavigate(server.id); - } - }} - className="group hover:bg-gray-500/5 dark:hover:bg-cyan-500/5 transition-colors cursor-pointer" - > - {/* Identity */} - - - {/* Resources */} - - - {/* Network */} - - - {/* Traffic */} - - - {/* Connections */} - - - {/* Meta */} - - - ); - })} - -
IdentityTelemetryI/O RateTrafficNetworkMeta / Tags
-
-
-
- {server.name} -
-
- {server.os} - - {server.arch} -
- {isOnline && server.metrics?.host && ( -
-
- - {formatUptime(server.metrics.host.uptime)} -
-
- - {server.metrics.host.procs} 进程 -
-
- )} -
-
-
- {isOnline ? ( -
- - - - {temperatures.length > 0 && ( -
- - {temperatures.map((temp, index) => ( - - {temp.temperature?.toFixed(1)}°C - {temp.type} - {index < temperatures.length - 1 && - |} - - ))} -
- )} -
- ) : ( -
- - CONNECTION_LOST // RECONNECTING... -
- )} -
-
- - - {formatSpeed(download)} - - - - {formatSpeed(upload)} - -
-
- {traffic?.enabled ? ( -
-
- {traffic.type === 'recv' ? '进站' : traffic.type === 'send' ? '出站' : '全部'}流量 -
- {traffic.limit > 0 ? ( - <> -
- - {formatBytes(traffic.used, 1)} / {formatBytes(traffic.limit, 1)} - - - {trafficUsagePercent.toFixed(1)}% - -
-
-
-
-
- 重置日期: 每月 {traffic.resetDay} 号 -
- - ) : ( -
- 已使用: {formatBytes(traffic.used, 1)} -
仅统计模式
-
- )} -
- ) : ( -
-
- )} -
- {isOnline && netConn ? ( -
-
- - {netConn.established || 0} - ESTABLISHED -
-
- - {netConn.listen || 0} - LISTEN -
-
- - {netConn.closeWait || 0} - CLOSE_WAIT -
-
- ) : ( -
-
- )} -
-
-
- {server.tags && server.tags.length > 0 && server.tags.map(tag => ( - - #{tag} - - ))} -
-
- - {server.expireTime > 0 && -
-
Expired: {new Date(server.expireTime).toLocaleDateString('zh-CN')}
-
- } -
-
-
-
- - {/* 移动端卡片布局 */} -
- {displayAgents.map(server => ( - - ))} -
- - )} -
- ); -}; - -export default ServerList; diff --git a/portal/src/types.ts b/portal/src/types.ts deleted file mode 100644 index 74d37d8..0000000 --- a/portal/src/types.ts +++ /dev/null @@ -1,255 +0,0 @@ -/* 主题前端使用的全部类型定义。 */ - -export type ColorMode = 'light' | 'dark' | 'system'; -export type MetricsAggregation = 'avg' | 'max' | 'raw'; - -export interface PikaRuntimeConfig { - apiVersion: 'v1'; - system: { - nameZh: string; - nameEn: string; - logo: string; - icpCode: string; - version: string; - defaultView: string; - defaultColorMode: ColorMode; - }; - theme: {id: string; version: string}; - features: Record; - legacySystemConfig?: LegacySystemConfig; -} - -interface LegacySystemConfig { - SystemNameZh: string; - SystemNameEn: string; - ICPCode: string; - DefaultView: string; - Version: string; -} - -export interface ListAgentParams {tag?: string; page?: number; pageSize?: number; [key: string]: string | number | boolean | undefined} -export interface MetricsParams { - type?: 'cpu' | 'memory' | 'disk' | 'network' | 'network_connection' | 'disk_io' | 'gpu' | 'temperature' | 'monitor'; - range?: string; - start?: number; - end?: number; - interface?: string; - aggregation?: MetricsAggregation; - [key: string]: string | number | boolean | undefined; -} -export interface HistoryParams { - range?: string; - start?: number; - end?: number; - aggregation?: MetricsAggregation; - [key: string]: string | number | boolean | undefined; -} -export interface TimeRangeOption {label: string; value: string} - -export interface Agent { - id: string; - name: string; - hostname: string; - ip: string; - ipv4?: string; - ipv6?: string; - os: string; - arch: string; - version: string; - tags?: string[]; - expireTime?: number; - status: number; - visibility?: string; - weight?: number; - remark?: string; - lastSeenAt: string | number; - trafficStats?: { - enabled: boolean; - type: string; - limit: number; - used: number; - resetDay: number; - periodStart: number; - periodEnd: number; - daysUntilReset: number; - baselineRecv: number; - baselineSend: number; - alertSent80: boolean; - alertSent90: boolean; - alertSent100: boolean; - }; -} - -export interface CPUMetric { - timestamp: number; - logicalCores: number; - physicalCores: number; - modelName: string; - usagePercent: number; -} - -export interface MemoryMetric { - timestamp: number; - total: number; - used: number; - free: number; - available: number; - usagePercent: number; - swapTotal: number; - swapUsed: number; - swapFree: number; -} - -export interface DiskSummary { - usagePercent: number; - totalDisks: number; - total: number; - used: number; - free: number; -} - -export interface DiskIOSummary { - totalReadBytesRate: number; - totalWriteBytesRate: number; - totalDevices: number; -} - -export interface NetworkSummary { - totalBytesSentRate: number; - totalBytesRecvRate: number; - totalBytesSentTotal: number; - totalBytesRecvTotal: number; - totalInterfaces: number; -} - -export interface NetworkInterfaceMetric { - interface: string; - macAddress?: string; - addrs?: string[]; - bytesSentRate: number; - bytesRecvRate: number; - bytesSentTotal: number; - bytesRecvTotal: number; -} - -export interface NetworkConnectionMetric { - established: number; - synSent: number; - synRecv: number; - finWait1: number; - finWait2: number; - timeWait: number; - close: number; - closeWait: number; - lastAck: number; - listen: number; - closing: number; - total: number; -} - -export interface HostInfo { - uptime: number; - bootTime: number; - procs: number; - load1: number; - load5: number; - load15: number; - platform: string; - platformVersion: string; - kernelVersion: string; - kernelArch: string; -} - -export interface GPUMetric { - index: number; - name: string; - utilization: number; - memoryTotal: number; - memoryUsed: number; - memoryFree: number; - temperature: number; - powerUsage: number; - fanSpeed: number; -} - -export interface TemperatureMetric { - sensorKey: string; - type: string; - temperature: number; -} - -export interface MonitorData { - agentId: string; - agentName: string; - monitorId: string; - monitorName?: string; - type: string; - target?: string; - status: string; - statusCode?: number; - responseTime: number; - error?: string; - checkedAt: number; - message?: string; - contentMatch?: boolean; - certExpiryTime?: number; - certDaysLeft?: number; -} - -export interface LatestMetrics { - timestamp?: number; - cpu?: CPUMetric; - memory?: MemoryMetric; - disk?: DiskSummary; - diskIO?: DiskIOSummary; - network?: NetworkSummary; - networkInterfaces?: NetworkInterfaceMetric[]; - networkConnection?: NetworkConnectionMetric; - host?: HostInfo; - gpu?: GPUMetric[]; - temperature?: TemperatureMetric[]; - monitors?: MonitorData[]; -} - -export interface PublicMonitor { - id: string; - name: string; - type: 'http' | 'https' | 'tcp' | 'icmp' | 'ping'; - target: string; - showTargetPublic: boolean; - description?: string; - enabled: boolean; - interval: number; - agentIds: string[]; - agentCount: number; - status: string; - responseTime: number; - responseTimeMin: number; - responseTimeMax: number; - certExpiryTime: number; - certDaysLeft: number; - agentStats: {up: number; down: number; unknown: number}; - lastCheckTime: number; -} - -export interface AgentMonitorStat { - agentId: string; - agentName: string; - monitorId: string; - type: string; - target: string; - status: string; - statusCode: number; - responseTime: number; - checkedAt: number; - message: string; - certExpiryTime: number; - certDaysLeft: number; -} - -export interface MetricPoint {timestamp: number; value: number} -export interface MetricSeries {name: string; labels?: Record; data: MetricPoint[]} -export interface MetricsResponse {agentId: string; type: string; range: string; series: MetricSeries[]} -export interface TagsResponse {tags: string[]} -export interface NetworkInterfacesResponse {interfaces: string[]} -export interface CurrentUser {userId: string; username: string} diff --git a/portal/tsconfig.app.json b/portal/tsconfig.app.json deleted file mode 100644 index bf71a42..0000000 --- a/portal/tsconfig.app.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", - "target": "ES2022", - "useDefineForClassFields": true, - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "module": "ESNext", - "types": ["vite/client"], - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - "strict": false, - - "paths": { - "@/*": [ - "./src/*" - ] - }, - "allowSyntheticDefaultImports": true - }, - "include": ["src"] -} diff --git a/portal/tsconfig.json b/portal/tsconfig.json deleted file mode 100644 index 4fa15f4..0000000 --- a/portal/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "files": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.node.json" - } - ], - "compilerOptions": { - "paths": { - "@/*": [ - "./src/*" - ] - } - } -} diff --git a/portal/tsconfig.node.json b/portal/tsconfig.node.json deleted file mode 100644 index 5104571..0000000 --- a/portal/tsconfig.node.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", - "target": "ES2023", - "lib": ["ES2023"], - "module": "ESNext", - "types": ["node"], - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "moduleDetection": "force", - "noEmit": true, - }, - "include": ["vite.config.ts"] -} diff --git a/portal/vite.config.ts b/portal/vite.config.ts deleted file mode 100644 index 76b917d..0000000 --- a/portal/vite.config.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {defineConfig} from 'vite'; -import react from '@vitejs/plugin-react'; -import tailwindcss from '@tailwindcss/vite'; -import path from 'path'; - -export default defineConfig(({command}) => ({ - base: command === 'serve' ? '/' : '/theme-assets/', - plugins: [react(), tailwindcss()], - publicDir: path.resolve(__dirname, 'public'), - resolve: {alias: {'@': path.resolve(__dirname, './src')}}, - build: { - outDir: path.resolve(__dirname, 'dist'), - emptyOutDir: true, - assetsDir: 'assets', - }, - server: { - port: 5173, - proxy: {'/api/': {target: 'http://localhost:8080/', changeOrigin: true}}, - }, -})); diff --git a/portal/yarn.lock b/portal/yarn.lock deleted file mode 100644 index d802cd4..0000000 --- a/portal/yarn.lock +++ /dev/null @@ -1,1384 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@eslint-community/eslint-utils@^4.8.0", "@eslint-community/eslint-utils@^4.9.1": - version "4.10.1" - resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz" - integrity sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg== - dependencies: - eslint-visitor-keys "^3.4.3" - -"@eslint-community/regexpp@^4.12.2": - version "4.12.2" - resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz" - integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== - -"@eslint/config-array@^0.23.5": - version "0.23.5" - resolved "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz" - integrity sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA== - dependencies: - "@eslint/object-schema" "^3.0.5" - debug "^4.3.1" - minimatch "^10.2.4" - -"@eslint/config-helpers@^0.7.0": - version "0.7.0" - resolved "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz" - integrity sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw== - dependencies: - "@eslint/core" "^1.2.1" - -"@eslint/core@^1.2.1": - version "1.2.1" - resolved "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz" - integrity sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ== - dependencies: - "@types/json-schema" "^7.0.15" - -"@eslint/object-schema@^3.0.5": - version "3.0.5" - resolved "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz" - integrity sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw== - -"@eslint/plugin-kit@^0.7.2": - version "0.7.2" - resolved "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz" - integrity sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A== - dependencies: - "@eslint/core" "^1.2.1" - levn "^0.4.1" - -"@floating-ui/core@^1.8.0": - version "1.8.0" - resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz" - integrity sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ== - dependencies: - "@floating-ui/utils" "^0.2.12" - -"@floating-ui/dom@^1.8.0": - version "1.8.0" - resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz" - integrity sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg== - dependencies: - "@floating-ui/core" "^1.8.0" - "@floating-ui/utils" "^0.2.12" - -"@floating-ui/react-dom@^2.0.0": - version "2.1.9" - resolved "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.9.tgz" - integrity sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg== - dependencies: - "@floating-ui/dom" "^1.8.0" - -"@floating-ui/utils@^0.2.12": - version "0.2.12" - resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz" - integrity sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww== - -"@humanfs/core@^0.19.2": - version "0.19.2" - resolved "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz" - integrity sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA== - dependencies: - "@humanfs/types" "^0.15.0" - -"@humanfs/node@^0.16.6": - version "0.16.8" - resolved "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz" - integrity sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ== - dependencies: - "@humanfs/core" "^0.19.2" - "@humanfs/types" "^0.15.0" - "@humanwhocodes/retry" "^0.4.0" - -"@humanfs/types@^0.15.0": - version "0.15.0" - resolved "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz" - integrity sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q== - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/retry@^0.4.0", "@humanwhocodes/retry@^0.4.2": - version "0.4.3" - resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz" - integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== - -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.13" - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz" - integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.5.0" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/remapping@^2.3.5": - version "2.3.5" - resolved "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz" - integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0", "@jridgewell/sourcemap-codec@^1.5.5": - version "1.5.5" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz" - integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== - -"@jridgewell/trace-mapping@^0.3.24": - version "0.3.31" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz" - integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@oxc-project/types@=0.139.0": - version "0.139.0" - resolved "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz" - integrity sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw== - -"@radix-ui/primitive@1.1.7": - version "1.1.7" - resolved "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.7.tgz" - integrity sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q== - -"@radix-ui/react-arrow@1.1.15": - version "1.1.15" - resolved "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.15.tgz" - integrity sha512-v4zggRcjadnI+ClKDuijlQEW4tw3NoaeHc/PwpKnLoLLKNUG4InLegkstooLcRIUWCs+8L22dGURCVuFfOKfnA== - dependencies: - "@radix-ui/react-primitive" "2.1.10" - -"@radix-ui/react-compose-refs@1.1.5": - version "1.1.5" - resolved "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.5.tgz" - integrity sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA== - -"@radix-ui/react-context@1.2.2": - version "1.2.2" - resolved "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.2.2.tgz" - integrity sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA== - -"@radix-ui/react-dismissable-layer@1.1.19": - version "1.1.19" - resolved "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.19.tgz" - integrity sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w== - dependencies: - "@radix-ui/primitive" "1.1.7" - "@radix-ui/react-compose-refs" "1.1.5" - "@radix-ui/react-primitive" "2.1.10" - "@radix-ui/react-use-callback-ref" "1.1.4" - "@radix-ui/react-use-effect-event" "0.0.5" - -"@radix-ui/react-id@1.1.4": - version "1.1.4" - resolved "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.4.tgz" - integrity sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA== - dependencies: - "@radix-ui/react-use-layout-effect" "1.1.4" - -"@radix-ui/react-popper@1.3.7": - version "1.3.7" - resolved "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.3.7.tgz" - integrity sha512-UsJrrd7w4wuKKTdvd/DNERVlwSlUcyXzjhyDwBk+3aPOsCjOY6ZSbxuw8E6lZTjjfP8Cpd0J8VVkrYUWyGYXyg== - dependencies: - "@floating-ui/react-dom" "^2.0.0" - "@radix-ui/react-arrow" "1.1.15" - "@radix-ui/react-compose-refs" "1.1.5" - "@radix-ui/react-context" "1.2.2" - "@radix-ui/react-primitive" "2.1.10" - "@radix-ui/react-use-callback-ref" "1.1.4" - "@radix-ui/react-use-layout-effect" "1.1.4" - "@radix-ui/react-use-rect" "1.1.4" - "@radix-ui/react-use-size" "1.1.4" - "@radix-ui/rect" "1.1.3" - -"@radix-ui/react-portal@1.1.17": - version "1.1.17" - resolved "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.17.tgz" - integrity sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ== - dependencies: - "@radix-ui/react-primitive" "2.1.10" - "@radix-ui/react-use-layout-effect" "1.1.4" - -"@radix-ui/react-presence@1.1.10": - version "1.1.10" - resolved "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.10.tgz" - integrity sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw== - dependencies: - "@radix-ui/react-use-layout-effect" "1.1.4" - -"@radix-ui/react-primitive@2.1.10": - version "2.1.10" - resolved "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.10.tgz" - integrity sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg== - dependencies: - "@radix-ui/react-slot" "1.3.3" - -"@radix-ui/react-slot@1.3.3": - version "1.3.3" - resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.3.3.tgz" - integrity sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q== - dependencies: - "@radix-ui/react-compose-refs" "1.1.5" - -"@radix-ui/react-tooltip@^1.2.12": - version "1.2.16" - resolved "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.16.tgz" - integrity sha512-6EamKFRRnlpdadndbZ6LMwycfwkwPte1B42hs6QA0gYhjaOKqW4PZ4pjaW9UrlDX5eVt/OjncE7BFTPL5nmZhg== - dependencies: - "@radix-ui/primitive" "1.1.7" - "@radix-ui/react-compose-refs" "1.1.5" - "@radix-ui/react-context" "1.2.2" - "@radix-ui/react-dismissable-layer" "1.1.19" - "@radix-ui/react-id" "1.1.4" - "@radix-ui/react-popper" "1.3.7" - "@radix-ui/react-portal" "1.1.17" - "@radix-ui/react-presence" "1.1.10" - "@radix-ui/react-primitive" "2.1.10" - "@radix-ui/react-slot" "1.3.3" - "@radix-ui/react-use-controllable-state" "1.2.6" - "@radix-ui/react-use-layout-effect" "1.1.4" - "@radix-ui/react-visually-hidden" "1.2.11" - -"@radix-ui/react-use-callback-ref@1.1.4": - version "1.1.4" - resolved "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.4.tgz" - integrity sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ== - -"@radix-ui/react-use-controllable-state@1.2.6": - version "1.2.6" - resolved "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.6.tgz" - integrity sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ== - dependencies: - "@radix-ui/primitive" "1.1.7" - "@radix-ui/react-use-effect-event" "0.0.5" - "@radix-ui/react-use-layout-effect" "1.1.4" - -"@radix-ui/react-use-effect-event@0.0.5": - version "0.0.5" - resolved "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.5.tgz" - integrity sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg== - dependencies: - "@radix-ui/react-use-layout-effect" "1.1.4" - -"@radix-ui/react-use-layout-effect@1.1.4": - version "1.1.4" - resolved "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.4.tgz" - integrity sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw== - -"@radix-ui/react-use-rect@1.1.4": - version "1.1.4" - resolved "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.4.tgz" - integrity sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ== - dependencies: - "@radix-ui/rect" "1.1.3" - -"@radix-ui/react-use-size@1.1.4": - version "1.1.4" - resolved "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.4.tgz" - integrity sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw== - dependencies: - "@radix-ui/react-use-layout-effect" "1.1.4" - -"@radix-ui/react-visually-hidden@1.2.11": - version "1.2.11" - resolved "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.11.tgz" - integrity sha512-NFS86RYYZb4/exihaESBGOpMJFz8MGLAfu3mOBSGByVnVPC9JPASfYubxd/8KbkQK0sYAv8lVQDEQukDX/qXvQ== - dependencies: - "@radix-ui/react-primitive" "2.1.10" - -"@radix-ui/rect@1.1.3": - version "1.1.3" - resolved "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.3.tgz" - integrity sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw== - -"@reduxjs/toolkit@^1.9.0 || 2.x.x": - version "2.12.0" - resolved "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.12.0.tgz" - integrity sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw== - dependencies: - "@standard-schema/spec" "^1.0.0" - "@standard-schema/utils" "^0.3.0" - immer "^11.0.0" - redux "^5.0.1" - redux-thunk "^3.1.0" - reselect "^5.1.0" - -"@rolldown/binding-darwin-arm64@1.1.5": - version "1.1.5" - resolved "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz" - integrity sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw== - -"@rolldown/pluginutils@^1.0.0", "@rolldown/pluginutils@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz" - integrity sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw== - -"@standard-schema/spec@^1.0.0": - version "1.1.0" - resolved "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz" - integrity sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w== - -"@standard-schema/utils@^0.3.0": - version "0.3.0" - resolved "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz" - integrity sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g== - -"@tailwindcss/node@4.3.3": - version "4.3.3" - resolved "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz" - integrity sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg== - dependencies: - "@jridgewell/remapping" "^2.3.5" - enhanced-resolve "^5.24.1" - jiti "^2.7.0" - lightningcss "1.32.0" - magic-string "^0.30.21" - source-map-js "^1.2.1" - tailwindcss "4.3.3" - -"@tailwindcss/oxide-darwin-arm64@4.3.3": - version "4.3.3" - resolved "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz" - integrity sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw== - -"@tailwindcss/oxide@4.3.3": - version "4.3.3" - resolved "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz" - integrity sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA== - optionalDependencies: - "@tailwindcss/oxide-android-arm64" "4.3.3" - "@tailwindcss/oxide-darwin-arm64" "4.3.3" - "@tailwindcss/oxide-darwin-x64" "4.3.3" - "@tailwindcss/oxide-freebsd-x64" "4.3.3" - "@tailwindcss/oxide-linux-arm-gnueabihf" "4.3.3" - "@tailwindcss/oxide-linux-arm64-gnu" "4.3.3" - "@tailwindcss/oxide-linux-arm64-musl" "4.3.3" - "@tailwindcss/oxide-linux-x64-gnu" "4.3.3" - "@tailwindcss/oxide-linux-x64-musl" "4.3.3" - "@tailwindcss/oxide-wasm32-wasi" "4.3.3" - "@tailwindcss/oxide-win32-arm64-msvc" "4.3.3" - "@tailwindcss/oxide-win32-x64-msvc" "4.3.3" - -"@tailwindcss/vite@^4.3.2": - version "4.3.3" - resolved "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.3.tgz" - integrity sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw== - dependencies: - "@tailwindcss/node" "4.3.3" - "@tailwindcss/oxide" "4.3.3" - tailwindcss "4.3.3" - -"@tanstack/query-core@5.101.4": - version "5.101.4" - resolved "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.101.4.tgz" - integrity sha512-gNwcvOJcRbLWPOLG/2OBm+zM+Yv+MKsXKEOWC57USuZDEsI71hEErQsiEGx5wX9rzWWkfwM0fVSPoiIFSsxfiw== - -"@tanstack/react-query@^5.101.2": - version "5.101.4" - resolved "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.101.4.tgz" - integrity sha512-yRg2pfOCxIs4ZJW3XYYHU/WgtD04FHSnfHlpRT7h7pR77hwkdRG4wxbKe4aq6P0RvXUTBSQpQeadS1SUYUe+KA== - dependencies: - "@tanstack/query-core" "5.101.4" - -"@types/d3-array@^3.0.3": - version "3.2.2" - resolved "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz" - integrity sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw== - -"@types/d3-color@*": - version "3.1.3" - resolved "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz" - integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A== - -"@types/d3-ease@^3.0.0": - version "3.0.2" - resolved "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz" - integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA== - -"@types/d3-interpolate@^3.0.1": - version "3.0.4" - resolved "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz" - integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA== - dependencies: - "@types/d3-color" "*" - -"@types/d3-path@*": - version "3.1.1" - resolved "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz" - integrity sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg== - -"@types/d3-scale@^4.0.2": - version "4.0.9" - resolved "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz" - integrity sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw== - dependencies: - "@types/d3-time" "*" - -"@types/d3-shape@^3.1.0": - version "3.1.8" - resolved "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz" - integrity sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w== - dependencies: - "@types/d3-path" "*" - -"@types/d3-time@*", "@types/d3-time@^3.0.0": - version "3.0.4" - resolved "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz" - integrity sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g== - -"@types/d3-timer@^3.0.0": - version "3.0.2" - resolved "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz" - integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw== - -"@types/esrecurse@^4.3.1": - version "4.3.1" - resolved "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz" - integrity sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw== - -"@types/estree@^1.0.6", "@types/estree@^1.0.8": - version "1.0.9" - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz" - integrity sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg== - -"@types/json-schema@^7.0.15": - version "7.0.15" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/node@^20.19.0 || >=22.12.0", "@types/node@^26.1.1": - version "26.1.2" - resolved "https://registry.npmjs.org/@types/node/-/node-26.1.2.tgz" - integrity sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg== - dependencies: - undici-types "~8.3.0" - -"@types/react-dom@*", "@types/react-dom@^19.2.3": - version "19.2.4" - resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.4.tgz" - integrity sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw== - -"@types/react@*", "@types/react@^18.2.25 || ^19", "@types/react@^19.2.0", "@types/react@^19.2.17": - version "19.2.18" - resolved "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz" - integrity sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w== - dependencies: - csstype "^3.2.2" - -"@types/use-sync-external-store@^0.0.6": - version "0.0.6" - resolved "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz" - integrity sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg== - -"@typescript-eslint/eslint-plugin@8.65.0": - version "8.65.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.65.0.tgz" - integrity sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA== - dependencies: - "@eslint-community/regexpp" "^4.12.2" - "@typescript-eslint/scope-manager" "8.65.0" - "@typescript-eslint/type-utils" "8.65.0" - "@typescript-eslint/utils" "8.65.0" - "@typescript-eslint/visitor-keys" "8.65.0" - ignore "^7.0.5" - natural-compare "^1.4.0" - ts-api-utils "^2.5.0" - -"@typescript-eslint/parser@^8.65.0", "@typescript-eslint/parser@8.65.0": - version "8.65.0" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.65.0.tgz" - integrity sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA== - dependencies: - "@typescript-eslint/scope-manager" "8.65.0" - "@typescript-eslint/types" "8.65.0" - "@typescript-eslint/typescript-estree" "8.65.0" - "@typescript-eslint/visitor-keys" "8.65.0" - debug "^4.4.3" - -"@typescript-eslint/project-service@8.65.0": - version "8.65.0" - resolved "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.65.0.tgz" - integrity sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q== - dependencies: - "@typescript-eslint/tsconfig-utils" "^8.65.0" - "@typescript-eslint/types" "^8.65.0" - debug "^4.4.3" - -"@typescript-eslint/scope-manager@8.65.0": - version "8.65.0" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.65.0.tgz" - integrity sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg== - dependencies: - "@typescript-eslint/types" "8.65.0" - "@typescript-eslint/visitor-keys" "8.65.0" - -"@typescript-eslint/tsconfig-utils@^8.65.0", "@typescript-eslint/tsconfig-utils@8.65.0": - version "8.65.0" - resolved "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.65.0.tgz" - integrity sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg== - -"@typescript-eslint/type-utils@8.65.0": - version "8.65.0" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.65.0.tgz" - integrity sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g== - dependencies: - "@typescript-eslint/types" "8.65.0" - "@typescript-eslint/typescript-estree" "8.65.0" - "@typescript-eslint/utils" "8.65.0" - debug "^4.4.3" - ts-api-utils "^2.5.0" - -"@typescript-eslint/types@^8.65.0", "@typescript-eslint/types@8.65.0": - version "8.65.0" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.65.0.tgz" - integrity sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg== - -"@typescript-eslint/typescript-estree@8.65.0": - version "8.65.0" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.65.0.tgz" - integrity sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg== - dependencies: - "@typescript-eslint/project-service" "8.65.0" - "@typescript-eslint/tsconfig-utils" "8.65.0" - "@typescript-eslint/types" "8.65.0" - "@typescript-eslint/visitor-keys" "8.65.0" - debug "^4.4.3" - minimatch "^10.2.2" - semver "^7.7.3" - tinyglobby "^0.2.15" - ts-api-utils "^2.5.0" - -"@typescript-eslint/utils@8.65.0": - version "8.65.0" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.65.0.tgz" - integrity sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA== - dependencies: - "@eslint-community/eslint-utils" "^4.9.1" - "@typescript-eslint/scope-manager" "8.65.0" - "@typescript-eslint/types" "8.65.0" - "@typescript-eslint/typescript-estree" "8.65.0" - -"@typescript-eslint/visitor-keys@8.65.0": - version "8.65.0" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.65.0.tgz" - integrity sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A== - dependencies: - "@typescript-eslint/types" "8.65.0" - eslint-visitor-keys "^5.0.0" - -"@vitejs/plugin-react@^6.0.3": - version "6.0.5" - resolved "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.5.tgz" - integrity sha512-BOVzne/NL162sMdResB25mUv+vWMF5NoAjNf09TeGlE7ZpszZWSD3winycicLJw72yeVsoCn/2kOhEuCvEShMA== - dependencies: - "@rolldown/pluginutils" "^1.0.1" - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.16.0: - version "8.18.0" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz" - integrity sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ== - -ajv@^6.14.0: - version "6.15.0" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz" - integrity sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -balanced-match@^4.0.2: - version "4.0.4" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz" - integrity sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA== - -brace-expansion@^5.0.8: - version "5.0.9" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz" - integrity sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg== - dependencies: - balanced-match "^4.0.2" - -clsx@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz" - integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== - -cookie@^1.0.1: - version "1.1.1" - resolved "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz" - integrity sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ== - -cross-spawn@^7.0.6: - version "7.0.6" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" - integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -csstype@^3.2.2: - version "3.2.3" - resolved "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz" - integrity sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ== - -d3-array@^3.1.6, "d3-array@2 - 3", "d3-array@2.10.0 - 3": - version "3.2.4" - resolved "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz" - integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== - dependencies: - internmap "1 - 2" - -"d3-color@1 - 3": - version "3.1.0" - resolved "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz" - integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== - -d3-ease@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz" - integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== - -"d3-format@1 - 3": - version "3.1.2" - resolved "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz" - integrity sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg== - -d3-interpolate@^3.0.1, "d3-interpolate@1.2.0 - 3": - version "3.0.1" - resolved "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz" - integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== - dependencies: - d3-color "1 - 3" - -d3-path@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz" - integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== - -d3-scale@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz" - integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== - dependencies: - d3-array "2.10.0 - 3" - d3-format "1 - 3" - d3-interpolate "1.2.0 - 3" - d3-time "2.1.1 - 3" - d3-time-format "2 - 4" - -d3-shape@^3.1.0: - version "3.2.0" - resolved "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz" - integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== - dependencies: - d3-path "^3.1.0" - -"d3-time-format@2 - 4": - version "4.1.0" - resolved "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz" - integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== - dependencies: - d3-time "1 - 3" - -d3-time@^3.0.0, "d3-time@1 - 3", "d3-time@2.1.1 - 3": - version "3.1.0" - resolved "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz" - integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== - dependencies: - d3-array "2 - 3" - -d3-timer@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz" - integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== - -dayjs@^1.11.21: - version "1.11.21" - resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz" - integrity sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA== - -debug@^4.3.1, debug@^4.3.2, debug@^4.4.3: - version "4.4.3" - resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz" - integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== - dependencies: - ms "^2.1.3" - -decimal.js-light@^2.5.1: - version "2.5.1" - resolved "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz" - integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -detect-libc@^2.0.3: - version "2.1.2" - resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz" - integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== - -enhanced-resolve@^5.24.1: - version "5.24.5" - resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz" - integrity sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.3.3" - -es-toolkit@^1.39.3: - version "1.50.0" - resolved "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.50.0.tgz" - integrity sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-scope@^9.1.2: - version "9.1.2" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz" - integrity sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ== - dependencies: - "@types/esrecurse" "^4.3.1" - "@types/estree" "^1.0.8" - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint-visitor-keys@^5.0.0, eslint-visitor-keys@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz" - integrity sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA== - -eslint@^10.7.0, "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^8.57.0 || ^9.0.0 || ^10.0.0": - version "10.8.0" - resolved "https://registry.npmjs.org/eslint/-/eslint-10.8.0.tgz" - integrity sha512-nuKKvN+oIBO0koN7Tm7dlkmnkc21mtt0QJLwAKzjLq14y6lRTdVG36MZHJ8eQHwdJMwZbQNMlPOYedMq/oVJvQ== - dependencies: - "@eslint-community/eslint-utils" "^4.8.0" - "@eslint-community/regexpp" "^4.12.2" - "@eslint/config-array" "^0.23.5" - "@eslint/config-helpers" "^0.7.0" - "@eslint/core" "^1.2.1" - "@eslint/plugin-kit" "^0.7.2" - "@humanfs/node" "^0.16.6" - "@humanwhocodes/module-importer" "^1.0.1" - "@humanwhocodes/retry" "^0.4.2" - "@types/estree" "^1.0.6" - ajv "^6.14.0" - cross-spawn "^7.0.6" - debug "^4.3.2" - escape-string-regexp "^4.0.0" - eslint-scope "^9.1.2" - eslint-visitor-keys "^5.0.1" - espree "^11.2.0" - esquery "^1.7.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^8.0.0" - find-up "^5.0.0" - glob-parent "^6.0.2" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - json-stable-stringify-without-jsonify "^1.0.1" - minimatch "^10.2.5" - natural-compare "^1.4.0" - optionator "^0.9.3" - -espree@^11.2.0: - version "11.2.0" - resolved "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz" - integrity sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw== - dependencies: - acorn "^8.16.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^5.0.1" - -esquery@^1.7.0: - version "1.7.0" - resolved "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz" - integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -eventemitter3@^5.0.1: - version "5.0.4" - resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz" - integrity sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw== - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fdir@^6.5.0: - version "6.5.0" - resolved "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz" - integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== - -file-entry-cache@^8.0.0: - version "8.0.0" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz" - integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== - dependencies: - flat-cache "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz" - integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.4" - -flatted@^3.2.9: - version "3.4.4" - resolved "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz" - integrity sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q== - -fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -globals@^17.7.0: - version "17.8.0" - resolved "https://registry.npmjs.org/globals/-/globals-17.8.0.tgz" - integrity sha512-Zz/LMDZScFmkakeL2cTHzf+PbWKdpU3uclqkZT7TjDG58j5WPt0PpA+n9uPI24fZtlw07q0OtEi84K+umsRzqQ== - -graceful-fs@^4.2.4: - version "4.2.11" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -ignore@^5.2.0: - version "5.3.2" - resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz" - integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== - -ignore@^7.0.5: - version "7.0.6" - resolved "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz" - integrity sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw== - -immer@^11.0.0, immer@^11.1.8: - version "11.1.15" - resolved "https://registry.npmjs.org/immer/-/immer-11.1.15.tgz" - integrity sha512-VrNANlmnWQnh5COXIIOQXM9oOJw7naGKlBT74ZOOR6lpVXc3gFEu9FJLDFcpCJ2j+NWr8TIwtWD//T6ZX6TKiQ== - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -"internmap@1 - 2": - version "2.0.3" - resolved "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz" - integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-glob@^4.0.0, is-glob@^4.0.3: - version "4.0.3" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -jiti@*, jiti@^2.7.0, jiti@>=1.21.0: - version "2.7.0" - resolved "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz" - integrity sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ== - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -keyv@^4.5.4: - version "4.5.4" - resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lightningcss-darwin-arm64@1.32.0: - version "1.32.0" - resolved "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz" - integrity sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ== - -lightningcss@^1.32.0, lightningcss@1.32.0: - version "1.32.0" - resolved "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz" - integrity sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ== - dependencies: - detect-libc "^2.0.3" - optionalDependencies: - lightningcss-android-arm64 "1.32.0" - lightningcss-darwin-arm64 "1.32.0" - lightningcss-darwin-x64 "1.32.0" - lightningcss-freebsd-x64 "1.32.0" - lightningcss-linux-arm-gnueabihf "1.32.0" - lightningcss-linux-arm64-gnu "1.32.0" - lightningcss-linux-arm64-musl "1.32.0" - lightningcss-linux-x64-gnu "1.32.0" - lightningcss-linux-x64-musl "1.32.0" - lightningcss-win32-arm64-msvc "1.32.0" - lightningcss-win32-x64-msvc "1.32.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lucide-react@^1.24.0: - version "1.28.0" - resolved "https://registry.npmjs.org/lucide-react/-/lucide-react-1.28.0.tgz" - integrity sha512-fARAFJULsGuDDydjp6+6blekG/sBIM29TerzLjc9bQUKAcEfrSc4ZQKb25KRz4OMKd87cZTb5dgq0w/T6KufVg== - -magic-string@^0.30.21: - version "0.30.21" - resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz" - integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== - dependencies: - "@jridgewell/sourcemap-codec" "^1.5.5" - -minimatch@^10.2.2, minimatch@^10.2.4, minimatch@^10.2.5: - version "10.2.6" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz" - integrity sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A== - dependencies: - brace-expansion "^5.0.8" - -ms@^2.1.3: - version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -nanoid@^3.3.16: - version "3.3.16" - resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz" - integrity sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -optionator@^0.9.3: - version "0.9.4" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz" - integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.5" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -picocolors@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" - integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== - -"picomatch@^3 || ^4", picomatch@^4.0.4, picomatch@^4.0.5: - version "4.0.5" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz" - integrity sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A== - -postcss@^8.5.16: - version "8.5.25" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz" - integrity sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw== - dependencies: - nanoid "^3.3.16" - picocolors "^1.1.1" - source-map-js "^1.2.1" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -"react-dom@^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", react-dom@^19.2.7, react-dom@>=16.8.0, react-dom@>=18: - version "19.2.8" - resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz" - integrity sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ== - dependencies: - scheduler "^0.27.0" - -"react-is@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0": - version "19.2.8" - resolved "https://registry.npmjs.org/react-is/-/react-is-19.2.8.tgz" - integrity sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ== - -"react-redux@^7.2.1 || ^8.1.3 || ^9.0.0", "react-redux@8.x.x || 9.x.x": - version "9.3.0" - resolved "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz" - integrity sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g== - dependencies: - "@types/use-sync-external-store" "^0.0.6" - use-sync-external-store "^1.4.0" - -react-router-dom@^7.18.1: - version "7.18.2" - resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.2.tgz" - integrity sha512-AIKJ/jgGlFb3EbfCXk5Gzshiwt+l3mqbCrNjmEWMMjqQxNJ3svBa6bgzFyCC2Sw3RA0VWF1kg3uQf2OFhxb8hw== - dependencies: - react-router "7.18.2" - -react-router@7.18.2: - version "7.18.2" - resolved "https://registry.npmjs.org/react-router/-/react-router-7.18.2.tgz" - integrity sha512-aUVMjFm3GAPTTZL7oYr5E7ETiqfQCHRLH+B+5afnICvf0r7kkK4eR6SMuwbSTJw/7t+12khT/Kahij49fqOCIg== - dependencies: - cookie "^1.0.1" - set-cookie-parser "^2.6.0" - -"react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.9.0 || ^17.0.0 || ^18 || ^19", "react@^18 || ^19", "react@^18.0 || ^19", react@^19.2.7, react@^19.2.8, react@>=16.8.0, react@>=18: - version "19.2.8" - resolved "https://registry.npmjs.org/react/-/react-19.2.8.tgz" - integrity sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw== - -recharts@^3.9.2: - version "3.10.1" - resolved "https://registry.npmjs.org/recharts/-/recharts-3.10.1.tgz" - integrity sha512-QXFrvt6IVcw7eeZCoyXTwkIJAX3Dv1nyVhMicXJ47GsGDDpcN8z6o644DibE9XjpBTThtsomLKnTV6lc+cVFUA== - dependencies: - "@reduxjs/toolkit" "^1.9.0 || 2.x.x" - clsx "^2.1.1" - decimal.js-light "^2.5.1" - es-toolkit "^1.39.3" - eventemitter3 "^5.0.1" - immer "^11.1.8" - react-redux "8.x.x || 9.x.x" - reselect "5.2.0" - tiny-invariant "^1.3.3" - use-sync-external-store "^1.2.2" - victory-vendor "^37.0.2" - -redux-thunk@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz" - integrity sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw== - -redux@^5.0.0, redux@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz" - integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w== - -reselect@^5.1.0, reselect@5.2.0: - version "5.2.0" - resolved "https://registry.npmjs.org/reselect/-/reselect-5.2.0.tgz" - integrity sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw== - -rolldown@~1.1.4: - version "1.1.5" - resolved "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz" - integrity sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA== - dependencies: - "@oxc-project/types" "=0.139.0" - "@rolldown/pluginutils" "^1.0.0" - optionalDependencies: - "@rolldown/binding-android-arm64" "1.1.5" - "@rolldown/binding-darwin-arm64" "1.1.5" - "@rolldown/binding-darwin-x64" "1.1.5" - "@rolldown/binding-freebsd-x64" "1.1.5" - "@rolldown/binding-linux-arm-gnueabihf" "1.1.5" - "@rolldown/binding-linux-arm64-gnu" "1.1.5" - "@rolldown/binding-linux-arm64-musl" "1.1.5" - "@rolldown/binding-linux-ppc64-gnu" "1.1.5" - "@rolldown/binding-linux-s390x-gnu" "1.1.5" - "@rolldown/binding-linux-x64-gnu" "1.1.5" - "@rolldown/binding-linux-x64-musl" "1.1.5" - "@rolldown/binding-openharmony-arm64" "1.1.5" - "@rolldown/binding-wasm32-wasi" "1.1.5" - "@rolldown/binding-win32-arm64-msvc" "1.1.5" - "@rolldown/binding-win32-x64-msvc" "1.1.5" - -scheduler@^0.27.0: - version "0.27.0" - resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz" - integrity sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q== - -semver@^7.7.3: - version "7.8.5" - resolved "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz" - integrity sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA== - -set-cookie-parser@^2.6.0: - version "2.7.2" - resolved "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz" - integrity sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw== - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -source-map-js@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz" - integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== - -tailwind-merge@^3.6.0: - version "3.6.0" - resolved "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz" - integrity sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w== - -tailwindcss@4.3.3: - version "4.3.3" - resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz" - integrity sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ== - -tapable@^2.3.3: - version "2.3.3" - resolved "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz" - integrity sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A== - -tiny-invariant@^1.3.3: - version "1.3.3" - resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz" - integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== - -tinyglobby@^0.2.15, tinyglobby@^0.2.17: - version "0.2.17" - resolved "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz" - integrity sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g== - dependencies: - fdir "^6.5.0" - picomatch "^4.0.4" - -ts-api-utils@^2.5.0: - version "2.5.0" - resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz" - integrity sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA== - -tw-animate-css@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz" - integrity sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ== - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -typescript-eslint@^8.63.0: - version "8.65.0" - resolved "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.65.0.tgz" - integrity sha512-/ggrHAwyjENDusvyxbuqxAC2dTnZg/Z8F+fgQtYIz+L6n/9HfSlEZcFGV/NsMNa6CkGk0xUjUAFwC0vHOflvIA== - dependencies: - "@typescript-eslint/eslint-plugin" "8.65.0" - "@typescript-eslint/parser" "8.65.0" - "@typescript-eslint/typescript-estree" "8.65.0" - "@typescript-eslint/utils" "8.65.0" - -typescript@>=4.8.4, "typescript@>=4.8.4 <6.1.0", typescript@~6.0.3: - version "6.0.3" - resolved "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz" - integrity sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw== - -undici-types@~8.3.0: - version "8.3.0" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz" - integrity sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ== - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -use-sync-external-store@^1.2.2, use-sync-external-store@^1.4.0: - version "1.6.0" - resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz" - integrity sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w== - -victory-vendor@^37.0.2: - version "37.3.6" - resolved "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz" - integrity sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ== - dependencies: - "@types/d3-array" "^3.0.3" - "@types/d3-ease" "^3.0.0" - "@types/d3-interpolate" "^3.0.1" - "@types/d3-scale" "^4.0.2" - "@types/d3-shape" "^3.1.0" - "@types/d3-time" "^3.0.0" - "@types/d3-timer" "^3.0.0" - d3-array "^3.1.6" - d3-ease "^3.0.1" - d3-interpolate "^3.0.1" - d3-scale "^4.0.2" - d3-shape "^3.1.0" - d3-time "^3.0.0" - d3-timer "^3.0.1" - -"vite@^5.2.0 || ^6 || ^7 || ^8", vite@^8.0.0, vite@8.1.4: - version "8.1.4" - resolved "https://registry.npmjs.org/vite/-/vite-8.1.4.tgz" - integrity sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ== - dependencies: - lightningcss "^1.32.0" - picomatch "^4.0.5" - postcss "^8.5.16" - rolldown "~1.1.4" - tinyglobby "^0.2.17" - optionalDependencies: - fsevents "~2.3.3" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.5: - version "1.2.5" - resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz" - integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/web/README.md b/web/README.md index a84d477..4b2203c 100644 --- a/web/README.md +++ b/web/README.md @@ -2,24 +2,35 @@ `web/` 是官方管理后台前端(React/Vite),发布到 `/admin/assets/*`。 -官方默认公开主题在仓库根目录的 `portal/`,是一个独立的项目,可以搬迁到单独的仓库。 +官方默认公开主题是独立项目 [`pika-monitor/pika-default-theme`](https://github.com/pika-monitor/pika-default-theme)。本地开发时,`Makefile` 默认从同级目录 `../pika-default-theme` 构建它。 ## 开发 ```bash -cd web && npm ci && npm run dev # 管理后台,http://localhost:5174/admin/ -cd portal && npm ci && npm run dev # 默认主题,http://localhost:5173/ +cd web && npm ci && npm run dev # 管理后台,http://localhost:5174/admin/ +cd ../pika-default-theme && npm ci && npm run dev # 默认主题,http://localhost:5173/ ``` 两者都把 `/api/*` 代理到 `http://localhost:8080`,可以同时启动。 ## 构建 -`make build-web` 分别构建 `web/`(管理后台 → `web/dist/admin/`)和 `portal/`(默认主题 → `portal/dist/`)。后端直接从这两个目录读取,无需组装脚本。 +`make build-web` 构建 `web/` 和独立的默认主题,将两者放到独立的发布目录: + +- 管理后台:`web/dist/`; +- 默认主题:`themes/default/`。 + +如果主题源码不在默认位置,可以显式指定: + +```bash +make DEFAULT_THEME_DIR=/path/to/pika-default-theme build-web +``` + +GitHub Actions 使用 `.github/default-theme.ref` 中的完整 Git Commit SHA 锁定默认主题,保证同一 Pika 版本的发布构建可复现。 ## 运行路径 - 公开主题:`/`、`/servers/*`、`/monitors/*`; - 管理后台:`/admin/*`,包括 `/admin/login` 和 OAuth/OIDC 回调; - 管理后台资源:`/admin/assets/*`; -- 活动主题资源:`/theme-assets/*`。 +- 活动主题资源:`/t/*`。 diff --git a/web/vite.config.ts b/web/vite.config.ts index ca4e335..40bc43f 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -11,7 +11,7 @@ export default defineConfig({ '@': path.resolve(__dirname, './src'), }}, build: { - outDir: path.resolve(__dirname, 'dist/admin'), + outDir: path.resolve(__dirname, 'dist'), emptyOutDir: true, assetsDir: 'assets', },
-
-
- -
-
- {'logo'} { - e.currentTarget.src = '/logo.png'; - }} - /> -
-
-

- {leftName}{rightName} -

-

- {runtime.system.nameZh} -

-
-
- - - {/* HUD Navigation - Desktop Only */} -
- {[ - {id: 'servers', icon: ServerIcon, label: '设备监控', to: '/'}, - {id: 'monitors', icon: Activity, label: '服务监控', to: '/monitors'} - ].map(tab => ( - - - - ))} -
-
- - {/* Desktop Right Section */} -
- - {/* Mobile Menu Button */} - -
-
-