/**
* LineChart — a time series, drawn and animated on the UI thread.
*
* The chart is composed rather than configured: the grid, each series, the
* axis and the crosshair are separate children, so a chart that wants no grid
* simply does not have one. A single component with twenty booleans is how
* charts end up unreadable at the call site.
*
* ```tsx
*
*
*
*
*
*
*
* ```
*
* Internally there are two layers, and the parts sort themselves into the
* right one: the geometry is SVG, and anything with text or a gesture on it is
* a React Native view laid over the top. That split is not a detail — SVG text
* ignores the platform's text scaling and the theme's font, and a gesture
* handler cannot be attached to an SVG node at all.
*
* Three things animate, each for a different reason:
*
* - **The reveal.** On mount the plot is uncovered left to right by an animated
* clip rectangle. Everything inside shares that clip, so the line, its fill
* and its markers arrive together rather than as three separate effects.
* - **The y-domain.** When the data changes the *scale* is tweened rather than
* the path swapped, so a series that grows is redrawn against a moving axis
* instead of jumping to a new shape. The reveal does not replay — it happened
* once, and repeating it on every refresh turns a data update into an
* animation.
* - **The crosshair.** A drag resolves the nearest index on the UI thread and
* moves the line and the dots from there. Only the index crosses back into
* JS, and only when it changes, so a drag costs a handful of re-renders
* rather than one per frame.
*
* Colours come from the `--color-chart-*` tokens, so a chart follows the active
* theme and is put on brand by overriding those five in the app's own
* global.css. Nothing here hardcodes a hex.
*/
import { type ReactNode } from 'react';
import { type ViewProps } from 'react-native';
import { type ChartAccessibilityProps } from '../../primitives/chart-accessibility.js';
/**
* Which layer a part belongs to. Read off the component itself, so composition
* stays a flat list of children instead of two nested slots the caller has to
* remember the order of.
*/
type Layer = 'svg' | 'series' | 'overlay' | 'header';
export type LineChartStatus = 'loading' | 'ready';
export type LineChartCurve = 'monotone' | 'linear';
export type LineChartDatum = Record;
/**
* The point under the crosshair, for something rendered *inside* the chart.
*
* A readout usually belongs in the card's header, which is outside this
* provider — use `onActiveIndexChange` for that. A hook cannot reach up out of
* the subtree it is called in, and pretending otherwise is how a component
* ends up with a context that has to wrap half the screen.
*/
export declare function useLineChart(): {
activeIndex: number;
activePoint: LineChartDatum | null;
xDataKey: string;
};
export interface LineChartProps extends ViewProps, ChartAccessibilityProps {
className?: string;
/** The rows. Each one is a point along the x-axis. */
data: LineChartDatum[];
/** Key holding the x label. Used by the axis and the crosshair readout. */
xDataKey?: string;
/**
* `loading` draws a flat skeleton with a sweep running along it, and morphs
* into the real series when it turns `ready`. One component throughout,
* rather than a spinner swapped for a chart — swapping loses the transition.
*/
status?: LineChartStatus;
/** Width ÷ height. `2` is the wide card shape; `1.6` suits a narrow column. */
aspectRatio?: number;
/** Milliseconds for the reveal on mount. */
animationDuration?: number;
/** Milliseconds for the y-axis to settle after the data changes. */
domainDuration?: number;
/** Fix the y-axis instead of deriving it from the data. */
yDomain?: [number, number];
/** `monotone` never overshoots between points; `linear` joins them straight. */
curve?: LineChartCurve;
/**
* The point under the crosshair as it moves, and `-1`/`null` when the finger
* lifts. This is how a readout in the card's header gets its value — that
* header is outside the chart, so it cannot use `useLineChart`.
*
* Fires when the index changes, not per frame.
*/
onActiveIndexChange?: (index: number, datum: LineChartDatum | null) => void;
/**
* Drop the axis padding so the line reaches the edges — for a sparkline with
* no grid, axis or crosshair, where the shape is the whole point.
*/
compact?: boolean;
children?: ReactNode;
}
/** Imperative handle: re-run the reveal on demand, for a "replay" control. */
export interface LineChartHandle {
replay: () => void;
}
export interface LineChartGridProps {
/** Horizontal rules across the plot. */
rows?: number;
color?: string;
/** Dash pattern, e.g. `"4,6"`. Omit for a solid rule. */
dashArray?: string;
opacity?: number;
}
/** Horizontal reference lines. Drawn under everything, outside the reveal clip. */
declare function LineChartGrid({ rows, color, dashArray, opacity }: LineChartGridProps): import("react").JSX.Element;
declare namespace LineChartGrid {
var displayName: string;
var layer: Layer;
}
export interface LineChartLineProps {
/** Key holding this series' y values. */
dataKey: string;
/**
* Stroke colour. Defaults to the `--color-chart-*` token at `colorIndex`, so
* a series follows the theme without the call site naming a colour.
*/
color?: string;
/** Which `--color-chart-*` token to take when `color` is not given. */
colorIndex?: 1 | 2 | 3 | 4 | 5;
strokeWidth?: number;
/** Dash pattern, e.g. `"6,4"` — for a projection or a secondary series. */
dashArray?: string;
/** A dot at every point. Best kept for short series. */
showMarkers?: boolean;
}
/** One series. */
declare function LineChartLine({ dataKey, color, colorIndex, strokeWidth, dashArray, showMarkers, }: LineChartLineProps): import("react").JSX.Element;
declare namespace LineChartLine {
var displayName: string;
var layer: Layer;
}
export interface LineChartAreaProps {
dataKey: string;
color?: string;
colorIndex?: 1 | 2 | 3 | 4 | 5;
/** Opacity at the line. Fades to nothing at the baseline. */
opacity?: number;
}
/**
* The fill under a series. A separate child from the line, because a chart with
* two series usually wants the fill on only one of them — two translucent
* fills over each other make a third colour that means nothing.
*/
declare function LineChartArea({ dataKey, color, colorIndex, opacity }: LineChartAreaProps): import("react").JSX.Element;
declare namespace LineChartArea {
var displayName: string;
var layer: Layer;
}
export interface LineChartSkeletonProps {
/** Milliseconds for one pass of the sweep. */
duration?: number;
color?: string;
}
/**
* The loading state: a flat rule where the series will be, with a highlight
* travelling along it. Drawn inside the same SVG rather than as an overlay, so
* arriving data is one tree changing rather than one view replacing another —
* which is what lets the flat line become the series instead of cutting to it.
*/
declare function LineChartSkeleton({ duration, color }: LineChartSkeletonProps): import("react").JSX.Element | null;
declare namespace LineChartSkeleton {
var displayName: string;
var layer: Layer;
}
export interface LineChartXAxisProps {
/** How many labels to show. The rest are dropped, evenly. */
ticks?: number;
/** Turn a row into its label. Defaults to the value at `xDataKey`. */
format?: (datum: LineChartDatum, index: number) => string;
className?: string;
}
/**
* The x labels. Real text rather than SVG text, so they follow the theme's font
* and the platform's text scaling — SVG text does neither.
*/
declare function LineChartXAxis({ ticks, format, className }: LineChartXAxisProps): import("react").JSX.Element;
declare namespace LineChartXAxis {
var displayName: string;
var layer: Layer;
}
export interface LineChartYAxisProps {
/** How many intervals to divide the axis into. Yields `ticks + 1` labels. */
ticks?: number;
/** Turn a value into its label. Defaults to a compact number. */
format?: (value: number) => string;
className?: string;
}
/**
* Value labels down the side, one per grid line.
*
* Give it the same `ticks` as the grid, or the numbers name lines that are not
* there. Four is the default on both for that reason.
*
* The labels are the domain the data settles at, not the tweening one — a
* number that counts up through every intermediate value while the axis
* animates is noise, and the axis is the part of the chart that is supposed to
* hold still enough to read.
*/
declare function LineChartYAxis({ ticks, format, className }: LineChartYAxisProps): import("react").JSX.Element;
declare namespace LineChartYAxis {
var displayName: string;
var layer: Layer;
var axis: "y";
}
export interface LineChartTooltipProps {
color?: string;
/**
* Float a small label at the crosshair showing the x-value and each series'
* value at that point — the minimal readout a drag wants. On by default.
*/
showLabel?: boolean;
/** Format one series' value for the label. Defaults to a compact number. */
formatValue?: (value: number, key: string) => string;
/** Format the label's heading from the row. Defaults to the value at xDataKey. */
formatX?: (datum: LineChartDatum) => string;
}
/**
* The crosshair, the gesture that drives it, and the label that rides it.
*
* They live in the view layer: a gesture handler cannot be attached to an SVG
* node, and once the gesture is a view the crosshair may as well be one too —
* a 1px view moved by `translateX` costs less than re-rendering an SVG line.
* The label follows on the UI thread the same way; only its *text* crosses back
* into JS, and only when the active index changes.
*
* The hit area is the whole plot. A crosshair you have to land on the line to
* summon is a crosshair nobody finds.
*/
declare function LineChartTooltip({ color, showLabel, formatValue, formatX }: LineChartTooltipProps): import("react").JSX.Element | null;
declare namespace LineChartTooltip {
var displayName: string;
var layer: Layer;
}
export interface LineChartLegendProps extends ViewProps {
className?: string;
/** Label per series key. A key with no label falls back to the key itself. */
labels?: Record;
}
/**
* A swatch and a name per registered series. Sits in the top-left of the plot
* by default — move it with `className`.
*/
declare function LineChartLegend({ className, labels, ...props }: LineChartLegendProps): import("react").JSX.Element | null;
declare namespace LineChartLegend {
var displayName: string;
var layer: Layer;
}
export interface LineChartHeaderProps extends ViewProps {
className?: string;
/** Small line above the value — what the chart is of. */
title?: string;
/** The readout. The largest thing on the card, and the first thing read. */
value?: string;
/** One muted line under the value — a period, a comparison, a total. */
caption?: string;
/** Prettier names for the series keys, as the legend takes. */
labels?: Record;
/**
* Draw a swatch and a name per series along the trailing edge. Prefer this to
* `LineChart.Legend` on a chart that has a header: the legend floats over the
* plot, where it competes with the lines for the same corner.
*/
legend?: boolean;
/** Trailing slot — a control, a badge, a range picker. Wins over `legend`. */
children?: ReactNode;
}
/**
* The strip above the plot: what the chart is of, what it currently reads, and
* what the colours mean.
*
* It belongs to the chart rather than to the card around it because it is about
* the *plot* — the number changes as a finger moves along the line, and the
* legend is the series list the chart itself is holding. The card's header is a
* caption on the tray the chart sits in; this is the chart introducing itself.
*
* The value is not derived here. A readout that follows the finger belongs to
* whoever owns the data — take it from `onActiveIndexChange` and pass the
* formatted string down, so one header can show a total when nothing is pressed
* and a point's value when something is.
*/
declare function LineChartHeader({ className, title, value, caption, labels, legend, children, ...props }: LineChartHeaderProps): import("react").JSX.Element;
declare namespace LineChartHeader {
var displayName: string;
var layer: Layer;
}
export declare const LineChart: import("react").ForwardRefExoticComponent> & {
Header: typeof LineChartHeader;
Grid: typeof LineChartGrid;
Area: typeof LineChartArea;
Line: typeof LineChartLine;
Skeleton: typeof LineChartSkeleton;
XAxis: typeof LineChartXAxis;
YAxis: typeof LineChartYAxis;
Tooltip: typeof LineChartTooltip;
Legend: typeof LineChartLegend;
};
export {};
//# sourceMappingURL=index.d.ts.map