diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5c5f667 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,38 @@ +name: CI + +on: + pull_request: + push: + branches: [main] + +concurrency: + group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + typecheck-and-test: + name: Typecheck & test + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "20.x" + cache: "npm" + + - name: Install dependencies + run: npm ci + + - name: Typecheck + run: npm run typecheck + + - name: Test + run: npm test + + - name: Build + run: npm run build diff --git a/.gitignore b/.gitignore index 19d82a0..9584a4a 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ coverage *.swp *.swo *~ +.hallmark # Claude diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..663252f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,30 @@ +# Changelog + +## 0.3.0 + +Aligned with **@chartgpu/chartgpu ^0.3.6** and modern React/TypeScript tooling. + +### Dependencies + +- Peer: `@chartgpu/chartgpu` **^0.3.6** (was ^0.2.8) +- Peer: React **≥18** (dev/tested on **React 19.2**) +- Dev: **TypeScript 7.0**, Vite 7, Vitest 4, `@types/react` 19 + +### API + +- `ChartGPUHandle.appendData` accepts optional `{ maxPoints }` for FIFO / fixed-capacity streaming (ChartGPU 0.3.x) +- `ChartGPUHandle.setZoomRange` passes optional `source` through to core +- `CartesianSeriesData` allows `null` gaps (matches core) +- Expanded type re-exports: heatmap, band, errorBar, impulse, OHLC, 3D series, `ZoomChangeSourceKind`, etc. +- New exported type: `ChartGPUAppendDataOptions` + +### Tooling + +- Build: Vite (ESM bundle) + `tsc` declaration emit + (`vite-plugin-dts` is incompatible with TypeScript 7’s slim package API) +- Package name restored to **`chartgpu-react`** for npmjs.org (GitHub Packages still scopes at publish) +- Test coverage for handle/hooks 0.3.x: `appendData`/`maxPoints`, `setZoomRange` source, external render, `useConnectCharts`, `useGPUContext`, `gpuContext` create path, `onDataAppend`/`onDeviceLost`, export smoke + +### Examples + +- Streaming multi-chart demos use `appendData(..., { maxPoints })` diff --git a/README.md b/README.md index af9629e..a7e1abe 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,9 @@ - **`ChartGPU` component (recommended)**: async create/dispose lifecycle + debounced `ResizeObserver` sizing - **Event props**: `onClick`, `onCrosshairMove`, `onZoomChange`, `onDataAppend`, `onDeviceLost`, etc. -- **Imperative `ref` API**: `ChartGPUHandle` (`getChart`, `getContainer`, `appendData`, `setOption`, `setZoomRange`, `setInteractionX`, `getInteractionX`, `hitTest`, `needsRender`, `renderFrame`, `getRenderMode`, `setRenderMode`) +- **Imperative `ref` API**: `ChartGPUHandle` (`getChart`, `getContainer`, `appendData` with optional `{ maxPoints }` FIFO, `setOption`, `setZoomRange`, `setInteractionX`, `getInteractionX`, `hitTest`, `needsRender`, `renderFrame`, `getRenderMode`, `setRenderMode`) - **Hooks**: `useChartGPU(...)`, `useGPUContext()`, `useConnectCharts(..., syncOptions?)` +- **Multi-chart + streaming**: share a `GPUDevice` via `gpuContext` / `useGPUContext`, sync with `useConnectCharts`, stream with `appendData(..., { maxPoints })` - **Helper re-exports (from `@chartgpu/chartgpu`)**: `createChart`, `connectCharts`, `createPipelineCache`, `getPipelineCacheStats`, `destroyPipelineCache`, `createAnnotationAuthoring` ## Quick start @@ -70,13 +71,16 @@ function MyChart() { npm install chartgpu-react @chartgpu/chartgpu react react-dom ``` +Peer dependency: **`@chartgpu/chartgpu` ^0.3.6** (aligned with this package’s 0.3.x line). + ### Requirements -- React 18.0.0 or higher +- **React 18 or 19** (`react` / `react-dom` ≥ 18) +- **TypeScript 5+** for consumers (this package is built and typechecked with **TypeScript 7**) - Browser with WebGPU support: - Chrome/Edge 113+ - Safari 18+ - - Firefox (not yet supported) + - Firefox: Windows 114+, Mac 145+, Linux nightly Check browser compatibility at [caniuse.com/webgpu](https://caniuse.com/webgpu). @@ -135,6 +139,40 @@ disconnect(); If you prefer a hook-driven approach, you can use `onReady` (or `useChartGPU`) to capture instances, then call `useConnectCharts(...)` once both are available. +### Streaming append with FIFO window (`maxPoints`) + +```tsx +import { useEffect, useRef } from 'react'; +import { ChartGPU } from 'chartgpu-react'; +import type { ChartGPUHandle } from 'chartgpu-react'; + +function StreamingChart() { + const ref = useRef(null); + const xRef = useRef(0); + + useEffect(() => { + const id = window.setInterval(() => { + const x = xRef.current++; + ref.current?.appendData(0, [{ x, y: Math.sin(x * 0.05) }], { maxPoints: 50_000 }); + }, 16); + return () => window.clearInterval(id); + }, []); + + return ( + + ); +} +``` + ### External render mode (app-owned render loop) ```tsx diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md index a9d7d6a..02df990 100644 --- a/docs/GETTING_STARTED.md +++ b/docs/GETTING_STARTED.md @@ -10,8 +10,9 @@ npm install chartgpu-react @chartgpu/chartgpu react react-dom ## Requirements -- **React**: 18+ -- **WebGPU**: a browser with `navigator.gpu` support (Chrome/Edge 113+, Safari 18+) +- **@chartgpu/chartgpu**: ^0.3.6 (peer) +- **React**: 18 or 19 +- **WebGPU**: a browser with `navigator.gpu` support (Chrome/Edge 113+, Safari 18+, modern Firefox) If WebGPU is not available, chart creation will fail. @@ -65,7 +66,27 @@ See [Streaming recipe](./recipes/streaming.md). ## React 18 StrictMode -In development, React 18 StrictMode intentionally runs effects twice (mount → unmount → mount). `ChartGPU` and `useChartGPU` are written to be safe under this behavior (async create + cleanup ordering). +In development, React 18 StrictMode intentionally runs effects twice (mount → unmount → mount). `ChartGPU`, `useChartGPU`, and `useGPUContext` are written to be safe under this behavior: + +- **`ChartGPU` / `useChartGPU`**: async create + cleanup ordering (dispose if unmounted before create resolves). +- **`useGPUContext`**: a shared init promise so StrictMode remount reuses one adapter/device/`PipelineCache` acquisition instead of requesting a second device. + +## Testing (unit coverage map) + +Unit tests live under `src/__tests__/` (Vitest + jsdom). They mock `@chartgpu/chartgpu` and do **not** require a real WebGPU device (except `useGPUContext`, which stubs `navigator.gpu`). + +| Area | File | +|------|------| +| Create / `setOption` race (issue #16) | `src/__tests__/ChartGPU.test.tsx`, `src/__tests__/useChartGPU.test.tsx` | +| Handle `appendData` + `{ maxPoints }`, `setZoomRange` source, external render | `src/__tests__/ChartGPU.test.tsx` | +| Handle smoke (`getChart`, `setOption`, interaction X, `hitTest`) | `src/__tests__/ChartGPU.test.tsx` | +| Event props (`onDataAppend`, `onDeviceLost`) | `src/__tests__/ChartGPU.test.tsx` | +| `gpuContext` → `ChartGPU.create` third arg | `src/__tests__/ChartGPU.test.tsx`, `src/__tests__/useChartGPU.test.tsx` | +| `useConnectCharts` | `src/__tests__/useConnectCharts.test.tsx` | +| `useGPUContext` | `src/__tests__/useGPUContext.test.tsx` | +| Public export surface | `src/__tests__/exports.test.ts` | + +Run: `npm test`, `npm run typecheck`, `npm run build`. ## Next steps diff --git a/docs/api/hooks.md b/docs/api/hooks.md index 7964552..2b11f86 100644 --- a/docs/api/hooks.md +++ b/docs/api/hooks.md @@ -113,8 +113,9 @@ function useGPUContext(): { - On mount, requests a `GPUAdapter` (high-performance preference) and `GPUDevice`, then creates a `PipelineCache`. - All fields are `null` until initialization completes. `isReady` becomes `true` once both `adapter` and `device` are available. - If WebGPU is not supported or adapter/device acquisition fails, `error` is set and other fields remain `null`. -- Safe in React 18 StrictMode dev (uses a ref guard to prevent double-initialization). -- Initialization runs once on mount and cannot be re-triggered. +- Safe in React 18 StrictMode dev: a **shared in-flight/completed init promise** ensures a single adapter/device/`PipelineCache` acquisition. The first effect may be cancelled by StrictMode’s simulated unmount; the second effect re-subscribes to the **same** promise and applies the result (it does **not** call `requestAdapter` again). +- Initialization runs once per hook instance and cannot be re-triggered. +- **Lifecycle / resource ownership:** the hook does **not** call `GPUDevice.destroy()` or `destroyPipelineCache` on unmount. It is intended for a **long-lived dashboard parent**. Mounting briefly and unmounting mid-init can leave a native device alive until page unload (auto-destroy would race with StrictMode remount, which reuses the shared promise). Keep `useGPUContext()` mounted for the process lifetime of the shared charts, or manage teardown yourself if you truly need a short-lived context. ### Usage with `` diff --git a/examples/assets/chartgpu.png b/examples/assets/chartgpu.png new file mode 100644 index 0000000..5fa0e5b Binary files /dev/null and b/examples/assets/chartgpu.png differ diff --git a/examples/index.html b/examples/index.html index 446e710..0723917 100644 --- a/examples/index.html +++ b/examples/index.html @@ -3,93 +3,184 @@ - ChartGPU React - Examples - - - -
-

ChartGPU React

-

WebGPU-powered charting for React applications

- -
-
- + diff --git a/examples/main.tsx b/examples/main.tsx index 9be2a56..8373a13 100644 --- a/examples/main.tsx +++ b/examples/main.tsx @@ -1,11 +1,8 @@ -import React, { useEffect, useMemo, useRef, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from 'react'; import { createRoot } from 'react-dom/client'; -import { ChartGPU, connectCharts, createAnnotationAuthoring, useGPUContext, useConnectCharts } from '../src'; +import { ChartGPU, useGPUContext, useConnectCharts } from '../src'; import type { - ChartGPUCrosshairMovePayload, ChartGPUCreateContext, - ChartGPUDataAppendPayload, - ChartGPUDeviceLostPayload, ChartGPUHandle, ChartGPUInstance, ChartGPUOptions, @@ -18,786 +15,871 @@ type Candle = Extract< { timestamp: number; open: number; close: number; low: number; high: number } >; +type ExampleStatus = 'idle' | 'loading' | 'ok' | 'error'; + +const DEMO_THEME = { + backgroundColor: '#05060a', + gridLineColor: 'rgba(255,255,255,0.06)', + axisLineColor: 'rgba(224,224,224,0.14)', + axisTickColor: 'rgba(224,224,224,0.22)', + textColor: 'rgba(224,224,224,0.82)', +} as const; + function generateLineData(points: number, seed: number): Array<{ x: number; y: number }> { const data: Array<{ x: number; y: number }> = []; for (let i = 0; i < points; i++) { - const x = i; - const y = Math.sin(i * 0.02 + seed) * 50 + Math.cos(i * 0.01 + seed) * 10; - data.push({ x, y }); + data.push({ + x: i, + y: Math.sin(i * 0.02 + seed) * 50 + Math.cos(i * 0.01 + seed) * 10, + }); } return data; } -function CrosshairMoveExample() { - const [chart, setChart] = useState(null); - const [crosshairX, setCrosshairX] = useState(null); +function ExampleCard(props: { + id: string; + index: string; + title: string; + description: string; + tags?: string[]; + status?: ExampleStatus; + statusLabel?: string; + meta?: ReactNode; + stack?: boolean; + featured?: boolean; + tall?: boolean; + bleed?: boolean; + children: ReactNode; +}) { + const { + id, + index, + title, + description, + tags = [], + status = 'idle', + statusLabel, + meta, + stack, + featured, + tall, + bleed, + children, + } = props; + + const statusClass = + status === 'ok' + ? 'example-status example-status--ok' + : status === 'error' + ? 'example-status example-status--error' + : status === 'loading' + ? 'example-status example-status--loading' + : 'example-status'; + + const resolvedLabel = + statusLabel ?? + (status === 'ok' + ? 'Live' + : status === 'loading' + ? 'Initializing…' + : status === 'error' + ? 'Unavailable' + : 'Ready'); + + const className = [ + 'example', + featured ? 'example--featured' : '', + tall ? 'example--tall' : '', + ] + .filter(Boolean) + .join(' '); + + const canvasClass = [ + 'example-canvas', + stack ? 'example-canvas--stack' : '', + bleed ? 'example-canvas--bleed' : '', + ] + .filter(Boolean) + .join(' '); - const options: ChartGPUOptions = useMemo( - () => ({ - series: [ - { - type: 'line', - name: 'Signal', - data: generateLineData(2000, 0.3), - lineStyle: { width: 2, color: '#667eea' }, - areaStyle: { color: 'rgba(102, 126, 234, 0.15)' }, - }, - ], - xAxis: { type: 'value' }, - yAxis: { type: 'value' }, - tooltip: { show: true, trigger: 'axis' }, - dataZoom: [{ type: 'inside' }, { type: 'slider' }], - grid: { left: 60, right: 40, top: 40, bottom: 40 }, - }), - [] + return ( +
+
+
+

{index}

+

{title}

+

{description}

+
+
+
+
+ + {meta ?
{meta}
: null} + + {tags.length > 0 ? ( +
+ {tags.map((tag) => ( + + {tag} + + ))} +
+ ) : null} + +
{children}
+
); +} +function ChartHost(props: { children: ReactNode; style?: React.CSSProperties }) { return ( -
-

Crosshair move + dataZoom

- -
- Features: 'crosshairMove' event, tooltip, inside+slider zoom -
- Crosshair X:{' '} - {crosshairX === null ? none : crosshairX.toFixed(2)} -
- {chart && !chart.disposed && ( - ✓ Chart Active - )} -
- -
- setCrosshairX(p.x)} - theme="dark" - /> -
+
+ {props.children}
); } -function ConnectedChartsExample() { - const [topChart, setTopChart] = useState(null); - const [bottomChart, setBottomChart] = useState(null); +// ─── 3D terrain + LiDAR (hero plate) ───────────────────────────────────────── + +const SURF_COLS = 96; +const SURF_ROWS = 64; +const SEED_CLOUD = 14_000; - const topOptions: ChartGPUOptions = useMemo( +function heightAt(u: number, v: number, t: number): number { + const g1 = Math.exp(-((u - 0.25) ** 2 + (v + 0.15) ** 2) / 0.12); + const g2 = 0.65 * Math.exp(-((u + 0.35) ** 2 + (v - 0.3) ** 2) / 0.09); + const ridge = 0.2 * Math.sin((u + t) * 5) * Math.cos(v * 4); + return g1 + g2 + ridge - 0.15 * (u * u + v * v); +} + +function fillTerrain(y: Float32Array, columns: number, rows: number, t = 0): void { + for (let j = 0; j < rows; j++) { + for (let i = 0; i < columns; i++) { + const u = (i / Math.max(1, columns - 1)) * 2 - 1; + const v = (j / Math.max(1, rows - 1)) * 2 - 1; + y[j * columns + i] = heightAt(u, v, t); + } + } +} + +function makeSeedCloud( + n: number, + yField: Float32Array, + columns: number, + rows: number, + xStart: number, + xStep: number, + zStart: number, + zStep: number +) { + const x = new Float32Array(n); + const y = new Float32Array(n); + const z = new Float32Array(n); + const value = new Float32Array(n); + for (let i = 0; i < n; i++) { + const ii = Math.floor(Math.random() * columns); + const jj = Math.floor(Math.random() * rows); + const wx = xStart + ii * xStep; + const wz = zStart + jj * zStep; + const h = yField[jj * columns + ii]! + (Math.random() - 0.5) * 0.08; + x[i] = wx + (Math.random() - 0.5) * 0.04; + y[i] = h + 0.05; + z[i] = wz + (Math.random() - 0.5) * 0.04; + value[i] = h; + } + return { x, y, z, value }; +} + +function Hero3DExample() { + const plateRef = useRef(null); + const [ready, setReady] = useState(false); + const chartRef = useRef(null); + const yFieldRef = useRef(new Float32Array(SURF_COLS * SURF_ROWS)); + const surfaceXStartRef = useRef(-1); + const streamTRef = useRef(0); + + const surfaceData = useMemo(() => { + fillTerrain(yFieldRef.current, SURF_COLS, SURF_ROWS, 0); + return { + xStart: -1, + xStep: 2 / Math.max(1, SURF_COLS - 1), + zStart: -1, + zStep: 2 / Math.max(1, SURF_ROWS - 1), + columns: SURF_COLS, + rows: SURF_ROWS, + y: yFieldRef.current, + }; + }, []); + + const cloudData = useMemo(() => { + const arrays = makeSeedCloud( + SEED_CLOUD, + yFieldRef.current, + SURF_COLS, + SURF_ROWS, + surfaceData.xStart, + surfaceData.xStep, + surfaceData.zStart, + surfaceData.zStep + ); + return arrays; + }, [surfaceData]); + + const options: ChartGPUOptions = useMemo( () => ({ + coordinateSystem: 'cartesian3d', + theme: DEMO_THEME, + legend: { show: false }, + tooltip: { show: true }, + // Wheel zoom would capture the page scroll on a full-viewport hero. + interaction3d: { orbit: true, pan: true, zoom: false }, + camera: { + type: 'perspective', + eye: [2.4, 1.6, 2.2], + target: [0, 0.15, 0], + up: [0, 1, 0], + fovY: Math.PI / 4, + }, + axes3d: { + showBox: true, + showGrid: true, + labelMode: 'auto', + x: { name: 'X (m)', tickCount: 5 }, + y: { name: 'Height', tickCount: 5 }, + z: { name: 'Y (m)', tickCount: 5 }, + }, series: [ { - type: 'line', - name: 'Top', - data: generateLineData(1000, 0.1), - lineStyle: { width: 2, color: '#4facfe' }, + type: 'surface3d', + name: 'Terrain', + data: surfaceData, + colormap: 'viridis', + lighting: 0.72, + opacity: 1, + contours: { + show: true, + levels: 10, + color: '#e2e8f0', + width: 1.5, + opacity: 0.85, + }, }, - ], - xAxis: { type: 'value' }, - yAxis: { type: 'value' }, - tooltip: { show: true, trigger: 'axis' }, - grid: { left: 60, right: 40, top: 40, bottom: 40 }, - }), - [] - ); - - const bottomOptions: ChartGPUOptions = useMemo( - () => ({ - series: [ { - type: 'line', - name: 'Bottom', - data: generateLineData(1000, 1.2), - lineStyle: { width: 2, color: '#f093fb' }, - areaStyle: { color: 'rgba(240, 147, 251, 0.12)' }, + type: 'pointCloud3d', + name: 'LiDAR', + data: cloudData, + pointStyle: { size: 2.5, color: '#38bdf8', opacity: 0.92 }, + colorBy: { colormap: 'plasma', min: -0.2, max: 1.2 }, }, ], - xAxis: { type: 'value' }, - yAxis: { type: 'value' }, - tooltip: { show: true, trigger: 'axis' }, - grid: { left: 60, right: 40, top: 40, bottom: 40 }, }), - [] + [surfaceData, cloudData] ); + const onReady = useCallback((chart: ChartGPUInstance) => { + chart.setCamera?.({ + type: 'perspective', + eye: [2.4, 1.6, 2.2], + target: [0, 0.15, 0], + up: [0, 1, 0], + fovY: Math.PI / 4, + }); + setReady(true); + plateRef.current?.classList.add('is-ready'); + }, []); + + // Live surface strip (always on for the hero) useEffect(() => { - if (!topChart || topChart.disposed) return; - if (!bottomChart || bottomChart.disposed) return; + if (!ready) return; + + let raf = 0; + const tick = () => { + const c = chartRef.current?.getChart() ?? null; + if (c && !c.disposed && c.updateSurface3D) { + streamTRef.current += 0.006; + const col = new Float32Array(SURF_ROWS); + const nextI = SURF_COLS; + const uEdge = + -1 + (nextI / Math.max(1, SURF_COLS - 1)) * 2 + streamTRef.current * 0.08; + for (let r = 0; r < SURF_ROWS; r++) { + const v = (r / Math.max(1, SURF_ROWS - 1)) * 2 - 1; + col[r] = heightAt(uEdge, v, streamTRef.current); + } + const yField = yFieldRef.current; + for (let r = 0; r < SURF_ROWS; r++) { + const row = r * SURF_COLS; + yField.copyWithin(row, row + 1, row + SURF_COLS); + yField[row + SURF_COLS - 1] = col[r]!; + } + const dx = surfaceData.xStep; + surfaceXStartRef.current += dx; + c.updateSurface3D(0, { + mode: 'appendColumns', + columns: 1, + y: col, + scrollX: true, + }); + const cam = c.getCamera?.(); + if (cam?.eye && cam.target) { + c.setCamera?.({ + eye: [cam.eye[0]! + dx, cam.eye[1]!, cam.eye[2]!], + target: [cam.target[0]! + dx, cam.target[1]!, cam.target[2]!], + }); + } + } + raf = requestAnimationFrame(tick); + }; + raf = requestAnimationFrame(tick); + return () => cancelAnimationFrame(raf); + }, [ready, surfaceData.xStep]); - const disconnect = connectCharts([topChart, bottomChart]); - return () => disconnect(); - }, [topChart, bottomChart]); + // Bind plate ref for is-ready class + useEffect(() => { + plateRef.current = document.getElementById('hero'); + }, []); return ( -
-

connectCharts (sync crosshair)

- -
- Features: Shared interaction-x between two charts via connectCharts -
- Try it: Move your mouse over either chart -
- -
- -
- + <> +
Initializing WebGPU 3D…
+
+

cartesian3d

+

surface3d + pointCloud3d

+

+ Drag to orbit · scroll the page to leave · live updateSurface3D strip +

-
+ + ); } -function SyncedDashboardExample() { - const { adapter, device, pipelineCache, isReady, error } = useGPUContext(); - - const [chartA, setChartA] = useState(null); - const [chartB, setChartB] = useState(null); - const [chartC, setChartC] = useState(null); - - // Sync crosshair and zoom across all three charts - useConnectCharts([chartA, chartB, chartC], { syncZoom: true }); - - const optionsA: ChartGPUOptions = useMemo( - () => ({ - series: [ - { - type: 'line', - name: 'Series A', - data: generateLineData(500, 0.5), - lineStyle: { width: 2, color: '#4facfe' }, - }, - ], - xAxis: { type: 'value' }, - yAxis: { type: 'value' }, - tooltip: { show: true, trigger: 'axis' }, - dataZoom: [{ type: 'inside' }], - grid: { left: 60, right: 40, top: 40, bottom: 30 }, - }), - [] - ); +// ─── 3D helix point cloud ──────────────────────────────────────────────────── + +function makeHelixCloud(n: number) { + const x = new Float32Array(n); + const y = new Float32Array(n); + const z = new Float32Array(n); + const value = new Float32Array(n); + for (let i = 0; i < n; i++) { + const t = i / n; + const ang = t * Math.PI * 10; + const r = 0.25 + t * 1.35; + const nx = (Math.random() - 0.5) * 0.12; + const ny = (Math.random() - 0.5) * 0.12; + const nz = (Math.random() - 0.5) * 0.12; + x[i] = Math.cos(ang) * r + nx; + y[i] = (t - 0.5) * 2.8 + ny; + z[i] = Math.sin(ang) * r + nz; + value[i] = Math.hypot(x[i]!, z[i]!); + } + return { x, y, z, value }; +} - const optionsB: ChartGPUOptions = useMemo( - () => ({ - series: [ - { - type: 'line', - name: 'Series B', - data: generateLineData(500, 2.1), - lineStyle: { width: 2, color: '#f093fb' }, - areaStyle: { color: 'rgba(240, 147, 251, 0.12)' }, - }, - ], - xAxis: { type: 'value' }, - yAxis: { type: 'value' }, - tooltip: { show: true, trigger: 'axis' }, - dataZoom: [{ type: 'inside' }], - grid: { left: 60, right: 40, top: 40, bottom: 30 }, - }), - [] - ); +function PointCloud3DExample() { + const [ready, setReady] = useState(false); + const POINT_COUNT = 80_000; + const cloud = useMemo(() => makeHelixCloud(POINT_COUNT), []); - const optionsC: ChartGPUOptions = useMemo( + const options: ChartGPUOptions = useMemo( () => ({ + coordinateSystem: 'cartesian3d', + theme: DEMO_THEME, + legend: { show: false }, + tooltip: { show: true }, + camera: { type: 'perspective' }, + axes3d: { + showBox: true, + showGrid: true, + labelMode: 'auto', + x: { name: 'X' }, + y: { name: 'Y' }, + z: { name: 'Z' }, + }, series: [ { - type: 'line', - name: 'Series C', - data: generateLineData(500, 4.0), - lineStyle: { width: 2, color: '#40d17c' }, + type: 'pointCloud3d', + name: 'Helix', + data: cloud, + pointStyle: { size: 2.2, color: '#38bdf8', opacity: 0.9 }, + colorBy: { colormap: 'viridis', min: 0, max: 1.8 }, }, ], - xAxis: { type: 'value' }, - yAxis: { type: 'value' }, - tooltip: { show: true, trigger: 'axis' }, - dataZoom: [{ type: 'inside' }], - grid: { left: 60, right: 40, top: 40, bottom: 30 }, }), - [] - ); - - if (error) return ( -
-

Synced dashboard (shared GPU + useConnectCharts)

-
- WebGPU not supported: {error.message} -
-
- ); - - if (!isReady) return ( -
-

Synced dashboard (shared GPU + useConnectCharts)

-
Initializing GPU...
-
+ [cloud] ); - const gpuContext = { adapter: adapter!, device: device!, pipelineCache: pipelineCache! }; - return ( -
-

Synced dashboard (shared GPU + useConnectCharts)

- -
- Features: useGPUContext() + useConnectCharts() +{' '} - gpuContext prop -
- Try it: Move crosshair or zoom on any chart — all three stay in sync -
- -
- -
+ + -
- setReady(true)} /> -
-
+ + ); } -function StreamingSyncedDashboardExample() { - const { adapter, device, pipelineCache, isReady, error } = useGPUContext(); +// ─── Scatter density ───────────────────────────────────────────────────────── - const [chartA, setChartA] = useState(null); - const [chartB, setChartB] = useState(null); - const [chartC, setChartC] = useState(null); - - const refA = useRef(null); - const refB = useRef(null); - const refC = useRef(null); +function generateScatterPoints(count: number, seed: number): ScatterPointTuple[] { + const mulberry32 = (a: number) => () => { + a |= 0; + a = (a + 0x6d2b79f5) | 0; + let t = Math.imul(a ^ (a >>> 15), 1 | a); + t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; + return ((t ^ (t >>> 14)) >>> 0) / 4294967296; + }; - // Sync crosshair and zoom across all three charts - useConnectCharts([chartA, chartB, chartC], { syncZoom: true }); + const rand = mulberry32(Math.floor(seed * 1_000_000)); + const normal = () => { + const u1 = Math.max(1e-12, rand()); + const u2 = rand(); + const r = Math.sqrt(-2.0 * Math.log(u1)); + const theta = 2.0 * Math.PI * u2; + return r * Math.cos(theta); + }; + const clamp = (v: number, lo: number, hi: number) => Math.min(hi, Math.max(lo, v)); - const optionsA: ChartGPUOptions = useMemo( - () => ({ - autoScroll: true, - series: [ - { - type: 'line', - name: 'latency(ms)', - data: generateLineData(200, 0.1), - lineStyle: { width: 2, color: '#4facfe' }, - }, - ], - xAxis: { type: 'value' }, - yAxis: { type: 'value' }, - tooltip: { show: true, trigger: 'axis' }, - dataZoom: [{ type: 'inside', start: 70, end: 100 }], - grid: { left: 60, right: 40, top: 40, bottom: 30 }, - }), - [] - ); + const points: ScatterPointTuple[] = []; + for (let i = 0; i < count; i++) { + const blob = rand() < 0.55 ? 0 : rand() < 0.7 ? 1 : 2; + const centers = [ + [30, 55, 9, 11], + [68, 38, 6, 8], + [50, 72, 5, 4], + ] as const; + const [cx, cy, sx, sy] = centers[blob]!; + points.push([clamp(cx + normal() * sx, 0, 100), clamp(cy + normal() * sy, 0, 100)]); + } + return points; +} - const optionsB: ChartGPUOptions = useMemo( - () => ({ - autoScroll: true, - series: [ - { - type: 'line', - name: 'throughput', - data: generateLineData(200, 1.7), - lineStyle: { width: 2, color: '#f093fb' }, - areaStyle: { color: 'rgba(240, 147, 251, 0.12)' }, - }, - ], - xAxis: { type: 'value' }, - yAxis: { type: 'value' }, - tooltip: { show: true, trigger: 'axis' }, - dataZoom: [{ type: 'inside', start: 70, end: 100 }], - grid: { left: 60, right: 40, top: 40, bottom: 30 }, - }), - [] - ); +function ScatterDensityExample() { + const POINT_COUNT = 500_000; + const scatterData = useMemo(() => generateScatterPoints(POINT_COUNT, 0.42), []); + const [ready, setReady] = useState(false); - const optionsC: ChartGPUOptions = useMemo( + const options: ChartGPUOptions = useMemo( () => ({ - autoScroll: true, + theme: DEMO_THEME, series: [ { - type: 'line', - name: 'errors', - data: generateLineData(200, 3.2), - lineStyle: { width: 2, color: '#ff6b6b' }, + type: 'scatter', + name: 'Density', + data: scatterData, + mode: 'density', + binSize: 2, + densityColormap: 'inferno', + densityNormalization: 'log', + sampling: 'none', }, ], xAxis: { type: 'value' }, yAxis: { type: 'value' }, tooltip: { show: true, trigger: 'axis' }, - dataZoom: [{ type: 'inside', start: 70, end: 100 }], - grid: { left: 60, right: 40, top: 40, bottom: 30 }, + dataZoom: [{ type: 'inside' }], + grid: { left: 56, right: 28, top: 28, bottom: 40 }, }), - [] - ); - - // Stream data into all three charts via refs - const xRef = useRef(200); - useEffect(() => { - const timer = window.setInterval(() => { - const x = xRef.current++; - refA.current?.appendData(0, [{ x, y: 40 + Math.sin(x * 0.03) * 25 + Math.random() * 5 }]); - refB.current?.appendData(0, [{ x, y: 55 + Math.cos(x * 0.02) * 22 + Math.random() * 6 }]); - refC.current?.appendData(0, [{ x, y: 10 + Math.abs(Math.sin(x * 0.05)) * 8 + Math.random() * 3 }]); - }, 120); - - return () => window.clearInterval(timer); - }, []); - - if (error) return ( -
-

Streaming synced dashboard (shared GPU + useConnectCharts + appendData)

-
- WebGPU not supported: {error.message} -
-
- ); - - if (!isReady) return ( -
-

Streaming synced dashboard (shared GPU + useConnectCharts + appendData)

-
Initializing GPU...
-
+ [scatterData] ); - const gpuContext = { adapter: adapter!, device: device!, pipelineCache: pipelineCache! }; - return ( -
-

Streaming synced dashboard (shared GPU + useConnectCharts + appendData)

- -
- Features: useGPUContext() + useConnectCharts() +{' '} - appendData streaming -
- Try it: Move crosshair or zoom on any chart while data streams — all three stay in sync -
- -
- -
- -
+ + setReady(true)} /> -
-
+ + ); } -function ExternalRenderModeExample() { - const ref = useRef(null); - const [mode, setMode] = useState<'auto' | 'external'>('external'); +// ─── Live spectrogram ──────────────────────────────────────────────────────── + +const TIME_BINS = 256; +const FREQ_BINS = 128; +const DT = 0.02; +const DF = 8; + +function fillSpectrogramColumn(column: Float32Array, t: number): void { + const rows = column.length; + for (let j = 0; j < rows; j++) { + const fNorm = j / Math.max(1, rows - 1); + const chirp = 0.15 + 0.7 * (0.5 + 0.5 * Math.sin(t * 0.7)); + const main = Math.exp(-((fNorm - chirp) ** 2) / 0.0015); + const harm = 0.45 * Math.exp(-((fNorm - chirp * 0.55) ** 2) / 0.002); + const noise = 0.04 * Math.random(); + column[j] = -100 + Math.min(1, main + harm + noise) * 100; + } +} + +function SpectrogramExample() { + const chartRef = useRef(null); + const [ready, setReady] = useState(false); + const liveT = useRef(0); + const z = useMemo(() => { + const buf = new Float32Array(TIME_BINS * FREQ_BINS); + buf.fill(-100); + return buf; + }, []); - const initial = useMemo(() => generateLineData(300, 0.9), []); - const lastXRef = useRef(initial.length); + const heatmapData = useMemo( + () => ({ + xStart: 0, + xStep: DT, + yStart: 20, + yStep: DF, + columns: TIME_BINS, + rows: FREQ_BINS, + z, + }), + [z] + ); const options: ChartGPUOptions = useMemo( () => ({ - renderMode: 'external', - autoScroll: true, + theme: DEMO_THEME, + animation: { duration: 0 }, + grid: { left: 64, right: 24, top: 28, bottom: 48 }, + xAxis: { type: 'value', name: 'Time (s)' }, + yAxis: { type: 'value', name: 'Frequency (Hz)' }, + tooltip: { show: true, trigger: 'item' }, series: [ { - type: 'line', - name: 'External loop', - data: initial, - lineStyle: { width: 2, color: '#ffd166' }, + type: 'heatmap', + name: 'Spectrogram', + data: heatmapData, + colormap: 'viridis', + zMin: -100, + zMax: 0, + opacity: 1, + cellAnchor: 'corner', + nullHandling: 'transparent', }, ], - xAxis: { type: 'value' }, - yAxis: { type: 'value' }, - tooltip: { show: true, trigger: 'axis' }, - dataZoom: [{ type: 'inside', start: 70, end: 100 }, { type: 'slider', start: 70, end: 100 }], - grid: { left: 60, right: 40, top: 40, bottom: 40 }, }), - [initial] + [heatmapData] ); - // App-owned render loop (requestAnimationFrame). Only runs in external mode. - useEffect(() => { - if (mode !== 'external') return; - - let rafId = 0; - const loop = () => { - const h = ref.current; - if (h && h.needsRender()) { - h.renderFrame(); - } - rafId = window.requestAnimationFrame(loop); - }; - rafId = window.requestAnimationFrame(loop); - return () => window.cancelAnimationFrame(rafId); - }, [mode]); - - // Stream data to force the chart dirty. useEffect(() => { + if (!ready) return; + const column = new Float32Array(FREQ_BINS); const timer = window.setInterval(() => { - const x = lastXRef.current++; - const y = Math.sin(x * 0.02) * 40 + Math.cos(x * 0.013) * 12; - ref.current?.appendData(0, [{ x, y }]); - }, 120); - + const c = chartRef.current?.getChart(); + if (!c || c.disposed || !c.updateHeatmap) return; + liveT.current += DT; + fillSpectrogramColumn(column, liveT.current); + c.updateHeatmap(0, { + mode: 'appendColumns', + columns: 1, + z: column, + scrollX: true, + }); + }, 40); return () => window.clearInterval(timer); - }, []); + }, [ready]); return ( -
-

External render mode (app-owned RAF loop)

- -
- Features: renderMode: 'external',{' '} - needsRender() + renderFrame() -
- Mode: {mode}{' '} - -
- -
+ + setReady(true)} /> -
-
+ + ); } -function StreamingDashboardExample() { - const { adapter, device, pipelineCache, isReady, error } = useGPUContext(); - - const gpuContext = useMemo(() => { - if (!adapter || !device) return undefined; - return pipelineCache - ? { adapter, device, pipelineCache } - : { adapter, device }; - }, [adapter, device, pipelineCache]); - - const [lastAppend, setLastAppend] = useState(null); - const [lost, setLost] = useState(null); +// ─── Streaming APM multi-chart ─────────────────────────────────────────────── +function StreamingAPMExample() { + const { adapter, device, pipelineCache, isReady, error } = useGPUContext(); const aRef = useRef(null); const bRef = useRef(null); const cRef = useRef(null); + const [chartA, setChartA] = useState(null); + const [chartB, setChartB] = useState(null); + const [chartC, setChartC] = useState(null); - const aOptions: ChartGPUOptions = useMemo( - () => ({ - autoScroll: true, - series: [ - { - type: 'line', - name: 'latency(ms)', - data: generateLineData(300, 0.1), - lineStyle: { width: 2, color: '#4facfe' }, - }, - ], - xAxis: { type: 'value' }, - yAxis: { type: 'value' }, - tooltip: { show: true, trigger: 'axis' }, - dataZoom: [{ type: 'inside', start: 70, end: 100 }], - grid: { left: 60, right: 40, top: 40, bottom: 30 }, - }), - [] - ); + useConnectCharts([chartA, chartB, chartC], { syncZoom: true }); - const bOptions: ChartGPUOptions = useMemo( - () => ({ - autoScroll: true, - series: [ - { - type: 'line', - name: 'cpu(%)', - data: generateLineData(300, 1.7), - lineStyle: { width: 2, color: '#f093fb' }, - areaStyle: { color: 'rgba(240, 147, 251, 0.12)' }, - }, - ], - xAxis: { type: 'value' }, - yAxis: { type: 'value' }, - tooltip: { show: true, trigger: 'axis' }, - dataZoom: [{ type: 'inside', start: 70, end: 100 }], - grid: { left: 60, right: 40, top: 40, bottom: 30 }, - }), + const gpuContext = useMemo(() => { + if (!adapter || !device) return undefined; + return pipelineCache ? { adapter, device, pipelineCache } : { adapter, device }; + }, [adapter, device, pipelineCache]); + + const mkOptions = (name: string, color: string, seed: number, area?: string): ChartGPUOptions => ({ + theme: DEMO_THEME, + autoScroll: true, + series: [ + { + type: 'line', + name, + data: generateLineData(280, seed), + lineStyle: { width: 2, color }, + ...(area ? { areaStyle: { color: area } } : {}), + }, + ], + xAxis: { type: 'value' }, + yAxis: { type: 'value' }, + tooltip: { show: true, trigger: 'axis' }, + dataZoom: [{ type: 'inside', start: 70, end: 100 }], + grid: { left: 52, right: 20, top: 28, bottom: 24 }, + legend: { show: true }, + }); + + const optionsA = useMemo(() => mkOptions('p99 latency', '#4facfe', 0.1), []); + const optionsB = useMemo( + () => mkOptions('throughput', '#c9a227', 1.7, 'rgba(201,162,39,0.12)'), [] ); - - const cOptions: ChartGPUOptions = useMemo( - () => ({ - autoScroll: true, - series: [ - { - type: 'line', - name: 'mem(%)', - data: generateLineData(300, 3.2), - lineStyle: { width: 2, color: '#40d17c' }, - areaStyle: { color: 'rgba(64, 209, 124, 0.12)' }, - }, - ], - xAxis: { type: 'value' }, - yAxis: { type: 'value' }, - tooltip: { show: true, trigger: 'axis' }, - dataZoom: [{ type: 'inside', start: 70, end: 100 }], - grid: { left: 60, right: 40, top: 40, bottom: 30 }, - }), + const optionsC = useMemo( + () => mkOptions('error rate', '#f093fb', 2.8, 'rgba(240,147,251,0.1)'), [] ); - // Stream data into all charts. Demonstrates multi-chart sharing via gpuContext. useEffect(() => { - let x = 300; + if (!isReady) return; + let x = 280; const timer = window.setInterval(() => { x += 1; - aRef.current?.appendData(0, [{ x, y: 40 + Math.sin(x * 0.03) * 25 + Math.random() * 5 }]); - bRef.current?.appendData(0, [{ x, y: 55 + Math.cos(x * 0.02) * 22 + Math.random() * 6 }]); - cRef.current?.appendData(0, [{ x, y: 50 + Math.sin(x * 0.017) * 18 + Math.random() * 4 }]); - }, 140); - + const maxPoints = 500; + aRef.current?.appendData( + 0, + [{ x, y: 40 + Math.sin(x * 0.03) * 25 + Math.random() * 5 }], + { maxPoints } + ); + bRef.current?.appendData( + 0, + [{ x, y: 55 + Math.cos(x * 0.02) * 22 + Math.random() * 6 }], + { maxPoints } + ); + cRef.current?.appendData( + 0, + [{ x, y: 8 + Math.abs(Math.sin(x * 0.05)) * 6 + Math.random() * 2 }], + { maxPoints } + ); + }, 80); return () => window.clearInterval(timer); - }, []); + }, [isReady]); - return ( -
-

Streaming multi-chart dashboard (shared GPUDevice + pipeline cache)

- -
- Features: useGPUContext() + gpuContext prop,{' '} - onDataAppend, onDeviceLost -
- GPU context:{' '} - {error ? ( - {error.message} - ) : isReady ? ( - ready - ) : ( - initializing… - )} - {lost && ( - <> -
- Device lost:{' '} - {lost.reason} {lost.message ? `— ${lost.message}` : ''} - - )} - {lastAppend && ( - <> -
- Last append:{' '} - series {lastAppend.seriesIndex}, count {lastAppend.count}, xExtent{' '} - - [{lastAppend.xExtent.min.toFixed(2)}, {lastAppend.xExtent.max.toFixed(2)}] - - - )} -
+ const status: ExampleStatus = error ? 'error' : isReady ? 'ok' : 'loading'; -
- {gpuContext ? ( - <> + return ( + {error.message}

: undefined} + > + {gpuContext ? ( + <> + setLastAppend(p)} - onDeviceLost={(p) => setLost(p)} /> -
+ + setLastAppend(p)} - onDeviceLost={(p) => setLost(p)} /> -
+ + setLastAppend(p)} - onDeviceLost={(p) => setLost(p)} /> - - ) : ( -
- {error ? 'WebGPU unavailable.' : isReady ? 'Preparing shared context…' : 'Initializing WebGPU…'} -
- )} -
-
+
+ + ) : ( +
+ {error ? 'WebGPU unavailable.' : 'Initializing shared GPU context…'} +
+ )} +
); } -function AnnotationAuthoringExample() { - const chartRef = useRef(null); - const [chart, setChart] = useState(null); +// ─── Confidence band ───────────────────────────────────────────────────────── + +function BandConfidenceExample() { + const n = 200; + const series = useMemo(() => { + const x = new Float64Array(n); + const mean = new Float64Array(n); + const lo = new Float64Array(n); + const hi = new Float64Array(n); + for (let i = 0; i < n; i++) { + const t = i / (n - 1); + x[i] = t * 10; + const m = Math.sin(t * Math.PI * 2.2) * 0.45 + Math.cos(t * Math.PI * 0.8) * 0.2 + 0.5; + const s = 0.08 + 0.06 * Math.sin(t * 6); + mean[i] = m; + lo[i] = m - s; + hi[i] = m + s; + } + return { x, mean, lo, hi }; + }, []); const options: ChartGPUOptions = useMemo( () => ({ + theme: DEMO_THEME, + animation: false, + grid: { left: 56, right: 24, top: 28, bottom: 44 }, + xAxis: { type: 'value', name: 't' }, + yAxis: { type: 'value', name: 'Value' }, + tooltip: { show: true, trigger: 'axis' }, + legend: { show: true }, + dataZoom: [{ type: 'inside' }], series: [ + { + type: 'band', + name: '±1σ', + data: { x: series.x, y: series.lo, y1: series.hi }, + areaStyle: { color: '#38bdf8', opacity: 0.28 }, + lineStyle: { width: 1.2, color: '#38bdf8', opacity: 0.7 }, + lineStyleY1: { width: 1.2, color: '#f472b6', opacity: 0.7 }, + sampling: 'none', + }, { type: 'line', - name: 'Annotate me', - data: generateLineData(800, 0.6), - lineStyle: { width: 2, color: '#40d17c' }, + name: 'Mean', + data: { x: series.x, y: series.mean }, + lineStyle: { width: 2.2, color: '#f8fafc' }, + sampling: 'none', }, ], - xAxis: { type: 'value' }, - yAxis: { type: 'value' }, - tooltip: { show: true, trigger: 'axis' }, - dataZoom: [{ type: 'inside' }, { type: 'slider' }], - // Note: annotations are managed by createAnnotationAuthoring, so we don't - // include them in options to avoid overwriting them when options update. - grid: { left: 60, right: 40, top: 40, bottom: 40 }, }), - [] + [series] ); - useEffect(() => { - const container = chartRef.current?.getContainer(); - const instance = chartRef.current?.getChart(); - if (!container || !instance || instance.disposed) return; - - const authoring = createAnnotationAuthoring(container, instance, { - enableContextMenu: true, - menuZIndex: 1000, - }); - - // Important: dispose authoring before the chart disposes. - return () => authoring.dispose(); - }, [chart]); - return ( -
-

Annotation authoring

- -
- Features: Right-click context menu + drag + undo/redo via{' '} - createAnnotationAuthoring -
- Try it: Right-click in the plot area to add annotations, right-click existing annotations to edit -
- -
- -
-
+ + + + + ); } +// ─── Candlestick streaming ─────────────────────────────────────────────────── + function seedCandles(count: number, intervalMs: number, startPrice: number): Candle[] { const now = Date.now(); const startTs = now - count * intervalMs; const out: Candle[] = []; - let lastClose = startPrice; for (let i = 0; i < count; i++) { const ts = startTs + i * intervalMs; const open = lastClose; const delta = (Math.sin(i * 0.35) + Math.cos(i * 0.22)) * 0.8; const close = open + delta; - const high = Math.max(open, close) + 0.6; - const low = Math.min(open, close) - 0.6; - out.push({ timestamp: ts, open, close, high, low }); + out.push({ + timestamp: ts, + open, + close, + high: Math.max(open, close) + 0.6, + low: Math.min(open, close) - 0.6, + }); lastClose = close; } - return out; } -function CandlestickStreamingExample() { +function CandlestickExample() { const ref = useRef(null); - const initial = useMemo(() => seedCandles(80, 1000, 100), []); + const initial = useMemo(() => seedCandles(100, 1000, 100), []); const last = initial[initial.length - 1]!; - const lastCloseRef = useRef(last.close); - const lastTsRef = useRef(last.timestamp); + const lastCloseRef = useRef(last.close); + const lastTsRef = useRef(last.timestamp); const options: ChartGPUOptions = useMemo( () => ({ + theme: DEMO_THEME, + legend: { show: false }, xAxis: { type: 'time' }, yAxis: { type: 'value' }, tooltip: { show: true, trigger: 'axis' }, dataZoom: [ - { type: 'inside', start: 80, end: 100 }, - { type: 'slider', start: 80, end: 100 }, + { type: 'inside', start: 75, end: 100 }, + { type: 'slider', start: 75, end: 100 }, ], autoScroll: true, series: [ @@ -808,7 +890,8 @@ function CandlestickStreamingExample() { data: initial, }, ], - grid: { left: 60, right: 40, top: 40, bottom: 40 }, + // Extra right gutter for the auto priceLabel badge + last candle wick. + grid: { left: 56, right: 72, top: 28, bottom: 52 }, }), [initial] ); @@ -816,153 +899,170 @@ function CandlestickStreamingExample() { useEffect(() => { const timer = window.setInterval(() => { const open = lastCloseRef.current; - const drift = (Math.random() - 0.5) * 2; - const close = open + drift; + const close = open + (Math.random() - 0.5) * 2; const high = Math.max(open, close) + Math.random() * 1.2; const low = Math.min(open, close) - Math.random() * 1.2; - const timestamp = lastTsRef.current + 1000; lastTsRef.current = timestamp; lastCloseRef.current = close; - - const next: Candle = { timestamp, open, close, high, low }; - ref.current?.appendData(0, [next]); - }, 500); - + ref.current?.appendData(0, [{ timestamp, open, close, high, low }]); + }, 450); return () => window.clearInterval(timer); }, []); return ( -
-

Candlestick streaming (appendData)

- -
- Features: Candlestick series + OHLC sampling + streaming{' '} - appendData (v0.2.3) -
- Note: Auto-scroll keeps the view pinned when zoomed to the end -
- -
- -
-
+ + + + + ); } -function generateScatterPoints(count: number, seed: number): ScatterPointTuple[] { - // Deterministic RNG so the example is stable across hot reloads. - const mulberry32 = (a: number) => () => { - a |= 0; - a = (a + 0x6d2b79f5) | 0; - let t = Math.imul(a ^ (a >>> 15), 1 | a); - t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; - return ((t ^ (t >>> 14)) >>> 0) / 4294967296; - }; - - const rand = mulberry32(Math.floor(seed * 1_000_000)); - const normal = () => { - // Box–Muller transform - const u1 = Math.max(1e-12, rand()); - const u2 = rand(); - const r = Math.sqrt(-2.0 * Math.log(u1)); - const theta = 2.0 * Math.PI * u2; - return r * Math.cos(theta); - }; - - const clamp = (v: number, lo: number, hi: number) => Math.min(hi, Math.max(lo, v)); - - const points: ScatterPointTuple[] = []; - for (let i = 0; i < count; i++) { - // Two Gaussian blobs so density mode shows structure. - const blob = rand() < 0.6 ? 0 : 1; - const cx = blob === 0 ? 35 : 70; - const cy = blob === 0 ? 55 : 35; - const sx = blob === 0 ? 8 : 5; - const sy = blob === 0 ? 10 : 7; - - const x = clamp(cx + normal() * sx, 0, 100); - const y = clamp(cy + normal() * sy, 0, 100); - points.push([x, y]); - } - - return points; -} +// ─── Synced hooks (React-specific) ─────────────────────────────────────────── -function ScatterDensityExample() { - const POINT_COUNT = 250_000; +function SyncedHooksExample() { + const { adapter, device, pipelineCache, isReady, error } = useGPUContext(); + const [a, setA] = useState(null); + const [b, setB] = useState(null); + useConnectCharts([a, b], { syncZoom: true }); - const scatterData = useMemo(() => generateScatterPoints(POINT_COUNT, 0.42), []); + const gpuContext = useMemo(() => { + if (!adapter || !device) return undefined; + return pipelineCache ? { adapter, device, pipelineCache } : { adapter, device }; + }, [adapter, device, pipelineCache]); - const options: ChartGPUOptions = useMemo( - () => ({ + const top = useMemo( + (): ChartGPUOptions => ({ + theme: DEMO_THEME, series: [ { - type: 'scatter', - name: 'Density', - data: scatterData, - mode: 'density', - binSize: 2, - densityColormap: 'viridis', - densityNormalization: 'log', - sampling: 'none', + type: 'line', + name: 'Alpha', + data: generateLineData(1200, 0.2), + lineStyle: { width: 2, color: '#4facfe' }, + areaStyle: { color: 'rgba(79,172,254,0.1)' }, }, ], xAxis: { type: 'value' }, yAxis: { type: 'value' }, tooltip: { show: true, trigger: 'axis' }, - grid: { left: 60, right: 40, top: 40, bottom: 40 }, + dataZoom: [{ type: 'inside' }], + grid: { left: 52, right: 24, top: 28, bottom: 28 }, }), - [scatterData] + [] ); - return ( -
-

Scatter density

+ const bottom = useMemo( + (): ChartGPUOptions => ({ + theme: DEMO_THEME, + series: [ + { + type: 'line', + name: 'Beta', + data: generateLineData(1200, 1.4), + lineStyle: { width: 2, color: '#c9a227' }, + }, + ], + xAxis: { type: 'value' }, + yAxis: { type: 'value' }, + tooltip: { show: true, trigger: 'axis' }, + dataZoom: [{ type: 'inside' }], + grid: { left: 52, right: 24, top: 28, bottom: 28 }, + }), + [] + ); -
- Features: Scatter series with mode: 'density', density colormap, binning -
- Point count: {POINT_COUNT.toLocaleString()} (adjust in code to increase) -
+ if (error) { + return ( + {error.message}

} + > +
WebGPU not supported.
+
+ ); + } -
- -
-
+ return ( + + {gpuContext && isReady ? ( + <> + + + + + + + + ) : ( +
Initializing GPU…
+ )} +
); } -function App() { +// ─── Mount ─────────────────────────────────────────────────────────────────── + +function DemosApp() { return ( <> - - - - - - - - + + + +
+ + +
+ ); } -// Mount React app +const heroRoot = document.getElementById('hero-root'); +if (heroRoot) { + createRoot(heroRoot).render(); +} + const rootElement = document.getElementById('root'); if (rootElement) { - const root = createRoot(rootElement); - root.render(); + createRoot(rootElement).render(); } else { console.error('Root element not found'); } diff --git a/examples/styles.css b/examples/styles.css new file mode 100644 index 0000000..bb23890 --- /dev/null +++ b/examples/styles.css @@ -0,0 +1,859 @@ +/* Hallmark · pre-emit critique: P5 H5 E5 S5 R4 V5 + * Hallmark · genre: atmospheric · macrostructure: Photographic + * tone: technical · theme: studied-DNA (ChartGPU brand) · enrichment: live WebGPU plates + * nav: N5 floating pill · footer: Ft5 · differs from: Component Playground + */ + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +html, +body { + overflow-x: clip; + min-width: 0; +} + +html { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + scroll-behavior: smooth; + scroll-padding-top: calc(var(--nav-height) + var(--space-md)); +} + +body { + font-family: var(--font-body); + background: var(--color-paper); + color: var(--color-ink); + line-height: 1.5; + min-height: 100vh; +} + +a { + color: inherit; + text-decoration: none; +} + +button { + font: inherit; + border: none; + background: none; + cursor: pointer; + color: inherit; +} + +img { + display: block; + max-width: 100%; +} + +code { + font-family: var(--font-mono); + font-size: 0.9em; + color: var(--color-accent); + background: var(--color-accent-soft); + padding: 0.1em 0.35em; + border-radius: 4px; +} + +:focus-visible { + outline: 2px solid var(--color-focus); + outline-offset: 3px; +} + +/* Soft atmospheric blooms */ +body::before, +body::after { + content: ''; + position: fixed; + pointer-events: none; + z-index: 0; + width: min(52vw, 560px); + height: min(52vw, 560px); + border-radius: 50%; + filter: blur(90px); + opacity: 0.18; +} + +body::before { + top: -10%; + left: -8%; + background: var(--color-accent-soft); +} + +body::after { + bottom: 8%; + right: -10%; + background: var(--color-blue-soft); +} + +/* ── N5 Floating pill nav ── */ +.nav { + position: fixed; + top: var(--space-sm); + left: 50%; + transform: translateX(-50%); + z-index: var(--z-nav); + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-sm); + width: min(calc(100% - 2 * var(--page-gutter)), 1080px); + height: 52px; + padding: 0 var(--space-xs) 0 var(--space-sm); + background: oklch(14% 0.014 265 / 0.78); + border: var(--rule-hair) solid var(--color-rule-strong); + border-radius: var(--radius-pill); + backdrop-filter: blur(14px); + -webkit-backdrop-filter: blur(14px); + box-shadow: 0 12px 40px oklch(0% 0 0 / 0.35); + min-width: 0; +} + +.nav-brand { + display: flex; + align-items: center; + gap: var(--space-2xs); + min-width: 0; +} + +.nav-brand img { + height: 22px; + width: auto; +} + +.nav-version { + font-family: var(--font-mono); + font-size: var(--text-xs); + color: var(--color-ink-2); + padding: 2px 8px; + background: var(--color-paper); + border: var(--rule-hair) solid var(--color-rule-strong); + border-radius: var(--radius-sm); + letter-spacing: 0.02em; + white-space: nowrap; +} + +.nav-actions { + display: flex; + align-items: center; + gap: 2px; + min-width: 0; +} + +.nav-link { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 6px 11px; + font-family: var(--font-display); + font-size: var(--text-sm); + font-weight: 500; + color: var(--color-ink-2); + border-radius: var(--radius-pill); + white-space: nowrap; + transition: + color var(--dur-short) var(--ease-out), + background var(--dur-short) var(--ease-out); +} + +.nav-link:hover { + color: var(--color-ink); + background: var(--color-paper-3); +} + +.nav-link:active { + transform: translateY(1px); +} + +.nav-link svg { + width: 14px; + height: 14px; + fill: currentColor; + flex-shrink: 0; +} + +.nav-cta { + display: inline-flex; + align-items: center; + padding: 7px 14px; + font-family: var(--font-display); + font-size: var(--text-sm); + font-weight: 600; + color: var(--color-accent-ink); + background: var(--color-accent); + border-radius: var(--radius-pill); + white-space: nowrap; + transition: + filter var(--dur-short) var(--ease-out), + transform var(--dur-short) var(--ease-out); +} + +.nav-cta:hover { + filter: brightness(1.08); +} + +.nav-cta:active { + transform: translateY(1px); +} + +/* ── Photographic hero plate ── */ +.plate-hero { + position: relative; + z-index: 1; + width: 100%; + min-height: 100vh; + min-height: 100dvh; + isolation: isolate; + background: #03040a; + overflow: hidden; +} + +.plate-hero__canvas { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + min-width: 0; +} + +/* ChartGPU host is the only in-flow child; overlays are absolute */ +.plate-hero__canvas > div:not(.plate-hero__status):not(.plate-hero__caption) { + position: absolute !important; + inset: 0 !important; + width: 100% !important; + height: 100% !important; + border: none !important; + border-radius: 0 !important; + background: transparent !important; +} + +.plate-hero__canvas canvas { + display: block; + width: 100% !important; + height: 100% !important; +} + +.plate-hero__caption { + position: absolute; + z-index: 3; + left: var(--page-gutter); + bottom: var(--space-xl); + max-width: min(38ch, calc(100% - 2 * var(--page-gutter))); + min-width: 0; + padding: var(--space-sm) var(--space-md); + background: oklch(8% 0.01 265 / 0.72); + border: var(--rule-hair) solid var(--color-rule-strong); + border-radius: var(--radius-md); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + pointer-events: none; +} + +.plate-hero__meta { + font-family: var(--font-mono); + font-size: var(--text-xs); + color: var(--color-accent); + letter-spacing: 0.05em; + margin-bottom: var(--space-3xs); +} + +.plate-hero__title { + font-family: var(--font-display); + font-style: normal; + font-size: var(--text-xl); + font-weight: 600; + letter-spacing: -0.02em; + line-height: 1.2; + color: var(--color-ink); + overflow-wrap: anywhere; + min-width: 0; +} + +.plate-hero__note { + margin-top: var(--space-3xs); + font-size: var(--text-sm); + color: var(--color-ink-2); +} + +.plate-hero__status { + position: absolute; + z-index: 3; + inset: 0; + display: grid; + place-items: center; + font-family: var(--font-mono); + font-size: var(--text-xs); + color: var(--color-ink-3); + letter-spacing: 0.08em; + text-transform: uppercase; + pointer-events: none; + background: #03040a; + transition: opacity var(--dur-mid) var(--ease-out); +} + +.plate-hero.is-ready .plate-hero__status { + opacity: 0; + visibility: hidden; +} + +/* ── Page body ── */ +.page { + position: relative; + z-index: 1; + padding: var(--space-2xl) var(--page-gutter) var(--space-3xl); + max-width: var(--max-width); + margin: 0 auto; + min-width: 0; +} + +.intro { + margin-bottom: var(--space-xl); + min-width: 0; +} + +.intro-title { + font-family: var(--font-display); + font-style: normal; + font-size: var(--text-2xl); + font-weight: 600; + letter-spacing: -0.03em; + line-height: 1.12; + color: var(--color-ink); + overflow-wrap: anywhere; + min-width: 0; + margin-bottom: var(--space-2xs); +} + +.intro-lede { + font-size: var(--text-md); + color: var(--color-ink-2); + max-width: 56ch; + margin-bottom: var(--space-md); +} + +.intro-lede code { + font-size: 0.88em; +} + +.hero-install { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: var(--space-2xs); +} + +.install-bar { + display: inline-flex; + align-items: center; + gap: var(--space-xs); + padding: 10px 14px; + background: var(--color-paper-2); + border: var(--rule-hair) solid var(--color-rule-strong); + border-radius: var(--radius-md); + min-width: 0; +} + +.install-prompt { + color: var(--color-ink-3); + font-family: var(--font-mono); + font-size: var(--text-sm); + user-select: none; +} + +.install-cmd { + font-family: var(--font-mono); + font-size: var(--text-sm); + color: var(--color-ink); + letter-spacing: 0.01em; + background: none; + padding: 0; +} + +.install-copy { + padding: 5px 11px; + font-family: var(--font-display); + font-size: var(--text-xs); + font-weight: 600; + color: var(--color-ink-2); + border: var(--rule-hair) solid var(--color-rule-strong); + border-radius: var(--radius-sm); + transition: + color var(--dur-short), + background var(--dur-short), + border-color var(--dur-short); + white-space: nowrap; +} + +.install-copy:hover { + color: var(--color-accent); + border-color: var(--color-accent-soft); + background: var(--color-accent-soft); +} + +.install-copy:active { + transform: translateY(1px); +} + +.install-copy.is-copied { + color: var(--color-ok); + border-color: transparent; +} + +/* ── Jump index ── */ +.index { + margin-bottom: var(--space-2xl); + min-width: 0; +} + +.index-head { + display: flex; + align-items: baseline; + justify-content: space-between; + gap: var(--space-sm); + margin-bottom: var(--space-md); + flex-wrap: wrap; +} + +.index-title { + font-family: var(--font-display); + font-style: normal; + font-size: var(--text-xl); + font-weight: 600; + letter-spacing: -0.02em; + color: var(--color-ink); +} + +.index-count { + font-family: var(--font-mono); + font-size: var(--text-xs); + color: var(--color-ink-3); + letter-spacing: 0.04em; +} + +.index-grid { + list-style: none; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(min(100%, 220px), 1fr)); + gap: var(--space-2xs); +} + +.index-card { + display: flex; + flex-direction: column; + gap: 4px; + min-width: 0; + padding: var(--space-sm) var(--space-md); + background: var(--color-paper-2); + border: var(--rule-hair) solid var(--color-rule); + border-radius: var(--radius-md); + transition: + background var(--dur-short) var(--ease-out), + border-color var(--dur-short) var(--ease-out), + transform var(--dur-short) var(--ease-out); +} + +.index-card:hover { + background: var(--color-paper-3); + border-color: var(--color-rule-strong); + transform: translateY(-1px); +} + +.index-card:active { + transform: translateY(0); +} + +.index-card__title { + font-family: var(--font-display); + font-size: var(--text-sm); + font-weight: 600; + color: var(--color-ink); + letter-spacing: -0.01em; + min-width: 0; + overflow-wrap: anywhere; +} + +.index-card__desc { + font-size: var(--text-xs); + color: var(--color-ink-2); + line-height: 1.4; + min-width: 0; +} + +.index-card__api { + font-family: var(--font-mono); + font-size: 0.625rem; + color: var(--color-accent); + letter-spacing: 0.02em; + margin-top: 2px; +} + +/* ── Live example cards ── */ +.examples { + display: flex; + flex-direction: column; + gap: var(--space-xl); + min-width: 0; +} + +.example { + scroll-margin-top: calc(var(--nav-height) + var(--space-lg)); + min-width: 0; + background: var(--color-paper-2); + border: var(--rule-hair) solid var(--color-rule); + border-radius: var(--radius-lg); + overflow: hidden; +} + +.example--featured { + border-color: oklch(74% 0.14 85 / 0.28); + box-shadow: 0 0 0 1px oklch(74% 0.14 85 / 0.08), 0 24px 80px oklch(0% 0 0 / 0.35); +} + +.example--tall .example-canvas { + min-height: min(62vh, 560px); +} + +.example--tall .example-canvas .chart-host { + min-height: min(58vh, 520px); +} + +.example--tall .example-canvas .chart-host > div { + min-height: inherit; +} + +.example-header { + display: flex; + flex-wrap: wrap; + align-items: flex-start; + justify-content: space-between; + gap: var(--space-sm); + padding: var(--space-md) var(--space-md) var(--space-sm); + border-bottom: var(--rule-hair) solid var(--color-rule); + min-width: 0; +} + +.example-header__main { + min-width: 0; + flex: 1 1 16rem; +} + +.example-id { + font-family: var(--font-mono); + font-size: var(--text-xs); + color: var(--color-ink-3); + letter-spacing: 0.04em; + margin-bottom: var(--space-3xs); +} + +.example-title { + font-family: var(--font-display); + font-style: normal; + font-size: var(--text-lg); + font-weight: 600; + letter-spacing: -0.02em; + color: var(--color-ink); + line-height: 1.25; + overflow-wrap: anywhere; + min-width: 0; + margin-bottom: var(--space-3xs); +} + +.example-desc { + font-size: var(--text-sm); + color: var(--color-ink-2); + max-width: 62ch; +} + +.example-status { + display: inline-flex; + align-items: center; + gap: 6px; + font-family: var(--font-mono); + font-size: var(--text-xs); + color: var(--color-ink-2); + padding: 5px 10px; + border-radius: var(--radius-pill); + border: var(--rule-hair) solid var(--color-rule-strong); + background: var(--color-paper); + white-space: nowrap; + flex-shrink: 0; +} + +.example-status__dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--color-ink-3); + flex-shrink: 0; +} + +.example-status--ok { + color: var(--color-ok); + border-color: oklch(72% 0.14 155 / 0.35); +} + +.example-status--ok .example-status__dot { + background: var(--color-ok); + box-shadow: 0 0 8px oklch(72% 0.14 155 / 0.5); +} + +.example-status--error { + color: var(--color-danger); + border-color: oklch(68% 0.16 25 / 0.4); +} + +.example-status--error .example-status__dot { + background: var(--color-danger); +} + +.example-status--loading .example-status__dot { + background: var(--color-accent); + animation: pulse-dot 1.2s var(--ease-in-out) infinite; +} + +@keyframes pulse-dot { + 0%, + 100% { + opacity: 0.4; + } + 50% { + opacity: 1; + } +} + +.example-meta { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: var(--space-xs) var(--space-md); + padding: var(--space-sm) var(--space-md); + background: oklch(10% 0.012 265 / 0.55); + border-bottom: var(--rule-hair) solid var(--color-rule); + font-size: var(--text-sm); + color: var(--color-ink-2); + min-width: 0; +} + +.example-meta strong { + font-family: var(--font-display); + font-weight: 500; + color: var(--color-ink); + margin-right: 0.35em; +} + +.example-meta p { + min-width: 0; + flex: 1 1 100%; +} + +.example-meta__row { + min-width: 0; + flex: 1 1 auto; + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 8px; +} + +.example-tags { + display: flex; + flex-wrap: wrap; + gap: 6px; + padding: 0 var(--space-md) var(--space-sm); +} + +.example-tag { + font-family: var(--font-mono); + font-size: 0.625rem; + color: var(--color-ink-2); + padding: 3px 8px; + border-radius: var(--radius-sm); + border: var(--rule-hair) solid var(--color-rule-strong); + background: var(--color-paper); + letter-spacing: 0.02em; + white-space: nowrap; +} + +.example-canvas { + padding: var(--space-sm) var(--space-md) var(--space-md); + min-width: 0; + background: oklch(10% 0.01 265); +} + +.example-canvas--stack { + display: flex; + flex-direction: column; + gap: var(--space-2xs); +} + +.example-canvas--bleed { + padding: 0; + background: #05060a; +} + +.example-canvas--bleed .chart-host { + border: none; + border-radius: 0; +} + +.example-canvas .chart-host { + min-width: 0; + border-radius: var(--radius-sm); + /* Do not clip priceLabel / legend overlays (they sit outside the plot grid). */ + overflow: visible; + border: var(--rule-hair) solid var(--color-rule); + background: var(--color-paper); +} + +.example-canvas .chart-host > canvas { + display: block; + border-radius: var(--radius-sm); +} + +.example-empty { + padding: var(--space-lg); + font-family: var(--font-mono); + font-size: var(--text-xs); + color: var(--color-ink-3); + letter-spacing: 0.04em; + text-align: center; +} + +.btn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 5px 11px; + font-family: var(--font-display); + font-size: var(--text-xs); + font-weight: 600; + color: var(--color-ink); + background: var(--color-paper-3); + border: var(--rule-hair) solid var(--color-rule-strong); + border-radius: var(--radius-sm); + transition: + background var(--dur-short) var(--ease-out), + border-color var(--dur-short) var(--ease-out), + color var(--dur-short) var(--ease-out); + white-space: nowrap; +} + +.btn:hover { + color: var(--color-accent); + border-color: var(--color-accent-soft); + background: var(--color-accent-soft); +} + +.btn:active { + transform: translateY(1px); +} + +.btn:disabled { + opacity: 0.45; + cursor: not-allowed; + transform: none; +} + +.btn--on { + color: var(--color-accent-ink); + background: var(--color-accent); + border-color: transparent; +} + +.btn--on:hover { + color: var(--color-accent-ink); + filter: brightness(1.06); + background: var(--color-accent); + border-color: transparent; +} + +.btn--ghost { + background: oklch(12% 0.012 265 / 0.65); + border-color: var(--color-rule-strong); + backdrop-filter: blur(8px); +} + +/* ── Split pair plates ── */ +.pair { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-md); + min-width: 0; +} + +.pair > .example { + min-width: 0; +} + +/* ── Footer ── */ +.footer { + position: relative; + z-index: 1; + margin-top: var(--space-xl); + padding: var(--space-md) var(--page-gutter) var(--space-xl); + border-top: var(--rule-hair) solid var(--color-rule); + max-width: var(--max-width); + margin-left: auto; + margin-right: auto; + min-width: 0; +} + +.footer-meta { + display: flex; + flex-wrap: wrap; + gap: var(--space-sm) var(--space-md); + font-size: var(--text-sm); + color: var(--color-ink-2); +} + +.footer-meta a { + color: var(--color-ink-2); + border-bottom: 1px solid transparent; + transition: color var(--dur-short), border-color var(--dur-short); + white-space: nowrap; +} + +.footer-meta a:hover { + color: var(--color-accent); + border-bottom-color: var(--color-accent); +} + +@media (max-width: 900px) { + .pair { + grid-template-columns: 1fr; + } +} + +@media (max-width: 640px) { + .nav-link--hide-sm { + display: none; + } + + .plate-hero__caption { + bottom: var(--space-md); + max-width: calc(100% - 2 * var(--page-gutter)); + } + + .example-header { + flex-direction: column; + } +} + +@media (prefers-reduced-motion: reduce) { + html { + scroll-behavior: auto; + } + + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} diff --git a/examples/tokens.css b/examples/tokens.css new file mode 100644 index 0000000..f9135c5 --- /dev/null +++ b/examples/tokens.css @@ -0,0 +1,74 @@ +/* Hallmark · pre-emit critique: P5 H5 E5 S5 R4 V5 + * Hallmark · genre: atmospheric · macrostructure: Photographic + * tone: technical · theme: studied-DNA (source: chart-gpu/dev-site) + * paper: oklch(12% 0.012 265) · accent: oklch(74% 0.14 85) · display: Space Grotesk + body: DM Sans + * axes: dark / geometric-sans / warm · enrichment: live WebGPU 3D plates · nav: N5 · footer: Ft5 + * theme_axes: dark / geometric-sans / warm · studied: yes · DNA-source: local dev-site + */ + +:root { + /* Brand paper / surfaces */ + --color-paper: oklch(12% 0.012 265); + --color-paper-2: oklch(15% 0.014 265); + --color-paper-3: oklch(19% 0.016 265); + --color-paper-hover: oklch(22% 0.018 265); + + /* Ink */ + --color-ink: oklch(92% 0.01 265); + --color-ink-2: oklch(62% 0.02 265); + --color-ink-3: oklch(42% 0.015 265); + + /* Brand accents — gold primary, blue secondary */ + --color-accent: oklch(74% 0.14 85); + --color-accent-soft: oklch(74% 0.14 85 / 0.14); + --color-accent-ink: oklch(18% 0.03 85); + --color-blue: oklch(58% 0.14 250); + --color-blue-soft: oklch(58% 0.14 250 / 0.16); + --color-focus: oklch(74% 0.14 85); + --color-ok: oklch(72% 0.14 155); + --color-danger: oklch(68% 0.16 25); + + --color-rule: oklch(92% 0.01 265 / 0.08); + --color-rule-strong: oklch(92% 0.01 265 / 0.14); + --color-overlay: oklch(0% 0 0 / 0.72); + + /* Type */ + --font-display: 'Space Grotesk', system-ui, sans-serif; + --font-body: 'DM Sans', system-ui, sans-serif; + --font-mono: 'SF Mono', 'Cascadia Code', 'Fira Mono', Consolas, monospace; + + --text-xs: 0.6875rem; + --text-sm: 0.8125rem; + --text-md: 0.9375rem; + --text-lg: 1.125rem; + --text-xl: 1.5rem; + --text-2xl: clamp(1.75rem, 3.5vw, 2.5rem); + --text-display: clamp(2rem, 4.5vw, 3.25rem); + + /* 4pt scale */ + --space-3xs: 0.25rem; + --space-2xs: 0.5rem; + --space-xs: 0.75rem; + --space-sm: 1rem; + --space-md: 1.5rem; + --space-lg: 2rem; + --space-xl: 3rem; + --space-2xl: 4.5rem; + --space-3xl: 7rem; + + --page-gutter: clamp(1rem, 4vw, 3rem); + --max-width: 1120px; + --radius-sm: 6px; + --radius-md: 10px; + --radius-lg: 14px; + --radius-pill: 999px; + + --ease-out: cubic-bezier(0.16, 1, 0.3, 1); + --ease-in-out: cubic-bezier(0.45, 0, 0.55, 1); + --dur-short: 180ms; + --dur-mid: 280ms; + + --rule-hair: 1px; + --nav-height: 56px; + --z-nav: 100; +} diff --git a/package-lock.json b/package-lock.json index 76f504f..62798e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,98 +1,91 @@ { - "name": "@chartgpu/chartgpu-react", - "version": "0.1.4", + "name": "chartgpu-react", + "version": "0.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@chartgpu/chartgpu-react", - "version": "0.1.4", + "name": "chartgpu-react", + "version": "0.3.0", "license": "MIT", "devDependencies": { - "@chartgpu/chartgpu": "^0.2.8", + "@chartgpu/chartgpu": "^0.3.6", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", - "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", - "@vitejs/plugin-react": "^4.2.1", - "@vitest/coverage-v8": "^4.0.18", - "jsdom": "^28.1.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "typescript": "^5.3.3", - "vite": "^5.1.4", - "vite-plugin-dts": "^3.7.3", - "vitest": "^4.0.18" + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.0.3", + "@vitest/coverage-v8": "^4.1.10", + "jsdom": "^29.1.1", + "react": "^19.2.8", + "react-dom": "^19.2.8", + "typescript": "^7.0.2", + "vite": "^7.1.5", + "vitest": "^4.1.10" + }, + "engines": { + "node": ">=20" }, "peerDependencies": { - "@chartgpu/chartgpu": "^0.2.8", + "@chartgpu/chartgpu": "^0.3.6", "react": ">=18.0.0", "react-dom": ">=18.0.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": false + } } }, - "node_modules/@acemir/cssom": { - "version": "0.9.31", - "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz", - "integrity": "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==", - "dev": true, - "license": "MIT" - }, "node_modules/@adobe/css-tools": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", - "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.5.0.tgz", + "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==", "dev": true, "license": "MIT" }, "node_modules/@asamuzakjp/css-color": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.0.1.tgz", - "integrity": "sha512-2SZFvqMyvboVV1d15lMf7XiI3m7SDqXUuKaTymJYLN6dSGadqp+fVojqJlVoMlbZnlTmu3S0TLwLTJpvBMO1Aw==", + "version": "5.1.11", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz", + "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==", "dev": true, "license": "MIT", "dependencies": { - "@csstools/css-calc": "^3.1.1", - "@csstools/css-color-parser": "^4.0.2", + "@asamuzakjp/generational-cache": "^1.0.1", + "@csstools/css-calc": "^3.2.0", + "@csstools/css-color-parser": "^4.1.0", "@csstools/css-parser-algorithms": "^4.0.0", - "@csstools/css-tokenizer": "^4.0.0", - "lru-cache": "^11.2.6" + "@csstools/css-tokenizer": "^4.0.0" }, "engines": { "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, "node_modules/@asamuzakjp/dom-selector": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz", - "integrity": "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz", + "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==", "dev": true, "license": "MIT", "dependencies": { + "@asamuzakjp/generational-cache": "^1.0.1", "@asamuzakjp/nwsapi": "^2.3.9", "bidi-js": "^1.0.3", - "css-tree": "^3.1.0", - "is-potential-custom-element-name": "^1.0.1", - "lru-cache": "^11.2.6" + "css-tree": "^3.2.1", + "is-potential-custom-element-name": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "node_modules/@asamuzakjp/generational-cache": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz", + "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "engines": { - "node": "20 || >=22" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, "node_modules/@asamuzakjp/nwsapi": { @@ -103,11 +96,13 @@ "license": "MIT" }, "node_modules/@babel/code-frame": { - "version": "7.28.6", + "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.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -116,7 +111,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.6", + "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": { @@ -124,20 +121,21 @@ } }, "node_modules/@babel/core": { - "version": "7.28.6", + "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", - "peer": true, "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6", + "@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", @@ -154,12 +152,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.6", + "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.28.6", - "@babel/types": "^7.28.6", + "@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" @@ -169,12 +169,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", + "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.28.6", - "@babel/helper-validator-option": "^7.27.1", + "@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" @@ -184,7 +186,9 @@ } }, "node_modules/@babel/helper-globals": { - "version": "7.28.0", + "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": { @@ -192,25 +196,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", + "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.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", + "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.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -220,7 +228,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "dev": true, "license": "MIT", "engines": { @@ -228,7 +238,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", + "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": { @@ -236,7 +248,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", + "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": { @@ -244,7 +258,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", + "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": { @@ -252,25 +268,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.6", + "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.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "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.0" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -280,11 +298,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -294,11 +314,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -308,9 +330,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", "dev": true, "license": "MIT", "engines": { @@ -318,29 +340,33 @@ } }, "node_modules/@babel/template": { - "version": "7.28.6", + "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.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@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.28.6", + "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.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6", + "@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": { @@ -348,14 +374,14 @@ } }, "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "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.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -385,16 +411,16 @@ } }, "node_modules/@chartgpu/chartgpu": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@chartgpu/chartgpu/-/chartgpu-0.2.8.tgz", - "integrity": "sha512-of5E6UjWbkya2xrFsLcBlCR2fouR2vUHSVjsY+S9pLsGkGb3F1kzSeDV/s/7iyyrimHjXs2ZyUrhEjaiYN7wVg==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@chartgpu/chartgpu/-/chartgpu-0.3.6.tgz", + "integrity": "sha512-YLHpU4mCduWN/LiLdI64qy1SOOFAVlTEbxtDDVBK4fX/npAzkzIXj2dK9dfcWxGA7V4miMjTOhqqk8S8m3gfsA==", "dev": true, "license": "MIT" }, "node_modules/@csstools/color-helpers": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", - "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.1.0.tgz", + "integrity": "sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==", "dev": true, "funding": [ { @@ -412,9 +438,9 @@ } }, "node_modules/@csstools/css-calc": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.1.1.tgz", - "integrity": "sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.2.1.tgz", + "integrity": "sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==", "dev": true, "funding": [ { @@ -436,9 +462,9 @@ } }, "node_modules/@csstools/css-color-parser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.0.2.tgz", - "integrity": "sha512-0GEfbBLmTFf0dJlpsNU7zwxRIH0/BGEMuXLTCvFYxuL1tNhqzTbtnFICyJLTNK4a+RechKP75e7w42ClXSnJQw==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.9.tgz", + "integrity": "sha512-paQcIaOO53Rk5+YrBaBjm/SgrV4INImjo2BT1DtQRYr+XeTRbeAYlS+jxXp9drqvKmtFnWRJKIalDLhZZDu42A==", "dev": true, "funding": [ { @@ -452,8 +478,8 @@ ], "license": "MIT", "dependencies": { - "@csstools/color-helpers": "^6.0.2", - "@csstools/css-calc": "^3.1.1" + "@csstools/color-helpers": "^6.1.0", + "@csstools/css-calc": "^3.2.1" }, "engines": { "node": ">=20.19.0" @@ -479,7 +505,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" }, @@ -488,9 +513,9 @@ } }, "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.0.29", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.29.tgz", - "integrity": "sha512-jx9GjkkP5YHuTmko2eWAvpPnb0mB4mGRr2U7XwVNwevm8nlpobZEVk+GNmiYMk2VuA75v+plfXWyroWKmICZXg==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.6.tgz", + "integrity": "sha512-TcJCWFbXLPpJYq6z7bfOyjWYJDiDg2/I4gyUC9pqPNqHFRIey0EB0q0L5cSnQDfWJg8Jd6VadakxdIez/3zkqQ==", "dev": true, "funding": [ { @@ -502,7 +527,15 @@ "url": "https://opencollective.com/csstools" } ], - "license": "MIT-0" + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } }, "node_modules/@csstools/css-tokenizer": { "version": "4.0.0", @@ -520,15 +553,14 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", "cpu": [ "ppc64" ], @@ -539,13 +571,13 @@ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", "cpu": [ "arm" ], @@ -556,13 +588,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "cpu": [ "arm64" ], @@ -573,13 +605,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "cpu": [ "x64" ], @@ -590,11 +622,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "cpu": [ "arm64" ], @@ -605,13 +639,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "cpu": [ "x64" ], @@ -622,13 +656,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "cpu": [ "arm64" ], @@ -639,13 +673,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "cpu": [ "x64" ], @@ -656,13 +690,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "cpu": [ "arm" ], @@ -673,13 +707,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "cpu": [ "arm64" ], @@ -690,13 +724,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "cpu": [ "ia32" ], @@ -707,13 +741,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "cpu": [ "loong64" ], @@ -724,13 +758,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "cpu": [ "mips64el" ], @@ -741,13 +775,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "cpu": [ "ppc64" ], @@ -758,13 +792,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "cpu": [ "riscv64" ], @@ -775,13 +809,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "cpu": [ "s390x" ], @@ -792,13 +826,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "cpu": [ "x64" ], @@ -809,13 +843,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "cpu": [ "arm64" ], @@ -830,9 +864,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "cpu": [ "x64" ], @@ -843,13 +877,13 @@ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "cpu": [ "arm64" ], @@ -864,9 +898,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "cpu": [ "x64" ], @@ -877,13 +911,13 @@ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", "cpu": [ "arm64" ], @@ -898,9 +932,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "cpu": [ "x64" ], @@ -911,13 +945,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", "cpu": [ "arm64" ], @@ -928,13 +962,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", "cpu": [ "ia32" ], @@ -945,13 +979,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", "cpu": [ "x64" ], @@ -962,13 +996,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@exodus/bytes": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.14.1.tgz", - "integrity": "sha512-OhkBFWI6GcRMUroChZiopRiSp2iAMvEBK47NhJooDqz1RERO4QuZIZnjP63TXX8GAiLABkYmX+fuQsdJ1dd2QQ==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz", + "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==", "dev": true, "license": "MIT", "engines": { @@ -985,6 +1019,8 @@ }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", "dependencies": { @@ -994,6 +1030,8 @@ }, "node_modules/@jridgewell/remapping": { "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1003,6 +1041,8 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", "engines": { @@ -1011,11 +1051,15 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -1023,139 +1067,17 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@microsoft/api-extractor": { - "version": "7.43.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@microsoft/api-extractor-model": "7.28.13", - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "~0.16.1", - "@rushstack/node-core-library": "4.0.2", - "@rushstack/rig-package": "0.5.2", - "@rushstack/terminal": "0.10.0", - "@rushstack/ts-command-line": "4.19.1", - "lodash": "~4.17.15", - "minimatch": "~3.0.3", - "resolve": "~1.22.1", - "semver": "~7.5.4", - "source-map": "~0.6.1", - "typescript": "5.4.2" - }, - "bin": { - "api-extractor": "bin/api-extractor" - } - }, - "node_modules/@microsoft/api-extractor-model": { - "version": "7.28.13", - "dev": true, - "license": "MIT", - "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "~0.16.1", - "@rushstack/node-core-library": "4.0.2" - } - }, - "node_modules/@microsoft/api-extractor/node_modules/lru-cache": { - "version": "6.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@microsoft/api-extractor/node_modules/semver": { - "version": "7.5.4", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@microsoft/api-extractor/node_modules/typescript": { - "version": "5.4.2", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/@microsoft/api-extractor/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/@microsoft/tsdoc": { - "version": "0.14.2", - "dev": true, - "license": "MIT" - }, - "node_modules/@microsoft/tsdoc-config": { - "version": "0.16.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "ajv": "~6.12.6", - "jju": "~1.4.0", - "resolve": "~1.19.0" - } - }, - "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { - "version": "1.19.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", "dev": true, "license": "MIT" }, - "node_modules/@rollup/pluginutils": { - "version": "5.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", - "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", "cpu": [ "arm" ], @@ -1167,9 +1089,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", - "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", "cpu": [ "arm64" ], @@ -1181,7 +1103,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.55.1", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", "cpu": [ "arm64" ], @@ -1193,9 +1117,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", - "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", "cpu": [ "x64" ], @@ -1207,9 +1131,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", - "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", "cpu": [ "arm64" ], @@ -1221,9 +1145,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", - "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", "cpu": [ "x64" ], @@ -1235,13 +1159,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", - "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", "cpu": [ "arm" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1249,13 +1176,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", - "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", "cpu": [ "arm" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1263,13 +1193,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", - "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1277,13 +1210,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", - "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1291,13 +1227,16 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", - "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", "cpu": [ "loong64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1305,13 +1244,16 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", - "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", "cpu": [ "loong64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1319,13 +1261,16 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", - "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", "cpu": [ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1333,13 +1278,16 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", - "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", "cpu": [ "ppc64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1347,13 +1295,16 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", - "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", "cpu": [ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1361,13 +1312,16 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", - "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", "cpu": [ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1375,13 +1329,16 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", - "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", "cpu": [ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1389,13 +1346,16 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", - "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1403,13 +1363,16 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", - "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1417,9 +1380,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", - "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", "cpu": [ "x64" ], @@ -1431,9 +1394,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", - "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", "cpu": [ "arm64" ], @@ -1445,9 +1408,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", - "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", "cpu": [ "arm64" ], @@ -1459,9 +1422,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", - "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", "cpu": [ "ia32" ], @@ -1473,9 +1436,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", - "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", "cpu": [ "x64" ], @@ -1487,9 +1450,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", - "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", "cpu": [ "x64" ], @@ -1500,94 +1463,6 @@ "win32" ] }, - "node_modules/@rushstack/node-core-library": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "fs-extra": "~7.0.1", - "import-lazy": "~4.0.0", - "jju": "~1.4.0", - "resolve": "~1.22.1", - "semver": "~7.5.4", - "z-schema": "~5.0.2" - }, - "peerDependencies": { - "@types/node": "*" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@rushstack/node-core-library/node_modules/lru-cache": { - "version": "6.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@rushstack/node-core-library/node_modules/semver": { - "version": "7.5.4", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@rushstack/node-core-library/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/@rushstack/rig-package": { - "version": "0.5.2", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve": "~1.22.1", - "strip-json-comments": "~3.1.1" - } - }, - "node_modules/@rushstack/terminal": { - "version": "0.10.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@rushstack/node-core-library": "4.0.2", - "supports-color": "~8.1.1" - }, - "peerDependencies": { - "@types/node": "*" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@rushstack/ts-command-line": { - "version": "4.19.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@rushstack/terminal": "0.10.0", - "@types/argparse": "1.0.38", - "argparse": "~1.0.9", - "string-argv": "~0.3.1" - } - }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", @@ -1671,20 +1546,18 @@ } } }, - "node_modules/@types/argparse": { - "version": "1.0.38", - "dev": true, - "license": "MIT" - }, "node_modules/@types/aria-query": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/babel__core": { "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "license": "MIT", "dependencies": { @@ -1697,6 +1570,8 @@ }, "node_modules/@types/babel__generator": { "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, "license": "MIT", "dependencies": { @@ -1705,6 +1580,8 @@ }, "node_modules/@types/babel__template": { "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "license": "MIT", "dependencies": { @@ -1714,6 +1591,8 @@ }, "node_modules/@types/babel__traverse": { "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1739,1248 +1618,637 @@ "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.8", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/prop-types": { - "version": "15.7.15", + "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/react": { - "version": "18.3.27", + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@types/prop-types": "*", "csstype": "^3.2.2" } }, "node_modules/@types/react-dom": { - "version": "18.3.7", + "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==", "dev": true, "license": "MIT", - "peer": true, "peerDependencies": { - "@types/react": "^18.0.0" + "@types/react": "^19.2.0" } }, - "node_modules/@vitejs/plugin-react": { - "version": "4.7.0", + "node_modules/@typescript/typescript-aix-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", + "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.28.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.27", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, - "node_modules/@vitest/coverage-v8": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.18.tgz", - "integrity": "sha512-7i+N2i0+ME+2JFZhfuz7Tg/FqKtilHjGyGvoHYQ6iLV0zahbsJ9sljC9OcFcPDbhYKCet+sG8SsVqlyGvPflZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.0.18", - "ast-v8-to-istanbul": "^0.3.10", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.2.0", - "magicast": "^0.5.1", - "obug": "^2.1.1", - "std-env": "^3.10.0", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@vitest/browser": "4.0.18", - "vitest": "4.0.18" - }, - "peerDependenciesMeta": { - "@vitest/browser": { - "optional": true - } - } - }, - "node_modules/@vitest/expect": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", - "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "chai": "^6.2.1", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/pretty-format": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", - "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", - "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "4.0.18", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", - "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.0.18", - "magic-string": "^0.30.21", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", - "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", - "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.0.18", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@volar/language-core": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/source-map": "1.11.1" - } - }, - "node_modules/@volar/source-map": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "muggle-string": "^0.3.1" - } - }, - "node_modules/@volar/typescript": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/language-core": "1.11.1", - "path-browserify": "^1.0.1" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.5.26", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.5", - "@vue/shared": "3.5.26", - "entities": "^7.0.0", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.5.26", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-core": "3.5.26", - "@vue/shared": "3.5.26" - } - }, - "node_modules/@vue/language-core": { - "version": "1.8.27", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/language-core": "~1.11.1", - "@volar/source-map": "~1.11.1", - "@vue/compiler-dom": "^3.3.0", - "@vue/shared": "^3.3.0", - "computeds": "^0.0.1", - "minimatch": "^9.0.3", - "muggle-string": "^0.3.1", - "path-browserify": "^1.0.1", - "vue-template-compiler": "^2.7.14" - }, - "peerDependencies": { - "typescript": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@vue/language-core/node_modules/brace-expansion": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@vue/language-core/node_modules/minimatch": { - "version": "9.0.5", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vue/shared": { - "version": "3.5.26", - "dev": true, - "license": "MIT" - }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "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/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/ast-v8-to-istanbul": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.12.tgz", - "integrity": "sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.31", - "estree-walker": "^3.0.3", - "js-tokens": "^10.0.0" - } - }, - "node_modules/ast-v8-to-istanbul/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", - "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.15", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/bidi-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", - "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", - "dev": true, - "license": "MIT", - "dependencies": { - "require-from-string": "^2.0.2" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/browserslist": { - "version": "4.28.1", - "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", - "peer": true, - "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001765", - "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/chai": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", - "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/commander": { - "version": "9.5.0", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/computeds": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/css-tree": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", - "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "mdn-data": "2.12.2", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cssstyle": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-6.2.0.tgz", - "integrity": "sha512-Fm5NvhYathRnXNVndkUsCCuR63DCLVVwGOOwQw782coXFi5HhkXdu289l59HlXZBawsyNccXfWRYvLzcDCdDig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@asamuzakjp/css-color": "^5.0.1", - "@csstools/css-syntax-patches-for-csstree": "^1.0.28", - "css-tree": "^3.1.0", - "lru-cache": "^11.2.6" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/cssstyle/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/csstype": { - "version": "3.2.3", - "dev": true, - "license": "MIT" - }, - "node_modules/data-urls": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", - "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-mimetype": "^5.0.0", - "whatwg-url": "^16.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - } - }, - "node_modules/de-indent": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decimal.js": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", - "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", - "dev": true, - "license": "MIT" - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=6" + "node": ">=16.20.0" } }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true, - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.267", - "dev": true, - "license": "ISC" - }, - "node_modules/entities": { - "version": "7.0.0", + "node_modules/@typescript/typescript-darwin-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", + "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-2-Clause", + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node": ">=16.20.0" } }, - "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.21.5", + "node_modules/@typescript/typescript-darwin-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", + "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", + "cpu": [ + "x64" + ], "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "node": ">=16.20.0" } }, - "node_modules/escalade": { - "version": "3.2.0", + "node_modules/@typescript/typescript-freebsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", + "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6" + "node": ">=16.20.0" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/expect-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "node_modules/@typescript/typescript-freebsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", + "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "cpu": [ + "x64" + ], "dev": true, "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=12.0.0" + "node": ">=16.20.0" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "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==", + "node_modules/@typescript/typescript-linux-arm": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", + "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "node": ">=16.20.0" } }, - "node_modules/fs-extra": { - "version": "7.0.1", + "node_modules/@typescript/typescript-linux-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", + "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6 <7 || >=8" + "node": ">=16.20.0" } }, - "node_modules/fsevents": { - "version": "2.3.3", + "node_modules/@typescript/typescript-linux-loong64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", + "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "cpu": [ + "loong64" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=16.20.0" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", + "node_modules/@typescript/typescript-linux-mips64el": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", + "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "cpu": [ + "mips64el" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=16.20.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "dev": true, - "license": "ISC" - }, - "node_modules/has-flag": { - "version": "4.0.0", + "node_modules/@typescript/typescript-linux-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", + "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=16.20.0" } }, - "node_modules/hasown": { - "version": "2.0.2", + "node_modules/@typescript/typescript-linux-riscv64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", + "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "cpu": [ + "riscv64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" + "node": ">=16.20.0" } }, - "node_modules/html-encoding-sniffer": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", - "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", + "node_modules/@typescript/typescript-linux-s390x": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", + "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "cpu": [ + "s390x" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@exodus/bytes": "^1.6.0" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": ">=16.20.0" } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "node_modules/@typescript/typescript-linux-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", + "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/http-proxy-agent": { + "node_modules/@typescript/typescript-netbsd-arm64": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", + "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">= 14" + "node": ">=16.20.0" } }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "node_modules/@typescript/typescript-netbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", + "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">= 14" + "node": ">=16.20.0" } }, - "node_modules/import-lazy": { - "version": "4.0.0", + "node_modules/@typescript/typescript-openbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", + "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=8" + "node": ">=16.20.0" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "node_modules/@typescript/typescript-openbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", + "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=8" + "node": ">=16.20.0" } }, - "node_modules/is-core-module": { - "version": "2.16.1", + "node_modules/@typescript/typescript-sunos-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", + "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=16.20.0" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "node_modules/@typescript/typescript-win32-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", + "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-3-Clause", + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": ">=16.20.0" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "node_modules/@typescript/typescript-win32-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", + "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" + "node": ">=16.20.0" } }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@vitejs/plugin-react": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz", + "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "node": "^20.19.0 || >=22.12.0" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/jju": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/jsdom": { - "version": "28.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-28.1.0.tgz", - "integrity": "sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==", + "node_modules/@vitest/coverage-v8": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.10.tgz", + "integrity": "sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@acemir/cssom": "^0.9.31", - "@asamuzakjp/dom-selector": "^6.8.1", - "@bramus/specificity": "^2.4.2", - "@exodus/bytes": "^1.11.0", - "cssstyle": "^6.0.1", - "data-urls": "^7.0.0", - "decimal.js": "^10.6.0", - "html-encoding-sniffer": "^6.0.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.6", - "is-potential-custom-element-name": "^1.0.1", - "parse5": "^8.0.0", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^6.0.0", - "undici": "^7.21.0", - "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^8.0.1", - "whatwg-mimetype": "^5.0.0", - "whatwg-url": "^16.0.0", - "xml-name-validator": "^5.0.0" + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.10", + "ast-v8-to-istanbul": "^1.0.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "funding": { + "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "canvas": "^3.0.0" + "@vitest/browser": "4.1.10", + "vitest": "4.1.10" }, "peerDependenciesMeta": { - "canvas": { + "@vitest/browser": { "optional": true } } }, - "node_modules/jsesc": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/kolorist": { - "version": "1.8.0", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash": { - "version": "4.17.21", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "dev": true, - "license": "MIT" - }, - "node_modules/loose-envify": { - "version": "1.4.0", + "node_modules/@vitest/expect": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", + "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", "dev": true, "license": "MIT", "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "dev": true, - "license": "MIT", - "bin": { - "lz-string": "bin/bin.js" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/magic-string": { - "version": "0.30.21", + "node_modules/@vitest/mocker": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", + "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "@vitest/spy": "4.1.10", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, - "node_modules/magicast": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", - "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", + "node_modules/@vitest/pretty-format": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", + "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "source-map-js": "^1.2.1" + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "node_modules/@vitest/runner": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", + "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" + "@vitest/utils": "4.1.10", + "pathe": "^2.0.3" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "node_modules/@vitest/snapshot": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", + "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "@vitest/utils": "4.1.10", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/mdn-data": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", - "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "node_modules/@vitest/spy": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", + "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=4" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/minimatch": { - "version": "3.0.8", + "node_modules/@vitest/utils": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", + "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@vitest/pretty-format": "4.1.10", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" }, - "engines": { - "node": "*" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/ms": { - "version": "2.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/muggle-string": { - "version": "0.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, + "peer": true, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=8" } }, - "node_modules/node-releases": { - "version": "2.0.27", - "dev": true, - "license": "MIT" - }, - "node_modules/obug": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", - "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", - "dev": true, - "funding": [ - "https://github.com/sponsors/sxzz", - "https://opencollective.com/debug" - ], - "license": "MIT" - }, - "node_modules/parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", - "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "dependencies": { - "entities": "^6.0.0" + "peer": true, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/parse5/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" } }, - "node_modules/path-browserify": { - "version": "1.0.1", + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=12" + } }, - "node_modules/path-parse": { - "version": "1.0.7", + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.5.tgz", + "integrity": "sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", "dev": true, "license": "MIT" }, - "node_modules/picocolors": { - "version": "1.1.1", + "node_modules/baseline-browser-mapping": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.0.tgz", + "integrity": "sha512-oCu2wfipvX3AePSgmOuKkIywOu+8n9psz7hXYmk56ghpu3+7KzNIBopaOs4c9BrtdnTtW30unG9GTfHo7EwERQ==", "dev": true, - "license": "ISC" + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } }, - "node_modules/picomatch": { - "version": "4.0.3", + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "dependencies": { + "require-from-string": "^2.0.2" } }, - "node_modules/postcss": { - "version": "8.5.6", + "node_modules/browserslist": { + "version": "4.28.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.7.tgz", + "integrity": "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==", "dev": true, "funding": [ { "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" + "url": "https://tidelift.com/funding/github/npm/browserslist" }, { "type": "github", @@ -2989,1106 +2257,1066 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "baseline-browser-mapping": "^2.10.44", + "caniuse-lite": "^1.0.30001806", + "electron-to-chromium": "^1.5.393", + "node-releases": "^2.0.51", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "node_modules/caniuse-lite": { + "version": "1.0.30001806", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz", + "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==", "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } + "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/punycode": { - "version": "2.3.1", + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=18" } }, - "node_modules/react": { - "version": "18.3.1", + "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/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "loose-envify": "^1.1.0" + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, - "node_modules/react-dom": { - "version": "18.3.1", + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } + "license": "MIT" }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "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==", "dev": true, "license": "MIT" }, - "node_modules/react-refresh": { - "version": "0.17.0", + "node_modules/data-urls": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", "dev": true, "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "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": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" + "ms": "^2.1.3" }, "engines": { - "node": ">=8" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/resolve": { - "version": "1.22.11", + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, + "peer": true + }, + "node_modules/electron-to-chromium": { + "version": "1.5.395", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.395.tgz", + "integrity": "sha512-7zt9Aw+SrmxLWLN0zhaTWZQiCdryLVrYTq5R7iZakLvi2UQPYMMsROYV/2qVCzMeCiSXHwKOU+sZ4zOVVlrtKA==", + "dev": true, + "license": "ISC" + }, + "node_modules/entities": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">= 0.4" + "node": ">=20.19.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/rollup": { - "version": "4.55.1", + "node_modules/es-module-lexer": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, "bin": { - "rollup": "dist/bin/rollup" + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "node": ">=18" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.55.1", - "@rollup/rollup-android-arm64": "4.55.1", - "@rollup/rollup-darwin-arm64": "4.55.1", - "@rollup/rollup-darwin-x64": "4.55.1", - "@rollup/rollup-freebsd-arm64": "4.55.1", - "@rollup/rollup-freebsd-x64": "4.55.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", - "@rollup/rollup-linux-arm-musleabihf": "4.55.1", - "@rollup/rollup-linux-arm64-gnu": "4.55.1", - "@rollup/rollup-linux-arm64-musl": "4.55.1", - "@rollup/rollup-linux-loong64-gnu": "4.55.1", - "@rollup/rollup-linux-loong64-musl": "4.55.1", - "@rollup/rollup-linux-ppc64-gnu": "4.55.1", - "@rollup/rollup-linux-ppc64-musl": "4.55.1", - "@rollup/rollup-linux-riscv64-gnu": "4.55.1", - "@rollup/rollup-linux-riscv64-musl": "4.55.1", - "@rollup/rollup-linux-s390x-gnu": "4.55.1", - "@rollup/rollup-linux-x64-gnu": "4.55.1", - "@rollup/rollup-linux-x64-musl": "4.55.1", - "@rollup/rollup-openbsd-x64": "4.55.1", - "@rollup/rollup-openharmony-arm64": "4.55.1", - "@rollup/rollup-win32-arm64-msvc": "4.55.1", - "@rollup/rollup-win32-ia32-msvc": "4.55.1", - "@rollup/rollup-win32-x64-gnu": "4.55.1", - "@rollup/rollup-win32-x64-msvc": "4.55.1", - "fsevents": "~2.3.2" + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" } }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "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": "ISC", - "dependencies": { - "xmlchars": "^2.2.0" - }, + "license": "MIT", "engines": { - "node": ">=v12.22.7" + "node": ">=6" } }, - "node_modules/scheduler": { - "version": "0.23.2", + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0" + "@types/estree": "^1.0.0" } }, - "node_modules/semver": { - "version": "6.3.1", + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" } }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } }, - "node_modules/source-map": { - "version": "0.6.1", + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, - "license": "BSD-3-Clause", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.10.0" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/source-map-js": { - "version": "1.2.1", + "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": "BSD-3-Clause", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "BSD-3-Clause" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.6.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, "license": "MIT" }, - "node_modules/string-argv": { - "version": "0.3.2", + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.6.19" + "node": ">=8" } }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true, - "license": "MIT", - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/strip-json-comments": { - "version": "3.1.1", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/supports-color": { - "version": "8.1.1", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "has-flag": "^4.0.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "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/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "node_modules/jsdom": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz", + "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==", "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^5.1.11", + "@asamuzakjp/dom-selector": "^7.1.1", + "@bramus/specificity": "^2.4.2", + "@csstools/css-syntax-patches-for-csstree": "^1.1.3", + "@exodus/bytes": "^1.15.0", + "css-tree": "^3.2.1", + "data-urls": "^7.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.3.5", + "parse5": "^8.0.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.1", + "undici": "^7.25.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.1", + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.1", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=18" + "node": "20 || >=22" } }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "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", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "bin": { + "jsesc": "bin/jsesc" }, "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "node": ">=6" } }, - "node_modules/tinyrainbow": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", - "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "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": ">=14.0.0" + "node": ">=6" } }, - "node_modules/tldts": { - "version": "7.0.24", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.24.tgz", - "integrity": "sha512-1r6vQTTt1rUiJkI5vX7KG8PR342Ru/5Oh13kEQP2SMbRSZpOey9SrBe27IDxkoWulx8ShWu4K6C0BkctP8Z1bQ==", + "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": "MIT", + "license": "ISC", "dependencies": { - "tldts-core": "^7.0.24" - }, + "yallist": "^3.0.2" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "license": "MIT", + "peer": true, "bin": { - "tldts": "bin/cli.js" + "lz-string": "bin/bin.js" } }, - "node_modules/tldts-core": { - "version": "7.0.24", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.24.tgz", - "integrity": "sha512-pj7yygNMoMRqG7ML2SDQ0xNIOfN3IBDUcPVM2Sg6hP96oFNN2nqnzHreT3z9xLq85IWJyNTvD38O002DdOrPMw==", + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } }, - "node_modules/tough-cookie": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", - "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", + "node_modules/magicast": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.3.tgz", + "integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "tldts": "^7.0.5" - }, - "engines": { - "node": ">=16" + "@babel/parser": "^7.29.3", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" } }, - "node_modules/tr46": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", - "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "license": "MIT", "dependencies": { - "punycode": "^2.3.1" + "semver": "^7.5.3" }, "engines": { - "node": ">=20" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typescript": { - "version": "5.9.3", + "node_modules/make-dir/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, - "license": "Apache-2.0", - "peer": true, + "license": "ISC", "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "semver": "bin/semver.js" }, "engines": { - "node": ">=14.17" + "node": ">=10" } }, - "node_modules/undici": { - "version": "7.22.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.22.0.tgz", - "integrity": "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==", + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.18.1" - } + "license": "CC0-1.0" }, - "node_modules/universalify": { - "version": "0.1.2", + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 4.0.0" + "node": ">=4" } }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", "dev": true, "funding": [ - { - "type": "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" + "nanoid": "bin/nanoid.cjs" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/uri-js": { - "version": "4.4.1", + "node_modules/node-releases": { + "version": "2.0.51", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz", + "integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" + "license": "MIT", + "engines": { + "node": ">=18" } }, - "node_modules/validator": { - "version": "13.15.26", + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=12.20.0" } }, - "node_modules/vite": { - "version": "5.4.21", + "node_modules/parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" + "entities": "^8.0.0" }, "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/vite-plugin-dts": { - "version": "3.9.1", + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, - "license": "MIT", - "dependencies": { - "@microsoft/api-extractor": "7.43.0", - "@rollup/pluginutils": "^5.1.0", - "@vue/language-core": "^1.8.27", - "debug": "^4.3.4", - "kolorist": "^1.8.0", - "magic-string": "^0.30.8", - "vue-tsc": "^1.8.27" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "typescript": "*", - "vite": "*" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } - } + "license": "MIT" }, - "node_modules/vitest": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", - "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "4.0.18", - "@vitest/mocker": "4.0.18", - "@vitest/pretty-format": "4.0.18", - "@vitest/runner": "4.0.18", - "@vitest/snapshot": "4.0.18", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "es-module-lexer": "^1.7.0", - "expect-type": "^1.2.2", - "magic-string": "^0.30.21", - "obug": "^2.1.1", - "pathe": "^2.0.3", - "picomatch": "^4.0.3", - "std-env": "^3.10.0", - "tinybench": "^2.9.0", - "tinyexec": "^1.0.2", - "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.0.3", - "vite": "^6.0.0 || ^7.0.0", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@opentelemetry/api": "^1.9.0", - "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.18", - "@vitest/browser-preview": "4.0.18", - "@vitest/browser-webdriverio": "4.0.18", - "@vitest/ui": "4.0.18", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@opentelemetry/api": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser-playwright": { - "optional": true - }, - "@vitest/browser-preview": { - "optional": true - }, - "@vitest/browser-webdriverio": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } + "license": "ISC" }, - "node_modules/vitest/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", - "cpu": [ - "ppc64" - ], + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/vitest/node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], + "node_modules/postcss": { + "version": "8.5.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.21.tgz", + "integrity": "sha512-v4sDNP3fdNiWMfabO7OwOQdOX8TiQSztKyT1Wj0w+j7LDallJThJRBBBmzVGyYj0crMh7jlV4zepPkiNu9UwDQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, "engines": { - "node": ">=18" + "node": "^10 || ^12 || >=14" } }, - "node_modules/vitest/node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", - "cpu": [ - "arm64" - ], + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, "engines": { - "node": ">=18" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/vitest/node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", - "cpu": [ - "x64" - ], + "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", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=18" + "node": ">=6" } }, - "node_modules/vitest/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", - "cpu": [ - "arm64" - ], + "node_modules/react": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", + "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/vitest/node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", - "cpu": [ - "x64" - ], + "node_modules/react-dom": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", + "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.8" } }, - "node_modules/vitest/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", - "cpu": [ - "arm64" - ], + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } + "peer": true }, - "node_modules/vitest/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", - "cpu": [ - "x64" - ], + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/vitest/node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", - "cpu": [ - "arm" - ], + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/vitest/node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", - "cpu": [ - "arm64" - ], + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/vitest/node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", - "cpu": [ - "ia32" - ], + "node_modules/rollup": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", + "fsevents": "~2.3.2" } }, - "node_modules/vitest/node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", - "cpu": [ - "loong64" - ], + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, "engines": { - "node": ">=18" + "node": ">=v12.22.7" } }, - "node_modules/vitest/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", - "cpu": [ - "mips64el" - ], + "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==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } + "license": "MIT" }, - "node_modules/vitest/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", - "cpu": [ - "ppc64" - ], + "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": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/vitest/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", - "cpu": [ - "riscv64" - ], + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } + "license": "ISC" }, - "node_modules/vitest/node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", - "cpu": [ - "s390x" - ], + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "BSD-3-Clause", "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/vitest/node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", - "cpu": [ - "x64" - ], + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", + "dev": true, + "license": "MIT" + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "min-indent": "^1.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/vitest/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", - "cpu": [ - "x64" - ], + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/vitest/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", - "cpu": [ - "x64" - ], + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], "engines": { "node": ">=18" } }, - "node_modules/vitest/node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", - "cpu": [ - "x64" - ], + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, "engines": { - "node": ">=18" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/vitest/node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", - "cpu": [ - "arm64" - ], + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=18" + "node": ">=14.0.0" } }, - "node_modules/vitest/node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", - "cpu": [ - "ia32" - ], + "node_modules/tldts": { + "version": "7.4.9", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.9.tgz", + "integrity": "sha512-3kZ8wQQ/k5DrChD4X4FVvr2D7E5uoRgAqkPyLpSCGUvqOvqu+JEdr3mwMUaVWb+vMHZaKhF5fp2PBigKsui7hA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "dependencies": { + "tldts-core": "^7.4.9" + }, + "bin": { + "tldts": "bin/cli.js" } }, - "node_modules/vitest/node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", - "cpu": [ - "x64" - ], + "node_modules/tldts-core": { + "version": "7.4.9", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.9.tgz", + "integrity": "sha512-DxKfPBI52p2msTEu7MPhdpdDTBhhVQg1a/8PjQckeyAvO13eMYElX545grIp6nnTGIMZlRvFZPvFhvI/WIz2Vg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "license": "MIT" + }, + "node_modules/tough-cookie": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.2.tgz", + "integrity": "sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, "engines": { - "node": ">=18" + "node": ">=16" } }, - "node_modules/vitest/node_modules/@vitest/mocker": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", - "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", + "node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.0.18", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.21" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0-0" + "punycode": "^2.3.1" }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } + "engines": { + "node": ">=20" } }, - "node_modules/vitest/node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "node_modules/typescript": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", + "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", "dev": true, - "hasInstallScript": true, - "license": "MIT", + "license": "Apache-2.0", "bin": { - "esbuild": "bin/esbuild" + "tsc": "bin/tsc" }, "engines": { - "node": ">=18" + "node": ">=16.20.0" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" - } - }, - "node_modules/vitest/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "@typescript/typescript-aix-ppc64": "7.0.2", + "@typescript/typescript-darwin-arm64": "7.0.2", + "@typescript/typescript-darwin-x64": "7.0.2", + "@typescript/typescript-freebsd-arm64": "7.0.2", + "@typescript/typescript-freebsd-x64": "7.0.2", + "@typescript/typescript-linux-arm": "7.0.2", + "@typescript/typescript-linux-arm64": "7.0.2", + "@typescript/typescript-linux-loong64": "7.0.2", + "@typescript/typescript-linux-mips64el": "7.0.2", + "@typescript/typescript-linux-ppc64": "7.0.2", + "@typescript/typescript-linux-riscv64": "7.0.2", + "@typescript/typescript-linux-s390x": "7.0.2", + "@typescript/typescript-linux-x64": "7.0.2", + "@typescript/typescript-netbsd-arm64": "7.0.2", + "@typescript/typescript-netbsd-x64": "7.0.2", + "@typescript/typescript-openbsd-arm64": "7.0.2", + "@typescript/typescript-openbsd-x64": "7.0.2", + "@typescript/typescript-sunos-x64": "7.0.2", + "@typescript/typescript-win32-arm64": "7.0.2", + "@typescript/typescript-win32-x64": "7.0.2" + } + }, + "node_modules/undici": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", + "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "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": { - "@types/estree": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/vitest/node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "node_modules/vite": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz", + "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "esbuild": "^0.27.0", + "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", @@ -4156,40 +3384,94 @@ } } }, - "node_modules/vue-template-compiler": { - "version": "2.7.16", - "dev": true, - "license": "MIT", - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } - }, - "node_modules/vue-tsc": { - "version": "1.8.27", + "node_modules/vitest": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", + "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", "dev": true, "license": "MIT", "dependencies": { - "@volar/typescript": "~1.11.1", - "@vue/language-core": "1.8.27", - "semver": "^7.5.4" + "@vitest/expect": "4.1.10", + "@vitest/mocker": "4.1.10", + "@vitest/pretty-format": "4.1.10", + "@vitest/runner": "4.1.10", + "@vitest/snapshot": "4.1.10", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" }, "bin": { - "vue-tsc": "bin/vue-tsc.js" + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "typescript": "*" - } - }, - "node_modules/vue-tsc/node_modules/semver": { - "version": "7.7.3", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.10", + "@vitest/browser-preview": "4.1.10", + "@vitest/browser-webdriverio": "4.1.10", + "@vitest/coverage-istanbul": "4.1.10", + "@vitest/coverage-v8": "4.1.10", + "@vitest/ui": "4.1.10", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } } }, "node_modules/w3c-xmlserializer": { @@ -4276,27 +3558,10 @@ }, "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/z-schema": { - "version": "5.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "validator": "^13.7.0" - }, - "bin": { - "z-schema": "bin/z-schema" - }, - "engines": { - "node": ">=8.0.0" - }, - "optionalDependencies": { - "commander": "^9.4.1" - } } } } diff --git a/package.json b/package.json index 48c7769..31a5765 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "@chartgpu/chartgpu-react", - "version": "0.1.4", - "description": "React bindings for ChartGPU - WebGPU-powered charting library", + "name": "chartgpu-react", + "version": "0.3.0", + "description": "React bindings for ChartGPU — WebGPU-powered high-performance charts", "license": "MIT", "author": "", "type": "module", @@ -21,35 +21,53 @@ "react", "chart", "webgpu", - "visualization" + "visualization", + "streaming", + "typescript" ], + "repository": { + "type": "git", + "url": "https://github.com/ChartGPU/chartgpu-react.git" + }, + "homepage": "https://github.com/ChartGPU/chartgpu-react#readme", + "bugs": { + "url": "https://github.com/ChartGPU/chartgpu-react/issues" + }, "scripts": { "dev": "vite", - "build": "npm run typecheck && vite build", - "typecheck": "tsc --noEmit", + "build": "npm run typecheck && vite build && tsc -p tsconfig.build.json", + "typecheck": "tsc --noEmit -p tsconfig.json", "preview": "vite preview", "test": "vitest run", "test:watch": "vitest" }, "peerDependencies": { - "@chartgpu/chartgpu": "^0.2.8", + "@chartgpu/chartgpu": "^0.3.6", "react": ">=18.0.0", "react-dom": ">=18.0.0" }, + "peerDependenciesMeta": { + "react-dom": { + "optional": false + } + }, "devDependencies": { - "@chartgpu/chartgpu": "^0.2.8", + "@chartgpu/chartgpu": "^0.3.6", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", - "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", - "@vitejs/plugin-react": "^4.2.1", - "@vitest/coverage-v8": "^4.0.18", - "jsdom": "^28.1.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "typescript": "^5.3.3", - "vite": "^5.1.4", - "vite-plugin-dts": "^3.7.3", - "vitest": "^4.0.18" - } + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.0.3", + "@vitest/coverage-v8": "^4.1.10", + "jsdom": "^29.1.1", + "react": "^19.2.8", + "react-dom": "^19.2.8", + "typescript": "^7.0.2", + "vite": "^7.1.5", + "vitest": "^4.1.10" + }, + "engines": { + "node": ">=20" + }, + "sideEffects": false } diff --git a/src/ChartGPU.tsx b/src/ChartGPU.tsx index 919b201..2407dd1 100644 --- a/src/ChartGPU.tsx +++ b/src/ChartGPU.tsx @@ -100,10 +100,10 @@ export const ChartGPU = forwardRef( () => ({ getChart: () => instanceRef.current, getContainer: () => containerRef.current, - appendData: (seriesIndex: number, newPoints) => { + appendData: (seriesIndex, newPoints, options) => { const instance = instanceRef.current; if (instance && !instance.disposed) { - instance.appendData(seriesIndex, newPoints); + instance.appendData(seriesIndex, newPoints, options); } }, renderFrame: () => { @@ -139,10 +139,10 @@ export const ChartGPU = forwardRef( instance.setOption(newOptions); } }, - setZoomRange: (start: number, end: number) => { + setZoomRange: (start: number, end: number, source?: unknown) => { const instance = instanceRef.current; if (instance && !instance.disposed) { - instance.setZoomRange(start, end); + instance.setZoomRange(start, end, source); } }, setInteractionX: (x: number | null, source?: unknown) => { diff --git a/src/ChartGPUChart.tsx b/src/ChartGPUChart.tsx index e37f2a9..fcb55f8 100644 --- a/src/ChartGPUChart.tsx +++ b/src/ChartGPUChart.tsx @@ -1,5 +1,4 @@ -import { useCallback, useEffect, useMemo, useRef } from 'react'; -import type { CSSProperties } from 'react'; +import { useCallback, useEffect, useMemo, useRef, type CSSProperties, type ReactElement } from 'react'; import type { ChartGPUOptions, ChartGPUInstance } from '@chartgpu/chartgpu'; import { ChartGPU } from './ChartGPU'; @@ -74,7 +73,7 @@ export function ChartGPUChart({ style, onInit, onDispose, -}: ChartGPUChartProps): JSX.Element { +}: ChartGPUChartProps): ReactElement { const didInitRef = useRef(false); const onInitRef = useRef(onInit); diff --git a/src/__tests__/ChartGPU.test.tsx b/src/__tests__/ChartGPU.test.tsx index acba555..13a1c75 100644 --- a/src/__tests__/ChartGPU.test.tsx +++ b/src/__tests__/ChartGPU.test.tsx @@ -1,19 +1,13 @@ /** - * Tests for ChartGPU.tsx — verifying the createdWithOptionsRef race-condition fix. - * - * The fix: ChartGPU.create() is async. When it resolves, React schedules a - * setOption effect. Without the fix, that effect would redundantly call - * setOption(options) even though create() already initialised with those - * options, potentially crashing during the internal init sequence. - * - * createdWithOptionsRef snapshots { options, theme } before the async create - * call. The first post-create invocation of the setOption effect is - * unconditionally skipped (issue #16). + * Tests for ChartGPU.tsx — race-condition fix (issue #16), 0.3.x handle + * forwarding, gpuContext create path, and event prop wiring. */ +import { createRef, type ComponentProps } from 'react'; import { render, act, waitFor } from '@testing-library/react'; import { vi, describe, it, expect, beforeEach } from 'vitest'; import { ChartGPU } from '../ChartGPU'; +import type { ChartGPUHandle } from '../types'; import type { ChartGPUOptions } from '@chartgpu/chartgpu'; // --------------------------------------------------------------------------- @@ -87,6 +81,14 @@ async function waitForChartInit() { }); } +async function renderWithHandle(props: ComponentProps = { options: makeOptions() }) { + const ref = createRef(); + const result = render(); + await waitForChartInit(); + expect(ref.current).not.toBeNull(); + return { ref, ...result }; +} + // --------------------------------------------------------------------------- // Setup // --------------------------------------------------------------------------- @@ -197,3 +199,283 @@ describe('ChartGPU component — createdWithOptionsRef race-condition fix', () = expect(mockInstance.setOption).not.toHaveBeenCalled(); }); }); + +describe('ChartGPU handle — appendData (0.3.x maxPoints)', () => { + it('forwards seriesIndex, points, and { maxPoints } to the instance', async () => { + const { ref } = await renderWithHandle(); + const points = [{ x: 1, y: 2 }]; + + ref.current!.appendData(0, points, { maxPoints: 50_000 }); + + expect(mockInstance.appendData).toHaveBeenCalledTimes(1); + expect(mockInstance.appendData).toHaveBeenCalledWith(0, points, { maxPoints: 50_000 }); + }); + + it('forwards a two-arg call (options may be undefined)', async () => { + const { ref } = await renderWithHandle(); + const points = [{ x: 3, y: 4 }]; + + ref.current!.appendData(1, points); + + expect(mockInstance.appendData).toHaveBeenCalledTimes(1); + // Implementation always passes the options parameter (undefined when omitted). + expect(mockInstance.appendData).toHaveBeenCalledWith(1, points, undefined); + }); + + it('no-ops after the instance is disposed without throwing', async () => { + const { ref } = await renderWithHandle(); + mockInstance.disposed = true; + + expect(() => { + ref.current!.appendData(0, [{ x: 1, y: 2 }], { maxPoints: 100 }); + }).not.toThrow(); + expect(mockInstance.appendData).not.toHaveBeenCalled(); + }); + + it('no-ops after unmount without throwing', async () => { + const { ref, unmount } = await renderWithHandle(); + // React clears ref.current on unmount; keep the handle object to exercise no-ops. + const handle = ref.current!; + unmount(); + + expect(() => { + handle.appendData(0, [{ x: 1, y: 2 }], { maxPoints: 100 }); + }).not.toThrow(); + expect(mockInstance.appendData).not.toHaveBeenCalled(); + }); +}); + +describe('ChartGPU handle — setZoomRange source', () => { + it('forwards start, end, and source to the instance', async () => { + const { ref } = await renderWithHandle(); + + ref.current!.setZoomRange(10, 90, 'test-source'); + + expect(mockInstance.setZoomRange).toHaveBeenCalledTimes(1); + expect(mockInstance.setZoomRange).toHaveBeenCalledWith(10, 90, 'test-source'); + }); + + it('forwards a two-arg call (source may be undefined)', async () => { + const { ref } = await renderWithHandle(); + + ref.current!.setZoomRange(0, 100); + + expect(mockInstance.setZoomRange).toHaveBeenCalledTimes(1); + expect(mockInstance.setZoomRange).toHaveBeenCalledWith(0, 100, undefined); + }); +}); + +describe('ChartGPU handle — external render methods', () => { + it('forwards setRenderMode / getRenderMode / needsRender / renderFrame when ready', async () => { + mockInstance.getRenderMode.mockReturnValue('auto'); + mockInstance.needsRender.mockReturnValue(true); + mockInstance.renderFrame.mockReturnValue(true); + + const { ref } = await renderWithHandle(); + + ref.current!.setRenderMode('external'); + expect(mockInstance.setRenderMode).toHaveBeenCalledTimes(1); + expect(mockInstance.setRenderMode).toHaveBeenCalledWith('external'); + + expect(ref.current!.getRenderMode()).toBe('auto'); + expect(mockInstance.getRenderMode).toHaveBeenCalledTimes(1); + + expect(ref.current!.needsRender()).toBe(true); + expect(mockInstance.needsRender).toHaveBeenCalledTimes(1); + + expect(ref.current!.renderFrame()).toBe(true); + expect(mockInstance.renderFrame).toHaveBeenCalledTimes(1); + }); + + it('returns disposed defaults when the instance is null (unmount)', async () => { + const { ref, unmount } = await renderWithHandle(); + const handle = ref.current!; + unmount(); + + expect(handle.needsRender()).toBe(false); + expect(handle.renderFrame()).toBe(false); + expect(handle.getRenderMode()).toBe('auto'); + // setRenderMode should no-op without throwing + expect(() => handle.setRenderMode('external')).not.toThrow(); + expect(mockInstance.setRenderMode).not.toHaveBeenCalled(); + expect(mockInstance.needsRender).not.toHaveBeenCalled(); + expect(mockInstance.renderFrame).not.toHaveBeenCalled(); + expect(mockInstance.getRenderMode).not.toHaveBeenCalled(); + }); + + it('returns disposed defaults when the live instance has disposed: true', async () => { + mockInstance.needsRender.mockReturnValue(true); + mockInstance.renderFrame.mockReturnValue(true); + mockInstance.getRenderMode.mockReturnValue('external' as never); + + const { ref } = await renderWithHandle(); + // Instance still referenced by the handle, but marked disposed (short-circuit path). + mockInstance.disposed = true; + + expect(ref.current!.needsRender()).toBe(false); + expect(ref.current!.renderFrame()).toBe(false); + expect(ref.current!.getRenderMode()).toBe('auto'); + expect(() => ref.current!.setRenderMode('auto')).not.toThrow(); + + expect(mockInstance.needsRender).not.toHaveBeenCalled(); + expect(mockInstance.renderFrame).not.toHaveBeenCalled(); + expect(mockInstance.getRenderMode).not.toHaveBeenCalled(); + expect(mockInstance.setRenderMode).not.toHaveBeenCalled(); + }); +}); + +describe('ChartGPU — gpuContext create path', () => { + it('passes gpuContext as the third argument to ChartGPU.create', async () => { + const gpuContext = { + adapter: { id: 'adapter' } as any, + device: { id: 'device' } as any, + pipelineCache: { id: 'cache' } as any, + }; + + render(); + await waitForChartInit(); + + expect(mockCreate).toHaveBeenCalledTimes(1); + const args = mockCreate.mock.calls[0]; + expect(args).toHaveLength(3); + expect(args[0]).toBeInstanceOf(HTMLElement); + expect(args[1]).toEqual(expect.objectContaining({ _testLabel: 'ctx' })); + expect(args[2]).toBe(gpuContext); + }); + + it('calls create with two args when gpuContext is not provided', async () => { + render(); + await waitForChartInit(); + + expect(mockCreate).toHaveBeenCalledTimes(1); + const args = mockCreate.mock.calls[0]; + expect(args).toHaveLength(2); + expect(args[0]).toBeInstanceOf(HTMLElement); + expect(args[1]).toEqual(expect.objectContaining({ _testLabel: 'no-ctx' })); + }); +}); + +describe('ChartGPU events — onDataAppend / onDeviceLost', () => { + it('subscribes to dataAppend and deviceLost and invokes prop handlers', async () => { + const onDataAppend = vi.fn(); + const onDeviceLost = vi.fn(); + + render( + + ); + await waitForChartInit(); + + const onCalls = mockInstance.on.mock.calls as Array<[string, (...args: unknown[]) => void]>; + const dataAppendCall = onCalls.find(([event]) => event === 'dataAppend'); + const deviceLostCall = onCalls.find(([event]) => event === 'deviceLost'); + + expect(dataAppendCall).toBeDefined(); + expect(typeof dataAppendCall![1]).toBe('function'); + expect(deviceLostCall).toBeDefined(); + expect(typeof deviceLostCall![1]).toBe('function'); + + const appendPayload = { + seriesIndex: 0, + count: 3, + xExtent: { min: 0, max: 2 }, + }; + const lostPayload = { reason: 'destroyed' }; + + dataAppendCall![1](appendPayload); + deviceLostCall![1](lostPayload); + + expect(onDataAppend).toHaveBeenCalledTimes(1); + expect(onDataAppend).toHaveBeenCalledWith(appendPayload); + expect(onDeviceLost).toHaveBeenCalledTimes(1); + expect(onDeviceLost).toHaveBeenCalledWith(lostPayload); + }); + + it('unsubscribes dataAppend and deviceLost handlers on unmount', async () => { + const { unmount } = render( + {}} + onDeviceLost={() => {}} + /> + ); + await waitForChartInit(); + + const dataAppendOn = (mockInstance.on.mock.calls as Array<[string, unknown]>).find( + ([event]) => event === 'dataAppend' + ); + const deviceLostOn = (mockInstance.on.mock.calls as Array<[string, unknown]>).find( + ([event]) => event === 'deviceLost' + ); + expect(dataAppendOn).toBeDefined(); + expect(deviceLostOn).toBeDefined(); + + unmount(); + + const offCalls = mockInstance.off.mock.calls as Array<[string, unknown]>; + expect(offCalls).toContainEqual(['dataAppend', dataAppendOn![1]]); + expect(offCalls).toContainEqual(['deviceLost', deviceLostOn![1]]); + }); +}); + +describe('ChartGPU handle — smoke surface', () => { + it('forwards getChart, getContainer, setOption, interaction X, and hitTest', async () => { + const hitResult = { + isInGrid: true, + canvasX: 10, + canvasY: 20, + gridX: 1, + gridY: 2, + match: { seriesIndex: 0, dataIndex: 1 }, + }; + mockInstance.getInteractionX.mockReturnValue(42 as never); + mockInstance.hitTest.mockReturnValue(hitResult as never); + + const { ref } = await renderWithHandle(); + + expect(ref.current!.getChart()).toBe(mockInstance); + + const container = ref.current!.getContainer(); + expect(container).toBeInstanceOf(HTMLDivElement); + + const nextOpts = makeOptions('handle-setOption'); + ref.current!.setOption(nextOpts); + expect(mockInstance.setOption).toHaveBeenCalledWith(nextOpts); + + ref.current!.setInteractionX(1); + expect(mockInstance.setInteractionX).toHaveBeenCalledWith(1, undefined); + + ref.current!.setInteractionX(null); + expect(mockInstance.setInteractionX).toHaveBeenCalledWith(null, undefined); + + expect(ref.current!.getInteractionX()).toBe(42); + expect(mockInstance.getInteractionX).toHaveBeenCalled(); + + const event = new MouseEvent('click'); + expect(ref.current!.hitTest(event)).toBe(hitResult); + expect(mockInstance.hitTest).toHaveBeenCalledWith(event); + }); + + it('returns null chart / empty hitTest after unmount', async () => { + const { ref, unmount } = await renderWithHandle(); + const handle = ref.current!; + unmount(); + + expect(handle.getChart()).toBeNull(); + expect(handle.getInteractionX()).toBeNull(); + + const empty = handle.hitTest(new MouseEvent('click')); + expect(empty).toEqual({ + isInGrid: false, + canvasX: NaN, + canvasY: NaN, + gridX: NaN, + gridY: NaN, + match: null, + }); + expect(mockInstance.hitTest).not.toHaveBeenCalled(); + }); +}); diff --git a/src/__tests__/exports.test.ts b/src/__tests__/exports.test.ts new file mode 100644 index 0000000..63fbf91 --- /dev/null +++ b/src/__tests__/exports.test.ts @@ -0,0 +1,76 @@ +/** + * Export smoke test — fails CI if documented public surface is renamed/removed. + * Runtime values are asserted; types are compile-only imports (typecheck gate). + */ + +import { describe, it, expect, vi } from 'vitest'; + +// Mock peer package so re-exports resolve without a real WebGPU runtime. +vi.mock('@chartgpu/chartgpu', () => { + return { + ChartGPU: { create: vi.fn() }, + createChart: vi.fn(), + connectCharts: vi.fn(), + createPipelineCache: vi.fn(), + destroyPipelineCache: vi.fn(), + getPipelineCacheStats: vi.fn(), + }; +}); + +import * as pkg from '../index'; + +// Compile-only: ensure 0.3.x types remain importable from the package root. +import type { + ChartGPUAppendDataOptions, + ChartGPUHandle, + ChartGPUProps, + ChartGPUCreateContext, + HeatmapUpdate, + RenderMode, + ChartSyncOptions, + UseGPUContextResult, + UseChartGPUResult, +} from '../index'; + +// Keep type imports "used" for noUnusedLocals without runtime cost. +type _Surface = [ + ChartGPUAppendDataOptions, + ChartGPUHandle, + ChartGPUProps, + ChartGPUCreateContext, + HeatmapUpdate, + RenderMode, + ChartSyncOptions, + UseGPUContextResult, + UseChartGPUResult, +]; +const _typesOk: _Surface | undefined = undefined; +void _typesOk; + +describe('package exports', () => { + it('exports the primary React component and hooks', () => { + // forwardRef components are objects (exotic component), not plain functions + expect(pkg.ChartGPU).toBeTruthy(); + expect(typeof pkg.ChartGPU === 'function' || typeof pkg.ChartGPU === 'object').toBe(true); + + expect(pkg.useChartGPU).toBeTypeOf('function'); + expect(pkg.useGPUContext).toBeTypeOf('function'); + expect(pkg.useConnectCharts).toBeTypeOf('function'); + }); + + it('re-exports documented ChartGPU helpers', () => { + expect(pkg.connectCharts).toBeTypeOf('function'); + expect(pkg.createChart).toBeTypeOf('function'); + expect(pkg.createPipelineCache).toBeTypeOf('function'); + expect(pkg.destroyPipelineCache).toBeTypeOf('function'); + expect(pkg.getPipelineCacheStats).toBeTypeOf('function'); + expect(pkg.createAnnotationAuthoring).toBeTypeOf('function'); + }); + + it('still exports the deprecated ChartGPUChart adapter', () => { + expect(pkg.ChartGPUChart).toBeTruthy(); + expect(typeof pkg.ChartGPUChart === 'function' || typeof pkg.ChartGPUChart === 'object').toBe( + true + ); + }); +}); diff --git a/src/__tests__/useChartGPU.test.tsx b/src/__tests__/useChartGPU.test.tsx index 4924088..ecbafa7 100644 --- a/src/__tests__/useChartGPU.test.tsx +++ b/src/__tests__/useChartGPU.test.tsx @@ -190,3 +190,52 @@ describe('useChartGPU hook — createdWithOptionsRef race-condition fix', () => unmount(); }); }); + +describe('useChartGPU — gpuContext create path', () => { + it('passes gpuContext as the third argument to ChartGPU.create', async () => { + const container = document.createElement('div'); + document.body.appendChild(container); + const gpuContext = { + adapter: { id: 'adapter' } as any, + device: { id: 'device' } as any, + pipelineCache: { id: 'cache' } as any, + }; + const opts = makeOptions('hook-ctx'); + + const { result, unmount } = renderHook( + ({ options }: { options: ChartGPUOptions }) => { + const containerRef = useRef(container); + return useChartGPU(containerRef, options, gpuContext); + }, + { initialProps: { options: opts } } + ); + + await waitFor(() => { + expect(result.current.isReady).toBe(true); + }); + + expect(mockCreate).toHaveBeenCalledTimes(1); + const args = mockCreate.mock.calls[0]; + expect(args).toHaveLength(3); + expect(args[0]).toBe(container); + expect(args[1]).toBe(opts); + expect(args[2]).toBe(gpuContext); + + unmount(); + container.remove(); + }); + + it('calls create with two args when gpuContext is omitted', async () => { + const opts = makeOptions('hook-no-ctx'); + const { result, unmount } = renderUseChartGPU(opts); + + await waitFor(() => { + expect(result.current.isReady).toBe(true); + }); + + expect(mockCreate).toHaveBeenCalledTimes(1); + expect(mockCreate.mock.calls[0]).toHaveLength(2); + + unmount(); + }); +}); diff --git a/src/__tests__/useConnectCharts.test.tsx b/src/__tests__/useConnectCharts.test.tsx new file mode 100644 index 0000000..98f6b52 --- /dev/null +++ b/src/__tests__/useConnectCharts.test.tsx @@ -0,0 +1,181 @@ +/** + * Tests for useConnectCharts — multi-chart sync wiring around connectCharts(). + */ + +import { renderHook } from '@testing-library/react'; +import { vi, describe, it, expect, beforeEach } from 'vitest'; +import { useConnectCharts } from '../useConnectCharts'; +import type { ChartGPUInstance } from '@chartgpu/chartgpu'; + +// --------------------------------------------------------------------------- +// Mock @chartgpu/chartgpu +// --------------------------------------------------------------------------- + +const mockDisconnect = vi.fn(); +const mockConnectCharts = vi.fn((..._args: unknown[]) => mockDisconnect); + +vi.mock('@chartgpu/chartgpu', () => { + return { + connectCharts: (charts: unknown, options?: unknown) => mockConnectCharts(charts, options), + }; +}); + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +function makeMockChart(label: string, disposed = false): ChartGPUInstance { + return { + disposed, + // Minimal identity object; only disposed is read by the hook. + _label: label, + } as unknown as ChartGPUInstance; +} + +// --------------------------------------------------------------------------- +// Setup +// --------------------------------------------------------------------------- + +beforeEach(() => { + vi.clearAllMocks(); + mockConnectCharts.mockImplementation(() => mockDisconnect); +}); + +// --------------------------------------------------------------------------- +// Tests +// --------------------------------------------------------------------------- + +describe('useConnectCharts', () => { + it('calls connectCharts once with resolved instances and undefined options', () => { + const a = makeMockChart('a'); + const b = makeMockChart('b'); + + renderHook(() => useConnectCharts([a, b])); + + expect(mockConnectCharts).toHaveBeenCalledTimes(1); + expect(mockConnectCharts).toHaveBeenCalledWith([a, b], undefined); + }); + + it('reconnects when syncOptions change', () => { + const a = makeMockChart('a'); + const b = makeMockChart('b'); + + const { rerender } = renderHook( + ({ opts }: { opts?: { syncZoom?: boolean } }) => useConnectCharts([a, b], opts), + { initialProps: { opts: undefined as { syncZoom?: boolean } | undefined } } + ); + + expect(mockConnectCharts).toHaveBeenCalledTimes(1); + expect(mockConnectCharts).toHaveBeenCalledWith([a, b], undefined); + + rerender({ opts: { syncZoom: true } }); + + expect(mockDisconnect).toHaveBeenCalledTimes(1); + expect(mockConnectCharts).toHaveBeenCalledTimes(2); + expect(mockConnectCharts).toHaveBeenLastCalledWith([a, b], { syncZoom: true }); + }); + + it('does not call connectCharts when any chart is null', () => { + const a = makeMockChart('a'); + + renderHook(() => useConnectCharts([a, null])); + + expect(mockConnectCharts).not.toHaveBeenCalled(); + }); + + it('does not call connectCharts when any chart is disposed', () => { + const a = makeMockChart('a'); + const b = makeMockChart('b', true); + + renderHook(() => useConnectCharts([a, b])); + + expect(mockConnectCharts).not.toHaveBeenCalled(); + }); + + it('calls disconnect on unmount', () => { + const a = makeMockChart('a'); + const b = makeMockChart('b'); + + const { unmount } = renderHook(() => useConnectCharts([a, b])); + + expect(mockConnectCharts).toHaveBeenCalledTimes(1); + unmount(); + expect(mockDisconnect).toHaveBeenCalledTimes(1); + }); + + it('disconnects the old connection and connects new instance identity', () => { + const a = makeMockChart('a'); + const b1 = makeMockChart('b1'); + const b2 = makeMockChart('b2'); + + const { rerender } = renderHook( + ({ charts }: { charts: Array }) => useConnectCharts(charts), + { initialProps: { charts: [a, b1] as Array } } + ); + + expect(mockConnectCharts).toHaveBeenCalledTimes(1); + expect(mockConnectCharts).toHaveBeenCalledWith([a, b1], undefined); + + rerender({ charts: [a, b2] }); + + expect(mockDisconnect).toHaveBeenCalledTimes(1); + expect(mockConnectCharts).toHaveBeenCalledTimes(2); + expect(mockConnectCharts).toHaveBeenLastCalledWith([a, b2], undefined); + }); + + it('does not reconnect when the same instances are passed in a new array', () => { + const a = makeMockChart('a'); + const b = makeMockChart('b'); + + const { rerender } = renderHook( + ({ charts }: { charts: Array }) => useConnectCharts(charts), + { initialProps: { charts: [a, b] as Array } } + ); + + expect(mockConnectCharts).toHaveBeenCalledTimes(1); + + // New array identity, same chart objects — signature is stable. + rerender({ charts: [a, b] }); + + expect(mockConnectCharts).toHaveBeenCalledTimes(1); + expect(mockDisconnect).not.toHaveBeenCalled(); + }); + + it('disconnects without reconnecting when a live chart becomes disposed', () => { + const a = makeMockChart('a'); + const b = makeMockChart('b'); + + const { rerender } = renderHook( + ({ charts }: { charts: Array }) => useConnectCharts(charts), + { initialProps: { charts: [a, b] as Array } } + ); + + expect(mockConnectCharts).toHaveBeenCalledTimes(1); + expect(mockDisconnect).not.toHaveBeenCalled(); + + // Same object identities; disposed bit flips → signature changes. + (b as { disposed: boolean }).disposed = true; + rerender({ charts: [a, b] }); + + // Effect teardown disconnects; early-return because b is disposed → no reconnect. + expect(mockDisconnect).toHaveBeenCalledTimes(1); + expect(mockConnectCharts).toHaveBeenCalledTimes(1); + }); + + it('disconnects without reconnecting when a live chart becomes null', () => { + const a = makeMockChart('a'); + const b = makeMockChart('b'); + + const { rerender } = renderHook( + ({ charts }: { charts: Array }) => useConnectCharts(charts), + { initialProps: { charts: [a, b] as Array } } + ); + + expect(mockConnectCharts).toHaveBeenCalledTimes(1); + + rerender({ charts: [a, null] }); + + expect(mockDisconnect).toHaveBeenCalledTimes(1); + expect(mockConnectCharts).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/__tests__/useGPUContext.test.tsx b/src/__tests__/useGPUContext.test.tsx new file mode 100644 index 0000000..811dee4 --- /dev/null +++ b/src/__tests__/useGPUContext.test.tsx @@ -0,0 +1,198 @@ +/** + * Tests for useGPUContext — shared adapter/device + pipeline cache init paths. + * Stubs navigator.gpu; never requires a real WebGPU device. + */ + +import { StrictMode } from 'react'; +import { renderHook, waitFor, act } from '@testing-library/react'; +import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest'; +import { useGPUContext } from '../useGPUContext'; + +// --------------------------------------------------------------------------- +// Mock @chartgpu/chartgpu +// --------------------------------------------------------------------------- + +const mockCreatePipelineCache = vi.fn(); + +vi.mock('@chartgpu/chartgpu', () => { + return { + createPipelineCache: (...args: unknown[]) => mockCreatePipelineCache(...args), + }; +}); + +// --------------------------------------------------------------------------- +// GPU stubs +// --------------------------------------------------------------------------- + +const originalGpuDescriptor = Object.getOwnPropertyDescriptor(navigator, 'gpu'); + +function stubGpu(gpu: unknown) { + Object.defineProperty(navigator, 'gpu', { + value: gpu, + configurable: true, + writable: true, + }); +} + +function restoreGpu() { + if (originalGpuDescriptor) { + Object.defineProperty(navigator, 'gpu', originalGpuDescriptor); + } else { + // setup.ts installs a default stub; reinstall empty object if needed + Object.defineProperty(navigator, 'gpu', { + value: {}, + configurable: true, + writable: true, + }); + } +} + +// --------------------------------------------------------------------------- +// Setup +// --------------------------------------------------------------------------- + +beforeEach(() => { + vi.clearAllMocks(); + mockCreatePipelineCache.mockReturnValue({ id: 'pipeline-cache' }); +}); + +afterEach(() => { + restoreGpu(); +}); + +// --------------------------------------------------------------------------- +// Tests +// --------------------------------------------------------------------------- + +describe('useGPUContext', () => { + it('happy path: acquires adapter/device/cache and sets isReady', async () => { + const adapter = { + requestDevice: vi.fn(async () => ({ id: 'device' })), + }; + const requestAdapter = vi.fn(async () => adapter); + stubGpu({ requestAdapter }); + + const { result } = renderHook(() => useGPUContext()); + + await waitFor(() => { + expect(result.current.isReady).toBe(true); + }); + + expect(result.current.error).toBeNull(); + expect(result.current.adapter).toBe(adapter); + expect(result.current.device).toEqual({ id: 'device' }); + expect(result.current.pipelineCache).toEqual({ id: 'pipeline-cache' }); + expect(requestAdapter).toHaveBeenCalledWith({ powerPreference: 'high-performance' }); + expect(adapter.requestDevice).toHaveBeenCalledTimes(1); + expect(mockCreatePipelineCache).toHaveBeenCalledTimes(1); + expect(mockCreatePipelineCache).toHaveBeenCalledWith({ id: 'device' }); + }); + + it('sets a WebGPU error when navigator.gpu is absent', async () => { + stubGpu(undefined); + + const { result } = renderHook(() => useGPUContext()); + + await waitFor(() => { + expect(result.current.error).not.toBeNull(); + }); + + expect(result.current.error!.message).toMatch(/WebGPU/i); + expect(result.current.isReady).toBe(false); + expect(result.current.adapter).toBeNull(); + expect(result.current.device).toBeNull(); + expect(result.current.pipelineCache).toBeNull(); + expect(mockCreatePipelineCache).not.toHaveBeenCalled(); + }); + + it('errors when requestAdapter resolves null', async () => { + const requestAdapter = vi.fn(async () => null); + stubGpu({ requestAdapter }); + + const { result } = renderHook(() => useGPUContext()); + + await waitFor(() => { + expect(result.current.error).not.toBeNull(); + }); + + expect(result.current.error!.message).toBe('Failed to acquire GPUAdapter'); + expect(result.current.isReady).toBe(false); + expect(result.current.adapter).toBeNull(); + expect(mockCreatePipelineCache).not.toHaveBeenCalled(); + }); + + it('cancels state updates when unmounted mid-init', async () => { + let resolveAdapter: (value: unknown) => void; + const adapterPromise = new Promise((resolve) => { + resolveAdapter = resolve; + }); + const requestDevice = vi.fn(async () => ({ id: 'device-late' })); + const requestAdapter = vi.fn(() => adapterPromise); + stubGpu({ requestAdapter }); + + const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {}); + + const { result, unmount } = renderHook(() => useGPUContext()); + + // Still pending — no ready state yet. + expect(result.current.isReady).toBe(false); + expect(result.current.error).toBeNull(); + + unmount(); + + // Resolve after unmount; init continues but setState must be gated by cancelled. + await act(async () => { + resolveAdapter!({ requestDevice }); + }); + + // Flush the full async chain (requestDevice → createPipelineCache → .then). + await waitFor(() => { + expect(requestDevice).toHaveBeenCalledTimes(1); + expect(mockCreatePipelineCache).toHaveBeenCalledTimes(1); + }); + + // Allow any remaining microtasks/macrotasks from the .then handler to settle. + await act(async () => { + await Promise.resolve(); + }); + + // State must remain frozen at pre-init defaults — proves cancelled path ran. + expect(result.current.isReady).toBe(false); + expect(result.current.error).toBeNull(); + expect(result.current.adapter).toBeNull(); + expect(result.current.device).toBeNull(); + expect(result.current.pipelineCache).toBeNull(); + + // React must not warn about setState on an unmounted component. + const stateUpdateWarnings = consoleError.mock.calls.filter((args) => + args.some( + (a) => + typeof a === 'string' && + (/unmounted|Can't perform a React state update|memory leak/i.test(a) || + /not mounted/i.test(a)) + ) + ); + expect(stateUpdateWarnings).toHaveLength(0); + consoleError.mockRestore(); + }); + + it('StrictMode double effect initializes only once (shared init promise)', async () => { + const adapter = { + requestDevice: vi.fn(async () => ({ id: 'device' })), + }; + const requestAdapter = vi.fn(async () => adapter); + stubGpu({ requestAdapter }); + + const { result } = renderHook(() => useGPUContext(), { + // React 18/19 StrictMode double-invokes effects in development. + wrapper: ({ children }) => {children}, + }); + + await waitFor(() => { + expect(result.current.isReady).toBe(true); + }); + + expect(requestAdapter).toHaveBeenCalledTimes(1); + expect(mockCreatePipelineCache).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/index.ts b/src/index.ts index f940555..97bcec6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,10 @@ /** * chartgpu-react - * React bindings for ChartGPU - WebGPU-powered charting library + * React bindings for ChartGPU — WebGPU-powered high-performance charts + * Compatible with @chartgpu/chartgpu ^0.3.6 */ -// Primary ChartGPU component (Story 6.18) +// Primary ChartGPU component export { ChartGPU } from './ChartGPU'; // Wrapper types for the ChartGPU component @@ -18,17 +19,18 @@ export type { InterleavedXYData, XYArraysData, ChartGPUDataAppendPayload, + ChartGPUAppendDataOptions, } from './types'; -// useChartGPU hook (Story 6.19) +// useChartGPU hook export { useChartGPU } from './useChartGPU'; export type { UseChartGPUResult } from './useChartGPU'; -// Shared GPU context hook (ChartGPU v0.2.7+) +// Shared GPU context hook (multi-chart dashboards) export { useGPUContext } from './useGPUContext'; export type { UseGPUContextResult } from './useGPUContext'; -// Chart sync hook (connectCharts) - ChartGPU v0.2.3+ +// Chart sync hook (connectCharts) export { useConnectCharts } from './useConnectCharts'; /** @@ -61,6 +63,7 @@ export type { ChartGPUCrosshairMovePayload, ChartGPUZoomRangeChangePayload, ChartGPUDeviceLostPayload, + ZoomChangeSourceKind, RenderMode, // Hit testing @@ -82,7 +85,16 @@ export type { PieSeriesConfig, ScatterSeriesConfig, CandlestickSeriesConfig, + OhlcSeriesConfig, + HeatmapSeriesConfig, + BandSeriesConfig, + ErrorBarSeriesConfig, + ImpulseSeriesConfig, + PointCloud3DSeriesConfig, + Surface3DSeriesConfig, SeriesConfig, + SeriesType, + SeriesSampling, // Style configurations LineStyleConfig, @@ -92,6 +104,13 @@ export type { DataPoint, OHLCDataPoint, ScatterPointTuple, + HeatmapData, + HeatmapUpdate, + BandSeriesData, + ErrorBarSeriesData, + PointCloud3DData, + Surface3DGridData, + Surface3DUpdate, // Zoom / interaction DataZoomConfig, @@ -121,4 +140,10 @@ export type { GridConfig, GridLinesConfig, GridLinesDirectionConfig, + + // 3D + CoordinateSystem, + Chart3DCameraOptions, + Interaction3DOptions, + Axes3DOptions, } from '@chartgpu/chartgpu'; diff --git a/src/types.ts b/src/types.ts index 3ae6157..aea31ac 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,6 +1,6 @@ /** - * Type definitions for ChartGPU React wrapper - * Story 6.18: Wrapper types for the new ChartGPU component + * Type definitions for ChartGPU React wrapper. + * Aligned with @chartgpu/chartgpu ^0.3.6. */ import type { CSSProperties } from 'react'; @@ -19,7 +19,7 @@ import type { /** * Separate x/y/size arrays for cartesian series data. - * Mirrors the upstream shape used by ChartGPU's `appendData(...)`. + * Mirrors ChartGPU's internal `XYArraysData` (not yet re-exported from package root). */ export type XYArraysData = Readonly<{ x: ArrayLike; @@ -29,29 +29,30 @@ export type XYArraysData = Readonly<{ /** * Pre-interleaved XY cartesian data as a typed array view. - * Data must be laid out as [x0, y0, x1, y1, ...]. - * - * Note: This is a type-level convenience for `appendData(...)`. It matches - * ChartGPU's public behavior but is not currently exported as a named type - * from `@chartgpu/chartgpu` due to its package `exports` map. + * Layout: [x0, y0, x1, y1, ...]. */ export type InterleavedXYData = ArrayBufferView; /** * Union type for cartesian series data formats supported by `appendData(...)`. - * Mirrors the upstream `CartesianSeriesData` type used internally by ChartGPU. + * Matches ChartGPU 0.3.x (`DataPoint | null` gaps allowed in object arrays). */ export type CartesianSeriesData = - | ReadonlyArray + | ReadonlyArray | XYArraysData | InterleavedXYData; +/** + * Optional second argument to `appendData` (ChartGPU 0.3.x). + * `maxPoints` is opt-in fixed-capacity ring / FIFO window for that call only. + */ +export type ChartGPUAppendDataOptions = Readonly<{ + maxPoints?: number; +}>; + /** * Payload emitted by the ChartGPU `'dataAppend'` event. - * - * Note: ChartGPU emits this event in v0.2.7+ but does not currently export the - * payload type from its package root due to its package `exports` map. - * We provide this wrapper type so React consumers can strongly type `onDataAppend`. + * Not re-exported from `@chartgpu/chartgpu` package root; mirrored here for React consumers. */ export type ChartGPUDataAppendPayload = Readonly<{ readonly seriesIndex: number; @@ -64,28 +65,23 @@ export type ChartGPUDataAppendPayload = Readonly<{ /** * Bivariant callback helper (matches React's event handler variance behavior). - * This preserves backwards-compatibility for userland handlers. */ -type BivariantCallback any> = { +type BivariantCallback unknown> = { bivarianceHack(...args: Parameters): ReturnType; }['bivarianceHack']; /** * Type alias for the ChartGPU instance. - * This provides a more React-friendly name while maintaining compatibility - * with the underlying chartgpu library. */ export type ChartInstance = ChartGPUInstance; /** * Event parameters for chart click events. - * Wraps the underlying ChartGPUEventPayload with a React-friendly name. */ export type ClickParams = ChartGPUEventPayload; /** * Event parameters for chart mouseover events. - * Wraps the underlying ChartGPUEventPayload with a React-friendly name. */ export type MouseOverParams = ChartGPUEventPayload; @@ -98,9 +94,6 @@ export type ZoomRange = NonNullable /** * Props interface for the ChartGPU React component. - * - * This component provides a declarative React wrapper around the imperative - * ChartGPU library, handling initialization, updates, and cleanup. */ export interface ChartGPUProps { /** @@ -110,7 +103,7 @@ export interface ChartGPUProps { options: ChartGPUOptions; /** - * Optional shared GPU context for multi-chart dashboards (ChartGPU v0.2.7+). + * Optional shared GPU context for multi-chart dashboards. * * IMPORTANT: This prop is **init-only** (only read during `ChartGPU.create(...)`). * Changing it after mount has no effect. @@ -135,23 +128,16 @@ export interface ChartGPUProps { /** * Callback invoked when the chart instance is ready after async initialization. - * Provides access to the underlying ChartGPU instance. - * - * @param chart - The initialized ChartGPU instance */ onReady?: (chart: ChartInstance) => void; /** * Callback invoked when a chart element is clicked. - * - * @param params - Event payload containing click details */ onClick?: (params: ClickParams) => void; /** * Callback invoked when the mouse hovers over a chart element. - * - * @param params - Event payload containing mouseover details */ onMouseOver?: (params: MouseOverParams) => void; @@ -162,27 +148,22 @@ export interface ChartGPUProps { /** * Callback invoked when the crosshair moves. - * - * @param payload - Crosshair move payload containing domain-space x and optional source */ onCrosshairMove?: (payload: ChartGPUCrosshairMovePayload) => void; /** - * Callback invoked when data is appended via `appendData(...)` (ChartGPU v0.2.7+). - * Useful for coordinated streaming dashboards and cross-chart synchronization. + * Callback invoked when data is appended via `appendData(...)`. */ onDataAppend?: (payload: ChartGPUDataAppendPayload) => void; /** - * Callback invoked when a shared GPU device is lost (ChartGPU v0.2.7+). + * Callback invoked when a shared GPU device is lost. * Most useful when using `gpuContext` to share a `GPUDevice` across charts. */ onDeviceLost?: (payload: ChartGPUDeviceLostPayload) => void; /** * Callback invoked when the chart zoom range changes. - * - * @param range - The new zoom range with start and end values */ onZoomChange?: BivariantCallback<(range: ZoomRange) => void>; } @@ -190,45 +171,36 @@ export interface ChartGPUProps { /** * Imperative handle interface for the ChartGPU component. * - * Exposed via React.forwardRef to allow parent components to interact - * directly with the chart instance using imperative methods. - * - * Example usage: + * Example: * ```tsx * const chartRef = useRef(null); - * - * // Later: - * chartRef.current?.appendData(0, [{ x: 10, y: 20 }]); + * chartRef.current?.appendData(0, newPoints, { maxPoints: 50_000 }); * ``` */ export interface ChartGPUHandle { /** * Get the underlying ChartGPU instance. * Returns null if the chart hasn't been initialized yet or has been disposed. - * - * @returns The ChartGPU instance or null */ getChart(): ChartGPUInstance | null; /** * Get the container element used to mount the chart. - * Useful for wiring up helpers like `createAnnotationAuthoring(...)`. */ getContainer(): HTMLDivElement | null; /** * Append new data points to an existing series. - * This is more efficient than replacing the entire dataset. - * - * @param seriesIndex - Zero-based index of the series to update - * @param newPoints - Array of data points to append + * Prefer `{ maxPoints }` for FIFO / streaming windows over sliding-window `setOption`. */ - appendData(seriesIndex: number, newPoints: CartesianSeriesData | OHLCDataPoint[]): void; + appendData( + seriesIndex: number, + newPoints: CartesianSeriesData | OHLCDataPoint[], + options?: ChartGPUAppendDataOptions + ): void; /** * Render a single frame (external render mode only). - * - * @returns true if a frame was rendered, false if already clean */ renderFrame(): boolean; @@ -249,27 +221,18 @@ export interface ChartGPUHandle { /** * Replace the entire chart options. - * Note: This replaces the full options object, not a partial update. - * - * @param options - New complete chart configuration */ setOption(options: ChartGPUOptions): void; /** * Programmatically set the zoom range (percent-space). * No-op when zoom is disabled on the chart. - * - * @param start - Start of zoom range (0-100) - * @param end - End of zoom range (0-100) */ - setZoomRange(start: number, end: number): void; + setZoomRange(start: number, end: number, source?: unknown): void; /** * Programmatically drive the crosshair / tooltip to a domain-space x value. * Passing `null` clears the crosshair. - * - * @param x - Domain-space x value, or null to clear - * @param source - Optional source identifier (useful for sync disambiguation) */ setInteractionX(x: number | null, source?: unknown): void; @@ -280,17 +243,12 @@ export interface ChartGPUHandle { /** * Perform hit-testing on a pointer or mouse event. - * Returns coordinates and matched chart element (if any). - * - * @param e - Pointer or mouse event to test - * @returns Hit-test result with coordinates and optional match */ hitTest(e: PointerEvent | MouseEvent): ChartGPUHitTestResult; } /** - * Re-export ThemeConfig for convenience. - * This allows consumers to import all types from the wrapper package. + * Re-export common core types for convenience. */ export type { ThemeConfig, diff --git a/src/useChartGPU.ts b/src/useChartGPU.ts index 79ed485..8f377a1 100644 --- a/src/useChartGPU.ts +++ b/src/useChartGPU.ts @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react'; +import { useEffect, useRef, useState, type RefObject } from 'react'; import { ChartGPU as ChartGPULib } from '@chartgpu/chartgpu'; import type { ChartGPUCreateContext, ChartGPUOptions } from '@chartgpu/chartgpu'; import type { ChartInstance } from './types'; @@ -58,7 +58,7 @@ export interface UseChartGPUResult { * ``` */ export function useChartGPU( - containerRef: React.RefObject, + containerRef: RefObject, options: ChartGPUOptions, gpuContext?: ChartGPUCreateContext ): UseChartGPUResult { diff --git a/src/useGPUContext.ts b/src/useGPUContext.ts index a2fec1c..97adc9b 100644 --- a/src/useGPUContext.ts +++ b/src/useGPUContext.ts @@ -17,9 +17,16 @@ export interface UseGPUContextResult { * single `GPUDevice` and optional `PipelineCache` to reduce shader/pipeline compilation overhead. * * Usage: - * - Call `useGPUContext()` once in a parent component. + * - Call `useGPUContext()` once in a **long-lived** parent component. * - Pass `{ adapter, device, pipelineCache }` to each `` * or to `useChartGPU(containerRef, options, gpuContext)`. + * + * StrictMode: init is deduped via a shared in-flight/completed promise (single + * `requestAdapter` / `requestDevice` / `createPipelineCache` per hook instance). + * + * Lifecycle: does **not** destroy the `GPUDevice` or pipeline cache on unmount. + * Auto-destroy would race with StrictMode remount (same promise is re-subscribed). + * Keep this hook mounted for the shared charts’ process lifetime. */ interface GPUContextState { adapter: ChartGPUCreateContext['adapter'] | null; @@ -36,43 +43,54 @@ export function useGPUContext(): UseGPUContextResult { error: null, }); - // StrictMode safety: avoid double-initializing in dev (effect is invoked twice). - const startedRef = useRef(false); + // StrictMode safety: start GPU init at most once per hook instance. + // The promise is shared so a remount (StrictMode: effect → cleanup → effect) + // reuses the same in-flight/completed init instead of requesting a second device. + const initPromiseRef = useRef | null>(null); useEffect(() => { - if (startedRef.current) return; - startedRef.current = true; - let cancelled = false; - const init = async () => { - try { - const gpu = (navigator as unknown as { gpu?: any }).gpu; - if (!gpu) { - throw new Error('WebGPU not supported in this browser'); - } - - const nextAdapter = await gpu.requestAdapter({ - powerPreference: 'high-performance', - }); - if (!nextAdapter) { - throw new Error('Failed to acquire GPUAdapter'); - } + if (!initPromiseRef.current) { + initPromiseRef.current = (async (): Promise => { + try { + const gpu = (navigator as unknown as { gpu?: any }).gpu; + if (!gpu) { + throw new Error('WebGPU not supported in this browser'); + } - const nextDevice = await nextAdapter.requestDevice(); - const nextCache = createPipelineCache(nextDevice); + const nextAdapter = await gpu.requestAdapter({ + powerPreference: 'high-performance', + }); + if (!nextAdapter) { + throw new Error('Failed to acquire GPUAdapter'); + } - if (cancelled) return; + const nextDevice = await nextAdapter.requestDevice(); + const nextCache = createPipelineCache(nextDevice); - setState({ adapter: nextAdapter, device: nextDevice, pipelineCache: nextCache, error: null }); - } catch (err) { - if (cancelled) return; - const normalized = err instanceof Error ? err : new Error(String(err)); - setState({ adapter: null, device: null, pipelineCache: null, error: normalized }); - } - }; + return { + adapter: nextAdapter, + device: nextDevice, + pipelineCache: nextCache, + error: null, + }; + } catch (err) { + const normalized = err instanceof Error ? err : new Error(String(err)); + return { + adapter: null, + device: null, + pipelineCache: null, + error: normalized, + }; + } + })(); + } - init(); + initPromiseRef.current.then((next) => { + if (cancelled) return; + setState(next); + }); return () => { cancelled = true; diff --git a/src/utils.ts b/src/utils.ts index b0ced66..7032432 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -5,12 +5,12 @@ /** * Debounce utility for throttling frequent calls. */ -export function debounce void>( - fn: T, +export function debounce( + fn: (...args: TArgs) => void, delayMs: number -): (...args: Parameters) => void { +): (...args: TArgs) => void { let timeoutId: ReturnType | null = null; - return (...args: Parameters) => { + return (...args: TArgs) => { if (timeoutId !== null) { clearTimeout(timeoutId); } diff --git a/tsconfig.build.json b/tsconfig.build.json index fe657e4..a0e9a11 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -5,8 +5,10 @@ "declaration": true, "declarationMap": true, "emitDeclarationOnly": true, - "outDir": "dist" + "outDir": "dist", + "rootDir": "src", + "allowImportingTsExtensions": false }, "include": ["src"], - "exclude": ["src/**/*.test.ts", "src/**/*.test.tsx", "examples"] + "exclude": ["src/**/*.test.ts", "src/**/*.test.tsx", "src/__tests__", "examples"] } diff --git a/tsconfig.json b/tsconfig.json index 90a26cb..3f9f6f1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { - "target": "ES2020", + "target": "ES2022", "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], + "lib": ["ES2022", "DOM", "DOM.Iterable"], "module": "ESNext", "skipLibCheck": true, @@ -19,12 +19,13 @@ "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": false, - /* React */ + /* React / interop */ "allowSyntheticDefaultImports": true, "esModuleInterop": true, - "forceConsistentCasingInFileNames": true + "forceConsistentCasingInFileNames": true, + "verbatimModuleSyntax": false }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] + "include": ["src"] } diff --git a/tsconfig.node.json b/tsconfig.node.json index 97ede7e..cc71fdf 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -1,11 +1,16 @@ { "compilerOptions": { - "composite": true, - "skipLibCheck": true, + "target": "ES2022", + "lib": ["ES2022"], "module": "ESNext", "moduleResolution": "bundler", "allowSyntheticDefaultImports": true, - "strict": true + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "noEmit": true, + "resolveJsonModule": true, + "isolatedModules": true }, - "include": ["vite.config.ts"] + "include": ["vite.config.ts", "vitest.config.ts"] } diff --git a/vite.config.ts b/vite.config.ts index c1d090a..1161ba1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,6 +1,5 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -import dts from 'vite-plugin-dts'; import { resolve } from 'path'; export default defineConfig(({ command }) => { @@ -17,16 +16,10 @@ export default defineConfig(({ command }) => { }; } - // Build mode: library output + // Build mode: library JS only (declarations via `tsc -p tsconfig.build.json`) + // Note: vite-plugin-dts is incompatible with TypeScript 7's slim package API. return { - plugins: [ - react(), - dts({ - insertTypesEntry: true, - rollupTypes: true, - tsconfigPath: './tsconfig.build.json', - }), - ], + plugins: [react()], build: { lib: { entry: resolve(__dirname, 'src/index.ts'), @@ -41,6 +34,7 @@ export default defineConfig(({ command }) => { }, outDir: 'dist', emptyOutDir: true, + sourcemap: true, }, }; });