panelui-native 0.43.0 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/lib/module/components/card/index.js +8 -154
- package/lib/module/components/card/index.js.map +1 -1
- package/lib/module/components/combobox/index.js +7 -1
- package/lib/module/components/combobox/index.js.map +1 -1
- package/lib/module/components/date-time-picker/index.js +254 -0
- package/lib/module/components/date-time-picker/index.js.map +1 -0
- package/lib/module/components/grid-item/index.js +486 -0
- package/lib/module/components/grid-item/index.js.map +1 -0
- package/lib/module/components/{kpi-chart → kpi}/index.js +62 -62
- package/lib/module/components/kpi/index.js.map +1 -0
- package/lib/module/components/line-chart/index.js +92 -10
- package/lib/module/components/line-chart/index.js.map +1 -1
- package/lib/module/components/pie-chart/index.js +625 -0
- package/lib/module/components/pie-chart/index.js.map +1 -0
- package/lib/module/components/scatter-chart/index.js +1173 -0
- package/lib/module/components/scatter-chart/index.js.map +1 -0
- package/lib/module/components/tabs/index.js +275 -33
- package/lib/module/components/tabs/index.js.map +1 -1
- package/lib/module/index.js +5 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/chart.js +81 -0
- package/lib/module/utils/chart.js.map +1 -1
- package/lib/typescript/src/components/card/index.d.ts +0 -20
- package/lib/typescript/src/components/card/index.d.ts.map +1 -1
- package/lib/typescript/src/components/combobox/index.d.ts.map +1 -1
- package/lib/typescript/src/components/date-time-picker/index.d.ts +121 -0
- package/lib/typescript/src/components/date-time-picker/index.d.ts.map +1 -0
- package/lib/typescript/src/components/grid-item/index.d.ts +292 -0
- package/lib/typescript/src/components/grid-item/index.d.ts.map +1 -0
- package/lib/typescript/src/components/{kpi-chart → kpi}/index.d.ts +65 -65
- package/lib/typescript/src/components/kpi/index.d.ts.map +1 -0
- package/lib/typescript/src/components/line-chart/index.d.ts +25 -1
- package/lib/typescript/src/components/line-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/pie-chart/index.d.ts +245 -0
- package/lib/typescript/src/components/pie-chart/index.d.ts.map +1 -0
- package/lib/typescript/src/components/scatter-chart/index.d.ts +309 -0
- package/lib/typescript/src/components/scatter-chart/index.d.ts.map +1 -0
- package/lib/typescript/src/components/tabs/index.d.ts +20 -2
- package/lib/typescript/src/components/tabs/index.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +7 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/chart.d.ts +34 -0
- package/lib/typescript/src/utils/chart.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/card/index.tsx +7 -209
- package/src/components/combobox/index.tsx +7 -1
- package/src/components/date-time-picker/index.tsx +375 -0
- package/src/components/grid-item/index.tsx +515 -0
- package/src/components/{kpi-chart → kpi}/index.tsx +85 -85
- package/src/components/line-chart/index.tsx +98 -8
- package/src/components/pie-chart/index.tsx +863 -0
- package/src/components/scatter-chart/index.tsx +1401 -0
- package/src/components/tabs/index.tsx +305 -35
- package/src/index.ts +66 -18
- package/src/utils/chart.ts +110 -0
- package/lib/module/components/kpi-chart/index.js.map +0 -1
- package/lib/typescript/src/components/kpi-chart/index.d.ts.map +0 -1
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PieChart — one whole, divided between its parts.
|
|
3
|
+
*
|
|
4
|
+
* ```tsx
|
|
5
|
+
* <PieChart data={spend} innerRadius={0.58}>
|
|
6
|
+
* <PieChart.Header title="This month" value="$18,420" legend />
|
|
7
|
+
* <PieChart.Slices />
|
|
8
|
+
* <PieChart.Center />
|
|
9
|
+
* </PieChart>
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* ## What it is, against the ring beside it
|
|
13
|
+
*
|
|
14
|
+
* A ring chart draws a value against *its own* target, so three rings can all
|
|
15
|
+
* sit at ninety percent of three unrelated numbers and nothing has to add up.
|
|
16
|
+
* A pie is the opposite claim: every slice is a share of one total, the angles
|
|
17
|
+
* must come to a full turn, and a slice only means anything next to the others.
|
|
18
|
+
* That is why nothing here takes a `maxValue` and why every value is normalised
|
|
19
|
+
* against the sum — the sum *is* the subject.
|
|
20
|
+
*
|
|
21
|
+
* It follows that a pie is the wrong shape for a great many things. Two numbers
|
|
22
|
+
* that do not belong to one whole, a series over time, anything a reader has to
|
|
23
|
+
* compare precisely: all of those are a bar chart, because an angle is the
|
|
24
|
+
* hardest quantity to read off a page and the fifth-largest slice of eleven is
|
|
25
|
+
* not a fact anybody is going to extract. Use it for a handful of parts of one
|
|
26
|
+
* obvious total, and put the number in the middle.
|
|
27
|
+
*
|
|
28
|
+
* ## Drawing
|
|
29
|
+
*
|
|
30
|
+
* Each slice is a filled path rather than a stroked arc, because a slice is a
|
|
31
|
+
* *region* — two arcs and two radial edges — and a stroke is a band of even
|
|
32
|
+
* thickness with no ends of its own. `wedgePath` builds it, and rebuilds it on
|
|
33
|
+
* the UI thread on every frame of the reveal.
|
|
34
|
+
*
|
|
35
|
+
* That is what makes the reveal an unroll rather than a fade: one angle sweeps
|
|
36
|
+
* clockwise from the start and each slice is drawn only as far as it has got
|
|
37
|
+
* to. The pie fills the way it would be drawn by hand, and the slices arrive in
|
|
38
|
+
* the order they are listed rather than all at once.
|
|
39
|
+
*
|
|
40
|
+
* Touch, not hover: a slice is selected by pressing it, and pressing the same
|
|
41
|
+
* one again clears the selection. There is no equivalent of a pointer resting
|
|
42
|
+
* somewhere without committing, so a chart that only revealed its numbers on
|
|
43
|
+
* hover would never reveal them at all.
|
|
44
|
+
*/
|
|
45
|
+
import { type ReactNode } from 'react';
|
|
46
|
+
import { type ViewProps } from 'react-native';
|
|
47
|
+
/** Whether the chart is showing data or waiting for it. */
|
|
48
|
+
export type PieChartStatus = 'loading' | 'ready';
|
|
49
|
+
/** One slice. Its share is worked out from the others, so there is no maximum. */
|
|
50
|
+
export interface PieDatum {
|
|
51
|
+
/** Name for the legend, the centre readout and the accessibility label. */
|
|
52
|
+
label: string;
|
|
53
|
+
/** How much of the whole this slice is. Negatives are treated as zero. */
|
|
54
|
+
value: number;
|
|
55
|
+
/** Explicit colour, overriding the `--color-chart-*` token. */
|
|
56
|
+
color?: string;
|
|
57
|
+
}
|
|
58
|
+
/** The selected slice and its share, for something rendered inside the chart. */
|
|
59
|
+
export declare function usePieChart(): {
|
|
60
|
+
activeIndex: number;
|
|
61
|
+
activeSlice: PieDatum | null;
|
|
62
|
+
/** The selected slice's share of the whole, 0 to 1. */
|
|
63
|
+
activeFraction: number;
|
|
64
|
+
};
|
|
65
|
+
export interface PieChartProps extends ViewProps {
|
|
66
|
+
className?: string;
|
|
67
|
+
/** One entry per slice, in the order they are drawn clockwise. */
|
|
68
|
+
data: PieDatum[];
|
|
69
|
+
/** Fixed diameter in points. Measured from the container when omitted. */
|
|
70
|
+
size?: number;
|
|
71
|
+
/**
|
|
72
|
+
* The hole, as a share of the radius. `0` is a pie; anything above it is a
|
|
73
|
+
* donut, and `0.55`–`0.65` is the range that leaves room for a readout in the
|
|
74
|
+
* middle without the band getting thin enough to be hard to hit.
|
|
75
|
+
*
|
|
76
|
+
* Given as a share rather than in points so a chart keeps its proportions at
|
|
77
|
+
* whatever size it is measured at.
|
|
78
|
+
*/
|
|
79
|
+
innerRadius?: number;
|
|
80
|
+
/** Where the first slice begins, in degrees clockwise from twelve o'clock. */
|
|
81
|
+
startAngle?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Where the last one ends, on the same clock. Leaving a turn's worth between
|
|
84
|
+
* the two gives a closed pie; anything less leaves a gap and reads as a dial.
|
|
85
|
+
*/
|
|
86
|
+
endAngle?: number;
|
|
87
|
+
/** Gap between one slice and the next, in degrees. */
|
|
88
|
+
padAngle?: number;
|
|
89
|
+
/**
|
|
90
|
+
* The smallest angle any non-zero slice is drawn at, in degrees.
|
|
91
|
+
*
|
|
92
|
+
* A slice worth a fifth of a percent is a hairline nobody can see and nobody
|
|
93
|
+
* can press, so it reads as missing rather than as small — and "missing" is a
|
|
94
|
+
* different claim from "nearly none". The angle it borrows comes off the
|
|
95
|
+
* others in proportion, so the turn still closes.
|
|
96
|
+
*/
|
|
97
|
+
minAngle?: number;
|
|
98
|
+
/** Milliseconds for the pie to unroll. */
|
|
99
|
+
animationDuration?: number;
|
|
100
|
+
/** `loading` draws a plain muted ring until the data arrives. */
|
|
101
|
+
status?: PieChartStatus;
|
|
102
|
+
/** Selected slice. Leave unset to let the chart track it. */
|
|
103
|
+
activeIndex?: number;
|
|
104
|
+
/** Fires with the selected slice, or `-1` when the selection is cleared. */
|
|
105
|
+
onActiveIndexChange?: (index: number) => void;
|
|
106
|
+
children?: ReactNode;
|
|
107
|
+
}
|
|
108
|
+
/** Imperative handle: re-run the unroll, for a "replay" control. */
|
|
109
|
+
export interface PieChartHandle {
|
|
110
|
+
replay: () => void;
|
|
111
|
+
}
|
|
112
|
+
export interface PieChartSlicesProps {
|
|
113
|
+
/** Rounds the four turns of each slice, in points. */
|
|
114
|
+
cornerRadius?: number;
|
|
115
|
+
/** How far a selected slice lifts out of the pie, in points. */
|
|
116
|
+
popOut?: number;
|
|
117
|
+
/** Opacity of the slices that are not selected, once one is. */
|
|
118
|
+
dimOpacity?: number;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Every slice, drawn in the order the data lists them.
|
|
122
|
+
*
|
|
123
|
+
* One part rather than one per datum, unlike the rings next door. A ring is
|
|
124
|
+
* configured on its own — its own thickness, its own cap, its own segment count
|
|
125
|
+
* — because it is its own measurement. Slices of a pie are not: they share a
|
|
126
|
+
* radius, a hole and a dial by definition, and a chart where one of them could
|
|
127
|
+
* be given a different radius would be a chart drawing a lie.
|
|
128
|
+
*/
|
|
129
|
+
declare function PieChartSlices({ cornerRadius, popOut, dimOpacity, }: PieChartSlicesProps): import("react").JSX.Element | null;
|
|
130
|
+
declare namespace PieChartSlices {
|
|
131
|
+
var displayName: string;
|
|
132
|
+
var slot: "svg";
|
|
133
|
+
}
|
|
134
|
+
export interface PieChartSkeletonProps {
|
|
135
|
+
color?: string;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* The loading state: the dial as one plain band, with nothing divided up yet.
|
|
139
|
+
*
|
|
140
|
+
* Deliberately undivided. Placeholder slices would be a made-up split, and a
|
|
141
|
+
* reader has no way to tell an invented one from a real one until it changes
|
|
142
|
+
* under them — which is worse than showing nothing, because it is showing
|
|
143
|
+
* something wrong.
|
|
144
|
+
*/
|
|
145
|
+
declare function PieChartSkeleton({ color }: PieChartSkeletonProps): import("react").JSX.Element | null;
|
|
146
|
+
declare namespace PieChartSkeleton {
|
|
147
|
+
var displayName: string;
|
|
148
|
+
var slot: "svg";
|
|
149
|
+
}
|
|
150
|
+
export interface PieChartCenterProps {
|
|
151
|
+
/** Heading shown when no slice is selected. */
|
|
152
|
+
defaultLabel?: string;
|
|
153
|
+
/** Format the number under the label. Defaults to a compact number. */
|
|
154
|
+
formatValue?: (value: number, slice: PieDatum | null) => string;
|
|
155
|
+
/**
|
|
156
|
+
* Draw the middle yourself. Given the selected slice, or `null` when nothing
|
|
157
|
+
* is selected.
|
|
158
|
+
*/
|
|
159
|
+
children?: (slice: PieDatum | null) => ReactNode;
|
|
160
|
+
className?: string;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* The hole's readout: the total, and the selected slice's own figures once one
|
|
164
|
+
* is picked.
|
|
165
|
+
*
|
|
166
|
+
* Unlike the ring chart's centre, the default here *is* an aggregate, and it is
|
|
167
|
+
* the honest one — the whole point of a pie is that its parts belong to a total,
|
|
168
|
+
* so the total is the number the chart is about. Selecting a slice swaps it for
|
|
169
|
+
* that slice's value and its share.
|
|
170
|
+
*/
|
|
171
|
+
declare function PieChartCenter({ defaultLabel, formatValue, children, className, }: PieChartCenterProps): import("react").JSX.Element | null;
|
|
172
|
+
declare namespace PieChartCenter {
|
|
173
|
+
var displayName: string;
|
|
174
|
+
var slot: "overlay";
|
|
175
|
+
}
|
|
176
|
+
export interface PieChartLegendProps extends ViewProps {
|
|
177
|
+
className?: string;
|
|
178
|
+
/** Show each slice's share of the whole beside its name. */
|
|
179
|
+
showValue?: boolean;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* A swatch, a name and a share per slice, under the chart and across the width
|
|
183
|
+
* of it. Pressable in the same way the slices are — the legend is usually the
|
|
184
|
+
* easier target of the two, and a slice worth a couple of percent is not a
|
|
185
|
+
* target at all.
|
|
186
|
+
*
|
|
187
|
+
* It wraps rather than stacking, so five or six entries take two lines instead
|
|
188
|
+
* of six. A key is a lookup table, and a lookup table read down a column of one
|
|
189
|
+
* word each is a column the eye has to walk.
|
|
190
|
+
*/
|
|
191
|
+
declare function PieChartLegend({ className, showValue, ...props }: PieChartLegendProps): import("react").JSX.Element | null;
|
|
192
|
+
declare namespace PieChartLegend {
|
|
193
|
+
var displayName: string;
|
|
194
|
+
var slot: "footer";
|
|
195
|
+
}
|
|
196
|
+
export interface PieChartHeaderProps extends ViewProps {
|
|
197
|
+
className?: string;
|
|
198
|
+
/** Small line above the value — what the chart is of. */
|
|
199
|
+
title?: string;
|
|
200
|
+
/** The readout. The largest thing on the card, and the first thing read. */
|
|
201
|
+
value?: string;
|
|
202
|
+
/** One muted line under the value — a period, a comparison, a caveat. */
|
|
203
|
+
caption?: string;
|
|
204
|
+
/** Prettier names for the slices, keyed by their `label`. */
|
|
205
|
+
labels?: Record<string, string>;
|
|
206
|
+
/**
|
|
207
|
+
* Draw a swatch and a name per slice along the trailing edge.
|
|
208
|
+
*
|
|
209
|
+
* For two or three short names. Past that use `PieChart.Legend`, which runs
|
|
210
|
+
* under the chart across the full width: a key of five long names crammed
|
|
211
|
+
* into the trailing corner of a header wraps to a column and leaves the title
|
|
212
|
+
* beside it a few points wide.
|
|
213
|
+
*/
|
|
214
|
+
legend?: boolean;
|
|
215
|
+
/** Trailing slot — a control, a badge, a range picker. Wins over `legend`. */
|
|
216
|
+
children?: ReactNode;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* The strip above the pie: what the chart is of, what it reads, and what the
|
|
220
|
+
* colours mean.
|
|
221
|
+
*
|
|
222
|
+
* It belongs to the chart rather than to the card around it because it is about
|
|
223
|
+
* the *slices* — the number changes as one is selected, and the legend is the
|
|
224
|
+
* list the chart itself is holding. The card's header is a caption on the tray
|
|
225
|
+
* the chart sits in; this is the chart introducing itself.
|
|
226
|
+
*
|
|
227
|
+
* The value is not derived here even though there is a total to derive it from,
|
|
228
|
+
* because the formatting is not the chart's to guess: a total of 18420 is a
|
|
229
|
+
* count, a currency or a percentage depending on what was counted, and only the
|
|
230
|
+
* caller knows which.
|
|
231
|
+
*/
|
|
232
|
+
declare function PieChartHeader({ className, title, value, caption, labels, legend, children, ...props }: PieChartHeaderProps): import("react").JSX.Element;
|
|
233
|
+
declare namespace PieChartHeader {
|
|
234
|
+
var displayName: string;
|
|
235
|
+
var slot: "header";
|
|
236
|
+
}
|
|
237
|
+
export declare const PieChart: import("react").ForwardRefExoticComponent<PieChartProps & import("react").RefAttributes<PieChartHandle>> & {
|
|
238
|
+
Header: typeof PieChartHeader;
|
|
239
|
+
Slices: typeof PieChartSlices;
|
|
240
|
+
Center: typeof PieChartCenter;
|
|
241
|
+
Legend: typeof PieChartLegend;
|
|
242
|
+
Skeleton: typeof PieChartSkeleton;
|
|
243
|
+
};
|
|
244
|
+
export {};
|
|
245
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/pie-chart/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ScatterChart — two quantities against each other, drawn on the UI thread.
|
|
3
|
+
*
|
|
4
|
+
* Every other chart in this library spaces its points evenly along the x-axis,
|
|
5
|
+
* because their x is a position: twelve months are twelve equal steps whatever
|
|
6
|
+
* the gaps between the dates behind them. A scatter plot is the one shape where
|
|
7
|
+
* that is wrong. Both coordinates are *measured*, and the reader is being asked
|
|
8
|
+
* to look for a relationship between them — spread the points evenly and the
|
|
9
|
+
* relationship is the one thing you have thrown away.
|
|
10
|
+
*
|
|
11
|
+
* So this chart carries an x-domain as well as a y-domain, and both are tweened
|
|
12
|
+
* when the data changes.
|
|
13
|
+
*
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <ScatterChart data={sessions} xDataKey="spend">
|
|
16
|
+
* <ScatterChart.Grid />
|
|
17
|
+
* <ScatterChart.Points dataKey="revenue" />
|
|
18
|
+
* <ScatterChart.XAxis />
|
|
19
|
+
* <ScatterChart.YAxis />
|
|
20
|
+
* <ScatterChart.Tooltip />
|
|
21
|
+
* </ScatterChart>
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* As elsewhere, there are two layers and the parts sort themselves into the
|
|
25
|
+
* right one: the geometry is SVG, and anything with text or a gesture on it is
|
|
26
|
+
* a React Native view over the top. SVG text ignores the platform's text
|
|
27
|
+
* scaling and the theme's font, and a gesture handler cannot be attached to an
|
|
28
|
+
* SVG node at all.
|
|
29
|
+
*
|
|
30
|
+
* **Finding a point.** A crosshair that snaps to an x index — the way a line
|
|
31
|
+
* chart's does — has nothing to snap to here, because there is no shared x and
|
|
32
|
+
* two points can sit at the same one. Instead the nearest point to the finger
|
|
33
|
+
* is resolved by distance, on the UI thread, and only within a radius: a touch
|
|
34
|
+
* in an empty corner of the plot selects nothing rather than lighting up
|
|
35
|
+
* whichever point happens to be least far away. The radius is generous, because
|
|
36
|
+
* the points are a few pixels across and a fingertip is not.
|
|
37
|
+
*
|
|
38
|
+
* Colours come from the `--color-chart-*` tokens, so a chart follows the active
|
|
39
|
+
* theme. Nothing here hardcodes a hex.
|
|
40
|
+
*/
|
|
41
|
+
import { type ReactNode } from 'react';
|
|
42
|
+
import { type ViewProps } from 'react-native';
|
|
43
|
+
type Layer = 'svg' | 'overlay' | 'header';
|
|
44
|
+
export type ScatterChartStatus = 'loading' | 'ready';
|
|
45
|
+
export type ScatterChartDatum = Record<string, string | number | null | undefined>;
|
|
46
|
+
/** One plotted point, resolved back to the row it came from. */
|
|
47
|
+
export interface ScatterChartPoint {
|
|
48
|
+
/** Index into `data`. */
|
|
49
|
+
index: number;
|
|
50
|
+
/** The series key this point belongs to. */
|
|
51
|
+
dataKey: string;
|
|
52
|
+
x: number;
|
|
53
|
+
y: number;
|
|
54
|
+
datum: ScatterChartDatum;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The selected point, for something rendered *inside* the chart.
|
|
58
|
+
*
|
|
59
|
+
* A readout usually belongs in the card's header, which is outside this
|
|
60
|
+
* provider — use `onActivePointChange` for that. A hook cannot reach up out of
|
|
61
|
+
* the subtree it is called in.
|
|
62
|
+
*/
|
|
63
|
+
export declare function useScatterChart(): {
|
|
64
|
+
activePoint: ScatterChartPoint | null;
|
|
65
|
+
xDataKey: string;
|
|
66
|
+
};
|
|
67
|
+
export interface ScatterChartProps extends ViewProps {
|
|
68
|
+
className?: string;
|
|
69
|
+
/** The rows. Each one is a point, placed by two of its values. */
|
|
70
|
+
data: ScatterChartDatum[];
|
|
71
|
+
/** Key holding the x value. Unlike the other charts, this must be a number. */
|
|
72
|
+
xDataKey?: string;
|
|
73
|
+
/**
|
|
74
|
+
* `loading` draws a still field of muted dots and settles into the real ones
|
|
75
|
+
* when it turns `ready`. One component throughout, rather than a spinner
|
|
76
|
+
* swapped for a chart — swapping loses the transition.
|
|
77
|
+
*/
|
|
78
|
+
status?: ScatterChartStatus;
|
|
79
|
+
/** Width ÷ height. `1` suits a scatter plot: neither axis is the important one. */
|
|
80
|
+
aspectRatio?: number;
|
|
81
|
+
/** Milliseconds for the reveal on mount. */
|
|
82
|
+
animationDuration?: number;
|
|
83
|
+
/** Milliseconds for the axes to settle after the data changes. */
|
|
84
|
+
domainDuration?: number;
|
|
85
|
+
/** Fix the x-axis instead of deriving it from the data. */
|
|
86
|
+
xDomain?: [number, number];
|
|
87
|
+
/** Fix the y-axis instead of deriving it from the data. */
|
|
88
|
+
yDomain?: [number, number];
|
|
89
|
+
/**
|
|
90
|
+
* The point under the finger, and `null` when it lifts. This is how a readout
|
|
91
|
+
* in the card's header gets its value — that header is outside the chart, so
|
|
92
|
+
* it cannot use `useScatterChart`.
|
|
93
|
+
*
|
|
94
|
+
* Fires when the selection changes, not per frame.
|
|
95
|
+
*/
|
|
96
|
+
onActivePointChange?: (point: ScatterChartPoint | null) => void;
|
|
97
|
+
/** Drop the axis padding so the field reaches the edges, for a thumbnail. */
|
|
98
|
+
compact?: boolean;
|
|
99
|
+
children?: ReactNode;
|
|
100
|
+
}
|
|
101
|
+
/** Imperative handle: re-run the reveal on demand, for a "replay" control. */
|
|
102
|
+
export interface ScatterChartHandle {
|
|
103
|
+
replay: () => void;
|
|
104
|
+
}
|
|
105
|
+
export interface ScatterChartGridProps {
|
|
106
|
+
/** Horizontal rules across the plot. */
|
|
107
|
+
rows?: number;
|
|
108
|
+
/**
|
|
109
|
+
* Vertical rules down it. A scatter plot's x is a quantity, so it earns a
|
|
110
|
+
* grid in both directions — a line chart's does not, because its x is a
|
|
111
|
+
* label and a rule under a label divides nothing.
|
|
112
|
+
*/
|
|
113
|
+
columns?: number;
|
|
114
|
+
color?: string;
|
|
115
|
+
/** Dash pattern, e.g. `"4,6"`. Omit for a solid rule. */
|
|
116
|
+
dashArray?: string;
|
|
117
|
+
opacity?: number;
|
|
118
|
+
}
|
|
119
|
+
/** Reference lines both ways. Drawn under everything, and not part of the reveal. */
|
|
120
|
+
declare function ScatterChartGrid({ rows, columns, color, dashArray, opacity, }: ScatterChartGridProps): import("react").JSX.Element;
|
|
121
|
+
declare namespace ScatterChartGrid {
|
|
122
|
+
var displayName: string;
|
|
123
|
+
var layer: Layer;
|
|
124
|
+
}
|
|
125
|
+
export interface ScatterChartPointsProps {
|
|
126
|
+
/** Key holding this series' y values. */
|
|
127
|
+
dataKey: string;
|
|
128
|
+
/**
|
|
129
|
+
* Fill colour. Defaults to the `--color-chart-*` token at `colorIndex`, so a
|
|
130
|
+
* series follows the theme without the call site naming a colour.
|
|
131
|
+
*/
|
|
132
|
+
color?: string;
|
|
133
|
+
/** Which `--color-chart-*` token to take when `color` is not given. */
|
|
134
|
+
colorIndex?: 1 | 2 | 3 | 4 | 5;
|
|
135
|
+
/** Radius of a point, in points. Ignored when `sizeKey` is given. */
|
|
136
|
+
size?: number;
|
|
137
|
+
/**
|
|
138
|
+
* Key holding a third quantity, mapped to each point's *area* — a bubble
|
|
139
|
+
* chart. Area rather than radius, because doubling a radius quadruples the
|
|
140
|
+
* ink and the reader sees four times the value that is there.
|
|
141
|
+
*/
|
|
142
|
+
sizeKey?: string;
|
|
143
|
+
/** Smallest and largest radius `sizeKey` maps onto. */
|
|
144
|
+
sizeRange?: [number, number];
|
|
145
|
+
/**
|
|
146
|
+
* Fill opacity. Below 1 by default so that overlapping points read as denser
|
|
147
|
+
* rather than hiding each other — in a crowded region that overlap *is* the
|
|
148
|
+
* finding, and opaque dots erase it.
|
|
149
|
+
*/
|
|
150
|
+
opacity?: number;
|
|
151
|
+
}
|
|
152
|
+
/** One series, as a field of dots. */
|
|
153
|
+
declare function ScatterChartPoints({ dataKey, color, colorIndex, size, sizeKey, sizeRange, opacity, }: ScatterChartPointsProps): import("react").JSX.Element | null;
|
|
154
|
+
declare namespace ScatterChartPoints {
|
|
155
|
+
var displayName: string;
|
|
156
|
+
var layer: Layer;
|
|
157
|
+
}
|
|
158
|
+
export interface ScatterChartSkeletonProps {
|
|
159
|
+
/** How many placeholder dots to scatter. */
|
|
160
|
+
count?: number;
|
|
161
|
+
color?: string;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* The loading state: a still field of muted dots where the data will be.
|
|
165
|
+
*
|
|
166
|
+
* Deliberately still. A shimmer over a field of dots reads as the points
|
|
167
|
+
* *moving*, which is the one thing a scatter plot must never appear to do —
|
|
168
|
+
* position is the entire message, and a loading state that implies it is
|
|
169
|
+
* changing is a loading state that lies.
|
|
170
|
+
*
|
|
171
|
+
* The layout is deterministic rather than random, so it does not reshuffle on
|
|
172
|
+
* every render of a component that may re-render several times while waiting.
|
|
173
|
+
*
|
|
174
|
+
* Still is not the same as abrupt, though. It dissolves as the real points grow
|
|
175
|
+
* in, and outlives the status change by exactly that long — cut at the frame the
|
|
176
|
+
* data lands, the placeholder disappears before anything has replaced it and the
|
|
177
|
+
* plot is briefly empty.
|
|
178
|
+
*/
|
|
179
|
+
declare function ScatterChartSkeleton({ count, color }: ScatterChartSkeletonProps): import("react").JSX.Element | null;
|
|
180
|
+
declare namespace ScatterChartSkeleton {
|
|
181
|
+
var displayName: string;
|
|
182
|
+
var layer: Layer;
|
|
183
|
+
}
|
|
184
|
+
export interface ScatterChartXAxisProps {
|
|
185
|
+
/** How many intervals to divide the axis into. Yields `ticks + 1` labels. */
|
|
186
|
+
ticks?: number;
|
|
187
|
+
/** Turn a value into its label. Defaults to a compact number. */
|
|
188
|
+
format?: (value: number) => string;
|
|
189
|
+
className?: string;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* The x labels, evenly along the axis.
|
|
193
|
+
*
|
|
194
|
+
* Evenly spaced here — unlike a line chart's, where each label sits on the point
|
|
195
|
+
* it names — because this axis is a continuous scale rather than a list of
|
|
196
|
+
* rows. There is no point to sit on.
|
|
197
|
+
*/
|
|
198
|
+
declare function ScatterChartXAxis({ ticks, format, className }: ScatterChartXAxisProps): import("react").JSX.Element;
|
|
199
|
+
declare namespace ScatterChartXAxis {
|
|
200
|
+
var displayName: string;
|
|
201
|
+
var layer: Layer;
|
|
202
|
+
}
|
|
203
|
+
export interface ScatterChartYAxisProps {
|
|
204
|
+
/** How many intervals to divide the axis into. Yields `ticks + 1` labels. */
|
|
205
|
+
ticks?: number;
|
|
206
|
+
/** Turn a value into its label. Defaults to a compact number. */
|
|
207
|
+
format?: (value: number) => string;
|
|
208
|
+
className?: string;
|
|
209
|
+
}
|
|
210
|
+
/** Value labels down the side, one per grid line. */
|
|
211
|
+
declare function ScatterChartYAxis({ ticks, format, className }: ScatterChartYAxisProps): import("react").JSX.Element;
|
|
212
|
+
declare namespace ScatterChartYAxis {
|
|
213
|
+
var displayName: string;
|
|
214
|
+
var layer: Layer;
|
|
215
|
+
var axis: "y";
|
|
216
|
+
}
|
|
217
|
+
export interface ScatterChartTooltipProps {
|
|
218
|
+
/** Float a small readout beside the selected point. On by default. */
|
|
219
|
+
showLabel?: boolean;
|
|
220
|
+
/** Format the x value for the readout. Defaults to a compact number. */
|
|
221
|
+
formatX?: (value: number) => string;
|
|
222
|
+
/** Format the y value for the readout. Defaults to a compact number. */
|
|
223
|
+
formatY?: (value: number, key: string) => string;
|
|
224
|
+
/** A heading for the readout, from the row — a name, a label, a category. */
|
|
225
|
+
formatTitle?: (datum: ScatterChartDatum) => string;
|
|
226
|
+
/** How far from a point a touch still counts as being on it, in points. */
|
|
227
|
+
hitRadius?: number;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* The touch target, the selection it drives, and the readout that follows it.
|
|
231
|
+
*
|
|
232
|
+
* A line chart's crosshair snaps to an x index. That is not available here:
|
|
233
|
+
* there is no shared x, and two points can sit on the same one. So the nearest
|
|
234
|
+
* point is found by distance instead — and only within `hitRadius`, so a touch
|
|
235
|
+
* in an empty corner selects nothing rather than lighting up whichever point is
|
|
236
|
+
* least far away.
|
|
237
|
+
*
|
|
238
|
+
* The search runs on the UI thread over a flat array of already-projected
|
|
239
|
+
* coordinates, and only the *identity* of the winner crosses back into JS, and
|
|
240
|
+
* only when it changes. A drag across the plot therefore costs a handful of
|
|
241
|
+
* re-renders rather than one per frame.
|
|
242
|
+
*
|
|
243
|
+
* Distances are compared squared. The nearest point by distance is the nearest
|
|
244
|
+
* by distance-squared, and a square root per point per frame buys nothing.
|
|
245
|
+
*/
|
|
246
|
+
declare function ScatterChartTooltip({ showLabel, formatX, formatY, formatTitle, hitRadius, }: ScatterChartTooltipProps): import("react").JSX.Element | null;
|
|
247
|
+
declare namespace ScatterChartTooltip {
|
|
248
|
+
var displayName: string;
|
|
249
|
+
var layer: Layer;
|
|
250
|
+
}
|
|
251
|
+
export interface ScatterChartLegendProps extends ViewProps {
|
|
252
|
+
className?: string;
|
|
253
|
+
/** Label per series key. A key with no label falls back to the key itself. */
|
|
254
|
+
labels?: Record<string, string>;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* A swatch and a name per registered series. Sits in the top-left of the plot
|
|
258
|
+
* by default — move it with `className`.
|
|
259
|
+
*/
|
|
260
|
+
declare function ScatterChartLegend({ className, labels, ...props }: ScatterChartLegendProps): import("react").JSX.Element | null;
|
|
261
|
+
declare namespace ScatterChartLegend {
|
|
262
|
+
var displayName: string;
|
|
263
|
+
var layer: Layer;
|
|
264
|
+
}
|
|
265
|
+
export interface ScatterChartHeaderProps extends ViewProps {
|
|
266
|
+
className?: string;
|
|
267
|
+
/** Small line above the value — what the chart is of. */
|
|
268
|
+
title?: string;
|
|
269
|
+
/** The readout. The largest thing on the card, and the first thing read. */
|
|
270
|
+
value?: string;
|
|
271
|
+
/** One muted line under the value — a period, a comparison, a total. */
|
|
272
|
+
caption?: string;
|
|
273
|
+
/** Prettier names for the series keys, as the legend takes. */
|
|
274
|
+
labels?: Record<string, string>;
|
|
275
|
+
/**
|
|
276
|
+
* Draw a swatch and a name per series along the trailing edge. Prefer this to
|
|
277
|
+
* `ScatterChart.Legend` on a chart that has a header: the legend floats over
|
|
278
|
+
* the plot, where it competes with the points for the same corner.
|
|
279
|
+
*/
|
|
280
|
+
legend?: boolean;
|
|
281
|
+
/** Trailing slot — a control, a badge, a range picker. Wins over `legend`. */
|
|
282
|
+
children?: ReactNode;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* The strip above the plot: what the chart is of, what it currently reads, and
|
|
286
|
+
* what the colours mean.
|
|
287
|
+
*
|
|
288
|
+
* The value is not derived here. A readout that follows the finger belongs to
|
|
289
|
+
* whoever owns the data — take it from `onActivePointChange` and pass the
|
|
290
|
+
* formatted string down, so one header can show a summary when nothing is
|
|
291
|
+
* pressed and a point's values when something is.
|
|
292
|
+
*/
|
|
293
|
+
declare function ScatterChartHeader({ className, title, value, caption, labels, legend, children, ...props }: ScatterChartHeaderProps): import("react").JSX.Element;
|
|
294
|
+
declare namespace ScatterChartHeader {
|
|
295
|
+
var displayName: string;
|
|
296
|
+
var layer: Layer;
|
|
297
|
+
}
|
|
298
|
+
export declare const ScatterChart: import("react").ForwardRefExoticComponent<ScatterChartProps & import("react").RefAttributes<ScatterChartHandle>> & {
|
|
299
|
+
Header: typeof ScatterChartHeader;
|
|
300
|
+
Grid: typeof ScatterChartGrid;
|
|
301
|
+
Points: typeof ScatterChartPoints;
|
|
302
|
+
Skeleton: typeof ScatterChartSkeleton;
|
|
303
|
+
XAxis: typeof ScatterChartXAxis;
|
|
304
|
+
YAxis: typeof ScatterChartYAxis;
|
|
305
|
+
Tooltip: typeof ScatterChartTooltip;
|
|
306
|
+
Legend: typeof ScatterChartLegend;
|
|
307
|
+
};
|
|
308
|
+
export {};
|
|
309
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/scatter-chart/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -15,10 +15,19 @@
|
|
|
15
15
|
* <Tabs.Content value="account">…</Tabs.Content>
|
|
16
16
|
* </Tabs>
|
|
17
17
|
* ```
|
|
18
|
+
*
|
|
19
|
+
* **Swiping.** Only the visible panel is mounted, so a drag has nothing behind
|
|
20
|
+
* it to reveal. The panel still tracks the finger one to one and dims as it
|
|
21
|
+
* goes, and the panel arriving comes back up through the same fade — the
|
|
22
|
+
* movement carries the change and the dissolve covers the gap. On release the
|
|
23
|
+
* arriving panel picks up a whole panel's width from wherever the outgoing one
|
|
24
|
+
* was let go, so the two views draw one continuous movement between them. The
|
|
25
|
+
* displacement lives on the root for exactly that reason: a value belonging to
|
|
26
|
+
* either panel would be destroyed at the handover.
|
|
18
27
|
*/
|
|
19
28
|
import { type ReactNode } from 'react';
|
|
20
29
|
import { type ViewProps } from 'react-native';
|
|
21
|
-
export type TabsVariant = 'segmented' | 'underline' | 'pill';
|
|
30
|
+
export type TabsVariant = 'segmented' | 'underline' | 'pill' | 'expanding';
|
|
22
31
|
export interface TabsProps extends ViewProps {
|
|
23
32
|
className?: string;
|
|
24
33
|
value?: string;
|
|
@@ -27,6 +36,12 @@ export interface TabsProps extends ViewProps {
|
|
|
27
36
|
/**
|
|
28
37
|
* `segmented` is a chip travelling inside a recessed track, `underline` is a
|
|
29
38
|
* rule under the active tab, `pill` is a filled chip on the page.
|
|
39
|
+
*
|
|
40
|
+
* `expanding` is a row of icon pills where only the selected one is open:
|
|
41
|
+
* it widens to let its label out and closes again behind it. For a short row
|
|
42
|
+
* of destinations that are recognisable by their icons, where the labels
|
|
43
|
+
* would otherwise take the whole width to say things nobody rereads. Give
|
|
44
|
+
* every trigger an `icon` — a closed tab has nothing else.
|
|
30
45
|
*/
|
|
31
46
|
variant?: TabsVariant;
|
|
32
47
|
/**
|
|
@@ -62,7 +77,10 @@ declare function TabsList({ className, scrollable, children, ...props }: TabsLis
|
|
|
62
77
|
export interface TabsTriggerProps {
|
|
63
78
|
className?: string;
|
|
64
79
|
value: string;
|
|
65
|
-
/**
|
|
80
|
+
/**
|
|
81
|
+
* Rendered before the label. Required by `variant="expanding"`, where it is
|
|
82
|
+
* the only thing a closed tab has left to identify it by.
|
|
83
|
+
*/
|
|
66
84
|
icon?: ReactNode;
|
|
67
85
|
/** Rendered after the label — a count, a dot, a status. */
|
|
68
86
|
badge?: ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/tabs/index.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/tabs/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAsFtB,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,MAAM,GAAG,WAAW,CAAC;AAsI3E,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,KAAK,EACL,aAAa,EACb,YAAY,EACZ,OAAqB,EACrB,WAAmB,EACnB,SAAiB,EACjB,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,SAAS,+BAkIX;AAqCD,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,iBAAS,QAAQ,CAAC,EAAE,SAAS,EAAE,UAAkB,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,+BA6CrF;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,KAAK,EACL,IAAI,EACJ,KAAK,EACL,QAAgB,EAChB,QAAQ,GACT,EAAE,gBAAgB,+BA8DlB;AA0ID,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,EAAE,gBAAgB,sCAuJrF;AAED,eAAO,MAAM,IAAI;;;;CAIf,CAAC"}
|