- {/* ── WiFi Tab ─────────────────────────────────────────────*/}
- {tab === 'wifi' && (
- <>
- {/* WiFi Status */}
-
-
- {/* Connect dialog */}
- {showConnect && (
-
- )}
- >
- )}
-
- {/* ── Bluetooth Tab ─────────────────────────────────────────*/}
- {tab === 'bt' && (
- <>
-
-
-
-
Bluetooth
-
{btState?.powered ? 'Powered on' : 'Off'}
-
-
handleBtPower(!btState?.powered)} />
-
- {btState?.powered && (
- <>
-
-
-
Discoverable
-
{btState?.name} ({btState?.address})
-
-
{ try { await apiPost('/api/bluetooth/discoverable', { on: !btState?.discoverable }); setTimeout(refresh, 500); } catch(e) {} }} />
-
-
-
-
Bluetooth MIDI
-
{btState?.midi_enabled ? 'Enabled' : 'Disabled'}
-
-
{ try { await (btState?.midi_enabled ? apiPost('/api/bluetooth/midi-disable') : apiPost('/api/bluetooth/midi-enable')); setTimeout(refresh, 500); } catch(e) {} }} />
-
- >
- )}
-
-
- {btState?.powered && (
-
-
-
Paired Devices ({btPaired.length})
-
- {btScanning ? "..." : "Scan"}
-
-
- {btPaired.length === 0 ? (
-
No paired devices.
- ) : (
- btPaired.map(d => (
-
-
-
{d.name || d.address}
-
{d.address} · {d.connected ? 'Connected' : 'Paired'}
-
- {!d.connected && (
-
{ try { await apiPost('/api/bluetooth/connect', { address: d.address }); } catch(e) { alert('Failed'); } }}>Connect
- )}
-
- ))
- )}
-
- )}
-
- {btScanning && btDevices.length > 0 && (
-
-
Discovered
- {btDevices.map(d => (
-
-
-
{d.name || d.address}
-
{d.address}
-
-
pairBt(d.address)}>Pair
-
- ))}
-
- )}
- >
- )}
-
- {/* ── Routing Tab ───────────────────────────────────────────*/}
- {tab === 'routing' && (
- <>
-
-
4CM Routing
-
-
-
Mode
-
Mono (normal) or 4CM (4-cable method)
-
-
{ setRoutingMode(e.target.value); handleRouting(e.target.value, routingBp); }}
- style={{ background: T.surface, border: `1px solid ${T.border}`, borderRadius: 6, padding: "6px 10px", color: T.textPrimary, fontSize: 13, outline: "none" }}>
- Mono
- 4CM
-
-
- {routingMode === '4cm' && (
-
-
-
Breakpoint
-
Chain position for amp send/return
-
-
{ const v = +e.target.value; setRoutingBp(v); handleRouting(routingMode, v); }}
- style={{ background: T.surface, border: `1px solid ${T.border}`, borderRadius: 6, padding: "6px 10px", color: T.textPrimary, fontSize: 13, width: 60, outline: "none", textAlign: "center" }} />
-
- )}
-
- {/* Channel Mode */}
-
-
Channel Mode
-
-
-
Routing
-
Dual-mono: two independent channels · Stereo: linked as L/R pair
-
-
handleChannelMode(e.target.value)}
- style={{ background: T.surface, border: `1px solid ${T.border}`, borderRadius: 6, padding: "6px 10px", color: T.textPrimary, fontSize: 13, outline: "none" }}>
- Dual-Mono
- Stereo
-
-
-
- {channelMode === 'dual-mono'
- ? 'Each channel controlled independently from its own phone.'
- : 'Channels A (Left) and B (Right) are controlled together.'}
-
-
- >
- )}
-
-
- );
-}
-
-// 7. LOOPER / RECORDER SCREEN ──────────────────────────────────
-function RecordScreen({ state }) {
- const [recording, setRecording] = useState(false);
- const [captures, setCaptures] = useState([]);
- const [loading, setLoading] = useState(true);
- const inputLevel = state?.input_level ?? 0;
- const outputLevel = state?.output_level ?? 0;
-
- const loadCaptures = useCallback(async () => {
- try {
- const data = await apiGet('/api/captures');
- setCaptures(data.captures || []);
- } catch (e) { /* ignore */ }
- setLoading(false);
- }, []);
-
- useEffect(() => { loadCaptures(); }, [loadCaptures]);
-
- const handleRecord = async () => {
- try {
- await apiPost('/api/capture/start');
- setRecording(true);
- } catch (e) { alert('Failed to start recording'); }
- };
-
- const handleStop = async () => {
- try {
- await apiPost('/api/capture/stop');
- setRecording(false);
- loadCaptures();
- } catch (e) { alert('Failed to stop recording'); }
- };
-
- return (
-
-
-
-
Looper / Recorder
-
- {state?.sample_rate ? `${state.sample_rate/1000}kHz` : '—'}
- {recording && ● RECORDING }
-
-
-
- {recording ? (
-
- ⏹ Stop
-
- ) : (
-
- ● Record
-
- )}
-
-
-
-
- {/* Live levels during recording */}
-
-
-
Input Level
-
- {Array.from({ length: 12 }).map((_, i) => {
- const active = Math.round((inputLevel / 100) * 12) > i;
- const c = i >= 10 ? T.red : i >= 8 ? '#E8C030' : T.green;
- return
;
- })}
-
-
-
-
Output Level
-
- {Array.from({ length: 12 }).map((_, i) => {
- const active = Math.round((outputLevel / 100) * 12) > i;
- const c = i >= 10 ? T.red : i >= 8 ? '#E8C030' : T.green;
- return
;
- })}
-
-
-
-
- {/* Recording status */}
- {recording && (
-
-
🔴
-
Recording...
-
- Saving to captures folder — tap Stop to finish
-
-
- )}
-
- {/* Captured files */}
- {!recording && (
- <>
-
-
Recordings ({captures.length})
- {loading ? (
-
- ) : captures.length === 0 ? (
-
- No recordings yet. Tap ● Record to capture audio.
-
- ) : (
- captures.map(c => (
-
-
-
{c.name}
-
{c.size_display}
-
-
▶ Play
-
- ))
- )}
-
- >
- )}
-
-
-
-
- );
-}
-
-// ══════════════════════════════════════════════════════════════
-// SNAPSHOT PANEL
-// ══════════════════════════════════════════════════════════════
-
-function SnapshotPanel({ onClose, state, connected }) {
- const [snapshots, setSnapshots] = useState({});
- const [loading, setLoading] = useState(true);
- const [editingSlot, setEditingSlot] = useState(null);
- const [editName, setEditName] = useState('');
- const [saveFlash, setSaveFlash] = useState(null);
- const [discardEdits, setDiscardEdits] = useState(false);
- const holdTimer = useRef(null);
- const currentSlot = state?.current_snapshot ?? 0;
-
- const loadSnapshots = useCallback(async () => {
- if (!connected) { setLoading(false); return; }
- try {
- const data = await apiGet('/api/snapshots');
- setSnapshots(data.snapshots || {});
- } catch (e) { /* ignore */ }
- setLoading(false);
- }, [connected]);
-
- useEffect(() => { loadSnapshots(); }, [loadSnapshots]);
-
- // Handle press & hold vs tap
- const handlePointerDown = (slot) => {
- holdTimer.current = setTimeout(() => {
- // Long press → save
- holdTimer.current = null;
- handleSave(slot);
- }, 600);
- };
-
- const handlePointerUp = (slot) => {
- if (holdTimer.current) {
- clearTimeout(holdTimer.current);
- holdTimer.current = null;
- // Short tap → recall (or save if empty)
- if (snapshots[String(slot)]) {
- handleRecall(slot);
- } else {
- handleSave(slot);
- }
- }
- };
-
- const handlePointerLeave = () => {
- if (holdTimer.current) {
- clearTimeout(holdTimer.current);
- holdTimer.current = null;
- }
- };
-
- const handleSave = async (slot) => {
- try {
- await apiPost(`/api/snapshots/${slot}/save`);
- setSaveFlash(slot);
- setTimeout(() => setSaveFlash(null), 800);
- await loadSnapshots();
- } catch (e) { /* ignore */ }
- };
-
- const handleRecall = async (slot) => {
- try {
- await apiPost(`/api/snapshots/${slot}/recall`);
- await loadSnapshots();
- } catch (e) { /* ignore */ }
- };
-
- const handleRename = async (slot) => {
- if (!editName.trim()) return;
- try {
- await apiPut(`/api/snapshots/${slot}`, { name: editName.trim() });
- setEditingSlot(null);
- await loadSnapshots();
- } catch (e) { /* ignore */ }
- };
-
- const handleDelete = async (slot) => {
- try {
- await apiDelete(`/api/snapshots/${slot}`);
- await loadSnapshots();
- } catch (e) { /* ignore */ }
- };
-
- return (
-
-
-
Snapshots
-
-
- setDiscardEdits(d => !d)}>
-
-
- Discard Edits
-
-
-
-
-
- Tap to recall · Hold to save
- {discardEdits && Edits will be discarded on recall }
-
-
- {[1,2,3,4,5,6,7,8].map(slot => {
- const snap = snapshots[String(slot)];
- const isActive = currentSlot === slot;
- const isFilled = !!snap;
- const isEditing = editingSlot === slot;
- const isFlashing = saveFlash === slot;
- return (
-
handlePointerDown(slot)}
- onTouchStart={() => handlePointerDown(slot)}
- onMouseUp={() => handlePointerUp(slot)}
- onTouchEnd={() => handlePointerUp(slot)}
- onMouseLeave={handlePointerLeave}
- onTouchCancel={handlePointerLeave}
- style={isFlashing ? { background: 'rgba(58,184,122,.15)' } : {}}>
-
{slot}
- {isEditing ? (
-
setEditName(e.target.value)}
- onBlur={() => handleRename(slot)}
- onKeyDown={e => { if (e.key === 'Enter') handleRename(slot); if (e.key === 'Escape') setEditingSlot(null); }}
- autoFocus onClick={e => e.stopPropagation()} />
- ) : snap ? (
-
{
- e.stopPropagation();
- setEditingSlot(slot);
- setEditName(snap.name);
- }}>{snap.name}
- ) : (
-
Empty
- )}
- {isFlashing &&
}
- {isActive &&
}
-
- );
- })}
-
-
- {/* Delete button for active snapshot */}
- {currentSlot > 0 && snapshots[String(currentSlot)] && (
-
- handleDelete(currentSlot)}>
- Delete Snapshot {currentSlot}
-
-
- )}
-
-
- );
-}
-
-// ══════════════════════════════════════════════════════════════
-// APP SHELL
-// ══════════════════════════════════════════════════════════════
-
-const TABS = [
- { id: "rig", label: "Rig", icon: "🎛" },
- { id: "fx", label: "FX Chain", icon: "⛓" },
- { id: "models", label: "Models", icon: "📁" },
- { id: "irs", label: "IRs", icon: "🎚" },
- { id: "presets", label: "Presets", icon: "⭐" },
- { id: "settings", label: "Settings", icon: "⚙" },
- { id: "record", label: "Looper", icon: "🎙" },
-];
-
-export default function App() {
- const [tab, setTab] = useState("rig");
- const [showSnapshots, setShowSnapshots] = useState(false);
- const [channel, setChannelState] = useState(() => {
- try { return localStorage.getItem('pedal_channel') || 'guitar'; } catch { return 'guitar'; }
- });
- const { state, connected, refresh } = usePedalState();
-
- useEffect(() => { document.title = "Pi Multi-FX Pedal"; }, []);
-
- // Sync channel to localStorage + module-level API var
- useEffect(() => {
- try { localStorage.setItem('pedal_channel', channel); } catch (e) {}
- setChannel(channel);
- }, [channel]);
-
- const handleChannel = (ch) => {
- setChannelState(ch);
- };
-
- return (
- <>
-
-
-
- {/* Status bar */}
-
-
-
- {/* Channel toggle — hidden in stereo mode */}
- {state?.channel_mode === 'stereo' ? (
-
- STEREO
-
- ) : (
-
- handleChannel('guitar')}
- style={{ padding: '2px 8px', fontSize: 10, fontWeight: 700, letterSpacing: '.1em' }}>
- GUITAR
-
- handleChannel('bass')}
- style={{ padding: '2px 8px', fontSize: 10, fontWeight: 700, letterSpacing: '.1em' }}>
- BASS
-
-
- )}
- {state?.tuner_enabled &&
TUNER }
-
-
- {/* Snapshot camera icon */}
- setShowSnapshots(true)}
- title="Snapshots">
- 📷
- {state?.current_snapshot > 0 && (
- {state.current_snapshot}
- )}
-
- {state?.cpu_percent != null && (
- CPU {state.cpu_percent}%
- )}
- {state?.sample_rate && (
- {state.sample_rate/1000}kHz
- )}
- {state?.bypass && BYP }
- {state?.nam_loaded && NAM }
- {state?.ir_loaded && IR }
-
-
-
- {/* Screen */}
-
- {tab === "rig" &&
}
- {tab === "fx" &&
}
- {tab === "models" &&
}
- {tab === "irs" &&
}
- {tab === "presets" &&
}
- {tab === "settings" &&
}
- {tab === "record" &&
}
-
-
- {/* Tab bar */}
-
- {TABS.map(t => (
-
setTab(t.id)}>
- {t.icon}
- {t.label}
-
- ))}
-
-
- {/* Snapshot panel overlay */}
- {showSnapshots && (
-
setShowSnapshots(false)} state={state} connected={connected} />
- )}
-
- >
- );
-}
diff --git a/frontend-react/src/index.css b/frontend-react/src/index.css
deleted file mode 100644
index 4e1b41b..0000000
--- a/frontend-react/src/index.css
+++ /dev/null
@@ -1,2 +0,0 @@
-* { margin: 0; padding: 0; box-sizing: border-box; }
-body { background: #0A0A0C; color: #F0EDE6; }
diff --git a/frontend-react/src/main.jsx b/frontend-react/src/main.jsx
deleted file mode 100644
index b9a1a6d..0000000
--- a/frontend-react/src/main.jsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { StrictMode } from 'react'
-import { createRoot } from 'react-dom/client'
-import './index.css'
-import App from './App.jsx'
-
-createRoot(document.getElementById('root')).render(
-
-
- ,
-)
diff --git a/frontend-react/vite.config.js b/frontend-react/vite.config.js
deleted file mode 100644
index 5e8d157..0000000
--- a/frontend-react/vite.config.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react'
-
-// https://vite.dev/config/
-export default defineConfig({
- plugins: [react()],
- base: '/ui/',
- build: {
- outDir: '../src/web/ui-dist',
- emptyOutDir: true,
- },
-})
diff --git a/ui/.gitignore b/ui/.gitignore
deleted file mode 100644
index a547bf3..0000000
--- a/ui/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-lerna-debug.log*
-
-node_modules
-dist
-dist-ssr
-*.local
-
-# Editor directories and files
-.vscode/*
-!.vscode/extensions.json
-.idea
-.DS_Store
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?
diff --git a/ui/README.md b/ui/README.md
deleted file mode 100644
index 7dbf7eb..0000000
--- a/ui/README.md
+++ /dev/null
@@ -1,73 +0,0 @@
-# React + TypeScript + Vite
-
-This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
-
-Currently, two official plugins are available:
-
-- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
-- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
-
-## React Compiler
-
-The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
-
-## Expanding the ESLint configuration
-
-If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
-
-```js
-export default defineConfig([
- globalIgnores(['dist']),
- {
- files: ['**/*.{ts,tsx}'],
- extends: [
- // Other configs...
-
- // Remove tseslint.configs.recommended and replace with this
- tseslint.configs.recommendedTypeChecked,
- // Alternatively, use this for stricter rules
- tseslint.configs.strictTypeChecked,
- // Optionally, add this for stylistic rules
- tseslint.configs.stylisticTypeChecked,
-
- // Other configs...
- ],
- languageOptions: {
- parserOptions: {
- project: ['./tsconfig.node.json', './tsconfig.app.json'],
- tsconfigRootDir: import.meta.dirname,
- },
- // other options...
- },
- },
-])
-```
-
-You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
-
-```js
-// eslint.config.js
-import reactX from 'eslint-plugin-react-x'
-import reactDom from 'eslint-plugin-react-dom'
-
-export default defineConfig([
- globalIgnores(['dist']),
- {
- files: ['**/*.{ts,tsx}'],
- extends: [
- // Other configs...
- // Enable lint rules for React
- reactX.configs['recommended-typescript'],
- // Enable lint rules for React DOM
- reactDom.configs.recommended,
- ],
- languageOptions: {
- parserOptions: {
- project: ['./tsconfig.node.json', './tsconfig.app.json'],
- tsconfigRootDir: import.meta.dirname,
- },
- // other options...
- },
- },
-])
-```
diff --git a/ui/components.json b/ui/components.json
deleted file mode 100644
index c17a536..0000000
--- a/ui/components.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "$schema": "https://ui.shadcn.com/schema.json",
- "style": "default",
- "rsc": false,
- "tsx": true,
- "tailwind": {
- "config": "",
- "css": "src/index.css",
- "baseColor": "zinc",
- "cssVariables": true,
- "prefix": ""
- },
- "aliases": {
- "components": "@/components",
- "utils": "@/lib/utils",
- "ui": "@/components/ui",
- "lib": "@/lib",
- "hooks": "@/hooks"
- }
-}
diff --git a/ui/eslint.config.js b/ui/eslint.config.js
deleted file mode 100644
index ef614d2..0000000
--- a/ui/eslint.config.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import js from '@eslint/js'
-import globals from 'globals'
-import reactHooks from 'eslint-plugin-react-hooks'
-import reactRefresh from 'eslint-plugin-react-refresh'
-import tseslint from 'typescript-eslint'
-import { defineConfig, globalIgnores } from 'eslint/config'
-
-export default defineConfig([
- globalIgnores(['dist']),
- {
- files: ['**/*.{ts,tsx}'],
- extends: [
- js.configs.recommended,
- tseslint.configs.recommended,
- reactHooks.configs.flat.recommended,
- reactRefresh.configs.vite,
- ],
- languageOptions: {
- globals: globals.browser,
- },
- },
-])
diff --git a/ui/index.html b/ui/index.html
deleted file mode 100644
index b6e9e2d..0000000
--- a/ui/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
ui
-
-
-
-
-
-
diff --git a/ui/package-lock.json b/ui/package-lock.json
deleted file mode 100644
index abbd3ae..0000000
--- a/ui/package-lock.json
+++ /dev/null
@@ -1,3869 +0,0 @@
-{
- "name": "ui",
- "version": "0.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "ui",
- "version": "0.0.0",
- "dependencies": {
- "@radix-ui/react-select": "^2.3.0",
- "@radix-ui/react-slider": "^1.4.0",
- "@radix-ui/react-slot": "^1.2.5",
- "@radix-ui/react-switch": "^1.3.0",
- "@radix-ui/react-tabs": "^1.1.14",
- "@tailwindcss/vite": "^4.3.1",
- "class-variance-authority": "^0.7.1",
- "clsx": "^2.1.1",
- "lucide-react": "^1.18.0",
- "react": "^19.2.6",
- "react-dom": "^19.2.6",
- "tailwind-merge": "^3.6.0"
- },
- "devDependencies": {
- "@eslint/js": "^10.0.1",
- "@types/node": "^24.12.3",
- "@types/react": "^19.2.14",
- "@types/react-dom": "^19.2.3",
- "@vitejs/plugin-react": "^6.0.1",
- "eslint": "^10.3.0",
- "eslint-plugin-react-hooks": "^7.1.1",
- "eslint-plugin-react-refresh": "^0.5.2",
- "globals": "^17.6.0",
- "typescript": "~6.0.2",
- "typescript-eslint": "^8.59.2",
- "vite": "^8.0.12"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
- "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.29.7",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.1.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/compat-data": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
- "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/core": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
- "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.7",
- "@babel/generator": "^7.29.7",
- "@babel/helper-compilation-targets": "^7.29.7",
- "@babel/helper-module-transforms": "^7.29.7",
- "@babel/helpers": "^7.29.7",
- "@babel/parser": "^7.29.7",
- "@babel/template": "^7.29.7",
- "@babel/traverse": "^7.29.7",
- "@babel/types": "^7.29.7",
- "@jridgewell/remapping": "^2.3.5",
- "convert-source-map": "^2.0.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.3",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/babel"
- }
- },
- "node_modules/@babel/generator": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz",
- "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.29.7",
- "@babel/types": "^7.29.7",
- "@jridgewell/gen-mapping": "^0.3.12",
- "@jridgewell/trace-mapping": "^0.3.28",
- "jsesc": "^3.0.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
- "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/compat-data": "^7.29.7",
- "@babel/helper-validator-option": "^7.29.7",
- "browserslist": "^4.24.0",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-globals": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
- "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
- "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.29.7",
- "@babel/types": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
- "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-imports": "^7.29.7",
- "@babel/helper-validator-identifier": "^7.29.7",
- "@babel/traverse": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
- "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
- "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-option": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
- "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helpers": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz",
- "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/template": "^7.29.7",
- "@babel/types": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz",
- "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.29.7"
- },
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
- "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.7",
- "@babel/parser": "^7.29.7",
- "@babel/types": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz",
- "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.7",
- "@babel/generator": "^7.29.7",
- "@babel/helper-globals": "^7.29.7",
- "@babel/parser": "^7.29.7",
- "@babel/template": "^7.29.7",
- "@babel/types": "^7.29.7",
- "debug": "^4.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/types": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz",
- "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.29.7",
- "@babel/helper-validator-identifier": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@emnapi/core": {
- "version": "1.10.0",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
- "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/wasi-threads": "1.2.1",
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@emnapi/runtime": {
- "version": "1.10.0",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
- "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@emnapi/wasi-threads": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
- "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@eslint-community/eslint-utils": {
- "version": "4.9.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
- "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "eslint-visitor-keys": "^3.4.3"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- },
- "peerDependencies": {
- "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
- }
- },
- "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
- "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/@eslint-community/regexpp": {
- "version": "4.12.2",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
- "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
- }
- },
- "node_modules/@eslint/config-array": {
- "version": "0.23.5",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz",
- "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@eslint/object-schema": "^3.0.5",
- "debug": "^4.3.1",
- "minimatch": "^10.2.4"
- },
- "engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- }
- },
- "node_modules/@eslint/config-helpers": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.6.0.tgz",
- "integrity": "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@eslint/core": "^1.2.1"
- },
- "engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- }
- },
- "node_modules/@eslint/core": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz",
- "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@types/json-schema": "^7.0.15"
- },
- "engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- }
- },
- "node_modules/@eslint/js": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz",
- "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- },
- "funding": {
- "url": "https://eslint.org/donate"
- },
- "peerDependencies": {
- "eslint": "^10.0.0"
- },
- "peerDependenciesMeta": {
- "eslint": {
- "optional": true
- }
- }
- },
- "node_modules/@eslint/object-schema": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz",
- "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- }
- },
- "node_modules/@eslint/plugin-kit": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz",
- "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@eslint/core": "^1.2.1",
- "levn": "^0.4.1"
- },
- "engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- }
- },
- "node_modules/@floating-ui/core": {
- "version": "1.7.5",
- "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
- "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
- "license": "MIT",
- "dependencies": {
- "@floating-ui/utils": "^0.2.11"
- }
- },
- "node_modules/@floating-ui/dom": {
- "version": "1.7.6",
- "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
- "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
- "license": "MIT",
- "dependencies": {
- "@floating-ui/core": "^1.7.5",
- "@floating-ui/utils": "^0.2.11"
- }
- },
- "node_modules/@floating-ui/react-dom": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
- "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
- "license": "MIT",
- "dependencies": {
- "@floating-ui/dom": "^1.7.6"
- },
- "peerDependencies": {
- "react": ">=16.8.0",
- "react-dom": ">=16.8.0"
- }
- },
- "node_modules/@floating-ui/utils": {
- "version": "0.2.11",
- "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
- "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
- "license": "MIT"
- },
- "node_modules/@humanfs/core": {
- "version": "0.19.2",
- "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz",
- "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@humanfs/types": "^0.15.0"
- },
- "engines": {
- "node": ">=18.18.0"
- }
- },
- "node_modules/@humanfs/node": {
- "version": "0.16.8",
- "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz",
- "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@humanfs/core": "^0.19.2",
- "@humanfs/types": "^0.15.0",
- "@humanwhocodes/retry": "^0.4.0"
- },
- "engines": {
- "node": ">=18.18.0"
- }
- },
- "node_modules/@humanfs/types": {
- "version": "0.15.0",
- "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz",
- "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=18.18.0"
- }
- },
- "node_modules/@humanwhocodes/module-importer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
- "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=12.22"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/nzakas"
- }
- },
- "node_modules/@humanwhocodes/retry": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
- "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=18.18"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/nzakas"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.13",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
- "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/remapping": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
- "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
- "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.31",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
- "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@napi-rs/wasm-runtime": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.5.tgz",
- "integrity": "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@tybys/wasm-util": "^0.10.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- },
- "peerDependencies": {
- "@emnapi/core": "^1.7.1",
- "@emnapi/runtime": "^1.7.1"
- }
- },
- "node_modules/@oxc-project/types": {
- "version": "0.133.0",
- "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz",
- "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/Boshen"
- }
- },
- "node_modules/@radix-ui/number": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.2.tgz",
- "integrity": "sha512-ceTwaxc4I5IOi97DgCotl3pqiyRGvffcc0oOsE2dQYaJOFIDsDt4VWG6xEbg1QePv9QWausCEIppud/tJ1wNig==",
- "license": "MIT"
- },
- "node_modules/@radix-ui/primitive": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.4.tgz",
- "integrity": "sha512-7AdCK9PQyiljKoBDbN8OuctCbd/esdwZPQ8RtOE3SsyQtUpiPb+ND75q0jEhC1m1ecBI0MFNeLJvwIh9iKHRcQ==",
- "license": "MIT"
- },
- "node_modules/@radix-ui/react-arrow": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.9.tgz",
- "integrity": "sha512-yqHW5WQ/cTpU/un7dqqIKNy2iRU8BC0JB78PEzTfCCYvZu1U6W9KwObAniMk9nhSfyotKPQTYaUD/HB0f5muig==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-primitive": "2.1.5"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-collection": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.9.tgz",
- "integrity": "sha512-zuSVi7ziP7uQRqc+yGxsKJfNkdyHv3ZKDaHe0gzg4dRgws96TPKWIiz84tVHP4GEcEl8bC0mdt17NkcxaJHmaQ==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.3",
- "@radix-ui/react-context": "1.1.4",
- "@radix-ui/react-primitive": "2.1.5",
- "@radix-ui/react-slot": "1.2.5"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-compose-refs": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.3.tgz",
- "integrity": "sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-context": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.4.tgz",
- "integrity": "sha512-QwH4PO5urrbO+FaGd5Aglg+YJgWTyyuZ3g/6mKvsqraLkglDdckw9JafgL5McL5VEJ6EPNduPaT3ZE9BttDAqg==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-direction": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.2.tgz",
- "integrity": "sha512-C3vFhbyi4SW3PmbAi6Awpu4OzJtd0MxGurvSsYtr7p7nM8RNB3VAF3CUmnp2j50knpkrRcB7+ycVXzgLgF6yNA==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-dismissable-layer": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.12.tgz",
- "integrity": "sha512-MhoruH6xEzsbvOmo4TNgMfmtvRGyDZw4MDSdf4ybMHfezjqwzv6hyd4lsMzBp8K9Sn6sGzCF62x1I7BYUECXOg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.4",
- "@radix-ui/react-compose-refs": "1.1.3",
- "@radix-ui/react-primitive": "2.1.5",
- "@radix-ui/react-use-callback-ref": "1.1.2",
- "@radix-ui/react-use-escape-keydown": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-focus-guards": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.4.tgz",
- "integrity": "sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-focus-scope": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.9.tgz",
- "integrity": "sha512-9Se8t+Zry+1rEOL7Y6l/4ANYU/TOtAtf8O2fKdwLltcaMcm6kOqYGbzO4tMFQ0bvzO920pRAoHpFZ4W85S3keQ==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.3",
- "@radix-ui/react-primitive": "2.1.5",
- "@radix-ui/react-use-callback-ref": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-id": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.2.tgz",
- "integrity": "sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-popper": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.3.0.tgz",
- "integrity": "sha512-9PB589e1aWZbrlFUHdz6WiPCL+xLZHQFX7oibqG/6Q0SwOkxDyQX9W/cyPa+sAPPKuC8cpLCpRczE5a/1DiwVQ==",
- "license": "MIT",
- "dependencies": {
- "@floating-ui/react-dom": "^2.0.0",
- "@radix-ui/react-arrow": "1.1.9",
- "@radix-ui/react-compose-refs": "1.1.3",
- "@radix-ui/react-context": "1.1.4",
- "@radix-ui/react-primitive": "2.1.5",
- "@radix-ui/react-use-callback-ref": "1.1.2",
- "@radix-ui/react-use-layout-effect": "1.1.2",
- "@radix-ui/react-use-rect": "1.1.2",
- "@radix-ui/react-use-size": "1.1.2",
- "@radix-ui/rect": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-portal": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.11.tgz",
- "integrity": "sha512-UEytdjgEh2tJGgD/gZK4FUx6t1rNIlM3U0DENhSrG7I75FGm1DnaDuVUWF1pWAWUwGmn1sCJ1VGHn8LhN1aTOw==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-primitive": "2.1.5",
- "@radix-ui/react-use-layout-effect": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-presence": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.6.tgz",
- "integrity": "sha512-zdTk4PlUO0E18HnZ3wYbW0KkJJxWCdiNYp6g6X1PtONFhxVkg01vliTJAmwIszU6mHiyBOoW9P0rAugl5/hULQ==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-primitive": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.5.tgz",
- "integrity": "sha512-zifXeB8Y88qCYx8PLZ5oQb32KwZub+s925mMoZsBBq9KUQqWKkREubTfs6ASjRPPBe7Jt9O8OHH89+95VG+grA==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-slot": "1.2.5"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-roving-focus": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.12.tgz",
- "integrity": "sha512-FvgPt1bRmg8Xt2QpF7NUZW3dE0ZQHGm41dAdgT2J2GJPoIXz+9Em3NobAxf4fupcxhgHu03E5CRiU2MWvObXyg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.4",
- "@radix-ui/react-collection": "1.1.9",
- "@radix-ui/react-compose-refs": "1.1.3",
- "@radix-ui/react-context": "1.1.4",
- "@radix-ui/react-direction": "1.1.2",
- "@radix-ui/react-id": "1.1.2",
- "@radix-ui/react-primitive": "2.1.5",
- "@radix-ui/react-use-callback-ref": "1.1.2",
- "@radix-ui/react-use-controllable-state": "1.2.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-select": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.3.0.tgz",
- "integrity": "sha512-mENc7WpJvJcW8hlMpzfFcHcEhTvYS5JMBmi9HVC1Q00uhBwML086MHYUV8QQdQv6lcu0Wg8dzd1RB8AFADcG/g==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/number": "1.1.2",
- "@radix-ui/primitive": "1.1.4",
- "@radix-ui/react-collection": "1.1.9",
- "@radix-ui/react-compose-refs": "1.1.3",
- "@radix-ui/react-context": "1.1.4",
- "@radix-ui/react-direction": "1.1.2",
- "@radix-ui/react-dismissable-layer": "1.1.12",
- "@radix-ui/react-focus-guards": "1.1.4",
- "@radix-ui/react-focus-scope": "1.1.9",
- "@radix-ui/react-id": "1.1.2",
- "@radix-ui/react-popper": "1.3.0",
- "@radix-ui/react-portal": "1.1.11",
- "@radix-ui/react-presence": "1.1.6",
- "@radix-ui/react-primitive": "2.1.5",
- "@radix-ui/react-slot": "1.2.5",
- "@radix-ui/react-use-callback-ref": "1.1.2",
- "@radix-ui/react-use-controllable-state": "1.2.3",
- "@radix-ui/react-use-layout-effect": "1.1.2",
- "@radix-ui/react-use-previous": "1.1.2",
- "@radix-ui/react-visually-hidden": "1.2.5",
- "aria-hidden": "^1.2.4",
- "react-remove-scroll": "^2.7.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-slider": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.4.0.tgz",
- "integrity": "sha512-RHcPlLOThRJM51DSIC33ZnpDEBYhyEFroVWkd2P54PGGjkmAt14RboYUU9E1MFst666zFHM0tGtWvMjSOtU1pw==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/number": "1.1.2",
- "@radix-ui/primitive": "1.1.4",
- "@radix-ui/react-collection": "1.1.9",
- "@radix-ui/react-compose-refs": "1.1.3",
- "@radix-ui/react-context": "1.1.4",
- "@radix-ui/react-direction": "1.1.2",
- "@radix-ui/react-primitive": "2.1.5",
- "@radix-ui/react-use-controllable-state": "1.2.3",
- "@radix-ui/react-use-layout-effect": "1.1.2",
- "@radix-ui/react-use-previous": "1.1.2",
- "@radix-ui/react-use-size": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-slot": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.5.tgz",
- "integrity": "sha512-rCMO3QsIVKv5JTY5CVbo2MvO77SpEqqYc8AvRE7OWqRDOIqAKjsp+DrmnY9uc8NPdxB5E2z47HTYGeE2+NTptg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-switch": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.3.0.tgz",
- "integrity": "sha512-GP1EZwhoZO/GGnhM1P5/2Vpm8iN8EnngyU0oezn2l78kN8tj25pyrvjIaT7azBhK615KSt+P2w39y57YV5jVkA==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.4",
- "@radix-ui/react-compose-refs": "1.1.3",
- "@radix-ui/react-context": "1.1.4",
- "@radix-ui/react-primitive": "2.1.5",
- "@radix-ui/react-use-controllable-state": "1.2.3",
- "@radix-ui/react-use-previous": "1.1.2",
- "@radix-ui/react-use-size": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-tabs": {
- "version": "1.1.14",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.14.tgz",
- "integrity": "sha512-D5jwp9JNuwDeCw3CYD2Fz+sSHo0droQjC8u75dJHe4aWr5q6yBiXZU+hurXnKudRgEpUkD5TsI6bjHPo5ThUxA==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.4",
- "@radix-ui/react-context": "1.1.4",
- "@radix-ui/react-direction": "1.1.2",
- "@radix-ui/react-id": "1.1.2",
- "@radix-ui/react-presence": "1.1.6",
- "@radix-ui/react-primitive": "2.1.5",
- "@radix-ui/react-roving-focus": "1.1.12",
- "@radix-ui/react-use-controllable-state": "1.2.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-callback-ref": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.2.tgz",
- "integrity": "sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-controllable-state": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.3.tgz",
- "integrity": "sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-effect-event": "0.0.3",
- "@radix-ui/react-use-layout-effect": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-effect-event": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.3.tgz",
- "integrity": "sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-escape-keydown": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.2.tgz",
- "integrity": "sha512-2uVLvLjgO7NZCWw01/FdqRwmA42J0BcjPMUCA+koFEOAb+zjqIP7SiFz/7zWPrKnVmSqr76Omq2ALyCuX4dhLw==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-callback-ref": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-layout-effect": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.2.tgz",
- "integrity": "sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-previous": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.2.tgz",
- "integrity": "sha512-IGBQPtRFdhN6MQ8dbegVmBq1LVZluya3F1jWY+puIcQC3MHctRwTDSBWCkL/3ZcnMJLTMJ++Z+ktmvg0F89iCw==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-rect": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.2.tgz",
- "integrity": "sha512-d8a+bBY/FxikNPlgJJoaBHZX+zKVbWHYJGTLnLvveQgFSTntkGdEKv3JDtHrMS0DNYpllz2nRsTLGLKYttbpmw==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/rect": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-size": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.2.tgz",
- "integrity": "sha512-giWQp+4mxjBPt4KZ0MmyuykFNWfbDxKt4x+fPkRYmgRFJSbCZFzUglvMb/Kjn38tm10YP4ufiQZDx3zna4LU6w==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-visually-hidden": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.5.tgz",
- "integrity": "sha512-tPcHNI3FajdDBFpl/Ez1m2WL0ufJqBKyHxMDBvKitopamK36WwBGOMicuMEZKkM5Wce41QxUyv6BsiqfrWBiGg==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-primitive": "2.1.5"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/rect": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.2.tgz",
- "integrity": "sha512-xnXE7wG13PI+cxieVssYXlQJuYVRhH9NBoxt3KNwzghDIA69GMm7d4wXRouHIYjE+KvS6U/MsMO73NdS2MH9ZA==",
- "license": "MIT"
- },
- "node_modules/@rolldown/binding-android-arm64": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz",
- "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-darwin-arm64": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz",
- "integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-darwin-x64": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz",
- "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-freebsd-x64": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz",
- "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz",
- "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-arm64-gnu": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz",
- "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-arm64-musl": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz",
- "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-ppc64-gnu": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz",
- "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-s390x-gnu": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz",
- "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-x64-gnu": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz",
- "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-x64-musl": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz",
- "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-openharmony-arm64": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz",
- "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-wasm32-wasi": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz",
- "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==",
- "cpu": [
- "wasm32"
- ],
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "1.10.0",
- "@emnapi/runtime": "1.10.0",
- "@napi-rs/wasm-runtime": "^1.1.4"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-win32-arm64-msvc": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz",
- "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-win32-x64-msvc": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz",
- "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/pluginutils": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
- "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
- "license": "MIT"
- },
- "node_modules/@tailwindcss/node": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.1.tgz",
- "integrity": "sha512-6NDaqRoAMSXD1mr/RXu0HBvNE9a2n5tHPsxu9XHLws8o4Twes5rBM2205SUUiJ9goAtadrN6xTGX0UDEwp/N4A==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/remapping": "^2.3.5",
- "enhanced-resolve": "5.21.6",
- "jiti": "^2.7.0",
- "lightningcss": "1.32.0",
- "magic-string": "^0.30.21",
- "source-map-js": "^1.2.1",
- "tailwindcss": "4.3.1"
- }
- },
- "node_modules/@tailwindcss/oxide": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.1.tgz",
- "integrity": "sha512-yVPyo8RNkabVr3O2EhHEE0Rewu7YKzc1DhIqfL46LKveFrmu9XbDazNOJY7/GRuvw1h6u3utWnR29H/p5JPlgA==",
- "license": "MIT",
- "engines": {
- "node": ">= 20"
- },
- "optionalDependencies": {
- "@tailwindcss/oxide-android-arm64": "4.3.1",
- "@tailwindcss/oxide-darwin-arm64": "4.3.1",
- "@tailwindcss/oxide-darwin-x64": "4.3.1",
- "@tailwindcss/oxide-freebsd-x64": "4.3.1",
- "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.1",
- "@tailwindcss/oxide-linux-arm64-gnu": "4.3.1",
- "@tailwindcss/oxide-linux-arm64-musl": "4.3.1",
- "@tailwindcss/oxide-linux-x64-gnu": "4.3.1",
- "@tailwindcss/oxide-linux-x64-musl": "4.3.1",
- "@tailwindcss/oxide-wasm32-wasi": "4.3.1",
- "@tailwindcss/oxide-win32-arm64-msvc": "4.3.1",
- "@tailwindcss/oxide-win32-x64-msvc": "4.3.1"
- }
- },
- "node_modules/@tailwindcss/oxide-android-arm64": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.1.tgz",
- "integrity": "sha512-SVlyf61g374l5cHyg8x9kf5xmLcOaxvOTsbsqDnSsDJaKOEFZ7GCvi84VAVGpxojYOs1+3K6M0UjXfqPU8vmOQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-arm64": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.1.tgz",
- "integrity": "sha512-hVnWLwv+e/l7c4WKyVtHVrIPvYdqWHjRB3MDIqARynzFtnQg85kmQEFCbV9Ja0VVx4xXTIiDWY60Y7iz/iNoDA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-x64": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.1.tgz",
- "integrity": "sha512-Cf7abu0WVgbhU7ANgPUnSAvm7nCvMweusHb8FnaHlLfv/Caq4GYaEZg7ZImzzmjx4lIAfuS8q+eLIS7A7IzxIg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-freebsd-x64": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.1.tgz",
- "integrity": "sha512-ZZqzX2Y+GXtXXfqSfpJhDm60OoZfvLHLCgm+J7NVqgHHJjG/m9ugZI77RwTsVd4fnBJuCFP6Ae6kTJb71UdS8g==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.1.tgz",
- "integrity": "sha512-/Ah/xik0LaMYfv9DZ0S/t4pBlBNYOcqtRwusjgovHkvT8ixueWCLyJjsaF5kQIckjb4IT8Q6K6p/iPmZMixYgg==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.1.tgz",
- "integrity": "sha512-gqdFoVJlw444GvpnheZLHmvTzSxI/cOUUh2KSNejQjTcYkW062SVD+En0rUgD+QV91bz1XGIGtt1HJd48xUGbQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.1.tgz",
- "integrity": "sha512-Bwv9KwOvE0VKa86xPFif9b9c3Y1NxOV1P0gLti/IYaWEsQYZXDlxfGEtA8mdDZ7SG3wyNXAWYT5SIn3giL57oA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.1.tgz",
- "integrity": "sha512-Ymi8O8T15HYQdOUWUtTI6ldN0neHP85FC+Qz32xTcZ7iJXtem/x8ITev0o1e9e5rkqj4lONZfTRLvkmin1+tKg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-musl": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.1.tgz",
- "integrity": "sha512-M+P/91qJ6uILLw4k2G93GMDRAXj61SMvFQYt39AqvUqYgExXpLL5aepfns7sj4HiAQeolirQF9E0lzRvdf4zPQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-wasm32-wasi": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.1.tgz",
- "integrity": "sha512-zsM8uOeqvVGHsAXsJxsT28ttosFahLJKCLOTUBqRAtKnVgGSRitds9T432QiT8b77Yga7JIBkulIRRlJPtYhRA==",
- "bundleDependencies": [
- "@napi-rs/wasm-runtime",
- "@emnapi/core",
- "@emnapi/runtime",
- "@tybys/wasm-util",
- "@emnapi/wasi-threads",
- "tslib"
- ],
- "cpu": [
- "wasm32"
- ],
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "^1.10.0",
- "@emnapi/runtime": "^1.10.0",
- "@emnapi/wasi-threads": "^1.2.1",
- "@napi-rs/wasm-runtime": "^1.1.4",
- "@tybys/wasm-util": "^0.10.2",
- "tslib": "^2.8.1"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.1.tgz",
- "integrity": "sha512-aiNvSq9BsVk8V513lDKlrCFAgf8qBMPZTpgEhInL+NwQqs97mYmupVMrPrgBBSL8Pv/0zXu9MrMF9rMun1ZeNg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.1.tgz",
- "integrity": "sha512-xDEyu1rg290472FEGaKHnzyDyh5QH+AlWvsU5hMoMtPpzmKlRI0jaYKCgSHDYtaQWZOYbMaduSyCwFwY4n1HmA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/vite": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.1.tgz",
- "integrity": "sha512-hItDHuIIlEV61R+faXu66s1K36aTurO/Qw0e45Vskz57gXl9pWOT6eg3zmcEui6CZXddbN7zd41bwmvag4JGwQ==",
- "license": "MIT",
- "dependencies": {
- "@tailwindcss/node": "4.3.1",
- "@tailwindcss/oxide": "4.3.1",
- "tailwindcss": "4.3.1"
- },
- "peerDependencies": {
- "vite": "^5.2.0 || ^6 || ^7 || ^8"
- }
- },
- "node_modules/@tybys/wasm-util": {
- "version": "0.10.2",
- "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz",
- "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@types/esrecurse": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
- "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/estree": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
- "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/json-schema": {
- "version": "7.0.15",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
- "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/node": {
- "version": "24.13.2",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.2.tgz",
- "integrity": "sha512-fRa09kZTgu8o71KFcDjUFuc7F+dEbZYZmkI0mg5YBTRs0yMKjYHsq/c0urDKeDb+D5qVgXOdFcuu+DZPKOITwA==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "undici-types": "~7.18.0"
- }
- },
- "node_modules/@types/react": {
- "version": "19.2.17",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz",
- "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "csstype": "^3.2.2"
- }
- },
- "node_modules/@types/react-dom": {
- "version": "19.2.3",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
- "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
- "devOptional": true,
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "^19.2.0"
- }
- },
- "node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.61.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz",
- "integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@eslint-community/regexpp": "^4.12.2",
- "@typescript-eslint/scope-manager": "8.61.0",
- "@typescript-eslint/type-utils": "8.61.0",
- "@typescript-eslint/utils": "8.61.0",
- "@typescript-eslint/visitor-keys": "8.61.0",
- "ignore": "^7.0.5",
- "natural-compare": "^1.4.0",
- "ts-api-utils": "^2.5.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "@typescript-eslint/parser": "^8.61.0",
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
- "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/@typescript-eslint/parser": {
- "version": "8.61.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.0.tgz",
- "integrity": "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/scope-manager": "8.61.0",
- "@typescript-eslint/types": "8.61.0",
- "@typescript-eslint/typescript-estree": "8.61.0",
- "@typescript-eslint/visitor-keys": "8.61.0",
- "debug": "^4.4.3"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/project-service": {
- "version": "8.61.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.0.tgz",
- "integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.61.0",
- "@typescript-eslint/types": "^8.61.0",
- "debug": "^4.4.3"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/scope-manager": {
- "version": "8.61.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz",
- "integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.61.0",
- "@typescript-eslint/visitor-keys": "8.61.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.61.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz",
- "integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/type-utils": {
- "version": "8.61.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz",
- "integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.61.0",
- "@typescript-eslint/typescript-estree": "8.61.0",
- "@typescript-eslint/utils": "8.61.0",
- "debug": "^4.4.3",
- "ts-api-utils": "^2.5.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/types": {
- "version": "8.61.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz",
- "integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.61.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz",
- "integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/project-service": "8.61.0",
- "@typescript-eslint/tsconfig-utils": "8.61.0",
- "@typescript-eslint/types": "8.61.0",
- "@typescript-eslint/visitor-keys": "8.61.0",
- "debug": "^4.4.3",
- "minimatch": "^10.2.2",
- "semver": "^7.7.3",
- "tinyglobby": "^0.2.15",
- "ts-api-utils": "^2.5.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz",
- "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@typescript-eslint/utils": {
- "version": "8.61.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.0.tgz",
- "integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.9.1",
- "@typescript-eslint/scope-manager": "8.61.0",
- "@typescript-eslint/types": "8.61.0",
- "@typescript-eslint/typescript-estree": "8.61.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.61.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz",
- "integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.61.0",
- "eslint-visitor-keys": "^5.0.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@vitejs/plugin-react": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.2.tgz",
- "integrity": "sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@rolldown/pluginutils": "^1.0.0"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- },
- "peerDependencies": {
- "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0",
- "babel-plugin-react-compiler": "^1.0.0",
- "vite": "^8.0.0"
- },
- "peerDependenciesMeta": {
- "@rolldown/plugin-babel": {
- "optional": true
- },
- "babel-plugin-react-compiler": {
- "optional": true
- }
- }
- },
- "node_modules/acorn": {
- "version": "8.17.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz",
- "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
- }
- },
- "node_modules/ajv": {
- "version": "6.15.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
- "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/aria-hidden": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
- "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/balanced-match": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
- "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/baseline-browser-mapping": {
- "version": "2.10.36",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.36.tgz",
- "integrity": "sha512-lVq/Df7LXlO79MVaaUHztSwWiG9oXoWHlgvNS51v8Dpd4+G4/VIy6qYePTw31nAVls33nUtnfezYeLkYAak9dg==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "baseline-browser-mapping": "dist/cli.cjs"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/brace-expansion": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
- "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^4.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/browserslist": {
- "version": "4.28.2",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
- "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "baseline-browser-mapping": "^2.10.12",
- "caniuse-lite": "^1.0.30001782",
- "electron-to-chromium": "^1.5.328",
- "node-releases": "^2.0.36",
- "update-browserslist-db": "^1.2.3"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "node_modules/caniuse-lite": {
- "version": "1.0.30001799",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz",
- "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "CC-BY-4.0"
- },
- "node_modules/class-variance-authority": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
- "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
- "license": "Apache-2.0",
- "dependencies": {
- "clsx": "^2.1.1"
- },
- "funding": {
- "url": "https://polar.sh/cva"
- }
- },
- "node_modules/clsx": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
- "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/csstype": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
- "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/detect-libc": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
- "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/detect-node-es": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
- "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
- "license": "MIT"
- },
- "node_modules/electron-to-chromium": {
- "version": "1.5.371",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.371.tgz",
- "integrity": "sha512-e9htk9mAYL6AzmkEhSvVVw7IWGSBJ/Bqdn2eRyRLrj1g6sncN4WbFt5qnILYoCktktr45pyjIrOiRvBThQ808w==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/enhanced-resolve": {
- "version": "5.21.6",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.6.tgz",
- "integrity": "sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.4",
- "tapable": "^2.3.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint": {
- "version": "10.4.1",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.4.1.tgz",
- "integrity": "sha512-AyIKhnOBuOAdueD7RB3xB+YeAWScb9jHsJBgH2Hcde8InP5JYhqrRR6iTMHyTEwgENK54Cp44e4v8BwNhsuHuw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.8.0",
- "@eslint-community/regexpp": "^4.12.2",
- "@eslint/config-array": "^0.23.5",
- "@eslint/config-helpers": "^0.6.0",
- "@eslint/core": "^1.2.1",
- "@eslint/plugin-kit": "^0.7.2",
- "@humanfs/node": "^0.16.6",
- "@humanwhocodes/module-importer": "^1.0.1",
- "@humanwhocodes/retry": "^0.4.2",
- "@types/estree": "^1.0.6",
- "ajv": "^6.14.0",
- "cross-spawn": "^7.0.6",
- "debug": "^4.3.2",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^9.1.2",
- "eslint-visitor-keys": "^5.0.1",
- "espree": "^11.2.0",
- "esquery": "^1.7.0",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^8.0.0",
- "find-up": "^5.0.0",
- "glob-parent": "^6.0.2",
- "ignore": "^5.2.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "minimatch": "^10.2.4",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.3"
- },
- "bin": {
- "eslint": "bin/eslint.js"
- },
- "engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- },
- "funding": {
- "url": "https://eslint.org/donate"
- },
- "peerDependencies": {
- "jiti": "*"
- },
- "peerDependenciesMeta": {
- "jiti": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-plugin-react-hooks": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz",
- "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.24.4",
- "@babel/parser": "^7.24.4",
- "hermes-parser": "^0.25.1",
- "zod": "^3.25.0 || ^4.0.0",
- "zod-validation-error": "^3.5.0 || ^4.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "peerDependencies": {
- "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0"
- }
- },
- "node_modules/eslint-plugin-react-refresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.2.tgz",
- "integrity": "sha512-hmgTH57GfzoTFjVN0yBwTggnsVUF2tcqi7RJZHqi9lIezSs4eFyAMktA68YD4r5kNw1mxyY4dmkyoFDb3FIqrA==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "eslint": "^9 || ^10"
- }
- },
- "node_modules/eslint-scope": {
- "version": "9.1.2",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz",
- "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "@types/esrecurse": "^4.3.1",
- "@types/estree": "^1.0.8",
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-visitor-keys": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
- "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/espree": {
- "version": "11.2.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
- "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "acorn": "^8.16.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^5.0.1"
- },
- "engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/esquery": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
- "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "estraverse": "^5.1.0"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/file-entry-cache": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
- "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "flat-cache": "^4.0.0"
- },
- "engines": {
- "node": ">=16.0.0"
- }
- },
- "node_modules/find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/flat-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
- "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.4"
- },
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/flatted": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
- "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/get-nonce": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
- "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/globals": {
- "version": "17.6.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz",
- "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "license": "ISC"
- },
- "node_modules/hermes-estree": {
- "version": "0.25.1",
- "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
- "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/hermes-parser": {
- "version": "0.25.1",
- "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
- "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "hermes-estree": "0.25.1"
- }
- },
- "node_modules/ignore": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
- "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/jiti": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
- "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
- "license": "MIT",
- "bin": {
- "jiti": "lib/jiti-cli.mjs"
- }
- },
- "node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/jsesc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
- "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "json-buffer": "3.0.1"
- }
- },
- "node_modules/levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/lightningcss": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
- "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
- "license": "MPL-2.0",
- "dependencies": {
- "detect-libc": "^2.0.3"
- },
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- },
- "optionalDependencies": {
- "lightningcss-android-arm64": "1.32.0",
- "lightningcss-darwin-arm64": "1.32.0",
- "lightningcss-darwin-x64": "1.32.0",
- "lightningcss-freebsd-x64": "1.32.0",
- "lightningcss-linux-arm-gnueabihf": "1.32.0",
- "lightningcss-linux-arm64-gnu": "1.32.0",
- "lightningcss-linux-arm64-musl": "1.32.0",
- "lightningcss-linux-x64-gnu": "1.32.0",
- "lightningcss-linux-x64-musl": "1.32.0",
- "lightningcss-win32-arm64-msvc": "1.32.0",
- "lightningcss-win32-x64-msvc": "1.32.0"
- }
- },
- "node_modules/lightningcss-android-arm64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
- "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-darwin-arm64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
- "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-darwin-x64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
- "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-freebsd-x64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
- "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm-gnueabihf": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
- "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
- "cpu": [
- "arm"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm64-gnu": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
- "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm64-musl": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
- "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-x64-gnu": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz",
- "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-x64-musl": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz",
- "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-win32-arm64-msvc": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
- "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-win32-x64-msvc": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
- "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-locate": "^5.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
- "node_modules/lucide-react": {
- "version": "1.18.0",
- "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.18.0.tgz",
- "integrity": "sha512-LZDb7H/0YfM+RJncD0hDQRCAu+vSGODqpe35TuVI8EuXaRjkczbsx7p8dY4J87F/MUSj6bpYqeI8nw8qXaAdmA==",
- "license": "ISC",
- "peerDependencies": {
- "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
- }
- },
- "node_modules/magic-string": {
- "version": "0.30.21",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
- "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.5"
- }
- },
- "node_modules/minimatch": {
- "version": "10.2.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
- "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "brace-expansion": "^5.0.5"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/nanoid": {
- "version": "3.3.12",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
- "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/node-releases": {
- "version": "2.0.47",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz",
- "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/optionator": {
- "version": "0.9.4",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
- "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "deep-is": "^0.1.3",
- "fast-levenshtein": "^2.0.6",
- "levn": "^0.4.1",
- "prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.5"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/p-limit": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
- "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "yocto-queue": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
- "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-limit": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/picocolors": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "license": "ISC"
- },
- "node_modules/picomatch": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
- "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/postcss": {
- "version": "8.5.15",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
- "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.12",
- "picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/punycode": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
- "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/react": {
- "version": "19.2.7",
- "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz",
- "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-dom": {
- "version": "19.2.7",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz",
- "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==",
- "license": "MIT",
- "dependencies": {
- "scheduler": "^0.27.0"
- },
- "peerDependencies": {
- "react": "^19.2.7"
- }
- },
- "node_modules/react-remove-scroll": {
- "version": "2.7.2",
- "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz",
- "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==",
- "license": "MIT",
- "dependencies": {
- "react-remove-scroll-bar": "^2.3.7",
- "react-style-singleton": "^2.2.3",
- "tslib": "^2.1.0",
- "use-callback-ref": "^1.3.3",
- "use-sidecar": "^1.1.3"
- },
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/react-remove-scroll-bar": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
- "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
- "license": "MIT",
- "dependencies": {
- "react-style-singleton": "^2.2.2",
- "tslib": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/react-style-singleton": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
- "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
- "license": "MIT",
- "dependencies": {
- "get-nonce": "^1.0.0",
- "tslib": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/rolldown": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz",
- "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==",
- "license": "MIT",
- "dependencies": {
- "@oxc-project/types": "=0.133.0",
- "@rolldown/pluginutils": "^1.0.0"
- },
- "bin": {
- "rolldown": "bin/cli.mjs"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- },
- "optionalDependencies": {
- "@rolldown/binding-android-arm64": "1.0.3",
- "@rolldown/binding-darwin-arm64": "1.0.3",
- "@rolldown/binding-darwin-x64": "1.0.3",
- "@rolldown/binding-freebsd-x64": "1.0.3",
- "@rolldown/binding-linux-arm-gnueabihf": "1.0.3",
- "@rolldown/binding-linux-arm64-gnu": "1.0.3",
- "@rolldown/binding-linux-arm64-musl": "1.0.3",
- "@rolldown/binding-linux-ppc64-gnu": "1.0.3",
- "@rolldown/binding-linux-s390x-gnu": "1.0.3",
- "@rolldown/binding-linux-x64-gnu": "1.0.3",
- "@rolldown/binding-linux-x64-musl": "1.0.3",
- "@rolldown/binding-openharmony-arm64": "1.0.3",
- "@rolldown/binding-wasm32-wasi": "1.0.3",
- "@rolldown/binding-win32-arm64-msvc": "1.0.3",
- "@rolldown/binding-win32-x64-msvc": "1.0.3"
- }
- },
- "node_modules/scheduler": {
- "version": "0.27.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
- "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
- "license": "MIT"
- },
- "node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/tailwind-merge": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz",
- "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/dcastil"
- }
- },
- "node_modules/tailwindcss": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.1.tgz",
- "integrity": "sha512-hk+TB1m+K8CYNrP6rjQaq/Y+4Zylwpa87mLYBKCunwnnQ9p+fHb7kmSfGqyEJoxF/O6CDyABWVFEafNSYKll+Q==",
- "license": "MIT"
- },
- "node_modules/tapable": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
- "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/webpack"
- }
- },
- "node_modules/tinyglobby": {
- "version": "0.2.17",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
- "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
- "license": "MIT",
- "dependencies": {
- "fdir": "^6.5.0",
- "picomatch": "^4.0.4"
- },
- "engines": {
- "node": ">=12.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/SuperchupuDev"
- }
- },
- "node_modules/ts-api-utils": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
- "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18.12"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4"
- }
- },
- "node_modules/tslib": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
- "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
- "license": "0BSD"
- },
- "node_modules/type-check": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
- "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "prelude-ls": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/typescript": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
- "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/typescript-eslint": {
- "version": "8.61.0",
- "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.61.0.tgz",
- "integrity": "sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/eslint-plugin": "8.61.0",
- "@typescript-eslint/parser": "8.61.0",
- "@typescript-eslint/typescript-estree": "8.61.0",
- "@typescript-eslint/utils": "8.61.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/undici-types": {
- "version": "7.18.2",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
- "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/update-browserslist-db": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
- "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "escalade": "^3.2.0",
- "picocolors": "^1.1.1"
- },
- "bin": {
- "update-browserslist-db": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
- }
- },
- "node_modules/uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "punycode": "^2.1.0"
- }
- },
- "node_modules/use-callback-ref": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
- "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/use-sidecar": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
- "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
- "license": "MIT",
- "dependencies": {
- "detect-node-es": "^1.1.0",
- "tslib": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/vite": {
- "version": "8.0.16",
- "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz",
- "integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==",
- "license": "MIT",
- "dependencies": {
- "lightningcss": "^1.32.0",
- "picomatch": "^4.0.4",
- "postcss": "^8.5.15",
- "rolldown": "1.0.3",
- "tinyglobby": "^0.2.17"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- },
- "peerDependencies": {
- "@types/node": "^20.19.0 || >=22.12.0",
- "@vitejs/devtools": "^0.1.18",
- "esbuild": "^0.27.0 || ^0.28.0",
- "jiti": ">=1.21.0",
- "less": "^4.0.0",
- "sass": "^1.70.0",
- "sass-embedded": "^1.70.0",
- "stylus": ">=0.54.8",
- "sugarss": "^5.0.0",
- "terser": "^5.16.0",
- "tsx": "^4.8.1",
- "yaml": "^2.4.2"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "@vitejs/devtools": {
- "optional": true
- },
- "esbuild": {
- "optional": true
- },
- "jiti": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "sass-embedded": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- },
- "tsx": {
- "optional": true
- },
- "yaml": {
- "optional": true
- }
- }
- },
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/word-wrap": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
- "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/yocto-queue": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
- "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/zod": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
- "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/colinhacks"
- }
- },
- "node_modules/zod-validation-error": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
- "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18.0.0"
- },
- "peerDependencies": {
- "zod": "^3.25.0 || ^4.0.0"
- }
- }
- }
-}
diff --git a/ui/package.json b/ui/package.json
deleted file mode 100644
index 23ffa15..0000000
--- a/ui/package.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "name": "ui",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build": "tsc -b && vite build",
- "lint": "eslint .",
- "preview": "vite preview"
- },
- "dependencies": {
- "@radix-ui/react-select": "^2.3.0",
- "@radix-ui/react-slider": "^1.4.0",
- "@radix-ui/react-slot": "^1.2.5",
- "@radix-ui/react-switch": "^1.3.0",
- "@radix-ui/react-tabs": "^1.1.14",
- "@tailwindcss/vite": "^4.3.1",
- "class-variance-authority": "^0.7.1",
- "clsx": "^2.1.1",
- "lucide-react": "^1.18.0",
- "react": "^19.2.6",
- "react-dom": "^19.2.6",
- "tailwind-merge": "^3.6.0"
- },
- "devDependencies": {
- "@eslint/js": "^10.0.1",
- "@types/node": "^24.12.3",
- "@types/react": "^19.2.14",
- "@types/react-dom": "^19.2.3",
- "@vitejs/plugin-react": "^6.0.1",
- "eslint": "^10.3.0",
- "eslint-plugin-react-hooks": "^7.1.1",
- "eslint-plugin-react-refresh": "^0.5.2",
- "globals": "^17.6.0",
- "typescript": "~6.0.2",
- "typescript-eslint": "^8.59.2",
- "vite": "^8.0.12"
- }
-}
diff --git a/ui/public/favicon.svg b/ui/public/favicon.svg
deleted file mode 100644
index 6893eb1..0000000
--- a/ui/public/favicon.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/ui/public/icons.svg b/ui/public/icons.svg
deleted file mode 100644
index e952219..0000000
--- a/ui/public/icons.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ui/src/App.tsx b/ui/src/App.tsx
deleted file mode 100644
index 75fcb30..0000000
--- a/ui/src/App.tsx
+++ /dev/null
@@ -1,707 +0,0 @@
-/**
- * Pi Multi-FX Pedal — App Shell
- *
- * Main application with:
- * - Status bar (mode selector, connection status, CPU, sample rate)
- * - Screen area (tab content: Rig, FX Chain, Models, IRs, Presets, Settings)
- * - Footswitch bar (8 footswitches with dynamic scribble strips per mode)
- * - Tab bar (bottom navigation)
- */
-
-import { useState, useEffect, useCallback } from 'react';
-import { usePedalState, fetchPresets, apiPost, apiPut, apiGet, apiUpload } from './pedal/hooks/usePedalState';
-import { FootswitchModeProvider } from './pedal/FootswitchModeContext';
-import { FootswitchBar } from './pedal/footswitch/FootswitchBar';
-import { ModeSelector } from './pedal/footswitch/ModeSelector';
-import type { PedalState, PedalBlock, BankData } from './pedal/types';
-import './pedal/pedal.css';
-
-const T = {
- bg: '#0A0A0C', panel: '#141418', surface: '#1C1C22',
- border: '#2A2A32', amber: '#E8A030', blue: '#3A7BA8',
- blueDim: '#1E4060', amberDim: '#7A5218',
- green: '#3AB87A', red: '#C84040', text: '#F0EDE6',
- textSec: '#8888A0', textDim: '#444458',
-};
-
-// ── VU Meter ─────────────────────────────────────────────────
-
-function VUMeter({ level = 0, height = 60 }: { level?: number; height?: number }) {
- const segs = 12;
- const active = Math.round((level / 100) * segs);
- const segColor = (i: number) => {
- if (i >= 10) return T.red;
- if (i >= 8) return '#E8C030';
- return T.green;
- };
- return (
-
- {Array.from({ length: segs }).map((_, i) => (
-
- ))}
-
- );
-}
-
-// ── FX Type Labels ───────────────────────────────────────────
-
-const FX_TYPE_LABELS: Record
= {
- noise_gate: 'Noise Gate', compressor: 'Compressor', boost: 'Boost',
- overdrive: 'Overdrive', distortion: 'Distortion', fuzz: 'Fuzz',
- eq: 'EQ', chorus: 'Chorus', flanger: 'Flanger', phaser: 'Phaser',
- tremolo: 'Tremolo', vibrato: 'Vibrato', delay: 'Delay', reverb: 'Reverb',
- volume: 'Volume', nam_amp: 'NAM Amp', ir_cab: 'IR Cab',
- octaver: 'Octaver', pitch_shifter: 'Pitch Shifter', harmonizer: 'Harmonizer',
- whammy: 'Whammy', detune: 'Detune', ring_modulator: 'Ring Mod',
- auto_wah: 'Auto Wah', envelope_filter: 'Env Filter', rotary_speaker: 'Rotary',
- uni_vibe: 'Uni-Vibe', auto_pan: 'Auto Pan', stereo_widener: 'Stereo Widener',
- bitcrusher: 'Bitcrusher', wavefolder: 'Wavefolder', rectifier: 'Rectifier',
- expander: 'Expander', de_esser: 'De-esser', transient_shaper: 'Transient Shaper',
- parametric_eq: 'Parametric EQ', high_pass_filter: 'High Pass',
- low_pass_filter: 'Low Pass', band_pass_filter: 'Band Pass',
- notch_filter: 'Notch Filter', formant_filter: 'Formant Filter',
- ping_pong_delay: 'Ping Pong Delay', multi_tap_delay: 'Multi Tap',
- reverse_delay: 'Reverse Delay', tape_echo: 'Tape Echo',
- shimmer_reverb: 'Shimmer Reverb', early_reflections: 'Early Reflections',
- sidechain_compressor: 'Sidechain Comp', looper: 'Looper',
-};
-
-// ══════════════════════════════════════════════════════════════
-// RIG SCREEN
-// ══════════════════════════════════════════════════════════════
-
-function RigScreen({ state, connected }: { state: PedalState | null; connected: boolean; refresh?: () => void }) {
- const [volume, setVolume] = useState(
- state?.master_volume != null ? Math.round(state.master_volume * 100) : 80
- );
- const [localBypass, setLocalBypass] = useState(null);
- const [localTuner, setLocalTuner] = useState(null);
-
- const bypass = localBypass ?? state?.bypass ?? false;
- const tuner = localTuner ?? state?.tuner_enabled ?? false;
-
- useEffect(() => {
- if (state?.master_volume != null) setVolume(Math.round(state.master_volume * 100));
- }, [state?.master_volume]);
-
- useEffect(() => {
- if (state?.bypass !== undefined) setLocalBypass(null);
- if (state?.tuner_enabled !== undefined) setLocalTuner(null);
- }, [state?.bypass, state?.tuner_enabled]);
-
- const handleVolume = async (val: number) => {
- setVolume(val);
- try { await apiPut('/api/volume', { volume: val / 100 }); } catch {}
- };
-
- const handleBypass = async () => {
- const next = !bypass;
- setLocalBypass(next);
- try { await apiPost('/api/bypass', { bypass: next }); } catch { setLocalBypass(null); }
- };
-
- const handleTuner = async () => {
- const next = !tuner;
- setLocalTuner(next);
- try { await apiPost('/api/tuner', { enabled: next }); } catch { setLocalTuner(null); }
- };
-
- const inputLevel = state?.input_level ?? 0;
- const outputLevel = state?.output_level ?? 0;
-
- return (
-
-
-
-
Active Rig
-
- {state?.current_preset ? (
-
- {state.current_preset.name}
-
- ) : (
- No preset loaded
- )}
- {connected ? (
- Connected
- ) : (
- Offline
- )}
-
-
-
-
-
-
-
-
- {/* Status row */}
-
-
-
-
-
Routing
-
{state?.routing_mode || 'mono'}
-
-
-
- {/* Tuner */}
- {tuner && (
-
-
🎵
-
TUNER ACTIVE
-
—————●—————
-
Tap switch again to exit tuner mode
-
- )}
-
- {/* Volume */}
-
-
-
Master Volume
-
handleVolume(+e.target.value)}
- style={{ width: '100%', accentColor: T.amber }} />
-
{volume}%
-
-
- {state?.nam_loaded ? 'NAM: Active' : 'NAM: —'}
- {state?.ir_loaded ? 'IR: Active' : 'IR: —'}
-
-
-
- {/* Signal chain */}
-
-
Signal Chain
-
- {['IN', state?.bypass ? 'BYP' : (state?.nam_loaded ? 'NAM' : 'AMP'), state?.ir_loaded ? 'IR' : 'CAB', 'OUT'].map((s, i, arr) => (
-
-
{s}
- {i < arr.length - 1 &&
}
-
- ))}
-
-
-
-
- );
-}
-
-// ══════════════════════════════════════════════════════════════
-// FX CHAIN SCREEN
-// ══════════════════════════════════════════════════════════════
-
-function FXBlock({ title, type, active = true, bypassed = false }: {
- title: string; type: string; active?: boolean; bypassed?: boolean;
-}) {
- const [open, setOpen] = useState(true);
- return (
-
-
setOpen(o => !o)}>
-
-
{title}
-
{type}
-
{open ? '▾' : '▸'}
-
-
- );
-}
-
-function FXScreen({ state, connected }: { state: PedalState | null; connected: boolean }) {
- const [fxList, setFxList] = useState<{ id: number; title: string; type: string; bypassed: boolean }[]>([]);
- const [loading, setLoading] = useState(true);
-
- useEffect(() => {
- if (!connected || !state?.current_preset) { setFxList([]); setLoading(false); return; }
- fetchPresets().then(data => {
- const banks = data.banks || [];
- const cp = state.current_preset;
- const preset = cp ? banks[cp.bank]?.presets?.[cp.program] : null;
- if (preset?.chain) {
- setFxList(preset.chain.map((b, i) => ({
- id: i + 1,
- title: FX_TYPE_LABELS[b.fx_type] || b.fx_type,
- type: b.fx_type,
- bypassed: b.bypassed ?? false,
- })));
- }
- setLoading(false);
- }).catch(() => { setFxList([]); setLoading(false); });
- }, [connected, state]);
-
- if (loading) return ;
-
- return (
-
-
-
FX Chain {fxList.length > 0 ? `(${fxList.length})` : ''}
-
-
- {fxList.length === 0 ? (
-
No FX blocks in the chain.
- ) : (
- fxList.map(f =>
)
- )}
-
-
- );
-}
-
-// ══════════════════════════════════════════════════════════════
-// MODELS SCREEN
-// ══════════════════════════════════════════════════════════════
-
-function ModelsScreen({ connected, refresh }: { state?: PedalState | null; connected: boolean; refresh: () => void }) {
- const [models, setModels] = useState<{ name: string; path?: string; architecture?: string; size_mb?: string; loaded?: boolean }[]>([]);
- const [current, setCurrent] = useState(null);
- const [loading, setLoading] = useState(true);
- const [fileRef, setFileRef] = useState(null);
-
- const loadModels = useCallback(async () => {
- if (!connected) { setLoading(false); return; }
- try {
- const data = await apiGet<{ models?: any[]; current?: string }>('/api/models');
- setModels(data.models || []);
- setCurrent(data.current ?? null);
- } catch {}
- setLoading(false);
- }, [connected]);
-
- useEffect(() => { loadModels(); }, [loadModels]);
-
- const handleLoad = async (path?: string) => {
- if (!path) return;
- try { await apiPost('/api/models/load', { path }); await loadModels(); refresh(); } catch { alert('Failed to load model'); }
- };
-
- const handleUnload = async () => {
- try { await apiPost('/api/models/unload'); setCurrent(null); await loadModels(); refresh(); } catch { alert('Failed to unload'); }
- };
-
- const handleUpload = async (e: React.ChangeEvent) => {
- const file = e.target.files?.[0];
- if (!file) return;
- try { await apiUpload('/api/models/upload', file); await loadModels(); } catch { alert('Upload failed'); }
- };
-
- if (loading) return ;
-
- return (
-
-
-
NAM Models ({models.length})
-
fileRef?.click()}>+ Upload
-
setFileRef(el)} type="file" accept=".nam" style={{ display: 'none' }} onChange={handleUpload} />
-
-
- {current && (
-
-
Loaded Model
-
- {current}
- Unload
-
-
- )}
- {models.length === 0 ? (
-
No NAM models found.
- ) : (
- models.map(m => (
-
!m.loaded && handleLoad(m.path)}>
-
-
{m.name}
-
{m.architecture} · {m.size_mb} MB
-
- {m.loaded ?
Loaded :
Load }
-
- ))
- )}
-
-
- );
-}
-
-// ══════════════════════════════════════════════════════════════
-// IRS SCREEN
-// ══════════════════════════════════════════════════════════════
-
-function IRsScreen({ connected, refresh }: { state?: PedalState | null; connected: boolean; refresh: () => void }) {
- const [irs, setIrs] = useState<{ name: string; path?: string; sample_rate?: number; length_ms?: number; loaded?: boolean }[]>([]);
- const [current, setCurrent] = useState(null);
- const [loading, setLoading] = useState(true);
- const [fileRef, setFileRef] = useState(null);
-
- const loadIrs = useCallback(async () => {
- if (!connected) { setLoading(false); return; }
- try {
- const data = await apiGet<{ irs?: any[]; current?: string }>('/api/irs');
- setIrs(data.irs || []);
- setCurrent(data.current ?? null);
- } catch {}
- setLoading(false);
- }, [connected]);
-
- useEffect(() => { loadIrs(); }, [loadIrs]);
-
- const handleLoad = async (path?: string) => {
- if (!path) return;
- try { await apiPost('/api/irs/load', { path }); await loadIrs(); refresh(); } catch { alert('Failed to load IR'); }
- };
-
- const handleUnload = async () => {
- try { await apiPost('/api/irs/unload'); setCurrent(null); await loadIrs(); refresh(); } catch { alert('Failed to unload'); }
- };
-
- const handleUpload = async (e: React.ChangeEvent) => {
- const file = e.target.files?.[0];
- if (!file) return;
- try { await apiUpload('/api/irs/upload', file); await loadIrs(); } catch { alert('Upload failed'); }
- };
-
- if (loading) return ;
-
- return (
-
-
-
IR Files ({irs.length})
-
fileRef?.click()}>+ Upload
-
setFileRef(el)} type="file" accept=".wav" style={{ display: 'none' }} onChange={handleUpload} />
-
-
- {current && (
-
-
Loaded IR
-
- {current}
- Unload
-
-
- )}
- {irs.length === 0 ? (
-
No IR files found.
- ) : (
- irs.map(ir => (
-
!ir.loaded && handleLoad(ir.path)}>
-
-
{ir.name}
-
{ir.sample_rate} Hz · {ir.length_ms} ms
-
- {ir.loaded ?
Loaded :
Load }
-
- ))
- )}
-
-
- );
-}
-
-// ══════════════════════════════════════════════════════════════
-// PRESETS SCREEN
-// ══════════════════════════════════════════════════════════════
-
-function PresetsScreen({ state, connected, refresh }: { state: PedalState | null; connected: boolean; refresh: () => void }) {
- const [banks, setBanks] = useState([]);
- const [selectedBank, setSelectedBank] = useState(0);
- const [loading, setLoading] = useState(true);
-
- const loadPresets = useCallback(async () => {
- if (!connected) {
- setBanks([{ name: 'Default', number: 0, presets: [{ name: 'Edge of Breakup', bank: 0, program: 0 }, { name: 'Modern High Gain', bank: 0, program: 1 }, null, null] }]);
- setLoading(false);
- return;
- }
- try {
- const data = await fetchPresets();
- setBanks(data.banks || []);
- } catch {}
- setLoading(false);
- }, [connected]);
-
- useEffect(() => { loadPresets(); }, [loadPresets]);
-
- const handleActivate = async (bank: number, program: number) => {
- try { await apiPost(`/api/presets/${bank}/${program}/activate`); await loadPresets(); refresh(); } catch { alert('Failed to load preset'); }
- };
-
- if (loading) return ;
-
- const currentPreset = state?.current_preset;
- const bankData = banks[selectedBank];
- const presets = bankData?.presets || [];
-
- return (
-
-
-
- {banks.length > 1 && (
-
- {banks.map((b, i) => (
- setSelectedBank(i)}>{b.name}
- ))}
-
- )}
- {currentPreset && (
-
-
-
Current
-
- {currentPreset.name}
- Bank {currentPreset.bank} · Prog {currentPreset.program}
-
-
-
- )}
- {presets.length === 0 ? (
-
No presets in this bank.
- ) : (
- presets.map((p, i) => {
- if (!p) return null;
- const isActive = currentPreset?.bank === p.bank && currentPreset?.program === p.program;
- return (
-
handleActivate(p.bank, p.program)}>
-
{p.program + 1}
-
-
{p.name}
-
Bank {p.bank} · Program {p.program}
-
- {isActive &&
● }
-
- );
- })
- )}
-
-
- );
-}
-
-// ══════════════════════════════════════════════════════════════
-// SETTINGS SCREEN
-// ══════════════════════════════════════════════════════════════
-
-function SettingsScreen({ state: pedalState }: { state: PedalState | null; refresh?: () => void }) {
- return (
-
-
-
-
-
System
- {pedalState?.cpu_percent != null && (
-
- CPU
- {pedalState.cpu_percent}%
-
- )}
- {pedalState?.sample_rate && (
-
- Sample Rate
- {pedalState.sample_rate / 1000}kHz
-
- )}
-
- Connection
- Live
-
-
-
-
- );
-}
-
-// ══════════════════════════════════════════════════════════════
-// APP SHELL
-// ══════════════════════════════════════════════════════════════
-
-const TABS = [
- { id: 'rig', label: 'Rig', icon: '🎛' },
- { id: 'fx', label: 'FX', icon: '⛓' },
- { id: 'models', label: 'Models', icon: '📁' },
- { id: 'irs', label: 'IRs', icon: '🎚' },
- { id: 'presets', label: 'Presets', icon: '⭐' },
- { id: 'settings', label: 'Settings', icon: '⚙' },
-] as const;
-
-type TabId = (typeof TABS)[number]['id'];
-
-// ── Pedal Shell Content (inner component that has context access) ──
-
-function PedalContent() {
- const [tab, setTab] = useState('rig');
- const { state, connected, refresh } = usePedalState();
-
- // Build block list from current preset state
- const [blocks, setBlocks] = useState([]);
- const [bankNames, setBankNames] = useState(['Default']);
-
- useEffect(() => {
- if (connected && state?.current_preset) {
- fetchPresets().then(data => {
- const names = (data.banks || []).map((b: BankData) => b.name);
- if (names.length > 0) setBankNames(names);
-
- const cp = state.current_preset;
- if (!cp) return;
- const bank = data.banks?.[cp.bank];
- const preset = bank?.presets?.[cp.program];
- if (preset?.chain) {
- setBlocks(preset.chain.map((b, i) => ({
- id: i + 1,
- fx_type: b.fx_type,
- title: FX_TYPE_LABELS[b.fx_type] || b.fx_type,
- bypassed: b.bypassed ?? false,
- })));
- }
- }).catch(() => {});
- }
- }, [connected, state?.current_preset]);
-
- const handleToggleBlock = useCallback(async (blockId: number, newBypass: boolean) => {
- setBlocks(prev => prev.map(b => b.id === blockId ? { ...b, bypassed: newBypass } : b));
- if (connected) {
- try { await apiPost('/api/blocks/toggle', { block_id: blockId, bypass: newBypass }); } catch {}
- }
- }, [connected]);
-
- // Snapshots (placeholder — will be wired to real API)
- const [snapshots] = useState<{ name: string; active: boolean }[]>(
- Array.from({ length: 8 }, (_, i) => ({ name: `Snap ${i + 1}`, active: false }))
- );
-
- return (
-
-
- {/* ── Status Bar ── */}
-
-
-
-
PI MULTI-FX
- {state?.tuner_enabled &&
TUNER }
-
-
-
-
-
- {state?.cpu_percent != null && (
- CPU {state.cpu_percent}%
- )}
- {state?.sample_rate && (
- {state.sample_rate / 1000}kHz
- )}
- {state?.bypass && BYP }
- {state?.nam_loaded && NAM }
- {state?.ir_loaded && IR }
-
-
-
- {/* ── Screen Area ── */}
-
- {tab === 'rig' &&
}
- {tab === 'fx' &&
}
- {tab === 'models' &&
}
- {tab === 'irs' &&
}
- {tab === 'presets' &&
}
- {tab === 'settings' &&
}
-
-
- {/* ── Footswitch Bar ── */}
-
-
- {/* ── Tab Bar ── */}
-
- {TABS.map(t => (
-
setTab(t.id)}>
- {t.icon}
- {t.label}
-
- ))}
-
-
-
- );
-}
-
-// ── Root App ─────────────────────────────────────────────────
-
-export default function App() {
- useEffect(() => { document.title = 'Pi Multi-FX Pedal'; }, []);
-
- return (
- <>
- {/* Global styles for inline-styled components */}
-
-
- >
- );
-}
diff --git a/ui/src/assets/hero.png b/ui/src/assets/hero.png
deleted file mode 100644
index 02251f4..0000000
Binary files a/ui/src/assets/hero.png and /dev/null differ
diff --git a/ui/src/assets/react.svg b/ui/src/assets/react.svg
deleted file mode 100644
index 6c87de9..0000000
--- a/ui/src/assets/react.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/ui/src/assets/vite.svg b/ui/src/assets/vite.svg
deleted file mode 100644
index 5101b67..0000000
--- a/ui/src/assets/vite.svg
+++ /dev/null
@@ -1 +0,0 @@
-Vite
diff --git a/ui/src/components/ui/badge.tsx b/ui/src/components/ui/badge.tsx
deleted file mode 100644
index f000e3e..0000000
--- a/ui/src/components/ui/badge.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import * as React from "react"
-import { cva, type VariantProps } from "class-variance-authority"
-
-import { cn } from "@/lib/utils"
-
-const badgeVariants = cva(
- "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
- {
- variants: {
- variant: {
- default:
- "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
- secondary:
- "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
- destructive:
- "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
- outline: "text-foreground",
- },
- },
- defaultVariants: {
- variant: "default",
- },
- }
-)
-
-export interface BadgeProps
- extends React.HTMLAttributes,
- VariantProps {}
-
-function Badge({ className, variant, ...props }: BadgeProps) {
- return (
-
- )
-}
-
-export { Badge, badgeVariants }
diff --git a/ui/src/components/ui/button.tsx b/ui/src/components/ui/button.tsx
deleted file mode 100644
index 36496a2..0000000
--- a/ui/src/components/ui/button.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import * as React from "react"
-import { Slot } from "@radix-ui/react-slot"
-import { cva, type VariantProps } from "class-variance-authority"
-
-import { cn } from "@/lib/utils"
-
-const buttonVariants = cva(
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
- {
- variants: {
- variant: {
- default: "bg-primary text-primary-foreground hover:bg-primary/90",
- destructive:
- "bg-destructive text-destructive-foreground hover:bg-destructive/90",
- outline:
- "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
- secondary:
- "bg-secondary text-secondary-foreground hover:bg-secondary/80",
- ghost: "hover:bg-accent hover:text-accent-foreground",
- link: "text-primary underline-offset-4 hover:underline",
- },
- size: {
- default: "h-10 px-4 py-2",
- sm: "h-9 rounded-md px-3",
- lg: "h-11 rounded-md px-8",
- icon: "h-10 w-10",
- },
- },
- defaultVariants: {
- variant: "default",
- size: "default",
- },
- }
-)
-
-export interface ButtonProps
- extends React.ButtonHTMLAttributes,
- VariantProps {
- asChild?: boolean
-}
-
-const Button = React.forwardRef(
- ({ className, variant, size, asChild = false, ...props }, ref) => {
- const Comp = asChild ? Slot : "button"
- return (
-
- )
- }
-)
-Button.displayName = "Button"
-
-export { Button, buttonVariants }
diff --git a/ui/src/components/ui/card.tsx b/ui/src/components/ui/card.tsx
deleted file mode 100644
index f62edea..0000000
--- a/ui/src/components/ui/card.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import * as React from "react"
-
-import { cn } from "@/lib/utils"
-
-const Card = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-Card.displayName = "Card"
-
-const CardHeader = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-CardHeader.displayName = "CardHeader"
-
-const CardTitle = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-CardTitle.displayName = "CardTitle"
-
-const CardDescription = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-CardDescription.displayName = "CardDescription"
-
-const CardContent = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-CardContent.displayName = "CardContent"
-
-const CardFooter = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-CardFooter.displayName = "CardFooter"
-
-export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
diff --git a/ui/src/components/ui/input.tsx b/ui/src/components/ui/input.tsx
deleted file mode 100644
index 68551b9..0000000
--- a/ui/src/components/ui/input.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import * as React from "react"
-
-import { cn } from "@/lib/utils"
-
-const Input = React.forwardRef>(
- ({ className, type, ...props }, ref) => {
- return (
-
- )
- }
-)
-Input.displayName = "Input"
-
-export { Input }
diff --git a/ui/src/components/ui/select.tsx b/ui/src/components/ui/select.tsx
deleted file mode 100644
index d826bdb..0000000
--- a/ui/src/components/ui/select.tsx
+++ /dev/null
@@ -1,158 +0,0 @@
-import * as React from "react"
-import * as SelectPrimitive from "@radix-ui/react-select"
-import { Check, ChevronDown, ChevronUp } from "lucide-react"
-
-import { cn } from "@/lib/utils"
-
-const Select = SelectPrimitive.Root
-
-const SelectGroup = SelectPrimitive.Group
-
-const SelectValue = SelectPrimitive.Value
-
-const SelectTrigger = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, children, ...props }, ref) => (
- span]:line-clamp-1",
- className
- )}
- {...props}
- >
- {children}
-
-
-
-
-))
-SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
-
-const SelectScrollUpButton = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-
-
-))
-SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
-
-const SelectScrollDownButton = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-
-
-))
-SelectScrollDownButton.displayName =
- SelectPrimitive.ScrollDownButton.displayName
-
-const SelectContent = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, children, position = "popper", ...props }, ref) => (
-
-
-
-
- {children}
-
-
-
-
-))
-SelectContent.displayName = SelectPrimitive.Content.displayName
-
-const SelectLabel = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-SelectLabel.displayName = SelectPrimitive.Label.displayName
-
-const SelectItem = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, children, ...props }, ref) => (
-
-
-
-
-
-
-
- {children}
-
-))
-SelectItem.displayName = SelectPrimitive.Item.displayName
-
-const SelectSeparator = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-SelectSeparator.displayName = SelectPrimitive.Separator.displayName
-
-export {
- Select,
- SelectGroup,
- SelectValue,
- SelectTrigger,
- SelectContent,
- SelectLabel,
- SelectItem,
- SelectSeparator,
- SelectScrollUpButton,
- SelectScrollDownButton,
-}
diff --git a/ui/src/components/ui/slider.tsx b/ui/src/components/ui/slider.tsx
deleted file mode 100644
index e161dae..0000000
--- a/ui/src/components/ui/slider.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import * as React from "react"
-import * as SliderPrimitive from "@radix-ui/react-slider"
-
-import { cn } from "@/lib/utils"
-
-const Slider = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-
-
-
-
-
-))
-Slider.displayName = SliderPrimitive.Root.displayName
-
-export { Slider }
diff --git a/ui/src/components/ui/switch.tsx b/ui/src/components/ui/switch.tsx
deleted file mode 100644
index bc69cf2..0000000
--- a/ui/src/components/ui/switch.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-"use client"
-
-import * as React from "react"
-import * as SwitchPrimitives from "@radix-ui/react-switch"
-
-import { cn } from "@/lib/utils"
-
-const Switch = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-
-
-))
-Switch.displayName = SwitchPrimitives.Root.displayName
-
-export { Switch }
diff --git a/ui/src/components/ui/tabs.tsx b/ui/src/components/ui/tabs.tsx
deleted file mode 100644
index 26eb109..0000000
--- a/ui/src/components/ui/tabs.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-"use client"
-
-import * as React from "react"
-import * as TabsPrimitive from "@radix-ui/react-tabs"
-
-import { cn } from "@/lib/utils"
-
-const Tabs = TabsPrimitive.Root
-
-const TabsList = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-TabsList.displayName = TabsPrimitive.List.displayName
-
-const TabsTrigger = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
-
-const TabsContent = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-TabsContent.displayName = TabsPrimitive.Content.displayName
-
-export { Tabs, TabsList, TabsTrigger, TabsContent }
diff --git a/ui/src/index.css b/ui/src/index.css
deleted file mode 100644
index c0ec2a4..0000000
--- a/ui/src/index.css
+++ /dev/null
@@ -1,31 +0,0 @@
-@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Inter:wght@300;400;500;600&display=swap');
-@import "tailwindcss";
-
-@custom-variant dark (&:is(.dark *));
-
-:root {
- --background: #0A0A0C;
- --foreground: #F0EDE6;
-}
-
-@theme inline {
- --color-background: var(--background);
- --color-foreground: var(--foreground);
- --radius-sm: calc(0.625rem - 4px);
- --radius-md: calc(0.625rem - 2px);
- --radius-lg: 0.625rem;
- --radius-xl: calc(0.625rem + 4px);
-}
-
-@layer base {
- * { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }
- body {
- background: var(--background);
- color: var(--foreground);
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
- user-select: none;
- -webkit-user-select: none;
- overflow: hidden;
- }
- input, textarea, select { font-family: inherit; }
-}
diff --git a/ui/src/lib/utils.ts b/ui/src/lib/utils.ts
deleted file mode 100644
index d084cca..0000000
--- a/ui/src/lib/utils.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { type ClassValue, clsx } from "clsx"
-import { twMerge } from "tailwind-merge"
-
-export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs))
-}
diff --git a/ui/src/main.tsx b/ui/src/main.tsx
deleted file mode 100644
index bef5202..0000000
--- a/ui/src/main.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { StrictMode } from 'react'
-import { createRoot } from 'react-dom/client'
-import './index.css'
-import App from './App.tsx'
-
-createRoot(document.getElementById('root')!).render(
-
-
- ,
-)
diff --git a/ui/src/pedal/FootswitchModeContext.tsx b/ui/src/pedal/FootswitchModeContext.tsx
deleted file mode 100644
index 6b691f8..0000000
--- a/ui/src/pedal/FootswitchModeContext.tsx
+++ /dev/null
@@ -1,369 +0,0 @@
-/**
- * FootswitchMode Context — provides the current mode and mode switching
- * to all footswitch components.
- */
-
-import { createContext, useContext, useState, useCallback, useEffect, type ReactNode } from 'react';
-import type { FootswitchMode, ScribbleStripData, PedalState, PedalBlock } from './types';
-import { apiPost, activatePreset } from "./hooks/usePedalState";
-
-// ── Context Shape ─────────────────────────────────────────────
-
-interface FootswitchModeContextValue {
- mode: FootswitchMode;
- setMode: (mode: FootswitchMode) => void;
- /** Scribble strip data for each footswitch position (0–7) */
- scribbleData: ScribbleStripData[];
- /** Handle a footswitch press at a given position */
- handleFootswitch: (index: number) => void;
- /** Handle secondary action (double-tap / long-press) at a given position */
- handleSecondary: (index: number) => void;
- /** Current banks/presets for preset mode */
- currentBankIndex: number;
- currentPresetIndex: number;
- setBank: (bank: number) => void;
- setPreset: (preset: number) => void;
- /** Whether the preset has been modified */
- dirty: boolean;
-}
-
-const FootswitchModeContext = createContext(null);
-
-// ── Mode-specific scribble strip generators ───────────────────
-
-function stompScribbles(
- blocks: PedalBlock[],
- _state: PedalState | null,
-): ScribbleStripData[] {
- const items: ScribbleStripData[] = [];
- for (let i = 0; i < 8; i++) {
- const block = blocks[i];
- if (block) {
- items.push({
- key: `stomp-${block.id}`,
- label: block.title.length > 6 ? block.title.slice(0, 6) : block.title,
- sublabel: block.bypassed ? 'BYP' : 'ON',
- color: block.bypassed ? 'off' : 'green',
- active: !block.bypassed,
- bypassed: block.bypassed,
- });
- } else {
- items.push({
- key: `stomp-empty-${i}`,
- label: '—',
- sublabel: '',
- color: 'off',
- active: false,
- bypassed: false,
- });
- }
- }
- return items;
-}
-
-function presetScribbles(
- state: PedalState | null,
- bankIndex: number,
- bankNames: string[],
-): ScribbleStripData[] {
- const items: ScribbleStripData[] = [];
-
- // FS 0-1: Bank navigation
- items.push({
- key: 'bank-down',
- label: 'BANK',
- sublabel: bankIndex > 0 ? `${bankNames[bankIndex - 1] || '−'}` : '—',
- color: 'blue',
- active: bankIndex > 0,
- });
- items.push({
- key: 'bank-up',
- label: 'BANK',
- sublabel: bankIndex < bankNames.length - 1 ? `${bankNames[bankIndex + 1] || '+'}` : '—',
- color: 'blue',
- active: bankIndex < bankNames.length - 1,
- });
-
- // FS 2-7: Preset slots
- for (let i = 0; i < 6; i++) {
- const presetIdx = i;
- const isActive = state?.current_preset?.program === presetIdx &&
- state?.current_preset?.bank === bankIndex;
- items.push({
- key: `preset-${presetIdx}`,
- label: String(presetIdx + 1),
- sublabel: state?.current_preset && state.current_preset.program === presetIdx
- ? state.current_preset.name : '',
- color: isActive ? 'green' : 'off',
- active: isActive,
- });
- }
-
- return items;
-}
-
-function snapshotScribbles(
- snapshots: { name: string; active: boolean }[],
-): ScribbleStripData[] {
- const items: ScribbleStripData[] = [];
- for (let i = 0; i < 8; i++) {
- const snap = snapshots[i];
- if (snap) {
- items.push({
- key: `snapshot-${i}`,
- label: snap.name.length > 6 ? snap.name.slice(0, 6) : (snap.name || `Snap ${i + 1}`),
- sublabel: snap.active ? 'ACTIVE' : '',
- color: snap.active ? 'amber' : 'off',
- active: snap.active,
- });
- } else {
- items.push({
- key: `snapshot-empty-${i}`,
- label: `Snap ${i + 1}`,
- sublabel: '',
- color: 'off',
- active: false,
- });
- }
- }
- return items;
-}
-
-function comboScribbles(
- blocks: PedalBlock[],
- state: PedalState | null,
- bankNames: string[],
- bankIndex: number,
-): ScribbleStripData[] {
- // Combo = first 4 stomp + bank/preset info on last 4
- const stomp = stompScribbles(blocks.slice(0, 4), state);
-
- // FS 4: bank down, FS 5: bank up, FS 6-7: preset select
- return [
- ...stomp.slice(0, 4),
- {
- key: 'bank-down',
- label: 'BANK',
- sublabel: bankIndex > 0 ? '▼' : '—',
- color: 'blue',
- active: bankIndex > 0,
- },
- {
- key: 'bank-up',
- label: 'BANK',
- sublabel: bankIndex < bankNames.length - 1 ? '▲' : '—',
- color: 'blue',
- active: bankIndex < bankNames.length - 1,
- },
- {
- key: 'preset-select',
- label: state?.current_preset?.name?.slice(0, 6) || '—',
- sublabel: state?.current_preset ? `B${bankIndex + 1}` : '',
- color: 'amber',
- active: true,
- },
- {
- key: 'global-bypass',
- label: 'BYP',
- sublabel: state?.bypass ? 'ON' : 'OFF',
- color: state?.bypass ? 'red' : 'off',
- active: !!state?.bypass,
- },
- ];
-}
-
-// ── Provider ──────────────────────────────────────────────────
-
-interface FootswitchModeProviderProps {
- children: ReactNode;
- state: PedalState | null;
- connected: boolean;
- refresh: () => void;
- blocks: PedalBlock[];
- bankNames: string[];
- /** Current snapshot definitions */
- snapshots: { name: string; active: boolean }[];
- /** Called when a block toggle needs to happen */
- onToggleBlock?: (blockId: number, bypassed: boolean) => void;
-}
-
-export function FootswitchModeProvider({
- children,
- state,
- connected,
- refresh,
- blocks,
- bankNames,
- snapshots,
- onToggleBlock,
-}: FootswitchModeProviderProps) {
- const [mode, setMode] = useState('stomp');
- const [currentBankIndex, setCurrentBankIndex] = useState(() => {
- try {
- const saved = localStorage.getItem('pedal-footswitch-bank');
- return saved !== null ? parseInt(saved, 10) : 0;
- } catch {
- return 0;
- }
- });
- const [currentPresetIndex, setCurrentPresetIndex] = useState(0);
- const [dirty, _setDirty] = useState(false);
-
- // Persist bank index to localStorage
- useEffect(() => {
- try {
- localStorage.setItem('pedal-footswitch-bank', String(currentBankIndex));
- } catch { /* quota exceeded or storage disabled */ }
- }, [currentBankIndex]);
-
- // Generate scribble data based on mode
- let scribbleData: ScribbleStripData[];
- switch (mode) {
- case 'stomp':
- scribbleData = stompScribbles(blocks, state);
- break;
- case 'preset':
- scribbleData = presetScribbles(state, currentBankIndex, bankNames);
- break;
- case 'snapshot':
- scribbleData = snapshotScribbles(snapshots);
- break;
- case 'combo':
- scribbleData = comboScribbles(blocks, state, bankNames, currentBankIndex);
- break;
- default:
- scribbleData = stompScribbles(blocks, state);
- }
-
- const handleFootswitch = useCallback((index: number) => {
- switch (mode) {
- case 'stomp': {
- const block = blocks[index];
- if (block && onToggleBlock) {
- onToggleBlock(block.id, !block.bypassed);
- }
- break;
- }
- case 'preset': {
- // FS 0 = bank down, FS 1 = bank up, FS 2-7 = presets
- if (index === 0) {
- setCurrentBankIndex(prev => Math.max(0, prev - 1));
- } else if (index === 1) {
- setCurrentBankIndex(prev => Math.min(bankNames.length - 1, prev + 1));
- } else {
- const presetIndex = index - 2;
- if (connected) {
- activatePreset(currentBankIndex, presetIndex).then(() => refresh());
- setCurrentPresetIndex(presetIndex);
- }
- }
- break;
- }
- case 'snapshot': {
- // Recall snapshot at index
- if (connected) {
- apiPost(`/api/snapshots/${index}/recall`).catch(() => {});
- }
- break;
- }
- case 'combo': {
- // FS 0-3 = stomp toggles, FS 4 = bank down, FS 5 = bank up,
- // FS 6 = open preset browser, FS 7 = global bypass
- if (index < 4) {
- const block = blocks[index];
- if (block && onToggleBlock) {
- onToggleBlock(block.id, !block.bypassed);
- }
- } else if (index === 4) {
- setCurrentBankIndex(prev => Math.max(0, prev - 1));
- } else if (index === 5) {
- setCurrentBankIndex(prev => Math.min(bankNames.length - 1, prev + 1));
- } else if (index === 6) {
- setMode('preset');
- } else if (index === 7) {
- if (connected) {
- apiPost('/api/bypass', { bypass: !state?.bypass }).catch(() => {});
- }
- }
- break;
- }
- }
- }, [mode, blocks, onToggleBlock, connected, currentBankIndex, bankNames, state, refresh]);
-
- const handleSecondary = useCallback((index: number) => {
- // Double-tap / long-press secondary actions per mode
- switch (mode) {
- case 'stomp': {
- // Secondary: toggle tuner on FS 7 (last footswitch), or reset block params
- if (index === 7 && connected) {
- apiPost('/api/tuner', { enabled: !state?.tuner_enabled }).catch(() => {});
- }
- break;
- }
- case 'preset': {
- // Secondary on bank switches: jump to first/last bank
- if (index === 0) {
- setCurrentBankIndex(0);
- } else if (index === 1) {
- setCurrentBankIndex(bankNames.length - 1);
- }
- break;
- }
- case 'snapshot': {
- // Secondary: save current state to snapshot
- if (connected) {
- apiPost(`/api/snapshots/${index}/save`).catch(() => {});
- }
- break;
- }
- case 'combo': {
- // Secondary on stomp blocks: edit block params (would open param panel)
- // Secondary on bypass: enter tuner mode
- if (index === 7 && connected) {
- apiPost('/api/tuner', { enabled: !state?.tuner_enabled }).catch(() => {});
- }
- break;
- }
- }
- }, [mode, state, connected, bankNames]);
-
- const setBank = useCallback((bank: number) => {
- setCurrentBankIndex(bank);
- }, []);
-
- const setPreset = useCallback((preset: number) => {
- setCurrentPresetIndex(preset);
- if (connected) {
- activatePreset(currentBankIndex, preset).then(() => refresh());
- }
- }, [connected, currentBankIndex, refresh]);
-
- const value: FootswitchModeContextValue = {
- mode,
- setMode,
- scribbleData,
- handleFootswitch,
- handleSecondary,
- currentBankIndex,
- currentPresetIndex,
- setBank,
- setPreset,
- dirty,
- };
-
- return (
-
- {children}
-
- );
-}
-
-// ── Consumer Hook ─────────────────────────────────────────────
-
-export function useFootswitchMode(): FootswitchModeContextValue {
- const ctx = useContext(FootswitchModeContext);
- if (!ctx) {
- throw new Error('useFootswitchMode must be used within a FootswitchModeProvider');
- }
- return ctx;
-}
diff --git a/ui/src/pedal/footswitch/FootswitchBar.tsx b/ui/src/pedal/footswitch/FootswitchBar.tsx
deleted file mode 100644
index 5099168..0000000
--- a/ui/src/pedal/footswitch/FootswitchBar.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * FootswitchBar — the bottom bar of 8 footswitches with scribble strip LCDs.
- *
- * Renders the appropriate scribble data per mode (handled via FootswitchModeContext).
- * Each footswitch supports single-tap (primary action) and double-tap (secondary).
- */
-
-import { useFootswitchMode } from '../FootswitchModeContext';
-import { ScribbleStrip } from './ScribbleStrip';
-
-export function FootswitchBar() {
- const { scribbleData, handleFootswitch, handleSecondary } = useFootswitchMode();
-
- return (
-
- {scribbleData.map((sd, i) => (
-
- {/* Scribble strip LCD above the switch */}
-
handleFootswitch(i)}
- onSecondary={() => handleSecondary(i)}
- />
-
- {/* Footswitch button */}
- handleFootswitch(i)}
- onContextMenu={(e) => { e.preventDefault(); handleSecondary(i); }}
- style={{
- '--fs-color': sd.color,
- } as React.CSSProperties}
- >
-
-
-
-
- ))}
-
- );
-}
diff --git a/ui/src/pedal/footswitch/ModeSelector.tsx b/ui/src/pedal/footswitch/ModeSelector.tsx
deleted file mode 100644
index 257fe3b..0000000
--- a/ui/src/pedal/footswitch/ModeSelector.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * ModeSelector — mode switch buttons shown in the status bar.
- * Lets the user cycle between Stomp, Preset, Snapshot, and Combo modes.
- */
-
-import { useFootswitchMode } from '../FootswitchModeContext';
-import type { FootswitchMode } from '../types';
-import { FOOTSWITCH_MODE_LABELS } from '../types';
-
-const MODES: FootswitchMode[] = ['stomp', 'preset', 'snapshot', 'combo'];
-const MODE_ICONS: Record = {
- stomp: '◉',
- preset: '☆',
- snapshot: '◆',
- combo: '◈',
- transport: '▶',
-};
-
-interface ModeSelectorProps {
- collapsed?: boolean;
-}
-
-export function ModeSelector({ collapsed = false }: ModeSelectorProps) {
- const { mode, setMode } = useFootswitchMode();
-
- if (collapsed) {
- // Compact: just a single click target that cycles
- const nextIdx = (MODES.indexOf(mode) + 1) % MODES.length;
- return (
- setMode(MODES[nextIdx])}
- title={`Mode: ${FOOTSWITCH_MODE_LABELS[mode]} — tap to switch`}
- >
- {MODE_ICONS[mode]}
- {FOOTSWITCH_MODE_LABELS[mode]}
-
- );
- }
-
- return (
-
- {MODES.map(m => (
- setMode(m)}
- title={FOOTSWITCH_MODE_LABELS[m]}
- >
- {MODE_ICONS[m]}
- {FOOTSWITCH_MODE_LABELS[m]}
-
- ))}
-
- );
-}
diff --git a/ui/src/pedal/footswitch/ScribbleStrip.tsx b/ui/src/pedal/footswitch/ScribbleStrip.tsx
deleted file mode 100644
index e529cd1..0000000
--- a/ui/src/pedal/footswitch/ScribbleStrip.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * ScribbleStrip — the LCD-like label display above each footswitch.
- *
- * Shows block/preset/snapshot name and status, mimicking the
- * Helix / Line 6 scribble strip LCDs.
- */
-
-import type { ScribbleStripData } from '../types';
-import { SCRIBBLE_COLORS } from '../types';
-import { useDoubleTap } from '../hooks/useDoubleTap';
-
-interface ScribbleStripProps {
- data: ScribbleStripData;
- onPress: () => void;
- onSecondary: () => void;
-}
-
-export function ScribbleStrip({ data, onPress, onSecondary }: ScribbleStripProps) {
- const { handleTap } = useDoubleTap({
- onSingleTap: onPress,
- onDoubleTap: onSecondary,
- });
-
- const color = SCRIBBLE_COLORS[data.color ?? 'off'];
- const isActive = data.active ?? false;
- const isBypassed = data.bypassed ?? false;
-
- return (
-
- {/* LED indicator */}
-
-
- {/* Label area — LCD-style */}
-
- {data.label || '—'}
- {data.sublabel && (
- {data.sublabel}
- )}
-
-
- {/* Icon (optional) */}
- {data.icon &&
{data.icon} }
-
- );
-}
diff --git a/ui/src/pedal/hooks/useDoubleTap.ts b/ui/src/pedal/hooks/useDoubleTap.ts
deleted file mode 100644
index 5af0ec2..0000000
--- a/ui/src/pedal/hooks/useDoubleTap.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * Double-tap gesture hook for footswitch capacitive touch / secondary actions.
- *
- * Detects two rapid taps within a configurable threshold and fires
- * onDoubleTap. Single taps fire onSingleTap after a short debounce.
- */
-
-import { useRef, useCallback } from 'react';
-
-interface UseDoubleTapOptions {
- /** Max ms between taps to count as double-tap (default: 300) */
- threshold?: number;
- /** Called on single tap after debounce */
- onSingleTap?: () => void;
- /** Called on double tap */
- onDoubleTap?: () => void;
-}
-
-export function useDoubleTap({
- threshold = 300,
- onSingleTap,
- onDoubleTap,
-}: UseDoubleTapOptions) {
- const lastTapRef = useRef(0);
- const singleTimerRef = useRef | null>(null);
-
- const handleTap = useCallback(() => {
- const now = Date.now();
- const sinceLast = now - lastTapRef.current;
-
- if (sinceLast < threshold) {
- // Double tap detected
- if (singleTimerRef.current) {
- clearTimeout(singleTimerRef.current);
- singleTimerRef.current = null;
- }
- lastTapRef.current = 0;
- onDoubleTap?.();
- } else {
- // Potential single tap — wait for double-tap window to close
- lastTapRef.current = now;
- if (singleTimerRef.current) {
- clearTimeout(singleTimerRef.current);
- }
- singleTimerRef.current = setTimeout(() => {
- onSingleTap?.();
- singleTimerRef.current = null;
- }, threshold);
- }
- }, [threshold, onSingleTap, onDoubleTap]);
-
- return { handleTap };
-}
-
-/**
- * Hook for long-press gesture detection.
- * Fires onLongPress after `duration` ms of continuous hold.
- */
-export function useLongPress({
- duration = 500,
- onLongPress,
-}: {
- duration?: number;
- onLongPress?: () => void;
-}) {
- const timerRef = useRef | null>(null);
-
- const handleStart = useCallback(() => {
- timerRef.current = setTimeout(() => {
- onLongPress?.();
- }, duration);
- }, [duration, onLongPress]);
-
- const handleEnd = useCallback(() => {
- if (timerRef.current) {
- clearTimeout(timerRef.current);
- timerRef.current = null;
- }
- }, []);
-
- return { handleStart, handleEnd };
-}
diff --git a/ui/src/pedal/hooks/usePedalState.ts b/ui/src/pedal/hooks/usePedalState.ts
deleted file mode 100644
index c8a4251..0000000
--- a/ui/src/pedal/hooks/usePedalState.ts
+++ /dev/null
@@ -1,155 +0,0 @@
-/**
- * Pi Multi-FX Pedal — State Hook
- *
- * API helpers, WebSocket real-time updates, and pedal state management.
- * Ported and organized from frontend-react/App.jsx.
- */
-
-import { useState, useRef, useEffect, useCallback } from 'react';
-import type { PedalState, PresetListResponse } from '../types';
-
-// ── API Base ──────────────────────────────────────────────────
-
-const API = window.location.origin;
-const WS_URL = API.replace(/^http/, 'ws') + '/ws';
-
-// ── API Helpers ───────────────────────────────────────────────
-
-export async function apiGet(path: string): Promise {
- const r = await fetch(`${API}${path}`);
- if (!r.ok) throw new Error(`${path} => ${r.status}`);
- return r.json();
-}
-
-export async function apiPost(path: string, data?: unknown): Promise {
- const r = await fetch(`${API}${path}`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: data != null ? JSON.stringify(data) : undefined,
- });
- if (!r.ok) throw new Error(`${path} => ${r.status}`);
- return r.json();
-}
-
-export async function apiPut(path: string, data: unknown): Promise {
- const r = await fetch(`${API}${path}`, {
- method: 'PUT',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(data),
- });
- if (!r.ok) throw new Error(`${path} => ${r.status}`);
- return r.json();
-}
-
-export async function apiDelete(path: string): Promise {
- const r = await fetch(`${API}${path}`, { method: 'DELETE' });
- if (!r.ok) throw new Error(`${path} => ${r.status}`);
- return r.json();
-}
-
-export async function apiUpload(path: string, file: File): Promise {
- const fd = new FormData();
- fd.append('file', file);
- const r = await fetch(`${API}${path}`, { method: 'POST', body: fd });
- if (!r.ok) throw new Error(`${path} => ${r.status}`);
- return r.json();
-}
-
-// ── usePedalState Hook ────────────────────────────────────────
-
-export interface PedalStateResult {
- state: PedalState | null;
- connected: boolean;
- refresh: () => void;
-}
-
-export function usePedalState(): PedalStateResult {
- const [state, setState] = useState(null);
- const [connected, setConnected] = useState(false);
- const wsRef = useRef(null);
- const pollRef = useRef | null>(null);
-
- useEffect(() => {
- // Fetch initial state
- apiGet('/api/state')
- .then(s => { setState(s); setConnected(true); })
- .catch(() => { setConnected(false); });
-
- // WebSocket for real-time updates
- let reconnectTimer: ReturnType;
-
- function connect() {
- try {
- const ws = new WebSocket(WS_URL);
- ws.onmessage = (e) => {
- try {
- const msg = JSON.parse(e.data);
- if (msg.type === 'connected' || msg.type === 'state') {
- setState(msg.state);
- setConnected(true);
- }
- if (msg.type === 'preset_changed' && msg.state) setState(msg.state);
- if (msg.type === 'bypass_changed') {
- setState(prev => prev ? { ...prev, bypass: msg.bypass } : prev);
- }
- if (msg.type === 'tuner_changed') {
- setState(prev => prev ? { ...prev, tuner_enabled: msg.tuner_enabled } : prev);
- }
- if (msg.type === 'routing_changed') {
- setState(prev => prev ? {
- ...prev,
- routing_mode: msg.routing_mode,
- routing_breakpoint: msg.routing_breakpoint,
- } : prev);
- }
- if (msg.type === 'model_loaded' || msg.type === 'ir_loaded') {
- apiGet('/api/state').then(s => setState(s));
- }
- } catch {
- // ignore parse errors
- }
- };
- ws.onclose = () => {
- setConnected(false);
- reconnectTimer = setTimeout(connect, 3000);
- };
- ws.onerror = () => ws.close();
- wsRef.current = ws;
- } catch {
- reconnectTimer = setTimeout(connect, 3000);
- }
- }
- connect();
-
- // Polling fallback every 5s
- pollRef.current = setInterval(() => {
- apiGet('/api/state')
- .then(s => { setState(s); setConnected(true); })
- .catch(() => {});
- }, 5000);
-
- return () => {
- if (pollRef.current) clearInterval(pollRef.current);
- clearTimeout(reconnectTimer);
- if (wsRef.current) wsRef.current.close();
- };
- }, []);
-
- const refresh = useCallback(() => {
- apiGet('/api/state')
- .then(s => { setState(s); setConnected(true); })
- .catch(() => {});
- }, []);
-
- return { state, connected, refresh };
-}
-
-// ── Preset helpers ────────────────────────────────────────────
-
-export async function fetchPresets(): Promise {
- return apiGet('/api/presets');
-}
-
-export async function activatePreset(bank: number, program: number): Promise {
- await apiPost(`/api/presets/${bank}/${program}/activate`);
-}
diff --git a/ui/src/pedal/pedal.css b/ui/src/pedal/pedal.css
deleted file mode 100644
index 131029a..0000000
--- a/ui/src/pedal/pedal.css
+++ /dev/null
@@ -1,447 +0,0 @@
-/* ══════════════════════════════════════════════════════════════
- Pi Multi-FX Pedal — Styles
- Dark pedal theme with Helix-inspired footswitch bar
- ══════════════════════════════════════════════════════════════ */
-
-/* ── Design Tokens ─────────────────────────────────────────── */
-
-:root {
- --pedal-bg: #0A0A0C;
- --pedal-panel: #141418;
- --pedal-surface: #1C1C22;
- --pedal-border: #2A2A32;
- --pedal-border-light: #3A3A48;
- --pedal-amber: #E8A030;
- --pedal-amber-dim: #7A5218;
- --pedal-blue: #3A7BA8;
- --pedal-blue-dim: #1E4060;
- --pedal-green: #3AB87A;
- --pedal-green-dim: #1E6040;
- --pedal-red: #C84040;
- --pedal-red-dim: #602020;
- --pedal-purple: #9B59B6;
- --pedal-cyan: #1ABC9C;
- --pedal-text: #F0EDE6;
- --pedal-text-sec: #8888A0;
- --pedal-text-dim: #444458;
- --pedal-radius: 0.625rem;
- --pedal-fs-height: 80px;
-}
-
-/* ── Status Bar ────────────────────────────────────────────── */
-
-.pedal-statusbar {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 6px 12px 4px;
- background: var(--pedal-panel);
- border-bottom: 1px solid var(--pedal-border);
- flex-shrink: 0;
- gap: 8px;
- min-height: 32px;
-}
-
-.pedal-statusbar-left,
-.pedal-statusbar-right {
- display: flex;
- align-items: center;
- gap: 6px;
-}
-
-.pedal-statusbar-mid {
- display: flex;
- align-items: center;
- gap: 4px;
- flex: 1;
- justify-content: center;
-}
-
-.pedal-brand {
- font-family: 'JetBrains Mono', 'SF Mono', monospace;
- font-size: 9px;
- color: var(--pedal-text-sec);
- letter-spacing: 0.08em;
- text-transform: uppercase;
-}
-
-/* ── Mode Selector ─────────────────────────────────────────── */
-
-.mode-selector {
- display: flex;
- gap: 2px;
- background: var(--pedal-surface);
- border-radius: 6px;
- border: 1px solid var(--pedal-border);
- overflow: hidden;
-}
-
-.mode-selector-collapsed {
- display: flex;
- align-items: center;
- gap: 4px;
- padding: 4px 8px;
- cursor: pointer;
- border-radius: 5px;
- background: var(--pedal-surface);
- border: 1px solid var(--pedal-border);
- transition: background 0.15s;
-}
-
-.mode-selector-collapsed:hover {
- background: var(--pedal-border);
-}
-
-.mode-btn {
- flex: 1;
- display: flex;
- align-items: center;
- gap: 3px;
- padding: 5px 7px;
- font-size: 10px;
- font-weight: 600;
- letter-spacing: 0.04em;
- text-transform: uppercase;
- background: none;
- border: none;
- color: var(--pedal-text-dim);
- cursor: pointer;
- transition: all 0.12s;
- white-space: nowrap;
-}
-
-.mode-btn:hover {
- color: var(--pedal-text-sec);
-}
-
-.mode-btn-active {
- background: var(--pedal-amber-dim);
- color: var(--pedal-amber) !important;
-}
-
-.mode-btn-icon {
- font-size: 11px;
-}
-
-.mode-icon {
- font-size: 12px;
- color: var(--pedal-amber);
-}
-
-.mode-label {
- font-size: 10px;
- color: var(--pedal-text-sec);
- font-weight: 600;
- letter-spacing: 0.04em;
- text-transform: uppercase;
-}
-
-/* ── Badge chips in status bar ─────────────────────────────── */
-
-.pedal-badge {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- padding: 1px 5px;
- border-radius: 3px;
- font-size: 8px;
- font-weight: 700;
- letter-spacing: 0.06em;
- text-transform: uppercase;
-}
-
-.pedal-badge-amber {
- background: rgba(232, 160, 48, 0.2);
- color: var(--pedal-amber);
-}
-
-.pedal-badge-green {
- background: rgba(58, 184, 122, 0.2);
- color: var(--pedal-green);
-}
-
-.pedal-badge-red {
- background: rgba(200, 64, 64, 0.2);
- color: var(--pedal-red);
-}
-
-.pedal-badge-blue {
- background: rgba(58, 123, 168, 0.2);
- color: var(--pedal-blue);
-}
-
-/* ── Status LED dot ────────────────────────────────────────── */
-
-.pedal-led-dot {
- width: 6px;
- height: 6px;
- border-radius: 50%;
- flex-shrink: 0;
-}
-
-/* ── Footswitch Bar ────────────────────────────────────────── */
-
-.footswitch-bar {
- display: flex;
- gap: 3px;
- padding: 4px 6px 6px;
- background: var(--pedal-panel);
- border-top: 1px solid var(--pedal-border);
- flex-shrink: 0;
- justify-content: center;
-}
-
-.footswitch-slot {
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 3px;
- flex: 1;
- min-width: 0;
- max-width: 56px;
-}
-
-/* ── Scribble Strip ────────────────────────────────────────── */
-
-.scribble-strip {
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 1px;
- width: 100%;
- padding: 3px 2px;
- background: #0D0D10;
- border: 1px solid var(--pedal-border);
- border-radius: 3px;
- cursor: pointer;
- transition: border-color 0.15s;
- user-select: none;
- -webkit-tap-highlight-color: transparent;
-}
-
-.scribble-strip[data-active="true"] {
- border-color: var(--scribble-color, var(--pedal-amber));
-}
-
-.scribble-strip[data-bypassed="true"] {
- opacity: 0.5;
-}
-
-.scribble-led {
- width: 4px;
- height: 4px;
- border-radius: 50%;
- flex-shrink: 0;
- transition: opacity 0.15s;
- margin-bottom: 1px;
-}
-
-.scribble-label-wrap {
- display: flex;
- flex-direction: column;
- align-items: center;
- width: 100%;
- min-height: 22px;
- justify-content: center;
-}
-
-.scribble-label {
- font-family: 'JetBrains Mono', 'SF Mono', monospace;
- font-size: 8px;
- font-weight: 600;
- color: var(--pedal-text);
- text-align: center;
- line-height: 1.1;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- max-width: 100%;
-}
-
-.scribble-sublabel {
- font-family: 'JetBrains Mono', 'SF Mono', monospace;
- font-size: 6.5px;
- color: var(--scribble-color, var(--pedal-text-sec));
- text-align: center;
- line-height: 1;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- max-width: 100%;
- text-transform: uppercase;
- letter-spacing: 0.03em;
-}
-
-.scribble-icon {
- font-size: 9px;
- line-height: 1;
-}
-
-/* ── Footswitch Button ─────────────────────────────────────── */
-
-.footswitch-btn {
- position: relative;
- width: 42px;
- height: 42px;
- cursor: pointer;
- user-select: none;
- -webkit-tap-highlight-color: transparent;
- touch-action: manipulation;
- transition: transform 0.08s;
-}
-
-.footswitch-btn:active {
- transform: scale(0.93);
-}
-
-.footswitch-ring {
- position: absolute;
- inset: 0;
- border-radius: 50%;
- border: 2.5px solid var(--pedal-border);
- background: radial-gradient(circle at 40% 35%, #2A2A38, #141418);
- transition: border-color 0.12s, box-shadow 0.12s;
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.06);
-}
-
-.footswitch-btn-active .footswitch-ring {
- border-color: var(--fs-color, var(--pedal-green));
- box-shadow:
- 0 2px 6px rgba(0, 0, 0, 0.5),
- inset 0 1px 0 rgba(255, 255, 255, 0.06),
- 0 0 8px var(--fs-color, var(--pedal-green));
-}
-
-.footswitch-btn-bypassed .footswitch-ring {
- opacity: 0.5;
- border-color: var(--pedal-text-dim);
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
-}
-
-.footswitch-cap {
- position: absolute;
- inset: 8px;
- border-radius: 50%;
- background: radial-gradient(circle at 38% 32%, #3A3A48, #1A1A22);
- box-shadow:
- inset 0 1px 0 rgba(255, 255, 255, 0.08),
- inset 0 -1px 0 rgba(0, 0, 0, 0.3);
-}
-
-.footswitch-cap::after {
- content: '';
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- width: 8px;
- height: 8px;
- border-radius: 50%;
- background: radial-gradient(circle at 50% 35%, #5A5A6A, #2A2A38);
-}
-
-/* ── Tab bar (existing, aligned) ───────────────────────────── */
-
-.pedal-tabbar {
- display: flex;
- background: var(--pedal-panel);
- border-top: 1px solid var(--pedal-border);
- flex-shrink: 0;
-}
-
-.pedal-tab {
- flex: 1;
- padding: 8px 4px 6px;
- font-size: 9px;
- font-weight: 500;
- letter-spacing: 0.04em;
- text-align: center;
- text-transform: uppercase;
- color: var(--pedal-text-dim);
- cursor: pointer;
- border-top: 2px solid transparent;
- transition: all 0.12s;
- user-select: none;
-}
-
-.pedal-tab-active {
- color: var(--pedal-amber);
- border-top-color: var(--pedal-amber);
-}
-
-.pedal-tab-icon {
- font-size: 13px;
- display: block;
- margin-bottom: 1px;
-}
-
-/* ── Screen Area ───────────────────────────────────────────── */
-
-.pedal-screen {
- flex: 1;
- overflow: hidden;
- display: flex;
- flex-direction: column;
-}
-
-/* ── Responsive ────────────────────────────────────────────── */
-
-@media (max-width: 420px) {
- .footswitch-bar {
- padding: 3px 3px 5px;
- gap: 2px;
- }
-
- .footswitch-slot {
- max-width: 48px;
- }
-
- .footswitch-btn {
- width: 36px;
- height: 36px;
- }
-
- .footswitch-cap {
- inset: 6px;
- }
-
- .footswitch-cap::after {
- width: 6px;
- height: 6px;
- }
-
- .scribble-label {
- font-size: 7px;
- }
-
- .mode-btn {
- padding: 3px 5px;
- font-size: 9px;
- }
-
- .mode-btn-label {
- display: none;
- }
-}
-
-/* ── Pedal Shell ───────────────────────────────────────────── */
-
-.pedal-shell {
- width: 100%;
- max-width: 440px;
- margin: 0 auto;
- height: 100dvh;
- display: flex;
- flex-direction: column;
- background: var(--pedal-bg);
- color: var(--pedal-text);
- overflow: hidden;
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
-}
-
-@media (min-width: 441px) {
- .pedal-shell {
- border-left: 1px solid var(--pedal-border);
- border-right: 1px solid var(--pedal-border);
- }
-}
diff --git a/ui/src/pedal/types.ts b/ui/src/pedal/types.ts
deleted file mode 100644
index 23962f5..0000000
--- a/ui/src/pedal/types.ts
+++ /dev/null
@@ -1,164 +0,0 @@
-/**
- * Pi Multi-FX Pedal — Type Definitions
- *
- * Core types for footswitch modes, pedal state, and UI components.
- */
-
-// ── Footswitch Modes ──────────────────────────────────────────
-
-export type FootswitchMode = 'stomp' | 'preset' | 'snapshot' | 'combo' | 'transport';
-
-export const FOOTSWITCH_MODES: FootswitchMode[] = ['stomp', 'preset', 'snapshot', 'combo'];
-export const FOOTSWITCH_MODE_LABELS: Record = {
- stomp: 'Stomp',
- preset: 'Preset',
- snapshot: 'Snapshot',
- combo: 'Combo',
- transport: 'Transport',
-};
-
-// ── Scribble Strip ────────────────────────────────────────────
-
-export interface ScribbleStripData {
- /** Main label shown on the strip (uppercase track name) */
- label: string;
- /** Optional secondary line below the label */
- sublabel?: string;
- /** LED color for the footswitch ring / indicator */
- color?: ScribbleColor;
- /** Whether the footswitch is active/enabled */
- active?: boolean;
- /** Whether the block is bypassed (stomp mode) */
- bypassed?: boolean;
- /** Unique key for this footswitch */
- key: string;
- /** Optional icon */
- icon?: string;
-}
-
-export type ScribbleColor =
- | 'amber'
- | 'green'
- | 'red'
- | 'blue'
- | 'purple'
- | 'cyan'
- | 'white'
- | 'off';
-
-export const SCRIBBLE_COLORS: Record = {
- amber: '#E8A030',
- green: '#3AB87A',
- red: '#C84040',
- blue: '#3A7BA8',
- purple: '#9B59B6',
- cyan: '#1ABC9C',
- white: '#F0EDE6',
- off: '#444458',
-};
-
-// ── Footswitch Action ─────────────────────────────────────────
-
-export type FootswitchAction =
- | { type: 'toggle_block'; blockId: string }
- | { type: 'bank_up' }
- | { type: 'bank_down' }
- | { type: 'select_preset'; bank: number; program: number }
- | { type: 'recall_snapshot'; snapshotIndex: number }
- | { type: 'global_bypass' }
- | { type: 'tap_tempo' }
- | { type: 'tuner' }
- | { type: 'bank_select'; bank: number };
-
-// ── Pedal State (from API) ────────────────────────────────────
-
-export interface PedalState {
- master_volume?: number;
- bypass?: boolean;
- tuner_enabled?: boolean;
- cpu_percent?: number;
- sample_rate?: number;
- nam_loaded?: boolean;
- nam_model?: string;
- ir_loaded?: boolean;
- ir_name?: string;
- current_preset?: { name: string; bank: number; program: number };
- input_level?: number;
- output_level?: number;
- routing_mode?: string;
- routing_breakpoint?: number;
- wifi?: {
- connected: boolean;
- ssid?: string;
- ip?: string;
- signal?: number;
- hotspot_active: boolean;
- hotspot_ssid?: string;
- };
- bluetooth?: {
- powered: boolean;
- discoverable: boolean;
- midi_enabled: boolean;
- name?: string;
- address?: string;
- };
- blocks?: PedalBlock[];
-}
-
-export interface PedalBlock {
- id: number;
- fx_type: string;
- title: string;
- bypassed: boolean;
- params?: BlockParam[];
-}
-
-export interface BlockParam {
- name: string;
- key: string;
- default?: number;
- min?: number;
- max?: number;
-}
-
-// ── Preset Data ───────────────────────────────────────────────
-
-export interface PresetData {
- name: string;
- bank: number;
- program: number;
- chain?: PedalBlock[];
-}
-
-export interface BankData {
- name: string;
- number: number;
- presets: (PresetData | null)[];
-}
-
-export interface PresetListResponse {
- banks: BankData[];
-}
-
-// ── Snapshot ──────────────────────────────────────────────────
-
-export interface SnapshotData {
- name: string;
- index: number;
- /** Block bypass states at snapshot time */
- blockStates: Record;
- /** Parameter values at snapshot time (blockId -> paramKey -> value) */
- paramValues: Record>;
-}
-
-// ── WebSocket Messages ────────────────────────────────────────
-
-export type WsMessage =
- | { type: 'connected'; state: PedalState }
- | { type: 'state'; state: PedalState }
- | { type: 'preset_changed'; state: PedalState }
- | { type: 'bypass_changed'; bypass: boolean }
- | { type: 'tuner_changed'; tuner_enabled: boolean }
- | { type: 'routing_changed'; routing_mode: string; routing_breakpoint: number }
- | { type: 'model_loaded' }
- | { type: 'ir_loaded' };
diff --git a/ui/tsconfig.app.json b/ui/tsconfig.app.json
deleted file mode 100644
index 9918c77..0000000
--- a/ui/tsconfig.app.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "compilerOptions": {
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
- "target": "es2023",
- "lib": ["ES2023", "DOM"],
- "module": "esnext",
- "types": ["vite/client"],
- "skipLibCheck": true,
- "ignoreDeprecations": "6.0",
-
- /* Bundler mode */
- "moduleResolution": "bundler",
- "allowImportingTsExtensions": true,
- "verbatimModuleSyntax": true,
- "moduleDetection": "force",
- "noEmit": true,
- "jsx": "react-jsx",
- "baseUrl": ".",
- "paths": {
- "@/*": ["./src/*"]
- },
-
- /* Linting */
- "noUnusedLocals": true,
- "noUnusedParameters": true,
- "erasableSyntaxOnly": true,
- "noFallthroughCasesInSwitch": true
- },
- "include": ["src"]
-}
diff --git a/ui/tsconfig.json b/ui/tsconfig.json
deleted file mode 100644
index 1ffef60..0000000
--- a/ui/tsconfig.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "files": [],
- "references": [
- { "path": "./tsconfig.app.json" },
- { "path": "./tsconfig.node.json" }
- ]
-}
diff --git a/ui/tsconfig.node.json b/ui/tsconfig.node.json
deleted file mode 100644
index d3c52ea..0000000
--- a/ui/tsconfig.node.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "compilerOptions": {
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
- "target": "es2023",
- "lib": ["ES2023"],
- "module": "esnext",
- "types": ["node"],
- "skipLibCheck": true,
-
- /* Bundler mode */
- "moduleResolution": "bundler",
- "allowImportingTsExtensions": true,
- "verbatimModuleSyntax": true,
- "moduleDetection": "force",
- "noEmit": true,
-
- /* Linting */
- "noUnusedLocals": true,
- "noUnusedParameters": true,
- "erasableSyntaxOnly": true,
- "noFallthroughCasesInSwitch": true
- },
- "include": ["vite.config.ts"]
-}
diff --git a/ui/vite.config.ts b/ui/vite.config.ts
deleted file mode 100644
index 8be321e..0000000
--- a/ui/vite.config.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react'
-import tailwindcss from '@tailwindcss/vite'
-import path from 'path'
-
-export default defineConfig({
- base: '/ui/',
- plugins: [react(), tailwindcss()],
- resolve: {
- alias: {
- '@': path.resolve(__dirname, './src'),
- },
- },
- server: {
- proxy: {
- '/api': 'http://pedal.local:8080',
- '/ws': {
- target: 'ws://pedal.local:8080',
- ws: true,
- },
- },
- },
-})