feature: add portal server ui library
Hee Sung Son committed
Nov 18, 2025 at 12:31 UTC
bca1e72ee435ac9ac0a48ae9562237f8301f7ecb
45 files changed
+6908
-91
.gitignore
+2
@@ -12,6 +12,8 @@ chat
12
13
cmd/relay-server/dist/*
14
!cmd/relay-server/dist/.gitkeep
15
+cmd/relay-server/app/*
16
+!cmd/relay-server/app/.gitkeep
17
18
# Test binary, built with `go test -c`
19
*.test
Dockerfile
+1
-1
@@ -26,7 +26,7 @@ COPY . .
26
27
RUN --mount=type=cache,target=/go/pkg/mod \
28
--mount=type=cache,target=/root/.cache/go-build \
29
- make build-wasm compress-wasm
29
+ make build-wasm
30
31
ARG TARGETPLATFORM
32
ARG TARGETOS
Makefile
+25
-2
@@ -1,6 +1,20 @@
1
SHELL := /bin/sh
2
3
-.PHONY: run build build-wasm compress-wasm build-server clean
3
+.PHONY: help run build build-wasm compress-wasm build-frontend build-server clean
4
+
5
+.DEFAULT_GOAL := help
6
+
7
+help:
8
+ @echo "Available targets:"
9
+ @echo " make build - Build everything (protoc, wasm, frontend, server, tunnel)"
10
+ @echo " make build-protoc - Generate Go code from protobuf definitions"
11
+ @echo " make build-wasm - Build WASM client with optimization"
12
+ @echo " make compress-wasm - Compress WASM with brotli"
13
+ @echo " make build-frontend - Build React frontend (Tailwind CSS 4)"
14
+ @echo " make build-server - Build Go relay server (includes frontend build)"
15
+ @echo " make build-tunnel - Build Portal Tunnel CLI"
16
+ @echo " make run - Run relay server"
17
+ @echo " make clean - Remove build artifacts"
18
19
run:
20
./bin/relay-server
@@ -48,6 +62,7 @@ build-wasm:
62
@cp cmd/webclient/portal.mp4 cmd/relay-server/dist/portal.mp4
63
64
@echo "[wasm] build complete"
65
+ @make compress-wasm
66
67
# Precompress content-addressed WASM with brotli
68
compress-wasm:
@@ -66,8 +81,15 @@ compress-wasm:
81
rm -f "$$WASM_FILE"; \
82
echo "[wasm] brotli: cmd/relay-server/dist/$$WASM_HASH.wasm.br"
83
84
+
85
+# Build React frontend with Tailwind CSS 4
86
+build-frontend:
87
+ @echo "[frontend] building React frontend..."
88
+ @cd cmd/relay-server/frontend && npm run build
89
+ @echo "[frontend] build complete"
90
+
91
# Build Go relay server (embeds WASM from cmd/relay-server/static)
70
-build-server:
92
+build-server: build-frontend
93
@echo "[server] building Go portal..."
94
CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" -o bin/relay-server ./cmd/relay-server
95
@@ -78,3 +100,4 @@ build-tunnel:
100
101
clean:
102
rm -rf bin
103
+ rm -rf app
cmd/relay-server/app/.gitkeep
cmd/relay-server/frontend.go
+109
-12
@@ -10,11 +10,15 @@ import (
10
"sync"
11
12
"github.com/rs/zerolog/log"
13
+ "gosuda.org/portal/portal"
14
)
15
16
//go:embed dist/*
17
var wasmFS embed.FS
18
19
+//go:embed app/*
20
+var appFS embed.FS
21
+
22
// portalHost is the host for portal frontend.
23
var portalHost = "localhost"
24
@@ -144,7 +148,7 @@ func createPortalMux() *http.ServeMux {
148
149
// Special handling for manifest.json - generate dynamically
150
if path == "manifest.json" {
147
- serveDynamicManifest(w, r)
151
+ serveDynamicManifest(w)
152
return
153
}
154
@@ -170,6 +174,59 @@ func createPortalMux() *http.ServeMux {
174
return mux
175
}
176
177
+// servePortalHTMLWithSSR serves portal.html with SSR data injection
178
+func servePortalHTMLWithSSR(w http.ResponseWriter, r *http.Request, serv *portal.RelayServer) {
179
+ setCORSHeaders(w)
180
+
181
+ // Read portal.html from embedded FS
182
+ fullPath := pathpkg.Join("app", "portal.html")
183
+ htmlContent, err := appFS.ReadFile(fullPath)
184
+ if err != nil {
185
+ log.Error().Err(err).Msg("Failed to read portal.html")
186
+ http.NotFound(w, r)
187
+ return
188
+ }
189
+
190
+ // Inject SSR data
191
+ injectedHTML := injectServerData(string(htmlContent), serv)
192
+
193
+ // Set headers
194
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
195
+ w.Header().Set("Cache-Control", "no-cache, must-revalidate")
196
+
197
+ // Send response
198
+ w.WriteHeader(http.StatusOK)
199
+ w.Write([]byte(injectedHTML))
200
+
201
+ log.Debug().Msg("Served portal.html with SSR data")
202
+}
203
+
204
+// injectServerData injects server data into HTML for SSR
205
+func injectServerData(htmlContent string, serv *portal.RelayServer) string {
206
+ // Get server data from lease manager
207
+ rows := convertLeaseEntriesToRows(serv)
208
+
209
+ // Marshal to JSON
210
+ jsonData, err := json.Marshal(rows)
211
+ if err != nil {
212
+ log.Error().Err(err).Msg("Failed to marshal server data for SSR")
213
+ jsonData = []byte("[]")
214
+ }
215
+
216
+ // Create SSR script tag
217
+ ssrScript := `<script id="__SSR_DATA__" type="application/json">` + string(jsonData) + `</script>`
218
+
219
+ // Inject before </head> tag
220
+ injected := strings.Replace(htmlContent, "</head>", ssrScript+"\n</head>", 1)
221
+
222
+ log.Debug().
223
+ Int("rows", len(rows)).
224
+ Int("jsonSize", len(jsonData)).
225
+ Msg("Injected SSR data into HTML")
226
+
227
+ return injected
228
+}
229
+
230
// servePortalStaticFile serves static files for portal frontend with caching
231
func servePortalStaticFile(w http.ResponseWriter, r *http.Request, filePath string) {
232
// Check if this is a content-addressed WASM file
@@ -194,7 +251,26 @@ func serveCompressedWasm(w http.ResponseWriter, r *http.Request, filePath string
251
252
if !ok {
253
log.Debug().Str("path", filePath).Msg("WASM file not in cache")
197
- http.NotFound(w, r)
254
+ // Fallback: try to serve uncompressed WASM from embedded FS
255
+ fullPath := pathpkg.Join("dist", filePath)
256
+ data, err := wasmFS.ReadFile(fullPath)
257
+ if err != nil {
258
+ log.Debug().Err(err).Str("path", fullPath).Msg("WASM file not found in embedded FS")
259
+ http.NotFound(w, r)
260
+ return
261
+ }
262
+
263
+ // Serve uncompressed WASM
264
+ setCORSHeaders(w)
265
+ w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
266
+ w.Header().Set("Content-Type", "application/wasm")
267
+ w.Header().Set("Content-Length", strconv.Itoa(len(data)))
268
+ w.WriteHeader(http.StatusOK)
269
+ w.Write(data)
270
+ log.Debug().
271
+ Str("path", filePath).
272
+ Int("size", len(data)).
273
+ Msg("served uncompressed WASM from embedded FS")
274
return
275
}
276
@@ -227,22 +303,30 @@ func serveCompressedWasm(w http.ResponseWriter, r *http.Request, filePath string
303
Msg("served compressed WASM")
304
}
305
230
-// serveAdminStatic serves static files for admin UI from embedded FS
231
-func serveAdminStatic(w http.ResponseWriter, r *http.Request, path string) {
306
+// serveAppStatic serves static files for app UI (React app) from embedded FS
307
+// Falls back to portal.html with SSR when path is root or file not found
308
+func serveAppStatic(w http.ResponseWriter, r *http.Request, path string, serv *portal.RelayServer) {
309
// Prevent directory traversal
310
if strings.Contains(path, "..") {
311
http.Error(w, "Invalid path", http.StatusBadRequest)
312
return
313
}
314
238
- // Try to read from embedded FS
315
setCORSHeaders(w)
316
241
- fullPath := pathpkg.Join("static", path)
242
- data, err := assetsFS.ReadFile(fullPath)
317
+ // If path is empty or "/", serve portal.html with SSR
318
+ if path == "" || path == "/" {
319
+ servePortalHTMLWithSSR(w, r, serv)
320
+ return
321
+ }
322
+
323
+ // Try to read from embedded FS
324
+ fullPath := pathpkg.Join("app", path)
325
+ data, err := appFS.ReadFile(fullPath)
326
if err != nil {
244
- log.Debug().Err(err).Str("path", path).Msg("admin static file not found")
245
- http.NotFound(w, r)
327
+ // File not found - fallback to portal.html with SSR for SPA routing
328
+ log.Debug().Err(err).Str("path", path).Msg("app static file not found, falling back to SSR")
329
+ servePortalHTMLWithSSR(w, r, serv)
330
return
331
}
332
@@ -260,7 +344,7 @@ func serveAdminStatic(w http.ResponseWriter, r *http.Request, path string) {
344
log.Debug().
345
Str("path", path).
346
Int("size", len(data)).
263
- Msg("served admin static file")
347
+ Msg("served app static file")
348
}
349
350
// servePortalStatic serves static files for portal frontend with appropriate cache headers
@@ -408,7 +492,20 @@ func isPortalSubdomain(host string) bool {
492
if portalHost == "" {
493
return false
494
}
411
- return strings.HasSuffix(host, "."+portalHost)
495
+
496
+ // Remove port from host for comparison
497
+ hostWithoutPort := host
498
+ if idx := strings.LastIndex(host, ":"); idx != -1 {
499
+ hostWithoutPort = host[:idx]
500
+ }
501
+
502
+ // Remove port from portalHost for comparison
503
+ portalHostWithoutPort := portalHost
504
+ if idx := strings.LastIndex(portalHost, ":"); idx != -1 {
505
+ portalHostWithoutPort = portalHost[:idx]
506
+ }
507
+
508
+ return strings.HasSuffix(hostWithoutPort, "."+portalHostWithoutPort)
509
}
510
511
// matchesWildcardPattern checks if a host matches a wildcard pattern (e.g., *.localhost:4017)
@@ -434,7 +531,7 @@ func isHexString(s string) bool {
531
}
532
533
// serveDynamicManifest generates and serves manifest.json dynamically
437
-func serveDynamicManifest(w http.ResponseWriter, r *http.Request) {
534
+func serveDynamicManifest(w http.ResponseWriter) {
535
setCORSHeaders(w)
536
537
// Find the content-addressed WASM file
cmd/relay-server/frontend/.eslintrc.cjs
new
+18
@@ -0,0 +1,18 @@
1
+module.exports = {
2
+ root: true,
3
+ env: { browser: true, es2020: true },
4
+ extends: [
5
+ "eslint:recommended",
6
+ "plugin:@typescript-eslint/recommended",
7
+ "plugin:react-hooks/recommended",
8
+ ],
9
+ ignorePatterns: ["dist", ".eslintrc.cjs"],
10
+ parser: "@typescript-eslint/parser",
11
+ plugins: ["react-refresh"],
12
+ rules: {
13
+ "react-refresh/only-export-components": [
14
+ "warn",
15
+ { allowConstantExport: true },
16
+ ],
17
+ },
18
+};
cmd/relay-server/frontend/.gitignore
new
+24
@@ -0,0 +1,24 @@
1
+# Logs
2
+logs
3
+*.log
4
+npm-debug.log*
5
+yarn-debug.log*
6
+yarn-error.log*
7
+pnpm-debug.log*
8
+lerna-debug.log*
9
+
10
+node_modules
11
+dist
12
+dist-ssr
13
+*.local
14
+
15
+# Editor directories and files
16
+.vscode/*
17
+!.vscode/extensions.json
18
+.idea
19
+.DS_Store
20
+*.suo
21
+*.ntvs*
22
+*.njsproj
23
+*.sln
24
+*.sw?
cmd/relay-server/frontend/README.md
new
+227
@@ -0,0 +1,227 @@
1
+# Relay Server Frontend
2
+
3
+ServerShare-style frontend built with React + TypeScript + shadcn/ui, featuring dynamic GeoIP-based server filtering and SSR data integration.
4
+
5
+## Tech Stack
6
+
7
+- **React 19** - UI library
8
+- **TypeScript** - Type safety
9
+- **Vite 7** - Build tool
10
+- **Tailwind CSS 4** - CSS-first configuration styling
11
+- **shadcn/ui** - UI components (Radix UI-based)
12
+- **Lucide React** - Icons
13
+
14
+## Project Structure
15
+
16
+```
17
+frontend/
18
+├── src/
19
+│ ├── components/
20
+│ │ ├── ui/ # shadcn/ui base components
21
+│ │ │ ├── button.tsx
22
+│ │ │ ├── input.tsx
23
+│ │ │ └── select.tsx
24
+│ │ ├── Header.tsx # Header component
25
+│ │ ├── SearchBar.tsx # Search and filter bar (Country, Status, Sort By)
26
+│ │ ├── ServerCard.tsx # Server card component
27
+│ │ └── Pagination.tsx # Pagination component
28
+│ ├── hooks/
29
+│ │ └── useSSRData.ts # SSR data hook (reads __SSR_DATA__ from Go backend)
30
+│ ├── lib/
31
+│ │ ├── utils.ts # Utility functions
32
+│ │ └── countries.ts # ISO 3166-1 alpha-2 country code mapping (~200 countries)
33
+│ ├── App.tsx # Main app component (filter logic, dynamic country extraction)
34
+│ ├── main.tsx # Entry point
35
+│ └── index.css # Global styles and Tailwind CSS 4 configuration
36
+├── index.html
37
+├── package.json
38
+├── tsconfig.json
39
+└── vite.config.ts # @tailwindcss/vite plugin
40
+```
41
+
42
+## Key Features
43
+
44
+### 1. Server-Side Rendering (SSR)
45
+- Go backend injects server data into HTML via `<script id="__SSR_DATA__">` tag
46
+- Frontend reads SSR data using `useSSRData()` hook
47
+- Zero initial loading time for server list
48
+
49
+### 2. GeoIP Integration
50
+- Backend uses MaxMind GeoLite2-Country.mmdb database
51
+- Automatically detects server location based on IP address
52
+- Provides ISO 3166-1 alpha-2 country codes (e.g., "US", "KR", "JP")
53
+
54
+### 3. Dynamic Country Filtering
55
+- Extracts unique countries from currently connected servers
56
+- Only displays countries that actually have servers online
57
+- Full country mapping (~200 countries) in `lib/countries.ts`
58
+- Converts country codes to human-readable names
59
+
60
+### 4. Advanced Filter System
61
+Three Select dropdowns:
62
+- **Country**: Filter by GeoIP-detected location (dynamic list)
63
+- **Status**: Filter by online/offline status
64
+- **Sort By**: Sort by Description, Tags, or Owner
65
+
66
+### 5. Search Functionality
67
+Search across:
68
+- Server names
69
+- Descriptions
70
+- Tags
71
+
72
+### Tailwind CSS 4 Migration
73
+
74
+This project uses Tailwind CSS v4:
75
+
76
+- ✅ CSS-first configuration (`@theme` directive in `index.css`)
77
+- ✅ `@tailwindcss/vite` plugin
78
+- ✅ Removed `tailwind.config.js` (config moved to CSS)
79
+- ✅ Removed `postcss.config.js` (auto-handled)
80
+- ✅ `@import "tailwindcss"` syntax
81
+
82
+For details, see [Tailwind CSS v4 Official Documentation](https://tailwindcss.com/docs/upgrade-guide).
83
+
84
+## Installation and Build
85
+
86
+### Install Dependencies
87
+
88
+```bash
89
+cd cmd/relay-server/frontend
90
+npm install
91
+```
92
+
93
+### Development Server
94
+
95
+```bash
96
+npm run dev
97
+```
98
+
99
+Development server runs at `http://localhost:5173`.
100
+
101
+### Production Build
102
+
103
+```bash
104
+npm run build
105
+```
106
+
107
+Build output in `/dist` directory:
108
+- `portal.html` - Main HTML file (served by Go server with SSR data injection)
109
+- `assets/` - JS and CSS bundles
110
+
111
+### Using Makefile
112
+
113
+```bash
114
+# Install dependencies
115
+make install
116
+
117
+# Build
118
+make build
119
+
120
+# Development server
121
+make dev
122
+
123
+# Clean
124
+make clean
125
+```
126
+
127
+## Go Server Integration
128
+
129
+The relay-server serves the frontend at:
130
+
131
+- `/` - React frontend (ServerShare UI with SSR data)
132
+- `/app/` - React app static assets
133
+- `/healthz` - Health check endpoint
134
+- `/relay` - WebSocket relay endpoint
135
+
136
+### Running the Server
137
+
138
+```bash
139
+# Build frontend
140
+cd cmd/relay-server/frontend
141
+npm run build
142
+
143
+# Run server
144
+cd ../../..
145
+go run cmd/relay-server/*.go -port 4017
146
+```
147
+
148
+Or specify static directory:
149
+
150
+```bash
151
+STATIC_DIR=./dist go run cmd/relay-server/*.go -port 4017
152
+```
153
+
154
+### SSR Data Flow
155
+
156
+1. Go backend reads lease entries and GeoIP data
157
+2. Converts to JSON and injects into `portal.html` as `<script id="__SSR_DATA__">`
158
+3. React app reads SSR data via `useSSRData()` hook
159
+4. Displays server list with GeoIP-based filtering
160
+
161
+## Design System
162
+
163
+### Colors
164
+
165
+- **Primary**: `#47cdff` - Primary action buttons
166
+- **Background Light**: `#f5f8f8` - Light mode background
167
+- **Background Dark**: `#0f1e23` - Dark mode background (default)
168
+- **Green Status**: `#50E3C2` - Online status indicator
169
+
170
+### Components
171
+
172
+#### Header
173
+Navigation header with logo and "Add Your Server" button
174
+
175
+#### SearchBar
176
+Search input + three filter dropdowns:
177
+- Country (GeoIP-based, dynamic)
178
+- Status (All/Online/Offline)
179
+- Sort By (Default/Description/Tags/Owner)
180
+
181
+#### ServerCard
182
+Server information card displaying:
183
+- Thumbnail image
184
+- Online/offline status badge
185
+- Server name
186
+- Description
187
+- Tags (including country)
188
+- Owner information
189
+- Connect button
190
+
191
+#### Pagination
192
+Page navigation with previous/next buttons (6 items per page)
193
+
194
+## Implementation Status
195
+
196
+### Completed Features
197
+- ✅ Server-side rendering (SSR) with Go backend
198
+- ✅ GeoIP integration with MaxMind GeoLite2-Country database
199
+- ✅ Dynamic country filtering (shows only countries with connected servers)
200
+- ✅ Search functionality (name, description, tags)
201
+- ✅ Status filtering (online/offline)
202
+- ✅ Sort by Description, Tags, or Owner
203
+- ✅ Pagination (6 servers per page)
204
+- ✅ Dark mode UI (default)
205
+- ✅ Responsive design (mobile/tablet/desktop)
206
+- ✅ ISO 3166-1 alpha-2 country code mapping (~200 countries)
207
+- ✅ Radix UI Select components with proper value handling
208
+
209
+## Technical Notes
210
+
211
+### Radix UI Select Constraints
212
+- Select values cannot be empty strings (`""`)
213
+- Use meaningful defaults: `"all"`, `"default"` instead of `""`
214
+
215
+### GeoIP Detection
216
+- Detects country based on server IP address
217
+- Localhost (::1) connections show no country
218
+- Requires external IP addresses for proper country detection
219
+
220
+### Dynamic Country List
221
+- Extracts unique countries from connected servers using `useMemo` and `Set`
222
+- Updates automatically as servers connect/disconnect
223
+- Maps country codes to human-readable names via `COUNTRY_NAMES`
224
+
225
+## License
226
+
227
+This project is part of gosuda/portal.
cmd/relay-server/frontend/components.json
new
+20
@@ -0,0 +1,20 @@
1
+{
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "new-york",
4
+ "rsc": false,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "tailwind.config.ts",
8
+ "css": "src/index.css",
9
+ "baseColor": "zinc",
10
+ "cssVariables": true,
11
+ "prefix": ""
12
+ },
13
+ "aliases": {
14
+ "components": "@/components",
15
+ "utils": "@/lib/utils",
16
+ "ui": "@/components/ui",
17
+ "lib": "@/lib",
18
+ "hooks": "@/hooks"
19
+ }
20
+}
cmd/relay-server/frontend/index.html
new
+28
@@ -0,0 +1,28 @@
1
+<!doctype html>
2
+<html lang="en" class="dark" style="color-scheme: dark;">
3
+
4
+<head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <meta name="color-scheme" content="dark" />
8
+ <meta name="theme-color" content="#0f1e23" />
9
+ <meta name="description"
10
+ content="Transform your local services into web-accessible endpoints. Instant access from anywhere." />
11
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
12
+ <title>Portal - Local to web. Instant access.</title>
13
+ <style>
14
+ /* Prevent flash of light mode */
15
+ html,
16
+ body {
17
+ background-color: #0f1e23;
18
+ color: #ffffff;
19
+ }
20
+ </style>
21
+</head>
22
+
23
+<body class="dark">
24
+ <div id="root"></div>
25
+ <script type="module" src="/src/main.tsx"></script>
26
+</body>
27
+
28
+</html>
\ No newline at end of file
cmd/relay-server/frontend/package-lock.json
new
+5066
@@ -0,0 +1,5066 @@
1
+{
2
+ "name": "relay-server-frontend",
3
+ "version": "0.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "relay-server-frontend",
9
+ "version": "0.0.0",
10
+ "dependencies": {
11
+ "@radix-ui/react-dialog": "^1.1.15",
12
+ "@radix-ui/react-popover": "^1.1.15",
13
+ "@radix-ui/react-select": "^2.2.6",
14
+ "@radix-ui/react-slot": "^1.2.4",
15
+ "class-variance-authority": "^0.7.1",
16
+ "clsx": "^2.1.1",
17
+ "cmdk": "^1.1.1",
18
+ "lucide-react": "^0.553.0",
19
+ "react": "^19.2.0",
20
+ "react-dom": "^19.2.0",
21
+ "tailwind-merge": "^3.4.0"
22
+ },
23
+ "devDependencies": {
24
+ "@tailwindcss/vite": "^4.1.17",
25
+ "@types/node": "^24.10.1",
26
+ "@types/react": "^19.2.5",
27
+ "@types/react-dom": "^19.2.3",
28
+ "@typescript-eslint/eslint-plugin": "^8.46.4",
29
+ "@typescript-eslint/parser": "^8.46.4",
30
+ "@vitejs/plugin-react": "^5.1.1",
31
+ "eslint": "^9.39.1",
32
+ "eslint-plugin-react-hooks": "^7.0.1",
33
+ "eslint-plugin-react-refresh": "^0.4.24",
34
+ "tailwindcss": "^4.1.17",
35
+ "typescript": "^5.9.3",
36
+ "vite": "^7.2.2"
37
+ }
38
+ },
39
+ "node_modules/@babel/code-frame": {
40
+ "version": "7.27.1",
41
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
42
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
43
+ "dev": true,
44
+ "license": "MIT",
45
+ "dependencies": {
46
+ "@babel/helper-validator-identifier": "^7.27.1",
47
+ "js-tokens": "^4.0.0",
48
+ "picocolors": "^1.1.1"
49
+ },
50
+ "engines": {
51
+ "node": ">=6.9.0"
52
+ }
53
+ },
54
+ "node_modules/@babel/compat-data": {
55
+ "version": "7.28.5",
56
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz",
57
+ "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==",
58
+ "dev": true,
59
+ "license": "MIT",
60
+ "engines": {
61
+ "node": ">=6.9.0"
62
+ }
63
+ },
64
+ "node_modules/@babel/core": {
65
+ "version": "7.28.5",
66
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
67
+ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
68
+ "dev": true,
69
+ "license": "MIT",
70
+ "dependencies": {
71
+ "@babel/code-frame": "^7.27.1",
72
+ "@babel/generator": "^7.28.5",
73
+ "@babel/helper-compilation-targets": "^7.27.2",
74
+ "@babel/helper-module-transforms": "^7.28.3",
75
+ "@babel/helpers": "^7.28.4",
76
+ "@babel/parser": "^7.28.5",
77
+ "@babel/template": "^7.27.2",
78
+ "@babel/traverse": "^7.28.5",
79
+ "@babel/types": "^7.28.5",
80
+ "@jridgewell/remapping": "^2.3.5",
81
+ "convert-source-map": "^2.0.0",
82
+ "debug": "^4.1.0",
83
+ "gensync": "^1.0.0-beta.2",
84
+ "json5": "^2.2.3",
85
+ "semver": "^6.3.1"
86
+ },
87
+ "engines": {
88
+ "node": ">=6.9.0"
89
+ },
90
+ "funding": {
91
+ "type": "opencollective",
92
+ "url": "https://opencollective.com/babel"
93
+ }
94
+ },
95
+ "node_modules/@babel/core/node_modules/semver": {
96
+ "version": "6.3.1",
97
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
98
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
99
+ "dev": true,
100
+ "license": "ISC",
101
+ "bin": {
102
+ "semver": "bin/semver.js"
103
+ }
104
+ },
105
+ "node_modules/@babel/generator": {
106
+ "version": "7.28.5",
107
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
108
+ "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
109
+ "dev": true,
110
+ "license": "MIT",
111
+ "dependencies": {
112
+ "@babel/parser": "^7.28.5",
113
+ "@babel/types": "^7.28.5",
114
+ "@jridgewell/gen-mapping": "^0.3.12",
115
+ "@jridgewell/trace-mapping": "^0.3.28",
116
+ "jsesc": "^3.0.2"
117
+ },
118
+ "engines": {
119
+ "node": ">=6.9.0"
120
+ }
121
+ },
122
+ "node_modules/@babel/helper-compilation-targets": {
123
+ "version": "7.27.2",
124
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
125
+ "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
126
+ "dev": true,
127
+ "license": "MIT",
128
+ "dependencies": {
129
+ "@babel/compat-data": "^7.27.2",
130
+ "@babel/helper-validator-option": "^7.27.1",
131
+ "browserslist": "^4.24.0",
132
+ "lru-cache": "^5.1.1",
133
+ "semver": "^6.3.1"
134
+ },
135
+ "engines": {
136
+ "node": ">=6.9.0"
137
+ }
138
+ },
139
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
140
+ "version": "6.3.1",
141
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
142
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
143
+ "dev": true,
144
+ "license": "ISC",
145
+ "bin": {
146
+ "semver": "bin/semver.js"
147
+ }
148
+ },
149
+ "node_modules/@babel/helper-globals": {
150
+ "version": "7.28.0",
151
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
152
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
153
+ "dev": true,
154
+ "license": "MIT",
155
+ "engines": {
156
+ "node": ">=6.9.0"
157
+ }
158
+ },
159
+ "node_modules/@babel/helper-module-imports": {
160
+ "version": "7.27.1",
161
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
162
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
163
+ "dev": true,
164
+ "license": "MIT",
165
+ "dependencies": {
166
+ "@babel/traverse": "^7.27.1",
167
+ "@babel/types": "^7.27.1"
168
+ },
169
+ "engines": {
170
+ "node": ">=6.9.0"
171
+ }
172
+ },
173
+ "node_modules/@babel/helper-module-transforms": {
174
+ "version": "7.28.3",
175
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
176
+ "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
177
+ "dev": true,
178
+ "license": "MIT",
179
+ "dependencies": {
180
+ "@babel/helper-module-imports": "^7.27.1",
181
+ "@babel/helper-validator-identifier": "^7.27.1",
182
+ "@babel/traverse": "^7.28.3"
183
+ },
184
+ "engines": {
185
+ "node": ">=6.9.0"
186
+ },
187
+ "peerDependencies": {
188
+ "@babel/core": "^7.0.0"
189
+ }
190
+ },
191
+ "node_modules/@babel/helper-plugin-utils": {
192
+ "version": "7.27.1",
193
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
194
+ "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
195
+ "dev": true,
196
+ "license": "MIT",
197
+ "engines": {
198
+ "node": ">=6.9.0"
199
+ }
200
+ },
201
+ "node_modules/@babel/helper-string-parser": {
202
+ "version": "7.27.1",
203
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
204
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
205
+ "dev": true,
206
+ "license": "MIT",
207
+ "engines": {
208
+ "node": ">=6.9.0"
209
+ }
210
+ },
211
+ "node_modules/@babel/helper-validator-identifier": {
212
+ "version": "7.28.5",
213
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
214
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
215
+ "dev": true,
216
+ "license": "MIT",
217
+ "engines": {
218
+ "node": ">=6.9.0"
219
+ }
220
+ },
221
+ "node_modules/@babel/helper-validator-option": {
222
+ "version": "7.27.1",
223
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
224
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
225
+ "dev": true,
226
+ "license": "MIT",
227
+ "engines": {
228
+ "node": ">=6.9.0"
229
+ }
230
+ },
231
+ "node_modules/@babel/helpers": {
232
+ "version": "7.28.4",
233
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz",
234
+ "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
235
+ "dev": true,
236
+ "license": "MIT",
237
+ "dependencies": {
238
+ "@babel/template": "^7.27.2",
239
+ "@babel/types": "^7.28.4"
240
+ },
241
+ "engines": {
242
+ "node": ">=6.9.0"
243
+ }
244
+ },
245
+ "node_modules/@babel/parser": {
246
+ "version": "7.28.5",
247
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
248
+ "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
249
+ "dev": true,
250
+ "license": "MIT",
251
+ "dependencies": {
252
+ "@babel/types": "^7.28.5"
253
+ },
254
+ "bin": {
255
+ "parser": "bin/babel-parser.js"
256
+ },
257
+ "engines": {
258
+ "node": ">=6.0.0"
259
+ }
260
+ },
261
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
262
+ "version": "7.27.1",
263
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
264
+ "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
265
+ "dev": true,
266
+ "license": "MIT",
267
+ "dependencies": {
268
+ "@babel/helper-plugin-utils": "^7.27.1"
269
+ },
270
+ "engines": {
271
+ "node": ">=6.9.0"
272
+ },
273
+ "peerDependencies": {
274
+ "@babel/core": "^7.0.0-0"
275
+ }
276
+ },
277
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
278
+ "version": "7.27.1",
279
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
280
+ "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
281
+ "dev": true,
282
+ "license": "MIT",
283
+ "dependencies": {
284
+ "@babel/helper-plugin-utils": "^7.27.1"
285
+ },
286
+ "engines": {
287
+ "node": ">=6.9.0"
288
+ },
289
+ "peerDependencies": {
290
+ "@babel/core": "^7.0.0-0"
291
+ }
292
+ },
293
+ "node_modules/@babel/template": {
294
+ "version": "7.27.2",
295
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
296
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
297
+ "dev": true,
298
+ "license": "MIT",
299
+ "dependencies": {
300
+ "@babel/code-frame": "^7.27.1",
301
+ "@babel/parser": "^7.27.2",
302
+ "@babel/types": "^7.27.1"
303
+ },
304
+ "engines": {
305
+ "node": ">=6.9.0"
306
+ }
307
+ },
308
+ "node_modules/@babel/traverse": {
309
+ "version": "7.28.5",
310
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
311
+ "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
312
+ "dev": true,
313
+ "license": "MIT",
314
+ "dependencies": {
315
+ "@babel/code-frame": "^7.27.1",
316
+ "@babel/generator": "^7.28.5",
317
+ "@babel/helper-globals": "^7.28.0",
318
+ "@babel/parser": "^7.28.5",
319
+ "@babel/template": "^7.27.2",
320
+ "@babel/types": "^7.28.5",
321
+ "debug": "^4.3.1"
322
+ },
323
+ "engines": {
324
+ "node": ">=6.9.0"
325
+ }
326
+ },
327
+ "node_modules/@babel/types": {
328
+ "version": "7.28.5",
329
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
330
+ "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
331
+ "dev": true,
332
+ "license": "MIT",
333
+ "dependencies": {
334
+ "@babel/helper-string-parser": "^7.27.1",
335
+ "@babel/helper-validator-identifier": "^7.28.5"
336
+ },
337
+ "engines": {
338
+ "node": ">=6.9.0"
339
+ }
340
+ },
341
+ "node_modules/@esbuild/aix-ppc64": {
342
+ "version": "0.25.12",
343
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
344
+ "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
345
+ "cpu": [
346
+ "ppc64"
347
+ ],
348
+ "dev": true,
349
+ "license": "MIT",
350
+ "optional": true,
351
+ "os": [
352
+ "aix"
353
+ ],
354
+ "engines": {
355
+ "node": ">=18"
356
+ }
357
+ },
358
+ "node_modules/@esbuild/android-arm": {
359
+ "version": "0.25.12",
360
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
361
+ "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
362
+ "cpu": [
363
+ "arm"
364
+ ],
365
+ "dev": true,
366
+ "license": "MIT",
367
+ "optional": true,
368
+ "os": [
369
+ "android"
370
+ ],
371
+ "engines": {
372
+ "node": ">=18"
373
+ }
374
+ },
375
+ "node_modules/@esbuild/android-arm64": {
376
+ "version": "0.25.12",
377
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
378
+ "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
379
+ "cpu": [
380
+ "arm64"
381
+ ],
382
+ "dev": true,
383
+ "license": "MIT",
384
+ "optional": true,
385
+ "os": [
386
+ "android"
387
+ ],
388
+ "engines": {
389
+ "node": ">=18"
390
+ }
391
+ },
392
+ "node_modules/@esbuild/android-x64": {
393
+ "version": "0.25.12",
394
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
395
+ "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
396
+ "cpu": [
397
+ "x64"
398
+ ],
399
+ "dev": true,
400
+ "license": "MIT",
401
+ "optional": true,
402
+ "os": [
403
+ "android"
404
+ ],
405
+ "engines": {
406
+ "node": ">=18"
407
+ }
408
+ },
409
+ "node_modules/@esbuild/darwin-arm64": {
410
+ "version": "0.25.12",
411
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
412
+ "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
413
+ "cpu": [
414
+ "arm64"
415
+ ],
416
+ "dev": true,
417
+ "license": "MIT",
418
+ "optional": true,
419
+ "os": [
420
+ "darwin"
421
+ ],
422
+ "engines": {
423
+ "node": ">=18"
424
+ }
425
+ },
426
+ "node_modules/@esbuild/darwin-x64": {
427
+ "version": "0.25.12",
428
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
429
+ "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
430
+ "cpu": [
431
+ "x64"
432
+ ],
433
+ "dev": true,
434
+ "license": "MIT",
435
+ "optional": true,
436
+ "os": [
437
+ "darwin"
438
+ ],
439
+ "engines": {
440
+ "node": ">=18"
441
+ }
442
+ },
443
+ "node_modules/@esbuild/freebsd-arm64": {
444
+ "version": "0.25.12",
445
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
446
+ "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
447
+ "cpu": [
448
+ "arm64"
449
+ ],
450
+ "dev": true,
451
+ "license": "MIT",
452
+ "optional": true,
453
+ "os": [
454
+ "freebsd"
455
+ ],
456
+ "engines": {
457
+ "node": ">=18"
458
+ }
459
+ },
460
+ "node_modules/@esbuild/freebsd-x64": {
461
+ "version": "0.25.12",
462
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
463
+ "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
464
+ "cpu": [
465
+ "x64"
466
+ ],
467
+ "dev": true,
468
+ "license": "MIT",
469
+ "optional": true,
470
+ "os": [
471
+ "freebsd"
472
+ ],
473
+ "engines": {
474
+ "node": ">=18"
475
+ }
476
+ },
477
+ "node_modules/@esbuild/linux-arm": {
478
+ "version": "0.25.12",
479
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
480
+ "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
481
+ "cpu": [
482
+ "arm"
483
+ ],
484
+ "dev": true,
485
+ "license": "MIT",
486
+ "optional": true,
487
+ "os": [
488
+ "linux"
489
+ ],
490
+ "engines": {
491
+ "node": ">=18"
492
+ }
493
+ },
494
+ "node_modules/@esbuild/linux-arm64": {
495
+ "version": "0.25.12",
496
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
497
+ "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
498
+ "cpu": [
499
+ "arm64"
500
+ ],
501
+ "dev": true,
502
+ "license": "MIT",
503
+ "optional": true,
504
+ "os": [
505
+ "linux"
506
+ ],
507
+ "engines": {
508
+ "node": ">=18"
509
+ }
510
+ },
511
+ "node_modules/@esbuild/linux-ia32": {
512
+ "version": "0.25.12",
513
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
514
+ "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
515
+ "cpu": [
516
+ "ia32"
517
+ ],
518
+ "dev": true,
519
+ "license": "MIT",
520
+ "optional": true,
521
+ "os": [
522
+ "linux"
523
+ ],
524
+ "engines": {
525
+ "node": ">=18"
526
+ }
527
+ },
528
+ "node_modules/@esbuild/linux-loong64": {
529
+ "version": "0.25.12",
530
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
531
+ "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
532
+ "cpu": [
533
+ "loong64"
534
+ ],
535
+ "dev": true,
536
+ "license": "MIT",
537
+ "optional": true,
538
+ "os": [
539
+ "linux"
540
+ ],
541
+ "engines": {
542
+ "node": ">=18"
543
+ }
544
+ },
545
+ "node_modules/@esbuild/linux-mips64el": {
546
+ "version": "0.25.12",
547
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
548
+ "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
549
+ "cpu": [
550
+ "mips64el"
551
+ ],
552
+ "dev": true,
553
+ "license": "MIT",
554
+ "optional": true,
555
+ "os": [
556
+ "linux"
557
+ ],
558
+ "engines": {
559
+ "node": ">=18"
560
+ }
561
+ },
562
+ "node_modules/@esbuild/linux-ppc64": {
563
+ "version": "0.25.12",
564
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
565
+ "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
566
+ "cpu": [
567
+ "ppc64"
568
+ ],
569
+ "dev": true,
570
+ "license": "MIT",
571
+ "optional": true,
572
+ "os": [
573
+ "linux"
574
+ ],
575
+ "engines": {
576
+ "node": ">=18"
577
+ }
578
+ },
579
+ "node_modules/@esbuild/linux-riscv64": {
580
+ "version": "0.25.12",
581
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
582
+ "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
583
+ "cpu": [
584
+ "riscv64"
585
+ ],
586
+ "dev": true,
587
+ "license": "MIT",
588
+ "optional": true,
589
+ "os": [
590
+ "linux"
591
+ ],
592
+ "engines": {
593
+ "node": ">=18"
594
+ }
595
+ },
596
+ "node_modules/@esbuild/linux-s390x": {
597
+ "version": "0.25.12",
598
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
599
+ "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
600
+ "cpu": [
601
+ "s390x"
602
+ ],
603
+ "dev": true,
604
+ "license": "MIT",
605
+ "optional": true,
606
+ "os": [
607
+ "linux"
608
+ ],
609
+ "engines": {
610
+ "node": ">=18"
611
+ }
612
+ },
613
+ "node_modules/@esbuild/linux-x64": {
614
+ "version": "0.25.12",
615
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
616
+ "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
617
+ "cpu": [
618
+ "x64"
619
+ ],
620
+ "dev": true,
621
+ "license": "MIT",
622
+ "optional": true,
623
+ "os": [
624
+ "linux"
625
+ ],
626
+ "engines": {
627
+ "node": ">=18"
628
+ }
629
+ },
630
+ "node_modules/@esbuild/netbsd-arm64": {
631
+ "version": "0.25.12",
632
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
633
+ "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
634
+ "cpu": [
635
+ "arm64"
636
+ ],
637
+ "dev": true,
638
+ "license": "MIT",
639
+ "optional": true,
640
+ "os": [
641
+ "netbsd"
642
+ ],
643
+ "engines": {
644
+ "node": ">=18"
645
+ }
646
+ },
647
+ "node_modules/@esbuild/netbsd-x64": {
648
+ "version": "0.25.12",
649
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
650
+ "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
651
+ "cpu": [
652
+ "x64"
653
+ ],
654
+ "dev": true,
655
+ "license": "MIT",
656
+ "optional": true,
657
+ "os": [
658
+ "netbsd"
659
+ ],
660
+ "engines": {
661
+ "node": ">=18"
662
+ }
663
+ },
664
+ "node_modules/@esbuild/openbsd-arm64": {
665
+ "version": "0.25.12",
666
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
667
+ "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
668
+ "cpu": [
669
+ "arm64"
670
+ ],
671
+ "dev": true,
672
+ "license": "MIT",
673
+ "optional": true,
674
+ "os": [
675
+ "openbsd"
676
+ ],
677
+ "engines": {
678
+ "node": ">=18"
679
+ }
680
+ },
681
+ "node_modules/@esbuild/openbsd-x64": {
682
+ "version": "0.25.12",
683
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
684
+ "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
685
+ "cpu": [
686
+ "x64"
687
+ ],
688
+ "dev": true,
689
+ "license": "MIT",
690
+ "optional": true,
691
+ "os": [
692
+ "openbsd"
693
+ ],
694
+ "engines": {
695
+ "node": ">=18"
696
+ }
697
+ },
698
+ "node_modules/@esbuild/openharmony-arm64": {
699
+ "version": "0.25.12",
700
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
701
+ "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
702
+ "cpu": [
703
+ "arm64"
704
+ ],
705
+ "dev": true,
706
+ "license": "MIT",
707
+ "optional": true,
708
+ "os": [
709
+ "openharmony"
710
+ ],
711
+ "engines": {
712
+ "node": ">=18"
713
+ }
714
+ },
715
+ "node_modules/@esbuild/sunos-x64": {
716
+ "version": "0.25.12",
717
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
718
+ "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
719
+ "cpu": [
720
+ "x64"
721
+ ],
722
+ "dev": true,
723
+ "license": "MIT",
724
+ "optional": true,
725
+ "os": [
726
+ "sunos"
727
+ ],
728
+ "engines": {
729
+ "node": ">=18"
730
+ }
731
+ },
732
+ "node_modules/@esbuild/win32-arm64": {
733
+ "version": "0.25.12",
734
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
735
+ "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
736
+ "cpu": [
737
+ "arm64"
738
+ ],
739
+ "dev": true,
740
+ "license": "MIT",
741
+ "optional": true,
742
+ "os": [
743
+ "win32"
744
+ ],
745
+ "engines": {
746
+ "node": ">=18"
747
+ }
748
+ },
749
+ "node_modules/@esbuild/win32-ia32": {
750
+ "version": "0.25.12",
751
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
752
+ "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
753
+ "cpu": [
754
+ "ia32"
755
+ ],
756
+ "dev": true,
757
+ "license": "MIT",
758
+ "optional": true,
759
+ "os": [
760
+ "win32"
761
+ ],
762
+ "engines": {
763
+ "node": ">=18"
764
+ }
765
+ },
766
+ "node_modules/@esbuild/win32-x64": {
767
+ "version": "0.25.12",
768
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
769
+ "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
770
+ "cpu": [
771
+ "x64"
772
+ ],
773
+ "dev": true,
774
+ "license": "MIT",
775
+ "optional": true,
776
+ "os": [
777
+ "win32"
778
+ ],
779
+ "engines": {
780
+ "node": ">=18"
781
+ }
782
+ },
783
+ "node_modules/@eslint-community/eslint-utils": {
784
+ "version": "4.9.0",
785
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
786
+ "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
787
+ "dev": true,
788
+ "license": "MIT",
789
+ "dependencies": {
790
+ "eslint-visitor-keys": "^3.4.3"
791
+ },
792
+ "engines": {
793
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
794
+ },
795
+ "funding": {
796
+ "url": "https://opencollective.com/eslint"
797
+ },
798
+ "peerDependencies": {
799
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
800
+ }
801
+ },
802
+ "node_modules/@eslint-community/regexpp": {
803
+ "version": "4.12.2",
804
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
805
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
806
+ "dev": true,
807
+ "license": "MIT",
808
+ "engines": {
809
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
810
+ }
811
+ },
812
+ "node_modules/@eslint/config-array": {
813
+ "version": "0.21.1",
814
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
815
+ "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
816
+ "dev": true,
817
+ "license": "Apache-2.0",
818
+ "dependencies": {
819
+ "@eslint/object-schema": "^2.1.7",
820
+ "debug": "^4.3.1",
821
+ "minimatch": "^3.1.2"
822
+ },
823
+ "engines": {
824
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
825
+ }
826
+ },
827
+ "node_modules/@eslint/config-array/node_modules/brace-expansion": {
828
+ "version": "1.1.12",
829
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
830
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
831
+ "dev": true,
832
+ "license": "MIT",
833
+ "dependencies": {
834
+ "balanced-match": "^1.0.0",
835
+ "concat-map": "0.0.1"
836
+ }
837
+ },
838
+ "node_modules/@eslint/config-array/node_modules/minimatch": {
839
+ "version": "3.1.2",
840
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
841
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
842
+ "dev": true,
843
+ "license": "ISC",
844
+ "dependencies": {
845
+ "brace-expansion": "^1.1.7"
846
+ },
847
+ "engines": {
848
+ "node": "*"
849
+ }
850
+ },
851
+ "node_modules/@eslint/config-helpers": {
852
+ "version": "0.4.2",
853
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
854
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
855
+ "dev": true,
856
+ "license": "Apache-2.0",
857
+ "dependencies": {
858
+ "@eslint/core": "^0.17.0"
859
+ },
860
+ "engines": {
861
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
862
+ }
863
+ },
864
+ "node_modules/@eslint/core": {
865
+ "version": "0.17.0",
866
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
867
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
868
+ "dev": true,
869
+ "license": "Apache-2.0",
870
+ "dependencies": {
871
+ "@types/json-schema": "^7.0.15"
872
+ },
873
+ "engines": {
874
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
875
+ }
876
+ },
877
+ "node_modules/@eslint/eslintrc": {
878
+ "version": "3.3.1",
879
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
880
+ "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
881
+ "dev": true,
882
+ "license": "MIT",
883
+ "dependencies": {
884
+ "ajv": "^6.12.4",
885
+ "debug": "^4.3.2",
886
+ "espree": "^10.0.1",
887
+ "globals": "^14.0.0",
888
+ "ignore": "^5.2.0",
889
+ "import-fresh": "^3.2.1",
890
+ "js-yaml": "^4.1.0",
891
+ "minimatch": "^3.1.2",
892
+ "strip-json-comments": "^3.1.1"
893
+ },
894
+ "engines": {
895
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
896
+ },
897
+ "funding": {
898
+ "url": "https://opencollective.com/eslint"
899
+ }
900
+ },
901
+ "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
902
+ "version": "1.1.12",
903
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
904
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
905
+ "dev": true,
906
+ "license": "MIT",
907
+ "dependencies": {
908
+ "balanced-match": "^1.0.0",
909
+ "concat-map": "0.0.1"
910
+ }
911
+ },
912
+ "node_modules/@eslint/eslintrc/node_modules/ignore": {
913
+ "version": "5.3.2",
914
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
915
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
916
+ "dev": true,
917
+ "license": "MIT",
918
+ "engines": {
919
+ "node": ">= 4"
920
+ }
921
+ },
922
+ "node_modules/@eslint/eslintrc/node_modules/minimatch": {
923
+ "version": "3.1.2",
924
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
925
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
926
+ "dev": true,
927
+ "license": "ISC",
928
+ "dependencies": {
929
+ "brace-expansion": "^1.1.7"
930
+ },
931
+ "engines": {
932
+ "node": "*"
933
+ }
934
+ },
935
+ "node_modules/@eslint/js": {
936
+ "version": "9.39.1",
937
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz",
938
+ "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==",
939
+ "dev": true,
940
+ "license": "MIT",
941
+ "engines": {
942
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
943
+ },
944
+ "funding": {
945
+ "url": "https://eslint.org/donate"
946
+ }
947
+ },
948
+ "node_modules/@eslint/object-schema": {
949
+ "version": "2.1.7",
950
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
951
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
952
+ "dev": true,
953
+ "license": "Apache-2.0",
954
+ "engines": {
955
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
956
+ }
957
+ },
958
+ "node_modules/@eslint/plugin-kit": {
959
+ "version": "0.4.1",
960
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
961
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
962
+ "dev": true,
963
+ "license": "Apache-2.0",
964
+ "dependencies": {
965
+ "@eslint/core": "^0.17.0",
966
+ "levn": "^0.4.1"
967
+ },
968
+ "engines": {
969
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
970
+ }
971
+ },
972
+ "node_modules/@floating-ui/core": {
973
+ "version": "1.7.3",
974
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
975
+ "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
976
+ "license": "MIT",
977
+ "dependencies": {
978
+ "@floating-ui/utils": "^0.2.10"
979
+ }
980
+ },
981
+ "node_modules/@floating-ui/dom": {
982
+ "version": "1.7.4",
983
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz",
984
+ "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
985
+ "license": "MIT",
986
+ "dependencies": {
987
+ "@floating-ui/core": "^1.7.3",
988
+ "@floating-ui/utils": "^0.2.10"
989
+ }
990
+ },
991
+ "node_modules/@floating-ui/react-dom": {
992
+ "version": "2.1.6",
993
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz",
994
+ "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==",
995
+ "license": "MIT",
996
+ "dependencies": {
997
+ "@floating-ui/dom": "^1.7.4"
998
+ },
999
+ "peerDependencies": {
1000
+ "react": ">=16.8.0",
1001
+ "react-dom": ">=16.8.0"
1002
+ }
1003
+ },
1004
+ "node_modules/@floating-ui/utils": {
1005
+ "version": "0.2.10",
1006
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
1007
+ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
1008
+ "license": "MIT"
1009
+ },
1010
+ "node_modules/@humanfs/core": {
1011
+ "version": "0.19.1",
1012
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
1013
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
1014
+ "dev": true,
1015
+ "license": "Apache-2.0",
1016
+ "engines": {
1017
+ "node": ">=18.18.0"
1018
+ }
1019
+ },
1020
+ "node_modules/@humanfs/node": {
1021
+ "version": "0.16.7",
1022
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
1023
+ "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
1024
+ "dev": true,
1025
+ "license": "Apache-2.0",
1026
+ "dependencies": {
1027
+ "@humanfs/core": "^0.19.1",
1028
+ "@humanwhocodes/retry": "^0.4.0"
1029
+ },
1030
+ "engines": {
1031
+ "node": ">=18.18.0"
1032
+ }
1033
+ },
1034
+ "node_modules/@humanwhocodes/module-importer": {
1035
+ "version": "1.0.1",
1036
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
1037
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
1038
+ "dev": true,
1039
+ "license": "Apache-2.0",
1040
+ "engines": {
1041
+ "node": ">=12.22"
1042
+ },
1043
+ "funding": {
1044
+ "type": "github",
1045
+ "url": "https://github.com/sponsors/nzakas"
1046
+ }
1047
+ },
1048
+ "node_modules/@humanwhocodes/retry": {
1049
+ "version": "0.4.3",
1050
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
1051
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
1052
+ "dev": true,
1053
+ "license": "Apache-2.0",
1054
+ "engines": {
1055
+ "node": ">=18.18"
1056
+ },
1057
+ "funding": {
1058
+ "type": "github",
1059
+ "url": "https://github.com/sponsors/nzakas"
1060
+ }
1061
+ },
1062
+ "node_modules/@jridgewell/gen-mapping": {
1063
+ "version": "0.3.13",
1064
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
1065
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
1066
+ "dev": true,
1067
+ "license": "MIT",
1068
+ "dependencies": {
1069
+ "@jridgewell/sourcemap-codec": "^1.5.0",
1070
+ "@jridgewell/trace-mapping": "^0.3.24"
1071
+ }
1072
+ },
1073
+ "node_modules/@jridgewell/remapping": {
1074
+ "version": "2.3.5",
1075
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
1076
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
1077
+ "dev": true,
1078
+ "license": "MIT",
1079
+ "dependencies": {
1080
+ "@jridgewell/gen-mapping": "^0.3.5",
1081
+ "@jridgewell/trace-mapping": "^0.3.24"
1082
+ }
1083
+ },
1084
+ "node_modules/@jridgewell/resolve-uri": {
1085
+ "version": "3.1.2",
1086
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
1087
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
1088
+ "dev": true,
1089
+ "license": "MIT",
1090
+ "engines": {
1091
+ "node": ">=6.0.0"
1092
+ }
1093
+ },
1094
+ "node_modules/@jridgewell/sourcemap-codec": {
1095
+ "version": "1.5.5",
1096
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
1097
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
1098
+ "dev": true,
1099
+ "license": "MIT"
1100
+ },
1101
+ "node_modules/@jridgewell/trace-mapping": {
1102
+ "version": "0.3.31",
1103
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
1104
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
1105
+ "dev": true,
1106
+ "license": "MIT",
1107
+ "dependencies": {
1108
+ "@jridgewell/resolve-uri": "^3.1.0",
1109
+ "@jridgewell/sourcemap-codec": "^1.4.14"
1110
+ }
1111
+ },
1112
+ "node_modules/@nodelib/fs.scandir": {
1113
+ "version": "2.1.5",
1114
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
1115
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
1116
+ "dev": true,
1117
+ "license": "MIT",
1118
+ "dependencies": {
1119
+ "@nodelib/fs.stat": "2.0.5",
1120
+ "run-parallel": "^1.1.9"
1121
+ },
1122
+ "engines": {
1123
+ "node": ">= 8"
1124
+ }
1125
+ },
1126
+ "node_modules/@nodelib/fs.stat": {
1127
+ "version": "2.0.5",
1128
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
1129
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
1130
+ "dev": true,
1131
+ "license": "MIT",
1132
+ "engines": {
1133
+ "node": ">= 8"
1134
+ }
1135
+ },
1136
+ "node_modules/@nodelib/fs.walk": {
1137
+ "version": "1.2.8",
1138
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
1139
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
1140
+ "dev": true,
1141
+ "license": "MIT",
1142
+ "dependencies": {
1143
+ "@nodelib/fs.scandir": "2.1.5",
1144
+ "fastq": "^1.6.0"
1145
+ },
1146
+ "engines": {
1147
+ "node": ">= 8"
1148
+ }
1149
+ },
1150
+ "node_modules/@radix-ui/number": {
1151
+ "version": "1.1.1",
1152
+ "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
1153
+ "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==",
1154
+ "license": "MIT"
1155
+ },
1156
+ "node_modules/@radix-ui/primitive": {
1157
+ "version": "1.1.3",
1158
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
1159
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
1160
+ "license": "MIT"
1161
+ },
1162
+ "node_modules/@radix-ui/react-arrow": {
1163
+ "version": "1.1.7",
1164
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
1165
+ "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
1166
+ "license": "MIT",
1167
+ "dependencies": {
1168
+ "@radix-ui/react-primitive": "2.1.3"
1169
+ },
1170
+ "peerDependencies": {
1171
+ "@types/react": "*",
1172
+ "@types/react-dom": "*",
1173
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1174
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1175
+ },
1176
+ "peerDependenciesMeta": {
1177
+ "@types/react": {
1178
+ "optional": true
1179
+ },
1180
+ "@types/react-dom": {
1181
+ "optional": true
1182
+ }
1183
+ }
1184
+ },
1185
+ "node_modules/@radix-ui/react-collection": {
1186
+ "version": "1.1.7",
1187
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
1188
+ "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
1189
+ "license": "MIT",
1190
+ "dependencies": {
1191
+ "@radix-ui/react-compose-refs": "1.1.2",
1192
+ "@radix-ui/react-context": "1.1.2",
1193
+ "@radix-ui/react-primitive": "2.1.3",
1194
+ "@radix-ui/react-slot": "1.2.3"
1195
+ },
1196
+ "peerDependencies": {
1197
+ "@types/react": "*",
1198
+ "@types/react-dom": "*",
1199
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1200
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1201
+ },
1202
+ "peerDependenciesMeta": {
1203
+ "@types/react": {
1204
+ "optional": true
1205
+ },
1206
+ "@types/react-dom": {
1207
+ "optional": true
1208
+ }
1209
+ }
1210
+ },
1211
+ "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
1212
+ "version": "1.2.3",
1213
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
1214
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
1215
+ "license": "MIT",
1216
+ "dependencies": {
1217
+ "@radix-ui/react-compose-refs": "1.1.2"
1218
+ },
1219
+ "peerDependencies": {
1220
+ "@types/react": "*",
1221
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1222
+ },
1223
+ "peerDependenciesMeta": {
1224
+ "@types/react": {
1225
+ "optional": true
1226
+ }
1227
+ }
1228
+ },
1229
+ "node_modules/@radix-ui/react-compose-refs": {
1230
+ "version": "1.1.2",
1231
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
1232
+ "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
1233
+ "license": "MIT",
1234
+ "peerDependencies": {
1235
+ "@types/react": "*",
1236
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1237
+ },
1238
+ "peerDependenciesMeta": {
1239
+ "@types/react": {
1240
+ "optional": true
1241
+ }
1242
+ }
1243
+ },
1244
+ "node_modules/@radix-ui/react-context": {
1245
+ "version": "1.1.2",
1246
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
1247
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
1248
+ "license": "MIT",
1249
+ "peerDependencies": {
1250
+ "@types/react": "*",
1251
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1252
+ },
1253
+ "peerDependenciesMeta": {
1254
+ "@types/react": {
1255
+ "optional": true
1256
+ }
1257
+ }
1258
+ },
1259
+ "node_modules/@radix-ui/react-dialog": {
1260
+ "version": "1.1.15",
1261
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz",
1262
+ "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==",
1263
+ "license": "MIT",
1264
+ "dependencies": {
1265
+ "@radix-ui/primitive": "1.1.3",
1266
+ "@radix-ui/react-compose-refs": "1.1.2",
1267
+ "@radix-ui/react-context": "1.1.2",
1268
+ "@radix-ui/react-dismissable-layer": "1.1.11",
1269
+ "@radix-ui/react-focus-guards": "1.1.3",
1270
+ "@radix-ui/react-focus-scope": "1.1.7",
1271
+ "@radix-ui/react-id": "1.1.1",
1272
+ "@radix-ui/react-portal": "1.1.9",
1273
+ "@radix-ui/react-presence": "1.1.5",
1274
+ "@radix-ui/react-primitive": "2.1.3",
1275
+ "@radix-ui/react-slot": "1.2.3",
1276
+ "@radix-ui/react-use-controllable-state": "1.2.2",
1277
+ "aria-hidden": "^1.2.4",
1278
+ "react-remove-scroll": "^2.6.3"
1279
+ },
1280
+ "peerDependencies": {
1281
+ "@types/react": "*",
1282
+ "@types/react-dom": "*",
1283
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1284
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1285
+ },
1286
+ "peerDependenciesMeta": {
1287
+ "@types/react": {
1288
+ "optional": true
1289
+ },
1290
+ "@types/react-dom": {
1291
+ "optional": true
1292
+ }
1293
+ }
1294
+ },
1295
+ "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": {
1296
+ "version": "1.2.3",
1297
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
1298
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
1299
+ "license": "MIT",
1300
+ "dependencies": {
1301
+ "@radix-ui/react-compose-refs": "1.1.2"
1302
+ },
1303
+ "peerDependencies": {
1304
+ "@types/react": "*",
1305
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1306
+ },
1307
+ "peerDependenciesMeta": {
1308
+ "@types/react": {
1309
+ "optional": true
1310
+ }
1311
+ }
1312
+ },
1313
+ "node_modules/@radix-ui/react-direction": {
1314
+ "version": "1.1.1",
1315
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
1316
+ "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
1317
+ "license": "MIT",
1318
+ "peerDependencies": {
1319
+ "@types/react": "*",
1320
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1321
+ },
1322
+ "peerDependenciesMeta": {
1323
+ "@types/react": {
1324
+ "optional": true
1325
+ }
1326
+ }
1327
+ },
1328
+ "node_modules/@radix-ui/react-dismissable-layer": {
1329
+ "version": "1.1.11",
1330
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
1331
+ "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
1332
+ "license": "MIT",
1333
+ "dependencies": {
1334
+ "@radix-ui/primitive": "1.1.3",
1335
+ "@radix-ui/react-compose-refs": "1.1.2",
1336
+ "@radix-ui/react-primitive": "2.1.3",
1337
+ "@radix-ui/react-use-callback-ref": "1.1.1",
1338
+ "@radix-ui/react-use-escape-keydown": "1.1.1"
1339
+ },
1340
+ "peerDependencies": {
1341
+ "@types/react": "*",
1342
+ "@types/react-dom": "*",
1343
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1344
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1345
+ },
1346
+ "peerDependenciesMeta": {
1347
+ "@types/react": {
1348
+ "optional": true
1349
+ },
1350
+ "@types/react-dom": {
1351
+ "optional": true
1352
+ }
1353
+ }
1354
+ },
1355
+ "node_modules/@radix-ui/react-focus-guards": {
1356
+ "version": "1.1.3",
1357
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
1358
+ "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
1359
+ "license": "MIT",
1360
+ "peerDependencies": {
1361
+ "@types/react": "*",
1362
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1363
+ },
1364
+ "peerDependenciesMeta": {
1365
+ "@types/react": {
1366
+ "optional": true
1367
+ }
1368
+ }
1369
+ },
1370
+ "node_modules/@radix-ui/react-focus-scope": {
1371
+ "version": "1.1.7",
1372
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
1373
+ "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
1374
+ "license": "MIT",
1375
+ "dependencies": {
1376
+ "@radix-ui/react-compose-refs": "1.1.2",
1377
+ "@radix-ui/react-primitive": "2.1.3",
1378
+ "@radix-ui/react-use-callback-ref": "1.1.1"
1379
+ },
1380
+ "peerDependencies": {
1381
+ "@types/react": "*",
1382
+ "@types/react-dom": "*",
1383
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1384
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1385
+ },
1386
+ "peerDependenciesMeta": {
1387
+ "@types/react": {
1388
+ "optional": true
1389
+ },
1390
+ "@types/react-dom": {
1391
+ "optional": true
1392
+ }
1393
+ }
1394
+ },
1395
+ "node_modules/@radix-ui/react-id": {
1396
+ "version": "1.1.1",
1397
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
1398
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
1399
+ "license": "MIT",
1400
+ "dependencies": {
1401
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1402
+ },
1403
+ "peerDependencies": {
1404
+ "@types/react": "*",
1405
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1406
+ },
1407
+ "peerDependenciesMeta": {
1408
+ "@types/react": {
1409
+ "optional": true
1410
+ }
1411
+ }
1412
+ },
1413
+ "node_modules/@radix-ui/react-popover": {
1414
+ "version": "1.1.15",
1415
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz",
1416
+ "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==",
1417
+ "license": "MIT",
1418
+ "dependencies": {
1419
+ "@radix-ui/primitive": "1.1.3",
1420
+ "@radix-ui/react-compose-refs": "1.1.2",
1421
+ "@radix-ui/react-context": "1.1.2",
1422
+ "@radix-ui/react-dismissable-layer": "1.1.11",
1423
+ "@radix-ui/react-focus-guards": "1.1.3",
1424
+ "@radix-ui/react-focus-scope": "1.1.7",
1425
+ "@radix-ui/react-id": "1.1.1",
1426
+ "@radix-ui/react-popper": "1.2.8",
1427
+ "@radix-ui/react-portal": "1.1.9",
1428
+ "@radix-ui/react-presence": "1.1.5",
1429
+ "@radix-ui/react-primitive": "2.1.3",
1430
+ "@radix-ui/react-slot": "1.2.3",
1431
+ "@radix-ui/react-use-controllable-state": "1.2.2",
1432
+ "aria-hidden": "^1.2.4",
1433
+ "react-remove-scroll": "^2.6.3"
1434
+ },
1435
+ "peerDependencies": {
1436
+ "@types/react": "*",
1437
+ "@types/react-dom": "*",
1438
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1439
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1440
+ },
1441
+ "peerDependenciesMeta": {
1442
+ "@types/react": {
1443
+ "optional": true
1444
+ },
1445
+ "@types/react-dom": {
1446
+ "optional": true
1447
+ }
1448
+ }
1449
+ },
1450
+ "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": {
1451
+ "version": "1.2.3",
1452
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
1453
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
1454
+ "license": "MIT",
1455
+ "dependencies": {
1456
+ "@radix-ui/react-compose-refs": "1.1.2"
1457
+ },
1458
+ "peerDependencies": {
1459
+ "@types/react": "*",
1460
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1461
+ },
1462
+ "peerDependenciesMeta": {
1463
+ "@types/react": {
1464
+ "optional": true
1465
+ }
1466
+ }
1467
+ },
1468
+ "node_modules/@radix-ui/react-popper": {
1469
+ "version": "1.2.8",
1470
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
1471
+ "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
1472
+ "license": "MIT",
1473
+ "dependencies": {
1474
+ "@floating-ui/react-dom": "^2.0.0",
1475
+ "@radix-ui/react-arrow": "1.1.7",
1476
+ "@radix-ui/react-compose-refs": "1.1.2",
1477
+ "@radix-ui/react-context": "1.1.2",
1478
+ "@radix-ui/react-primitive": "2.1.3",
1479
+ "@radix-ui/react-use-callback-ref": "1.1.1",
1480
+ "@radix-ui/react-use-layout-effect": "1.1.1",
1481
+ "@radix-ui/react-use-rect": "1.1.1",
1482
+ "@radix-ui/react-use-size": "1.1.1",
1483
+ "@radix-ui/rect": "1.1.1"
1484
+ },
1485
+ "peerDependencies": {
1486
+ "@types/react": "*",
1487
+ "@types/react-dom": "*",
1488
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1489
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1490
+ },
1491
+ "peerDependenciesMeta": {
1492
+ "@types/react": {
1493
+ "optional": true
1494
+ },
1495
+ "@types/react-dom": {
1496
+ "optional": true
1497
+ }
1498
+ }
1499
+ },
1500
+ "node_modules/@radix-ui/react-portal": {
1501
+ "version": "1.1.9",
1502
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
1503
+ "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
1504
+ "license": "MIT",
1505
+ "dependencies": {
1506
+ "@radix-ui/react-primitive": "2.1.3",
1507
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1508
+ },
1509
+ "peerDependencies": {
1510
+ "@types/react": "*",
1511
+ "@types/react-dom": "*",
1512
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1513
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1514
+ },
1515
+ "peerDependenciesMeta": {
1516
+ "@types/react": {
1517
+ "optional": true
1518
+ },
1519
+ "@types/react-dom": {
1520
+ "optional": true
1521
+ }
1522
+ }
1523
+ },
1524
+ "node_modules/@radix-ui/react-presence": {
1525
+ "version": "1.1.5",
1526
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
1527
+ "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
1528
+ "license": "MIT",
1529
+ "dependencies": {
1530
+ "@radix-ui/react-compose-refs": "1.1.2",
1531
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1532
+ },
1533
+ "peerDependencies": {
1534
+ "@types/react": "*",
1535
+ "@types/react-dom": "*",
1536
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1537
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1538
+ },
1539
+ "peerDependenciesMeta": {
1540
+ "@types/react": {
1541
+ "optional": true
1542
+ },
1543
+ "@types/react-dom": {
1544
+ "optional": true
1545
+ }
1546
+ }
1547
+ },
1548
+ "node_modules/@radix-ui/react-primitive": {
1549
+ "version": "2.1.3",
1550
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
1551
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
1552
+ "license": "MIT",
1553
+ "dependencies": {
1554
+ "@radix-ui/react-slot": "1.2.3"
1555
+ },
1556
+ "peerDependencies": {
1557
+ "@types/react": "*",
1558
+ "@types/react-dom": "*",
1559
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1560
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1561
+ },
1562
+ "peerDependenciesMeta": {
1563
+ "@types/react": {
1564
+ "optional": true
1565
+ },
1566
+ "@types/react-dom": {
1567
+ "optional": true
1568
+ }
1569
+ }
1570
+ },
1571
+ "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
1572
+ "version": "1.2.3",
1573
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
1574
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
1575
+ "license": "MIT",
1576
+ "dependencies": {
1577
+ "@radix-ui/react-compose-refs": "1.1.2"
1578
+ },
1579
+ "peerDependencies": {
1580
+ "@types/react": "*",
1581
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1582
+ },
1583
+ "peerDependenciesMeta": {
1584
+ "@types/react": {
1585
+ "optional": true
1586
+ }
1587
+ }
1588
+ },
1589
+ "node_modules/@radix-ui/react-select": {
1590
+ "version": "2.2.6",
1591
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz",
1592
+ "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==",
1593
+ "license": "MIT",
1594
+ "dependencies": {
1595
+ "@radix-ui/number": "1.1.1",
1596
+ "@radix-ui/primitive": "1.1.3",
1597
+ "@radix-ui/react-collection": "1.1.7",
1598
+ "@radix-ui/react-compose-refs": "1.1.2",
1599
+ "@radix-ui/react-context": "1.1.2",
1600
+ "@radix-ui/react-direction": "1.1.1",
1601
+ "@radix-ui/react-dismissable-layer": "1.1.11",
1602
+ "@radix-ui/react-focus-guards": "1.1.3",
1603
+ "@radix-ui/react-focus-scope": "1.1.7",
1604
+ "@radix-ui/react-id": "1.1.1",
1605
+ "@radix-ui/react-popper": "1.2.8",
1606
+ "@radix-ui/react-portal": "1.1.9",
1607
+ "@radix-ui/react-primitive": "2.1.3",
1608
+ "@radix-ui/react-slot": "1.2.3",
1609
+ "@radix-ui/react-use-callback-ref": "1.1.1",
1610
+ "@radix-ui/react-use-controllable-state": "1.2.2",
1611
+ "@radix-ui/react-use-layout-effect": "1.1.1",
1612
+ "@radix-ui/react-use-previous": "1.1.1",
1613
+ "@radix-ui/react-visually-hidden": "1.2.3",
1614
+ "aria-hidden": "^1.2.4",
1615
+ "react-remove-scroll": "^2.6.3"
1616
+ },
1617
+ "peerDependencies": {
1618
+ "@types/react": "*",
1619
+ "@types/react-dom": "*",
1620
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1621
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1622
+ },
1623
+ "peerDependenciesMeta": {
1624
+ "@types/react": {
1625
+ "optional": true
1626
+ },
1627
+ "@types/react-dom": {
1628
+ "optional": true
1629
+ }
1630
+ }
1631
+ },
1632
+ "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": {
1633
+ "version": "1.2.3",
1634
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
1635
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
1636
+ "license": "MIT",
1637
+ "dependencies": {
1638
+ "@radix-ui/react-compose-refs": "1.1.2"
1639
+ },
1640
+ "peerDependencies": {
1641
+ "@types/react": "*",
1642
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1643
+ },
1644
+ "peerDependenciesMeta": {
1645
+ "@types/react": {
1646
+ "optional": true
1647
+ }
1648
+ }
1649
+ },
1650
+ "node_modules/@radix-ui/react-slot": {
1651
+ "version": "1.2.4",
1652
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz",
1653
+ "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==",
1654
+ "license": "MIT",
1655
+ "dependencies": {
1656
+ "@radix-ui/react-compose-refs": "1.1.2"
1657
+ },
1658
+ "peerDependencies": {
1659
+ "@types/react": "*",
1660
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1661
+ },
1662
+ "peerDependenciesMeta": {
1663
+ "@types/react": {
1664
+ "optional": true
1665
+ }
1666
+ }
1667
+ },
1668
+ "node_modules/@radix-ui/react-use-callback-ref": {
1669
+ "version": "1.1.1",
1670
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
1671
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
1672
+ "license": "MIT",
1673
+ "peerDependencies": {
1674
+ "@types/react": "*",
1675
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1676
+ },
1677
+ "peerDependenciesMeta": {
1678
+ "@types/react": {
1679
+ "optional": true
1680
+ }
1681
+ }
1682
+ },
1683
+ "node_modules/@radix-ui/react-use-controllable-state": {
1684
+ "version": "1.2.2",
1685
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
1686
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
1687
+ "license": "MIT",
1688
+ "dependencies": {
1689
+ "@radix-ui/react-use-effect-event": "0.0.2",
1690
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1691
+ },
1692
+ "peerDependencies": {
1693
+ "@types/react": "*",
1694
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1695
+ },
1696
+ "peerDependenciesMeta": {
1697
+ "@types/react": {
1698
+ "optional": true
1699
+ }
1700
+ }
1701
+ },
1702
+ "node_modules/@radix-ui/react-use-effect-event": {
1703
+ "version": "0.0.2",
1704
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
1705
+ "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
1706
+ "license": "MIT",
1707
+ "dependencies": {
1708
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1709
+ },
1710
+ "peerDependencies": {
1711
+ "@types/react": "*",
1712
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1713
+ },
1714
+ "peerDependenciesMeta": {
1715
+ "@types/react": {
1716
+ "optional": true
1717
+ }
1718
+ }
1719
+ },
1720
+ "node_modules/@radix-ui/react-use-escape-keydown": {
1721
+ "version": "1.1.1",
1722
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
1723
+ "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
1724
+ "license": "MIT",
1725
+ "dependencies": {
1726
+ "@radix-ui/react-use-callback-ref": "1.1.1"
1727
+ },
1728
+ "peerDependencies": {
1729
+ "@types/react": "*",
1730
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1731
+ },
1732
+ "peerDependenciesMeta": {
1733
+ "@types/react": {
1734
+ "optional": true
1735
+ }
1736
+ }
1737
+ },
1738
+ "node_modules/@radix-ui/react-use-layout-effect": {
1739
+ "version": "1.1.1",
1740
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
1741
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
1742
+ "license": "MIT",
1743
+ "peerDependencies": {
1744
+ "@types/react": "*",
1745
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1746
+ },
1747
+ "peerDependenciesMeta": {
1748
+ "@types/react": {
1749
+ "optional": true
1750
+ }
1751
+ }
1752
+ },
1753
+ "node_modules/@radix-ui/react-use-previous": {
1754
+ "version": "1.1.1",
1755
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
1756
+ "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
1757
+ "license": "MIT",
1758
+ "peerDependencies": {
1759
+ "@types/react": "*",
1760
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1761
+ },
1762
+ "peerDependenciesMeta": {
1763
+ "@types/react": {
1764
+ "optional": true
1765
+ }
1766
+ }
1767
+ },
1768
+ "node_modules/@radix-ui/react-use-rect": {
1769
+ "version": "1.1.1",
1770
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
1771
+ "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
1772
+ "license": "MIT",
1773
+ "dependencies": {
1774
+ "@radix-ui/rect": "1.1.1"
1775
+ },
1776
+ "peerDependencies": {
1777
+ "@types/react": "*",
1778
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1779
+ },
1780
+ "peerDependenciesMeta": {
1781
+ "@types/react": {
1782
+ "optional": true
1783
+ }
1784
+ }
1785
+ },
1786
+ "node_modules/@radix-ui/react-use-size": {
1787
+ "version": "1.1.1",
1788
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
1789
+ "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
1790
+ "license": "MIT",
1791
+ "dependencies": {
1792
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1793
+ },
1794
+ "peerDependencies": {
1795
+ "@types/react": "*",
1796
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1797
+ },
1798
+ "peerDependenciesMeta": {
1799
+ "@types/react": {
1800
+ "optional": true
1801
+ }
1802
+ }
1803
+ },
1804
+ "node_modules/@radix-ui/react-visually-hidden": {
1805
+ "version": "1.2.3",
1806
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
1807
+ "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
1808
+ "license": "MIT",
1809
+ "dependencies": {
1810
+ "@radix-ui/react-primitive": "2.1.3"
1811
+ },
1812
+ "peerDependencies": {
1813
+ "@types/react": "*",
1814
+ "@types/react-dom": "*",
1815
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1816
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1817
+ },
1818
+ "peerDependenciesMeta": {
1819
+ "@types/react": {
1820
+ "optional": true
1821
+ },
1822
+ "@types/react-dom": {
1823
+ "optional": true
1824
+ }
1825
+ }
1826
+ },
1827
+ "node_modules/@radix-ui/rect": {
1828
+ "version": "1.1.1",
1829
+ "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
1830
+ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
1831
+ "license": "MIT"
1832
+ },
1833
+ "node_modules/@rolldown/pluginutils": {
1834
+ "version": "1.0.0-beta.47",
1835
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.47.tgz",
1836
+ "integrity": "sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==",
1837
+ "dev": true,
1838
+ "license": "MIT"
1839
+ },
1840
+ "node_modules/@rollup/rollup-android-arm-eabi": {
1841
+ "version": "4.53.2",
1842
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.2.tgz",
1843
+ "integrity": "sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==",
1844
+ "cpu": [
1845
+ "arm"
1846
+ ],
1847
+ "dev": true,
1848
+ "license": "MIT",
1849
+ "optional": true,
1850
+ "os": [
1851
+ "android"
1852
+ ]
1853
+ },
1854
+ "node_modules/@rollup/rollup-android-arm64": {
1855
+ "version": "4.53.2",
1856
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.2.tgz",
1857
+ "integrity": "sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==",
1858
+ "cpu": [
1859
+ "arm64"
1860
+ ],
1861
+ "dev": true,
1862
+ "license": "MIT",
1863
+ "optional": true,
1864
+ "os": [
1865
+ "android"
1866
+ ]
1867
+ },
1868
+ "node_modules/@rollup/rollup-darwin-arm64": {
1869
+ "version": "4.53.2",
1870
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.2.tgz",
1871
+ "integrity": "sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==",
1872
+ "cpu": [
1873
+ "arm64"
1874
+ ],
1875
+ "dev": true,
1876
+ "license": "MIT",
1877
+ "optional": true,
1878
+ "os": [
1879
+ "darwin"
1880
+ ]
1881
+ },
1882
+ "node_modules/@rollup/rollup-darwin-x64": {
1883
+ "version": "4.53.2",
1884
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.2.tgz",
1885
+ "integrity": "sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==",
1886
+ "cpu": [
1887
+ "x64"
1888
+ ],
1889
+ "dev": true,
1890
+ "license": "MIT",
1891
+ "optional": true,
1892
+ "os": [
1893
+ "darwin"
1894
+ ]
1895
+ },
1896
+ "node_modules/@rollup/rollup-freebsd-arm64": {
1897
+ "version": "4.53.2",
1898
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.2.tgz",
1899
+ "integrity": "sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==",
1900
+ "cpu": [
1901
+ "arm64"
1902
+ ],
1903
+ "dev": true,
1904
+ "license": "MIT",
1905
+ "optional": true,
1906
+ "os": [
1907
+ "freebsd"
1908
+ ]
1909
+ },
1910
+ "node_modules/@rollup/rollup-freebsd-x64": {
1911
+ "version": "4.53.2",
1912
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.2.tgz",
1913
+ "integrity": "sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==",
1914
+ "cpu": [
1915
+ "x64"
1916
+ ],
1917
+ "dev": true,
1918
+ "license": "MIT",
1919
+ "optional": true,
1920
+ "os": [
1921
+ "freebsd"
1922
+ ]
1923
+ },
1924
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
1925
+ "version": "4.53.2",
1926
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.2.tgz",
1927
+ "integrity": "sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==",
1928
+ "cpu": [
1929
+ "arm"
1930
+ ],
1931
+ "dev": true,
1932
+ "license": "MIT",
1933
+ "optional": true,
1934
+ "os": [
1935
+ "linux"
1936
+ ]
1937
+ },
1938
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
1939
+ "version": "4.53.2",
1940
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.2.tgz",
1941
+ "integrity": "sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==",
1942
+ "cpu": [
1943
+ "arm"
1944
+ ],
1945
+ "dev": true,
1946
+ "license": "MIT",
1947
+ "optional": true,
1948
+ "os": [
1949
+ "linux"
1950
+ ]
1951
+ },
1952
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
1953
+ "version": "4.53.2",
1954
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.2.tgz",
1955
+ "integrity": "sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==",
1956
+ "cpu": [
1957
+ "arm64"
1958
+ ],
1959
+ "dev": true,
1960
+ "license": "MIT",
1961
+ "optional": true,
1962
+ "os": [
1963
+ "linux"
1964
+ ]
1965
+ },
1966
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
1967
+ "version": "4.53.2",
1968
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.2.tgz",
1969
+ "integrity": "sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==",
1970
+ "cpu": [
1971
+ "arm64"
1972
+ ],
1973
+ "dev": true,
1974
+ "license": "MIT",
1975
+ "optional": true,
1976
+ "os": [
1977
+ "linux"
1978
+ ]
1979
+ },
1980
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
1981
+ "version": "4.53.2",
1982
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.2.tgz",
1983
+ "integrity": "sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==",
1984
+ "cpu": [
1985
+ "loong64"
1986
+ ],
1987
+ "dev": true,
1988
+ "license": "MIT",
1989
+ "optional": true,
1990
+ "os": [
1991
+ "linux"
1992
+ ]
1993
+ },
1994
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
1995
+ "version": "4.53.2",
1996
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.2.tgz",
1997
+ "integrity": "sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==",
1998
+ "cpu": [
1999
+ "ppc64"
2000
+ ],
2001
+ "dev": true,
2002
+ "license": "MIT",
2003
+ "optional": true,
2004
+ "os": [
2005
+ "linux"
2006
+ ]
2007
+ },
2008
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
2009
+ "version": "4.53.2",
2010
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.2.tgz",
2011
+ "integrity": "sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==",
2012
+ "cpu": [
2013
+ "riscv64"
2014
+ ],
2015
+ "dev": true,
2016
+ "license": "MIT",
2017
+ "optional": true,
2018
+ "os": [
2019
+ "linux"
2020
+ ]
2021
+ },
2022
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
2023
+ "version": "4.53.2",
2024
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.2.tgz",
2025
+ "integrity": "sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==",
2026
+ "cpu": [
2027
+ "riscv64"
2028
+ ],
2029
+ "dev": true,
2030
+ "license": "MIT",
2031
+ "optional": true,
2032
+ "os": [
2033
+ "linux"
2034
+ ]
2035
+ },
2036
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
2037
+ "version": "4.53.2",
2038
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.2.tgz",
2039
+ "integrity": "sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==",
2040
+ "cpu": [
2041
+ "s390x"
2042
+ ],
2043
+ "dev": true,
2044
+ "license": "MIT",
2045
+ "optional": true,
2046
+ "os": [
2047
+ "linux"
2048
+ ]
2049
+ },
2050
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
2051
+ "version": "4.53.2",
2052
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.2.tgz",
2053
+ "integrity": "sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==",
2054
+ "cpu": [
2055
+ "x64"
2056
+ ],
2057
+ "dev": true,
2058
+ "license": "MIT",
2059
+ "optional": true,
2060
+ "os": [
2061
+ "linux"
2062
+ ]
2063
+ },
2064
+ "node_modules/@rollup/rollup-linux-x64-musl": {
2065
+ "version": "4.53.2",
2066
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.2.tgz",
2067
+ "integrity": "sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==",
2068
+ "cpu": [
2069
+ "x64"
2070
+ ],
2071
+ "dev": true,
2072
+ "license": "MIT",
2073
+ "optional": true,
2074
+ "os": [
2075
+ "linux"
2076
+ ]
2077
+ },
2078
+ "node_modules/@rollup/rollup-openharmony-arm64": {
2079
+ "version": "4.53.2",
2080
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.2.tgz",
2081
+ "integrity": "sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==",
2082
+ "cpu": [
2083
+ "arm64"
2084
+ ],
2085
+ "dev": true,
2086
+ "license": "MIT",
2087
+ "optional": true,
2088
+ "os": [
2089
+ "openharmony"
2090
+ ]
2091
+ },
2092
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
2093
+ "version": "4.53.2",
2094
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.2.tgz",
2095
+ "integrity": "sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==",
2096
+ "cpu": [
2097
+ "arm64"
2098
+ ],
2099
+ "dev": true,
2100
+ "license": "MIT",
2101
+ "optional": true,
2102
+ "os": [
2103
+ "win32"
2104
+ ]
2105
+ },
2106
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
2107
+ "version": "4.53.2",
2108
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.2.tgz",
2109
+ "integrity": "sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==",
2110
+ "cpu": [
2111
+ "ia32"
2112
+ ],
2113
+ "dev": true,
2114
+ "license": "MIT",
2115
+ "optional": true,
2116
+ "os": [
2117
+ "win32"
2118
+ ]
2119
+ },
2120
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
2121
+ "version": "4.53.2",
2122
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.2.tgz",
2123
+ "integrity": "sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==",
2124
+ "cpu": [
2125
+ "x64"
2126
+ ],
2127
+ "dev": true,
2128
+ "license": "MIT",
2129
+ "optional": true,
2130
+ "os": [
2131
+ "win32"
2132
+ ]
2133
+ },
2134
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
2135
+ "version": "4.53.2",
2136
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.2.tgz",
2137
+ "integrity": "sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==",
2138
+ "cpu": [
2139
+ "x64"
2140
+ ],
2141
+ "dev": true,
2142
+ "license": "MIT",
2143
+ "optional": true,
2144
+ "os": [
2145
+ "win32"
2146
+ ]
2147
+ },
2148
+ "node_modules/@tailwindcss/node": {
2149
+ "version": "4.1.17",
2150
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.17.tgz",
2151
+ "integrity": "sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg==",
2152
+ "dev": true,
2153
+ "license": "MIT",
2154
+ "dependencies": {
2155
+ "@jridgewell/remapping": "^2.3.4",
2156
+ "enhanced-resolve": "^5.18.3",
2157
+ "jiti": "^2.6.1",
2158
+ "lightningcss": "1.30.2",
2159
+ "magic-string": "^0.30.21",
2160
+ "source-map-js": "^1.2.1",
2161
+ "tailwindcss": "4.1.17"
2162
+ }
2163
+ },
2164
+ "node_modules/@tailwindcss/oxide": {
2165
+ "version": "4.1.17",
2166
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.17.tgz",
2167
+ "integrity": "sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA==",
2168
+ "dev": true,
2169
+ "license": "MIT",
2170
+ "engines": {
2171
+ "node": ">= 10"
2172
+ },
2173
+ "optionalDependencies": {
2174
+ "@tailwindcss/oxide-android-arm64": "4.1.17",
2175
+ "@tailwindcss/oxide-darwin-arm64": "4.1.17",
2176
+ "@tailwindcss/oxide-darwin-x64": "4.1.17",
2177
+ "@tailwindcss/oxide-freebsd-x64": "4.1.17",
2178
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.17",
2179
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.1.17",
2180
+ "@tailwindcss/oxide-linux-arm64-musl": "4.1.17",
2181
+ "@tailwindcss/oxide-linux-x64-gnu": "4.1.17",
2182
+ "@tailwindcss/oxide-linux-x64-musl": "4.1.17",
2183
+ "@tailwindcss/oxide-wasm32-wasi": "4.1.17",
2184
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.1.17",
2185
+ "@tailwindcss/oxide-win32-x64-msvc": "4.1.17"
2186
+ }
2187
+ },
2188
+ "node_modules/@tailwindcss/oxide-android-arm64": {
2189
+ "version": "4.1.17",
2190
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.17.tgz",
2191
+ "integrity": "sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ==",
2192
+ "cpu": [
2193
+ "arm64"
2194
+ ],
2195
+ "dev": true,
2196
+ "license": "MIT",
2197
+ "optional": true,
2198
+ "os": [
2199
+ "android"
2200
+ ],
2201
+ "engines": {
2202
+ "node": ">= 10"
2203
+ }
2204
+ },
2205
+ "node_modules/@tailwindcss/oxide-darwin-arm64": {
2206
+ "version": "4.1.17",
2207
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.17.tgz",
2208
+ "integrity": "sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg==",
2209
+ "cpu": [
2210
+ "arm64"
2211
+ ],
2212
+ "dev": true,
2213
+ "license": "MIT",
2214
+ "optional": true,
2215
+ "os": [
2216
+ "darwin"
2217
+ ],
2218
+ "engines": {
2219
+ "node": ">= 10"
2220
+ }
2221
+ },
2222
+ "node_modules/@tailwindcss/oxide-darwin-x64": {
2223
+ "version": "4.1.17",
2224
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.17.tgz",
2225
+ "integrity": "sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog==",
2226
+ "cpu": [
2227
+ "x64"
2228
+ ],
2229
+ "dev": true,
2230
+ "license": "MIT",
2231
+ "optional": true,
2232
+ "os": [
2233
+ "darwin"
2234
+ ],
2235
+ "engines": {
2236
+ "node": ">= 10"
2237
+ }
2238
+ },
2239
+ "node_modules/@tailwindcss/oxide-freebsd-x64": {
2240
+ "version": "4.1.17",
2241
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.17.tgz",
2242
+ "integrity": "sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g==",
2243
+ "cpu": [
2244
+ "x64"
2245
+ ],
2246
+ "dev": true,
2247
+ "license": "MIT",
2248
+ "optional": true,
2249
+ "os": [
2250
+ "freebsd"
2251
+ ],
2252
+ "engines": {
2253
+ "node": ">= 10"
2254
+ }
2255
+ },
2256
+ "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
2257
+ "version": "4.1.17",
2258
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.17.tgz",
2259
+ "integrity": "sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ==",
2260
+ "cpu": [
2261
+ "arm"
2262
+ ],
2263
+ "dev": true,
2264
+ "license": "MIT",
2265
+ "optional": true,
2266
+ "os": [
2267
+ "linux"
2268
+ ],
2269
+ "engines": {
2270
+ "node": ">= 10"
2271
+ }
2272
+ },
2273
+ "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
2274
+ "version": "4.1.17",
2275
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.17.tgz",
2276
+ "integrity": "sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ==",
2277
+ "cpu": [
2278
+ "arm64"
2279
+ ],
2280
+ "dev": true,
2281
+ "license": "MIT",
2282
+ "optional": true,
2283
+ "os": [
2284
+ "linux"
2285
+ ],
2286
+ "engines": {
2287
+ "node": ">= 10"
2288
+ }
2289
+ },
2290
+ "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
2291
+ "version": "4.1.17",
2292
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.17.tgz",
2293
+ "integrity": "sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==",
2294
+ "cpu": [
2295
+ "arm64"
2296
+ ],
2297
+ "dev": true,
2298
+ "license": "MIT",
2299
+ "optional": true,
2300
+ "os": [
2301
+ "linux"
2302
+ ],
2303
+ "engines": {
2304
+ "node": ">= 10"
2305
+ }
2306
+ },
2307
+ "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
2308
+ "version": "4.1.17",
2309
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.17.tgz",
2310
+ "integrity": "sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==",
2311
+ "cpu": [
2312
+ "x64"
2313
+ ],
2314
+ "dev": true,
2315
+ "license": "MIT",
2316
+ "optional": true,
2317
+ "os": [
2318
+ "linux"
2319
+ ],
2320
+ "engines": {
2321
+ "node": ">= 10"
2322
+ }
2323
+ },
2324
+ "node_modules/@tailwindcss/oxide-linux-x64-musl": {
2325
+ "version": "4.1.17",
2326
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.17.tgz",
2327
+ "integrity": "sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==",
2328
+ "cpu": [
2329
+ "x64"
2330
+ ],
2331
+ "dev": true,
2332
+ "license": "MIT",
2333
+ "optional": true,
2334
+ "os": [
2335
+ "linux"
2336
+ ],
2337
+ "engines": {
2338
+ "node": ">= 10"
2339
+ }
2340
+ },
2341
+ "node_modules/@tailwindcss/oxide-wasm32-wasi": {
2342
+ "version": "4.1.17",
2343
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.17.tgz",
2344
+ "integrity": "sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==",
2345
+ "bundleDependencies": [
2346
+ "@napi-rs/wasm-runtime",
2347
+ "@emnapi/core",
2348
+ "@emnapi/runtime",
2349
+ "@tybys/wasm-util",
2350
+ "@emnapi/wasi-threads",
2351
+ "tslib"
2352
+ ],
2353
+ "cpu": [
2354
+ "wasm32"
2355
+ ],
2356
+ "dev": true,
2357
+ "license": "MIT",
2358
+ "optional": true,
2359
+ "dependencies": {
2360
+ "@emnapi/core": "^1.6.0",
2361
+ "@emnapi/runtime": "^1.6.0",
2362
+ "@emnapi/wasi-threads": "^1.1.0",
2363
+ "@napi-rs/wasm-runtime": "^1.0.7",
2364
+ "@tybys/wasm-util": "^0.10.1",
2365
+ "tslib": "^2.4.0"
2366
+ },
2367
+ "engines": {
2368
+ "node": ">=14.0.0"
2369
+ }
2370
+ },
2371
+ "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
2372
+ "version": "4.1.17",
2373
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.17.tgz",
2374
+ "integrity": "sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A==",
2375
+ "cpu": [
2376
+ "arm64"
2377
+ ],
2378
+ "dev": true,
2379
+ "license": "MIT",
2380
+ "optional": true,
2381
+ "os": [
2382
+ "win32"
2383
+ ],
2384
+ "engines": {
2385
+ "node": ">= 10"
2386
+ }
2387
+ },
2388
+ "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
2389
+ "version": "4.1.17",
2390
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.17.tgz",
2391
+ "integrity": "sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw==",
2392
+ "cpu": [
2393
+ "x64"
2394
+ ],
2395
+ "dev": true,
2396
+ "license": "MIT",
2397
+ "optional": true,
2398
+ "os": [
2399
+ "win32"
2400
+ ],
2401
+ "engines": {
2402
+ "node": ">= 10"
2403
+ }
2404
+ },
2405
+ "node_modules/@tailwindcss/vite": {
2406
+ "version": "4.1.17",
2407
+ "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.17.tgz",
2408
+ "integrity": "sha512-4+9w8ZHOiGnpcGI6z1TVVfWaX/koK7fKeSYF3qlYg2xpBtbteP2ddBxiarL+HVgfSJGeK5RIxRQmKm4rTJJAwA==",
2409
+ "dev": true,
2410
+ "license": "MIT",
2411
+ "dependencies": {
2412
+ "@tailwindcss/node": "4.1.17",
2413
+ "@tailwindcss/oxide": "4.1.17",
2414
+ "tailwindcss": "4.1.17"
2415
+ },
2416
+ "peerDependencies": {
2417
+ "vite": "^5.2.0 || ^6 || ^7"
2418
+ }
2419
+ },
2420
+ "node_modules/@types/babel__core": {
2421
+ "version": "7.20.5",
2422
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
2423
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
2424
+ "dev": true,
2425
+ "license": "MIT",
2426
+ "dependencies": {
2427
+ "@babel/parser": "^7.20.7",
2428
+ "@babel/types": "^7.20.7",
2429
+ "@types/babel__generator": "*",
2430
+ "@types/babel__template": "*",
2431
+ "@types/babel__traverse": "*"
2432
+ }
2433
+ },
2434
+ "node_modules/@types/babel__generator": {
2435
+ "version": "7.27.0",
2436
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
2437
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
2438
+ "dev": true,
2439
+ "license": "MIT",
2440
+ "dependencies": {
2441
+ "@babel/types": "^7.0.0"
2442
+ }
2443
+ },
2444
+ "node_modules/@types/babel__template": {
2445
+ "version": "7.4.4",
2446
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
2447
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
2448
+ "dev": true,
2449
+ "license": "MIT",
2450
+ "dependencies": {
2451
+ "@babel/parser": "^7.1.0",
2452
+ "@babel/types": "^7.0.0"
2453
+ }
2454
+ },
2455
+ "node_modules/@types/babel__traverse": {
2456
+ "version": "7.28.0",
2457
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
2458
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
2459
+ "dev": true,
2460
+ "license": "MIT",
2461
+ "dependencies": {
2462
+ "@babel/types": "^7.28.2"
2463
+ }
2464
+ },
2465
+ "node_modules/@types/estree": {
2466
+ "version": "1.0.8",
2467
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
2468
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
2469
+ "dev": true,
2470
+ "license": "MIT"
2471
+ },
2472
+ "node_modules/@types/json-schema": {
2473
+ "version": "7.0.15",
2474
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
2475
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
2476
+ "dev": true,
2477
+ "license": "MIT"
2478
+ },
2479
+ "node_modules/@types/node": {
2480
+ "version": "24.10.1",
2481
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz",
2482
+ "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
2483
+ "dev": true,
2484
+ "license": "MIT",
2485
+ "dependencies": {
2486
+ "undici-types": "~7.16.0"
2487
+ }
2488
+ },
2489
+ "node_modules/@types/react": {
2490
+ "version": "19.2.5",
2491
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.5.tgz",
2492
+ "integrity": "sha512-keKxkZMqnDicuvFoJbzrhbtdLSPhj/rZThDlKWCDbgXmUg0rEUFtRssDXKYmtXluZlIqiC5VqkCgRwzuyLHKHw==",
2493
+ "devOptional": true,
2494
+ "license": "MIT",
2495
+ "dependencies": {
2496
+ "csstype": "^3.0.2"
2497
+ }
2498
+ },
2499
+ "node_modules/@types/react-dom": {
2500
+ "version": "19.2.3",
2501
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
2502
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
2503
+ "devOptional": true,
2504
+ "license": "MIT",
2505
+ "peerDependencies": {
2506
+ "@types/react": "^19.2.0"
2507
+ }
2508
+ },
2509
+ "node_modules/@typescript-eslint/eslint-plugin": {
2510
+ "version": "8.46.4",
2511
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.4.tgz",
2512
+ "integrity": "sha512-R48VhmTJqplNyDxCyqqVkFSZIx1qX6PzwqgcXn1olLrzxcSBDlOsbtcnQuQhNtnNiJ4Xe5gREI1foajYaYU2Vg==",
2513
+ "dev": true,
2514
+ "license": "MIT",
2515
+ "dependencies": {
2516
+ "@eslint-community/regexpp": "^4.10.0",
2517
+ "@typescript-eslint/scope-manager": "8.46.4",
2518
+ "@typescript-eslint/type-utils": "8.46.4",
2519
+ "@typescript-eslint/utils": "8.46.4",
2520
+ "@typescript-eslint/visitor-keys": "8.46.4",
2521
+ "graphemer": "^1.4.0",
2522
+ "ignore": "^7.0.0",
2523
+ "natural-compare": "^1.4.0",
2524
+ "ts-api-utils": "^2.1.0"
2525
+ },
2526
+ "engines": {
2527
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2528
+ },
2529
+ "funding": {
2530
+ "type": "opencollective",
2531
+ "url": "https://opencollective.com/typescript-eslint"
2532
+ },
2533
+ "peerDependencies": {
2534
+ "@typescript-eslint/parser": "^8.46.4",
2535
+ "eslint": "^8.57.0 || ^9.0.0",
2536
+ "typescript": ">=4.8.4 <6.0.0"
2537
+ }
2538
+ },
2539
+ "node_modules/@typescript-eslint/parser": {
2540
+ "version": "8.46.4",
2541
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.4.tgz",
2542
+ "integrity": "sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==",
2543
+ "dev": true,
2544
+ "license": "MIT",
2545
+ "dependencies": {
2546
+ "@typescript-eslint/scope-manager": "8.46.4",
2547
+ "@typescript-eslint/types": "8.46.4",
2548
+ "@typescript-eslint/typescript-estree": "8.46.4",
2549
+ "@typescript-eslint/visitor-keys": "8.46.4",
2550
+ "debug": "^4.3.4"
2551
+ },
2552
+ "engines": {
2553
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2554
+ },
2555
+ "funding": {
2556
+ "type": "opencollective",
2557
+ "url": "https://opencollective.com/typescript-eslint"
2558
+ },
2559
+ "peerDependencies": {
2560
+ "eslint": "^8.57.0 || ^9.0.0",
2561
+ "typescript": ">=4.8.4 <6.0.0"
2562
+ }
2563
+ },
2564
+ "node_modules/@typescript-eslint/project-service": {
2565
+ "version": "8.46.4",
2566
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.4.tgz",
2567
+ "integrity": "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==",
2568
+ "dev": true,
2569
+ "license": "MIT",
2570
+ "dependencies": {
2571
+ "@typescript-eslint/tsconfig-utils": "^8.46.4",
2572
+ "@typescript-eslint/types": "^8.46.4",
2573
+ "debug": "^4.3.4"
2574
+ },
2575
+ "engines": {
2576
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2577
+ },
2578
+ "funding": {
2579
+ "type": "opencollective",
2580
+ "url": "https://opencollective.com/typescript-eslint"
2581
+ },
2582
+ "peerDependencies": {
2583
+ "typescript": ">=4.8.4 <6.0.0"
2584
+ }
2585
+ },
2586
+ "node_modules/@typescript-eslint/scope-manager": {
2587
+ "version": "8.46.4",
2588
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz",
2589
+ "integrity": "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==",
2590
+ "dev": true,
2591
+ "license": "MIT",
2592
+ "dependencies": {
2593
+ "@typescript-eslint/types": "8.46.4",
2594
+ "@typescript-eslint/visitor-keys": "8.46.4"
2595
+ },
2596
+ "engines": {
2597
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2598
+ },
2599
+ "funding": {
2600
+ "type": "opencollective",
2601
+ "url": "https://opencollective.com/typescript-eslint"
2602
+ }
2603
+ },
2604
+ "node_modules/@typescript-eslint/tsconfig-utils": {
2605
+ "version": "8.46.4",
2606
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz",
2607
+ "integrity": "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==",
2608
+ "dev": true,
2609
+ "license": "MIT",
2610
+ "engines": {
2611
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2612
+ },
2613
+ "funding": {
2614
+ "type": "opencollective",
2615
+ "url": "https://opencollective.com/typescript-eslint"
2616
+ },
2617
+ "peerDependencies": {
2618
+ "typescript": ">=4.8.4 <6.0.0"
2619
+ }
2620
+ },
2621
+ "node_modules/@typescript-eslint/type-utils": {
2622
+ "version": "8.46.4",
2623
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.4.tgz",
2624
+ "integrity": "sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ==",
2625
+ "dev": true,
2626
+ "license": "MIT",
2627
+ "dependencies": {
2628
+ "@typescript-eslint/types": "8.46.4",
2629
+ "@typescript-eslint/typescript-estree": "8.46.4",
2630
+ "@typescript-eslint/utils": "8.46.4",
2631
+ "debug": "^4.3.4",
2632
+ "ts-api-utils": "^2.1.0"
2633
+ },
2634
+ "engines": {
2635
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2636
+ },
2637
+ "funding": {
2638
+ "type": "opencollective",
2639
+ "url": "https://opencollective.com/typescript-eslint"
2640
+ },
2641
+ "peerDependencies": {
2642
+ "eslint": "^8.57.0 || ^9.0.0",
2643
+ "typescript": ">=4.8.4 <6.0.0"
2644
+ }
2645
+ },
2646
+ "node_modules/@typescript-eslint/types": {
2647
+ "version": "8.46.4",
2648
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz",
2649
+ "integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==",
2650
+ "dev": true,
2651
+ "license": "MIT",
2652
+ "engines": {
2653
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2654
+ },
2655
+ "funding": {
2656
+ "type": "opencollective",
2657
+ "url": "https://opencollective.com/typescript-eslint"
2658
+ }
2659
+ },
2660
+ "node_modules/@typescript-eslint/typescript-estree": {
2661
+ "version": "8.46.4",
2662
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz",
2663
+ "integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==",
2664
+ "dev": true,
2665
+ "license": "MIT",
2666
+ "dependencies": {
2667
+ "@typescript-eslint/project-service": "8.46.4",
2668
+ "@typescript-eslint/tsconfig-utils": "8.46.4",
2669
+ "@typescript-eslint/types": "8.46.4",
2670
+ "@typescript-eslint/visitor-keys": "8.46.4",
2671
+ "debug": "^4.3.4",
2672
+ "fast-glob": "^3.3.2",
2673
+ "is-glob": "^4.0.3",
2674
+ "minimatch": "^9.0.4",
2675
+ "semver": "^7.6.0",
2676
+ "ts-api-utils": "^2.1.0"
2677
+ },
2678
+ "engines": {
2679
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2680
+ },
2681
+ "funding": {
2682
+ "type": "opencollective",
2683
+ "url": "https://opencollective.com/typescript-eslint"
2684
+ },
2685
+ "peerDependencies": {
2686
+ "typescript": ">=4.8.4 <6.0.0"
2687
+ }
2688
+ },
2689
+ "node_modules/@typescript-eslint/utils": {
2690
+ "version": "8.46.4",
2691
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.4.tgz",
2692
+ "integrity": "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==",
2693
+ "dev": true,
2694
+ "license": "MIT",
2695
+ "dependencies": {
2696
+ "@eslint-community/eslint-utils": "^4.7.0",
2697
+ "@typescript-eslint/scope-manager": "8.46.4",
2698
+ "@typescript-eslint/types": "8.46.4",
2699
+ "@typescript-eslint/typescript-estree": "8.46.4"
2700
+ },
2701
+ "engines": {
2702
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2703
+ },
2704
+ "funding": {
2705
+ "type": "opencollective",
2706
+ "url": "https://opencollective.com/typescript-eslint"
2707
+ },
2708
+ "peerDependencies": {
2709
+ "eslint": "^8.57.0 || ^9.0.0",
2710
+ "typescript": ">=4.8.4 <6.0.0"
2711
+ }
2712
+ },
2713
+ "node_modules/@typescript-eslint/visitor-keys": {
2714
+ "version": "8.46.4",
2715
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz",
2716
+ "integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==",
2717
+ "dev": true,
2718
+ "license": "MIT",
2719
+ "dependencies": {
2720
+ "@typescript-eslint/types": "8.46.4",
2721
+ "eslint-visitor-keys": "^4.2.1"
2722
+ },
2723
+ "engines": {
2724
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2725
+ },
2726
+ "funding": {
2727
+ "type": "opencollective",
2728
+ "url": "https://opencollective.com/typescript-eslint"
2729
+ }
2730
+ },
2731
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
2732
+ "version": "4.2.1",
2733
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
2734
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
2735
+ "dev": true,
2736
+ "license": "Apache-2.0",
2737
+ "engines": {
2738
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2739
+ },
2740
+ "funding": {
2741
+ "url": "https://opencollective.com/eslint"
2742
+ }
2743
+ },
2744
+ "node_modules/@vitejs/plugin-react": {
2745
+ "version": "5.1.1",
2746
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.1.tgz",
2747
+ "integrity": "sha512-WQfkSw0QbQ5aJ2CHYw23ZGkqnRwqKHD/KYsMeTkZzPT4Jcf0DcBxBtwMJxnu6E7oxw5+JC6ZAiePgh28uJ1HBA==",
2748
+ "dev": true,
2749
+ "license": "MIT",
2750
+ "dependencies": {
2751
+ "@babel/core": "^7.28.5",
2752
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
2753
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
2754
+ "@rolldown/pluginutils": "1.0.0-beta.47",
2755
+ "@types/babel__core": "^7.20.5",
2756
+ "react-refresh": "^0.18.0"
2757
+ },
2758
+ "engines": {
2759
+ "node": "^20.19.0 || >=22.12.0"
2760
+ },
2761
+ "peerDependencies": {
2762
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
2763
+ }
2764
+ },
2765
+ "node_modules/acorn": {
2766
+ "version": "8.15.0",
2767
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
2768
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
2769
+ "dev": true,
2770
+ "license": "MIT",
2771
+ "bin": {
2772
+ "acorn": "bin/acorn"
2773
+ },
2774
+ "engines": {
2775
+ "node": ">=0.4.0"
2776
+ }
2777
+ },
2778
+ "node_modules/acorn-jsx": {
2779
+ "version": "5.3.2",
2780
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
2781
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
2782
+ "dev": true,
2783
+ "license": "MIT",
2784
+ "peerDependencies": {
2785
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
2786
+ }
2787
+ },
2788
+ "node_modules/ajv": {
2789
+ "version": "6.12.6",
2790
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
2791
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
2792
+ "dev": true,
2793
+ "license": "MIT",
2794
+ "dependencies": {
2795
+ "fast-deep-equal": "^3.1.1",
2796
+ "fast-json-stable-stringify": "^2.0.0",
2797
+ "json-schema-traverse": "^0.4.1",
2798
+ "uri-js": "^4.2.2"
2799
+ },
2800
+ "funding": {
2801
+ "type": "github",
2802
+ "url": "https://github.com/sponsors/epoberezkin"
2803
+ }
2804
+ },
2805
+ "node_modules/ansi-styles": {
2806
+ "version": "4.3.0",
2807
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
2808
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
2809
+ "dev": true,
2810
+ "license": "MIT",
2811
+ "dependencies": {
2812
+ "color-convert": "^2.0.1"
2813
+ },
2814
+ "engines": {
2815
+ "node": ">=8"
2816
+ },
2817
+ "funding": {
2818
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
2819
+ }
2820
+ },
2821
+ "node_modules/argparse": {
2822
+ "version": "2.0.1",
2823
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
2824
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
2825
+ "dev": true,
2826
+ "license": "Python-2.0"
2827
+ },
2828
+ "node_modules/aria-hidden": {
2829
+ "version": "1.2.6",
2830
+ "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
2831
+ "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
2832
+ "license": "MIT",
2833
+ "dependencies": {
2834
+ "tslib": "^2.0.0"
2835
+ },
2836
+ "engines": {
2837
+ "node": ">=10"
2838
+ }
2839
+ },
2840
+ "node_modules/balanced-match": {
2841
+ "version": "1.0.2",
2842
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
2843
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
2844
+ "dev": true,
2845
+ "license": "MIT"
2846
+ },
2847
+ "node_modules/baseline-browser-mapping": {
2848
+ "version": "2.8.28",
2849
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.28.tgz",
2850
+ "integrity": "sha512-gYjt7OIqdM0PcttNYP2aVrr2G0bMALkBaoehD4BuRGjAOtipg0b6wHg1yNL+s5zSnLZZrGHOw4IrND8CD+3oIQ==",
2851
+ "dev": true,
2852
+ "license": "Apache-2.0",
2853
+ "bin": {
2854
+ "baseline-browser-mapping": "dist/cli.js"
2855
+ }
2856
+ },
2857
+ "node_modules/brace-expansion": {
2858
+ "version": "2.0.2",
2859
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
2860
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
2861
+ "dev": true,
2862
+ "license": "MIT",
2863
+ "dependencies": {
2864
+ "balanced-match": "^1.0.0"
2865
+ }
2866
+ },
2867
+ "node_modules/braces": {
2868
+ "version": "3.0.3",
2869
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
2870
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
2871
+ "dev": true,
2872
+ "license": "MIT",
2873
+ "dependencies": {
2874
+ "fill-range": "^7.1.1"
2875
+ },
2876
+ "engines": {
2877
+ "node": ">=8"
2878
+ }
2879
+ },
2880
+ "node_modules/browserslist": {
2881
+ "version": "4.28.0",
2882
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz",
2883
+ "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==",
2884
+ "dev": true,
2885
+ "funding": [
2886
+ {
2887
+ "type": "opencollective",
2888
+ "url": "https://opencollective.com/browserslist"
2889
+ },
2890
+ {
2891
+ "type": "tidelift",
2892
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
2893
+ },
2894
+ {
2895
+ "type": "github",
2896
+ "url": "https://github.com/sponsors/ai"
2897
+ }
2898
+ ],
2899
+ "license": "MIT",
2900
+ "dependencies": {
2901
+ "baseline-browser-mapping": "^2.8.25",
2902
+ "caniuse-lite": "^1.0.30001754",
2903
+ "electron-to-chromium": "^1.5.249",
2904
+ "node-releases": "^2.0.27",
2905
+ "update-browserslist-db": "^1.1.4"
2906
+ },
2907
+ "bin": {
2908
+ "browserslist": "cli.js"
2909
+ },
2910
+ "engines": {
2911
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
2912
+ }
2913
+ },
2914
+ "node_modules/callsites": {
2915
+ "version": "3.1.0",
2916
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
2917
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
2918
+ "dev": true,
2919
+ "license": "MIT",
2920
+ "engines": {
2921
+ "node": ">=6"
2922
+ }
2923
+ },
2924
+ "node_modules/caniuse-lite": {
2925
+ "version": "1.0.30001754",
2926
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz",
2927
+ "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==",
2928
+ "dev": true,
2929
+ "funding": [
2930
+ {
2931
+ "type": "opencollective",
2932
+ "url": "https://opencollective.com/browserslist"
2933
+ },
2934
+ {
2935
+ "type": "tidelift",
2936
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
2937
+ },
2938
+ {
2939
+ "type": "github",
2940
+ "url": "https://github.com/sponsors/ai"
2941
+ }
2942
+ ],
2943
+ "license": "CC-BY-4.0"
2944
+ },
2945
+ "node_modules/chalk": {
2946
+ "version": "4.1.2",
2947
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
2948
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
2949
+ "dev": true,
2950
+ "license": "MIT",
2951
+ "dependencies": {
2952
+ "ansi-styles": "^4.1.0",
2953
+ "supports-color": "^7.1.0"
2954
+ },
2955
+ "engines": {
2956
+ "node": ">=10"
2957
+ },
2958
+ "funding": {
2959
+ "url": "https://github.com/chalk/chalk?sponsor=1"
2960
+ }
2961
+ },
2962
+ "node_modules/class-variance-authority": {
2963
+ "version": "0.7.1",
2964
+ "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
2965
+ "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
2966
+ "license": "Apache-2.0",
2967
+ "dependencies": {
2968
+ "clsx": "^2.1.1"
2969
+ },
2970
+ "funding": {
2971
+ "url": "https://polar.sh/cva"
2972
+ }
2973
+ },
2974
+ "node_modules/clsx": {
2975
+ "version": "2.1.1",
2976
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
2977
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
2978
+ "license": "MIT",
2979
+ "engines": {
2980
+ "node": ">=6"
2981
+ }
2982
+ },
2983
+ "node_modules/cmdk": {
2984
+ "version": "1.1.1",
2985
+ "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz",
2986
+ "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==",
2987
+ "license": "MIT",
2988
+ "dependencies": {
2989
+ "@radix-ui/react-compose-refs": "^1.1.1",
2990
+ "@radix-ui/react-dialog": "^1.1.6",
2991
+ "@radix-ui/react-id": "^1.1.0",
2992
+ "@radix-ui/react-primitive": "^2.0.2"
2993
+ },
2994
+ "peerDependencies": {
2995
+ "react": "^18 || ^19 || ^19.0.0-rc",
2996
+ "react-dom": "^18 || ^19 || ^19.0.0-rc"
2997
+ }
2998
+ },
2999
+ "node_modules/color-convert": {
3000
+ "version": "2.0.1",
3001
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
3002
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
3003
+ "dev": true,
3004
+ "license": "MIT",
3005
+ "dependencies": {
3006
+ "color-name": "~1.1.4"
3007
+ },
3008
+ "engines": {
3009
+ "node": ">=7.0.0"
3010
+ }
3011
+ },
3012
+ "node_modules/color-name": {
3013
+ "version": "1.1.4",
3014
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
3015
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
3016
+ "dev": true,
3017
+ "license": "MIT"
3018
+ },
3019
+ "node_modules/concat-map": {
3020
+ "version": "0.0.1",
3021
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
3022
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
3023
+ "dev": true,
3024
+ "license": "MIT"
3025
+ },
3026
+ "node_modules/convert-source-map": {
3027
+ "version": "2.0.0",
3028
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
3029
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
3030
+ "dev": true,
3031
+ "license": "MIT"
3032
+ },
3033
+ "node_modules/cross-spawn": {
3034
+ "version": "7.0.6",
3035
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
3036
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
3037
+ "dev": true,
3038
+ "license": "MIT",
3039
+ "dependencies": {
3040
+ "path-key": "^3.1.0",
3041
+ "shebang-command": "^2.0.0",
3042
+ "which": "^2.0.1"
3043
+ },
3044
+ "engines": {
3045
+ "node": ">= 8"
3046
+ }
3047
+ },
3048
+ "node_modules/csstype": {
3049
+ "version": "3.2.1",
3050
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.1.tgz",
3051
+ "integrity": "sha512-98XGutrXoh75MlgLihlNxAGbUuFQc7l1cqcnEZlLNKc0UrVdPndgmaDmYTDDh929VS/eqTZV0rozmhu2qqT1/g==",
3052
+ "devOptional": true,
3053
+ "license": "MIT"
3054
+ },
3055
+ "node_modules/debug": {
3056
+ "version": "4.4.3",
3057
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
3058
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
3059
+ "dev": true,
3060
+ "license": "MIT",
3061
+ "dependencies": {
3062
+ "ms": "^2.1.3"
3063
+ },
3064
+ "engines": {
3065
+ "node": ">=6.0"
3066
+ },
3067
+ "peerDependenciesMeta": {
3068
+ "supports-color": {
3069
+ "optional": true
3070
+ }
3071
+ }
3072
+ },
3073
+ "node_modules/deep-is": {
3074
+ "version": "0.1.4",
3075
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
3076
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
3077
+ "dev": true,
3078
+ "license": "MIT"
3079
+ },
3080
+ "node_modules/detect-libc": {
3081
+ "version": "2.1.2",
3082
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
3083
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
3084
+ "dev": true,
3085
+ "license": "Apache-2.0",
3086
+ "engines": {
3087
+ "node": ">=8"
3088
+ }
3089
+ },
3090
+ "node_modules/detect-node-es": {
3091
+ "version": "1.1.0",
3092
+ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
3093
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
3094
+ "license": "MIT"
3095
+ },
3096
+ "node_modules/electron-to-chromium": {
3097
+ "version": "1.5.254",
3098
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.254.tgz",
3099
+ "integrity": "sha512-DcUsWpVhv9svsKRxnSCZ86SjD+sp32SGidNB37KpqXJncp1mfUgKbHvBomE89WJDbfVKw1mdv5+ikrvd43r+Bg==",
3100
+ "dev": true,
3101
+ "license": "ISC"
3102
+ },
3103
+ "node_modules/enhanced-resolve": {
3104
+ "version": "5.18.3",
3105
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
3106
+ "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
3107
+ "dev": true,
3108
+ "license": "MIT",
3109
+ "dependencies": {
3110
+ "graceful-fs": "^4.2.4",
3111
+ "tapable": "^2.2.0"
3112
+ },
3113
+ "engines": {
3114
+ "node": ">=10.13.0"
3115
+ }
3116
+ },
3117
+ "node_modules/esbuild": {
3118
+ "version": "0.25.12",
3119
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
3120
+ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
3121
+ "dev": true,
3122
+ "hasInstallScript": true,
3123
+ "license": "MIT",
3124
+ "bin": {
3125
+ "esbuild": "bin/esbuild"
3126
+ },
3127
+ "engines": {
3128
+ "node": ">=18"
3129
+ },
3130
+ "optionalDependencies": {
3131
+ "@esbuild/aix-ppc64": "0.25.12",
3132
+ "@esbuild/android-arm": "0.25.12",
3133
+ "@esbuild/android-arm64": "0.25.12",
3134
+ "@esbuild/android-x64": "0.25.12",
3135
+ "@esbuild/darwin-arm64": "0.25.12",
3136
+ "@esbuild/darwin-x64": "0.25.12",
3137
+ "@esbuild/freebsd-arm64": "0.25.12",
3138
+ "@esbuild/freebsd-x64": "0.25.12",
3139
+ "@esbuild/linux-arm": "0.25.12",
3140
+ "@esbuild/linux-arm64": "0.25.12",
3141
+ "@esbuild/linux-ia32": "0.25.12",
3142
+ "@esbuild/linux-loong64": "0.25.12",
3143
+ "@esbuild/linux-mips64el": "0.25.12",
3144
+ "@esbuild/linux-ppc64": "0.25.12",
3145
+ "@esbuild/linux-riscv64": "0.25.12",
3146
+ "@esbuild/linux-s390x": "0.25.12",
3147
+ "@esbuild/linux-x64": "0.25.12",
3148
+ "@esbuild/netbsd-arm64": "0.25.12",
3149
+ "@esbuild/netbsd-x64": "0.25.12",
3150
+ "@esbuild/openbsd-arm64": "0.25.12",
3151
+ "@esbuild/openbsd-x64": "0.25.12",
3152
+ "@esbuild/openharmony-arm64": "0.25.12",
3153
+ "@esbuild/sunos-x64": "0.25.12",
3154
+ "@esbuild/win32-arm64": "0.25.12",
3155
+ "@esbuild/win32-ia32": "0.25.12",
3156
+ "@esbuild/win32-x64": "0.25.12"
3157
+ }
3158
+ },
3159
+ "node_modules/escalade": {
3160
+ "version": "3.2.0",
3161
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
3162
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
3163
+ "dev": true,
3164
+ "license": "MIT",
3165
+ "engines": {
3166
+ "node": ">=6"
3167
+ }
3168
+ },
3169
+ "node_modules/escape-string-regexp": {
3170
+ "version": "4.0.0",
3171
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
3172
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
3173
+ "dev": true,
3174
+ "license": "MIT",
3175
+ "engines": {
3176
+ "node": ">=10"
3177
+ },
3178
+ "funding": {
3179
+ "url": "https://github.com/sponsors/sindresorhus"
3180
+ }
3181
+ },
3182
+ "node_modules/eslint": {
3183
+ "version": "9.39.1",
3184
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz",
3185
+ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
3186
+ "dev": true,
3187
+ "license": "MIT",
3188
+ "dependencies": {
3189
+ "@eslint-community/eslint-utils": "^4.8.0",
3190
+ "@eslint-community/regexpp": "^4.12.1",
3191
+ "@eslint/config-array": "^0.21.1",
3192
+ "@eslint/config-helpers": "^0.4.2",
3193
+ "@eslint/core": "^0.17.0",
3194
+ "@eslint/eslintrc": "^3.3.1",
3195
+ "@eslint/js": "9.39.1",
3196
+ "@eslint/plugin-kit": "^0.4.1",
3197
+ "@humanfs/node": "^0.16.6",
3198
+ "@humanwhocodes/module-importer": "^1.0.1",
3199
+ "@humanwhocodes/retry": "^0.4.2",
3200
+ "@types/estree": "^1.0.6",
3201
+ "ajv": "^6.12.4",
3202
+ "chalk": "^4.0.0",
3203
+ "cross-spawn": "^7.0.6",
3204
+ "debug": "^4.3.2",
3205
+ "escape-string-regexp": "^4.0.0",
3206
+ "eslint-scope": "^8.4.0",
3207
+ "eslint-visitor-keys": "^4.2.1",
3208
+ "espree": "^10.4.0",
3209
+ "esquery": "^1.5.0",
3210
+ "esutils": "^2.0.2",
3211
+ "fast-deep-equal": "^3.1.3",
3212
+ "file-entry-cache": "^8.0.0",
3213
+ "find-up": "^5.0.0",
3214
+ "glob-parent": "^6.0.2",
3215
+ "ignore": "^5.2.0",
3216
+ "imurmurhash": "^0.1.4",
3217
+ "is-glob": "^4.0.0",
3218
+ "json-stable-stringify-without-jsonify": "^1.0.1",
3219
+ "lodash.merge": "^4.6.2",
3220
+ "minimatch": "^3.1.2",
3221
+ "natural-compare": "^1.4.0",
3222
+ "optionator": "^0.9.3"
3223
+ },
3224
+ "bin": {
3225
+ "eslint": "bin/eslint.js"
3226
+ },
3227
+ "engines": {
3228
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
3229
+ },
3230
+ "funding": {
3231
+ "url": "https://eslint.org/donate"
3232
+ },
3233
+ "peerDependencies": {
3234
+ "jiti": "*"
3235
+ },
3236
+ "peerDependenciesMeta": {
3237
+ "jiti": {
3238
+ "optional": true
3239
+ }
3240
+ }
3241
+ },
3242
+ "node_modules/eslint-plugin-react-hooks": {
3243
+ "version": "7.0.1",
3244
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz",
3245
+ "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==",
3246
+ "dev": true,
3247
+ "license": "MIT",
3248
+ "dependencies": {
3249
+ "@babel/core": "^7.24.4",
3250
+ "@babel/parser": "^7.24.4",
3251
+ "hermes-parser": "^0.25.1",
3252
+ "zod": "^3.25.0 || ^4.0.0",
3253
+ "zod-validation-error": "^3.5.0 || ^4.0.0"
3254
+ },
3255
+ "engines": {
3256
+ "node": ">=18"
3257
+ },
3258
+ "peerDependencies": {
3259
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
3260
+ }
3261
+ },
3262
+ "node_modules/eslint-plugin-react-refresh": {
3263
+ "version": "0.4.24",
3264
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.24.tgz",
3265
+ "integrity": "sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==",
3266
+ "dev": true,
3267
+ "license": "MIT",
3268
+ "peerDependencies": {
3269
+ "eslint": ">=8.40"
3270
+ }
3271
+ },
3272
+ "node_modules/eslint-scope": {
3273
+ "version": "8.4.0",
3274
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
3275
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
3276
+ "dev": true,
3277
+ "license": "BSD-2-Clause",
3278
+ "dependencies": {
3279
+ "esrecurse": "^4.3.0",
3280
+ "estraverse": "^5.2.0"
3281
+ },
3282
+ "engines": {
3283
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
3284
+ },
3285
+ "funding": {
3286
+ "url": "https://opencollective.com/eslint"
3287
+ }
3288
+ },
3289
+ "node_modules/eslint-visitor-keys": {
3290
+ "version": "3.4.3",
3291
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
3292
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
3293
+ "dev": true,
3294
+ "license": "Apache-2.0",
3295
+ "engines": {
3296
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
3297
+ },
3298
+ "funding": {
3299
+ "url": "https://opencollective.com/eslint"
3300
+ }
3301
+ },
3302
+ "node_modules/eslint/node_modules/brace-expansion": {
3303
+ "version": "1.1.12",
3304
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
3305
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
3306
+ "dev": true,
3307
+ "license": "MIT",
3308
+ "dependencies": {
3309
+ "balanced-match": "^1.0.0",
3310
+ "concat-map": "0.0.1"
3311
+ }
3312
+ },
3313
+ "node_modules/eslint/node_modules/eslint-visitor-keys": {
3314
+ "version": "4.2.1",
3315
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
3316
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
3317
+ "dev": true,
3318
+ "license": "Apache-2.0",
3319
+ "engines": {
3320
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
3321
+ },
3322
+ "funding": {
3323
+ "url": "https://opencollective.com/eslint"
3324
+ }
3325
+ },
3326
+ "node_modules/eslint/node_modules/ignore": {
3327
+ "version": "5.3.2",
3328
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
3329
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
3330
+ "dev": true,
3331
+ "license": "MIT",
3332
+ "engines": {
3333
+ "node": ">= 4"
3334
+ }
3335
+ },
3336
+ "node_modules/eslint/node_modules/minimatch": {
3337
+ "version": "3.1.2",
3338
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
3339
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
3340
+ "dev": true,
3341
+ "license": "ISC",
3342
+ "dependencies": {
3343
+ "brace-expansion": "^1.1.7"
3344
+ },
3345
+ "engines": {
3346
+ "node": "*"
3347
+ }
3348
+ },
3349
+ "node_modules/espree": {
3350
+ "version": "10.4.0",
3351
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
3352
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
3353
+ "dev": true,
3354
+ "license": "BSD-2-Clause",
3355
+ "dependencies": {
3356
+ "acorn": "^8.15.0",
3357
+ "acorn-jsx": "^5.3.2",
3358
+ "eslint-visitor-keys": "^4.2.1"
3359
+ },
3360
+ "engines": {
3361
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
3362
+ },
3363
+ "funding": {
3364
+ "url": "https://opencollective.com/eslint"
3365
+ }
3366
+ },
3367
+ "node_modules/espree/node_modules/eslint-visitor-keys": {
3368
+ "version": "4.2.1",
3369
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
3370
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
3371
+ "dev": true,
3372
+ "license": "Apache-2.0",
3373
+ "engines": {
3374
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
3375
+ },
3376
+ "funding": {
3377
+ "url": "https://opencollective.com/eslint"
3378
+ }
3379
+ },
3380
+ "node_modules/esquery": {
3381
+ "version": "1.6.0",
3382
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
3383
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
3384
+ "dev": true,
3385
+ "license": "BSD-3-Clause",
3386
+ "dependencies": {
3387
+ "estraverse": "^5.1.0"
3388
+ },
3389
+ "engines": {
3390
+ "node": ">=0.10"
3391
+ }
3392
+ },
3393
+ "node_modules/esrecurse": {
3394
+ "version": "4.3.0",
3395
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
3396
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
3397
+ "dev": true,
3398
+ "license": "BSD-2-Clause",
3399
+ "dependencies": {
3400
+ "estraverse": "^5.2.0"
3401
+ },
3402
+ "engines": {
3403
+ "node": ">=4.0"
3404
+ }
3405
+ },
3406
+ "node_modules/estraverse": {
3407
+ "version": "5.3.0",
3408
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
3409
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
3410
+ "dev": true,
3411
+ "license": "BSD-2-Clause",
3412
+ "engines": {
3413
+ "node": ">=4.0"
3414
+ }
3415
+ },
3416
+ "node_modules/esutils": {
3417
+ "version": "2.0.3",
3418
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
3419
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
3420
+ "dev": true,
3421
+ "license": "BSD-2-Clause",
3422
+ "engines": {
3423
+ "node": ">=0.10.0"
3424
+ }
3425
+ },
3426
+ "node_modules/fast-deep-equal": {
3427
+ "version": "3.1.3",
3428
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
3429
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
3430
+ "dev": true,
3431
+ "license": "MIT"
3432
+ },
3433
+ "node_modules/fast-glob": {
3434
+ "version": "3.3.3",
3435
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
3436
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
3437
+ "dev": true,
3438
+ "license": "MIT",
3439
+ "dependencies": {
3440
+ "@nodelib/fs.stat": "^2.0.2",
3441
+ "@nodelib/fs.walk": "^1.2.3",
3442
+ "glob-parent": "^5.1.2",
3443
+ "merge2": "^1.3.0",
3444
+ "micromatch": "^4.0.8"
3445
+ },
3446
+ "engines": {
3447
+ "node": ">=8.6.0"
3448
+ }
3449
+ },
3450
+ "node_modules/fast-glob/node_modules/glob-parent": {
3451
+ "version": "5.1.2",
3452
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
3453
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
3454
+ "dev": true,
3455
+ "license": "ISC",
3456
+ "dependencies": {
3457
+ "is-glob": "^4.0.1"
3458
+ },
3459
+ "engines": {
3460
+ "node": ">= 6"
3461
+ }
3462
+ },
3463
+ "node_modules/fast-json-stable-stringify": {
3464
+ "version": "2.1.0",
3465
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
3466
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
3467
+ "dev": true,
3468
+ "license": "MIT"
3469
+ },
3470
+ "node_modules/fast-levenshtein": {
3471
+ "version": "2.0.6",
3472
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
3473
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
3474
+ "dev": true,
3475
+ "license": "MIT"
3476
+ },
3477
+ "node_modules/fastq": {
3478
+ "version": "1.19.1",
3479
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
3480
+ "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
3481
+ "dev": true,
3482
+ "license": "ISC",
3483
+ "dependencies": {
3484
+ "reusify": "^1.0.4"
3485
+ }
3486
+ },
3487
+ "node_modules/file-entry-cache": {
3488
+ "version": "8.0.0",
3489
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
3490
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
3491
+ "dev": true,
3492
+ "license": "MIT",
3493
+ "dependencies": {
3494
+ "flat-cache": "^4.0.0"
3495
+ },
3496
+ "engines": {
3497
+ "node": ">=16.0.0"
3498
+ }
3499
+ },
3500
+ "node_modules/fill-range": {
3501
+ "version": "7.1.1",
3502
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
3503
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
3504
+ "dev": true,
3505
+ "license": "MIT",
3506
+ "dependencies": {
3507
+ "to-regex-range": "^5.0.1"
3508
+ },
3509
+ "engines": {
3510
+ "node": ">=8"
3511
+ }
3512
+ },
3513
+ "node_modules/find-up": {
3514
+ "version": "5.0.0",
3515
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
3516
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
3517
+ "dev": true,
3518
+ "license": "MIT",
3519
+ "dependencies": {
3520
+ "locate-path": "^6.0.0",
3521
+ "path-exists": "^4.0.0"
3522
+ },
3523
+ "engines": {
3524
+ "node": ">=10"
3525
+ },
3526
+ "funding": {
3527
+ "url": "https://github.com/sponsors/sindresorhus"
3528
+ }
3529
+ },
3530
+ "node_modules/flat-cache": {
3531
+ "version": "4.0.1",
3532
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
3533
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
3534
+ "dev": true,
3535
+ "license": "MIT",
3536
+ "dependencies": {
3537
+ "flatted": "^3.2.9",
3538
+ "keyv": "^4.5.4"
3539
+ },
3540
+ "engines": {
3541
+ "node": ">=16"
3542
+ }
3543
+ },
3544
+ "node_modules/flatted": {
3545
+ "version": "3.3.3",
3546
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
3547
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
3548
+ "dev": true,
3549
+ "license": "ISC"
3550
+ },
3551
+ "node_modules/fsevents": {
3552
+ "version": "2.3.3",
3553
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
3554
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
3555
+ "dev": true,
3556
+ "hasInstallScript": true,
3557
+ "license": "MIT",
3558
+ "optional": true,
3559
+ "os": [
3560
+ "darwin"
3561
+ ],
3562
+ "engines": {
3563
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
3564
+ }
3565
+ },
3566
+ "node_modules/gensync": {
3567
+ "version": "1.0.0-beta.2",
3568
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
3569
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
3570
+ "dev": true,
3571
+ "license": "MIT",
3572
+ "engines": {
3573
+ "node": ">=6.9.0"
3574
+ }
3575
+ },
3576
+ "node_modules/get-nonce": {
3577
+ "version": "1.0.1",
3578
+ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
3579
+ "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
3580
+ "license": "MIT",
3581
+ "engines": {
3582
+ "node": ">=6"
3583
+ }
3584
+ },
3585
+ "node_modules/glob-parent": {
3586
+ "version": "6.0.2",
3587
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
3588
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
3589
+ "dev": true,
3590
+ "license": "ISC",
3591
+ "dependencies": {
3592
+ "is-glob": "^4.0.3"
3593
+ },
3594
+ "engines": {
3595
+ "node": ">=10.13.0"
3596
+ }
3597
+ },
3598
+ "node_modules/globals": {
3599
+ "version": "14.0.0",
3600
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
3601
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
3602
+ "dev": true,
3603
+ "license": "MIT",
3604
+ "engines": {
3605
+ "node": ">=18"
3606
+ },
3607
+ "funding": {
3608
+ "url": "https://github.com/sponsors/sindresorhus"
3609
+ }
3610
+ },
3611
+ "node_modules/graceful-fs": {
3612
+ "version": "4.2.11",
3613
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
3614
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
3615
+ "dev": true,
3616
+ "license": "ISC"
3617
+ },
3618
+ "node_modules/graphemer": {
3619
+ "version": "1.4.0",
3620
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
3621
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
3622
+ "dev": true,
3623
+ "license": "MIT"
3624
+ },
3625
+ "node_modules/has-flag": {
3626
+ "version": "4.0.0",
3627
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
3628
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
3629
+ "dev": true,
3630
+ "license": "MIT",
3631
+ "engines": {
3632
+ "node": ">=8"
3633
+ }
3634
+ },
3635
+ "node_modules/hermes-estree": {
3636
+ "version": "0.25.1",
3637
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
3638
+ "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
3639
+ "dev": true,
3640
+ "license": "MIT"
3641
+ },
3642
+ "node_modules/hermes-parser": {
3643
+ "version": "0.25.1",
3644
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
3645
+ "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
3646
+ "dev": true,
3647
+ "license": "MIT",
3648
+ "dependencies": {
3649
+ "hermes-estree": "0.25.1"
3650
+ }
3651
+ },
3652
+ "node_modules/ignore": {
3653
+ "version": "7.0.5",
3654
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
3655
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
3656
+ "dev": true,
3657
+ "license": "MIT",
3658
+ "engines": {
3659
+ "node": ">= 4"
3660
+ }
3661
+ },
3662
+ "node_modules/import-fresh": {
3663
+ "version": "3.3.1",
3664
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
3665
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
3666
+ "dev": true,
3667
+ "license": "MIT",
3668
+ "dependencies": {
3669
+ "parent-module": "^1.0.0",
3670
+ "resolve-from": "^4.0.0"
3671
+ },
3672
+ "engines": {
3673
+ "node": ">=6"
3674
+ },
3675
+ "funding": {
3676
+ "url": "https://github.com/sponsors/sindresorhus"
3677
+ }
3678
+ },
3679
+ "node_modules/imurmurhash": {
3680
+ "version": "0.1.4",
3681
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
3682
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
3683
+ "dev": true,
3684
+ "license": "MIT",
3685
+ "engines": {
3686
+ "node": ">=0.8.19"
3687
+ }
3688
+ },
3689
+ "node_modules/is-extglob": {
3690
+ "version": "2.1.1",
3691
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
3692
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
3693
+ "dev": true,
3694
+ "license": "MIT",
3695
+ "engines": {
3696
+ "node": ">=0.10.0"
3697
+ }
3698
+ },
3699
+ "node_modules/is-glob": {
3700
+ "version": "4.0.3",
3701
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
3702
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
3703
+ "dev": true,
3704
+ "license": "MIT",
3705
+ "dependencies": {
3706
+ "is-extglob": "^2.1.1"
3707
+ },
3708
+ "engines": {
3709
+ "node": ">=0.10.0"
3710
+ }
3711
+ },
3712
+ "node_modules/is-number": {
3713
+ "version": "7.0.0",
3714
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
3715
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
3716
+ "dev": true,
3717
+ "license": "MIT",
3718
+ "engines": {
3719
+ "node": ">=0.12.0"
3720
+ }
3721
+ },
3722
+ "node_modules/isexe": {
3723
+ "version": "2.0.0",
3724
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
3725
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
3726
+ "dev": true,
3727
+ "license": "ISC"
3728
+ },
3729
+ "node_modules/jiti": {
3730
+ "version": "2.6.1",
3731
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
3732
+ "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
3733
+ "dev": true,
3734
+ "license": "MIT",
3735
+ "bin": {
3736
+ "jiti": "lib/jiti-cli.mjs"
3737
+ }
3738
+ },
3739
+ "node_modules/js-tokens": {
3740
+ "version": "4.0.0",
3741
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
3742
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
3743
+ "dev": true,
3744
+ "license": "MIT"
3745
+ },
3746
+ "node_modules/js-yaml": {
3747
+ "version": "4.1.1",
3748
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
3749
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
3750
+ "dev": true,
3751
+ "license": "MIT",
3752
+ "dependencies": {
3753
+ "argparse": "^2.0.1"
3754
+ },
3755
+ "bin": {
3756
+ "js-yaml": "bin/js-yaml.js"
3757
+ }
3758
+ },
3759
+ "node_modules/jsesc": {
3760
+ "version": "3.1.0",
3761
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
3762
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
3763
+ "dev": true,
3764
+ "license": "MIT",
3765
+ "bin": {
3766
+ "jsesc": "bin/jsesc"
3767
+ },
3768
+ "engines": {
3769
+ "node": ">=6"
3770
+ }
3771
+ },
3772
+ "node_modules/json-buffer": {
3773
+ "version": "3.0.1",
3774
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
3775
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
3776
+ "dev": true,
3777
+ "license": "MIT"
3778
+ },
3779
+ "node_modules/json-schema-traverse": {
3780
+ "version": "0.4.1",
3781
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
3782
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
3783
+ "dev": true,
3784
+ "license": "MIT"
3785
+ },
3786
+ "node_modules/json-stable-stringify-without-jsonify": {
3787
+ "version": "1.0.1",
3788
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
3789
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
3790
+ "dev": true,
3791
+ "license": "MIT"
3792
+ },
3793
+ "node_modules/json5": {
3794
+ "version": "2.2.3",
3795
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
3796
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
3797
+ "dev": true,
3798
+ "license": "MIT",
3799
+ "bin": {
3800
+ "json5": "lib/cli.js"
3801
+ },
3802
+ "engines": {
3803
+ "node": ">=6"
3804
+ }
3805
+ },
3806
+ "node_modules/keyv": {
3807
+ "version": "4.5.4",
3808
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
3809
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
3810
+ "dev": true,
3811
+ "license": "MIT",
3812
+ "dependencies": {
3813
+ "json-buffer": "3.0.1"
3814
+ }
3815
+ },
3816
+ "node_modules/levn": {
3817
+ "version": "0.4.1",
3818
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
3819
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
3820
+ "dev": true,
3821
+ "license": "MIT",
3822
+ "dependencies": {
3823
+ "prelude-ls": "^1.2.1",
3824
+ "type-check": "~0.4.0"
3825
+ },
3826
+ "engines": {
3827
+ "node": ">= 0.8.0"
3828
+ }
3829
+ },
3830
+ "node_modules/lightningcss": {
3831
+ "version": "1.30.2",
3832
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
3833
+ "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==",
3834
+ "dev": true,
3835
+ "license": "MPL-2.0",
3836
+ "dependencies": {
3837
+ "detect-libc": "^2.0.3"
3838
+ },
3839
+ "engines": {
3840
+ "node": ">= 12.0.0"
3841
+ },
3842
+ "funding": {
3843
+ "type": "opencollective",
3844
+ "url": "https://opencollective.com/parcel"
3845
+ },
3846
+ "optionalDependencies": {
3847
+ "lightningcss-android-arm64": "1.30.2",
3848
+ "lightningcss-darwin-arm64": "1.30.2",
3849
+ "lightningcss-darwin-x64": "1.30.2",
3850
+ "lightningcss-freebsd-x64": "1.30.2",
3851
+ "lightningcss-linux-arm-gnueabihf": "1.30.2",
3852
+ "lightningcss-linux-arm64-gnu": "1.30.2",
3853
+ "lightningcss-linux-arm64-musl": "1.30.2",
3854
+ "lightningcss-linux-x64-gnu": "1.30.2",
3855
+ "lightningcss-linux-x64-musl": "1.30.2",
3856
+ "lightningcss-win32-arm64-msvc": "1.30.2",
3857
+ "lightningcss-win32-x64-msvc": "1.30.2"
3858
+ }
3859
+ },
3860
+ "node_modules/lightningcss-android-arm64": {
3861
+ "version": "1.30.2",
3862
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz",
3863
+ "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==",
3864
+ "cpu": [
3865
+ "arm64"
3866
+ ],
3867
+ "dev": true,
3868
+ "license": "MPL-2.0",
3869
+ "optional": true,
3870
+ "os": [
3871
+ "android"
3872
+ ],
3873
+ "engines": {
3874
+ "node": ">= 12.0.0"
3875
+ },
3876
+ "funding": {
3877
+ "type": "opencollective",
3878
+ "url": "https://opencollective.com/parcel"
3879
+ }
3880
+ },
3881
+ "node_modules/lightningcss-darwin-arm64": {
3882
+ "version": "1.30.2",
3883
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz",
3884
+ "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==",
3885
+ "cpu": [
3886
+ "arm64"
3887
+ ],
3888
+ "dev": true,
3889
+ "license": "MPL-2.0",
3890
+ "optional": true,
3891
+ "os": [
3892
+ "darwin"
3893
+ ],
3894
+ "engines": {
3895
+ "node": ">= 12.0.0"
3896
+ },
3897
+ "funding": {
3898
+ "type": "opencollective",
3899
+ "url": "https://opencollective.com/parcel"
3900
+ }
3901
+ },
3902
+ "node_modules/lightningcss-darwin-x64": {
3903
+ "version": "1.30.2",
3904
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz",
3905
+ "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==",
3906
+ "cpu": [
3907
+ "x64"
3908
+ ],
3909
+ "dev": true,
3910
+ "license": "MPL-2.0",
3911
+ "optional": true,
3912
+ "os": [
3913
+ "darwin"
3914
+ ],
3915
+ "engines": {
3916
+ "node": ">= 12.0.0"
3917
+ },
3918
+ "funding": {
3919
+ "type": "opencollective",
3920
+ "url": "https://opencollective.com/parcel"
3921
+ }
3922
+ },
3923
+ "node_modules/lightningcss-freebsd-x64": {
3924
+ "version": "1.30.2",
3925
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz",
3926
+ "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==",
3927
+ "cpu": [
3928
+ "x64"
3929
+ ],
3930
+ "dev": true,
3931
+ "license": "MPL-2.0",
3932
+ "optional": true,
3933
+ "os": [
3934
+ "freebsd"
3935
+ ],
3936
+ "engines": {
3937
+ "node": ">= 12.0.0"
3938
+ },
3939
+ "funding": {
3940
+ "type": "opencollective",
3941
+ "url": "https://opencollective.com/parcel"
3942
+ }
3943
+ },
3944
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
3945
+ "version": "1.30.2",
3946
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz",
3947
+ "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==",
3948
+ "cpu": [
3949
+ "arm"
3950
+ ],
3951
+ "dev": true,
3952
+ "license": "MPL-2.0",
3953
+ "optional": true,
3954
+ "os": [
3955
+ "linux"
3956
+ ],
3957
+ "engines": {
3958
+ "node": ">= 12.0.0"
3959
+ },
3960
+ "funding": {
3961
+ "type": "opencollective",
3962
+ "url": "https://opencollective.com/parcel"
3963
+ }
3964
+ },
3965
+ "node_modules/lightningcss-linux-arm64-gnu": {
3966
+ "version": "1.30.2",
3967
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz",
3968
+ "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==",
3969
+ "cpu": [
3970
+ "arm64"
3971
+ ],
3972
+ "dev": true,
3973
+ "license": "MPL-2.0",
3974
+ "optional": true,
3975
+ "os": [
3976
+ "linux"
3977
+ ],
3978
+ "engines": {
3979
+ "node": ">= 12.0.0"
3980
+ },
3981
+ "funding": {
3982
+ "type": "opencollective",
3983
+ "url": "https://opencollective.com/parcel"
3984
+ }
3985
+ },
3986
+ "node_modules/lightningcss-linux-arm64-musl": {
3987
+ "version": "1.30.2",
3988
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz",
3989
+ "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==",
3990
+ "cpu": [
3991
+ "arm64"
3992
+ ],
3993
+ "dev": true,
3994
+ "license": "MPL-2.0",
3995
+ "optional": true,
3996
+ "os": [
3997
+ "linux"
3998
+ ],
3999
+ "engines": {
4000
+ "node": ">= 12.0.0"
4001
+ },
4002
+ "funding": {
4003
+ "type": "opencollective",
4004
+ "url": "https://opencollective.com/parcel"
4005
+ }
4006
+ },
4007
+ "node_modules/lightningcss-linux-x64-gnu": {
4008
+ "version": "1.30.2",
4009
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz",
4010
+ "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==",
4011
+ "cpu": [
4012
+ "x64"
4013
+ ],
4014
+ "dev": true,
4015
+ "license": "MPL-2.0",
4016
+ "optional": true,
4017
+ "os": [
4018
+ "linux"
4019
+ ],
4020
+ "engines": {
4021
+ "node": ">= 12.0.0"
4022
+ },
4023
+ "funding": {
4024
+ "type": "opencollective",
4025
+ "url": "https://opencollective.com/parcel"
4026
+ }
4027
+ },
4028
+ "node_modules/lightningcss-linux-x64-musl": {
4029
+ "version": "1.30.2",
4030
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz",
4031
+ "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==",
4032
+ "cpu": [
4033
+ "x64"
4034
+ ],
4035
+ "dev": true,
4036
+ "license": "MPL-2.0",
4037
+ "optional": true,
4038
+ "os": [
4039
+ "linux"
4040
+ ],
4041
+ "engines": {
4042
+ "node": ">= 12.0.0"
4043
+ },
4044
+ "funding": {
4045
+ "type": "opencollective",
4046
+ "url": "https://opencollective.com/parcel"
4047
+ }
4048
+ },
4049
+ "node_modules/lightningcss-win32-arm64-msvc": {
4050
+ "version": "1.30.2",
4051
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz",
4052
+ "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==",
4053
+ "cpu": [
4054
+ "arm64"
4055
+ ],
4056
+ "dev": true,
4057
+ "license": "MPL-2.0",
4058
+ "optional": true,
4059
+ "os": [
4060
+ "win32"
4061
+ ],
4062
+ "engines": {
4063
+ "node": ">= 12.0.0"
4064
+ },
4065
+ "funding": {
4066
+ "type": "opencollective",
4067
+ "url": "https://opencollective.com/parcel"
4068
+ }
4069
+ },
4070
+ "node_modules/lightningcss-win32-x64-msvc": {
4071
+ "version": "1.30.2",
4072
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz",
4073
+ "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==",
4074
+ "cpu": [
4075
+ "x64"
4076
+ ],
4077
+ "dev": true,
4078
+ "license": "MPL-2.0",
4079
+ "optional": true,
4080
+ "os": [
4081
+ "win32"
4082
+ ],
4083
+ "engines": {
4084
+ "node": ">= 12.0.0"
4085
+ },
4086
+ "funding": {
4087
+ "type": "opencollective",
4088
+ "url": "https://opencollective.com/parcel"
4089
+ }
4090
+ },
4091
+ "node_modules/locate-path": {
4092
+ "version": "6.0.0",
4093
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
4094
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
4095
+ "dev": true,
4096
+ "license": "MIT",
4097
+ "dependencies": {
4098
+ "p-locate": "^5.0.0"
4099
+ },
4100
+ "engines": {
4101
+ "node": ">=10"
4102
+ },
4103
+ "funding": {
4104
+ "url": "https://github.com/sponsors/sindresorhus"
4105
+ }
4106
+ },
4107
+ "node_modules/lodash.merge": {
4108
+ "version": "4.6.2",
4109
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
4110
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
4111
+ "dev": true,
4112
+ "license": "MIT"
4113
+ },
4114
+ "node_modules/lru-cache": {
4115
+ "version": "5.1.1",
4116
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
4117
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
4118
+ "dev": true,
4119
+ "license": "ISC",
4120
+ "dependencies": {
4121
+ "yallist": "^3.0.2"
4122
+ }
4123
+ },
4124
+ "node_modules/lucide-react": {
4125
+ "version": "0.553.0",
4126
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.553.0.tgz",
4127
+ "integrity": "sha512-BRgX5zrWmNy/lkVAe0dXBgd7XQdZ3HTf+Hwe3c9WK6dqgnj9h+hxV+MDncM88xDWlCq27+TKvHGE70ViODNILw==",
4128
+ "license": "ISC",
4129
+ "peerDependencies": {
4130
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
4131
+ }
4132
+ },
4133
+ "node_modules/magic-string": {
4134
+ "version": "0.30.21",
4135
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
4136
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
4137
+ "dev": true,
4138
+ "license": "MIT",
4139
+ "dependencies": {
4140
+ "@jridgewell/sourcemap-codec": "^1.5.5"
4141
+ }
4142
+ },
4143
+ "node_modules/merge2": {
4144
+ "version": "1.4.1",
4145
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
4146
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
4147
+ "dev": true,
4148
+ "license": "MIT",
4149
+ "engines": {
4150
+ "node": ">= 8"
4151
+ }
4152
+ },
4153
+ "node_modules/micromatch": {
4154
+ "version": "4.0.8",
4155
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
4156
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
4157
+ "dev": true,
4158
+ "license": "MIT",
4159
+ "dependencies": {
4160
+ "braces": "^3.0.3",
4161
+ "picomatch": "^2.3.1"
4162
+ },
4163
+ "engines": {
4164
+ "node": ">=8.6"
4165
+ }
4166
+ },
4167
+ "node_modules/minimatch": {
4168
+ "version": "9.0.5",
4169
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
4170
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
4171
+ "dev": true,
4172
+ "license": "ISC",
4173
+ "dependencies": {
4174
+ "brace-expansion": "^2.0.1"
4175
+ },
4176
+ "engines": {
4177
+ "node": ">=16 || 14 >=14.17"
4178
+ },
4179
+ "funding": {
4180
+ "url": "https://github.com/sponsors/isaacs"
4181
+ }
4182
+ },
4183
+ "node_modules/ms": {
4184
+ "version": "2.1.3",
4185
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
4186
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
4187
+ "dev": true,
4188
+ "license": "MIT"
4189
+ },
4190
+ "node_modules/nanoid": {
4191
+ "version": "3.3.11",
4192
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
4193
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
4194
+ "dev": true,
4195
+ "funding": [
4196
+ {
4197
+ "type": "github",
4198
+ "url": "https://github.com/sponsors/ai"
4199
+ }
4200
+ ],
4201
+ "license": "MIT",
4202
+ "bin": {
4203
+ "nanoid": "bin/nanoid.cjs"
4204
+ },
4205
+ "engines": {
4206
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
4207
+ }
4208
+ },
4209
+ "node_modules/natural-compare": {
4210
+ "version": "1.4.0",
4211
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
4212
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
4213
+ "dev": true,
4214
+ "license": "MIT"
4215
+ },
4216
+ "node_modules/node-releases": {
4217
+ "version": "2.0.27",
4218
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
4219
+ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
4220
+ "dev": true,
4221
+ "license": "MIT"
4222
+ },
4223
+ "node_modules/optionator": {
4224
+ "version": "0.9.4",
4225
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
4226
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
4227
+ "dev": true,
4228
+ "license": "MIT",
4229
+ "dependencies": {
4230
+ "deep-is": "^0.1.3",
4231
+ "fast-levenshtein": "^2.0.6",
4232
+ "levn": "^0.4.1",
4233
+ "prelude-ls": "^1.2.1",
4234
+ "type-check": "^0.4.0",
4235
+ "word-wrap": "^1.2.5"
4236
+ },
4237
+ "engines": {
4238
+ "node": ">= 0.8.0"
4239
+ }
4240
+ },
4241
+ "node_modules/p-limit": {
4242
+ "version": "3.1.0",
4243
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
4244
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
4245
+ "dev": true,
4246
+ "license": "MIT",
4247
+ "dependencies": {
4248
+ "yocto-queue": "^0.1.0"
4249
+ },
4250
+ "engines": {
4251
+ "node": ">=10"
4252
+ },
4253
+ "funding": {
4254
+ "url": "https://github.com/sponsors/sindresorhus"
4255
+ }
4256
+ },
4257
+ "node_modules/p-locate": {
4258
+ "version": "5.0.0",
4259
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
4260
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
4261
+ "dev": true,
4262
+ "license": "MIT",
4263
+ "dependencies": {
4264
+ "p-limit": "^3.0.2"
4265
+ },
4266
+ "engines": {
4267
+ "node": ">=10"
4268
+ },
4269
+ "funding": {
4270
+ "url": "https://github.com/sponsors/sindresorhus"
4271
+ }
4272
+ },
4273
+ "node_modules/parent-module": {
4274
+ "version": "1.0.1",
4275
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
4276
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
4277
+ "dev": true,
4278
+ "license": "MIT",
4279
+ "dependencies": {
4280
+ "callsites": "^3.0.0"
4281
+ },
4282
+ "engines": {
4283
+ "node": ">=6"
4284
+ }
4285
+ },
4286
+ "node_modules/path-exists": {
4287
+ "version": "4.0.0",
4288
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
4289
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
4290
+ "dev": true,
4291
+ "license": "MIT",
4292
+ "engines": {
4293
+ "node": ">=8"
4294
+ }
4295
+ },
4296
+ "node_modules/path-key": {
4297
+ "version": "3.1.1",
4298
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
4299
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
4300
+ "dev": true,
4301
+ "license": "MIT",
4302
+ "engines": {
4303
+ "node": ">=8"
4304
+ }
4305
+ },
4306
+ "node_modules/picocolors": {
4307
+ "version": "1.1.1",
4308
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
4309
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
4310
+ "dev": true,
4311
+ "license": "ISC"
4312
+ },
4313
+ "node_modules/picomatch": {
4314
+ "version": "2.3.1",
4315
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
4316
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
4317
+ "dev": true,
4318
+ "license": "MIT",
4319
+ "engines": {
4320
+ "node": ">=8.6"
4321
+ },
4322
+ "funding": {
4323
+ "url": "https://github.com/sponsors/jonschlinkert"
4324
+ }
4325
+ },
4326
+ "node_modules/postcss": {
4327
+ "version": "8.5.6",
4328
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
4329
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
4330
+ "dev": true,
4331
+ "funding": [
4332
+ {
4333
+ "type": "opencollective",
4334
+ "url": "https://opencollective.com/postcss/"
4335
+ },
4336
+ {
4337
+ "type": "tidelift",
4338
+ "url": "https://tidelift.com/funding/github/npm/postcss"
4339
+ },
4340
+ {
4341
+ "type": "github",
4342
+ "url": "https://github.com/sponsors/ai"
4343
+ }
4344
+ ],
4345
+ "license": "MIT",
4346
+ "dependencies": {
4347
+ "nanoid": "^3.3.11",
4348
+ "picocolors": "^1.1.1",
4349
+ "source-map-js": "^1.2.1"
4350
+ },
4351
+ "engines": {
4352
+ "node": "^10 || ^12 || >=14"
4353
+ }
4354
+ },
4355
+ "node_modules/prelude-ls": {
4356
+ "version": "1.2.1",
4357
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
4358
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
4359
+ "dev": true,
4360
+ "license": "MIT",
4361
+ "engines": {
4362
+ "node": ">= 0.8.0"
4363
+ }
4364
+ },
4365
+ "node_modules/punycode": {
4366
+ "version": "2.3.1",
4367
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
4368
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
4369
+ "dev": true,
4370
+ "license": "MIT",
4371
+ "engines": {
4372
+ "node": ">=6"
4373
+ }
4374
+ },
4375
+ "node_modules/queue-microtask": {
4376
+ "version": "1.2.3",
4377
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
4378
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
4379
+ "dev": true,
4380
+ "funding": [
4381
+ {
4382
+ "type": "github",
4383
+ "url": "https://github.com/sponsors/feross"
4384
+ },
4385
+ {
4386
+ "type": "patreon",
4387
+ "url": "https://www.patreon.com/feross"
4388
+ },
4389
+ {
4390
+ "type": "consulting",
4391
+ "url": "https://feross.org/support"
4392
+ }
4393
+ ],
4394
+ "license": "MIT"
4395
+ },
4396
+ "node_modules/react": {
4397
+ "version": "19.2.0",
4398
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
4399
+ "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
4400
+ "license": "MIT",
4401
+ "engines": {
4402
+ "node": ">=0.10.0"
4403
+ }
4404
+ },
4405
+ "node_modules/react-dom": {
4406
+ "version": "19.2.0",
4407
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
4408
+ "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
4409
+ "license": "MIT",
4410
+ "dependencies": {
4411
+ "scheduler": "^0.27.0"
4412
+ },
4413
+ "peerDependencies": {
4414
+ "react": "^19.2.0"
4415
+ }
4416
+ },
4417
+ "node_modules/react-refresh": {
4418
+ "version": "0.18.0",
4419
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz",
4420
+ "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==",
4421
+ "dev": true,
4422
+ "license": "MIT",
4423
+ "engines": {
4424
+ "node": ">=0.10.0"
4425
+ }
4426
+ },
4427
+ "node_modules/react-remove-scroll": {
4428
+ "version": "2.7.1",
4429
+ "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz",
4430
+ "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==",
4431
+ "license": "MIT",
4432
+ "dependencies": {
4433
+ "react-remove-scroll-bar": "^2.3.7",
4434
+ "react-style-singleton": "^2.2.3",
4435
+ "tslib": "^2.1.0",
4436
+ "use-callback-ref": "^1.3.3",
4437
+ "use-sidecar": "^1.1.3"
4438
+ },
4439
+ "engines": {
4440
+ "node": ">=10"
4441
+ },
4442
+ "peerDependencies": {
4443
+ "@types/react": "*",
4444
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
4445
+ },
4446
+ "peerDependenciesMeta": {
4447
+ "@types/react": {
4448
+ "optional": true
4449
+ }
4450
+ }
4451
+ },
4452
+ "node_modules/react-remove-scroll-bar": {
4453
+ "version": "2.3.8",
4454
+ "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
4455
+ "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
4456
+ "license": "MIT",
4457
+ "dependencies": {
4458
+ "react-style-singleton": "^2.2.2",
4459
+ "tslib": "^2.0.0"
4460
+ },
4461
+ "engines": {
4462
+ "node": ">=10"
4463
+ },
4464
+ "peerDependencies": {
4465
+ "@types/react": "*",
4466
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
4467
+ },
4468
+ "peerDependenciesMeta": {
4469
+ "@types/react": {
4470
+ "optional": true
4471
+ }
4472
+ }
4473
+ },
4474
+ "node_modules/react-style-singleton": {
4475
+ "version": "2.2.3",
4476
+ "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
4477
+ "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
4478
+ "license": "MIT",
4479
+ "dependencies": {
4480
+ "get-nonce": "^1.0.0",
4481
+ "tslib": "^2.0.0"
4482
+ },
4483
+ "engines": {
4484
+ "node": ">=10"
4485
+ },
4486
+ "peerDependencies": {
4487
+ "@types/react": "*",
4488
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
4489
+ },
4490
+ "peerDependenciesMeta": {
4491
+ "@types/react": {
4492
+ "optional": true
4493
+ }
4494
+ }
4495
+ },
4496
+ "node_modules/resolve-from": {
4497
+ "version": "4.0.0",
4498
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
4499
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
4500
+ "dev": true,
4501
+ "license": "MIT",
4502
+ "engines": {
4503
+ "node": ">=4"
4504
+ }
4505
+ },
4506
+ "node_modules/reusify": {
4507
+ "version": "1.1.0",
4508
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
4509
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
4510
+ "dev": true,
4511
+ "license": "MIT",
4512
+ "engines": {
4513
+ "iojs": ">=1.0.0",
4514
+ "node": ">=0.10.0"
4515
+ }
4516
+ },
4517
+ "node_modules/rollup": {
4518
+ "version": "4.53.2",
4519
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz",
4520
+ "integrity": "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==",
4521
+ "dev": true,
4522
+ "license": "MIT",
4523
+ "dependencies": {
4524
+ "@types/estree": "1.0.8"
4525
+ },
4526
+ "bin": {
4527
+ "rollup": "dist/bin/rollup"
4528
+ },
4529
+ "engines": {
4530
+ "node": ">=18.0.0",
4531
+ "npm": ">=8.0.0"
4532
+ },
4533
+ "optionalDependencies": {
4534
+ "@rollup/rollup-android-arm-eabi": "4.53.2",
4535
+ "@rollup/rollup-android-arm64": "4.53.2",
4536
+ "@rollup/rollup-darwin-arm64": "4.53.2",
4537
+ "@rollup/rollup-darwin-x64": "4.53.2",
4538
+ "@rollup/rollup-freebsd-arm64": "4.53.2",
4539
+ "@rollup/rollup-freebsd-x64": "4.53.2",
4540
+ "@rollup/rollup-linux-arm-gnueabihf": "4.53.2",
4541
+ "@rollup/rollup-linux-arm-musleabihf": "4.53.2",
4542
+ "@rollup/rollup-linux-arm64-gnu": "4.53.2",
4543
+ "@rollup/rollup-linux-arm64-musl": "4.53.2",
4544
+ "@rollup/rollup-linux-loong64-gnu": "4.53.2",
4545
+ "@rollup/rollup-linux-ppc64-gnu": "4.53.2",
4546
+ "@rollup/rollup-linux-riscv64-gnu": "4.53.2",
4547
+ "@rollup/rollup-linux-riscv64-musl": "4.53.2",
4548
+ "@rollup/rollup-linux-s390x-gnu": "4.53.2",
4549
+ "@rollup/rollup-linux-x64-gnu": "4.53.2",
4550
+ "@rollup/rollup-linux-x64-musl": "4.53.2",
4551
+ "@rollup/rollup-openharmony-arm64": "4.53.2",
4552
+ "@rollup/rollup-win32-arm64-msvc": "4.53.2",
4553
+ "@rollup/rollup-win32-ia32-msvc": "4.53.2",
4554
+ "@rollup/rollup-win32-x64-gnu": "4.53.2",
4555
+ "@rollup/rollup-win32-x64-msvc": "4.53.2",
4556
+ "fsevents": "~2.3.2"
4557
+ }
4558
+ },
4559
+ "node_modules/run-parallel": {
4560
+ "version": "1.2.0",
4561
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
4562
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
4563
+ "dev": true,
4564
+ "funding": [
4565
+ {
4566
+ "type": "github",
4567
+ "url": "https://github.com/sponsors/feross"
4568
+ },
4569
+ {
4570
+ "type": "patreon",
4571
+ "url": "https://www.patreon.com/feross"
4572
+ },
4573
+ {
4574
+ "type": "consulting",
4575
+ "url": "https://feross.org/support"
4576
+ }
4577
+ ],
4578
+ "license": "MIT",
4579
+ "dependencies": {
4580
+ "queue-microtask": "^1.2.2"
4581
+ }
4582
+ },
4583
+ "node_modules/scheduler": {
4584
+ "version": "0.27.0",
4585
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
4586
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
4587
+ "license": "MIT"
4588
+ },
4589
+ "node_modules/semver": {
4590
+ "version": "7.7.3",
4591
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
4592
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
4593
+ "dev": true,
4594
+ "license": "ISC",
4595
+ "bin": {
4596
+ "semver": "bin/semver.js"
4597
+ },
4598
+ "engines": {
4599
+ "node": ">=10"
4600
+ }
4601
+ },
4602
+ "node_modules/shebang-command": {
4603
+ "version": "2.0.0",
4604
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
4605
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
4606
+ "dev": true,
4607
+ "license": "MIT",
4608
+ "dependencies": {
4609
+ "shebang-regex": "^3.0.0"
4610
+ },
4611
+ "engines": {
4612
+ "node": ">=8"
4613
+ }
4614
+ },
4615
+ "node_modules/shebang-regex": {
4616
+ "version": "3.0.0",
4617
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
4618
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
4619
+ "dev": true,
4620
+ "license": "MIT",
4621
+ "engines": {
4622
+ "node": ">=8"
4623
+ }
4624
+ },
4625
+ "node_modules/source-map-js": {
4626
+ "version": "1.2.1",
4627
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
4628
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
4629
+ "dev": true,
4630
+ "license": "BSD-3-Clause",
4631
+ "engines": {
4632
+ "node": ">=0.10.0"
4633
+ }
4634
+ },
4635
+ "node_modules/strip-json-comments": {
4636
+ "version": "3.1.1",
4637
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
4638
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
4639
+ "dev": true,
4640
+ "license": "MIT",
4641
+ "engines": {
4642
+ "node": ">=8"
4643
+ },
4644
+ "funding": {
4645
+ "url": "https://github.com/sponsors/sindresorhus"
4646
+ }
4647
+ },
4648
+ "node_modules/supports-color": {
4649
+ "version": "7.2.0",
4650
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
4651
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
4652
+ "dev": true,
4653
+ "license": "MIT",
4654
+ "dependencies": {
4655
+ "has-flag": "^4.0.0"
4656
+ },
4657
+ "engines": {
4658
+ "node": ">=8"
4659
+ }
4660
+ },
4661
+ "node_modules/tailwind-merge": {
4662
+ "version": "3.4.0",
4663
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz",
4664
+ "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==",
4665
+ "license": "MIT",
4666
+ "funding": {
4667
+ "type": "github",
4668
+ "url": "https://github.com/sponsors/dcastil"
4669
+ }
4670
+ },
4671
+ "node_modules/tailwindcss": {
4672
+ "version": "4.1.17",
4673
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.17.tgz",
4674
+ "integrity": "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==",
4675
+ "dev": true,
4676
+ "license": "MIT"
4677
+ },
4678
+ "node_modules/tapable": {
4679
+ "version": "2.3.0",
4680
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
4681
+ "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
4682
+ "dev": true,
4683
+ "license": "MIT",
4684
+ "engines": {
4685
+ "node": ">=6"
4686
+ },
4687
+ "funding": {
4688
+ "type": "opencollective",
4689
+ "url": "https://opencollective.com/webpack"
4690
+ }
4691
+ },
4692
+ "node_modules/tinyglobby": {
4693
+ "version": "0.2.15",
4694
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
4695
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
4696
+ "dev": true,
4697
+ "license": "MIT",
4698
+ "dependencies": {
4699
+ "fdir": "^6.5.0",
4700
+ "picomatch": "^4.0.3"
4701
+ },
4702
+ "engines": {
4703
+ "node": ">=12.0.0"
4704
+ },
4705
+ "funding": {
4706
+ "url": "https://github.com/sponsors/SuperchupuDev"
4707
+ }
4708
+ },
4709
+ "node_modules/tinyglobby/node_modules/fdir": {
4710
+ "version": "6.5.0",
4711
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
4712
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
4713
+ "dev": true,
4714
+ "license": "MIT",
4715
+ "engines": {
4716
+ "node": ">=12.0.0"
4717
+ },
4718
+ "peerDependencies": {
4719
+ "picomatch": "^3 || ^4"
4720
+ },
4721
+ "peerDependenciesMeta": {
4722
+ "picomatch": {
4723
+ "optional": true
4724
+ }
4725
+ }
4726
+ },
4727
+ "node_modules/tinyglobby/node_modules/picomatch": {
4728
+ "version": "4.0.3",
4729
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
4730
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
4731
+ "dev": true,
4732
+ "license": "MIT",
4733
+ "engines": {
4734
+ "node": ">=12"
4735
+ },
4736
+ "funding": {
4737
+ "url": "https://github.com/sponsors/jonschlinkert"
4738
+ }
4739
+ },
4740
+ "node_modules/to-regex-range": {
4741
+ "version": "5.0.1",
4742
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
4743
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
4744
+ "dev": true,
4745
+ "license": "MIT",
4746
+ "dependencies": {
4747
+ "is-number": "^7.0.0"
4748
+ },
4749
+ "engines": {
4750
+ "node": ">=8.0"
4751
+ }
4752
+ },
4753
+ "node_modules/ts-api-utils": {
4754
+ "version": "2.1.0",
4755
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
4756
+ "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
4757
+ "dev": true,
4758
+ "license": "MIT",
4759
+ "engines": {
4760
+ "node": ">=18.12"
4761
+ },
4762
+ "peerDependencies": {
4763
+ "typescript": ">=4.8.4"
4764
+ }
4765
+ },
4766
+ "node_modules/tslib": {
4767
+ "version": "2.8.1",
4768
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
4769
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
4770
+ "license": "0BSD"
4771
+ },
4772
+ "node_modules/type-check": {
4773
+ "version": "0.4.0",
4774
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
4775
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
4776
+ "dev": true,
4777
+ "license": "MIT",
4778
+ "dependencies": {
4779
+ "prelude-ls": "^1.2.1"
4780
+ },
4781
+ "engines": {
4782
+ "node": ">= 0.8.0"
4783
+ }
4784
+ },
4785
+ "node_modules/typescript": {
4786
+ "version": "5.9.3",
4787
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
4788
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
4789
+ "dev": true,
4790
+ "license": "Apache-2.0",
4791
+ "bin": {
4792
+ "tsc": "bin/tsc",
4793
+ "tsserver": "bin/tsserver"
4794
+ },
4795
+ "engines": {
4796
+ "node": ">=14.17"
4797
+ }
4798
+ },
4799
+ "node_modules/undici-types": {
4800
+ "version": "7.16.0",
4801
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
4802
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
4803
+ "dev": true,
4804
+ "license": "MIT"
4805
+ },
4806
+ "node_modules/update-browserslist-db": {
4807
+ "version": "1.1.4",
4808
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz",
4809
+ "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==",
4810
+ "dev": true,
4811
+ "funding": [
4812
+ {
4813
+ "type": "opencollective",
4814
+ "url": "https://opencollective.com/browserslist"
4815
+ },
4816
+ {
4817
+ "type": "tidelift",
4818
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
4819
+ },
4820
+ {
4821
+ "type": "github",
4822
+ "url": "https://github.com/sponsors/ai"
4823
+ }
4824
+ ],
4825
+ "license": "MIT",
4826
+ "dependencies": {
4827
+ "escalade": "^3.2.0",
4828
+ "picocolors": "^1.1.1"
4829
+ },
4830
+ "bin": {
4831
+ "update-browserslist-db": "cli.js"
4832
+ },
4833
+ "peerDependencies": {
4834
+ "browserslist": ">= 4.21.0"
4835
+ }
4836
+ },
4837
+ "node_modules/uri-js": {
4838
+ "version": "4.4.1",
4839
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
4840
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
4841
+ "dev": true,
4842
+ "license": "BSD-2-Clause",
4843
+ "dependencies": {
4844
+ "punycode": "^2.1.0"
4845
+ }
4846
+ },
4847
+ "node_modules/use-callback-ref": {
4848
+ "version": "1.3.3",
4849
+ "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
4850
+ "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
4851
+ "license": "MIT",
4852
+ "dependencies": {
4853
+ "tslib": "^2.0.0"
4854
+ },
4855
+ "engines": {
4856
+ "node": ">=10"
4857
+ },
4858
+ "peerDependencies": {
4859
+ "@types/react": "*",
4860
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
4861
+ },
4862
+ "peerDependenciesMeta": {
4863
+ "@types/react": {
4864
+ "optional": true
4865
+ }
4866
+ }
4867
+ },
4868
+ "node_modules/use-sidecar": {
4869
+ "version": "1.1.3",
4870
+ "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
4871
+ "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
4872
+ "license": "MIT",
4873
+ "dependencies": {
4874
+ "detect-node-es": "^1.1.0",
4875
+ "tslib": "^2.0.0"
4876
+ },
4877
+ "engines": {
4878
+ "node": ">=10"
4879
+ },
4880
+ "peerDependencies": {
4881
+ "@types/react": "*",
4882
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
4883
+ },
4884
+ "peerDependenciesMeta": {
4885
+ "@types/react": {
4886
+ "optional": true
4887
+ }
4888
+ }
4889
+ },
4890
+ "node_modules/vite": {
4891
+ "version": "7.2.2",
4892
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.2.tgz",
4893
+ "integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
4894
+ "dev": true,
4895
+ "license": "MIT",
4896
+ "dependencies": {
4897
+ "esbuild": "^0.25.0",
4898
+ "fdir": "^6.5.0",
4899
+ "picomatch": "^4.0.3",
4900
+ "postcss": "^8.5.6",
4901
+ "rollup": "^4.43.0",
4902
+ "tinyglobby": "^0.2.15"
4903
+ },
4904
+ "bin": {
4905
+ "vite": "bin/vite.js"
4906
+ },
4907
+ "engines": {
4908
+ "node": "^20.19.0 || >=22.12.0"
4909
+ },
4910
+ "funding": {
4911
+ "url": "https://github.com/vitejs/vite?sponsor=1"
4912
+ },
4913
+ "optionalDependencies": {
4914
+ "fsevents": "~2.3.3"
4915
+ },
4916
+ "peerDependencies": {
4917
+ "@types/node": "^20.19.0 || >=22.12.0",
4918
+ "jiti": ">=1.21.0",
4919
+ "less": "^4.0.0",
4920
+ "lightningcss": "^1.21.0",
4921
+ "sass": "^1.70.0",
4922
+ "sass-embedded": "^1.70.0",
4923
+ "stylus": ">=0.54.8",
4924
+ "sugarss": "^5.0.0",
4925
+ "terser": "^5.16.0",
4926
+ "tsx": "^4.8.1",
4927
+ "yaml": "^2.4.2"
4928
+ },
4929
+ "peerDependenciesMeta": {
4930
+ "@types/node": {
4931
+ "optional": true
4932
+ },
4933
+ "jiti": {
4934
+ "optional": true
4935
+ },
4936
+ "less": {
4937
+ "optional": true
4938
+ },
4939
+ "lightningcss": {
4940
+ "optional": true
4941
+ },
4942
+ "sass": {
4943
+ "optional": true
4944
+ },
4945
+ "sass-embedded": {
4946
+ "optional": true
4947
+ },
4948
+ "stylus": {
4949
+ "optional": true
4950
+ },
4951
+ "sugarss": {
4952
+ "optional": true
4953
+ },
4954
+ "terser": {
4955
+ "optional": true
4956
+ },
4957
+ "tsx": {
4958
+ "optional": true
4959
+ },
4960
+ "yaml": {
4961
+ "optional": true
4962
+ }
4963
+ }
4964
+ },
4965
+ "node_modules/vite/node_modules/fdir": {
4966
+ "version": "6.5.0",
4967
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
4968
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
4969
+ "dev": true,
4970
+ "license": "MIT",
4971
+ "engines": {
4972
+ "node": ">=12.0.0"
4973
+ },
4974
+ "peerDependencies": {
4975
+ "picomatch": "^3 || ^4"
4976
+ },
4977
+ "peerDependenciesMeta": {
4978
+ "picomatch": {
4979
+ "optional": true
4980
+ }
4981
+ }
4982
+ },
4983
+ "node_modules/vite/node_modules/picomatch": {
4984
+ "version": "4.0.3",
4985
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
4986
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
4987
+ "dev": true,
4988
+ "license": "MIT",
4989
+ "engines": {
4990
+ "node": ">=12"
4991
+ },
4992
+ "funding": {
4993
+ "url": "https://github.com/sponsors/jonschlinkert"
4994
+ }
4995
+ },
4996
+ "node_modules/which": {
4997
+ "version": "2.0.2",
4998
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
4999
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
This file is too large to show in full.
cmd/relay-server/frontend/package.json
new
+42
@@ -0,0 +1,42 @@
1
+{
2
+ "name": "relay-server-frontend",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc && vite build",
9
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10
+ "preview": "vite preview",
11
+ "build:go": "cd ../../.. && CGO_ENABLED=0 go build -o bin/relay-server cmd/relay-server/*.go",
12
+ "serve": "npm run build && npm run build:go && STATIC_DIR=../../../dist ../../../bin/relay-server -port 4017"
13
+ },
14
+ "dependencies": {
15
+ "@radix-ui/react-dialog": "^1.1.15",
16
+ "@radix-ui/react-popover": "^1.1.15",
17
+ "@radix-ui/react-select": "^2.2.6",
18
+ "@radix-ui/react-slot": "^1.2.4",
19
+ "class-variance-authority": "^0.7.1",
20
+ "clsx": "^2.1.1",
21
+ "cmdk": "^1.1.1",
22
+ "lucide-react": "^0.553.0",
23
+ "react": "^19.2.0",
24
+ "react-dom": "^19.2.0",
25
+ "tailwind-merge": "^3.4.0"
26
+ },
27
+ "devDependencies": {
28
+ "@tailwindcss/vite": "^4.1.17",
29
+ "@types/node": "^24.10.1",
30
+ "@types/react": "^19.2.5",
31
+ "@types/react-dom": "^19.2.3",
32
+ "@typescript-eslint/eslint-plugin": "^8.46.4",
33
+ "@typescript-eslint/parser": "^8.46.4",
34
+ "@vitejs/plugin-react": "^5.1.1",
35
+ "eslint": "^9.39.1",
36
+ "eslint-plugin-react-hooks": "^7.0.1",
37
+ "eslint-plugin-react-refresh": "^0.4.24",
38
+ "tailwindcss": "^4.1.17",
39
+ "typescript": "^5.9.3",
40
+ "vite": "^7.2.2"
41
+ }
42
+}
cmd/relay-server/frontend/public/apple-touch-icon.png
Binary files /dev/null and b/cmd/relay-server/frontend/public/apple-touch-icon.png differ
cmd/relay-server/frontend/public/favicon-96x96.png
Binary files /dev/null and b/cmd/relay-server/frontend/public/favicon-96x96.png differ
cmd/relay-server/frontend/public/favicon.ico
Binary files /dev/null and b/cmd/relay-server/frontend/public/favicon.ico differ
cmd/relay-server/frontend/public/favicon.svg
new
+3
@@ -0,0 +1,3 @@
1
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="1554" height="2500"><svg xmlns="http://www.w3.org/2000/svg" width="1554" height="2500" viewBox="0 0 906.26 1457.543"><path fill="#17C0E9" d="M254.854 137.158c-34.46 84.407-88.363 149.39-110.934 245.675 90.926-187.569 308.397-483.654 554.729-348.685 135.487 74.216 194.878 270.78 206.058 467.566 21.924 385.996-190.977 853.604-467.585 943.057-174.879 56.543-307.375-86.447-364.527-198.115-176.498-344.82 2.041-910.077 182.259-1109.498zm198.13 7.918C202.61 280.257 4.622 968.542 207.322 1270.414c51.713 77.029 194.535 160.648 285.294 71.318-209.061 31.529-288.389-176.143-301.145-340.765 31.411 147.743 139.396 326.12 309.075 253.588 251.957-107.723 376.778-648.46 269.433-966.817 22.394 134.616 15.572 317.711-47.551 412.087 86.655-230.615 7.903-704.478-269.444-554.749z"></path></svg><style>@media (prefers-color-scheme: light) { :root { filter: none; } }
2
+@media (prefers-color-scheme: dark) { :root { filter: none; } }
3
+</style></svg>
\ No newline at end of file
cmd/relay-server/frontend/public/web-app-manifest-192x192.png
Binary files /dev/null and b/cmd/relay-server/frontend/public/web-app-manifest-192x192.png differ
cmd/relay-server/frontend/public/web-app-manifest-512x512.png
Binary files /dev/null and b/cmd/relay-server/frontend/public/web-app-manifest-512x512.png differ
cmd/relay-server/frontend/src/App.tsx
new
+219
@@ -0,0 +1,219 @@
1
+import { useState, useMemo } from "react";
2
+import { Header } from "./components/Header";
3
+import { SearchBar } from "./components/SearchBar";
4
+import { ServerCard } from "./components/ServerCard";
5
+import { Pagination } from "./components/Pagination";
6
+import { useSSRData } from "./hooks/useSSRData";
7
+import type { ServerData, Metadata } from "./hooks/useSSRData";
8
+
9
+const ITEMS_PER_PAGE = 6;
10
+
11
+// Helper function to convert SSR ServerData to frontend format
12
+function convertSSRDataToServers(ssrData: ServerData[]) {
13
+ return ssrData.map((row, index) => {
14
+ // Parse metadata JSON string
15
+ let metadata: Metadata = {
16
+ description: "",
17
+ tags: [],
18
+ thumbnail: "",
19
+ owner: "",
20
+ hide: false,
21
+ };
22
+
23
+ try {
24
+ if (row.Metadata) {
25
+ metadata = JSON.parse(row.Metadata);
26
+ }
27
+ } catch (err) {
28
+ console.error("[App] Failed to parse metadata:", err, row.Metadata);
29
+ }
30
+
31
+ // Get region from SSR data (GeoIP-detected region)
32
+ const region = row.Region || "unknown";
33
+
34
+ // Combine region tag with metadata tags
35
+ const metadataTags = Array.isArray(metadata.tags) ? metadata.tags : [];
36
+ const allTags =
37
+ region !== "unknown" ? [region, ...metadataTags] : metadataTags;
38
+
39
+ return {
40
+ id: index + 1,
41
+ name: row.Name || row.DNS || "(unnamed)",
42
+ description: metadata.description || "",
43
+ tags: allTags,
44
+ thumbnail: metadata.thumbnail || "",
45
+ owner: metadata.owner || "",
46
+ online: row.Connected,
47
+ dns: row.DNS || "",
48
+ link: row.Link,
49
+ region: region,
50
+ countryCode: row.CountryCode || "",
51
+ };
52
+ });
53
+}
54
+
55
+function App() {
56
+ const [currentPage, setCurrentPage] = useState(1);
57
+ const [searchQuery, setSearchQuery] = useState("");
58
+ const [region, setRegion] = useState("all");
59
+ const [status, setStatus] = useState("all");
60
+ const [sortBy, setSortBy] = useState("default");
61
+
62
+ // Get SSR data
63
+ const ssrData = useSSRData();
64
+
65
+ // Use SSR data if available, otherwise fall back to sample servers
66
+ const servers = useMemo(() => {
67
+ console.log("[App] SSR data length:", ssrData.length);
68
+ if (ssrData.length > 0) {
69
+ console.log("[App] Using SSR data");
70
+ const converted = convertSSRDataToServers(ssrData);
71
+ console.log("[App] Converted servers:", converted);
72
+ return converted;
73
+ }
74
+ console.log("[App] Using sample servers");
75
+ return [];
76
+ }, [ssrData]);
77
+
78
+ // Extract unique available countries from servers
79
+ const availableCountries = useMemo(() => {
80
+ const countryCodes = new Set<string>();
81
+ servers.forEach((server) => {
82
+ if (server.countryCode) {
83
+ countryCodes.add(server.countryCode);
84
+ }
85
+ });
86
+ return Array.from(countryCodes).sort();
87
+ }, [servers]);
88
+
89
+ // Filter and sort servers
90
+ const filteredServers = useMemo(() => {
91
+ let filtered = servers.filter((server) => {
92
+ // Search filter - searches name, description, and tags
93
+ const matchesSearch =
94
+ searchQuery === "" ||
95
+ server.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
96
+ server.description.toLowerCase().includes(searchQuery.toLowerCase()) ||
97
+ server.tags.some((tag) =>
98
+ tag.toLowerCase().includes(searchQuery.toLowerCase())
99
+ );
100
+
101
+ // Country filter (using country code)
102
+ const matchesRegion =
103
+ region === "all" ||
104
+ server.countryCode === region;
105
+
106
+ // Status filter
107
+ const matchesStatus =
108
+ status === "all" ||
109
+ (status === "online" && server.online) ||
110
+ (status === "offline" && !server.online);
111
+
112
+ return matchesSearch && matchesRegion && matchesStatus;
113
+ });
114
+
115
+ // Sort based on sortBy value
116
+ if (sortBy === "description") {
117
+ filtered = [...filtered].sort((a, b) =>
118
+ a.description.localeCompare(b.description)
119
+ );
120
+ } else if (sortBy === "tags") {
121
+ filtered = [...filtered].sort((a, b) => {
122
+ const aTag = a.tags[0] || "";
123
+ const bTag = b.tags[0] || "";
124
+ return aTag.localeCompare(bTag);
125
+ });
126
+ } else if (sortBy === "owner") {
127
+ filtered = [...filtered].sort((a, b) =>
128
+ a.owner.localeCompare(b.owner)
129
+ );
130
+ }
131
+
132
+ return filtered;
133
+ }, [servers, searchQuery, region, status, sortBy]);
134
+
135
+ // Pagination
136
+ const totalPages = Math.ceil(filteredServers.length / ITEMS_PER_PAGE);
137
+ const paginatedServers = useMemo(() => {
138
+ const startIndex = (currentPage - 1) * ITEMS_PER_PAGE;
139
+ return filteredServers.slice(startIndex, startIndex + ITEMS_PER_PAGE);
140
+ }, [filteredServers, currentPage]);
141
+
142
+ // Reset to page 1 when filters change
143
+ const handleSearchChange = (value: string) => {
144
+ setSearchQuery(value);
145
+ setCurrentPage(1);
146
+ };
147
+
148
+ const handleRegionChange = (value: string) => {
149
+ setRegion(value);
150
+ setCurrentPage(1);
151
+ };
152
+
153
+ const handleStatusChange = (value: string) => {
154
+ setStatus(value);
155
+ setCurrentPage(1);
156
+ };
157
+
158
+ const handleSortByChange = (value: string) => {
159
+ setSortBy(value);
160
+ setCurrentPage(1);
161
+ };
162
+
163
+ return (
164
+ <div className="relative flex h-auto min-h-screen w-full flex-col overflow-x-hidden">
165
+ <div className="layout-container flex h-full grow flex-col">
166
+ <div className="flex flex-1 justify-center py-5">
167
+ <div className="layout-content-container flex flex-col w-full max-w-6xl flex-1 px-4 md:px-8">
168
+ <Header />
169
+ <main className="flex-1 mt-6">
170
+ <SearchBar
171
+ searchQuery={searchQuery}
172
+ onSearchChange={handleSearchChange}
173
+ region={region}
174
+ onRegionChange={handleRegionChange}
175
+ status={status}
176
+ onStatusChange={handleStatusChange}
177
+ sortBy={sortBy}
178
+ onSortByChange={handleSortByChange}
179
+ availableCountries={availableCountries}
180
+ />
181
+ <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6 p-4 sm:p-6 mt-4">
182
+ {paginatedServers.length > 0 ? (
183
+ paginatedServers.map((server) => (
184
+ <ServerCard
185
+ key={server.id}
186
+ name={server.name}
187
+ description={server.description}
188
+ tags={server.tags}
189
+ thumbnail={server.thumbnail}
190
+ owner={server.owner}
191
+ online={server.online}
192
+ dns={server.dns}
193
+ serverUrl={server.link}
194
+ />
195
+ ))
196
+ ) : (
197
+ <div className="col-span-full text-center py-12">
198
+ <p className="text-text-muted text-lg">
199
+ No servers found matching your criteria
200
+ </p>
201
+ </div>
202
+ )}
203
+ </div>
204
+ {totalPages > 0 && (
205
+ <Pagination
206
+ currentPage={currentPage}
207
+ totalPages={totalPages}
208
+ onPageChange={setCurrentPage}
209
+ />
210
+ )}
211
+ </main>
212
+ </div>
213
+ </div>
214
+ </div>
215
+ </div>
216
+ );
217
+}
218
+
219
+export default App;
cmd/relay-server/frontend/src/components/Header.tsx
new
+46
@@ -0,0 +1,46 @@
1
+export function Header() {
2
+ return (
3
+ <header className="flex items-center justify-between whitespace-nowrap border-b border-solid border-border-dark px-4 sm:px-6 py-3">
4
+ <div className="flex items-center gap-4 text-white">
5
+ <div className="text-primary size-6">
6
+ <svg
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ width="24"
9
+ height="24"
10
+ viewBox="0 0 906.26 1457.543"
11
+ >
12
+ <path
13
+ fill="#17C0E9"
14
+ d="M254.854 137.158c-34.46 84.407-88.363 149.39-110.934 245.675 90.926-187.569 308.397-483.654 554.729-348.685 135.487 74.216 194.878 270.78 206.058 467.566 21.924 385.996-190.977 853.604-467.585 943.057-174.879 56.543-307.375-86.447-364.527-198.115-176.498-344.82 2.041-910.077 182.259-1109.498zm198.13 7.918C202.61 280.257 4.622 968.542 207.322 1270.414c51.713 77.029 194.535 160.648 285.294 71.318-209.061 31.529-288.389-176.143-301.145-340.765 31.411 147.743 139.396 326.12 309.075 253.588 251.957-107.723 376.778-648.46 269.433-966.817 22.394 134.616 15.572 317.711-47.551 412.087 86.655-230.615 7.903-704.478-269.444-554.749z"
15
+ ></path>
16
+ </svg>
17
+ </div>
18
+ <h2 className="text-white text-lg font-bold leading-tight tracking-[-0.015em]">
19
+ PORTAL
20
+ </h2>
21
+ </div>
22
+ <div className="flex items-center gap-3">
23
+ <a
24
+ href="https://github.com/gosuda/portal"
25
+ target="_blank"
26
+ rel="noopener noreferrer"
27
+ className="text-white hover:text-primary transition-colors"
28
+ aria-label="View source on GitHub"
29
+ >
30
+ <svg
31
+ height="32"
32
+ width="32"
33
+ viewBox="0 0 24 24"
34
+ fill="currentColor"
35
+ className="opacity-80 hover:opacity-100"
36
+ >
37
+ <path d="M12 1C5.923 1 1 5.923 1 12c0 4.867 3.149 8.979 7.521 10.436.55.096.756-.233.756-.522 0-.262-.013-1.128-.013-2.049-2.764.509-3.479-.674-3.699-1.292-.124-.317-.66-1.293-1.127-1.554-.385-.207-.936-.715-.014-.729.866-.014 1.485.797 1.691 1.128.99 1.663 2.571 1.196 3.204.907.096-.715.385-1.196.701-1.471-2.448-.275-5.005-1.224-5.005-5.432 0-1.196.426-2.186 1.128-2.956-.111-.275-.496-1.402.11-2.915 0 0 .921-.288 3.024 1.128a10.193 10.193 0 0 1 2.75-.371c.936 0 1.871.123 2.75.371 2.104-1.43 3.025-1.128 3.025-1.128.605 1.513.221 2.64.111 2.915.701.77 1.127 1.747 1.127 2.956 0 4.222-2.571 5.157-5.019 5.432.399.344.743 1.004.743 2.035 0 1.471-.014 2.654-.014 3.025 0 .289.206.632.756.522C19.851 20.979 23 16.854 23 12c0-6.077-4.922-11-11-11Z"></path>
38
+ </svg>
39
+ </a>
40
+ {/* <Button>
41
+ <span className="truncate">Add Your Server</span>
42
+ </Button> */}
43
+ </div>
44
+ </header>
45
+ );
46
+}
cmd/relay-server/frontend/src/components/Pagination.tsx
new
+35
@@ -0,0 +1,35 @@
1
+import { ChevronLeft, ChevronRight } from "lucide-react";
2
+
3
+interface PaginationProps {
4
+ currentPage: number;
5
+ totalPages: number;
6
+ onPageChange: (page: number) => void;
7
+}
8
+
9
+export function Pagination({
10
+ currentPage,
11
+ totalPages,
12
+ onPageChange,
13
+}: PaginationProps) {
14
+ return (
15
+ <div className="flex items-center justify-center gap-4 px-4 sm:px-6 py-8">
16
+ <button
17
+ onClick={() => onPageChange(currentPage - 1)}
18
+ disabled={currentPage === 1}
19
+ className="flex h-10 w-10 cursor-pointer items-center justify-center overflow-hidden rounded-full bg-[#233348] text-white hover:bg-[#2d3f58] transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
20
+ >
21
+ <ChevronLeft className="w-6 h-6" />
22
+ </button>
23
+ <span className="text-sm text-gray-400">
24
+ Page {currentPage} of {totalPages}
25
+ </span>
26
+ <button
27
+ onClick={() => onPageChange(currentPage + 1)}
28
+ disabled={currentPage === totalPages}
29
+ className="flex h-10 w-10 cursor-pointer items-center justify-center overflow-hidden rounded-full bg-[#233348] text-white hover:bg-[#2d3f58] transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
30
+ >
31
+ <ChevronRight className="w-6 h-6" />
32
+ </button>
33
+ </div>
34
+ );
35
+}
cmd/relay-server/frontend/src/components/SearchBar.tsx
new
+89
@@ -0,0 +1,89 @@
1
+import { Search } from "lucide-react";
2
+import { Input } from "./ui/input";
3
+import {
4
+ Select,
5
+ SelectContent,
6
+ SelectItem,
7
+ SelectTrigger,
8
+ SelectValue,
9
+} from "./ui/select";
10
+import { COUNTRY_NAMES } from "../lib/countries";
11
+
12
+interface SearchBarProps {
13
+ searchQuery: string;
14
+ onSearchChange: (value: string) => void;
15
+ region: string;
16
+ onRegionChange: (value: string) => void;
17
+ status: string;
18
+ onStatusChange: (value: string) => void;
19
+ sortBy: string;
20
+ onSortByChange: (value: string) => void;
21
+ availableCountries: string[];
22
+}
23
+
24
+export function SearchBar({
25
+ searchQuery,
26
+ onSearchChange,
27
+ region,
28
+ onRegionChange,
29
+ status,
30
+ onStatusChange,
31
+ sortBy,
32
+ onSortByChange,
33
+ availableCountries,
34
+}: SearchBarProps) {
35
+ return (
36
+ <div className="space-y-4 px-4 sm:px-6">
37
+ <label className="flex flex-col min-w-40 h-12 w-full">
38
+ <div className="flex w-full flex-1 items-stretch rounded-lg h-full">
39
+ <div className="text-[#92a9c9] flex border-none bg-[#233348] items-center justify-center pl-4 rounded-l-lg border-r-0">
40
+ <Search className="w-5 h-5" />
41
+ </div>
42
+ <Input
43
+ placeholder="Search by server name..."
44
+ value={searchQuery}
45
+ onChange={(e) => onSearchChange(e.target.value)}
46
+ />
47
+ </div>
48
+ </label>
49
+ <div className="flex flex-wrap gap-3">
50
+ <Select value={region} onValueChange={onRegionChange}>
51
+ <SelectTrigger className="w-[140px] h-8">
52
+ <SelectValue placeholder="Country" />
53
+ </SelectTrigger>
54
+ <SelectContent>
55
+ <SelectItem value="all">All Countries</SelectItem>
56
+ {availableCountries.map((countryCode) => (
57
+ <SelectItem key={countryCode} value={countryCode}>
58
+ {COUNTRY_NAMES[countryCode] || countryCode}
59
+ </SelectItem>
60
+ ))}
61
+ </SelectContent>
62
+ </Select>
63
+
64
+ <Select value={status} onValueChange={onStatusChange}>
65
+ <SelectTrigger className="w-[140px] h-8">
66
+ <SelectValue placeholder="Status" />
67
+ </SelectTrigger>
68
+ <SelectContent>
69
+ <SelectItem value="all">All Status</SelectItem>
70
+ <SelectItem value="online">Online</SelectItem>
71
+ <SelectItem value="offline">Offline</SelectItem>
72
+ </SelectContent>
73
+ </Select>
74
+
75
+ <Select value={sortBy} onValueChange={onSortByChange}>
76
+ <SelectTrigger className="w-[140px] h-8">
77
+ <SelectValue placeholder="Sort By" />
78
+ </SelectTrigger>
79
+ <SelectContent>
80
+ <SelectItem value="default">Default</SelectItem>
81
+ <SelectItem value="description">Description</SelectItem>
82
+ <SelectItem value="tags">Tags</SelectItem>
83
+ <SelectItem value="owner">Owner</SelectItem>
84
+ </SelectContent>
85
+ </Select>
86
+ </div>
87
+ </div>
88
+ );
89
+}
cmd/relay-server/frontend/src/components/ServerCard.tsx
new
+81
@@ -0,0 +1,81 @@
1
+import { Button } from "./ui/button";
2
+
3
+interface ServerCardProps {
4
+ name: string;
5
+ description: string;
6
+ tags: string[];
7
+ thumbnail: string;
8
+ owner: string;
9
+ online: boolean;
10
+ dns: string;
11
+ serverUrl: string;
12
+}
13
+
14
+export function ServerCard({
15
+ name,
16
+ description,
17
+ tags,
18
+ thumbnail,
19
+ owner,
20
+ online,
21
+ serverUrl,
22
+}: ServerCardProps) {
23
+ const defaultThumbnail =
24
+ "https://cdn.jsdelivr.net/gh/gosuda/portal@main/portal.jpg";
25
+
26
+ const goServer = () => {
27
+ window.location.href = serverUrl;
28
+ };
29
+ return (
30
+ <div className="flex flex-col gap-4 rounded-xl bg-card-dark p-4 shadow-sm hover:shadow-lg transition-shadow duration-300">
31
+ <div
32
+ className="w-full bg-center bg-no-repeat aspect-video bg-cover rounded-lg"
33
+ style={{ backgroundImage: `url(${thumbnail || defaultThumbnail})` }}
34
+ />
35
+ <div className="flex flex-1 flex-col justify-between gap-4">
36
+ <div className="flex flex-col gap-2">
37
+ <div className="flex items-center gap-2">
38
+ <div
39
+ className={`w-2.5 h-2.5 rounded-full ${
40
+ online ? "bg-green-status" : "bg-red-500"
41
+ }`}
42
+ />
43
+ <p
44
+ className={`text-sm font-medium leading-normal ${
45
+ online ? "text-green-status" : "text-red-500"
46
+ }`}
47
+ >
48
+ {online ? "Online" : "Offline"}
49
+ </p>
50
+ </div>
51
+ <p className="text-white text-lg font-bold leading-tight">{name}</p>
52
+ {description && (
53
+ <p className="text-text-muted text-sm font-normal leading-normal line-clamp-2">
54
+ {description}
55
+ </p>
56
+ )}
57
+ {tags && tags.length > 0 && (
58
+ <div className="flex flex-wrap gap-1.5 mt-1">
59
+ {tags.map((tag, index) => (
60
+ <span
61
+ key={index}
62
+ className="px-2 py-1 bg-border-dark text-primary text-xs font-medium rounded"
63
+ >
64
+ {tag}
65
+ </span>
66
+ ))}
67
+ </div>
68
+ )}
69
+ {owner && (
70
+ <p className="text-text-muted text-xs font-normal leading-normal">
71
+ by {owner}
72
+ </p>
73
+ )}
74
+ </div>
75
+ <Button variant="secondary" className="w-full" onClick={goServer}>
76
+ <span className="truncate">Connect</span>
77
+ </Button>
78
+ </div>
79
+ </div>
80
+ );
81
+}
cmd/relay-server/frontend/src/components/ui/button.tsx
new
+49
@@ -0,0 +1,49 @@
1
+import * as React from "react";
2
+import { Slot } from "@radix-ui/react-slot";
3
+import { cva, type VariantProps } from "class-variance-authority";
4
+import { cn } from "@/lib/utils";
5
+
6
+const buttonVariants = cva(
7
+ "inline-flex items-center justify-center overflow-hidden rounded-lg text-sm font-bold leading-normal tracking-[0.015em] transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-primary text-black hover:bg-primary/90",
12
+ secondary: "bg-border-dark text-white hover:bg-[#2d3f58]",
13
+ ghost: "hover:bg-[#2d3f58] text-white",
14
+ },
15
+ size: {
16
+ default: "h-10 px-4",
17
+ sm: "h-9 px-4",
18
+ lg: "h-11 px-8",
19
+ icon: "h-10 w-10",
20
+ },
21
+ },
22
+ defaultVariants: {
23
+ variant: "default",
24
+ size: "default",
25
+ },
26
+ }
27
+);
28
+
29
+export interface ButtonProps
30
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
31
+ VariantProps<typeof buttonVariants> {
32
+ asChild?: boolean;
33
+}
34
+
35
+const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
36
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
37
+ const Comp = asChild ? Slot : "button";
38
+ return (
39
+ <Comp
40
+ className={cn(buttonVariants({ variant, size, className }))}
41
+ ref={ref}
42
+ {...props}
43
+ />
44
+ );
45
+ }
46
+);
47
+Button.displayName = "Button";
48
+
49
+export { Button, buttonVariants };
cmd/relay-server/frontend/src/components/ui/input.tsx
new
+24
@@ -0,0 +1,24 @@
1
+import * as React from "react";
2
+import { cn } from "@/lib/utils";
3
+
4
+export interface InputProps
5
+ extends React.InputHTMLAttributes<HTMLInputElement> {}
6
+
7
+const Input = React.forwardRef<HTMLInputElement, InputProps>(
8
+ ({ className, type, ...props }, ref) => {
9
+ return (
10
+ <input
11
+ type={type}
12
+ className={cn(
13
+ "flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-r-lg text-white focus:outline-0 focus:ring-2 focus:ring-primary/50 border-none bg-border-dark h-full placeholder:text-text-muted px-4 pl-2 text-base font-normal leading-normal",
14
+ className
15
+ )}
16
+ ref={ref}
17
+ {...props}
18
+ />
19
+ );
20
+ }
21
+);
22
+Input.displayName = "Input";
23
+
24
+export { Input };
cmd/relay-server/frontend/src/components/ui/select.tsx
new
+159
@@ -0,0 +1,159 @@
1
+import * as React from "react";
2
+import * as SelectPrimitive from "@radix-ui/react-select";
3
+import { Check, ChevronDown, ChevronUp } from "lucide-react";
4
+import { cn } from "@/lib/utils";
5
+
6
+const Select = SelectPrimitive.Root;
7
+
8
+const SelectGroup = SelectPrimitive.Group;
9
+
10
+const SelectValue = SelectPrimitive.Value;
11
+
12
+const SelectTrigger = React.forwardRef<
13
+ React.ElementRef<typeof SelectPrimitive.Trigger>,
14
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
15
+>(({ className, children, ...props }, ref) => (
16
+ <SelectPrimitive.Trigger
17
+ ref={ref}
18
+ className={cn(
19
+ "flex h-9 w-full items-center justify-between whitespace-nowrap rounded-lg bg-[#233348] px-3 py-2 text-sm text-white shadow-sm ring-offset-background placeholder:text-[#92a9c9] focus:outline-none focus:ring-2 focus:ring-primary/50 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
20
+ className
21
+ )}
22
+ {...props}
23
+ >
24
+ {children}
25
+ <SelectPrimitive.Icon asChild>
26
+ <ChevronDown className="h-4 w-4 opacity-50" />
27
+ </SelectPrimitive.Icon>
28
+ </SelectPrimitive.Trigger>
29
+));
30
+SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
31
+
32
+const SelectScrollUpButton = React.forwardRef<
33
+ React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
34
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
35
+>(({ className, ...props }, ref) => (
36
+ <SelectPrimitive.ScrollUpButton
37
+ ref={ref}
38
+ className={cn(
39
+ "flex cursor-default items-center justify-center py-1",
40
+ className
41
+ )}
42
+ {...props}
43
+ >
44
+ <ChevronUp className="h-4 w-4" />
45
+ </SelectPrimitive.ScrollUpButton>
46
+));
47
+SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
48
+
49
+const SelectScrollDownButton = React.forwardRef<
50
+ React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
51
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
52
+>(({ className, ...props }, ref) => (
53
+ <SelectPrimitive.ScrollDownButton
54
+ ref={ref}
55
+ className={cn(
56
+ "flex cursor-default items-center justify-center py-1",
57
+ className
58
+ )}
59
+ {...props}
60
+ >
61
+ <ChevronDown className="h-4 w-4" />
62
+ </SelectPrimitive.ScrollDownButton>
63
+));
64
+SelectScrollDownButton.displayName =
65
+ SelectPrimitive.ScrollDownButton.displayName;
66
+
67
+const SelectContent = React.forwardRef<
68
+ React.ElementRef<typeof SelectPrimitive.Content>,
69
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
70
+>(({ className, children, position = "popper", ...props }, ref) => (
71
+ <SelectPrimitive.Portal>
72
+ <SelectPrimitive.Content
73
+ ref={ref}
74
+ className={cn(
75
+ "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-lg bg-[#192433] text-white shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
76
+ position === "popper" &&
77
+ "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
78
+ className
79
+ )}
80
+ position={position}
81
+ {...props}
82
+ >
83
+ <SelectScrollUpButton />
84
+ <SelectPrimitive.Viewport
85
+ className={cn(
86
+ "p-1",
87
+ position === "popper" &&
88
+ "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
89
+ )}
90
+ >
91
+ {children}
92
+ </SelectPrimitive.Viewport>
93
+ <SelectScrollDownButton />
94
+ </SelectPrimitive.Content>
95
+ </SelectPrimitive.Portal>
96
+));
97
+SelectContent.displayName = SelectPrimitive.Content.displayName;
98
+
99
+const SelectLabel = React.forwardRef<
100
+ React.ElementRef<typeof SelectPrimitive.Label>,
101
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
102
+>(({ className, ...props }, ref) => (
103
+ <SelectPrimitive.Label
104
+ ref={ref}
105
+ className={cn(
106
+ "px-2 py-1.5 text-sm font-semibold text-text-muted",
107
+ className
108
+ )}
109
+ {...props}
110
+ />
111
+));
112
+SelectLabel.displayName = SelectPrimitive.Label.displayName;
113
+
114
+const SelectItem = React.forwardRef<
115
+ React.ElementRef<typeof SelectPrimitive.Item>,
116
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
117
+>(({ className, children, ...props }, ref) => (
118
+ <SelectPrimitive.Item
119
+ ref={ref}
120
+ className={cn(
121
+ "relative flex w-full cursor-pointer select-none items-center rounded-md py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-[#233348] focus:text-white data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
122
+ className
123
+ )}
124
+ {...props}
125
+ >
126
+ <span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
127
+ <SelectPrimitive.ItemIndicator>
128
+ <Check className="h-4 w-4" />
129
+ </SelectPrimitive.ItemIndicator>
130
+ </span>
131
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
132
+ </SelectPrimitive.Item>
133
+));
134
+SelectItem.displayName = SelectPrimitive.Item.displayName;
135
+
136
+const SelectSeparator = React.forwardRef<
137
+ React.ElementRef<typeof SelectPrimitive.Separator>,
138
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
139
+>(({ className, ...props }, ref) => (
140
+ <SelectPrimitive.Separator
141
+ ref={ref}
142
+ className={cn("-mx-1 my-1 h-px bg-[#233348]", className)}
143
+ {...props}
144
+ />
145
+));
146
+SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
147
+
148
+export {
149
+ Select,
150
+ SelectGroup,
151
+ SelectValue,
152
+ SelectTrigger,
153
+ SelectContent,
154
+ SelectLabel,
155
+ SelectItem,
156
+ SelectSeparator,
157
+ SelectScrollUpButton,
158
+ SelectScrollDownButton,
159
+};
cmd/relay-server/frontend/src/hooks/useSSRData.ts
new
+62
@@ -0,0 +1,62 @@
1
+import { useState, useEffect } from "react";
2
+
3
+export interface Metadata {
4
+ description: string;
5
+ tags: string[];
6
+ thumbnail: string;
7
+ owner: string;
8
+ hide: boolean;
9
+}
10
+
11
+export interface ServerData {
12
+ Peer: string;
13
+ Name: string;
14
+ Kind: string;
15
+ Connected: boolean;
16
+ DNS: string;
17
+ LastSeen: string;
18
+ LastSeenISO: string;
19
+ TTL: string;
20
+ Link: string;
21
+ StaleRed: boolean;
22
+ Hide: boolean;
23
+ Metadata: string;
24
+ Region: string;
25
+ CountryCode: string;
26
+ City: string;
27
+}
28
+
29
+/**
30
+ * useSSRData hook reads server data injected by Go SSR
31
+ * The data is embedded in a <script id="__SSR_DATA__"> tag in the HTML
32
+ */
33
+export function useSSRData(): ServerData[] {
34
+ const [data, setData] = useState<ServerData[]>([]);
35
+
36
+ useEffect(() => {
37
+ // Try to read SSR data from the script tag
38
+ const ssrScript = document.getElementById("__SSR_DATA__");
39
+ console.log("[SSR] Script tag found:", !!ssrScript);
40
+
41
+ if (ssrScript && ssrScript.textContent) {
42
+ console.log(
43
+ "[SSR] Script content:",
44
+ ssrScript.textContent.substring(0, 200)
45
+ );
46
+ try {
47
+ const parsed = JSON.parse(ssrScript.textContent);
48
+ console.log("[SSR] Parsed data:", parsed);
49
+ console.log("[SSR] Is array:", Array.isArray(parsed));
50
+ console.log("[SSR] Length:", Array.isArray(parsed) ? parsed.length : 0);
51
+ setData(Array.isArray(parsed) ? parsed : []);
52
+ } catch (err) {
53
+ console.error("[SSR] Failed to parse SSR data:", err);
54
+ setData([]);
55
+ }
56
+ } else {
57
+ console.log("[SSR] No script tag or content found");
58
+ }
59
+ }, []);
60
+
61
+ return data;
62
+}
cmd/relay-server/frontend/src/index.css
new
+60
@@ -0,0 +1,60 @@
1
+@import url('https://fonts.googleapis.com/css2?family=Public+Sans:wght@400;500;700;900&display=swap');
2
+@import "tailwindcss";
3
+
4
+@theme {
5
+ /* ServerShare Custom Colors - Dark Mode Only */
6
+ --color-primary: #47cdff;
7
+ --color-background-dark: #0f1e23;
8
+ --color-green-status: #50e3c2;
9
+ --color-card-dark: #192433;
10
+ --color-border-dark: #233348;
11
+ --color-text-muted: #92a9c9;
12
+
13
+ /* Font families */
14
+ --font-family-display: "Public Sans", sans-serif;
15
+
16
+ /* Border radius */
17
+ --radius: 0.5rem;
18
+ --radius-lg: 0.75rem;
19
+ --radius-xl: 1rem;
20
+}
21
+
22
+@layer base {
23
+ :root {
24
+ /* Dark mode only - using ServerShare color palette */
25
+ --background: 197 56% 9%; /* #0f1e23 */
26
+ --foreground: 210 40% 98%; /* white text */
27
+ --card: 200 48% 12%; /* #192433 */
28
+ --card-foreground: 210 40% 98%;
29
+ --popover: 200 48% 12%;
30
+ --popover-foreground: 210 40% 98%;
31
+ --primary: 195 100% 64%; /* #47cdff */
32
+ --primary-foreground: 0 0% 0%;
33
+ --secondary: 200 34% 18%; /* #233348 */
34
+ --secondary-foreground: 210 40% 98%;
35
+ --muted: 200 34% 18%;
36
+ --muted-foreground: 207 39% 68%; /* #92a9c9 */
37
+ --accent: 200 34% 18%;
38
+ --accent-foreground: 210 40% 98%;
39
+ --destructive: 0 84.2% 60.2%;
40
+ --destructive-foreground: 210 40% 98%;
41
+ --border: 207 28% 21%; /* #233348 */
42
+ --input: 207 28% 21%;
43
+ --ring: 195 100% 64%; /* #47cdff */
44
+ }
45
+
46
+ * {
47
+ border-color: hsl(var(--border));
48
+ }
49
+
50
+ body {
51
+ background-color: var(--color-background-dark);
52
+ color: rgb(255 255 255);
53
+ font-family: var(--font-family-display);
54
+ }
55
+
56
+ /* Force dark mode always */
57
+ html {
58
+ color-scheme: dark;
59
+ }
60
+}
cmd/relay-server/frontend/src/lib/countries.ts
new
+199
@@ -0,0 +1,199 @@
1
+// ISO 3166-1 alpha-2 country code to country name mapping
2
+export const COUNTRY_NAMES: Record<string, string> = {
3
+ AF: "Afghanistan",
4
+ AL: "Albania",
5
+ DZ: "Algeria",
6
+ AD: "Andorra",
7
+ AO: "Angola",
8
+ AR: "Argentina",
9
+ AM: "Armenia",
10
+ AU: "Australia",
11
+ AT: "Austria",
12
+ AZ: "Azerbaijan",
13
+ BS: "Bahamas",
14
+ BH: "Bahrain",
15
+ BD: "Bangladesh",
16
+ BB: "Barbados",
17
+ BY: "Belarus",
18
+ BE: "Belgium",
19
+ BZ: "Belize",
20
+ BJ: "Benin",
21
+ BT: "Bhutan",
22
+ BO: "Bolivia",
23
+ BA: "Bosnia and Herzegovina",
24
+ BW: "Botswana",
25
+ BR: "Brazil",
26
+ BN: "Brunei",
27
+ BG: "Bulgaria",
28
+ BF: "Burkina Faso",
29
+ BI: "Burundi",
30
+ KH: "Cambodia",
31
+ CM: "Cameroon",
32
+ CA: "Canada",
33
+ CV: "Cape Verde",
34
+ CF: "Central African Republic",
35
+ TD: "Chad",
36
+ CL: "Chile",
37
+ CN: "China",
38
+ CO: "Colombia",
39
+ KM: "Comoros",
40
+ CG: "Congo",
41
+ CD: "Congo (DRC)",
42
+ CR: "Costa Rica",
43
+ HR: "Croatia",
44
+ CU: "Cuba",
45
+ CY: "Cyprus",
46
+ CZ: "Czech Republic",
47
+ DK: "Denmark",
48
+ DJ: "Djibouti",
49
+ DM: "Dominica",
50
+ DO: "Dominican Republic",
51
+ EC: "Ecuador",
52
+ EG: "Egypt",
53
+ SV: "El Salvador",
54
+ GQ: "Equatorial Guinea",
55
+ ER: "Eritrea",
56
+ EE: "Estonia",
57
+ ET: "Ethiopia",
58
+ FJ: "Fiji",
59
+ FI: "Finland",
60
+ FR: "France",
61
+ GA: "Gabon",
62
+ GM: "Gambia",
63
+ GE: "Georgia",
64
+ DE: "Germany",
65
+ GH: "Ghana",
66
+ GR: "Greece",
67
+ GD: "Grenada",
68
+ GT: "Guatemala",
69
+ GN: "Guinea",
70
+ GW: "Guinea-Bissau",
71
+ GY: "Guyana",
72
+ HT: "Haiti",
73
+ HN: "Honduras",
74
+ HK: "Hong Kong",
75
+ HU: "Hungary",
76
+ IS: "Iceland",
77
+ IN: "India",
78
+ ID: "Indonesia",
79
+ IR: "Iran",
80
+ IQ: "Iraq",
81
+ IE: "Ireland",
82
+ IL: "Israel",
83
+ IT: "Italy",
84
+ JM: "Jamaica",
85
+ JP: "Japan",
86
+ JO: "Jordan",
87
+ KZ: "Kazakhstan",
88
+ KE: "Kenya",
89
+ KI: "Kiribati",
90
+ KP: "North Korea",
91
+ KR: "South Korea",
92
+ KW: "Kuwait",
93
+ KG: "Kyrgyzstan",
94
+ LA: "Laos",
95
+ LV: "Latvia",
96
+ LB: "Lebanon",
97
+ LS: "Lesotho",
98
+ LR: "Liberia",
99
+ LY: "Libya",
100
+ LI: "Liechtenstein",
101
+ LT: "Lithuania",
102
+ LU: "Luxembourg",
103
+ MO: "Macau",
104
+ MK: "North Macedonia",
105
+ MG: "Madagascar",
106
+ MW: "Malawi",
107
+ MY: "Malaysia",
108
+ MV: "Maldives",
109
+ ML: "Mali",
110
+ MT: "Malta",
111
+ MH: "Marshall Islands",
112
+ MR: "Mauritania",
113
+ MU: "Mauritius",
114
+ MX: "Mexico",
115
+ FM: "Micronesia",
116
+ MD: "Moldova",
117
+ MC: "Monaco",
118
+ MN: "Mongolia",
119
+ ME: "Montenegro",
120
+ MA: "Morocco",
121
+ MZ: "Mozambique",
122
+ MM: "Myanmar",
123
+ NA: "Namibia",
124
+ NR: "Nauru",
125
+ NP: "Nepal",
126
+ NL: "Netherlands",
127
+ NZ: "New Zealand",
128
+ NI: "Nicaragua",
129
+ NE: "Niger",
130
+ NG: "Nigeria",
131
+ NO: "Norway",
132
+ OM: "Oman",
133
+ PK: "Pakistan",
134
+ PW: "Palau",
135
+ PS: "Palestine",
136
+ PA: "Panama",
137
+ PG: "Papua New Guinea",
138
+ PY: "Paraguay",
139
+ PE: "Peru",
140
+ PH: "Philippines",
141
+ PL: "Poland",
142
+ PT: "Portugal",
143
+ QA: "Qatar",
144
+ RO: "Romania",
145
+ RU: "Russia",
146
+ RW: "Rwanda",
147
+ KN: "Saint Kitts and Nevis",
148
+ LC: "Saint Lucia",
149
+ VC: "Saint Vincent",
150
+ WS: "Samoa",
151
+ SM: "San Marino",
152
+ ST: "Sao Tome and Principe",
153
+ SA: "Saudi Arabia",
154
+ SN: "Senegal",
155
+ RS: "Serbia",
156
+ SC: "Seychelles",
157
+ SL: "Sierra Leone",
158
+ SG: "Singapore",
159
+ SK: "Slovakia",
160
+ SI: "Slovenia",
161
+ SB: "Solomon Islands",
162
+ SO: "Somalia",
163
+ ZA: "South Africa",
164
+ SS: "South Sudan",
165
+ ES: "Spain",
166
+ LK: "Sri Lanka",
167
+ SD: "Sudan",
168
+ SR: "Suriname",
169
+ SZ: "Swaziland",
170
+ SE: "Sweden",
171
+ CH: "Switzerland",
172
+ SY: "Syria",
173
+ TW: "Taiwan",
174
+ TJ: "Tajikistan",
175
+ TZ: "Tanzania",
176
+ TH: "Thailand",
177
+ TL: "Timor-Leste",
178
+ TG: "Togo",
179
+ TO: "Tonga",
180
+ TT: "Trinidad and Tobago",
181
+ TN: "Tunisia",
182
+ TR: "Turkey",
183
+ TM: "Turkmenistan",
184
+ TV: "Tuvalu",
185
+ UG: "Uganda",
186
+ UA: "Ukraine",
187
+ AE: "United Arab Emirates",
188
+ GB: "United Kingdom",
189
+ US: "United States",
190
+ UY: "Uruguay",
191
+ UZ: "Uzbekistan",
192
+ VU: "Vanuatu",
193
+ VA: "Vatican City",
194
+ VE: "Venezuela",
195
+ VN: "Vietnam",
196
+ YE: "Yemen",
197
+ ZM: "Zambia",
198
+ ZW: "Zimbabwe",
199
+};
cmd/relay-server/frontend/src/lib/utils.ts
new
+6
@@ -0,0 +1,6 @@
1
+import { type ClassValue, clsx } from "clsx";
2
+import { twMerge } from "tailwind-merge";
3
+
4
+export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+}
cmd/relay-server/frontend/src/main.tsx
new
+10
@@ -0,0 +1,10 @@
1
+import React from "react";
2
+import ReactDOM from "react-dom/client";
3
+import App from "./App.tsx";
4
+import "./index.css";
5
+
6
+ReactDOM.createRoot(document.getElementById("root")!).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>
10
+);
cmd/relay-server/frontend/src/vite-env.d.ts
new
+1
@@ -0,0 +1 @@
1
+/// <reference types="vite/client" />
cmd/relay-server/frontend/tsconfig.json
new
+31
@@ -0,0 +1,31 @@
1
+{
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+
9
+ /* Bundler mode */
10
+ "moduleResolution": "bundler",
11
+ "allowImportingTsExtensions": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "noEmit": true,
15
+ "jsx": "react-jsx",
16
+
17
+ /* Linting */
18
+ "strict": true,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "noFallthroughCasesInSwitch": true,
22
+
23
+ /* Path aliases */
24
+ "baseUrl": ".",
25
+ "paths": {
26
+ "@/*": ["./src/*"]
27
+ }
28
+ },
29
+ "include": ["src"],
30
+ "references": [{ "path": "./tsconfig.node.json" }]
31
+}
cmd/relay-server/frontend/tsconfig.node.json
new
+10
@@ -0,0 +1,10 @@
1
+{
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "skipLibCheck": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "allowSyntheticDefaultImports": true
8
+ },
9
+ "include": ["vite.config.ts"]
10
+}
cmd/relay-server/frontend/vite.config.ts
new
+41
@@ -0,0 +1,41 @@
1
+import { defineConfig } from "vite";
2
+import react from "@vitejs/plugin-react";
3
+import tailwindcss from "@tailwindcss/vite";
4
+import { resolve } from "path";
5
+import { renameSync } from "fs";
6
+
7
+// https://vitejs.dev/config/
8
+export default defineConfig({
9
+ plugins: [
10
+ react(),
11
+ tailwindcss(),
12
+ {
13
+ name: "rename-index",
14
+ closeBundle() {
15
+ const appDir = resolve(process.cwd(), "../app");
16
+ const indexPath = resolve(appDir, "index.html");
17
+ const portalPath = resolve(appDir, "portal.html");
18
+ try {
19
+ renameSync(indexPath, portalPath);
20
+ console.log("✓ Renamed index.html to portal.html");
21
+ } catch (err) {
22
+ console.error("Failed to rename index.html:", err);
23
+ }
24
+ },
25
+ },
26
+ ],
27
+ resolve: {
28
+ alias: {
29
+ "@": resolve(process.cwd(), "./src"),
30
+ },
31
+ },
32
+ build: {
33
+ outDir: "../app",
34
+ emptyOutDir: false,
35
+ rollupOptions: {
36
+ output: {
37
+ manualChunks: undefined,
38
+ },
39
+ },
40
+ },
41
+});
cmd/relay-server/main.go
+2
-2
@@ -49,7 +49,7 @@ func main() {
49
var flagBootstrapsCSV string
50
flag.StringVar(&flagBootstrapsCSV, "bootstraps", defaultBootstraps, "bootstrap addresses (comma-separated)")
51
flag.StringVar(&flagALPN, "alpn", "http/1.1", "ALPN identifier for this service")
52
- flag.IntVar(&flagPort, "port", 4017, "admin UI and HTTP proxy port")
52
+ flag.IntVar(&flagPort, "port", 4017, "app UI and HTTP proxy port")
53
flag.StringVar(&flagPortalHost, "portal-host", defaultPortalHost, "portal host for frontend serving (env: PORTAL_HOST)")
54
flag.IntVar(&flagMaxLease, "max-lease", 0, "maximum active relayed connections per lease (0 = unlimited)")
55
flag.IntVar(&flagLeaseBPS, "lease-bps", 0, "default bytes-per-second limit per lease (0 = unlimited)")
@@ -125,7 +125,7 @@ func runServer() error {
125
serv.Start()
126
defer serv.Stop()
127
128
- // Admin UI + Relay + Static Frontend
128
+ // App UI + Relay + Static Frontend
129
httpSrv := serveHTTP(ctx, fmt.Sprintf(":%d", flagPort), serv, cred.ID(), flagBootstraps, stop)
130
131
<-ctx.Done()
cmd/relay-server/static/GeoLite2-Country.mmdb
Binary files /dev/null and b/cmd/relay-server/static/GeoLite2-Country.mmdb differ
cmd/relay-server/view.go
+187
-55
@@ -5,12 +5,14 @@ import (
5
"embed"
6
"encoding/json"
7
"fmt"
8
- "html/template"
8
+ "net"
9
"net/http"
10
"strings"
11
+ "sync"
12
"time"
13
14
"github.com/gorilla/websocket"
15
+ "github.com/oschwald/geoip2-golang"
16
"github.com/rs/zerolog/log"
17
18
"gosuda.org/portal/portal"
@@ -21,6 +23,16 @@ import (
23
//go:embed static
24
var assetsFS embed.FS
25
26
+//go:embed static/GeoLite2-Country.mmdb
27
+var geoipFS embed.FS
28
+
29
+// GeoIP database reader (global instance with lazy initialization)
30
+var (
31
+ geoipReader *geoip2.Reader
32
+ geoipReaderOnce sync.Once
33
+ geoipReaderErr error
34
+)
35
+
36
func serveAsset(mux *http.ServeMux, route, assetPath, contentType string) {
37
mux.HandleFunc(route, func(w http.ResponseWriter, r *http.Request) {
38
b, err := assetsFS.ReadFile(assetPath)
@@ -42,30 +54,27 @@ func serveHTTP(_ context.Context, addr string, serv *portal.RelayServer, nodeID
54
addr = ":0"
55
}
56
45
- // Parse template once per server instance (no global var)
46
- tmpl := template.Must(template.ParseFS(assetsFS, "static/index.html"))
57
+ // Create app UI mux
58
+ appMux := http.NewServeMux()
59
48
- // Create admin UI mux
49
- adminMux := http.NewServeMux()
60
+ // Serve embedded favicons (ico/png/svg) for portal UI
61
+ serveAsset(appMux, "/favicon.ico", "static/favicon/favicon.ico", "image/x-icon")
62
+ serveAsset(appMux, "/favicon.png", "static/favicon/favicon.png", "image/png")
63
+ serveAsset(appMux, "/favicon.svg", "static/favicon/favicon.svg", "image/svg+xml")
64
51
- // Serve embedded favicons (ico/png/svg) for admin UI
52
- serveAsset(adminMux, "/favicon.ico", "static/favicon/favicon.ico", "image/x-icon")
53
- serveAsset(adminMux, "/favicon.png", "static/favicon/favicon.png", "image/png")
54
- serveAsset(adminMux, "/favicon.svg", "static/favicon/favicon.svg", "image/svg+xml")
55
-
56
- // Static assets for admin UI (embedded files)
57
- adminMux.HandleFunc("/static/", func(w http.ResponseWriter, r *http.Request) {
65
+ // Portal app assets (JS, CSS, etc.) - served from /app/
66
+ appMux.HandleFunc("/app/", func(w http.ResponseWriter, r *http.Request) {
67
setCORSHeaders(w)
68
if r.Method == http.MethodOptions {
69
w.WriteHeader(http.StatusOK)
70
return
71
}
63
- path := strings.TrimPrefix(r.URL.Path, "/static/")
64
- serveAdminStatic(w, r, path)
72
+ path := strings.TrimPrefix(r.URL.Path, "/app/")
73
+ serveAppStatic(w, r, path, serv)
74
})
75
67
- // Portal frontend files (for unified caching)
68
- adminMux.HandleFunc("/frontend/", func(w http.ResponseWriter, r *http.Request) {
76
+ // Portal frontend files (for unified caching)
77
+ appMux.HandleFunc("/frontend/", func(w http.ResponseWriter, r *http.Request) {
78
setCORSHeaders(w)
79
if r.Method == http.MethodOptions {
80
w.WriteHeader(http.StatusOK)
@@ -75,14 +84,14 @@ func serveHTTP(_ context.Context, addr string, serv *portal.RelayServer, nodeID
84
85
// Special handling for manifest.json - generate dynamically
86
if path == "manifest.json" {
78
- serveDynamicManifest(w, r)
87
+ serveDynamicManifest(w)
88
return
89
}
90
91
servePortalStaticFile(w, r, path)
92
})
93
85
- adminMux.HandleFunc("/relay", func(w http.ResponseWriter, r *http.Request) {
94
+ appMux.HandleFunc("/relay", func(w http.ResponseWriter, r *http.Request) {
95
if r.Method != http.MethodGet {
96
w.Header().Set("Allow", http.MethodGet)
97
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
@@ -96,36 +105,21 @@ func serveHTTP(_ context.Context, addr string, serv *portal.RelayServer, nodeID
105
}
106
107
stream := &wsstream.WsStream{Conn: wsConn}
99
- if err := serv.HandleConnection(stream); err != nil {
108
+ if err := serv.HandleConnection(stream, r.RemoteAddr); err != nil {
109
log.Error().Err(err).Msg("[server] websocket relay connection error")
110
wsConn.Close()
111
return
112
}
113
})
114
106
- // Admin UI index page
107
- adminMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
108
- if r.URL.Path != "/" {
109
- http.NotFound(w, r)
110
- return
111
- }
112
-
113
- // Convert lease entries to rows for the admin page
114
- rows := convertLeaseEntriesToRows(serv)
115
-
116
- data := adminPageData{
117
- NodeID: nodeID,
118
- Bootstraps: bootstraps,
119
- Rows: rows,
120
- }
121
-
122
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
123
- if err := tmpl.Execute(w, data); err != nil {
124
- log.Error().Err(err).Msg("[server] error rendering admin index")
125
- }
115
+ // App UI index page - serve React frontend with SSR (delegates to serveAppStatic)
116
+ appMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
117
+ // serveAppStatic handles both "/" and 404 fallback with SSR
118
+ path := strings.TrimPrefix(r.URL.Path, "/")
119
+ serveAppStatic(w, r, path, serv)
120
})
121
128
- adminMux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
122
+ appMux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
123
w.WriteHeader(http.StatusOK)
124
w.Write([]byte("{\"status\":\"ok\"}"))
125
})
@@ -133,12 +127,12 @@ func serveHTTP(_ context.Context, addr string, serv *portal.RelayServer, nodeID
127
// Create portal frontend mux
128
portalMux := createPortalMux()
129
136
- // Top-level handler that routes based on host
130
+ // Top-level handler that routes based on host and path
131
topHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
132
if isPortalSubdomain(r.Host) {
133
portalMux.ServeHTTP(w, r)
134
} else {
141
- adminMux.ServeHTTP(w, r)
135
+ appMux.ServeHTTP(w, r)
136
}
137
})
138
@@ -170,23 +164,131 @@ type leaseRow struct {
164
Link string
165
StaleRed bool
166
Hide bool
173
- Description string
174
- Tags string
175
- Owner string
167
+ Metadata string
168
+ Region string
169
+ CountryCode string
170
}
171
178
-type adminPageData struct {
179
- NodeID string
180
- Bootstraps []string
181
- Rows []leaseRow
172
+// initGeoIP initializes the GeoIP database reader (lazy loaded)
173
+func initGeoIP() error {
174
+ geoipReaderOnce.Do(func() {
175
+ // Try to load from embedded FS first
176
+ data, err := geoipFS.ReadFile("static/GeoLite2-Country.mmdb")
177
+ if err == nil {
178
+ reader, err := geoip2.FromBytes(data)
179
+ if err == nil {
180
+ geoipReader = reader
181
+ log.Info().
182
+ Str("source", "embedded").
183
+ Int("size", len(data)).
184
+ Msg("GeoIP database loaded successfully from embedded FS")
185
+ return
186
+ }
187
+ log.Warn().Err(err).Msg("Failed to parse embedded GeoIP database")
188
+ } else {
189
+ log.Debug().Err(err).Msg("Embedded GeoIP database not found, trying file paths")
190
+ }
191
+ })
192
+
193
+ return geoipReaderErr
194
}
195
184
-// convertLeaseEntriesToRows converts LeaseEntry data from LeaseManager to leaseRow format for the admin page
196
+// getRegionFromIP extracts region information from an IP address
197
+func getRegionFromIP(ipStr string) (region, countryCode string) {
198
+ // Initialize GeoIP if needed
199
+ if err := initGeoIP(); err != nil {
200
+ return "unknown", ""
201
+ }
202
+
203
+ // Parse IP address
204
+ ip := net.ParseIP(ipStr)
205
+ if ip == nil {
206
+ return "unknown", ""
207
+ }
208
+
209
+ // Skip private/local IPs
210
+ if ip.IsLoopback() || ip.IsPrivate() {
211
+ log.Debug().Str("ip", ipStr).Msg("[GeoIP] Skipping local/private IP")
212
+ return "local", ""
213
+ }
214
+
215
+ // Lookup country record
216
+ record, err := geoipReader.Country(ip)
217
+ if err != nil {
218
+ log.Debug().Err(err).Str("ip", ipStr).Msg("GeoIP lookup failed")
219
+ return "unknown", ""
220
+ }
221
+
222
+ // Extract country code
223
+ countryCode = record.Country.IsoCode
224
+
225
+ // Map country code to region
226
+ // Based on common regional groupings used in gaming/CDN services
227
+ switch countryCode {
228
+ // North America
229
+ case "US", "CA", "MX", "GT", "HN", "SV", "NI", "CR", "PA", "BZ":
230
+ region = "us-east"
231
+
232
+ // South America
233
+ case "BR", "AR", "CL", "CO", "PE", "VE", "EC", "BO", "PY", "UY", "GY", "SR", "GF":
234
+ region = "south-america"
235
+
236
+ // Europe - West
237
+ case "GB", "IE", "PT", "ES", "FR", "BE", "NL", "LU":
238
+ region = "eu-west"
239
+
240
+ // Europe - Central/East
241
+ case "DE", "AT", "CH", "IT", "PL", "CZ", "SK", "HU", "RO", "BG", "SI", "HR", "BA", "RS", "ME", "AL", "MK", "GR", "CY":
242
+ region = "eu-central"
243
+
244
+ // Europe - North
245
+ case "SE", "NO", "DK", "FI", "IS", "EE", "LV", "LT":
246
+ region = "eu-west"
247
+
248
+ // Asia - East
249
+ case "JP", "KR", "CN", "TW", "HK", "MO":
250
+ region = "asia-pacific"
251
+
252
+ // Asia - Southeast
253
+ case "SG", "MY", "TH", "ID", "PH", "VN", "LA", "KH", "MM", "BN":
254
+ region = "asia-pacific"
255
+
256
+ // Asia - South
257
+ case "IN", "PK", "BD", "LK", "NP", "BT", "MV":
258
+ region = "asia-pacific"
259
+
260
+ // Oceania
261
+ case "AU", "NZ", "FJ", "PG", "NC", "PF", "SB", "VU", "WS", "TO":
262
+ region = "asia-pacific"
263
+
264
+ // Middle East
265
+ case "AE", "SA", "IL", "TR", "EG", "IQ", "IR", "JO", "LB", "SY", "YE", "OM", "KW", "BH", "QA":
266
+ region = "eu-central"
267
+
268
+ // Africa
269
+ case "ZA", "NG", "KE", "GH", "TZ", "UG", "ET", "MA", "DZ", "TN", "LY", "SD", "AO", "MZ", "ZW", "BW", "NA", "ZM", "MW", "MG":
270
+ region = "eu-west"
271
+
272
+ default:
273
+ region = "unknown"
274
+ }
275
+
276
+ log.Debug().
277
+ Str("ip", ipStr).
278
+ Str("region", region).
279
+ Str("country", countryCode).
280
+ Msg("[GeoIP] Region mapped successfully")
281
+
282
+ return region, countryCode
283
+}
284
+
285
+// convertLeaseEntriesToRows converts LeaseEntry data from LeaseManager to leaseRow format for the app page
286
func convertLeaseEntriesToRows(serv *portal.RelayServer) []leaseRow {
287
// Get all lease entries directly from the lease manager
288
leaseEntries := serv.GetAllLeaseEntries()
289
189
- var rows []leaseRow
290
+ // Initialize with empty slice instead of nil to avoid "null" in JSON
291
+ rows := []leaseRow{}
292
now := time.Now()
293
294
for _, leaseEntry := range leaseEntries {
@@ -285,6 +387,34 @@ func convertLeaseEntriesToRows(serv *portal.RelayServer) []leaseRow {
387
link = fmt.Sprintf("//%s.%s/", lease.Name, portalHost)
388
}
389
390
+ // Get GeoIP information from RemoteAddr
391
+ var region string
392
+ var countryCode string
393
+ if leaseEntry.RemoteAddr != "" {
394
+ // Extract IP from RemoteAddr (format: "ip:port")
395
+ ipStr := leaseEntry.RemoteAddr
396
+ if idx := strings.LastIndex(ipStr, ":"); idx != -1 {
397
+ ipStr = ipStr[:idx]
398
+ }
399
+ log.Info().
400
+ Str("lease_id", identityID).
401
+ Str("remote_addr", leaseEntry.RemoteAddr).
402
+ Str("extracted_ip", ipStr).
403
+ Msg("[GeoIP] Processing lease RemoteAddr")
404
+ region, countryCode = getRegionFromIP(ipStr)
405
+ log.Info().
406
+ Str("lease_id", identityID).
407
+ Str("region", region).
408
+ Str("country_code", countryCode).
409
+ Msg("[GeoIP] Region detected")
410
+ } else {
411
+ log.Info().
412
+ Str("lease_id", identityID).
413
+ Msg("[GeoIP] No RemoteAddr available for lease")
414
+ region = "unknown"
415
+ countryCode = ""
416
+ }
417
+
418
row := leaseRow{
419
Peer: identityID,
420
Name: name,
@@ -297,12 +427,14 @@ func convertLeaseEntriesToRows(serv *portal.RelayServer) []leaseRow {
427
Link: link,
428
StaleRed: !connected && since >= 15*time.Second,
429
Hide: meta.Hide,
300
- Description: strings.TrimSpace(meta.Description),
301
- Tags: strings.Join(meta.Tags, ", "),
302
- Owner: strings.TrimSpace(meta.Owner),
430
+ Metadata: lease.Metadata,
431
+ Region: region,
432
+ CountryCode: countryCode,
433
}
434
305
- rows = append(rows, row)
435
+ if row.Hide != true {
436
+ rows = append(rows, row)
437
+ }
438
}
439
440
return rows
go.mod
+2
@@ -5,6 +5,7 @@ go 1.25.3
5
require (
6
github.com/gorilla/websocket v1.5.3
7
github.com/hashicorp/yamux v0.1.2
8
+ github.com/oschwald/geoip2-golang v1.13.0
9
github.com/planetscale/vtprotobuf v0.6.0
10
github.com/rs/zerolog v1.34.0
11
github.com/stretchr/testify v1.9.0
@@ -19,6 +20,7 @@ require (
20
github.com/davecgh/go-spew v1.1.1 // indirect
21
github.com/mattn/go-colorable v0.1.14 // indirect
22
github.com/mattn/go-isatty v0.0.20 // indirect
23
+ github.com/oschwald/maxminddb-golang v1.13.0 // indirect
24
github.com/pmezard/go-difflib v1.0.0 // indirect
25
golang.org/x/sys v0.37.0 // indirect
26
golang.org/x/text v0.30.0 // indirect
go.sum
+4
@@ -15,6 +15,10 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
15
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
16
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
17
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
18
+github.com/oschwald/geoip2-golang v1.13.0 h1:Q44/Ldc703pasJeP5V9+aFSZFmBN7DKHbNsSFzQATJI=
19
+github.com/oschwald/geoip2-golang v1.13.0/go.mod h1:P9zG+54KPEFOliZ29i7SeYZ/GM6tfEL+rgSn03hYuUo=
20
+github.com/oschwald/maxminddb-golang v1.13.0 h1:R8xBorY71s84yO06NgTmQvqvTvlS/bnYZrrWX1MElnU=
21
+github.com/oschwald/maxminddb-golang v1.13.0/go.mod h1:BU0z8BfFVhi1LQaonTwwGQlsHUEu9pWNdMfmq4ztm0o=
22
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
23
github.com/planetscale/vtprotobuf v0.6.0 h1:nBeETjudeJ5ZgBHUz1fVHvbqUKnYOXNhsIEabROxmNA=
24
github.com/planetscale/vtprotobuf v0.6.0/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
portal/core/cryptoops/handshaker.go
+3
@@ -190,6 +190,9 @@ func (sc *SecureConnection) writeFragmentation(p []byte) (int, error) {
190
191
// Read reads and decrypts data from the underlying connection
192
func (sc *SecureConnection) Read(p []byte) (int, error) {
193
+ if sc == nil || sc.conn == nil {
194
+ return 0, errors.New("connection is nil")
195
+ }
196
if len(sc.readBuffer.B) > 0 {
197
n := copy(p, sc.readBuffer.B)
198
copy(sc.readBuffer.B[:len(sc.readBuffer.B)-n], sc.readBuffer.B[n:])
portal/handlers.go
+1
-1
@@ -65,7 +65,7 @@ func (g *RelayServer) handleLeaseUpdateRequest(ctx *StreamContext, packet *rdver
65
var resp rdverb.LeaseUpdateResponse
66
67
// Update lease in lease manager
68
- if g.leaseManager.UpdateLease(req.Lease, ctx.ConnectionID) {
68
+ if g.leaseManager.UpdateLease(req.Lease, ctx.ConnectionID, ctx.Connection.RemoteAddr) {
69
resp.Code = rdverb.ResponseCode_RESPONSE_CODE_ACCEPTED
70
71
// Register lease connection
portal/lease.go
+4
-2
@@ -13,7 +13,8 @@ type LeaseEntry struct {
13
Lease *rdverb.Lease
14
Expires time.Time
15
LastSeen time.Time
16
- ConnectionID int64 // Store the connection ID
16
+ ConnectionID int64 // Store the connection ID
17
+ RemoteAddr string // Store the remote IP address
18
}
19
20
type LeaseManager struct {
@@ -78,7 +79,7 @@ func (lm *LeaseManager) cleanupExpiredLeases() {
79
}
80
}
81
81
-func (lm *LeaseManager) UpdateLease(lease *rdverb.Lease, connectionID int64) bool {
82
+func (lm *LeaseManager) UpdateLease(lease *rdverb.Lease, connectionID int64, remoteAddr string) bool {
83
lm.leasesLock.Lock()
84
defer lm.leasesLock.Unlock()
85
@@ -128,6 +129,7 @@ func (lm *LeaseManager) UpdateLease(lease *rdverb.Lease, connectionID int64) boo
129
Expires: expires,
130
LastSeen: time.Now(),
131
ConnectionID: connectionID,
132
+ RemoteAddr: remoteAddr,
133
}
134
135
// Apply default BPS limit for this lease if configured and no explicit limit set
portal/lease_test.go
+10
-10
@@ -40,12 +40,12 @@ func TestLeaseManager_NameConflict(t *testing.T) {
40
}
41
42
// First lease should succeed
43
- if !lm.UpdateLease(lease1, 1) {
43
+ if !lm.UpdateLease(lease1, 1, "192.168.1.1:1234") {
44
t.Fatal("First lease registration should succeed")
45
}
46
47
// Second lease with same name should fail (name conflict)
48
- if lm.UpdateLease(lease2, 2) {
48
+ if lm.UpdateLease(lease2, 2, "192.168.1.2:1234") {
49
t.Fatal("Second lease registration should fail due to name conflict")
50
}
51
@@ -91,12 +91,12 @@ func TestLeaseManager_SameIdentityUpdate(t *testing.T) {
91
}
92
93
// First registration
94
- if !lm.UpdateLease(lease1, 1) {
94
+ if !lm.UpdateLease(lease1, 1, "192.168.1.1:1234") {
95
t.Fatal("First lease registration should succeed")
96
}
97
98
// Update with same identity should succeed (no conflict)
99
- if !lm.UpdateLease(lease2, 1) {
99
+ if !lm.UpdateLease(lease2, 1, "192.168.1.1:1234") {
100
t.Fatal("Updating own lease should succeed")
101
}
102
@@ -139,11 +139,11 @@ func TestLeaseManager_EmptyNameAllowed(t *testing.T) {
139
Expires: time.Now().Add(10 * time.Minute).Unix(),
140
}
141
142
- if !lm.UpdateLease(lease1, 1) {
142
+ if !lm.UpdateLease(lease1, 1, "192.168.1.1:1234") {
143
t.Fatal("First lease with empty name should succeed")
144
}
145
146
- if !lm.UpdateLease(lease2, 2) {
146
+ if !lm.UpdateLease(lease2, 2, "192.168.1.2:1234") {
147
t.Fatal("Second lease with empty name should succeed (empty names don't conflict)")
148
}
149
}
@@ -177,11 +177,11 @@ func TestLeaseManager_UnnamedAllowed(t *testing.T) {
177
Expires: time.Now().Add(10 * time.Minute).Unix(),
178
}
179
180
- if !lm.UpdateLease(lease1, 1) {
180
+ if !lm.UpdateLease(lease1, 1, "192.168.1.1:1234") {
181
t.Fatal("First lease with '(unnamed)' should succeed")
182
}
183
184
- if !lm.UpdateLease(lease2, 2) {
184
+ if !lm.UpdateLease(lease2, 2, "192.168.1.2:1234") {
185
t.Fatal("Second lease with '(unnamed)' should succeed (unnamed don't conflict)")
186
}
187
}
@@ -215,11 +215,11 @@ func TestLeaseManager_UnicodeNameConflict(t *testing.T) {
215
Expires: time.Now().Add(10 * time.Minute).Unix(),
216
}
217
218
- if !lm.UpdateLease(lease1, 1) {
218
+ if !lm.UpdateLease(lease1, 1, "192.168.1.1:1234") {
219
t.Fatal("First lease with Korean name should succeed")
220
}
221
222
- if lm.UpdateLease(lease2, 2) {
222
+ if lm.UpdateLease(lease2, 2, "192.168.1.2:1234") {
223
t.Fatal("Second lease with same Korean name should fail")
224
}
225
}
portal/relay.go
+8
-6
@@ -14,8 +14,9 @@ import (
14
)
15
16
type Connection struct {
17
- conn io.ReadWriteCloser
18
- sess *yamux.Session
17
+ conn io.ReadWriteCloser
18
+ sess *yamux.Session
19
+ RemoteAddr string
20
21
streams map[uint32]*yamux.Stream
22
streamsLock sync.Mutex
@@ -253,7 +254,7 @@ func (g *RelayServer) handleStream(stream *yamux.Stream, id int64, connection *C
254
}
255
}
256
256
-func (g *RelayServer) HandleConnection(conn io.ReadWriteCloser) error {
257
+func (g *RelayServer) HandleConnection(conn io.ReadWriteCloser, remoteAddr string) error {
258
log.Debug().Msg("[RelayServer] New connection received")
259
260
sess, err := yamux.Server(conn, _yamux_config)
@@ -266,9 +267,10 @@ func (g *RelayServer) HandleConnection(conn io.ReadWriteCloser) error {
267
g.connidCounter++
268
connID := g.connidCounter
269
connection := &Connection{
269
- conn: conn,
270
- sess: sess,
271
- streams: make(map[uint32]*yamux.Stream),
270
+ conn: conn,
271
+ sess: sess,
272
+ RemoteAddr: remoteAddr,
273
+ streams: make(map[uint32]*yamux.Stream),
274
}
275
g.connections[connID] = connection
276
g.connectionsLock.Unlock()