/** * PieChart — one whole, divided between its parts. * * ```tsx * * * * * * ``` * * ## What it is, against the ring beside it * * A ring chart draws a value against *its own* target, so three rings can all * sit at ninety percent of three unrelated numbers and nothing has to add up. * A pie is the opposite claim: every slice is a share of one total, the angles * must come to a full turn, and a slice only means anything next to the others. * That is why nothing here takes a `maxValue` and why every value is normalised * against the sum — the sum *is* the subject. * * It follows that a pie is the wrong shape for a great many things. Two numbers * that do not belong to one whole, a series over time, anything a reader has to * compare precisely: all of those are a bar chart, because an angle is the * hardest quantity to read off a page and the fifth-largest slice of eleven is * not a fact anybody is going to extract. Use it for a handful of parts of one * obvious total, and put the number in the middle. * * ## Drawing * * Each slice is a filled path rather than a stroked arc, because a slice is a * *region* — two arcs and two radial edges — and a stroke is a band of even * thickness with no ends of its own. `wedgePath` builds it, and rebuilds it on * the UI thread on every frame of the reveal. * * That is what makes the reveal an unroll rather than a fade: one angle sweeps * clockwise from the start and each slice is drawn only as far as it has got * to. The pie fills the way it would be drawn by hand, and the slices arrive in * the order they are listed rather than all at once. * * Touch, not hover: a slice 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'; /** Whether the chart is showing data or waiting for it. */ export type PieChartStatus = 'loading' | 'ready'; /** One slice. Its share is worked out from the others, so there is no maximum. */ export interface PieDatum { /** Name for the legend, the centre readout and the accessibility label. */ label: string; /** How much of the whole this slice is. Negatives are treated as zero. */ value: number; /** Explicit colour, overriding the `--color-chart-*` token. */ color?: string; } /** The selected slice and its share, for something rendered inside the chart. */ export declare function usePieChart(): { activeIndex: number; activeSlice: PieDatum | null; /** The selected slice's share of the whole, 0 to 1. */ activeFraction: number; }; export interface PieChartProps extends ViewProps { className?: string; /** One entry per slice, in the order they are drawn clockwise. */ data: PieDatum[]; /** Fixed diameter in points. Measured from the container when omitted. */ size?: number; /** * The hole, as a share of the radius. `0` is a pie; anything above it is a * donut, and `0.55`–`0.65` is the range that leaves room for a readout in the * middle without the band getting thin enough to be hard to hit. * * Given as a share rather than in points so a chart keeps its proportions at * whatever size it is measured at. */ innerRadius?: number; /** Where the first slice begins, in degrees clockwise from twelve o'clock. */ startAngle?: number; /** * Where the last one ends, on the same clock. Leaving a turn's worth between * the two gives a closed pie; anything less leaves a gap and reads as a dial. */ endAngle?: number; /** Gap between one slice and the next, in degrees. */ padAngle?: number; /** * The smallest angle any non-zero slice is drawn at, in degrees. * * A slice worth a fifth of a percent is a hairline nobody can see and nobody * can press, so it reads as missing rather than as small — and "missing" is a * different claim from "nearly none". The angle it borrows comes off the * others in proportion, so the turn still closes. */ minAngle?: number; /** Milliseconds for the pie to unroll. */ animationDuration?: number; /** `loading` draws a plain muted ring until the data arrives. */ status?: PieChartStatus; /** Selected slice. Leave unset to let the chart track it. */ activeIndex?: number; /** Fires with the selected slice, or `-1` when the selection is cleared. */ onActiveIndexChange?: (index: number) => void; children?: ReactNode; } /** Imperative handle: re-run the unroll, for a "replay" control. */ export interface PieChartHandle { replay: () => void; } export interface PieChartSlicesProps { /** Rounds the four turns of each slice, in points. */ cornerRadius?: number; /** How far a selected slice lifts out of the pie, in points. */ popOut?: number; /** Opacity of the slices that are not selected, once one is. */ dimOpacity?: number; } /** * Every slice, drawn in the order the data lists them. * * One part rather than one per datum, unlike the rings next door. A ring is * configured on its own — its own thickness, its own cap, its own segment count * — because it is its own measurement. Slices of a pie are not: they share a * radius, a hole and a dial by definition, and a chart where one of them could * be given a different radius would be a chart drawing a lie. */ declare function PieChartSlices({ cornerRadius, popOut, dimOpacity, }: PieChartSlicesProps): import("react").JSX.Element | null; declare namespace PieChartSlices { var displayName: string; var slot: "svg"; } export interface PieChartSkeletonProps { color?: string; } /** * The loading state: the dial as one plain band, with nothing divided up yet. * * Deliberately undivided. Placeholder slices would be a made-up split, and a * reader has no way to tell an invented one from a real one until it changes * under them — which is worse than showing nothing, because it is showing * something wrong. */ declare function PieChartSkeleton({ color }: PieChartSkeletonProps): import("react").JSX.Element | null; declare namespace PieChartSkeleton { var displayName: string; var slot: "svg"; } export interface PieChartCenterProps { /** Heading shown when no slice is selected. */ defaultLabel?: string; /** Format the number under the label. Defaults to a compact number. */ formatValue?: (value: number, slice: PieDatum | null) => string; /** * Draw the middle yourself. Given the selected slice, or `null` when nothing * is selected. */ children?: (slice: PieDatum | null) => ReactNode; className?: string; } /** * The hole's readout: the total, and the selected slice's own figures once one * is picked. * * Unlike the ring chart's centre, the default here *is* an aggregate, and it is * the honest one — the whole point of a pie is that its parts belong to a total, * so the total is the number the chart is about. Selecting a slice swaps it for * that slice's value and its share. */ declare function PieChartCenter({ defaultLabel, formatValue, children, className, }: PieChartCenterProps): import("react").JSX.Element | null; declare namespace PieChartCenter { var displayName: string; var slot: "overlay"; } export interface PieChartLegendProps extends ViewProps { className?: string; /** Show each slice's share of the whole beside its name. */ showValue?: boolean; } /** * A swatch, a name and a share per slice, under the chart and across the width * of it. Pressable in the same way the slices are — the legend is usually the * easier target of the two, and a slice worth a couple of percent is not a * target at all. * * It wraps rather than stacking, so five or six entries take two lines instead * of six. A key is a lookup table, and a lookup table read down a column of one * word each is a column the eye has to walk. */ declare function PieChartLegend({ className, showValue, ...props }: PieChartLegendProps): import("react").JSX.Element | null; declare namespace PieChartLegend { var displayName: string; var slot: "footer"; } export interface PieChartHeaderProps 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 caveat. */ caption?: string; /** Prettier names for the slices, keyed by their `label`. */ labels?: Record; /** * Draw a swatch and a name per slice along the trailing edge. * * For two or three short names. Past that use `PieChart.Legend`, which runs * under the chart across the full width: a key of five long names crammed * into the trailing corner of a header wraps to a column and leaves the title * beside it a few points wide. */ legend?: boolean; /** Trailing slot — a control, a badge, a range picker. Wins over `legend`. */ children?: ReactNode; } /** * The strip above the pie: what the chart is of, what it reads, and what the * colours mean. * * It belongs to the chart rather than to the card around it because it is about * the *slices* — 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 even though there is a total to derive it from, * because the formatting is not the chart's to guess: a total of 18420 is a * count, a currency or a percentage depending on what was counted, and only the * caller knows which. */ declare function PieChartHeader({ className, title, value, caption, labels, legend, children, ...props }: PieChartHeaderProps): import("react").JSX.Element; declare namespace PieChartHeader { var displayName: string; var slot: "header"; } export declare const PieChart: import("react").ForwardRefExoticComponent> & { Header: typeof PieChartHeader; Slices: typeof PieChartSlices; Center: typeof PieChartCenter; Legend: typeof PieChartLegend; Skeleton: typeof PieChartSkeleton; }; export {}; //# sourceMappingURL=index.d.ts.map