panelui-native 0.44.0 → 0.49.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 +6 -1
- package/lib/module/components/accordion/index.js +32 -4
- package/lib/module/components/accordion/index.js.map +1 -1
- package/lib/module/components/button/index.js +83 -15
- package/lib/module/components/button/index.js.map +1 -1
- package/lib/module/components/button-group/index.js +186 -0
- package/lib/module/components/button-group/index.js.map +1 -0
- package/lib/module/components/color-picker/index.js +110 -1
- package/lib/module/components/color-picker/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 +272 -0
- package/lib/module/components/date-time-picker/index.js.map +1 -0
- package/lib/module/components/fab/index.js +514 -0
- package/lib/module/components/fab/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/markdown-editor/index.js +406 -0
- package/lib/module/components/markdown-editor/index.js.map +1 -0
- package/lib/module/components/markdown-editor/markdown-transforms.js +243 -0
- package/lib/module/components/markdown-editor/markdown-transforms.js.map +1 -0
- 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/questionnaire/index.js +1312 -0
- package/lib/module/components/questionnaire/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 +359 -41
- package/lib/module/components/tabs/index.js.map +1 -1
- package/lib/module/components/time-picker/index.js +34 -6
- package/lib/module/components/time-picker/index.js.map +1 -1
- package/lib/module/components/tree/index.js +500 -0
- package/lib/module/components/tree/index.js.map +1 -0
- package/lib/module/icons/index.js +217 -0
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/index.js +11 -2
- 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/accordion/index.d.ts +21 -0
- package/lib/typescript/src/components/accordion/index.d.ts.map +1 -1
- package/lib/typescript/src/components/button/index.d.ts +21 -0
- package/lib/typescript/src/components/button/index.d.ts.map +1 -1
- package/lib/typescript/src/components/button-group/index.d.ts +212 -0
- package/lib/typescript/src/components/button-group/index.d.ts.map +1 -0
- package/lib/typescript/src/components/color-picker/index.d.ts +82 -1
- package/lib/typescript/src/components/color-picker/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 +127 -0
- package/lib/typescript/src/components/date-time-picker/index.d.ts.map +1 -0
- package/lib/typescript/src/components/fab/index.d.ts +285 -0
- package/lib/typescript/src/components/fab/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/markdown-editor/index.d.ts +102 -0
- package/lib/typescript/src/components/markdown-editor/index.d.ts.map +1 -0
- package/lib/typescript/src/components/markdown-editor/markdown-transforms.d.ts +76 -0
- package/lib/typescript/src/components/markdown-editor/markdown-transforms.d.ts.map +1 -0
- 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/questionnaire/index.d.ts +336 -0
- package/lib/typescript/src/components/questionnaire/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 +29 -2
- package/lib/typescript/src/components/tabs/index.d.ts.map +1 -1
- package/lib/typescript/src/components/time-picker/index.d.ts +19 -1
- package/lib/typescript/src/components/time-picker/index.d.ts.map +1 -1
- package/lib/typescript/src/components/tree/index.d.ts +125 -0
- package/lib/typescript/src/components/tree/index.d.ts.map +1 -0
- package/lib/typescript/src/icons/index.d.ts +22 -0
- package/lib/typescript/src/icons/index.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +14 -5
- 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/accordion/index.tsx +48 -6
- package/src/components/button/index.tsx +97 -15
- package/src/components/button-group/index.tsx +199 -0
- package/src/components/color-picker/index.tsx +140 -3
- package/src/components/combobox/index.tsx +7 -1
- package/src/components/date-time-picker/index.tsx +411 -0
- package/src/components/fab/index.tsx +583 -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/markdown-editor/index.tsx +526 -0
- package/src/components/markdown-editor/markdown-transforms.ts +228 -0
- package/src/components/pie-chart/index.tsx +863 -0
- package/src/components/questionnaire/index.tsx +1615 -0
- package/src/components/scatter-chart/index.tsx +1401 -0
- package/src/components/tabs/index.tsx +392 -50
- package/src/components/time-picker/index.tsx +42 -6
- package/src/components/tree/index.tsx +564 -0
- package/src/icons/index.tsx +154 -0
- package/src/index.ts +142 -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,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MarkdownEditor — a field for writing markdown, and a way to see it rendered.
|
|
3
|
+
*
|
|
4
|
+
* ```tsx
|
|
5
|
+
* const [draft, setDraft] = useState('');
|
|
6
|
+
*
|
|
7
|
+
* <MarkdownEditor value={draft} onValueChange={setDraft} rows={12} />
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* ## Writing and reading are two modes, not two panes
|
|
11
|
+
*
|
|
12
|
+
* Side by side is how this is done on a desktop, and it does not survive the
|
|
13
|
+
* trip to a phone: two columns of a phone's width are two columns too narrow to
|
|
14
|
+
* read, and the keyboard covers the bottom half of the screen exactly when the
|
|
15
|
+
* writer is using it. So there is one pane and a switch — write, or read what
|
|
16
|
+
* you wrote. The toolbar carries the switch, because the toolbar is the one
|
|
17
|
+
* thing on screen in both modes.
|
|
18
|
+
*
|
|
19
|
+
* ## The toolbar edits the selection
|
|
20
|
+
*
|
|
21
|
+
* Every button here is a function of the text and where the caret is in it, and
|
|
22
|
+
* the answer that matters is not which characters get inserted but where the
|
|
23
|
+
* caret lands afterwards. Bolding a selected phrase leaves it selected, so it
|
|
24
|
+
* can be italicised next; bolding nothing puts the caret between the new
|
|
25
|
+
* markers, where the writing is about to go; and pressing the same button again
|
|
26
|
+
* takes the markers off. Those rules live in `markdown-transforms.ts` as pure
|
|
27
|
+
* functions over `(text, selection)`, away from anything to do with a field.
|
|
28
|
+
*
|
|
29
|
+
* ## Why it renders through Response
|
|
30
|
+
*
|
|
31
|
+
* The preview is `Response`, the same reader that renders a model's answer, so
|
|
32
|
+
* markdown means the same thing everywhere in the library and there is one
|
|
33
|
+
* parser to be right rather than two to keep in step. It renders through
|
|
34
|
+
* `Typography`, `CodeBlock` and `Table`, which is to say through the app's own
|
|
35
|
+
* type and colours — a preview that looked like a document viewer would be
|
|
36
|
+
* showing the writer something they are not going to ship.
|
|
37
|
+
*
|
|
38
|
+
* Nothing here reaches for a platform markdown renderer. `Text` in SwiftUI can
|
|
39
|
+
* parse markdown and Jetpack Compose's cannot, so a platform-backed editor
|
|
40
|
+
* would render on one of the two and be a plain string on the other.
|
|
41
|
+
*
|
|
42
|
+
* Works controlled (`value` + `onValueChange`) or uncontrolled (`defaultValue`).
|
|
43
|
+
*/
|
|
44
|
+
import { type ReactNode } from 'react';
|
|
45
|
+
import { View, type TextInput, type ViewProps } from 'react-native';
|
|
46
|
+
import { type TextareaProps } from '../textarea/index.js';
|
|
47
|
+
export type { EditorSelection, EditResult } from './markdown-transforms.js';
|
|
48
|
+
/** Which pane the editor is showing. */
|
|
49
|
+
export type MarkdownEditorMode = 'write' | 'preview';
|
|
50
|
+
/** A formatting action the toolbar can offer. */
|
|
51
|
+
export type MarkdownEditorAction = 'bold' | 'italic' | 'heading' | 'quote' | 'code' | 'bulletList' | 'orderedList' | 'link';
|
|
52
|
+
export interface MarkdownEditorProps extends Omit<ViewProps, 'children'> {
|
|
53
|
+
className?: string;
|
|
54
|
+
/** Controlled text. Leave unset and pass `defaultValue` to run uncontrolled. */
|
|
55
|
+
value?: string;
|
|
56
|
+
/** Starting text when uncontrolled. */
|
|
57
|
+
defaultValue?: string;
|
|
58
|
+
onValueChange?: (value: string) => void;
|
|
59
|
+
/** Controlled pane. */
|
|
60
|
+
mode?: MarkdownEditorMode;
|
|
61
|
+
/** Starting pane when uncontrolled. */
|
|
62
|
+
defaultMode?: MarkdownEditorMode;
|
|
63
|
+
onModeChange?: (mode: MarkdownEditorMode) => void;
|
|
64
|
+
/** Stop the field being edited and the toolbar being pressed. */
|
|
65
|
+
disabled?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* The parts, in the order they should stack. Left out, the editor draws its
|
|
68
|
+
* toolbar, its field and its preview in that order — which is the whole
|
|
69
|
+
* component, and the reason it usually needs no children.
|
|
70
|
+
*/
|
|
71
|
+
children?: ReactNode;
|
|
72
|
+
/** Forwarded to the field when the editor draws its own. */
|
|
73
|
+
placeholder?: string;
|
|
74
|
+
/** Height of the field, in lines. Forwarded to the field the editor draws. */
|
|
75
|
+
rows?: number;
|
|
76
|
+
}
|
|
77
|
+
export interface MarkdownEditorToolbarProps extends Omit<ViewProps, 'children'> {
|
|
78
|
+
className?: string;
|
|
79
|
+
/** Which formatting actions to offer, in the order given. */
|
|
80
|
+
actions?: MarkdownEditorAction[];
|
|
81
|
+
/**
|
|
82
|
+
* Show the write/preview switch. On by default — a preview nobody can reach
|
|
83
|
+
* is a pane that does not exist.
|
|
84
|
+
*/
|
|
85
|
+
showModeSwitch?: boolean;
|
|
86
|
+
/** Anything else to put on the row: a word count, a save state, a submit. */
|
|
87
|
+
children?: ReactNode;
|
|
88
|
+
}
|
|
89
|
+
export interface MarkdownEditorInputProps extends Omit<TextareaProps, 'value' | 'onChangeText' | 'defaultValue'> {
|
|
90
|
+
className?: string;
|
|
91
|
+
}
|
|
92
|
+
export interface MarkdownEditorPreviewProps extends Omit<ViewProps, 'children'> {
|
|
93
|
+
className?: string;
|
|
94
|
+
/** What to show when there is nothing written yet. */
|
|
95
|
+
emptyText?: string;
|
|
96
|
+
}
|
|
97
|
+
export declare const MarkdownEditor: import("react").ForwardRefExoticComponent<MarkdownEditorProps & import("react").RefAttributes<View>> & {
|
|
98
|
+
Toolbar: import("react").ForwardRefExoticComponent<MarkdownEditorToolbarProps & import("react").RefAttributes<View>>;
|
|
99
|
+
Input: import("react").ForwardRefExoticComponent<MarkdownEditorInputProps & import("react").RefAttributes<TextInput>>;
|
|
100
|
+
Preview: import("react").ForwardRefExoticComponent<MarkdownEditorPreviewProps & import("react").RefAttributes<View>>;
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/markdown-editor/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EACL,IAAI,EAEJ,KAAK,SAAS,EAEd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAmBtB,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,sBAAa,CAAC;AAW3D,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,0BAAuB,CAAC;AAEzE,wCAAwC;AACxC,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,CAAC;AAErD,iDAAiD;AACjD,MAAM,MAAM,oBAAoB,GAC5B,MAAM,GACN,QAAQ,GACR,SAAS,GACT,OAAO,GACP,MAAM,GACN,YAAY,GACZ,aAAa,GACb,MAAM,CAAC;AAwGX,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,uBAAuB;IACvB,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,uCAAuC;IACvC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClD,iEAAiE;IACjE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA0HD,MAAM,WAAW,0BAA2B,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACjC;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAmED,MAAM,WAAW,wBACf,SAAQ,IAAI,CAAC,aAAa,EAAE,OAAO,GAAG,cAAc,GAAG,cAAc,CAAC;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoDD,MAAM,WAAW,0BAA2B,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA+BD,eAAO,MAAM,cAAc;;;;CAIzB,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The edits a formatting toolbar makes, as functions of the text and where the
|
|
3
|
+
* caret is in it.
|
|
4
|
+
*
|
|
5
|
+
* Pure, and deliberately so. Every one of these takes `(text, selection)` and
|
|
6
|
+
* returns the text that should replace it together with where the selection
|
|
7
|
+
* should end up — no component, no ref, no input. What makes a formatting
|
|
8
|
+
* toolbar feel broken is never the characters it inserts; it is where the caret
|
|
9
|
+
* lands afterwards, and that is a property of these functions rather than of
|
|
10
|
+
* the field they are wired to.
|
|
11
|
+
*
|
|
12
|
+
* Three rules they all keep:
|
|
13
|
+
*
|
|
14
|
+
* - **Applying twice undoes it.** A toolbar button that only ever adds is a
|
|
15
|
+
* button you can press once, and every press after that damages the text.
|
|
16
|
+
* - **A selection stays selected.** Bolding three words and then italicising
|
|
17
|
+
* the same three has to be two presses, not a press and a re-selection.
|
|
18
|
+
* - **With nothing selected, the caret lands where the writing goes** — between
|
|
19
|
+
* the new markers rather than after them.
|
|
20
|
+
*/
|
|
21
|
+
export interface EditorSelection {
|
|
22
|
+
start: number;
|
|
23
|
+
end: number;
|
|
24
|
+
}
|
|
25
|
+
export interface EditResult {
|
|
26
|
+
text: string;
|
|
27
|
+
selection: EditorSelection;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Wraps the selection in `marker`, or unwraps it if it is already wrapped.
|
|
31
|
+
*
|
|
32
|
+
* "Already wrapped" is checked both ways round: the markers may be inside the
|
|
33
|
+
* selection (the writer selected `**bold**`) or immediately outside it (they
|
|
34
|
+
* selected `bold` in the middle of `**bold**`). Both are the same intent, and a
|
|
35
|
+
* toolbar that only recognised one of them would add a second pair of asterisks
|
|
36
|
+
* to text that already had them.
|
|
37
|
+
*/
|
|
38
|
+
export declare function toggleWrap(text: string, selection: EditorSelection, marker: string): EditResult;
|
|
39
|
+
/**
|
|
40
|
+
* Puts `prefix` on the front of every line the selection touches, or takes it
|
|
41
|
+
* off if every one of them already has it.
|
|
42
|
+
*
|
|
43
|
+
* Every one, not any one: a mixed block is a block the writer is trying to make
|
|
44
|
+
* uniform, so the useful answer there is to add rather than to remove.
|
|
45
|
+
*/
|
|
46
|
+
export declare function toggleLinePrefix(text: string, selection: EditorSelection, prefix: string): EditResult;
|
|
47
|
+
/**
|
|
48
|
+
* Numbers the lines the selection touches, or unnumbers them.
|
|
49
|
+
*
|
|
50
|
+
* Counted from one within the block rather than continuing whatever came above
|
|
51
|
+
* it: the numbers a writer types are not the numbers that get rendered — every
|
|
52
|
+
* markdown reader renumbers an ordered list from its first item — so the useful
|
|
53
|
+
* thing is for the source to read the way the output will.
|
|
54
|
+
*/
|
|
55
|
+
export declare function toggleOrderedList(text: string, selection: EditorSelection): EditResult;
|
|
56
|
+
/** Placeholder left where a link's target goes. */
|
|
57
|
+
export declare const LINK_PLACEHOLDER = "url";
|
|
58
|
+
/**
|
|
59
|
+
* Turns the selection into a link, and selects the part that still needs
|
|
60
|
+
* filling in.
|
|
61
|
+
*
|
|
62
|
+
* Which part that is depends on what was selected. With text selected, the
|
|
63
|
+
* label is written and the target is not, so the placeholder target is left
|
|
64
|
+
* selected and typing replaces it. With nothing selected there is neither, and
|
|
65
|
+
* the label comes first because it is the half the writer is thinking about.
|
|
66
|
+
*/
|
|
67
|
+
export declare function insertLink(text: string, selection: EditorSelection): EditResult;
|
|
68
|
+
/**
|
|
69
|
+
* Puts the selected lines in a fence, or takes them out of one.
|
|
70
|
+
*
|
|
71
|
+
* A fence is the one construct that has to sit on lines of its own, so this
|
|
72
|
+
* makes room for itself: a blank line before it when it is not already at the
|
|
73
|
+
* start of a paragraph, and one after it at the end.
|
|
74
|
+
*/
|
|
75
|
+
export declare function toggleFence(text: string, selection: EditorSelection): EditResult;
|
|
76
|
+
//# sourceMappingURL=markdown-transforms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-transforms.d.ts","sourceRoot":"","sources":["../../../../../src/components/markdown-editor/markdown-transforms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,eAAe,CAAC;CAC5B;AAaD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,eAAe,EAC1B,MAAM,EAAE,MAAM,GACb,UAAU,CAmCZ;AAiCD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,eAAe,EAC1B,MAAM,EAAE,MAAM,GACb,UAAU,CASZ;AAKD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,eAAe,GACzB,UAAU,CAQZ;AAMD,mDAAmD;AACnD,eAAO,MAAM,gBAAgB,QAAQ,CAAC;AAEtC;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,UAAU,CAY/E;AAMD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,UAAU,CAiBhF"}
|
|
@@ -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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"}
|