panelui-native 0.99.0 → 0.101.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.
Files changed (46) hide show
  1. package/README.md +2 -0
  2. package/lib/module/components/animated-badge/index.js +24 -2
  3. package/lib/module/components/animated-badge/index.js.map +1 -1
  4. package/lib/module/components/bump-chart/index.js +1236 -0
  5. package/lib/module/components/bump-chart/index.js.map +1 -0
  6. package/lib/module/components/compare/index.js +576 -0
  7. package/lib/module/components/compare/index.js.map +1 -0
  8. package/lib/module/components/mirror-area-chart/index.js +1113 -0
  9. package/lib/module/components/mirror-area-chart/index.js.map +1 -0
  10. package/lib/module/components/sankey-chart/index.js +933 -0
  11. package/lib/module/components/sankey-chart/index.js.map +1 -0
  12. package/lib/module/components/sankey-chart/sankey-layout.js +530 -0
  13. package/lib/module/components/sankey-chart/sankey-layout.js.map +1 -0
  14. package/lib/module/icons/index.js +15 -3
  15. package/lib/module/icons/index.js.map +1 -1
  16. package/lib/module/index.js +4 -0
  17. package/lib/module/index.js.map +1 -1
  18. package/lib/module/utils/chart.js +101 -0
  19. package/lib/module/utils/chart.js.map +1 -1
  20. package/lib/typescript/src/components/animated-badge/index.d.ts +5 -0
  21. package/lib/typescript/src/components/animated-badge/index.d.ts.map +1 -1
  22. package/lib/typescript/src/components/bump-chart/index.d.ts +267 -0
  23. package/lib/typescript/src/components/bump-chart/index.d.ts.map +1 -0
  24. package/lib/typescript/src/components/compare/index.d.ts +183 -0
  25. package/lib/typescript/src/components/compare/index.d.ts.map +1 -0
  26. package/lib/typescript/src/components/mirror-area-chart/index.d.ts +263 -0
  27. package/lib/typescript/src/components/mirror-area-chart/index.d.ts.map +1 -0
  28. package/lib/typescript/src/components/sankey-chart/index.d.ts +307 -0
  29. package/lib/typescript/src/components/sankey-chart/index.d.ts.map +1 -0
  30. package/lib/typescript/src/components/sankey-chart/sankey-layout.d.ts +107 -0
  31. package/lib/typescript/src/components/sankey-chart/sankey-layout.d.ts.map +1 -0
  32. package/lib/typescript/src/icons/index.d.ts.map +1 -1
  33. package/lib/typescript/src/index.d.ts +4 -0
  34. package/lib/typescript/src/index.d.ts.map +1 -1
  35. package/lib/typescript/src/utils/chart.d.ts +40 -0
  36. package/lib/typescript/src/utils/chart.d.ts.map +1 -1
  37. package/package.json +1 -1
  38. package/src/components/animated-badge/index.tsx +35 -2
  39. package/src/components/bump-chart/index.tsx +1455 -0
  40. package/src/components/compare/index.tsx +650 -0
  41. package/src/components/mirror-area-chart/index.tsx +1333 -0
  42. package/src/components/sankey-chart/index.tsx +1165 -0
  43. package/src/components/sankey-chart/sankey-layout.ts +645 -0
  44. package/src/icons/index.tsx +20 -6
  45. package/src/index.ts +62 -0
  46. package/src/utils/chart.ts +116 -0
@@ -0,0 +1,263 @@
1
+ /**
2
+ * MirrorAreaChart — two readings of one timeline, one above a baseline and one
3
+ * below it.
4
+ *
5
+ * ```tsx
6
+ * <MirrorAreaChart data={load} xDataKey="time">
7
+ * <MirrorAreaChart.Grid />
8
+ * <MirrorAreaChart.Area dataKey="jobs" label="jobs" muted />
9
+ * <MirrorAreaChart.Area dataKey="high" label="high priority" />
10
+ * <MirrorAreaChart.Area dataKey="share" label="% high" side="bottom" />
11
+ * <MirrorAreaChart.Baseline />
12
+ * <MirrorAreaChart.Tooltip />
13
+ * </MirrorAreaChart>
14
+ * ```
15
+ *
16
+ * ## Two scales, one timeline
17
+ *
18
+ * Each half has its own scale, because the two readings are usually in
19
+ * different units — a count above and a percentage below, or requests above
20
+ * and errors below. Both grow away from the baseline, so a peak in one lines
21
+ * up with whatever the other did at the same moment, and neither is squeezed
22
+ * into the other's range.
23
+ *
24
+ * Areas on the same side overlay in the order they are declared. Declare the
25
+ * whole first and the part of it second, so the part is drawn inside the whole.
26
+ */
27
+ import { type ReactNode } from 'react';
28
+ import { type ViewProps } from 'react-native';
29
+ import { type ChartAccessibilityProps } from '../../primitives/chart-accessibility.js';
30
+ import { type ChartCurve, type SeriesColorIndex } from '../../utils/chart.js';
31
+ type Layer = 'svg' | 'series' | 'overlay' | 'header';
32
+ export type MirrorAreaChartStatus = 'loading' | 'ready';
33
+ export type MirrorAreaChartSide = 'top' | 'bottom';
34
+ export type MirrorAreaChartDatum = Record<string, string | number | null | undefined>;
35
+ /** The row under the crosshair, for a header or a readout outside the chart. */
36
+ export declare function useMirrorAreaChart(): {
37
+ activeIndex: number;
38
+ activePoint: MirrorAreaChartDatum | null;
39
+ xDataKey: string;
40
+ };
41
+ export interface MirrorAreaChartProps extends ViewProps, ChartAccessibilityProps<MirrorAreaChartDatum> {
42
+ className?: string;
43
+ /** The rows. Each one is a point along the x-axis. */
44
+ data: MirrorAreaChartDatum[];
45
+ /** Key holding the x label. Used by the axis and the readout. */
46
+ xDataKey?: string;
47
+ /**
48
+ * How much of the plot's height sits above the baseline, from `0` to `1`.
49
+ * Give the half you want read first the larger share.
50
+ */
51
+ split?: number;
52
+ /**
53
+ * Fix the top half's scale instead of deriving it from the data. Only the
54
+ * upper end is used: the baseline is always zero.
55
+ */
56
+ topDomain?: [number, number];
57
+ /** Fix the bottom half's scale. Only the upper end is used. */
58
+ bottomDomain?: [number, number];
59
+ /** `monotone` never overshoots between points; `linear` joins them straight. */
60
+ curve?: ChartCurve;
61
+ /**
62
+ * `loading` holds the bands flat on the baseline and grows them out when it
63
+ * turns `ready`. Add a `MirrorAreaChart.Skeleton` to show something meanwhile.
64
+ */
65
+ status?: MirrorAreaChartStatus;
66
+ /** Width ÷ height. */
67
+ aspectRatio?: number;
68
+ /** Milliseconds for the bands to grow out on mount. */
69
+ animationDuration?: number;
70
+ /** Milliseconds for either scale to settle after the data changes. */
71
+ domainDuration?: number;
72
+ /**
73
+ * The point under the crosshair as it moves, and `-1`/`null` when it lifts.
74
+ * Fires when the index changes, not per frame.
75
+ */
76
+ onActiveIndexChange?: (index: number, datum: MirrorAreaChartDatum | null) => void;
77
+ /** Drop the axis padding so the bands reach the edges, for a sparkline. */
78
+ compact?: boolean;
79
+ children?: ReactNode;
80
+ }
81
+ /** Imperative handle: re-run the reveal on demand, for a "replay" control. */
82
+ export interface MirrorAreaChartHandle {
83
+ replay: () => void;
84
+ }
85
+ export interface MirrorAreaChartGridProps {
86
+ /** `dots` is a field of points; `lines` is dashed rules across each half. */
87
+ variant?: 'dots' | 'lines';
88
+ /** Distance between dots, or how many rules each half gets. */
89
+ spacing?: number;
90
+ color?: string;
91
+ opacity?: number;
92
+ }
93
+ /**
94
+ * The texture behind the bands. Dots by default, which mark the plot's extent
95
+ * without drawing lines that compete with the baseline.
96
+ */
97
+ declare function MirrorAreaChartGrid({ variant, spacing, color, opacity }: MirrorAreaChartGridProps): import("react").JSX.Element;
98
+ declare namespace MirrorAreaChartGrid {
99
+ var displayName: string;
100
+ var layer: Layer;
101
+ }
102
+ export interface MirrorAreaChartBaselineProps {
103
+ color?: string;
104
+ strokeWidth?: number;
105
+ opacity?: number;
106
+ }
107
+ /**
108
+ * The line both halves grow away from. Declare it after the areas so it is
109
+ * drawn over their bases.
110
+ */
111
+ declare function MirrorAreaChartBaseline({ color, strokeWidth, opacity }: MirrorAreaChartBaselineProps): import("react").JSX.Element;
112
+ declare namespace MirrorAreaChartBaseline {
113
+ var displayName: string;
114
+ var layer: Layer;
115
+ }
116
+ export interface MirrorAreaChartAreaProps {
117
+ /** Column in the data holding this series' values. */
118
+ dataKey: string;
119
+ /** Which half it is drawn in. */
120
+ side?: MirrorAreaChartSide;
121
+ /** The name shown by the readout and the legend. Defaults to `dataKey`. */
122
+ label?: string;
123
+ /** Explicit colour. Defaults to the `--color-chart-*` token for `colorIndex`. */
124
+ color?: string;
125
+ /** Which of the five chart tokens to take. */
126
+ colorIndex?: SeriesColorIndex;
127
+ /**
128
+ * Draw it in the muted foreground colour instead, for a total that the
129
+ * coloured areas are parts of.
130
+ */
131
+ muted?: boolean;
132
+ /** Opacity of the fill at the band's outer edge. */
133
+ fillOpacity?: number;
134
+ /** Opacity of the fill at the baseline. Defaults to `fillOpacity`, a flat fill. */
135
+ gradientToOpacity?: number;
136
+ /** Draw the line along the band's outer edge. */
137
+ showLine?: boolean;
138
+ /** Thickness of that line. */
139
+ strokeWidth?: number;
140
+ }
141
+ /**
142
+ * One band, growing away from the baseline on its side. Areas on one side
143
+ * overlay in declaration order, so a whole declared first is drawn behind a
144
+ * part of it declared second.
145
+ */
146
+ declare function MirrorAreaChartArea({ dataKey, side, label, color, colorIndex, muted, fillOpacity, gradientToOpacity, showLine, strokeWidth, }: MirrorAreaChartAreaProps): import("react").JSX.Element;
147
+ declare namespace MirrorAreaChartArea {
148
+ var displayName: string;
149
+ var layer: Layer;
150
+ var area: true;
151
+ }
152
+ export interface MirrorAreaChartSkeletonProps {
153
+ /** Milliseconds for one pass of the sweep. */
154
+ duration?: number;
155
+ color?: string;
156
+ }
157
+ /**
158
+ * The loading state: a low band either side of the baseline with a highlight
159
+ * travelling across it. Flat, so it says where the bands will be and nothing
160
+ * about their shape.
161
+ */
162
+ declare function MirrorAreaChartSkeleton({ duration, color }: MirrorAreaChartSkeletonProps): import("react").JSX.Element | null;
163
+ declare namespace MirrorAreaChartSkeleton {
164
+ var displayName: string;
165
+ var layer: Layer;
166
+ }
167
+ export interface MirrorAreaChartXAxisProps {
168
+ ticks?: number;
169
+ format?: (datum: MirrorAreaChartDatum, index: number) => string;
170
+ className?: string;
171
+ }
172
+ /** The x labels. Real text, so they follow the theme's font and text scaling. */
173
+ declare function MirrorAreaChartXAxis({ ticks, format, className }: MirrorAreaChartXAxisProps): import("react").JSX.Element;
174
+ declare namespace MirrorAreaChartXAxis {
175
+ var displayName: string;
176
+ var layer: Layer;
177
+ }
178
+ export interface MirrorAreaChartYAxisProps {
179
+ /** Format a value in the top half. */
180
+ formatTop?: (value: number) => string;
181
+ /** Format a value in the bottom half. */
182
+ formatBottom?: (value: number) => string;
183
+ className?: string;
184
+ }
185
+ /**
186
+ * Three labels down the side: the top half's maximum, zero on the baseline,
187
+ * and the bottom half's maximum. Two scales need two labels, and a column of
188
+ * evenly spaced numbers would suggest one.
189
+ */
190
+ declare function MirrorAreaChartYAxis({ formatTop, formatBottom, className }: MirrorAreaChartYAxisProps): import("react").JSX.Element;
191
+ declare namespace MirrorAreaChartYAxis {
192
+ var displayName: string;
193
+ var layer: Layer;
194
+ var axis: "y";
195
+ }
196
+ export interface MirrorAreaChartTooltipProps {
197
+ /** Colour of the crosshair and the dot. Defaults to the foreground token. */
198
+ color?: string;
199
+ /** Format one series' value. Defaults to a compact number. */
200
+ formatValue?: (value: number, key: string) => string;
201
+ /** Format the readout's heading from the row. Defaults to the value at xDataKey. */
202
+ formatX?: (datum: MirrorAreaChartDatum) => string;
203
+ /**
204
+ * One line to show instead of a row per series — "1,120 jobs · 78% high".
205
+ * Use it when the series only make sense read together.
206
+ */
207
+ formatSummary?: (datum: MirrorAreaChartDatum) => string;
208
+ className?: string;
209
+ }
210
+ /**
211
+ * A dashed crosshair, a dot on the outer edge of the top half, and a readout
212
+ * beside them. The hit area is the whole plot.
213
+ */
214
+ declare function MirrorAreaChartTooltip({ color, formatValue, formatX, formatSummary, className, }: MirrorAreaChartTooltipProps): import("react").JSX.Element | null;
215
+ declare namespace MirrorAreaChartTooltip {
216
+ var displayName: string;
217
+ var layer: Layer;
218
+ }
219
+ export interface MirrorAreaChartLegendProps extends ViewProps {
220
+ className?: string;
221
+ }
222
+ /** A swatch and a name per area, top half first. */
223
+ declare function MirrorAreaChartLegend({ className, ...props }: MirrorAreaChartLegendProps): import("react").JSX.Element | null;
224
+ declare namespace MirrorAreaChartLegend {
225
+ var displayName: string;
226
+ var layer: Layer;
227
+ }
228
+ export interface MirrorAreaChartHeaderProps extends ViewProps {
229
+ className?: string;
230
+ /** Small line above the value — what the chart is of. */
231
+ title?: string;
232
+ /** The readout. The largest thing on the card, and the first thing read. */
233
+ value?: string;
234
+ /** One muted line under the value — a period, a comparison, a total. */
235
+ caption?: string;
236
+ /** Draw a swatch and a name per area along the trailing edge. */
237
+ legend?: boolean;
238
+ /** Trailing slot — a control, a badge, a range picker. Wins over `legend`. */
239
+ children?: ReactNode;
240
+ }
241
+ /**
242
+ * The strip above the plot: what the chart is of and what it currently reads.
243
+ * The value is not derived here — pass the formatted string, from
244
+ * `onActiveIndexChange` if it follows the finger.
245
+ */
246
+ declare function MirrorAreaChartHeader({ className, title, value, caption, legend, children, ...props }: MirrorAreaChartHeaderProps): import("react").JSX.Element;
247
+ declare namespace MirrorAreaChartHeader {
248
+ var displayName: string;
249
+ var layer: Layer;
250
+ }
251
+ export declare const MirrorAreaChart: import("react").ForwardRefExoticComponent<MirrorAreaChartProps & import("react").RefAttributes<MirrorAreaChartHandle>> & {
252
+ Header: typeof MirrorAreaChartHeader;
253
+ Grid: typeof MirrorAreaChartGrid;
254
+ Area: typeof MirrorAreaChartArea;
255
+ Baseline: typeof MirrorAreaChartBaseline;
256
+ Skeleton: typeof MirrorAreaChartSkeleton;
257
+ XAxis: typeof MirrorAreaChartXAxis;
258
+ YAxis: typeof MirrorAreaChartYAxis;
259
+ Tooltip: typeof MirrorAreaChartTooltip;
260
+ Legend: typeof MirrorAreaChartLegend;
261
+ };
262
+ export {};
263
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/mirror-area-chart/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,307 @@
1
+ /**
2
+ * SankeyChart — where a quantity came from and where it ended up.
3
+ *
4
+ * ```tsx
5
+ * <SankeyChart nodes={stages} links={flows}>
6
+ * <SankeyChart.Header title="Traffic" value="128,400" />
7
+ * <SankeyChart.Links />
8
+ * <SankeyChart.Nodes />
9
+ * <SankeyChart.Labels />
10
+ * <SankeyChart.Tooltip />
11
+ * </SankeyChart>
12
+ * ```
13
+ *
14
+ * ## What it answers that the other charts do not
15
+ *
16
+ * Every other chart here takes one set of things and measures them. This one
17
+ * takes two and says how much of the first became the second. A treemap cuts a
18
+ * total into its parts, a funnel counts what survived each step, a waterfall
19
+ * carries a balance from one figure to another — none of them can say that
20
+ * *this* source fed *that* destination, because none of them draws a thing that
21
+ * has two ends.
22
+ *
23
+ * So the question to bring to it is a routing question. Which campaigns
24
+ * produced which signups; which budget lines paid for which departments; what
25
+ * the traffic that arrived on the landing page went on to do. If the answer
26
+ * does not need a source *and* a target, one of the simpler charts will read
27
+ * better at the same size.
28
+ *
29
+ * ## The ribbon is the reading
30
+ *
31
+ * A ribbon's thickness is its value, on one scale shared by the whole diagram,
32
+ * so a ribbon twice as thick is twice as much wherever it is on the page. That
33
+ * is the only quantity here: the horizontal distance a ribbon travels is the
34
+ * number of columns between its ends and means nothing else, and the vertical
35
+ * order within a column is chosen to keep the ribbons from crossing rather than
36
+ * to rank anything.
37
+ *
38
+ * A node's height is what passes through it — the larger of what arrives and
39
+ * what leaves, which are the same number unless some of it went nowhere. Where
40
+ * they differ, give the node an explicit `value` to pin it; the diagram cannot
41
+ * infer a loss it was never told about.
42
+ *
43
+ * ## Columns are the flow's, not the caller's
44
+ *
45
+ * Nothing about the order of the `nodes` array decides where a node is drawn. A
46
+ * node that receives from another has to be drawn after it or its ribbon would
47
+ * run backwards, so the columns come out of the links. `align` only settles the
48
+ * cases the flow leaves open, and the default pushes every node that feeds
49
+ * nothing into the last column, so the diagram ends on a straight edge of
50
+ * destinations instead of a ragged one.
51
+ *
52
+ * ## Bad rows are dropped rather than fatal
53
+ *
54
+ * Flow data is nearly always joined together from somewhere nobody in the room
55
+ * owns, and it arrives with rows that name a node that is not there, carry a
56
+ * zero, or close a loop. A loop in particular has no left-to-right reading at
57
+ * all. All of them are dropped and counted, and `onDropLinks` reports how many
58
+ * — so a screen can say "3 rows could not be drawn" instead of going blank or
59
+ * quietly showing less than it was given.
60
+ */
61
+ import { type ReactNode } from 'react';
62
+ import { type ViewProps } from 'react-native';
63
+ import { type ChartAccessibilityProps } from '../../primitives/chart-accessibility.js';
64
+ import { type SankeyAlign } from './sankey-layout.js';
65
+ export type { SankeyAlign } from './sankey-layout.js';
66
+ export type SankeyChartStatus = 'loading' | 'ready';
67
+ export interface SankeyNode {
68
+ /** Stable key the links name. Must be unique; a repeat is ignored. */
69
+ id: string;
70
+ /** Name drawn beside the bar. Defaults to the id. */
71
+ label?: string;
72
+ /** Explicit colour, instead of the node's place in the palette. */
73
+ color?: string;
74
+ /**
75
+ * Pins what passes through the node, for a stage that loses some of what it
76
+ * received to somewhere the links do not describe. Left unset the node is
77
+ * worth the larger of what arrives and what leaves.
78
+ */
79
+ value?: number;
80
+ }
81
+ export interface SankeyLink {
82
+ /** `id` of the node it leaves. */
83
+ source: string;
84
+ /** `id` of the node it reaches. */
85
+ target: string;
86
+ /** How much travels. Zero, negative and non-finite rows are dropped. */
87
+ value: number;
88
+ /** Explicit colour, instead of taking the source node's. */
89
+ color?: string;
90
+ }
91
+ /** The selected node and what runs through it, for something drawn inside the chart. */
92
+ export declare function useSankeyChart(): {
93
+ activeId: string | null;
94
+ activeNode: SankeyNode | null;
95
+ /** What passes through it — what the bar's height is drawn from. */
96
+ activeValue: number;
97
+ /** What arrives. Zero at a node the flow starts from. */
98
+ incoming: number;
99
+ /** What leaves. Zero at a node the flow ends at. */
100
+ outgoing: number;
101
+ };
102
+ export interface SankeyChartProps extends ViewProps, ChartAccessibilityProps<SankeyNode> {
103
+ className?: string;
104
+ /** The stages. Order does not decide position — the links do. */
105
+ nodes: SankeyNode[];
106
+ /** What travels between them. */
107
+ links: SankeyLink[];
108
+ /**
109
+ * How tall the diagram is drawn, in points.
110
+ *
111
+ * The width is the card's, but nothing in a flow says how deep it should be:
112
+ * a diagram of four nodes and one of forty are the same data at two heights,
113
+ * and which of them is right is a question about the screen.
114
+ */
115
+ height?: number;
116
+ /** How thick a node's bar is, in points. */
117
+ nodeWidth?: number;
118
+ /**
119
+ * The gap between two nodes in a column, in points.
120
+ *
121
+ * A maximum rather than a promise. A crowded column gives its spacing up
122
+ * before it gives up the height of its bars, because the bar is the reading.
123
+ */
124
+ nodePadding?: number;
125
+ /** Which column a node goes in where the flow leaves a choice. */
126
+ align?: SankeyAlign;
127
+ /** Relaxation rounds spent untangling the ribbons. */
128
+ iterations?: number;
129
+ /** How far a ribbon bends, `0` for a straight diagonal and `0.5` for an S. */
130
+ curve?: number;
131
+ /** The first hue. The rest of the palette follows from the theme's tokens. */
132
+ color?: string;
133
+ /** Milliseconds for one column to draw itself. */
134
+ animationDuration?: number;
135
+ /** Milliseconds between one column starting and the next. `0` for all at once. */
136
+ staggerDelay?: number;
137
+ /** `loading` draws a plain placeholder until the data arrives. */
138
+ status?: SankeyChartStatus;
139
+ /** Selected node. Leave unset to let the chart track it. */
140
+ activeId?: string | null;
141
+ /** Fires with the selected node's id, or `null` when the selection is cleared. */
142
+ onActiveIdChange?: (id: string | null) => void;
143
+ /**
144
+ * Fires with how many link rows could not be drawn — ones naming a node that
145
+ * is not there, carrying nothing, or closing a loop. `0` after a clean render,
146
+ * so a banner can be shown and taken away from the same signal.
147
+ */
148
+ onDropLinks?: (count: number) => void;
149
+ children?: ReactNode;
150
+ }
151
+ /** Imperative handle: re-run the entrance, for a "replay" control. */
152
+ export interface SankeyChartHandle {
153
+ replay: () => void;
154
+ }
155
+ export interface SankeyChartLinksProps {
156
+ /** A ribbon's opacity at rest. */
157
+ opacity?: number;
158
+ /** A ribbon's opacity when its node is selected. */
159
+ activeOpacity?: number;
160
+ /** And when something else is. */
161
+ dimOpacity?: number;
162
+ }
163
+ /**
164
+ * The ribbons.
165
+ *
166
+ * Drawn before the bars so a bar sits on top of the flows that meet it, which
167
+ * is what gives a node a clean edge to arrive at instead of a fringe of ribbon
168
+ * ends poking through it.
169
+ *
170
+ * Translucent at rest, and that is not decoration. Ribbons cross — that is the
171
+ * shape of routed data — and an opaque one hides whatever passes under it, so
172
+ * the reader loses the smaller of every pair. At this opacity a crossing reads
173
+ * as two ribbons rather than as one with a notch in it.
174
+ */
175
+ declare function SankeyChartLinks({ opacity, activeOpacity, dimOpacity, }: SankeyChartLinksProps): import("react").JSX.Element | null;
176
+ declare namespace SankeyChartLinks {
177
+ var displayName: string;
178
+ var slot: "svg";
179
+ }
180
+ export interface SankeyChartNodesProps {
181
+ /** Corner radius on a node's bar, in points. */
182
+ radius?: number;
183
+ /** A bar's opacity when something else is selected. */
184
+ dimOpacity?: number;
185
+ }
186
+ /**
187
+ * The bars the ribbons run between.
188
+ *
189
+ * Solid where the ribbons are translucent, because a node is the one thing on
190
+ * the diagram that is not crossing anything else — it is the edge the flow
191
+ * arrives at, and it reads as an edge only if nothing shows through it.
192
+ */
193
+ declare function SankeyChartNodes({ radius, dimOpacity }: SankeyChartNodesProps): import("react").JSX.Element | null;
194
+ declare namespace SankeyChartNodes {
195
+ var displayName: string;
196
+ var slot: "svg";
197
+ }
198
+ export interface SankeyChartLabelsProps {
199
+ className?: string;
200
+ /** Format the figure beside a name. Defaults to a compact number. */
201
+ formatValue?: (value: number, node: SankeyNode) => string;
202
+ /** Show the figure under the name. */
203
+ showValue?: boolean;
204
+ /**
205
+ * Hide the name on a bar shorter than this, in points.
206
+ *
207
+ * A diagram of forty nodes has bars a few points tall, and forty names at
208
+ * that spacing overlap into a grey band that hides the flow behind it. The
209
+ * names that are dropped are the smallest ones, which is where the tooltip
210
+ * takes over.
211
+ */
212
+ minHeight?: number;
213
+ }
214
+ /**
215
+ * The names, and the press targets that go with them.
216
+ *
217
+ * Outside the bars rather than on them. A node's bar is as thick as it was
218
+ * asked to be — ten points by default — and no name fits inside ten points, so
219
+ * putting the name on the bar means widening every bar to suit the longest
220
+ * label and losing the width the ribbons need.
221
+ *
222
+ * Which side a name goes on is decided by the column: the last column reads
223
+ * inwards from the right edge, everything else outwards to the right. So the
224
+ * names stay inside the chart's box at both ends, instead of the leftmost and
225
+ * rightmost ones being clipped.
226
+ *
227
+ * The target is the label's row, not the bar. A node worth one percent of the
228
+ * flow is a two-point sliver and cannot be hit; the row it sits in can, and it
229
+ * is padded out to a proper target where the sliver is smaller than one.
230
+ */
231
+ declare function SankeyChartLabels({ className, formatValue, showValue, minHeight, }: SankeyChartLabelsProps): import("react").JSX.Element | null;
232
+ declare namespace SankeyChartLabels {
233
+ var displayName: string;
234
+ var slot: "overlay";
235
+ }
236
+ export interface SankeyChartTooltipProps {
237
+ className?: string;
238
+ /** Format the figures. Defaults to a compact number. */
239
+ formatValue?: (value: number) => string;
240
+ }
241
+ /**
242
+ * What the selected node carries: the total through it, and what that total is
243
+ * made of at each end.
244
+ *
245
+ * In and out are shown separately because they are the two readings a flow
246
+ * diagram is for, and they are only the same number when nothing was lost. A
247
+ * node where they differ is the interesting one on the whole chart, and a
248
+ * single total would hide exactly that.
249
+ *
250
+ * Anchored beside the node and clamped to the plot, so it never leaves the box
251
+ * it belongs to — a card half off the edge of a phone is a card nobody can read.
252
+ */
253
+ declare function SankeyChartTooltip({ className, formatValue }: SankeyChartTooltipProps): import("react").JSX.Element | null;
254
+ declare namespace SankeyChartTooltip {
255
+ var displayName: string;
256
+ var slot: "overlay";
257
+ }
258
+ export interface SankeyChartSkeletonProps {
259
+ color?: string;
260
+ }
261
+ /**
262
+ * The loading state: a few plain bars and the ribbons between them, carrying no
263
+ * values.
264
+ *
265
+ * Every bar the same height and every ribbon the same thickness, deliberately.
266
+ * A placeholder with varied thicknesses would be an invented routing, and a
267
+ * reader cannot tell an invented one from a real one until it changes under
268
+ * them — which is worse than showing nothing, because it is showing something
269
+ * wrong.
270
+ */
271
+ declare function SankeyChartSkeleton({ color }: SankeyChartSkeletonProps): import("react").JSX.Element | null;
272
+ declare namespace SankeyChartSkeleton {
273
+ var displayName: string;
274
+ var slot: "svg";
275
+ }
276
+ export interface SankeyChartHeaderProps extends ViewProps {
277
+ className?: string;
278
+ /** Small line above the value — what the flow is of. */
279
+ title?: string;
280
+ /** The readout. The largest thing on the card, and the first thing read. */
281
+ value?: string;
282
+ /** One muted line under the value — a period, a comparison, a caveat. */
283
+ caption?: string;
284
+ /** Trailing slot — a control, a badge, a range picker. */
285
+ children?: ReactNode;
286
+ }
287
+ /**
288
+ * The strip above the diagram: what the flow is of and what it totals.
289
+ *
290
+ * The value is not derived even though there are sources to add up, because the
291
+ * formatting is not the chart's to guess: 128400 is a count, a currency or a
292
+ * rate depending on what was routed.
293
+ */
294
+ declare function SankeyChartHeader({ className, title, value, caption, children, ...props }: SankeyChartHeaderProps): import("react").JSX.Element;
295
+ declare namespace SankeyChartHeader {
296
+ var displayName: string;
297
+ var slot: "header";
298
+ }
299
+ export declare const SankeyChart: import("react").ForwardRefExoticComponent<SankeyChartProps & import("react").RefAttributes<SankeyChartHandle>> & {
300
+ Header: typeof SankeyChartHeader;
301
+ Links: typeof SankeyChartLinks;
302
+ Nodes: typeof SankeyChartNodes;
303
+ Labels: typeof SankeyChartLabels;
304
+ Tooltip: typeof SankeyChartTooltip;
305
+ Skeleton: typeof SankeyChartSkeleton;
306
+ };
307
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/sankey-chart/index.tsx"],"names":[],"mappings":"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"}