/** * RingChart — progress towards several targets, as concentric arcs. * * ```tsx * * * * * * * ``` * * ## What it is not * * It is not a pie or a donut, and the difference matters. A pie divides one * whole between its slices, so its parts are only meaningful against each * other and the angles must add to a full turn. A ring here is a value against * *its own* target — three rings can all be at ninety percent of three * unrelated numbers, and that is the reading. Nothing is normalised across * rings, and nothing has to add up. * * That is also why each ring gets a track. An arc drawn on nothing shows how * far something went; an arc drawn on a full circle shows how far it went *of * what it was aiming at*, which is the entire question. * * ## Drawing * * Each ring is two arcs — a track and the progress over it — with only the * progress animated, through `strokeDasharray`. Sweeping the arc by rebuilding * its path would work, but a dash offset is two numbers moving on an unchanged * path, and it keeps the rounded cap pinned to the moving end for free. * * The same dash pattern is what makes the other two shapes possible without any * more geometry. An open gauge is the pattern cut short of the circumference * and the whole circle turned to put the gap where it is wanted; a segmented * ring is the pattern repeated, one pair per tick. Both stay one `Circle`. * * Touch, not hover: a ring is selected by pressing it, and pressing the same * one again clears the selection. There is no equivalent of a pointer resting * somewhere without committing, so a chart that only revealed its numbers on * hover would never reveal them at all. */ import { type ReactNode } from 'react'; import { type ViewProps } from 'react-native'; import { type SeriesColorIndex } from '../../utils/chart.js'; /** One ring per datum, and the datum is the whole of its contract. */ export interface RingDatum { /** Name for the legend and the centre readout. */ label: string; /** Where this ring has got to. */ value: number; /** What it is aiming at. The ring is full when `value` reaches it. */ maxValue: number; /** Explicit colour, overriding the `--color-chart-*` token. */ color?: string; } /** The selected ring, for something rendered inside the chart. */ export declare function useRingChart(): { activeIndex: number; activeRing: RingDatum | null; }; export interface RingChartProps extends ViewProps { className?: string; /** One entry per ring, outermost first. */ data: RingDatum[]; /** Fixed diameter in points. Measured from the container when omitted. */ size?: number; /** Thickness of each ring. */ strokeWidth?: number; /** Gap between one ring and the next. */ ringGap?: number; /** * Where the arcs begin, in degrees clockwise from twelve o'clock. `0` is the * top, `90` the right-hand side. */ startAngle?: number; /** * Where they end, on the same clock. Leaving a turn's worth between the two * gives a closed ring; anything less leaves a gap and reads as a gauge — * `startAngle={-90} endAngle={90}` is the half circle over the top. */ endAngle?: number; /** Milliseconds for the arcs to sweep in. */ animationDuration?: number; /** Selected ring. Leave unset to let the chart track it. */ activeIndex?: number; /** Fires with the selected ring, or `-1` when the selection is cleared. */ onActiveIndexChange?: (index: number) => void; children?: ReactNode; } /** Imperative handle: re-run the sweep, for a "replay" control. */ export interface RingChartHandle { replay: () => void; } export interface RingChartRingProps { /** Which entry in `data` this ring draws. */ index: number; /** Explicit colour, overriding the datum's and the token. */ color?: string; /** Which of the five chart tokens to take, when the datum names no colour. */ colorIndex?: SeriesColorIndex; /** * Rounded ends, or square ones. Defaults to round, and to square when the * ring is segmented — a rounded cap on a tick as long as it is wide draws a * lozenge rather than a tick. */ lineCap?: 'round' | 'butt'; /** Opacity of the track behind the arc. */ trackOpacity?: number; /** * Break the ring into this many ticks, lit one at a time as the value * climbs. For a target made of countable things — eight of twelve sessions * reads off ticks you can count, and off a smooth arc only as "about two * thirds". */ segments?: number; /** Gap between one tick and the next, in points. */ segmentGap?: number; } /** * One ring: a full-circle track, and the arc showing how far along it the * value has got. * * The arc is swept with `strokeDasharray` rather than by rebuilding its path. * Both work, but a dash offset moves two numbers on a path that never changes * — and it keeps the rounded cap pinned to the moving end without any extra * geometry. */ declare function RingChartRing({ index, color, colorIndex, lineCap, trackOpacity, segments, segmentGap, }: RingChartRingProps): import("react").JSX.Element | null; declare namespace RingChartRing { var displayName: string; var slot: "ring"; } export interface RingChartCenterProps { /** * Heading shown when no ring is selected. Defaults to the outermost ring's * own name, which is what the centre shows when nothing has been picked. */ defaultLabel?: string; /** Format the number under the label. Defaults to a compact number. */ formatValue?: (value: number, ring: RingDatum | null) => string; /** * Draw the middle yourself. Given the selected ring, or `null` when nothing * is selected. */ children?: (ring: RingDatum | null) => ReactNode; className?: string; } /** * The readout in the hole. * * With nothing selected it shows the outermost ring — the one the eye lands on * first. Not a total: the rings measure different things against different * targets, so their values do not add up and their percentages do not average, * and a total here would be a confident number about nothing. Selecting a ring * swaps it for that ring's own figures. */ declare function RingChartCenter({ defaultLabel, formatValue, children, className, }: RingChartCenterProps): import("react").JSX.Element; declare namespace RingChartCenter { var displayName: string; var slot: "overlay"; } export interface RingChartLegendProps extends ViewProps { className?: string; /** Show each ring's percentage of its own target beside its name. */ showValue?: boolean; } /** * A swatch and a name per ring, pressable in the same way the rings are — the * legend is usually the easier target of the two, and on a small chart it is * the only comfortable one. */ declare function RingChartLegend({ className, showValue, ...props }: RingChartLegendProps): import("react").JSX.Element | null; declare namespace RingChartLegend { var displayName: string; var slot: "overlay"; } export interface RingChartHeaderProps 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 target. */ caption?: string; /** Prettier names for the rings, keyed by their `label`. */ labels?: Record; /** * Draw a swatch and a name per ring along the trailing edge. Prefer this to * `RingChart.Legend` on a chart that has a header: that legend hangs off the * bottom of the square, where it overlaps whatever is under the chart. */ legend?: boolean; /** Trailing slot — a control, a badge, a range picker. Wins over `legend`. */ children?: ReactNode; } /** * The strip above the rings: 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 *rings* — the number changes as one is selected, and the legend is the * 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. There is no total to derive: the rings measure * different things against different targets. Take it from `onActiveIndexChange` * and pass the formatted string down, so one header can show the headline figure * when nothing is selected and a ring's own when something is. */ declare function RingChartHeader({ className, title, value, caption, labels, legend, children, ...props }: RingChartHeaderProps): import("react").JSX.Element; declare namespace RingChartHeader { var displayName: string; var slot: "header"; } export declare const RingChart: import("react").ForwardRefExoticComponent> & { Header: typeof RingChartHeader; Ring: typeof RingChartRing; Center: typeof RingChartCenter; Legend: typeof RingChartLegend; }; export {}; //# sourceMappingURL=index.d.ts.map