diff --git a/CHANGELOG.md b/CHANGELOG.md index 523975a..8a634bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,52 @@ All notable changes to `@ossrandom/design-system` are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/). +## [Unreleased] + +### Changed — `ServiceMap` + +- **Visual refresh.** Nodes are now small dots (was: `round-rectangle` 80 × 36 cards). Diameter is computed from each node's degree (in + out edge count) using `√degree` scaling — 6 px (isolated) → 28 px (densest hub) — so hubs surface visually without dwarfing leaves. Status now drives the **fill color** (`success` / `warning` / `danger`), not just a border accent. +- **Node labels moved below the dot** (was: centered, inside the card). Light weight, no background pill — pills covered edges. Z-order keeps dots above edges and labels beside them. +- **Edges now declare direction and labels.** + - Cytoscape path: `target-arrow-shape: triangle`, `arrow-scale: 0.9`. `ServiceEdge.label` is rendered with `text-rotation: autorotate` but `text-opacity: 0` until the edge enters a focus set. + - deck.gl path: already directional via `ArcLayer` (gradient `source → target`); no behavior change. +- **Hover / touch focus highlight.** Hovering or tapping a node dims everything else to ~18 % opacity and lights the focused node (accent border, weight 500), its incident edges (accent stroke, 2 px, edge label revealed), and its direct neighbors. Hovering an edge lights both endpoints. Touch start triggers the same focus on the canvas path. `pointerleave` and an empty-area click clear focus. +- **WebGL highlight is in-place.** The deck.gl path builds an adjacency map up front and re-renders highlight state via `inst.setProps({ layers })` with `updateTriggers` keyed on the focus id — no full context re-init per hover. + +### Internal + +- New `computeDegrees(nodes, edges)` and `degreeRadius(deg, max)` helpers in `src/charts/ServiceMap.tsx`. `PositionedNode` extended with a precomputed `degree` field threaded through both rendering paths. +- New Cytoscape stylesheet classes `.rcs-dim`, `.rcs-focus`, `.rcs-focus-edge`, `.rcs-neighbor` with 120 ms transitions on opacity, color, and border-width. +- Tiny `cssEscape()` polyfill for Cytoscape ID selectors when `CSS.escape` is unavailable. + +## [0.3.0] — 2026-04-28 + +### Added + +- **Charts module** at the new `@ossrandom/design-system/charts` subpath — opt-in to keep the main entry zero-dep: + - **`Chart`** — line / area / bar / scatter time-series. Renders with `uplot` (canvas) when installed; falls back to inline SVG for small datasets. Auto-handoff to WebGL via `@deck.gl/core` + `@deck.gl/layers` once a series crosses ~100k points. Pan / zoom / crosshair / synced cursors across stacked panels; tabular tooltips with `Signal Red` accent. + - **`Sparkline`** — zero-dep inline SVG. `data: number[]`, optional `showArea`. Designed to drop into `Stat` tiles (80×24 default). Handles flat (range = 0) inputs without NaN. + - **`Donut`** + **`RadialGauge`** — zero-dep SVG. `Donut` takes typed `DonutSegment[]`, optional center label / value, optional legend, per-segment click handler. `RadialGauge` is a 270° arc with `tone: "good" | "warning" | "bad"`. + - **`UptimeBar`** — 90-day status grid on canvas. `UptimeCell[]` with `status: "operational" | "degraded" | "outage" | "maintenance" | "no-data"`; cursor-tracking tooltip; quadtree picking. + - **`Treemap`** — squarified treemap. Loads `d3-hierarchy` lazily; falls back to a built-in squarify pass when not installed. Canvas2d at any size, WebGL handoff on `>50k` leaves. + - **`ServiceMap`** — directed graph for production topology. Loads `cytoscape` + `cytoscape-cose-bilkent` lazily; falls back to a small force-directed canvas. Status-keyed node strokes (`healthy` / `degraded` / `failing` / `unknown`), arrow markers on edges, drag-to-pan, scroll-to-zoom. + +- **Optional peer deps** (`peerDependenciesMeta`): `uplot`, `d3-hierarchy`, `d3-force`, `cytoscape`, `cytoscape-cose-bilkent`, `@deck.gl/core`, `@deck.gl/layers`. The main entry imports none of them — install only what the charts you render require. + +- **Chart theming**: `readChartTheme()` + `onThemeChange()` exported from `/charts` — hook a custom renderer to the same tokens (`--accent`, `--fg-1`, `--bg-2`, `--font-mono`, …) and re-render on `data-theme` swap. + +- **Tokens**: `--elevation-tooltip` for chart tooltips; engine-badge surfaces `[data-engine]` attribute on chart roots — opt-in dev badge via `--rcs-show-engine: 1`. + +### Notes + +No breaking changes. Existing imports from `@ossrandom/design-system` continue to work unchanged. To use charts: + +```tsx +import { Chart, Sparkline, Donut } from "@ossrandom/design-system/charts"; +``` + +…and `pnpm add` the peer deps for the charts you render. + ## [0.2.1] — 2026-04-27 ### Fixed diff --git a/README.md b/README.md index 8fa88c9..f6566f9 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ export function Dashboard({ services }: { services: readonly Service[] }) { ## What's in the box - **50+ React components** — Buttons, Inputs, Form controls, Layout primitives, Navigation, Feedback, Data display, Chat, Code/Markdown/Terminal/RTE, plus `ThemeProvider` + imperative `toast` +- **Charts** (opt-in subpath) — `Chart` (line/area/bar/scatter), `Sparkline`, `Donut`, `RadialGauge`, `UptimeBar`, `Treemap`, `ServiceMap` — see [Charts](#charts) below - **Strongly-typed token unions** (`Size`, `SpaceSize`, `Radius`, `ThemeMode`, `BrandColor`, `Direction`, `Axis`, …) - **Generic components**: `Select`, `Combobox`, `Tabs`, `Menu`, `RadioGroup`, `Table` - **Strict TypeScript** — full type definitions emitted to `dist/`, source maps + declaration maps included @@ -135,6 +136,83 @@ import { ThemeProvider, ToastRegion, toast } from "@ossrandom/design-system"; ``` +## Charts + +Charts ship behind an opt-in subpath because they pull heavier peer deps. The main entry stays zero-dep — you only pay for charts if you import them. + +```tsx +import { + Chart, Sparkline, Donut, RadialGauge, + UptimeBar, Treemap, ServiceMap, +} from "@ossrandom/design-system/charts"; +``` + +Install the peer deps for the charts you actually render: + +| Component | Peer dep | Fallback | +| ------------------------- | ---------------------------------------------- | ----------------------------------- | +| `Chart` (time-series) | `uplot` | SVG renderer (small datasets only) | +| `Sparkline` | — | inline SVG, zero deps | +| `Donut` / `RadialGauge` | — | inline SVG, zero deps | +| `UptimeBar` | — | canvas2d, zero deps | +| `Treemap` | `d3-hierarchy` | canvas2d squarify | +| `ServiceMap` | `cytoscape` + `cytoscape-cose-bilkent` | force-directed canvas | + +Charts auto-handoff to WebGL (`@deck.gl/core`, `@deck.gl/layers`) when the dataset crosses an engine threshold (`Chart` ≥100k points; `ServiceMap` ≥200 nodes). The `data-engine` attribute on the rendered root reflects the active backend (`svg` / `canvas` / `webgl`); set `--rcs-show-engine: 1` to surface a dev badge. + +All chart components read tokens via `readChartTheme()` and re-render on `data-theme` swap — `Signal Red` accent, mono micro-labels, tabular numerics out of the box. + +#### `ServiceMap` — interaction model + +`ServiceMap` is a directed graph; semantics live in the data, not the visuals on top of it. + +- **Direction.** Edges flow `source → target` with arrowheads at the target end. The deck.gl path uses `ArcLayer` (gradient source/target colors); the canvas path uses Cytoscape's bezier curve with a `triangle` arrow. +- **Node size = degree.** Each dot's radius is computed from `in + out` edge count using `√degree` scaling — 3 px (isolated) → 14 px (densest hub). Hubs surface visually without dwarfing leaves. +- **Status drives fill.** `healthy` / `degraded` / `failing` / `unknown` map to the `success` / `warning` / `danger` / `fg-3` tokens. Failing edges paint in `danger`. +- **Labels.** Node labels sit below each dot in a light weight (`font-weight: 400`, `color: --fg-3`) so they don't compete with edges. Edge labels (`label?: string` on `ServiceEdge`) are rendered but hidden by default — they reveal only when their edge is in the focus set. +- **Hover / touch focus.** Hovering or tapping a node dims the rest of the graph to ~18 % opacity and lights the focused node, its incident edges, its neighbors, and the edge labels for those incident edges. Hovering an edge lights the edge plus both endpoints. `pointerleave` clears the focus state. +- **Engine handoff.** Auto resolves to `webgpu` › `webgl` › `canvas` based on `nodes + edges` count vs. the threshold. The deck.gl path uses an internal adjacency map and `setProps({ layers })` to re-render highlight state without rebuilding the WebGL context. + +```tsx + console.log("node:", n.id)} +/> +``` + +```tsx + + + + + +``` + ## Local development ```bash diff --git a/package.json b/package.json index 9d1f0f2..1193e3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ossrandom/design-system", - "version": "0.2.1", + "version": "0.3.0", "description": "RandomCodeSpace Design System — strongly-typed React component definitions.", "keywords": [ "design-system", @@ -36,6 +36,10 @@ "types": "./dist/tokens.d.ts", "import": "./dist/tokens.js" }, + "./charts": { + "types": "./dist/charts/index.d.ts", + "import": "./dist/charts/index.js" + }, "./styles.css": "./dist/styles.css" }, "files": [ @@ -62,7 +66,23 @@ }, "peerDependencies": { "react": ">=18", - "react-dom": ">=18" + "react-dom": ">=18", + "uplot": "^1.6.0", + "d3-hierarchy": "^3.0.0", + "d3-force": "^3.0.0", + "cytoscape": "^3.30.0", + "cytoscape-cose-bilkent": "^4.1.0", + "@deck.gl/core": "^9.0.0", + "@deck.gl/layers": "^9.0.0" + }, + "peerDependenciesMeta": { + "uplot": { "optional": true }, + "d3-hierarchy": { "optional": true }, + "d3-force": { "optional": true }, + "cytoscape": { "optional": true }, + "cytoscape-cose-bilkent": { "optional": true }, + "@deck.gl/core": { "optional": true }, + "@deck.gl/layers": { "optional": true } }, "devDependencies": { "@babel/standalone": "^7.29.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 97a17d6..075f83e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,28 @@ settings: importers: .: + dependencies: + '@deck.gl/core': + specifier: ^9.0.0 + version: 9.3.1 + '@deck.gl/layers': + specifier: ^9.0.0 + version: 9.3.1(@deck.gl/core@9.3.1)(@loaders.gl/core@4.4.1)(@luma.gl/core@9.3.3)(@luma.gl/engine@9.3.3(@luma.gl/core@9.3.3)(@luma.gl/shadertools@9.3.3(@luma.gl/core@9.3.3))) + cytoscape: + specifier: ^3.30.0 + version: 3.33.2 + cytoscape-cose-bilkent: + specifier: ^4.1.0 + version: 4.1.0(cytoscape@3.33.2) + d3-force: + specifier: ^3.0.0 + version: 3.0.0 + d3-hierarchy: + specifier: ^3.0.0 + version: 3.1.2 + uplot: + specifier: ^1.6.0 + version: 1.6.32 devDependencies: '@babel/standalone': specifier: ^7.29.0 @@ -159,6 +181,17 @@ packages: resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} engines: {node: '>=20.19.0'} + '@deck.gl/core@9.3.1': + resolution: {integrity: sha512-uixmBJhaAAgjzppcJ+0Hh2R1BYvFHvCHFReXN93iQxQoNB3VCC03pGEhZ0hrW7hcVLC8ExCUrg8VRJW60wXzcA==} + + '@deck.gl/layers@9.3.1': + resolution: {integrity: sha512-gUT/UMrmSCYsJCyv78qjHdeZVnqDexX61WxNP3dUa7ZplXiG3NxZvjhS0PYeBLritOtCJSv3b13vR2ka+j49ZQ==} + peerDependencies: + '@deck.gl/core': ~9.3.0 + '@loaders.gl/core': ^4.4.1 + '@luma.gl/core': ~9.3.2 + '@luma.gl/engine': ~9.3.2 + '@emnapi/core@1.10.0': resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} @@ -401,6 +434,67 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@loaders.gl/core@4.4.1': + resolution: {integrity: sha512-/s4IuvCCQUepvhjLnmePwQppGko2d1pxRS+sp7lyExU0uiqo5dVsAKaCZ2VnddBkFWgDVb/wvcZUBmv/dWcj0Q==} + + '@loaders.gl/images@4.4.1': + resolution: {integrity: sha512-v9A4BliEKGxhLuEbh0Ke8ElUlp04KxpKIknUtXXWoEaszAMTSrHI3YhaL/JdRlHraC1VUF/sjzbSBFkKh7nxJg==} + peerDependencies: + '@loaders.gl/core': ~4.4.0 + + '@loaders.gl/loader-utils@4.4.1': + resolution: {integrity: sha512-waosL7VtVRfXsNOXtAM3rOjZyNQD0lQBlhuB5/oY+E+lNzYNFlzgiGXiDOwBpcs7dK7kW2Vv8+KcxyIGIyXOtg==} + + '@loaders.gl/schema-utils@4.4.1': + resolution: {integrity: sha512-4upip2O6MFaWzk68/lnna7P2uRj9NQ8MIk/ff3CLbciP5/9lKl1qyuzObz5JrJRYzfGB6I81vpOn6FSVQ6m6KQ==} + peerDependencies: + '@loaders.gl/core': ~4.4.0 + + '@loaders.gl/schema@4.4.1': + resolution: {integrity: sha512-s7NjEnyK6jZvJJSWj/mHq+S9mHRHVzIYtFP+C7sMf1gVCQbdkt6OSAMUWRzwPr9+whQNVWjZ9pbLsI/IPW3zvw==} + + '@loaders.gl/worker-utils@4.4.1': + resolution: {integrity: sha512-ovMyIyj9dlChuHuD64Bel7Mir2UYlmLqlZ9MMzVxzTTLvaudJoNAXi6Disp0ooxwF62ZqjNXXutaSbS6UDeuIg==} + peerDependencies: + '@loaders.gl/core': ~4.4.0 + + '@luma.gl/core@9.3.3': + resolution: {integrity: sha512-jCFm2htvrVpcXIy85TBTF1ROgMfknKnfw2OH+Vydr41hiCFd6nqr79gM3f2uhaNkal0BghFNqF3qDioKiUWtew==} + + '@luma.gl/engine@9.3.3': + resolution: {integrity: sha512-StmMTzUcUlpKMU3wvWU48A6OQyphptD9zVGBsSkK6iHIBdtBKlOcmqRkyfvRouo8JHtlrnoJDHLVKhxorwhGAg==} + peerDependencies: + '@luma.gl/core': ~9.3.0 + '@luma.gl/shadertools': ~9.3.0 + + '@luma.gl/shadertools@9.3.3': + resolution: {integrity: sha512-4ZfG4/Utix951vqyiG/JIx+Eg+GMNwOxgr/07/i0gf7bK1gJZIEQ5BxVcDw4MCQfdoVlGPGzl0cQKbdqBvaCAQ==} + peerDependencies: + '@luma.gl/core': ~9.3.0 + + '@luma.gl/webgl@9.3.3': + resolution: {integrity: sha512-X+aavdP5o6VFHSA0es9gKZTT145jfcFbhKJt/gwJrptnKNoIW4+Y37ZEpCo1AzAnr+FQCxjgcM2kOCpoWMfSVA==} + peerDependencies: + '@luma.gl/core': ~9.3.0 + + '@mapbox/tiny-sdf@2.1.0': + resolution: {integrity: sha512-uFJhNh36BR4OCuWIEiWaEix9CA2WzT6CAIcqVjWYpnx8+QDtS+oC4QehRrx5cX4mgWs37MmKnwUejeHxVymzNg==} + + '@math.gl/core@4.1.0': + resolution: {integrity: sha512-FrdHBCVG3QdrworwrUSzXIaK+/9OCRLscxI2OUy6sLOHyHgBMyfnEGs99/m3KNvs+95BsnQLWklVfpKfQzfwKA==} + + '@math.gl/polygon@4.1.0': + resolution: {integrity: sha512-YA/9PzaCRHbIP5/0E9uTYrqe+jsYTQoqoDWhf6/b0Ixz8bPZBaGDEafLg3z7ffBomZLacUty9U3TlPjqMtzPjA==} + + '@math.gl/sun@4.1.0': + resolution: {integrity: sha512-i3q6OCBLSZ5wgZVhXg+X7gsjY/TUtuFW/2KBiq/U1ypLso3S4sEykoU/MGjxUv1xiiGtr+v8TeMbO1OBIh/HmA==} + + '@math.gl/types@4.1.0': + resolution: {integrity: sha512-clYZdHcmRvMzVK5fjeDkQlHUzXQSNdZ7s4xOqC3nJPgz4C/TZkUecTo9YS4PruZqtDda/ag4erndP0MIn40dGA==} + + '@math.gl/web-mercator@4.1.0': + resolution: {integrity: sha512-HZo3vO5GCMkXJThxRJ5/QYUYRr3XumfT8CzNNCwoJfinxy5NtKUd7dusNTXn7yJ40UoB8FMIwkVwNlqaiRZZAw==} + '@napi-rs/wasm-runtime@1.1.4': resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} peerDependencies: @@ -415,6 +509,15 @@ packages: engines: {node: '>=18'} hasBin: true + '@probe.gl/env@4.1.1': + resolution: {integrity: sha512-+68seNDMVsEegRB47pFA/Ws1Fjy8agcFYXxzorKToyPcD6zd+gZ5uhwoLd7TzsSw6Ydns//2KEszWn+EnNHTbA==} + + '@probe.gl/log@4.1.1': + resolution: {integrity: sha512-kcZs9BT44pL7hS1OkRGKYRXI/SN9KejUlPD+BY40DguRLzdC5tLG/28WGMyfKdn/51GT4a0p+0P8xvDn1Ez+Kg==} + + '@probe.gl/stats@4.1.1': + resolution: {integrity: sha512-4VpAyMHOqydSvPlEyHwXaE+AkIdR03nX+Qhlxsk2D/IW4OVmDZgIsvJB1cDzyEEtcfKcnaEbfXeiPgejBceT6g==} + '@rolldown/binding-android-arm64@1.0.0-rc.17': resolution: {integrity: sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -510,6 +613,9 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@swc/helpers@0.5.21': + resolution: {integrity: sha512-jI/VAmtdjB/RnI8GTnokyX7Ug8c+g+ffD6QRLa6XQewtnGyukKkKSk3wLTM3b5cjt1jNh9x0jfVlagdN2gDKQg==} + '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} @@ -548,18 +654,33 @@ packages: '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/command-line-args@5.2.3': + resolution: {integrity: sha512-uv0aG6R0Y8WHZLTamZwtfsDLVRnOa+n+n5rEvFWL5Na5gZ8V2Teab/duDPFzIIIhs9qizDpcavCusCLJZu62Kw==} + + '@types/command-line-usage@5.0.4': + resolution: {integrity: sha512-BwR5KP3Es/CSht0xqBcUXS3qCAUVXwpRKsV2+arxeb65atasuXG9LykC9Ab10Cw3s2raH92ZqOeILaQbsB2ACg==} + '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/geojson@7946.0.16': + resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} '@types/node@22.19.17': resolution: {integrity: sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==} + '@types/node@24.12.2': + resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==} + + '@types/offscreencanvas@2019.7.3': + resolution: {integrity: sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==} + '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: @@ -690,6 +811,10 @@ packages: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} + apache-arrow@21.1.0: + resolution: {integrity: sha512-kQrYLxhC+NTVVZ4CCzGF6L/uPVOzJmD1T3XgbiUnP7oTeVFOFgEUu6IKNwCDkpFoBVqDKQivlX4RUFqqnWFlEA==} + hasBin: true + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -700,6 +825,10 @@ packages: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} + array-back@6.2.3: + resolution: {integrity: sha512-SGDvmg6QTYiTxCBkYVmThcoa67uLl35pyzRHdpCGBOcqFy6BtwnphoFPk7LhJshD+Yk1Kt35WGWeZPTgwR4Fhw==} + engines: {node: '>=12.17'} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -732,6 +861,10 @@ packages: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} + chalk-template@0.4.0: + resolution: {integrity: sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==} + engines: {node: '>=12'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -743,12 +876,28 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + command-line-args@6.0.2: + resolution: {integrity: sha512-AIjYVxrV9X752LmPDLbVYv8aMCuHPSLZJXEo2qo/xJfv+NYhaZ4sMSF01rM+gHPaMgvPM0l5D/F+Qx+i2WfSmQ==} + engines: {node: '>=12.20'} + peerDependencies: + '@75lb/nature': latest + peerDependenciesMeta: + '@75lb/nature': + optional: true + + command-line-usage@7.0.4: + resolution: {integrity: sha512-85UdvzTNx/+s5CkSgBm/0hzP80RFHAa7PsfeADE5ezZF3uHz3/Tqj9gIKGT9PTtpycc3Ua64T0oVulGfKxzfqg==} + engines: {node: '>=12.20.0'} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cose-base@1.0.3: + resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -763,6 +912,35 @@ packages: csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + cytoscape-cose-bilkent@4.1.0: + resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} + peerDependencies: + cytoscape: ^3.2.0 + + cytoscape@3.33.2: + resolution: {integrity: sha512-sj4HXd3DokGhzZAdjDejGvTPLqlt84vNFN8m7bGsOzDY5DyVcxIb2ejIXat2Iy7HxWhdT/N1oKyheJ5YdpsGuw==} + engines: {node: '>=0.10'} + + d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + + d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + + d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + + d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + data-urls@7.0.0: resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -796,6 +974,9 @@ packages: dom-accessibility-api@0.6.3: resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + earcut@2.2.4: + resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==} + entities@8.0.0: resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} engines: {node: '>=20.19.0'} @@ -887,6 +1068,15 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} + find-replace@5.0.2: + resolution: {integrity: sha512-Y45BAiE3mz2QsrN2fb5QEtO4qb44NcS7en/0y9PEVsg351HsLeVclP8QPMH79Le9sH3rs5RSwJu99W0WPZO43Q==} + engines: {node: '>=14'} + peerDependencies: + '@75lb/nature': latest + peerDependenciesMeta: + '@75lb/nature': + optional: true + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -895,6 +1085,9 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} + flatbuffers@25.9.23: + resolution: {integrity: sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==} + flatted@3.4.2: resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} @@ -908,6 +1101,9 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + gl-matrix@3.4.4: + resolution: {integrity: sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==} + glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} @@ -992,6 +1188,10 @@ packages: canvas: optional: true + json-bignum@0.0.3: + resolution: {integrity: sha512-2WHyXj3OfHSgNyuzDbSxI1w2jgw5gkWSWhS7Qg4bWXx1nLk3jnbwfUeS0PSba3IzpTUWdHxBieELUzXRjQB2zg==} + engines: {node: '>=0.8'} + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -1004,6 +1204,9 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + layout-base@1.0.2: + resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1082,6 +1285,9 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -1117,6 +1323,9 @@ packages: minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + mjolnir.js@3.0.0: + resolution: {integrity: sha512-siX3YCG7N2HnmN1xMH3cK4JkUZJhbkhRFJL+G5N1vH0mh1t5088rJknIoqDFWDIU6NPGvRRgLnYW3ZHjSMEBLA==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1271,6 +1480,10 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + table-layout@4.1.1: + resolution: {integrity: sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==} + engines: {node: '>=12.17'} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -1319,13 +1532,23 @@ packages: engines: {node: '>=14.17'} hasBin: true + typical@7.3.0: + resolution: {integrity: sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==} + engines: {node: '>=12.17'} + undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + undici@7.25.0: resolution: {integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==} engines: {node: '>=20.18.1'} + uplot@1.6.32: + resolution: {integrity: sha512-KIMVnG68zvu5XXUbC4LQEPnhwOxBuLyW1AHtpm6IKTXImkbLgkMy+jabjLgSLMasNuGGzQm/ep3tOkyTxpiQIw==} + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -1443,6 +1666,10 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + wordwrapjs@5.1.1: + resolution: {integrity: sha512-0yweIbkINJodk27gX9LBGMzyQdBDan3s/dEAiwBOj+Mf0PPyWL6/rikalkv8EeD0E8jm4o5RXEOrFTP3NXbhJg==} + engines: {node: '>=12.17'} + xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} @@ -1531,6 +1758,44 @@ snapshots: '@csstools/css-tokenizer@4.0.0': {} + '@deck.gl/core@9.3.1': + dependencies: + '@loaders.gl/core': 4.4.1 + '@loaders.gl/images': 4.4.1(@loaders.gl/core@4.4.1) + '@luma.gl/core': 9.3.3 + '@luma.gl/engine': 9.3.3(@luma.gl/core@9.3.3)(@luma.gl/shadertools@9.3.3(@luma.gl/core@9.3.3)) + '@luma.gl/shadertools': 9.3.3(@luma.gl/core@9.3.3) + '@luma.gl/webgl': 9.3.3(@luma.gl/core@9.3.3) + '@math.gl/core': 4.1.0 + '@math.gl/sun': 4.1.0 + '@math.gl/types': 4.1.0 + '@math.gl/web-mercator': 4.1.0 + '@probe.gl/env': 4.1.1 + '@probe.gl/log': 4.1.1 + '@probe.gl/stats': 4.1.1 + '@types/offscreencanvas': 2019.7.3 + gl-matrix: 3.4.4 + mjolnir.js: 3.0.0 + transitivePeerDependencies: + - '@75lb/nature' + + '@deck.gl/layers@9.3.1(@deck.gl/core@9.3.1)(@loaders.gl/core@4.4.1)(@luma.gl/core@9.3.3)(@luma.gl/engine@9.3.3(@luma.gl/core@9.3.3)(@luma.gl/shadertools@9.3.3(@luma.gl/core@9.3.3)))': + dependencies: + '@deck.gl/core': 9.3.1 + '@loaders.gl/core': 4.4.1 + '@loaders.gl/images': 4.4.1(@loaders.gl/core@4.4.1) + '@loaders.gl/schema': 4.4.1 + '@luma.gl/core': 9.3.3 + '@luma.gl/engine': 9.3.3(@luma.gl/core@9.3.3)(@luma.gl/shadertools@9.3.3(@luma.gl/core@9.3.3)) + '@luma.gl/shadertools': 9.3.3(@luma.gl/core@9.3.3) + '@mapbox/tiny-sdf': 2.1.0 + '@math.gl/core': 4.1.0 + '@math.gl/polygon': 4.1.0 + '@math.gl/web-mercator': 4.1.0 + earcut: 2.2.4 + transitivePeerDependencies: + - '@75lb/nature' + '@emnapi/core@1.10.0': dependencies: '@emnapi/wasi-threads': 1.2.1 @@ -1698,6 +1963,100 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@loaders.gl/core@4.4.1': + dependencies: + '@loaders.gl/loader-utils': 4.4.1(@loaders.gl/core@4.4.1) + '@loaders.gl/schema': 4.4.1 + '@loaders.gl/schema-utils': 4.4.1(@loaders.gl/core@4.4.1) + '@loaders.gl/worker-utils': 4.4.1(@loaders.gl/core@4.4.1) + '@probe.gl/log': 4.1.1 + transitivePeerDependencies: + - '@75lb/nature' + + '@loaders.gl/images@4.4.1(@loaders.gl/core@4.4.1)': + dependencies: + '@loaders.gl/core': 4.4.1 + '@loaders.gl/loader-utils': 4.4.1(@loaders.gl/core@4.4.1) + transitivePeerDependencies: + - '@75lb/nature' + + '@loaders.gl/loader-utils@4.4.1(@loaders.gl/core@4.4.1)': + dependencies: + '@loaders.gl/schema': 4.4.1 + '@loaders.gl/worker-utils': 4.4.1(@loaders.gl/core@4.4.1) + '@probe.gl/log': 4.1.1 + '@probe.gl/stats': 4.1.1 + transitivePeerDependencies: + - '@75lb/nature' + - '@loaders.gl/core' + + '@loaders.gl/schema-utils@4.4.1(@loaders.gl/core@4.4.1)': + dependencies: + '@loaders.gl/core': 4.4.1 + '@loaders.gl/schema': 4.4.1 + '@types/geojson': 7946.0.16 + apache-arrow: 21.1.0 + transitivePeerDependencies: + - '@75lb/nature' + + '@loaders.gl/schema@4.4.1': + dependencies: + '@types/geojson': 7946.0.16 + apache-arrow: 21.1.0 + transitivePeerDependencies: + - '@75lb/nature' + + '@loaders.gl/worker-utils@4.4.1(@loaders.gl/core@4.4.1)': + dependencies: + '@loaders.gl/core': 4.4.1 + + '@luma.gl/core@9.3.3': + dependencies: + '@math.gl/types': 4.1.0 + '@probe.gl/env': 4.1.1 + '@probe.gl/log': 4.1.1 + '@probe.gl/stats': 4.1.1 + '@types/offscreencanvas': 2019.7.3 + + '@luma.gl/engine@9.3.3(@luma.gl/core@9.3.3)(@luma.gl/shadertools@9.3.3(@luma.gl/core@9.3.3))': + dependencies: + '@luma.gl/core': 9.3.3 + '@luma.gl/shadertools': 9.3.3(@luma.gl/core@9.3.3) + '@math.gl/core': 4.1.0 + '@math.gl/types': 4.1.0 + '@probe.gl/log': 4.1.1 + '@probe.gl/stats': 4.1.1 + + '@luma.gl/shadertools@9.3.3(@luma.gl/core@9.3.3)': + dependencies: + '@luma.gl/core': 9.3.3 + '@math.gl/core': 4.1.0 + '@math.gl/types': 4.1.0 + + '@luma.gl/webgl@9.3.3(@luma.gl/core@9.3.3)': + dependencies: + '@luma.gl/core': 9.3.3 + '@math.gl/types': 4.1.0 + '@probe.gl/env': 4.1.1 + + '@mapbox/tiny-sdf@2.1.0': {} + + '@math.gl/core@4.1.0': + dependencies: + '@math.gl/types': 4.1.0 + + '@math.gl/polygon@4.1.0': + dependencies: + '@math.gl/core': 4.1.0 + + '@math.gl/sun@4.1.0': {} + + '@math.gl/types@4.1.0': {} + + '@math.gl/web-mercator@4.1.0': + dependencies: + '@math.gl/core': 4.1.0 + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: '@emnapi/core': 1.10.0 @@ -1711,6 +2070,14 @@ snapshots: dependencies: playwright: 1.59.1 + '@probe.gl/env@4.1.1': {} + + '@probe.gl/log@4.1.1': + dependencies: + '@probe.gl/env': 4.1.1 + + '@probe.gl/stats@4.1.1': {} + '@rolldown/binding-android-arm64@1.0.0-rc.17': optional: true @@ -1764,6 +2131,10 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@swc/helpers@0.5.21': + dependencies: + tslib: 2.8.1 + '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.29.0 @@ -1810,16 +2181,28 @@ snapshots: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 + '@types/command-line-args@5.2.3': {} + + '@types/command-line-usage@5.0.4': {} + '@types/deep-eql@4.0.2': {} '@types/estree@1.0.8': {} + '@types/geojson@7946.0.16': {} + '@types/json-schema@7.0.15': {} '@types/node@22.19.17': dependencies: undici-types: 6.21.0 + '@types/node@24.12.2': + dependencies: + undici-types: 7.16.0 + + '@types/offscreencanvas@2019.7.3': {} + '@types/react-dom@19.2.3(@types/react@19.2.14)': dependencies: '@types/react': 19.2.14 @@ -1995,6 +2378,20 @@ snapshots: ansi-styles@5.2.0: {} + apache-arrow@21.1.0: + dependencies: + '@swc/helpers': 0.5.21 + '@types/command-line-args': 5.2.3 + '@types/command-line-usage': 5.0.4 + '@types/node': 24.12.2 + command-line-args: 6.0.2 + command-line-usage: 7.0.4 + flatbuffers: 25.9.23 + json-bignum: 0.0.3 + tslib: 2.8.1 + transitivePeerDependencies: + - '@75lb/nature' + argparse@2.0.1: {} aria-query@5.3.0: @@ -2003,6 +2400,8 @@ snapshots: aria-query@5.3.2: {} + array-back@6.2.3: {} + assertion-error@2.0.1: {} ast-v8-to-istanbul@1.0.0: @@ -2032,6 +2431,10 @@ snapshots: chai@6.2.2: {} + chalk-template@0.4.0: + dependencies: + chalk: 4.1.2 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -2043,10 +2446,28 @@ snapshots: color-name@1.1.4: {} + command-line-args@6.0.2: + dependencies: + array-back: 6.2.3 + find-replace: 5.0.2 + lodash.camelcase: 4.3.0 + typical: 7.3.0 + + command-line-usage@7.0.4: + dependencies: + array-back: 6.2.3 + chalk-template: 0.4.0 + table-layout: 4.1.1 + typical: 7.3.0 + concat-map@0.0.1: {} convert-source-map@2.0.0: {} + cose-base@1.0.3: + dependencies: + layout-base: 1.0.2 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -2062,6 +2483,27 @@ snapshots: csstype@3.2.3: {} + cytoscape-cose-bilkent@4.1.0(cytoscape@3.33.2): + dependencies: + cose-base: 1.0.3 + cytoscape: 3.33.2 + + cytoscape@3.33.2: {} + + d3-dispatch@3.0.1: {} + + d3-force@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + + d3-hierarchy@3.1.2: {} + + d3-quadtree@3.0.1: {} + + d3-timer@3.0.1: {} + data-urls@7.0.0: dependencies: whatwg-mimetype: 5.0.0 @@ -2085,6 +2527,8 @@ snapshots: dom-accessibility-api@0.6.3: {} + earcut@2.2.4: {} + entities@8.0.0: {} es-module-lexer@2.1.0: {} @@ -2208,6 +2652,8 @@ snapshots: dependencies: flat-cache: 4.0.1 + find-replace@5.0.2: {} + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -2218,6 +2664,8 @@ snapshots: flatted: 3.4.2 keyv: 4.5.4 + flatbuffers@25.9.23: {} + flatted@3.4.2: {} fsevents@2.3.2: @@ -2226,6 +2674,8 @@ snapshots: fsevents@2.3.3: optional: true + gl-matrix@3.4.4: {} + glob-parent@6.0.2: dependencies: is-glob: 4.0.3 @@ -2312,6 +2762,8 @@ snapshots: transitivePeerDependencies: - '@noble/hashes' + json-bignum@0.0.3: {} + json-buffer@3.0.1: {} json-schema-traverse@0.4.1: {} @@ -2322,6 +2774,8 @@ snapshots: dependencies: json-buffer: 3.0.1 + layout-base@1.0.2: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -2380,6 +2834,8 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash.camelcase@4.3.0: {} + lodash.merge@4.6.2: {} lru-cache@11.3.5: {} @@ -2412,6 +2868,8 @@ snapshots: dependencies: brace-expansion: 1.1.14 + mjolnir.js@3.0.0: {} + ms@2.1.3: {} nanoid@3.3.11: {} @@ -2552,6 +3010,11 @@ snapshots: symbol-tree@3.2.4: {} + table-layout@4.1.1: + dependencies: + array-back: 6.2.3 + wordwrapjs: 5.1.1 + tinybench@2.9.0: {} tinyexec@1.1.1: {} @@ -2581,8 +3044,7 @@ snapshots: dependencies: typescript: 5.9.3 - tslib@2.8.1: - optional: true + tslib@2.8.1: {} type-check@0.4.0: dependencies: @@ -2590,10 +3052,16 @@ snapshots: typescript@5.9.3: {} + typical@7.3.0: {} + undici-types@6.21.0: {} + undici-types@7.16.0: {} + undici@7.25.0: {} + uplot@1.6.32: {} + uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -2666,6 +3134,8 @@ snapshots: word-wrap@1.2.5: {} + wordwrapjs@5.1.1: {} + xml-name-validator@5.0.0: {} xmlchars@2.2.0: {} diff --git a/preview/components-charts-donut.html b/preview/components-charts-donut.html new file mode 100644 index 0000000..eda0d3c --- /dev/null +++ b/preview/components-charts-donut.html @@ -0,0 +1,70 @@ + + + + +
+
Charts · Donut · RadialGauge · proportional + scalar · pure SVG
+ +
+
Donut · resource usage breakdown
+
+ + + + + + + + + 2.4TB + total + +
    +
  • api38.0%
  • +
  • db24.0%
  • +
  • cache16.0%
  • +
  • queue12.0%
  • +
  • other10.0%
  • +
+
+
+ +
+
+
RadialGauge · capacity · neutral
+
+ + + + + + 76% + +
+
Disk capacity
+
+
+
RadialGauge · uptime SLO · good
+
+ + + + + 99.97% + +
+
30-day SLO
+
+
+ +
Donut: ≤50 segments · click to drill down · RadialGauge tones: neutral / good / warning / bad
+
+ diff --git a/preview/components-charts-line.html b/preview/components-charts-line.html new file mode 100644 index 0000000..2ebda54 --- /dev/null +++ b/preview/components-charts-line.html @@ -0,0 +1,99 @@ + +Charts — Line / Area / Bar + + +
+
+
Charts · Chart (line · area · bar)
+ engine: auto · canvas → webgl → webgpu +
+ + +
+
+
+
Request rate · last 24h
+
2 series · 144 points · uPlot canvas
+
+ canvas +
+ + + + + + + + + + +
requests/secp99 latency (ms)
+
+ + +
+
+
+
CPU utilization · 4 services
+
stacked area · 720 points · uPlot canvas
+
+ canvas +
+ + + + + + + + + + +
+ + +
+
+
+
Deployments · last 14 days
+
bar · 14 buckets
+
+ canvas +
+ + + + + + + + + + + + + + + + + + + + + + +
+
+ diff --git a/preview/components-charts-radial.html b/preview/components-charts-radial.html new file mode 100644 index 0000000..a74f12a --- /dev/null +++ b/preview/components-charts-radial.html @@ -0,0 +1,123 @@ + +Charts — Sparkline · Donut · Gauge + + +
+
Charts · Sparkline · Donut · RadialGauge
+ + +
+
Sparklines · embedded in Stat tiles
+
SVG · 80×24 · zero deps
+
+
+
+
Requests / min
+
12.4k
+
+ + + +
+
+
+
p99 latency
+
142ms
+
+ + + + +
+
+
+
Error rate
+
0.04%
+
+ + + +
+
+
+
Active sessions
+
3,284
+
+ + + +
+
+
+ + +
+
Resource breakdown · cluster usage
+
SVG · clickable segments · accent + mono palette
+
+ + + + + + + 847 + cores + +
    +
  • Compute45.0%
  • +
  • Database25.0%
  • +
  • Cache18.0%
  • +
  • Other12.0%
  • +
+
+
+ + +
+
Radial gauges · capacity indicators
+
SVG · tone: good / warning / bad
+
+
+ + + + 33% + +
Disk
+
+
+ + + + 76% + +
Memory
+
+
+ + + + 93% + +
CPU
+
+
+
+
+ diff --git a/preview/components-charts-servicemap.html b/preview/components-charts-servicemap.html new file mode 100644 index 0000000..a6f0731 --- /dev/null +++ b/preview/components-charts-servicemap.html @@ -0,0 +1,233 @@ + +Charts — ServiceMap + + +
+
Charts · ServiceMap · directed flow · labels reveal on focus
+ +
+
+
+
Production topology
+
cytoscape · cose-bilkent · webgl handoff at 200+ nodes
+
+ canvas +
+ +
+ + + + + + + + + + + + + + + http + + + + http + + + + http + + + + grpc + + + + grpc + + + + grpc · 5xx + + + + amqp + + + + amqp + + + + sql + + + + cache + + + + amqp + + + + http + + + + backup + + + + snapshot + + + + events + + + + events + + + + + + load-balancer + api-gateway + auth-service + webhooks + user-service + billing + notifications + scheduler + postgres + redis + queue + search + storage + analytics + + +
+ +
Hover or tap a service to light its connections and reveal edge labels.
+ +
+ healthy + degraded + failing + unknown + degree +
+ +
+ Nodes 14 + Edges 16 + Min/Max degree 1 / 4 + Latency probe 1s + Layout cose-bilkent +
+
+
+ + + diff --git a/preview/components-charts-sparkline.html b/preview/components-charts-sparkline.html new file mode 100644 index 0000000..8eab4c5 --- /dev/null +++ b/preview/components-charts-sparkline.html @@ -0,0 +1,76 @@ + + + + +
+
Charts · Sparkline · embedded in Stat cards · pure SVG, zero deps
+ +
+
+
Requests / min
+
12,481
+
↑ 4.2%
+ + + +
+
+
Error rate
+
0.024%
+
↓ 38%
+ + + + +
+
+
P99 latency
+
142ms
+
↑ 3ms
+ + + +
+
+ +
+
Sparkline · variants
+
+
+
line
+ +
+
+
area
+ + + + +
+
+
mono
+ +
+
+
noisy / dense
+ + + +
+
+
+ +
Sparkline auto-fits container · respects accent color · also rendered inline by <Stat>
+
+ diff --git a/preview/components-charts-timeseries.html b/preview/components-charts-timeseries.html new file mode 100644 index 0000000..2d40980 --- /dev/null +++ b/preview/components-charts-timeseries.html @@ -0,0 +1,143 @@ + + + + +
+
Charts · Time-series · CPU / RPS / latency · uPlot canvas + WebGL2/WebGPU
+ + +
+
+ Line · CPU per node · 24h + + 1H6H24H7D + canvas + +
+ + + + + + + + + + + + 0 + 25 + 50 + 75 + 100 + + 00:00 + 06:00 + 12:00 + 18:00 + 24:00 + + + + + + + + + + + + +
+ node-a + node-b + node-c + 14:42:18 · 78% / 41% / 33% +
+
+ + +
+
+ Area · Requests / sec · stacked + webgl +
+ + + + + + + 0 + 5k + 12k + + + + + + + +
+ api + auth + static +
+
+ + +
+
+ Bar · Deployments per day + canvas +
+ + + + + 0 + 10 + 20 + + + + + + + + + + + + + + + + + + + +
Apr 22 → today · peak 33 deploys on Apr 27
+
+ +
Performance · uPlot for ≤100k pts (~2ms/frame) · deck.gl WebGL2 path for 100k–1M (~6ms/frame) · WebGPU on supported browsers
+
+ diff --git a/preview/components-charts-treemap.html b/preview/components-charts-treemap.html new file mode 100644 index 0000000..b1628fe --- /dev/null +++ b/preview/components-charts-treemap.html @@ -0,0 +1,79 @@ + +Charts — Treemap + + +
+
Charts · Treemap · 5.4M LOC across 12 services
+ +
+
+
+
Codebase explorer · lines of code
+
d3-hierarchy squarify · canvas2d · quadtree picking
+
+ webgl auto +
+ +
+ + +
+
api-gateway
1.24M LOC
+
+
+
user-service
680k LOC
+
+
+
billing
498k LOC
+
+
+
notifications
580k LOC
+
+
+
analytics
472k LOC
+
+ + +
+
scheduler
540k LOC
+
+
+
webhooks
474k LOC
+
+
+
search
258k LOC
+
+
+
audit
128k LOC
+
+
+
storage
312k LOC
+
+
+
queue
242k LOC
+
+
+
docs
186k LOC
+
+
+ +
+ Total 5.4M LOC + Services 12 + Files 43,217 + Hover quadtree O(log n) +
+
+
+ diff --git a/preview/components-charts-uptime.html b/preview/components-charts-uptime.html new file mode 100644 index 0000000..036e1e5 --- /dev/null +++ b/preview/components-charts-uptime.html @@ -0,0 +1,79 @@ + +Charts — UptimeBar + + +
+
Charts · UptimeBar · 90 day status grid
+ +
+
Service uptime · last 90 days
+
canvas · hover for incident details
+ +
+ api.gateway +
+ 99.98% +
+
+ postgres.primary +
+ 99.92% +
+
+ redis.cache +
+ 100.00% +
+
+ worker.queue +
+ 98.74% +
+
+ cdn.edge +
+ 99.99% +
+ +
+ operational + degraded + outage + maintenance + no data +
+
+
+ + diff --git a/scripts/build-docs.mjs b/scripts/build-docs.mjs index 5efce8c..31c7585 100644 --- a/scripts/build-docs.mjs +++ b/scripts/build-docs.mjs @@ -20,6 +20,7 @@ * src/components.ts (interfaces, supporting types) * src/tokens.ts (token unions) * src/index.tsx (runtime export → category file) + * src/charts/index.ts (charts subpath exports — "Charts" category) * * The Pages workflow stages assets/, preview/*.html, ui_kits/, then runs * this script (which overwrites /preview/index.html with a styled one). @@ -30,7 +31,7 @@ import { readFileSync, writeFileSync, mkdirSync } from "node:fs"; import { join, resolve } from "node:path"; import { generateDemos } from "./component-examples.mjs"; -import { extractInterfaces, extractTypeAliases, parseRuntimeExports } from "./parse-source.mjs"; +import { extractInterfaces, extractTypeAliases, parseRuntimeExports, parseChartsExports } from "./parse-source.mjs"; const root = process.cwd(); const outDir = resolve(root, process.argv[2] || "_site"); @@ -39,6 +40,10 @@ mkdirSync(outDir, { recursive: true }); const componentsDts = readFileSync(join(root, "src/components.ts"), "utf8"); const tokensTs = readFileSync(join(root, "src/tokens.ts"), "utf8"); const indexTsx = readFileSync(join(root, "src/index.tsx"), "utf8"); +const chartsIndexTs = (() => { + try { return readFileSync(join(root, "src/charts/index.ts"), "utf8"); } + catch { return ""; } +})(); const colorsAndTypeCss = readFileSync(join(root, "colors_and_type.css"), "utf8"); const componentStylesCss = readFileSync(join(root, "src/styles.css"), "utf8"); const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8")); @@ -47,6 +52,7 @@ const REPO_URL = "https://github.com/RandomCodeSpace/design-system"; // ─── 1. Parse runtime exports + interfaces + token aliases ──────────── const runtimeExports = parseRuntimeExports(indexTsx); +const chartExports = parseChartsExports(chartsIndexTs); const interfaces = extractInterfaces(componentsDts); const componentTypeAliases = extractTypeAliases(componentsDts); const tokenTypeAliases = extractTypeAliases(tokensTs); @@ -62,11 +68,44 @@ const DOCS_CATEGORIES = [ { id: "navigation", label: "Navigation", blurb: "Tabs, menus, breadcrumb, pagination.", srcFiles: ["navigation"] }, { id: "feedback", label: "Feedback", blurb: "Status, modals, toasts, tooltips.", srcFiles: ["feedback"] }, { id: "content", label: "Content", blurb: "Code, markdown, terminal, chat, RTE.", srcFiles: ["code", "chat"] }, + { id: "charts", label: "Charts", blurb: "Opt-in subpath — Chart, Sparkline, Donut, RadialGauge, UptimeBar, Treemap, ServiceMap.", charts: true }, ]; +// Peer-dep callouts for chart pages. +const CHART_PEER_DEPS = { + Chart: ["uplot (canvas, default)", "@deck.gl/core + @deck.gl/layers (webgl/webgpu)"], + Sparkline: [], + Donut: [], + RadialGauge: [], + UptimeBar: [], + Treemap: ["d3-hierarchy"], + ServiceMap: ["cytoscape + cytoscape-cose-bilkent (canvas)", "@deck.gl/core + @deck.gl/layers + d3-force (webgl)"], +}; + +// Canonical static code snippets per chart (charts aren't in the IIFE +// bundle, so their docs pages show static code rather than live render). +const CHART_DEMOS = { + Chart: { title: "Time-series line chart", + code: `` }, + Sparkline: { title: "Inline trend", + code: `` }, + Donut: { title: "Capacity breakdown", + code: `` }, + RadialGauge: { title: "SLO gauge", + code: `` }, + UptimeBar: { title: "30-day uptime", + code: ` ({\n status: i === 12 ? "outage" : i === 19 ? "degraded" : "ok",\n timestamp: Date.now() - (29 - i) * 86_400_000,\n }))}\n/>` }, + Treemap: { title: "Resource breakdown", + code: `` }, + ServiceMap: { title: "Service topology", + code: `` }, +}; + +function isChart(name) { return chartExports.has(name); } function categoryForExport(name) { + if (isChart(name)) return DOCS_CATEGORIES.find((c) => c.id === "charts"); const f = runtimeExports.get(name); - return f ? DOCS_CATEGORIES.find((c) => c.srcFiles.includes(f)) : null; + return f ? DOCS_CATEGORIES.find((c) => !c.charts && c.srcFiles?.includes(f)) : null; } const exportsByCategory = new Map(DOCS_CATEGORIES.map((c) => [c.id, []])); @@ -74,8 +113,11 @@ for (const [name] of runtimeExports) { const cat = categoryForExport(name); if (cat) exportsByCategory.get(cat.id).push(name); } +for (const [name] of chartExports) { + exportsByCategory.get("charts").push(name); +} const HOOKS = new Set(["useTheme", "toast"]); -const ALL_NAMES = [...runtimeExports.keys()]; +const ALL_NAMES = [...runtimeExports.keys(), ...chartExports.keys()]; // ─── 4. Helpers ─────────────────────────────────────────────────────── function escapeHtml(s) { @@ -557,6 +599,34 @@ function renderDocsCss() { color: var(--fg-1); line-height: 1.55; white-space: pre; } +/* Charts: static placeholder where live preview would be, plus peer-dep list. */ +.demo-render--static { + display: flex; align-items: center; justify-content: center; + min-height: 120px; padding: 24px; + background: var(--bg-2); + background-image: + repeating-linear-gradient( + 45deg, transparent, transparent 8px, + var(--bg-1) 8px, var(--bg-1) 9px + ); +} +.demo-static-note { + font-family: var(--font-mono); font-size: 11px; line-height: 1.55; + color: var(--fg-3); text-align: center; max-width: 48ch; + background: var(--bg-1); border: 1px solid var(--border-1); border-radius: 4px; + padding: 10px 14px; +} +.demo-static-note a { color: var(--accent); } +ul.peer-deps { + list-style: none; margin: 0; padding: 0; + display: flex; flex-direction: column; gap: 6px; +} +ul.peer-deps li code { + font-family: var(--font-mono); font-size: 12px; color: var(--fg-2); + padding: 6px 10px; background: var(--bg-2); border: 1px solid var(--border-1); border-radius: 4px; + display: inline-block; +} + table.props { width: 100%; border-collapse: collapse; border: 1px solid var(--border-1); border-radius: 4px; overflow: hidden; } table.props th, table.props td { padding: 10px 14px; text-align: left; border-bottom: 1px solid var(--border-1); @@ -877,7 +947,9 @@ function renderDocsIndex() { .filter((c) => exportsByCategory.get(c.id).length > 0) .map((cat) => { const items = exportsByCategory.get(cat.id); - const srcLabel = cat.srcFiles.map((f) => `src/components/${f}.tsx`).join(" · "); + const srcLabel = cat.charts + ? `src/charts/ · import from "${pkg.name}/charts"` + : cat.srcFiles.map((f) => `src/components/${f}.tsx`).join(" · "); const cards = items.map((n) => { const iface = findPropsFor(n); const isHook = HOOKS.has(n); @@ -937,11 +1009,21 @@ function renderPropsTable(iface) { function renderComponentPage(name) { const iface = findPropsFor(name); const isHook = HOOKS.has(name); + const chart = isChart(name); const generics = iface?.generics || ""; const cat = categoryForExport(name); - const srcFile = runtimeExports.get(name); - const demos = getDemos(name); - const importLine = `import { ${name} } from "${pkg.name}";`; + const srcPath = chart + ? `src/charts/${chartExports.get(name)}.tsx` + : `src/components/${runtimeExports.get(name)}.tsx`; + // Charts can't run live in the IIFE bundle (peer deps live outside it), + // so we show static code snippets instead of running them. + const demos = chart + ? (CHART_DEMOS[name] ? [CHART_DEMOS[name]] : []) + : getDemos(name); + const importLine = chart + ? `import { ${name} } from "${pkg.name}/charts";` + : `import { ${name} } from "${pkg.name}";`; + const peerDeps = chart ? (CHART_PEER_DEPS[name] || []) : []; const inheritance = iface?.extends ? `

extends ${code(iface.extends)}

` : ""; const related = findRelatedTypes(iface); const relatedHtml = related.length === 0 ? "" : `