# PACKAGE: @nofinite/charts High-performance interactive SVG and canvas charting library with OKLCH theme tokens for React. You are an expert React developer using @nofinite/charts. Rules: 1. Import chart components (AreaChart, BarChart, LineChart, DonutChart, PieChart, ScatterChart, Sparkline, HeatmapChart) from '@nofinite/charts/react'. 2. All charts automatically adhere to active NUICSS themes and dark/light OKLCH color palettes. 3. Pass data arrays and custom accessor functions (xAccessor, yAccessor, labelAccessor, valueAccessor). --- ## TypeScript API Reference (Props) ### AreaChart - `data: T[]` (Default: none) - `series: ChartSeries[]` (Default: none) - `areaMode: any` (Default: overlapping) - `referenceLines: ReferenceLine[]` (Default: none) - `showLegend: boolean` (Default: none) - `legendPosition: enum` (Default: bottom) - `xAccessor: ((d: T) => string | number | Date)` (Default: none) - `yAccessor: ((d: T) => number)` (Default: none) - `width: number` (Default: none) - `height: number` (Default: 300) - `margin: { top: number; right: number; bottom: number; left: number; }` (Default: none) - `color: string` (Default: var(--chart-1, var(--color-primary))) - `className: string` (Default: none) - `ariaLabel: string` (Default: none) - `showGrid: boolean` (Default: true) - `showAxes: boolean` (Default: true) - `showTooltip: boolean` (Default: true) - `showCrosshair: boolean` (Default: true) - `animate: boolean` (Default: true) - `downsampleThreshold: number` (Default: none) - `xTickFormat: ((val: string | number | Date) => string)` (Default: none) - `yTickFormat: ((val: number) => string)` (Default: none) - `tooltipFormatter: any` (Default: none) - `onToggleSeries: ((seriesName: string) => void)` (Default: none) ### BarChart - `data: T[]` (Default: none) - `series: ChartSeries[]` (Default: none) - `barLayout: any` (Default: grouped) - `referenceLines: ReferenceLine[]` (Default: none) - `showLegend: boolean` (Default: none) - `legendPosition: enum` (Default: bottom) - `animate: boolean` (Default: true) - `xAccessor: ((d: T) => string | number | Date)` (Default: none) - `yAccessor: ((d: T) => number)` (Default: none) - `width: number` (Default: none) - `height: number` (Default: 300) - `margin: { top: number; right: number; bottom: number; left: number; }` (Default: none) - `color: string` (Default: var(--chart-1, var(--color-primary))) - `className: string` (Default: none) - `ariaLabel: string` (Default: none) - `showGrid: boolean` (Default: true) - `showAxes: boolean` (Default: true) - `showTooltip: boolean` (Default: true) - `xTickFormat: ((val: string | number | Date) => string)` (Default: none) - `yTickFormat: ((val: number) => string)` (Default: none) - `tooltipFormatter: any` (Default: none) - `onToggleSeries: ((seriesName: string) => void)` (Default: none) ### LineChart - `data: T[]` (Default: none) - `series: ChartSeries[]` (Default: none) - `referenceLines: ReferenceLine[]` (Default: none) - `showLegend: boolean` (Default: none) - `legendPosition: enum` (Default: bottom) - `xAccessor: ((d: T) => string | number | Date)` (Default: none) - `yAccessor: ((d: T) => number)` (Default: none) - `width: number` (Default: none) - `height: number` (Default: 300) - `margin: { top: number; right: number; bottom: number; left: number; }` (Default: none) - `color: string` (Default: var(--chart-1, var(--color-primary))) - `className: string` (Default: none) - `ariaLabel: string` (Default: none) - `showGrid: boolean` (Default: true) - `showAxes: boolean` (Default: true) - `showTooltip: boolean` (Default: true) - `showCrosshair: boolean` (Default: true) - `animate: boolean` (Default: true) - `downsampleThreshold: number` (Default: none) - `xTickFormat: ((val: string | number | Date) => string)` (Default: none) - `yTickFormat: ((val: number) => string)` (Default: none) - `tooltipFormatter: any` (Default: none) - `onToggleSeries: ((seriesName: string) => void)` (Default: none) ### DonutChart - `data (required): T[]` (Default: none) - `width: number` (Default: none) - `height: number` (Default: none) - `className: string` (Default: none) - `ariaLabel: string` (Default: none) - `showTooltip: boolean` (Default: none) - `animate: boolean` (Default: none) - `tooltipFormatter: any` (Default: none) - `labelAccessor: ((d: T) => string)` (Default: none) - `valueAccessor: ((d: T) => number)` (Default: none) - `donutCutout: number` (Default: none) ### PieChart - `data (required): T[]` (Default: none) - `width: number` (Default: none) - `height: number` (Default: 300) - `donutCutout: number` (Default: 0) - `className: string` (Default: none) - `ariaLabel: string` (Default: none) - `showTooltip: boolean` (Default: true) - `animate: boolean` (Default: true) - `tooltipFormatter: any` (Default: none) - `labelAccessor: ((d: T) => string)` (Default: none) - `valueAccessor: ((d: T) => number)` (Default: none) ### ScatterChart - `data: T[]` (Default: none) - `series: ChartSeries[]` (Default: none) - `xAccessor: ((d: T) => string | number | Date)` (Default: none) - `yAccessor: ((d: T) => number)` (Default: none) - `width: number` (Default: none) - `height: number` (Default: 300) - `margin: { top: number; right: number; bottom: number; left: number; }` (Default: none) - `color: string` (Default: var(--chart-1, var(--color-primary))) - `className: string` (Default: none) - `ariaLabel: string` (Default: none) - `showGrid: boolean` (Default: true) - `showAxes: boolean` (Default: true) - `showTooltip: boolean` (Default: true) - `showCrosshair: boolean` (Default: true) - `showLegend: boolean` (Default: false) - `legendPosition: enum` (Default: bottom) - `animate: boolean` (Default: true) - `xLabel: string` (Default: none) - `yLabel: string` (Default: none) - `downsampleThreshold: number` (Default: none) - `xTickFormat: ((val: string | number | Date) => string)` (Default: none) - `yTickFormat: ((val: number) => string)` (Default: none) - `tooltipFormatter: any` (Default: none) - `onToggleSeries: ((seriesName: string) => void)` (Default: none) ### Sparkline - `data (required): number[]` (Default: none) - `width: number` (Default: 120) - `height: number` (Default: 36) - `color: string` (Default: var(--color-primary)) - `className: string` (Default: none) - `ariaLabel: string` (Default: none) --- ### Document: charts/accessibility/page.mdx # Accessibility (A11y) Standards **Nofinite Charts** incorporates automated W3C WAI-ARIA standards, screen-reader data table generation (`generateA11yTableHtml`), and keyboard navigation directly into its universal core rendering engine. ```ts // Framework-Agnostic Core import { generateA11yTableHtml, Chart } from '@nofinite/charts'; // React Adapter import { AreaChart, BarChart } from '@nofinite/charts/react'; ``` --- ## Architectural Accessibility Standards 1. **Semantic Roles:** The parent container announces `role="region"` with an informative `aria-label`. The root SVG specifies `role="img"`. 2. **Automated Hidden Data Table (`generateA11yTableHtml`):** Automatically injects a visually hidden (`sr-only`) semantic HTML `` mirroring all chart data points. Screen reader users can inspect tabular numbers without relying on mouse coordinate hovers. 3. **SVG `` and `<desc>` Tags:** Every chart embeds dynamic SVG titles summarizing overall trend direction, data point count, and axis ranges. 4. **High-Contrast Mode Support:** Honors `forced-colors: active` media queries by utilizing system strokes (`CanvasText`, `Highlight`). --- ## 1. Framework-Agnostic Core Usage ### Automated Table Generation (`generateA11yTableHtml`) For server-side rendering, static site generation, or custom DOM builders, generate accessible tabular data representations: ```ts import { generateA11yTableHtml } from '@nofinite/charts'; const series = [ { name: 'Revenue', data: [ { label: 'Q1', y: 45000 }, { label: 'Q2', y: 58000 }, { label: 'Q3', y: 72000 } ] } ]; // Returns: <table class="sr-only"><caption>REVENUE data table</caption>...</table> const tableHtml = generateA11yTableHtml(series, { title: 'Quarterly Revenue Performance' }); ``` ### Native DOM Mounting with A11y When using `new Chart()`, accessibility structures are mounted automatically: ```ts import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const chart = new Chart({ element: document.querySelector('#a11y-chart'), variant: 'area', data: [ { time: '12:00', cpu: 42 }, { time: '12:05', cpu: 65 }, { time: '12:10', cpu: 88 } ], xAccessor: (d) => d.time, yAccessor: (d) => d.cpu, xLabel: 'Timestamp (UTC)', yLabel: 'CPU Load (%)' }); ``` --- ## 2. React Adapter Usage All React chart components provide first-class accessibility props: ```tsx import React from 'react'; import { AreaChart } from '@nofinite/charts/react'; import '@nofinite/nuicss/styles.css'; const telemetryData = [ { time: '12:00', cpu: 42 }, { time: '12:05', cpu: 65 }, { time: '12:10', cpu: 88 }, { time: '12:15', cpu: 54 }, ]; export function AccessibleTelemetryChart() { return ( <AreaChart data={telemetryData} xAccessor={(d) => d.time} yAccessor={(d) => d.cpu} height={300} showTooltip={true} /> ); } ``` --- ### Document: charts/area-chart/page.mdx # AreaChart AreaChart displays quantitative progression and continuous volume over time, featuring smooth Bézier curves, semi-transparent gradient fills, and interactive crosshair scrubbing. ```ts // Framework-Agnostic Core import { Chart, calculateAreaPath } from '@nofinite/charts'; // React Adapter import { AreaChart } from '@nofinite/charts/react'; ``` --- ## Interactive Preview <Preview name="charts-area" vanillaCode={`import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.getElementById('area-chart-container'); const chart = new Chart({ element: container, variant: 'area', data: [ { time: '00:00', latency: 42 }, { time: '04:00', latency: 38 }, { time: '08:00', latency: 45 }, { time: '12:00', latency: 68 }, { time: '16:00', latency: 52 }, { time: '20:00', latency: 31 } ], xAccessor: (d) => d.time, yAccessor: (d) => d.latency, color: 'var(--color-primary)', height: 260, showGrid: true, showAxes: true, showTooltip: true });`} /> --- ## 1. Framework-Agnostic Core Usage ### Direct DOM Mounting (`new Chart`) Mount interactive area charts directly to any HTML DOM node with automatic `ResizeObserver` responsiveness and crosshairs: ```ts import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.querySelector('#latency-chart'); const chart = new Chart({ element: container, variant: 'area', data: [ { time: '00:00', latency: 42 }, { time: '04:00', latency: 38 }, { time: '08:00', latency: 45 }, { time: '12:00', latency: 68 }, { time: '16:00', latency: 52 }, { time: '20:00', latency: 31 } ], xAccessor: (d) => d.time, yAccessor: (d) => d.latency, color: 'var(--color-primary)', showGrid: true, showAxes: true, showTooltip: true }); // Update data reactively chart.update([ { time: '00:00', latency: 40 }, { time: '04:00', latency: 35 }, { time: '08:00', latency: 50 }, { time: '12:00', latency: 62 }, { time: '16:00', latency: 48 }, { time: '20:00', latency: 29 } ]); // Clean up listeners and observers chart.destroy(); ``` ### Pure Mathematical Vector Path (`calculateAreaPath`) For custom SVG pipelines, SSR, or Canvas drawing, calculate closed area SVG path data (`d="..."`) without mounting to the DOM: ```ts import { calculateAreaPath } from '@nofinite/charts'; const { path, linePath } = calculateAreaPath({ data: [ { x: '2026-01-01', y: 100 }, { x: '2026-02-01', y: 150 }, { x: '2026-03-01', y: 130 } ], width: 600, height: 300, curve: 'monotoneX' }); // Use directly in SVG: // <path d={path} fill="url(#gradient)" /> // <path d={linePath} fill="none" stroke="var(--color-primary)" strokeWidth="2" /> ``` --- ## 2. React Adapter Usage Declarative React JSX component for React 18 & 19: ```tsx import { AreaChart } from '@nofinite/charts/react'; const latencyData = [ { time: '00:00', latency: 42 }, { time: '04:00', latency: 38 }, { time: '08:00', latency: 45 }, { time: '12:00', latency: 68 }, { time: '16:00', latency: 52 }, { time: '20:00', latency: 31 } ]; export default function LatencyWidget() { return ( ); } ``` --- ## API Reference ### Framework-Agnostic Core Options (`ChartOptions`) | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `element` | `HTMLElement` | — | Target DOM container to mount into. | | `variant` | `'area'` | `'area'` | Specifies the area visualization engine. | | `data` | `DataPoint[]` | `[]` | Array of data objects. | | `xAccessor` | `(d: any) => any` | `d => d.x` | Extracts the X-axis key or date. | | `yAccessor` | `(d: any) => number` | `d => d.y` | Extracts the numeric Y-axis value. | | `color` | `string` | `'var(--color-primary)'` | Primary stroke and gradient color. | | `height` | `number` | `300` | Height in pixels. | | `showGrid` | `boolean` | `true` | Renders background Cartesian gridlines. | | `showAxes` | `boolean` | `true` | Renders X and Y axis text labels. | | `showTooltip` | `boolean` | `true` | Renders glassmorphic hover popover. | ### React Component Props --- ### Document: charts/bar-chart/page.mdx # BarChart BarChart compares discrete values across categories using responsive rectangular columns with hover elevation, category axis alignment, and tooltip coordination. ```ts // Framework-Agnostic Core import { Chart, calculateBarLayout } from '@nofinite/charts'; // React Adapter import { BarChart } from '@nofinite/charts/react'; ``` --- ## Interactive Preview <Preview name="chart" vanillaCode={`import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.getElementById('bar-chart-container'); const chart = new Chart({ element: container, variant: 'bar', data: [ { label: 'Q1', revenue: 45000 }, { label: 'Q2', revenue: 58000 }, { label: 'Q3', revenue: 72000 }, { label: 'Q4', revenue: 91000 } ], xAccessor: (d) => d.label, yAccessor: (d) => d.revenue, height: 240, showGrid: true, showAxes: true, showTooltip: true });`} /> --- ## 1. Framework-Agnostic Core Usage ### Direct DOM Mounting (`new Chart`) Mount an interactive bar chart directly to any HTML DOM node: ```ts import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.querySelector('#revenue-chart'); const chart = new Chart({ element: container, variant: 'bar', data: [ { quarter: 'Q1', revenue: 45000 }, { quarter: 'Q2', revenue: 58000 }, { quarter: 'Q3', revenue: 72000 }, { quarter: 'Q4', revenue: 91000 } ], xAccessor: (d) => d.quarter, yAccessor: (d) => d.revenue, barLayout: 'grouped', // 'grouped' | 'stacked' | 'percent' height: 280, showGrid: true, showAxes: true, showTooltip: true }); // Update data in real-time chart.update([ { quarter: 'Q1', revenue: 50000 }, { quarter: 'Q2', revenue: 64000 }, { quarter: 'Q3', revenue: 81000 }, { quarter: 'Q4', revenue: 105000 } ]); // Clean up listeners and observers chart.destroy(); ``` ### Pure Mathematical Geometry Calculator (`calculateBarLayout`) For custom SVG pipelines or headless canvas generation, compute exact bar coordinate geometry (`x`, `y`, `width`, `height`) mathematically: ```ts import { calculateBarLayout } from '@nofinite/charts'; const bars = calculateBarLayout({ data: [ { label: 'Q1', value: 450 }, { label: 'Q2', value: 680 }, { label: 'Q3', value: 520 } ], width: 500, height: 250, orientation: 'vertical' }); bars.forEach((bar) => { console.log(`Bar ${bar.label}: x=${bar.x}, y=${bar.y}, w=${bar.width}, h=${bar.height}`); }); ``` --- ## 2. React Adapter Usage Declarative React JSX component for React 18 & 19: ```tsx import { BarChart } from '@nofinite/charts/react'; const quarterlyData = [ { quarter: 'Q1', revenue: 45000 }, { quarter: 'Q2', revenue: 58000 }, { quarter: 'Q3', revenue: 72000 }, { quarter: 'Q4', revenue: 91000 } ]; export default function QuarterlyRevenueChart() { return ( ); } ``` --- ## API Reference ### Framework-Agnostic Core Options (`ChartOptions`) | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `element` | `HTMLElement` | — | Target DOM container to mount into. | | `variant` | `'bar'` | `'bar'` | Specifies the bar visualization engine. | | `data` | `DataPoint[]` | `[]` | Array of data objects. | | `barLayout` | `'grouped' \| 'stacked' \| 'percent'` | `'grouped'` | Multi-series bar stacking geometry mode. | | `xAccessor` | `(d: any) => any` | `d => d.label` | Extracts category label key. | | `yAccessor` | `(d: any) => number` | `d => d.value` | Extracts numeric bar height value. | | `color` | `string` | `'var(--color-primary)'` | Column fill color or token variable. | | `height` | `number` | `280` | Height in pixels. | | `showGrid` | `boolean` | `true` | Renders background Cartesian gridlines. | | `showAxes` | `boolean` | `true` | Renders category and value axis labels. | ### React Component Props --- ### Document: charts/examples/page.mdx # Charts Production Examples Below are production-ready, copy-paste implementations of **Nofinite Charts** showcasing both **Framework-Agnostic Core** and **React** integrations. --- ## Example 1: Vanilla TypeScript / DOM High-Frequency Dashboard Direct DOM mounting with real-time streaming data updates and instant PNG export without React: ```ts import { Chart, downsampleLTTB } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; // 1. Initialize container const container = document.getElementById('telemetry-dashboard')!; // 2. Generate initial telemetry series let telemetryPoints = Array.from({ length: 5000 }, (_, i) => ({ time: new Date(Date.now() - (5000 - i) * 1000).toISOString(), cpu: 20 + Math.random() * 40 + Math.sin(i / 50) * 15 })); // Downsample 5,000 points to 400 visually pristine points let renderedData = downsampleLTTB(telemetryPoints, 400); // 3. Mount interactive chart const chart = new Chart({ element: container, variant: 'line', data: renderedData, xAccessor: (d) => d.time, yAccessor: (d) => d.cpu, color: 'var(--color-primary)', height: 320, showGrid: true, showAxes: true, showCrosshair: true, showTooltip: true }); // 4. Simulate real-time streaming ticks every second const interval = setInterval(() => { telemetryPoints.push({ time: new Date().toISOString(), cpu: 20 + Math.random() * 40 }); if (telemetryPoints.length > 5000) telemetryPoints.shift(); // Re-downsample and update chart.update(downsampleLTTB(telemetryPoints, 400)); }, 1000); // 5. Export to PNG button document.getElementById('export-btn')?.addEventListener('click', async () => { await chart.exportPNG('telemetry-report.png', 2); }); ``` --- ## Example 2: React Executive SaaS Revenue Dashboard Combines a multi-series Area Chart (New vs Expansion Revenue) with an executive summary cards grid featuring inline `<Sparkline />` trendlines: ```tsx import React from 'react'; import { AreaChart, Sparkline } from '@nofinite/charts/react'; import '@nofinite/nuicss/styles.css'; const revenueData = [ { month: 'Jan', newMrr: 28000, expansion: 14000 }, { month: 'Feb', newMrr: 32000, expansion: 18500 }, { month: 'Mar', newMrr: 39000, expansion: 22000 }, { month: 'Apr', newMrr: 43000, expansion: 27000 }, { month: 'May', newMrr: 49000, expansion: 31500 }, { month: 'Jun', newMrr: 58000, expansion: 39000 }, ]; export function SaasExecutiveDashboard() { return ( <Sparkline data={[820, 890, 940, 1010, 1080, 1164]} width={90} height={36} color="var(--color-success)" /> </div> <Sparkline data={[1.2, 1.15, 1.05, 0.98, 0.91, 0.82]} width={90} height={36} color="var(--color-success)" /> </div> </div> {/* Main Multi-Series Area Chart */} </div> ); } ``` --- ### Document: charts/export/page.mdx # Export Utilities `@nofinite/charts` provides high-performance client-side export functions for saving charts as raster images (`PNG`), vector assets (`SVG`), or tabular datasets (`CSV`). These utilities are pure JavaScript/TypeScript functions that operate directly on DOM SVG nodes or series data, working identically across Vanilla JS, Vue, Svelte, and React. ```ts // Framework-Agnostic Core import { exportToPNG, exportToSVG, exportToCSV } from '@nofinite/charts'; // React Adapter (Components) import { BarChart, AreaChart } from '@nofinite/charts/react'; ``` --- ## 1. Framework-Agnostic Core Usage ### Exporting via `Chart` Instance If you are using the state-managed `Chart` class, call the built-in instance export methods: ```ts import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const chart = new Chart({ element: document.getElementById('chart-container'), variant: 'bar', data: [ { label: 'Q1', value: 450 }, { label: 'Q2', value: 680 } ] }); // Download high-resolution 2x retina PNG await chart.exportPNG('quarterly-report.png', 2); // Download standalone SVG vector file chart.exportSVG('chart-vector.svg'); // Download underlying data as CSV spreadsheet chart.exportCSV('raw-metrics.csv'); ``` ### Standalone Functional DOM Exporters Operate directly on any rendered `<svg>` element in the DOM: ```ts import { exportToPNG, exportToSVG, exportToCSV } from '@nofinite/charts'; const svgElement = document.querySelector('.nui-chart-container svg') as SVGElement; // 1. Export as High-DPI PNG await exportToPNG(svgElement, 'dashboard-metric.png', 2); // 2. Export as SVG Vector exportToSVG(svgElement, 'dashboard-vector.svg'); // 3. Export Data Series as CSV exportToCSV(seriesList, 'metrics.csv'); ``` --- ## 2. React Adapter Usage Use standard React `useRef` to reference the chart container and invoke export functions: ```tsx import React, { useRef } from 'react'; import { BarChart } from '@nofinite/charts/react'; import { exportToPNG, exportToSVG } from '@nofinite/charts'; import { Button } from '@nofinite/nui'; import '@nofinite/nuicss/styles.css'; const data = [ { month: 'Jan', val: 45 }, { month: 'Feb', val: 58 }, { month: 'Mar', val: 72 } ]; export function ExportableChart() { const containerRef = useRef<HTMLDivElement>(null); const handleDownloadPng = async () => { if (!containerRef.current) return; const svgEl = containerRef.current.querySelector('svg'); if (svgEl) { await exportToPNG(svgEl, 'report.png', 2); } }; const handleDownloadSvg = () => { if (!containerRef.current) return; const svgEl = containerRef.current.querySelector('svg'); if (svgEl) { exportToSVG(svgEl, 'report.svg'); } }; return ( </div> ); } ``` --- ## API Reference ### Export Functions | Function | Parameters | Return Type | Description | | :--- | :--- | :--- | :--- | | `exportToPNG` | `(svgElement: SVGElement, filename = 'chart.png', scale = 2)` | `Promise<Blob \| null>` | Converts SVG to raster PNG and triggers browser download. | | `exportToSVG` | `(svgElement: SVGElement, filename = 'chart.svg')` | `string` | Serializes SVG markup and triggers vector file download. | | `exportToCSV` | `(seriesList: ChartSeries[], filename = 'chart-data.csv')` | `string` | Converts series data into CSV format and triggers spreadsheet download. | --- ### Document: charts/installation/page.mdx # Installation & Setup Get started with `@nofinite/charts`. **Nofinite Charts** is engineered as a **universal, framework-agnostic** data visualization suite. The core library (`@nofinite/charts`) runs in any JavaScript or TypeScript environment with zero framework dependencies. The React adapter (`@nofinite/charts/react`) is provided as an optional layer for React and Next.js applications. --- ## 1. Package Installation Install `@nofinite/charts` alongside `@nofinite/nuicss` using your preferred package manager: ```bash # pnpm pnpm add @nofinite/charts @nofinite/nuicss # npm npm install @nofinite/charts @nofinite/nuicss # yarn yarn add @nofinite/charts @nofinite/nuicss ``` > **Peer Dependency Notice:** `react` and `react-dom` are strictly **optional** peer dependencies (`peerDependenciesMeta.react.optional: true`). If you are using Vanilla JS, Vue, Svelte, or Node.js, you do **not** need to install React. --- ## 2. Stylesheet Configuration Chart container geometry, interactive crosshair scrubbers, frosted glass popovers, and keyframe animations are pre-compiled directly into **NUICSS**. Import the single unified stylesheet at the root of your application (`globals.css`, `main.ts`, or `layout.tsx`): ```css /* In your CSS */ @import "@nofinite/nuicss"; ``` Or in your JavaScript/TypeScript entry point: ```ts import '@nofinite/nuicss/styles.css'; ``` > **Zero Downstream CSS Invariant:** Do **not** import `@nofinite/charts/styles.css`. NUICSS provides all necessary styling classes and OKLCH color variables automatically. --- ## 3. Configure Theme Tokens `@nofinite/charts` resolves to perceptually uniform OKLCH variables. By default, it inherits your active NUICSS palette: ```css :root { --chart-1: oklch(0.65 0.22 260); /* Primary series accent */ --chart-2: oklch(0.70 0.19 160); /* Secondary series accent */ --chart-3: oklch(0.75 0.18 55); /* Tertiary series accent */ --chart-4: oklch(0.62 0.21 320); /* Fourth series accent */ --chart-5: oklch(0.80 0.16 85); /* Fifth series accent */ --chart-6: oklch(0.58 0.20 200); /* Sixth series accent */ --chart-7: oklch(0.68 0.18 290); /* Seventh series accent */ --chart-8: oklch(0.72 0.17 120); /* Eighth series accent */ } ``` --- ## 4. Verification ### Option A: Framework-Agnostic Core Verification (Vanilla JS / TS / DOM) Verify that charts mount into a raw HTML element: ```html <script type="module"> import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const chart = new Chart({ element: document.getElementById('chart'), variant: 'bar', data: [ { label: 'Q1', value: 45 }, { label: 'Q2', value: 80 }, { label: 'Q3', value: 65 }, { label: 'Q4', value: 95 } ], showGrid: true, showAxes: true, showTooltip: true }); </script> ``` ### Option B: React Verification (`@nofinite/charts/react`) If developing in React or Next.js, verify the declarative JSX component: ```tsx import React from 'react'; import { BarChart } from '@nofinite/charts/react'; import '@nofinite/nuicss/styles.css'; export default function TestChart() { return ( ); } ``` --- ### Document: charts/legend/page.mdx # ChartLegend & Dimensions `@nofinite/charts` provides modular auxiliary tools for synchronizing legends, measuring responsive container bounds, and positioning custom tooltips across both framework-agnostic DOM and React applications. ```ts // Framework-Agnostic Core import { renderLegendHtml, Chart } from '@nofinite/charts'; // React Adapter import { ChartLegend, useChartDimensions, useChartTooltip } from '@nofinite/charts/react'; ``` --- ## 1. Framework-Agnostic Core Usage ### Pure Legend HTML Generator (`renderLegendHtml`) Generate a lightweight, semantic color-coded legend in pure HTML: ```ts import { renderLegendHtml } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const legendHtml = renderLegendHtml([ { name: 'Organic Search', color: 'var(--chart-1)', hidden: false }, { name: 'Direct Traffic', color: 'var(--chart-2)', hidden: false }, { name: 'Social Media', color: 'var(--chart-3)', hidden: true } ]); // Mount into DOM document.querySelector('#legend-container').innerHTML = legendHtml; ``` --- ## 2. React Adapter Usage ### ChartLegend Component Renders responsive series chips with semantic OKLCH color indicators and interactive toggle triggers: ```tsx import { ChartLegend } from '@nofinite/charts/react'; const series = [ { label: 'Organic Search', color: 'var(--chart-1)' }, { label: 'Direct Traffic', color: 'var(--chart-2)' }, { label: 'Social Media', color: 'var(--chart-3)' }, ]; export default function LegendDemo() { return ( ); } ``` ### useChartDimensions Hook Measures a parent container's width and height in real time using `ResizeObserver`, ensuring SVG visualizations adapt instantly to viewport changes: ```tsx import { useRef } from 'react'; import { useChartDimensions } from '@nofinite/charts/react'; function CustomSvgViz() { const containerRef = useRef<HTMLDivElement>(null); const { width, height } = useChartDimensions(containerRef, { defaultWidth: 400, defaultHeight: 300, }); return ( ); } ``` --- ### Document: charts/line-chart/page.mdx # LineChart LineChart visualizes continuous data sequences, dynamic rates, and time-series fluctuations with precision Bézier curves, active marker points, and interactive crosshair scrubbing. ```ts // Framework-Agnostic Core import { Chart, downsampleLTTB } from '@nofinite/charts'; // React Adapter import { LineChart } from '@nofinite/charts/react'; ``` --- ## Interactive Preview <Preview name="charts-line" vanillaCode={`import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.getElementById('line-chart-container'); const chart = new Chart({ element: container, variant: 'line', data: [ { time: '00:00', cpu: 22 }, { time: '04:00', cpu: 35 }, { time: '08:00', cpu: 68 }, { time: '12:00', cpu: 84 }, { time: '16:00', cpu: 52 }, { time: '20:00', cpu: 40 } ], xAccessor: (d) => d.time, yAccessor: (d) => d.cpu, color: 'var(--color-primary)', height: 240, showGrid: true, showAxes: true, showTooltip: true, showCrosshair: true });`} /> --- ## 1. Framework-Agnostic Core Usage ### Direct DOM Mounting (`new Chart`) Mount an interactive line chart directly to any HTML DOM node: ```ts import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.querySelector('#cpu-trend-chart'); const chart = new Chart({ element: container, variant: 'line', data: [ { time: '00:00', cpu: 22 }, { time: '04:00', cpu: 35 }, { time: '08:00', cpu: 68 }, { time: '12:00', cpu: 84 }, { time: '16:00', cpu: 52 }, { time: '20:00', cpu: 40 } ], xAccessor: (d) => d.time, yAccessor: (d) => d.cpu, color: 'var(--color-primary)', showGrid: true, showAxes: true, showTooltip: true, showCrosshair: true }); // Real-time telemetry tick update chart.update([ { time: '00:00', cpu: 22 }, { time: '04:00', cpu: 35 }, { time: '08:00', cpu: 68 }, { time: '12:00', cpu: 84 }, { time: '16:00', cpu: 52 }, { time: '20:00', cpu: 40 }, { time: '24:00', cpu: 38 } ]); // Cleanup chart.destroy(); ``` ### High-Density Time-Series Downsampling (`downsampleLTTB`) When monitoring 10,000 to 1,000,000 telemetry points, use the built-in **Largest Triangle Three Buckets (LTTB)** algorithm to preserve visual peaks and troughs while keeping SVG frame rates at 60 FPS: ```ts import { downsampleLTTB, Chart } from '@nofinite/charts'; const rawHighFrequencyData = [ // 50,000 high-frequency sensor ticks ]; // Downsample 50,000 points to 600 visually identical points const optimizedData = downsampleLTTB(rawHighFrequencyData, 600); const chart = new Chart({ element: document.querySelector('#telemetry-chart'), variant: 'line', data: optimizedData }); ``` --- ## 2. React Adapter Usage Declarative React JSX component for React 18 & 19: ```tsx import { LineChart } from '@nofinite/charts/react'; const serverLoad = [ { time: '00:00', cpu: 22 }, { time: '04:00', cpu: 35 }, { time: '08:00', cpu: 68 }, { time: '12:00', cpu: 84 }, { time: '16:00', cpu: 52 }, { time: '20:00', cpu: 40 } ]; export default function CpuLoadChart() { return ( ); } ``` --- ## API Reference ### Framework-Agnostic Core Options (`ChartOptions`) | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `element` | `HTMLElement` | — | Target DOM container to mount into. | | `variant` | `'line'` | `'line'` | Specifies continuous line visualization engine. | | `data` | `DataPoint[]` | `[]` | Array of continuous sequence data objects. | | `xAccessor` | `(d: any) => any` | `d => d.x` | Extracts sequential X key or timestamp. | | `yAccessor` | `(d: any) => number` | `d => d.y` | Extracts numeric trend value. | | `color` | `string` | `'var(--color-primary)'` | Line stroke color or token variable. | | `height` | `number` | `260` | Height in pixels. | | `showCrosshair` | `boolean` | `true` | Renders dual-axis interactive scrubbing lines. | | `showTooltip` | `boolean` | `true` | Renders glassmorphic hover popover. | ### React Component Props --- ### Document: charts/llms/page.mdx # LLMs.txt Documentation How to get tools like Cursor, Windsurf, GitHub Copilot, ChatGPT, and Claude to understand `@nofinite/charts`. > [!TIP] > Looking for unified ecosystem presets or multi-package rules? Visit our central [AI Agents Hub](/ai). We support **LLMs.txt** files for making `@nofinite/charts` data visualization primitives directly available to large language models. --- ## Directory Overview The following machine-readable context files are available: - [`/charts/llms.txt`](/charts/llms.txt): The main LLMs index for `@nofinite/charts`. - [`/charts/llms-full.txt`](/charts/llms-full.txt): Complete context bundle containing all 8 chart components, props, and accessor patterns. - [`/llms.txt`](/llms.txt): Ecosystem index covering all 8 `@nofinite` libraries. - [`/llms-full.txt`](/llms-full.txt): The unified ecosystem bundle. --- ## Usage with Cursor & Windsurf ```markdown # Charts Rules for AI Assistants 1. Component Imports: Import charts from '@nofinite/charts/react' (AreaChart, BarChart, LineChart, PieChart, DonutChart, ScatterChart). 2. Data Accessors: Pass custom accessor functions: \`xAccessor={(d) => d.x}\`, \`yAccessor={(d) => d.y}\`. 3. Design Tokens: Charts automatically adhere to active NUICSS themes and dark/light OKLCH color palettes (var(--chart-1) through var(--chart-8)). ``` --- ### Document: charts/multi-series/page.mdx # Multi-Series Visualizations **Nofinite Charts** supports synchronized multi-series data visualization across Area, Bar, Line, and Scatter plots. Multi-series charts synchronize multiple data streams onto shared scales, allowing teams to compare performance across regions, cohorts, revenue streams, and time periods with zero visual misalignment. ```ts // Framework-Agnostic Core import { Chart, calculateMultiSeriesAreaPath, calculateMultiBarLayout } from '@nofinite/charts'; // React Adapter import { AreaChart, BarChart } from '@nofinite/charts/react'; ``` --- ## 1. Framework-Agnostic Core Usage ### Multi-Series DOM Instance (`new Chart`) Mount synchronized multi-series plots directly to any DOM container: ```ts import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.querySelector('#multi-area-chart'); const chart = new Chart({ element: container, variant: 'area', data: [ { date: '2026-01-01', usEast: 4200, euCentral: 3100, apSouth: 1800 }, { date: '2026-02-01', usEast: 5100, euCentral: 3800, apSouth: 2400 }, { date: '2026-03-01', usEast: 6300, euCentral: 4200, apSouth: 3100 }, { date: '2026-04-01', usEast: 5800, euCentral: 4900, apSouth: 3900 }, { date: '2026-05-01', usEast: 7200, euCentral: 5400, apSouth: 4800 }, { date: '2026-06-01', usEast: 8500, euCentral: 6200, apSouth: 5900 } ], series: [ { name: 'US East (N. Virginia)', key: 'usEast', color: 'var(--color-primary)' }, { name: 'EU Central (Frankfurt)', key: 'euCentral', color: 'var(--color-success)' }, { name: 'AP South (Mumbai)', key: 'apSouth', color: 'var(--color-warning)' } ], height: 320, showAxes: true, showGrid: true, showTooltip: true, showLegend: true }); ``` ### Multi-Series Mathematical Geometry (`calculateMultiBarLayout`) For headless bar layout calculations: ```ts import { calculateMultiBarLayout } from '@nofinite/charts'; const layout = calculateMultiBarLayout({ categories: ['Q1', 'Q2', 'Q3', 'Q4'], series: [ { name: 'Direct', data: [45, 52, 58, 64], color: 'var(--chart-1)' }, { name: 'Partner', data: [20, 26, 31, 38], color: 'var(--chart-2)' } ], width: 600, height: 300, mode: 'grouped' // 'grouped' | 'stacked' | 'percent' }); ``` --- ## 2. React Adapter Usage ### Multi-Series Area Chart ```tsx import React from 'react'; import { AreaChart } from '@nofinite/charts/react'; import '@nofinite/nuicss/styles.css'; const multiSeriesData = [ { date: '2026-01-01', usEast: 4200, euCentral: 3100, apSouth: 1800 }, { date: '2026-02-01', usEast: 5100, euCentral: 3800, apSouth: 2400 }, { date: '2026-03-01', usEast: 6300, euCentral: 4200, apSouth: 3100 }, { date: '2026-04-01', usEast: 5800, euCentral: 4900, apSouth: 3900 }, { date: '2026-05-01', usEast: 7200, euCentral: 5400, apSouth: 4800 }, { date: '2026-06-01', usEast: 8500, euCentral: 6200, apSouth: 5900 } ]; export function CloudRegionalTrafficChart() { return ( <AreaChart data={multiSeriesData} xKey="date" series={[ { key: 'usEast', label: 'US East (N. Virginia)', color: 'var(--color-primary)' }, { key: 'euCentral', label: 'EU Central (Frankfurt)', color: 'var(--color-success)' }, { key: 'apSouth', label: 'AP South (Mumbai)', color: 'var(--color-warning)' } ]} height={320} showAxes={true} showGrid={true} showTooltip={true} showLegend={true} legendPosition="bottom" /> </div> ); } ``` ### Grouped vs. Stacked Bar Charts ```tsx import { BarChart } from '@nofinite/charts/react'; // Grouped Bars (side-by-side) <BarChart data={multiSeriesData} xKey="date" series={seriesConfig} barLayout="grouped" /> // Stacked Bars (accumulated vertical total) <BarChart data={multiSeriesData} xKey="date" series={seriesConfig} barLayout="stacked" /> ``` --- ### Document: charts/page.mdx <PackageHero packageId="charts" /> --- ## Interactive Preview <Preview name="chart" vanillaCode={`import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.getElementById('chart-container'); // Mount responsive interactive bar chart directly to DOM const chart = new Chart({ element: container, variant: 'bar', data: [ { label: 'Jan', value: 45 }, { label: 'Feb', value: 52 }, { label: 'Mar', value: 68 }, { label: 'Apr', value: 84 }, { label: 'May', value: 95 }, { label: 'Jun', value: 110 } ], height: 240, showGrid: true, showAxes: true, showTooltip: true }); // Update data dynamically // chart.update(newSampleData); // Clean up when unmounting // chart.destroy();`} /> --- ## Quickstart ### 1. Framework-Agnostic Core (`@nofinite/charts`) Mount directly to any DOM element without React. Works in **Vanilla JavaScript**, **TypeScript**, **Vue 3**, **Svelte 5**, **SolidJS**, or backend **Node.js**: ```ts import { Chart, renderChart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.getElementById('chart')!; // Method A: State-managed, responsive interactive instance const chart = new Chart({ element: container, variant: 'area', // 'area' | 'line' | 'bar' | 'pie' | 'donut' | 'scatter' data: [ { date: '2026-01-01', value: 42 }, { date: '2026-02-01', value: 58 }, { date: '2026-03-01', value: 74 }, ], height: 280, showGrid: true, showAxes: true, showTooltip: true, }); // Method B: Pure isomorphic SVG HTML generator (zero DOM required) const svgHtml = renderChart({ variant: 'area', data: [{ x: 1, y: 10 }, { x: 2, y: 25 }], width: 600, height: 300, }); ``` ### 2. React Adapter (`@nofinite/charts/react`) Declarative JSX components for React 18 & 19 applications: ```tsx import React from 'react'; import { AreaChart } from '@nofinite/charts/react'; import '@nofinite/nuicss/styles.css'; const metrics = [ { time: '00:00', latency: 42 }, { time: '04:00', latency: 38 }, { time: '08:00', latency: 45 }, { time: '12:00', latency: 68 }, { time: '16:00', latency: 52 }, { time: '20:00', latency: 31 }, ]; export function LatencyChart() { return ( ); } ``` --- ## Architectural Invariants - **Universal Framework-Agnostic Core:** Zero React dependency required. The root export (`@nofinite/charts`) provides class-based DOM mounting, D3 math, downsampling, and SVG path generation. React (`@nofinite/charts/react`) is an optional adapter. - **Precision D3 Mathematical Engine:** Built on precision D3 algorithms (`d3-shape`, `d3-scale`, `d3-array`) with native SVG rendering and zero virtual DOM rendering bottlenecks. - **Zero Downstream CSS Invariant:** All chart containers, frosted glass popovers, and animated keyframes are bundled directly into **NUICSS**. You only ever need a single stylesheet import (`import '@nofinite/nuicss/styles.css'`). - **OKLCH Perceptual Theming:** Automatically synchronizes with your active **NUICSS** palette (`var(--color-primary)`, `var(--color-success)`, `var(--color-warning)`, `var(--color-danger)`) with 0ms light/dark mode reactivity. - **High-Frequency Downsampling:** Built-in Largest Triangle Three Buckets (`downsampleLTTB`) downsamples 100,000+ points to preserve 60 FPS fluidity. --- ## Supported Visualizations | Framework-Agnostic (`variant`) | React Component | Description | Best For | | :--- | :--- | :--- | :--- | | `variant: 'area'` | [`<AreaChart />`](/charts/area-chart) | Filled area curves with gradient fills | Cumulative volume, bandwidth, time-series growth | | `variant: 'bar'` | [`<BarChart />`](/charts/bar-chart) | Vertical or categorical columns | Categorical comparisons, revenue per quarter | | `variant: 'line'` | [`<LineChart />`](/charts/line-chart) | Continuous smooth trendlines | CPU load, real-time rates, stock prices | | `variant: 'pie'` / `'donut'` | [`<PieChart />`](/charts/pie-chart) | Proportional circular segments | Market share, segment allocation | | `variant: 'scatter'` | [`<ScatterChart />`](/charts/scatter-chart) | Multidimensional X/Y coordinate points | Statistical distribution, clusters, correlations | | Direct Vector Path | [`<Sparkline />`](/charts/sparklines) | Ultra-lightweight trendline | KPI summary cards, inline table rows | --- ## Documentation Directory ### Advanced Architecture & Deep Guides - [Vanilla Core & Math Engine](/charts/vanilla-core) — Pure D3 vector path generators, DOM mounting API, and Largest Triangle Three Buckets (`downsampleLTTB`) downsampling. - [Multi-Series Visualizations](/charts/multi-series) — Multi-series area charts, grouped/stacked bars, and multi-scatter plots on shared scales. - [Sparklines & Micro-Charts](/charts/sparklines) — Minimalist trendlines for KPI cards and data table rows. - [Theming & Glassmorphism](/charts/theming) — OKLCH palettes, frosted glass popovers (`backdrop-blur-xl`), and dark mode switching. - [Accessibility (A11y) Standards](/charts/accessibility) — Screen reader support, automated data table generation (`generateA11yTable`), and keyboard navigation. - [Exporting Charts](/charts/export) — Exporting SVG charts to PNG or standalone vector files. - [Production Examples](/charts/examples) — SaaS Revenue Dashboard, Financial KPI Grid, and High-Density Telemetry. - [Installation & Setup](/charts/installation) — Package installation, peer dependencies, and styling configuration. ### Visualizations Catalog - [AreaChart](/charts/area-chart) — Quantitative volume progression with smooth Bézier curves and gradient fills. - [BarChart](/charts/bar-chart) — Categorical data distributions, stacked bars, and hover highlights. - [LineChart](/charts/line-chart) — Multi-series trend monitoring with interactive marker points. - [PieChart & DonutChart](/charts/pie-chart) — Radial distributions and central summary callouts. - [ScatterChart](/charts/scatter-chart) — Two-dimensional coordinate projections and metric correlations. - [ChartLegend](/charts/legend) — Interactive series toggles and categorical color keys. --- ### Document: charts/pie-chart/page.mdx # PieChart & DonutChart PieChart and DonutChart illustrate numerical proportions and category shares with dynamic polar arc calculations, central summary callouts, and animated segment hover states. ```ts // Framework-Agnostic Core import { Chart, calculatePieSegments } from '@nofinite/charts'; // React Adapter import { PieChart, DonutChart } from '@nofinite/charts/react'; ``` --- ## Interactive Preview <Preview name="charts-donut" vanillaCode={`import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.getElementById('donut-chart-container'); const chart = new Chart({ element: container, variant: 'donut', data: [ { source: 'Direct', visitors: 4500 }, { source: 'Organic Search', visitors: 3200 }, { source: 'Referral', visitors: 1800 }, { source: 'Social Media', visitors: 950 } ], xAccessor: (d) => d.source, yAccessor: (d) => d.visitors, donutCutout: 0.65, height: 260, showLegend: true, showTooltip: true });`} /> --- ## 1. Framework-Agnostic Core Usage ### Direct DOM Mounting (`new Chart`) Mount interactive Donut or solid Pie charts directly to any HTML DOM node: ```ts import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.querySelector('#traffic-donut'); // Mount Donut Chart (with central cutout) const donutChart = new Chart({ element: container, variant: 'donut', // 'donut' | 'pie' donutCutout: 0.65, // 0 for solid pie, 0.65 for donut data: [ { label: 'Direct', value: 4500, color: 'var(--chart-1)' }, { label: 'Organic Search', value: 3200, color: 'var(--chart-2)' }, { label: 'Referral', value: 1800, color: 'var(--chart-3)' }, { label: 'Social Media', value: 950, color: 'var(--chart-4)' } ], height: 280, showLegend: true, showTooltip: true }); // Update data reactively donutChart.update([ { label: 'Direct', value: 5000 }, { label: 'Organic Search', value: 3800 }, { label: 'Referral', value: 2100 }, { label: 'Social Media', value: 1200 } ]); // Cleanup donutChart.destroy(); ``` ### Pure Polar Arc Calculator (`calculatePieSegments`) For custom SVG rendering, Canvas pipelines, or backend image generation, calculate raw arc paths (`d="..."`) without mounting to the DOM: ```ts import { calculatePieSegments } from '@nofinite/charts'; const segments = calculatePieSegments({ data: [ { label: 'Chrome', value: 68 }, { label: 'Safari', value: 19 }, { label: 'Firefox', value: 8 }, { label: 'Edge', value: 5 } ], width: 300, height: 300, donutRatio: 0.6 // 0 for solid pie }); segments.forEach(seg => { console.log(`Segment ${seg.data.label}: startAngle=${seg.startAngle}, endAngle=${seg.endAngle}, path=${seg.path}`); }); ``` --- ## 2. React Adapter Usage Declarative React JSX components for React 18 & 19: ### DonutChart Component ```tsx import { DonutChart } from '@nofinite/charts/react'; const trafficSources = [ { source: 'Direct', visitors: 4500 }, { source: 'Organic Search', visitors: 3200 }, { source: 'Referral', visitors: 1800 }, { source: 'Social', visitors: 950 } ]; export default function TrafficDonut() { return ( ); } ``` ### Solid PieChart Component ```tsx import { PieChart } from '@nofinite/charts/react'; <PieChart data={trafficSources} labelAccessor={(d) => d.source} valueAccessor={(d) => d.visitors} showTooltip={true} /> ``` --- ## API Reference ### Framework-Agnostic Core Options (`ChartOptions`) | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `element` | `HTMLElement` | — | Target DOM container to mount into. | | `variant` | `'pie' \| 'donut'` | `'pie'` | Specifies circular pie or donut layout. | | `data` | `DataPoint[]` | `[]` | Array of category proportion data objects. | | `donutCutout` | `number` | `0.6` | Center hole radius ratio (0 to 0.9). | | `xAccessor` | `(d: any) => any` | `d => d.label` | Extracts slice category label. | | `yAccessor` | `(d: any) => number` | `d => d.value` | Extracts numeric slice proportion. | | `height` | `number` | `280` | Height and bounding diameter in pixels. | | `showLegend` | `boolean` | `true` | Renders color chip legend. | | `showTooltip` | `boolean` | `true` | Renders glassmorphic hover popover. | ### React Component Props --- ### Document: charts/scatter-chart/page.mdx # ScatterChart ScatterChart visualizes multi-dimensional numeric data using Cartesian coordinates to identify clusters, mathematical correlations, and anomalies across large datasets. ```ts // Framework-Agnostic Core import { Chart } from '@nofinite/charts'; // React Adapter import { ScatterChart } from '@nofinite/charts/react'; ``` --- ## Interactive Preview <Preview name="charts-scatter" vanillaCode={`import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.getElementById('scatter-chart-container'); const chart = new Chart({ element: container, variant: 'scatter', data: [ { x: 10, y: 20 }, { x: 25, y: 45 }, { x: 40, y: 30 }, { x: 55, y: 70 }, { x: 70, y: 65 }, { x: 85, y: 90 } ], xAccessor: (d) => d.x, yAccessor: (d) => d.y, color: 'var(--color-primary)', height: 260, showGrid: true, showAxes: true, showCrosshair: true, showTooltip: true });`} /> --- ## 1. Framework-Agnostic Core Usage ### Direct DOM Mounting (`new Chart`) Mount an interactive scatter chart directly to any HTML DOM node with crosshair scrubbing: ```ts import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.querySelector('#cluster-chart'); const chart = new Chart({ element: container, variant: 'scatter', data: [ { x: 10, y: 20 }, { x: 25, y: 45 }, { x: 40, y: 30 }, { x: 55, y: 70 }, { x: 70, y: 65 }, { x: 85, y: 90 } ], xAccessor: (d) => d.x, yAccessor: (d) => d.y, color: 'var(--color-primary)', showGrid: true, showAxes: true, showCrosshair: true, showTooltip: true }); // Update coordinate points reactively chart.update([ { x: 12, y: 24 }, { x: 28, y: 50 }, { x: 45, y: 35 }, { x: 60, y: 78 } ]); // Cleanup chart.destroy(); ``` --- ## 2. React Adapter Usage Declarative React JSX component for React 18 & 19: ```tsx import { ScatterChart } from '@nofinite/charts/react'; const clusterData = [ { x: 10, y: 20 }, { x: 25, y: 45 }, { x: 40, y: 30 }, { x: 55, y: 70 }, { x: 70, y: 65 }, { x: 85, y: 90 } ]; export default function ScatterCluster() { return ( ); } ``` --- ## API Reference ### Framework-Agnostic Core Options (`ChartOptions`) | Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | `element` | `HTMLElement` | — | Target DOM container to mount into. | | `variant` | `'scatter'` | `'scatter'` | Specifies coordinate scatter layout. | | `data` | `DataPoint[]` | `[]` | Array of Cartesian coordinate data objects. | | `xAccessor` | `(d: any) => number` | `d => d.x` | Extracts continuous X coordinate value. | | `yAccessor` | `(d: any) => number` | `d => d.y` | Extracts continuous Y coordinate value. | | `color` | `string` | `'var(--color-primary)'` | Point marker fill and highlight color. | | `height` | `number` | `260` | Height in pixels. | | `showCrosshair` | `boolean` | `true` | Renders dual-axis interactive scrubbing lines. | | `showTooltip` | `boolean` | `true` | Renders glassmorphic hover popover. | ### React Component Props --- ### Document: charts/sparklines/page.mdx # Sparklines and Micro-Charts **Nofinite Charts** provides high-density micro-charts engineered for executive KPI summary cards, data table inline metrics, and high-frequency sparkline feeds. Sparklines eliminate axis chrome, gridlines, and legend overhead to deliver immediate trend momentum in compact, high-density footprints. ```ts // Framework-Agnostic Core import { calculateAreaPath, downsampleLTTB } from '@nofinite/charts'; // React Adapter import { Sparkline } from '@nofinite/charts/react'; ``` --- ## 1. Framework-Agnostic Core Usage ### Pure Vector Trendline Generation In Vanilla JavaScript, TypeScript, Svelte, or Vue, generate high-performance SVG trendlines with zero Virtual DOM overhead: ```ts import { calculateAreaPath } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; export function createSparklineSvg(data: number[], width = 120, height = 36, color = 'var(--color-primary)'): string { // Normalize array into coordinate points const points = data.map((val, idx) => ({ x: idx, y: val })); const { path, linePath } = calculateAreaPath({ data: points, width, height, curve: 'monotoneX', margin: { top: 2, right: 2, bottom: 2, left: 2 } }); return ` <svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" class="overflow-visible inline-block"> <path d="${path}" fill="${color}" fill-opacity="0.12" /> <path d="${linePath}" fill="none" stroke="${color}" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" /> </svg> `.trim(); } // Inject directly into an HTML table or card: const container = document.getElementById('kpi-trend'); container.innerHTML = createSparklineSvg([12, 19, 15, 27, 22, 34, 45]); ``` --- ## 2. React Adapter Usage ### Simple Sparkline Component ```tsx import React from 'react'; import { Sparkline } from '@nofinite/charts/react'; import '@nofinite/nuicss/styles.css'; export function SimpleSparkline() { const trendData = [12, 19, 15, 27, 22, 34, 45]; return ( <Sparkline data={trendData} width={120} height={36} color="var(--color-primary)" /> ); } ``` ### KPI Stat Cards Example Sparklines provide immediate visual context when paired with primary numbers: ```tsx import React from 'react'; import { Sparkline } from '@nofinite/charts/react'; import '@nofinite/nuicss/styles.css'; export function KpiMetricsGrid() { return ( <Sparkline data={[820, 890, 940, 1010, 1080, 1164]} width={100} height={40} color="var(--color-success)" /> </div> <Sparkline data={[68, 55, 62, 49, 44, 42]} width={100} height={40} color="var(--color-primary)" /> </div> </div> ); } ``` --- ## API Reference ### React Sparkline Props | Prop | Type | Default | Description | | :--- | :--- | :--- | :--- | | `data` | `number[]` | `[]` | Sequential numeric trend array. | | `width` | `number` | `120` | Bounding width in pixels. | | `height` | `number` | `36` | Bounding height in pixels. | | `color` | `string` | `'var(--color-primary)'` | Stroke line color and subtle fill tint. | | `showFill` | `boolean` | `true` | Renders semi-transparent translucent area fill under curve. | --- ### Document: charts/theming/page.mdx # Theming and Glassmorphic Popovers **Nofinite Charts** strictly adheres to the **Zero Downstream CSS Invariant**: it bundles no independent stylesheets. All colors, frosted glass surfaces, hairline reflections, and micro-typography are governed by **NUICSS** design tokens and superclasses. --- ## The OKLCH Color Palette In **NUICSS**, chart series map directly to perceptually uniform OKLCH design tokens: ```css :root { --color-primary: oklch(0.62 0.24 255); --color-info: oklch(0.65 0.18 220); --color-success: oklch(0.64 0.20 145); --color-warning: oklch(0.72 0.18 75); --color-danger: oklch(0.60 0.24 25); --chart-1: var(--color-primary); --chart-2: var(--color-success); --chart-3: var(--color-warning); --chart-4: var(--color-danger); --chart-5: var(--color-info); } ``` --- ## 1. Framework-Agnostic Core Theming In Vanilla JavaScript, TypeScript, or any framework, configure colors directly via CSS variables or the `color` option: ```ts import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const chart = new Chart({ element: document.querySelector('#themed-chart'), variant: 'line', data: myData, color: 'var(--chart-2)', // Directly inherits OKLCH success token series: [ { name: 'Primary Metric', key: 'primary', color: 'var(--color-primary)' }, { name: 'Benchmark Metric', key: 'benchmark', color: 'var(--fg-muted)' } ] }); ``` --- ## 2. React Adapter Theming When passing series colors in React, reference CSS variables directly: ```tsx import { LineChart } from '@nofinite/charts/react'; <LineChart data={data} xAccessor={(d) => d.date} yAccessor={(d) => d.value} strokeColor="var(--chart-1)" fillColor="var(--chart-1)" /> ``` --- ## Frosted Glass Popover Card (`.chart-tooltip`) Tooltips in **Nofinite Charts** render as modern, frosted glass popovers matching macOS / visionOS standards: - **`.chart-tooltip`:** `absolute pointer-events-none bg-surface/75 backdrop-blur-xl saturate-150 border border-white/10 dark:border-white/10 rounded-xl shadow-2xl px-3.5 py-2.5 text-xs text-default z-50` - **`.chart-tooltip-title`:** `text-[11px] font-semibold text-muted tracking-wider uppercase pb-1.5 mb-1.5 border-b border-default/20 opacity-80` - **`.chart-tooltip-swatch`:** `w-2 h-2 rounded-full ring-2 ring-current/25 shrink-0` - **`.chart-tooltip-value`:** `font-semibold font-mono text-default tabular-nums ml-auto` ### Specular Hairline & Ambient Shadows ```css /* Dark Mode */ .chart-tooltip { box-shadow: 0 16px 36px -6px oklch(0 0 0 / 0.35), inset 0 1px 0 0 oklch(1 0 0 / 0.15); } /* Light Mode */ [data-theme='light'] .chart-tooltip, .light .chart-tooltip { box-shadow: 0 12px 30px -4px oklch(0 0 0 / 0.12), inset 0 1px 0 0 oklch(1 0 0 / 0.6); } ``` --- ### Document: charts/vanilla-core/page.mdx # Framework-Agnostic Core & Mathematical Engine The foundation of **Nofinite Charts** is an isomorphic, zero-React mathematical calculation and rendering engine (`@nofinite/charts`). It exports pure vector path generators, scale builders, downsampling algorithms, export utilities, and a stateful DOM renderer (`Chart` class and `renderChart` function). ```ts import { Chart, renderChart, downsampleLTTB, calculateAreaPath, calculateBarLayout, calculatePieSegments, exportToPNG, exportToSVG, generateA11yTableHtml } from '@nofinite/charts'; ``` --- ## 1. High-Performance Time-Series Downsampling (`downsampleLTTB`) When rendering datasets with 10,000 to 1,000,000 data points (e.g. real-time telemetry, IoT sensors, high-frequency financial ticks), rendering raw SVG nodes causes DOM thrashing and frame drops. **Nofinite Charts** provides an optimized implementation of the **Largest Triangle Three Buckets (LTTB)** algorithm: - **$O(N)$ Linear Complexity:** Processes 100,000 points in sub-15ms. - **Morphology Preservation:** Unlike naive decimation (which skips intermediate points and misses critical spikes), LTTB evaluates triangular areas between consecutive buckets to preserve exact visual peaks, troughs, and volatility signatures. ```ts import { downsampleLTTB } from '@nofinite/charts'; const rawHighFrequencyData = [ // 50,000 telemetry samples { x: new Date('2026-01-01T00:00:00Z'), y: 12.4 }, { x: new Date('2026-01-01T00:00:01Z'), y: 14.1 }, ]; // Downsample down to 800 visually pristine points const optimizedData = downsampleLTTB(rawHighFrequencyData, 800); console.log(`Original points: ${rawHighFrequencyData.length}`); // 50,000 console.log(`Rendered points: ${optimizedData.length}`); // 800 ``` --- ## 2. Stateful DOM Engine (`new Chart`) The `Chart` class handles responsive element bounding, Cartesian scales, axis generation, interactive hover dots, crosshairs, and glassmorphic tooltips with zero virtual DOM overhead: ```ts import { Chart } from '@nofinite/charts'; import '@nofinite/nuicss/styles.css'; const container = document.getElementById('chart-container')!; const chart = new Chart({ element: container, variant: 'area', // 'area' | 'line' | 'bar' | 'pie' | 'donut' | 'scatter' data: [ { date: '2026-01-01', value: 45 }, { date: '2026-02-01', value: 52 }, { date: '2026-03-01', value: 68 }, ], xAccessor: (d) => d.date, yAccessor: (d) => d.value, height: 300, showGrid: true, showAxes: true, showTooltip: true, }); // Programmatic update chart.update([ { date: '2026-01-01', value: 50 }, { date: '2026-02-01', value: 65 }, { date: '2026-03-01', value: 82 }, ]); // Switch variant on the fly chart.setVariant('bar'); // Clean up observers and listeners chart.destroy(); ``` --- ## 3. Pure Mathematical Vector Calculators For custom graphics engines, server-side SVG generation, or Canvas rendering, the core exposes pure mathematical geometry calculators: ### `calculateAreaPath` Generates closed SVG path data (`d="..."`) for area fills and line paths: ```ts import { calculateAreaPath } from '@nofinite/charts'; const { path, linePath } = calculateAreaPath({ data: [{ x: 0, y: 10 }, { x: 1, y: 25 }, { x: 2, y: 18 }], width: 500, height: 250, curve: 'monotoneX' }); ``` ### `calculateBarLayout` Computes column geometry (`x`, `y`, `width`, `height`) for category data: ```ts import { calculateBarLayout } from '@nofinite/charts'; const bars = calculateBarLayout({ data: [{ label: 'Q1', value: 100 }, { label: 'Q2', value: 200 }], width: 500, height: 250, orientation: 'vertical' }); ``` ### `calculatePieSegments` Computes polar coordinates and arc paths: ```ts import { calculatePieSegments } from '@nofinite/charts'; const segments = calculatePieSegments({ data: [{ label: 'A', value: 60 }, { label: 'B', value: 40 }], width: 300, height: 300, donutRatio: 0.6 }); ``` --- ## 4. Universal Exporters & Accessibility ```ts import { exportToPNG, exportToSVG, exportToCSV, generateA11yTableHtml } from '@nofinite/charts'; // Export SVG to PNG await exportToPNG(svgElement, 'chart.png', 2); // Generate accessible W3C data table const a11yHtml = generateA11yTableHtml(seriesList, { title: 'Telemetry Data' }); ``` ---