panelui-native 0.100.0 → 0.101.1
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 -0
- package/lib/module/components/card/index.js +1 -1
- package/lib/module/components/card/index.js.map +1 -1
- package/lib/module/components/compare/index.js +576 -0
- package/lib/module/components/compare/index.js.map +1 -0
- package/lib/module/components/planner/index.js +8 -1
- package/lib/module/components/planner/index.js.map +1 -1
- package/lib/module/components/sankey-chart/index.js +933 -0
- package/lib/module/components/sankey-chart/index.js.map +1 -0
- package/lib/module/components/sankey-chart/sankey-layout.js +530 -0
- package/lib/module/components/sankey-chart/sankey-layout.js.map +1 -0
- package/lib/module/components/typography/index.js +10 -2
- package/lib/module/components/typography/index.js.map +1 -1
- package/lib/module/icons/index.js +15 -3
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/chart.js +31 -0
- package/lib/module/utils/chart.js.map +1 -1
- package/lib/typescript/src/components/compare/index.d.ts +183 -0
- package/lib/typescript/src/components/compare/index.d.ts.map +1 -0
- package/lib/typescript/src/components/planner/index.d.ts.map +1 -1
- package/lib/typescript/src/components/sankey-chart/index.d.ts +307 -0
- package/lib/typescript/src/components/sankey-chart/index.d.ts.map +1 -0
- package/lib/typescript/src/components/sankey-chart/sankey-layout.d.ts +107 -0
- package/lib/typescript/src/components/sankey-chart/sankey-layout.d.ts.map +1 -0
- package/lib/typescript/src/components/typography/index.d.ts +0 -3
- package/lib/typescript/src/components/typography/index.d.ts.map +1 -1
- package/lib/typescript/src/icons/index.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/chart.d.ts +17 -0
- package/lib/typescript/src/utils/chart.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/card/index.tsx +1 -1
- package/src/components/compare/index.tsx +650 -0
- package/src/components/planner/index.tsx +8 -1
- package/src/components/sankey-chart/index.tsx +1165 -0
- package/src/components/sankey-chart/sankey-layout.ts +645 -0
- package/src/components/typography/index.tsx +10 -2
- package/src/icons/index.tsx +20 -6
- package/src/index.ts +25 -0
- package/src/utils/chart.ts +46 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compare — two versions of one picture, with a seam the reader drags across
|
|
3
|
+
* it.
|
|
4
|
+
*
|
|
5
|
+
* ```tsx
|
|
6
|
+
* <Compare height={260}>
|
|
7
|
+
* <Compare.After>
|
|
8
|
+
* <Image source={retouched} style={{ width: '100%', height: '100%' }} />
|
|
9
|
+
* </Compare.After>
|
|
10
|
+
* <Compare.Before>
|
|
11
|
+
* <Image source={original} style={{ width: '100%', height: '100%' }} />
|
|
12
|
+
* </Compare.Before>
|
|
13
|
+
* <Compare.Handle />
|
|
14
|
+
* </Compare>
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* ## What it is for
|
|
18
|
+
*
|
|
19
|
+
* Showing that two images differ, when they differ in a way a pair of
|
|
20
|
+
* thumbnails side by side will not carry. Retouching, a filter, a render at two
|
|
21
|
+
* quality settings, a map at two dates: the change is spread across the frame
|
|
22
|
+
* rather than gathered in one place, and the eye cannot hold one image well
|
|
23
|
+
* enough to spot it in the other.
|
|
24
|
+
*
|
|
25
|
+
* The seam works because both versions are in the same place on the screen at
|
|
26
|
+
* the same scale. Every pixel the reader is comparing is a pixel that was just
|
|
27
|
+
* under the one beside it, so the difference arrives as movement rather than as
|
|
28
|
+
* something to be remembered.
|
|
29
|
+
*
|
|
30
|
+
* ## It clips, it does not resize
|
|
31
|
+
*
|
|
32
|
+
* The revealed side is a window onto a full-size copy of its content, not a
|
|
33
|
+
* copy of the content squeezed into the window. That distinction is the whole
|
|
34
|
+
* implementation: a view whose width is animated will lay its children out
|
|
35
|
+
* again at every new width, so an image inside one is an image being squashed
|
|
36
|
+
* and stretched as the seam moves, and the two halves stop lining up — which
|
|
37
|
+
* is the one thing this component exists to guarantee.
|
|
38
|
+
*
|
|
39
|
+
* It follows that the content has to be told how big to be, and the only thing
|
|
40
|
+
* that knows is the container once it has been measured. So nothing is drawn
|
|
41
|
+
* until the first layout pass has run, and `Compare.Before` sizes its child to
|
|
42
|
+
* the measured box rather than to itself.
|
|
43
|
+
*
|
|
44
|
+
* ## It needs a height
|
|
45
|
+
*
|
|
46
|
+
* Everything inside is positioned absolutely, so the box has no height of its
|
|
47
|
+
* own to take from its content. `height` is what gives it one. An image told to
|
|
48
|
+
* fill the box will fill whatever height is set here, and cropping is
|
|
49
|
+
* `resizeMode` on the image rather than anything this component does.
|
|
50
|
+
*
|
|
51
|
+
* ## Dragging, and the two ways round it
|
|
52
|
+
*
|
|
53
|
+
* The whole frame is the drag target, not just the knob — a knob is a small
|
|
54
|
+
* thing to hit on a phone and the reader's finger is already over the picture.
|
|
55
|
+
* The gesture only claims horizontal movement, so a Compare inside a scrolling
|
|
56
|
+
* page still scrolls.
|
|
57
|
+
*
|
|
58
|
+
* A drag is not available to everyone, so the seam is also `adjustable`: a
|
|
59
|
+
* screen reader moves it a `step` at a time without one, and `value` drives it
|
|
60
|
+
* from anywhere else — a button that snaps to the ends, an animation, a slider
|
|
61
|
+
* somewhere else on the screen.
|
|
62
|
+
*/
|
|
63
|
+
import { type ReactNode } from 'react';
|
|
64
|
+
import { type ViewProps } from 'react-native';
|
|
65
|
+
export type CompareOrientation = 'horizontal' | 'vertical';
|
|
66
|
+
export interface CompareProps extends Omit<ViewProps, 'children'> {
|
|
67
|
+
className?: string;
|
|
68
|
+
/**
|
|
69
|
+
* How tall the frame is, in points.
|
|
70
|
+
*
|
|
71
|
+
* Required in practice rather than in the types: both sides are positioned
|
|
72
|
+
* absolutely, so there is no content left to give the box a height of its own.
|
|
73
|
+
*/
|
|
74
|
+
height?: number;
|
|
75
|
+
/** Where the seam sits, `0` to `1`. Leave unset to let the frame track it. */
|
|
76
|
+
value?: number;
|
|
77
|
+
/** Where it starts when the frame is tracking it itself. */
|
|
78
|
+
defaultValue?: number;
|
|
79
|
+
/** Fires while the seam moves, with its new position. */
|
|
80
|
+
onValueChange?: (value: number) => void;
|
|
81
|
+
/** Fires once, when the finger is lifted. The one to persist. */
|
|
82
|
+
onValueCommit?: (value: number) => void;
|
|
83
|
+
/** Which way the seam runs. */
|
|
84
|
+
orientation?: CompareOrientation;
|
|
85
|
+
/** Freezes the seam where it is and takes it out of the accessibility tree. */
|
|
86
|
+
disabled?: boolean;
|
|
87
|
+
/** How far one screen-reader increment moves the seam, `0` to `1`. */
|
|
88
|
+
step?: number;
|
|
89
|
+
/** A tick when the seam reaches either end. */
|
|
90
|
+
haptics?: boolean;
|
|
91
|
+
children?: ReactNode;
|
|
92
|
+
}
|
|
93
|
+
declare function CompareRoot({ className, height, value, defaultValue, onValueChange, onValueCommit, orientation, disabled, step, haptics, children, ...props }: CompareProps): import("react").JSX.Element;
|
|
94
|
+
declare namespace CompareRoot {
|
|
95
|
+
var displayName: string;
|
|
96
|
+
}
|
|
97
|
+
export interface CompareAfterProps extends ViewProps {
|
|
98
|
+
className?: string;
|
|
99
|
+
children?: ReactNode;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The side the seam uncovers as it travels: the whole frame, underneath.
|
|
103
|
+
*
|
|
104
|
+
* It is drawn at full size and never clipped, so it is the one that decides
|
|
105
|
+
* what the frame looks like at either end of the travel.
|
|
106
|
+
*/
|
|
107
|
+
declare function CompareAfter({ className, children, ...props }: CompareAfterProps): import("react").JSX.Element;
|
|
108
|
+
declare namespace CompareAfter {
|
|
109
|
+
var displayName: string;
|
|
110
|
+
var layer: "base";
|
|
111
|
+
}
|
|
112
|
+
export interface CompareBeforeProps extends ViewProps {
|
|
113
|
+
className?: string;
|
|
114
|
+
children?: ReactNode;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* The side on the near edge of the seam: a window onto the content, sized to
|
|
118
|
+
* the frame.
|
|
119
|
+
*
|
|
120
|
+
* The child is given the frame's measured size in points rather than a
|
|
121
|
+
* percentage. A percentage would be a percentage *of the window*, which shrinks
|
|
122
|
+
* as the seam closes — so the image would slide and scale under the seam
|
|
123
|
+
* instead of standing still behind it, and the two halves would no longer be
|
|
124
|
+
* the same picture in the same place.
|
|
125
|
+
*/
|
|
126
|
+
declare function CompareBefore({ className, children, ...props }: CompareBeforeProps): import("react").JSX.Element;
|
|
127
|
+
declare namespace CompareBefore {
|
|
128
|
+
var displayName: string;
|
|
129
|
+
var layer: "clip";
|
|
130
|
+
}
|
|
131
|
+
export interface CompareHandleProps extends ViewProps {
|
|
132
|
+
className?: string;
|
|
133
|
+
/** Hide the two grip bars inside the knob. */
|
|
134
|
+
withGrip?: boolean;
|
|
135
|
+
/** Spoken name. */
|
|
136
|
+
accessibilityLabel?: string;
|
|
137
|
+
/** Replaces the knob. The line behind it is kept. */
|
|
138
|
+
children?: ReactNode;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* The seam: a line across the frame with a knob on it.
|
|
142
|
+
*
|
|
143
|
+
* The knob is a marker rather than the target — the drag is on the whole frame,
|
|
144
|
+
* and a 36-point circle is not something to ask a thumb to find. What it is
|
|
145
|
+
* for is saying where the seam is and that it is the thing that moves, which a
|
|
146
|
+
* bare line does not.
|
|
147
|
+
*
|
|
148
|
+
* It carries the accessibility wiring for the same reason a splitter's handle
|
|
149
|
+
* does: it is the one part of this that is a control, so it is the part that is
|
|
150
|
+
* `adjustable` and takes the increment and decrement a screen reader sends
|
|
151
|
+
* instead of a drag.
|
|
152
|
+
*/
|
|
153
|
+
declare function CompareHandle({ className, withGrip, accessibilityLabel, children, style, ...props }: CompareHandleProps): import("react").JSX.Element;
|
|
154
|
+
declare namespace CompareHandle {
|
|
155
|
+
var displayName: string;
|
|
156
|
+
var layer: "over";
|
|
157
|
+
}
|
|
158
|
+
export interface CompareLabelProps extends ViewProps {
|
|
159
|
+
className?: string;
|
|
160
|
+
/** Which side of the frame it sits on. */
|
|
161
|
+
side?: 'start' | 'end';
|
|
162
|
+
children?: ReactNode;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* A caption pinned to one corner, for saying which side is which.
|
|
166
|
+
*
|
|
167
|
+
* Worth adding wherever the two versions are not obviously an original and an
|
|
168
|
+
* edit — two dates, two settings, two models. Where they are, it is one more
|
|
169
|
+
* thing over the picture and the picture is the point.
|
|
170
|
+
*/
|
|
171
|
+
declare function CompareLabel({ className, side, children, ...props }: CompareLabelProps): import("react").JSX.Element;
|
|
172
|
+
declare namespace CompareLabel {
|
|
173
|
+
var displayName: string;
|
|
174
|
+
var layer: "over";
|
|
175
|
+
}
|
|
176
|
+
export declare const Compare: typeof CompareRoot & {
|
|
177
|
+
Before: typeof CompareBefore;
|
|
178
|
+
After: typeof CompareAfter;
|
|
179
|
+
Handle: typeof CompareHandle;
|
|
180
|
+
Label: typeof CompareLabel;
|
|
181
|
+
};
|
|
182
|
+
export {};
|
|
183
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/compare/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/planner/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,OAAO,EAYL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAML,IAAI,EAEJ,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAItB,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,0BAAuB,CAAC;AAE7D,OAAO,EAcL,KAAK,cAAc,EACnB,KAAK,UAAU,EAChB,MAAM,qBAAkB,CAAC;AAG1B,OAAO,EAML,KAAK,sBAAsB,EAC5B,MAAM,sBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/planner/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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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a flow diagram's nodes and ribbons go.
|
|
3
|
+
*
|
|
4
|
+
* Kept apart from the component for the same reason the splitter's maths is:
|
|
5
|
+
* it is the part with answers that can be checked, and a test that has to
|
|
6
|
+
* mount a chart to check them is a test nobody writes twice.
|
|
7
|
+
*
|
|
8
|
+
* ## The problem the layout is solving
|
|
9
|
+
*
|
|
10
|
+
* A node's column is decided by the flow, not by the caller — a stage that
|
|
11
|
+
* receives from another has to be drawn after it or the ribbon runs backwards.
|
|
12
|
+
* Its height is its value. Neither of those is a choice. What is left over is
|
|
13
|
+
* the *order within a column*, and that is the whole difficulty: the same graph
|
|
14
|
+
* drawn in two orders is the same numbers with a different number of crossings,
|
|
15
|
+
* and crossings are the only thing that makes one of these unreadable.
|
|
16
|
+
*
|
|
17
|
+
* There is no cheap exact answer — minimising crossings is the kind of problem
|
|
18
|
+
* that is only solved by trying — so the order is settled by relaxation. Every
|
|
19
|
+
* node is pulled towards the average height of what it connects to, the pull
|
|
20
|
+
* weakens each round, and nodes that end up overlapping are pushed apart. Six
|
|
21
|
+
* rounds is where the picture stops visibly improving.
|
|
22
|
+
*
|
|
23
|
+
* ## Why it never throws
|
|
24
|
+
*
|
|
25
|
+
* A flow that loops back on itself has no left-to-right reading at all, and the
|
|
26
|
+
* textbook answer is to refuse the graph. A chart cannot refuse: the data is
|
|
27
|
+
* usually arriving from somewhere nobody in the room controls, and a screen
|
|
28
|
+
* that crashes on a bad row is worse than one that draws the rows it can. So a
|
|
29
|
+
* link that closes a loop is dropped, counted, and reported on the layout —
|
|
30
|
+
* the caller can say so, and the rest of the diagram is still true.
|
|
31
|
+
*/
|
|
32
|
+
/** Which column a node is pushed into when the flow leaves a choice. */
|
|
33
|
+
export type SankeyAlign = 'justify' | 'left' | 'right' | 'center';
|
|
34
|
+
export interface SankeyLayoutNodeInput {
|
|
35
|
+
/** Stable key the links name. */
|
|
36
|
+
id: string;
|
|
37
|
+
/**
|
|
38
|
+
* Pins the node's total, for a stage whose links do not account for all of
|
|
39
|
+
* it — a step that also loses some of what it received to nowhere.
|
|
40
|
+
*/
|
|
41
|
+
value?: number;
|
|
42
|
+
}
|
|
43
|
+
export interface SankeyLayoutLinkInput {
|
|
44
|
+
source: string;
|
|
45
|
+
target: string;
|
|
46
|
+
value: number;
|
|
47
|
+
}
|
|
48
|
+
export interface SankeyLayoutOptions {
|
|
49
|
+
width: number;
|
|
50
|
+
height: number;
|
|
51
|
+
/** How thick a node's bar is drawn, in points. */
|
|
52
|
+
nodeWidth: number;
|
|
53
|
+
/** The gap asked for between two nodes in a column, in points. */
|
|
54
|
+
nodePadding: number;
|
|
55
|
+
align: SankeyAlign;
|
|
56
|
+
/** Relaxation rounds. More is steadier and slower; six is the useful knee. */
|
|
57
|
+
iterations: number;
|
|
58
|
+
}
|
|
59
|
+
export interface SankeyLayoutNode {
|
|
60
|
+
id: string;
|
|
61
|
+
/** Position in the input array, so a caller can find its own datum again. */
|
|
62
|
+
index: number;
|
|
63
|
+
/** Which column it landed in, counting from the left. */
|
|
64
|
+
layer: number;
|
|
65
|
+
/** What flows through it: the larger of what arrives and what leaves. */
|
|
66
|
+
value: number;
|
|
67
|
+
x0: number;
|
|
68
|
+
x1: number;
|
|
69
|
+
y0: number;
|
|
70
|
+
y1: number;
|
|
71
|
+
}
|
|
72
|
+
export interface SankeyLayoutLink {
|
|
73
|
+
index: number;
|
|
74
|
+
/**
|
|
75
|
+
* Position in the caller's link array. Not the same as `index`: links that
|
|
76
|
+
* name nothing or close a loop are dropped, so the drawn order closes up
|
|
77
|
+
* behind them while this still points at the row it came from.
|
|
78
|
+
*/
|
|
79
|
+
input: number;
|
|
80
|
+
/** Index into the laid-out nodes, not into the caller's array. */
|
|
81
|
+
source: number;
|
|
82
|
+
target: number;
|
|
83
|
+
value: number;
|
|
84
|
+
/** How thick the ribbon is, in points. */
|
|
85
|
+
width: number;
|
|
86
|
+
/** The ribbon's centre where it leaves the source, in points from the top. */
|
|
87
|
+
y0: number;
|
|
88
|
+
/** And where it meets the target. */
|
|
89
|
+
y1: number;
|
|
90
|
+
}
|
|
91
|
+
export interface SankeyLayout {
|
|
92
|
+
nodes: SankeyLayoutNode[];
|
|
93
|
+
links: SankeyLayoutLink[];
|
|
94
|
+
/** How many columns the flow turned out to need. */
|
|
95
|
+
columns: number;
|
|
96
|
+
/** Links dropped for closing a loop, naming nothing, or carrying nothing. */
|
|
97
|
+
dropped: number;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Lays out a flow diagram.
|
|
101
|
+
*
|
|
102
|
+
* Returns positions in points inside a `width` by `height` box. An input that
|
|
103
|
+
* cannot be drawn — no nodes, no room, nothing carrying a value — comes back
|
|
104
|
+
* empty rather than as a diagram of zeroes.
|
|
105
|
+
*/
|
|
106
|
+
export declare function sankeyLayout(nodeInput: readonly SankeyLayoutNodeInput[], linkInput: readonly SankeyLayoutLinkInput[], options: SankeyLayoutOptions): SankeyLayout;
|
|
107
|
+
//# sourceMappingURL=sankey-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sankey-layout.d.ts","sourceRoot":"","sources":["../../../../../src/components/sankey-chart/sankey-layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,wEAAwE;AACxE,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAElE,MAAM,WAAW,qBAAqB;IACpC,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;IACnB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,EAAE,EAAE,MAAM,CAAC;IACX,qCAAqC;IACrC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;CACjB;AAyQD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,SAAS,qBAAqB,EAAE,EAC3C,SAAS,EAAE,SAAS,qBAAqB,EAAE,EAC3C,OAAO,EAAE,mBAAmB,GAC3B,YAAY,CAwQd"}
|
|
@@ -41,7 +41,6 @@ declare const typographyVariants: import("tailwind-variants").TVReturnType<{
|
|
|
41
41
|
'body-xs': string;
|
|
42
42
|
/** Body, one step up — for a number or a name that carries the row. */
|
|
43
43
|
large: string;
|
|
44
|
-
/** Body, one step down and tighter — captions, footnotes, meta. */
|
|
45
44
|
small: string;
|
|
46
45
|
blockquote: string;
|
|
47
46
|
code: string;
|
|
@@ -91,7 +90,6 @@ declare const typographyVariants: import("tailwind-variants").TVReturnType<{
|
|
|
91
90
|
'body-xs': string;
|
|
92
91
|
/** Body, one step up — for a number or a name that carries the row. */
|
|
93
92
|
large: string;
|
|
94
|
-
/** Body, one step down and tighter — captions, footnotes, meta. */
|
|
95
93
|
small: string;
|
|
96
94
|
blockquote: string;
|
|
97
95
|
code: string;
|
|
@@ -141,7 +139,6 @@ declare const typographyVariants: import("tailwind-variants").TVReturnType<{
|
|
|
141
139
|
'body-xs': string;
|
|
142
140
|
/** Body, one step up — for a number or a name that carries the row. */
|
|
143
141
|
large: string;
|
|
144
|
-
/** Body, one step down and tighter — captions, footnotes, meta. */
|
|
145
142
|
small: string;
|
|
146
143
|
blockquote: string;
|
|
147
144
|
code: string;
|