/** * LiveLineChart — a reading that keeps arriving, against a window that keeps * moving. * * ```tsx * * * * * * * * ``` * * ## What it is, against the line chart beside it * * `LineChart` places a point by its position in the list, which is right for a * series of twelve months whatever the gaps between the dates behind them. Here * a point is placed at the time it carries, against a domain that runs from * `window` seconds ago to now — so the gaps are the subject, and a reading that * arrived late sits where it arrived rather than one slot along. * * ## The clock, and what it costs * * This is the only thing in the library that animates without an interaction or * a change of data. The window is tied to the wall clock, so the line drifts * left whether or not anything is arriving, and a feed that stalls shows as a * flat run reaching back from the tip rather than as a chart that has frozen. * Those two look identical if the window only moves when a point lands, and * they mean opposite things. * * The cost is a frame callback for as long as the chart is mounted. It is * stopped by `paused`, by `status="loading"`, while the app is backgrounded * and on unmount, and it is never started when the platform asks for reduced * motion — in that case the window advances as each point arrives instead, * which is the same picture sampled less often. * * Screen readers receive one image-role snapshot: its name, current or * selected value, direction, time window and paused state. It changes when the * React data changes, never on the UI-thread clock frame, and requests no live * announcement. The visual axes, badges and tooltip repeat that snapshot and * stay out of the accessibility tree; controls placed in Header remain normal * controls. * * ## Colour follows the recent direction * * With `momentumColors` set, the line, the fill and the tip take their colour * from where the reading has been going rather than from a fixed hue. It is the * one thing on the chart readable without looking at the axis, which is what a * number being watched out of the corner of an eye needs. */ import { type ReactNode } from 'react'; import { type ViewProps } from 'react-native'; import { type ChartCurve } from '../../utils/chart.js'; /** Which layer a part belongs to. Read off the component itself. */ type Layer = 'svg' | 'overlay' | 'header'; /** Whether the chart is showing data or waiting for it. */ export type LiveLineChartStatus = 'loading' | 'ready'; /** Where the reading has been going, over the last few points. */ export type LiveLineMomentum = 'up' | 'down' | 'flat'; /** A colour per direction, for a chart that is read by its colour. */ export interface LiveLineMomentumColors { up?: string; down?: string; flat?: string; } /** One reading. `time` is a timestamp in milliseconds, as `Date.now()` gives. */ export interface LiveLinePoint { time: number; value: number; } /** The reading under the crosshair, for something rendered inside the chart. */ export declare function useLiveLineChart(): { activePoint: LiveLinePoint | null; latest: LiveLinePoint | null; momentum: LiveLineMomentum; color: string; }; export interface LiveLineChartProps extends ViewProps { className?: string; /** * Names the chart's single screen-reader snapshot. Falls back to the Header * title, then to "Live line chart". */ accessibilityLabel?: string; /** Additional guidance after the snapshot. No gesture is invented for it. */ accessibilityHint?: string; /** The readings so far. Invalid values are dropped and timestamps are ordered. */ data: LiveLinePoint[]; /** How much time the plot spans, in seconds. Invalid values use 30. */ window?: number; /** Freeze the window where it is. The readings still arrive; the clock stops. */ paused?: boolean; /** Fix the y-axis instead of deriving it from what is visible. */ yDomain?: [number, number]; /** Milliseconds for the y-axis to settle after the range changes. */ domainDuration?: number; /** `monotone` never overshoots between readings; `linear` joins them straight. */ curve?: ChartCurve; /** * The most readings kept. Older ones are dropped, since they are off the * window and cannot come back — an unbounded feed otherwise grows an array * for as long as the screen is open. Must be positive and finite. */ maxPoints?: number; /** Width ÷ height of the plot. */ aspectRatio?: number; /** `loading` draws a flat placeholder and holds the clock. */ status?: LiveLineChartStatus; /** Colour per direction. Left out, the chart draws in one hue throughout. */ momentumColors?: LiveLineMomentumColors; /** Overrides the `--color-chart-1` token. Ignored when `momentumColors` is set. */ color?: string; /** The reading under the crosshair as it moves, and `null` when the finger lifts. */ onActivePointChange?: (point: LiveLinePoint | null) => void; children?: ReactNode; } export interface LiveLineChartHandle { /** Jump the window to the current moment — after a pause, or a background. */ sync: () => void; } export interface LiveLineChartGridProps { /** How many bands the plot is divided into. */ rows?: number; color?: string; dashArray?: string; } /** The horizontal rules the readings are judged against. */ declare function LiveLineChartGrid({ rows, color, dashArray }: LiveLineChartGridProps): import("react").JSX.Element; declare namespace LiveLineChartGrid { var displayName: string; var layer: Layer; } export interface LiveLineChartLineProps { strokeWidth?: number; /** Overrides the chart's colour, momentum included. */ color?: string; } /** The line itself, rebuilt on the UI thread every frame the window moves. */ declare function LiveLineChartLine({ strokeWidth, color }: LiveLineChartLineProps): import("react").JSX.Element | null; declare namespace LiveLineChartLine { var displayName: string; var layer: Layer; } export interface LiveLineChartAreaProps { /** Opacity at the top of the fill, fading to nothing at the baseline. */ opacity?: number; /** Overrides the chart's colour, momentum included. */ color?: string; } /** * The fill under the line. * * Its own part rather than a flag on the line, so a chart that wants the shape * without the weight of a filled band simply does not have one. */ declare function LiveLineChartArea({ opacity, color }: LiveLineChartAreaProps): import("react").JSX.Element | null; declare namespace LiveLineChartArea { var displayName: string; var layer: Layer; } export interface LiveLineChartTipProps { /** * Show the current reading in a badge beside the dot. * * Off by default. The badge is a floating card, which is the shape a reader * has learnt means "you touched something" — sitting there unasked it reads * as a tooltip nobody opened. Turn it on where the chart has no header to put * the reading in, and it becomes the only place the number is written. */ badge?: boolean; /** Ring the dot with a repeating pulse. */ pulse?: boolean; /** Format the badge. Defaults to a compact number. */ formatValue?: (value: number) => string; className?: string; } /** * The dot at the leading end, and what it currently reads. * * It rides the newest reading rather than the right-hand edge, so a feed that * stops is a dot drifting left with the rest of the line. Pinning it to the * edge would hold it still and steady, which is the picture of a feed that is * working. * * A view rather than an SVG node: it carries text and a pulse, and SVG text * ignores the platform's text scaling and the theme's font. */ declare function LiveLineChartTip({ badge, pulse, formatValue, className, }: LiveLineChartTipProps): import("react").JSX.Element | null; declare namespace LiveLineChartTip { var displayName: string; var layer: Layer; } export interface LiveLineChartXAxisProps { /** How many labels along the bottom. */ ticks?: number; /** Rewrites a label. Given how many seconds back the tick is. */ formatTick?: (secondsAgo: number) => string; className?: string; } /** * How far back the plot reaches, labelled along the bottom. * * The labels are offsets from now — `-30s`, `-15s`, `now` — rather than clock * times, and they never change. A moving window labelled with wall-clock times * would rewrite every one of them on every frame, which is a row of digits * churning under a chart that is trying to be read. */ declare function LiveLineChartXAxis({ ticks, formatTick, className }: LiveLineChartXAxisProps): import("react").JSX.Element | null; declare namespace LiveLineChartXAxis { var displayName: string; var layer: Layer; } export interface LiveLineChartYAxisProps { /** How many labels up the side. */ ticks?: number; /** Format a value. Defaults to a compact number. */ formatValue?: (value: number) => string; className?: string; } /** * The scale up the left-hand side. * * Declaring one widens the left gutter, which the root reads off the children * before anything is laid out — an axis given no room is drawn over the line, * which loses both the numbers and the shape they were there to explain. * * The labels follow the domain the tween is heading for rather than the tween * itself. A number re-rendered on every frame of a settle is thirty renders * landing on the string it started on. */ declare function LiveLineChartYAxis({ ticks, formatValue, className }: LiveLineChartYAxisProps): import("react").JSX.Element | null; declare namespace LiveLineChartYAxis { var displayName: string; var layer: Layer; var axis: "y"; } export interface LiveLineChartTooltipProps { /** Format the value. Defaults to a compact number. */ formatValue?: (value: number) => string; className?: string; } /** * Drag back through the window to read a reading that has already gone past. * * The crosshair is pinned to the *moment* it was put on rather than to the * place on screen, so it travels left with the reading it named instead of * sitting still while the line slides out from under it. */ declare function LiveLineChartTooltip({ formatValue, className }: LiveLineChartTooltipProps): import("react").JSX.Element | null; declare namespace LiveLineChartTooltip { var displayName: string; var layer: Layer; } export interface LiveLineChartSkeletonProps { color?: string; } /** * The waiting state: a flat line down the middle of the plot. * * The shape the real line grows out of once readings arrive, rather than a * placeholder series — an invented run of readings is indistinguishable from a * real one until it changes under the reader. */ declare function LiveLineChartSkeleton({ color }: LiveLineChartSkeletonProps): import("react").JSX.Element | null; declare namespace LiveLineChartSkeleton { var displayName: string; var layer: Layer; } export interface LiveLineChartHeaderProps extends ViewProps { className?: string; /** Small line above the value — what is being watched. */ title?: string; /** The readout. Left out, it shows the current reading. */ value?: string; /** One muted line under the value. */ caption?: string; /** Format the derived value. Defaults to a compact number. */ formatValue?: (value: number) => string; /** Trailing slot — a pause control, a badge, a unit. */ children?: ReactNode; } /** * The strip above the plot: what is being watched and what it currently reads. * * The value falls back to the reading under the crosshair, then to the latest * one, so a drag back through the window reads out here without the caller * wiring anything up. */ declare function LiveLineChartHeader({ className, title, value, caption, formatValue, children, ...props }: LiveLineChartHeaderProps): import("react").JSX.Element; declare namespace LiveLineChartHeader { var displayName: string; var layer: Layer; } export declare const LiveLineChart: import("react").ForwardRefExoticComponent> & { Header: typeof LiveLineChartHeader; Grid: typeof LiveLineChartGrid; Area: typeof LiveLineChartArea; Line: typeof LiveLineChartLine; Tip: typeof LiveLineChartTip; XAxis: typeof LiveLineChartXAxis; YAxis: typeof LiveLineChartYAxis; Tooltip: typeof LiveLineChartTooltip; Skeleton: typeof LiveLineChartSkeleton; }; export {}; //# sourceMappingURL=index.d.ts.map