@allxsmith/bestax-bulma 5.61.0 → 5.63.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/dist/bestax.css +1 -1
- package/dist/bestax.css.map +1 -1
- package/dist/esm/components/EmptyState.js +2 -6
- package/dist/esm/components/EmptyState.js.map +1 -1
- package/dist/esm/components/Timeline.js +5 -9
- package/dist/esm/components/Timeline.js.map +1 -1
- package/dist/esm/components/TreeView.js +16 -16
- package/dist/esm/components/TreeView.js.map +1 -1
- package/dist/esm/elements/Buttons.js +2 -0
- package/dist/esm/elements/Buttons.js.map +1 -1
- package/dist/esm/elements/CopyButton.js +132 -0
- package/dist/esm/elements/CopyButton.js.map +1 -0
- package/dist/esm/elements/DescriptionList.js +1 -5
- package/dist/esm/elements/DescriptionList.js.map +1 -1
- package/dist/esm/elements/Stat.js +196 -0
- package/dist/esm/elements/Stat.js.map +1 -0
- package/dist/esm/elements/Stats.js +48 -0
- package/dist/esm/elements/Stats.js.map +1 -0
- package/dist/esm/elements/statContext.js +10 -0
- package/dist/esm/elements/statContext.js.map +1 -0
- package/dist/esm/form/Combobox.js +10 -14
- package/dist/esm/form/Combobox.js.map +1 -1
- package/dist/esm/form/Field.js.map +1 -1
- package/dist/esm/form/TreeSelect.js +395 -0
- package/dist/esm/form/TreeSelect.js.map +1 -0
- package/dist/esm/form/_pickerInternals/PickerPopover.js +5 -1
- package/dist/esm/form/_pickerInternals/PickerPopover.js.map +1 -1
- package/dist/esm/form/_selectInternals/DialogSelect.js +208 -0
- package/dist/esm/form/_selectInternals/DialogSelect.js.map +1 -0
- package/dist/esm/form/_selectInternals/ValueTags.js +28 -0
- package/dist/esm/form/_selectInternals/ValueTags.js.map +1 -0
- package/dist/esm/helpers/checkIcon.js +20 -0
- package/dist/esm/helpers/checkIcon.js.map +1 -0
- package/dist/esm/helpers/isGiven.js +13 -0
- package/dist/esm/helpers/isGiven.js.map +1 -0
- package/dist/esm/helpers/statusRegion.js +3 -3
- package/dist/esm/helpers/treeData.js +97 -0
- package/dist/esm/helpers/treeData.js.map +1 -0
- package/dist/esm/helpers/useClipboard.js +176 -0
- package/dist/esm/helpers/useClipboard.js.map +1 -0
- package/dist/esm/helpers/useComboboxEngine.js +2 -2
- package/dist/esm/helpers/useComboboxEngine.js.map +1 -1
- package/dist/esm/helpers/useControlled.js +30 -0
- package/dist/esm/helpers/useControlled.js.map +1 -0
- package/dist/esm/helpers/useTreeView.js +15 -13
- package/dist/esm/helpers/useTreeView.js.map +1 -1
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +10605 -9380
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +5 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/types/elements/Buttons.d.ts +1 -0
- package/dist/types/elements/CopyButton.d.ts +105 -0
- package/dist/types/elements/Stat.d.ts +242 -0
- package/dist/types/elements/Stats.d.ts +40 -0
- package/dist/types/elements/statContext.d.ts +18 -0
- package/dist/types/form/Field.d.ts +1 -1
- package/dist/types/form/TreeSelect.d.ts +308 -0
- package/dist/types/form/_pickerInternals/PickerPopover.d.ts +8 -0
- package/dist/types/form/_selectInternals/DialogSelect.d.ts +86 -0
- package/dist/types/form/_selectInternals/ValueTags.d.ts +40 -0
- package/dist/types/helpers/checkIcon.d.ts +10 -0
- package/dist/types/helpers/isGiven.d.ts +7 -0
- package/dist/types/helpers/treeData.d.ts +48 -0
- package/dist/types/helpers/useClipboard.d.ts +65 -0
- package/dist/types/helpers/useControlled.d.ts +14 -0
- package/dist/types/helpers/useTreeView.d.ts +30 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types-cjs/elements/Buttons.d.ts +1 -0
- package/dist/types-cjs/elements/CopyButton.d.ts +105 -0
- package/dist/types-cjs/elements/Stat.d.ts +242 -0
- package/dist/types-cjs/elements/Stats.d.ts +40 -0
- package/dist/types-cjs/elements/statContext.d.ts +18 -0
- package/dist/types-cjs/form/Field.d.ts +1 -1
- package/dist/types-cjs/form/TreeSelect.d.ts +308 -0
- package/dist/types-cjs/form/_pickerInternals/PickerPopover.d.ts +8 -0
- package/dist/types-cjs/form/_selectInternals/DialogSelect.d.ts +86 -0
- package/dist/types-cjs/form/_selectInternals/ValueTags.d.ts +40 -0
- package/dist/types-cjs/helpers/checkIcon.d.ts +10 -0
- package/dist/types-cjs/helpers/isGiven.d.ts +7 -0
- package/dist/types-cjs/helpers/treeData.d.ts +48 -0
- package/dist/types-cjs/helpers/useClipboard.d.ts +65 -0
- package/dist/types-cjs/helpers/useControlled.d.ts +14 -0
- package/dist/types-cjs/helpers/useTreeView.d.ts +30 -0
- package/dist/types-cjs/index.d.ts +6 -0
- package/dist/versions/bestax-no-dark-mode.css +1 -1
- package/dist/versions/bestax-no-dark-mode.css.map +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
- package/dist/versions/bestax-no-helpers.css +1 -1
- package/dist/versions/bestax-no-helpers.css.map +1 -1
- package/dist/versions/bestax-prefixed.css +1 -1
- package/dist/versions/bestax-prefixed.css.map +1 -1
- package/package.json +1 -1
- package/src/scss/elements/_index.scss +1 -0
- package/src/scss/elements/_stat.scss +153 -0
- package/src/scss/form/_index.scss +1 -0
- package/src/scss/form/_picker-popover.scss +6 -0
- package/src/scss/form/_treeselect.scss +146 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { BulmaClassesProps } from '../helpers/useBulmaClasses.js';
|
|
3
|
+
import type { FormFieldProps } from './fieldProps.js';
|
|
4
|
+
import type { PickerPosition } from './_pickerInternals/pickerTypes.js';
|
|
5
|
+
/**
|
|
6
|
+
* One node in a TreeSelect's `data`: Combobox's item fields plus
|
|
7
|
+
* TreeView.Item's, with `children` for the nodes under it.
|
|
8
|
+
*/
|
|
9
|
+
export interface TreeItemData {
|
|
10
|
+
/** **Required.** What the value holds and `name` posts. Unique in the whole tree. */
|
|
11
|
+
value: string;
|
|
12
|
+
/** What the row, the field and the tags show, and what search matches. The `value` when it's left out. */
|
|
13
|
+
label?: string;
|
|
14
|
+
/** Reachable, but never picked, checked, opened or closed. */
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
/** A picture before the label: an `Icon` name, or a node. Hidden from assistive tech. */
|
|
17
|
+
icon?: React.ReactNode;
|
|
18
|
+
/** The nodes under this one. */
|
|
19
|
+
children?: TreeItemData[];
|
|
20
|
+
/** Shows the node as a parent before its children are known, for a branch that loads when it opens. */
|
|
21
|
+
hasChildren?: boolean;
|
|
22
|
+
/** Its children are on their way: an open branch ends in a row that says so, and the live region says it too. */
|
|
23
|
+
isLoading?: boolean;
|
|
24
|
+
/** Its children didn't load: an open branch ends in this message, with a Retry button when there's an `onRetry`. */
|
|
25
|
+
loadError?: React.ReactNode;
|
|
26
|
+
/** Called by the Retry button on a failed load's row. Set `isLoading` while the retry runs. */
|
|
27
|
+
onRetry?: () => void;
|
|
28
|
+
}
|
|
29
|
+
/** What a checked branch puts in the value a check makes. */
|
|
30
|
+
export type TreeSelectCheckedStrategy = 'child' | 'parent' | 'all';
|
|
31
|
+
/** The visible and accessible strings, in your app's language. */
|
|
32
|
+
export interface TreeSelectLabels {
|
|
33
|
+
/**
|
|
34
|
+
* Names the panel and the tree in it.
|
|
35
|
+
* @defaultValue the field's label
|
|
36
|
+
*/
|
|
37
|
+
choose?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Names the search box.
|
|
40
|
+
* @defaultValue 'Search'
|
|
41
|
+
*/
|
|
42
|
+
search?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Names the clear button.
|
|
45
|
+
* @defaultValue 'Clear'
|
|
46
|
+
*/
|
|
47
|
+
clear?: string;
|
|
48
|
+
/**
|
|
49
|
+
* What a loading branch's row says, as on TreeView.
|
|
50
|
+
* @defaultValue 'Loading…'
|
|
51
|
+
*/
|
|
52
|
+
loading?: string;
|
|
53
|
+
/**
|
|
54
|
+
* The Retry button's text on a failed load's row, as on TreeView.
|
|
55
|
+
* @defaultValue 'Retry'
|
|
56
|
+
*/
|
|
57
|
+
retry?: string;
|
|
58
|
+
/**
|
|
59
|
+
* What the live region says when an open branch starts loading, built
|
|
60
|
+
* from its name, as on TreeView.
|
|
61
|
+
* @defaultValue name => `Loading ${name}`
|
|
62
|
+
*/
|
|
63
|
+
loadingAnnouncement?: (name: string) => string;
|
|
64
|
+
/**
|
|
65
|
+
* What the live region says when that load finishes, as on TreeView.
|
|
66
|
+
* @defaultValue name => `${name} loaded`
|
|
67
|
+
*/
|
|
68
|
+
loadedAnnouncement?: (name: string) => string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* What every TreeSelect takes. The helper props and the other attributes
|
|
72
|
+
* land on the root `<div>`, as Combobox's do, and the `ref` on the field.
|
|
73
|
+
*/
|
|
74
|
+
interface TreeSelectBaseProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'onChange' | 'defaultValue' | 'children'>, Omit<BulmaClassesProps, 'color'>, FormFieldProps {
|
|
75
|
+
/** **Required.** The tree, as nodes nested through `children`. */
|
|
76
|
+
data: TreeItemData[];
|
|
77
|
+
/**
|
|
78
|
+
* The field's label, which names the field through `htmlFor`, and the
|
|
79
|
+
* panel and the tree in it through `aria-labelledby`. Dropped inside an
|
|
80
|
+
* outer `Field`, whose label names them instead.
|
|
81
|
+
*/
|
|
82
|
+
label?: React.ReactNode;
|
|
83
|
+
/** The field's `id`, which the label then points at. The panel's is this one with `-panel` after it. */
|
|
84
|
+
id?: string;
|
|
85
|
+
/** Names the field, and the panel and the tree, in place of a `label`. */
|
|
86
|
+
'aria-label'?: string;
|
|
87
|
+
/** The ids of what names the field, and the panel and the tree, in place of a `label`. */
|
|
88
|
+
'aria-labelledby'?: string;
|
|
89
|
+
/** The ids of what describes the field, ahead of the tags. */
|
|
90
|
+
'aria-describedby'?: string;
|
|
91
|
+
/** The open branches' values when you hold the state, as TreeView's `expanded`. */
|
|
92
|
+
expanded?: string[];
|
|
93
|
+
/** The branches open to begin with, when TreeSelect holds its own state. */
|
|
94
|
+
defaultExpanded?: string[];
|
|
95
|
+
/**
|
|
96
|
+
* Called with the new list whenever a branch opens or closes, opening the
|
|
97
|
+
* panel on the picked item's branch included. Fetch a lazy branch's
|
|
98
|
+
* children from here. The branches a search opens aren't in it.
|
|
99
|
+
*/
|
|
100
|
+
onExpandedChange?: (expanded: string[]) => void;
|
|
101
|
+
/** Whether the panel is open, controlled: opening and closing then only call `onOpenChange`. */
|
|
102
|
+
open?: boolean;
|
|
103
|
+
/** The panel is open to begin with. */
|
|
104
|
+
defaultOpen?: boolean;
|
|
105
|
+
/** Called with the new state when the panel opens or closes. */
|
|
106
|
+
onOpenChange?: (open: boolean) => void;
|
|
107
|
+
/**
|
|
108
|
+
* Puts a search box at the top of the panel. It matches labels, keeps a
|
|
109
|
+
* match's ancestors and the nodes under it, and opens every branch with a
|
|
110
|
+
* match. A printable key on the field opens the panel with it in the box,
|
|
111
|
+
* and the search empties when the panel closes.
|
|
112
|
+
*/
|
|
113
|
+
searchable?: boolean;
|
|
114
|
+
/** The search text when you hold the state. */
|
|
115
|
+
query?: string;
|
|
116
|
+
/** The search text to begin with. */
|
|
117
|
+
defaultQuery?: string;
|
|
118
|
+
/** Called with the search text as it changes. */
|
|
119
|
+
onQueryChange?: (query: string) => void;
|
|
120
|
+
/**
|
|
121
|
+
* Whether a node matches the search, in place of the locale-aware match on
|
|
122
|
+
* its label. It's handed the search text trimmed, the node, and its path
|
|
123
|
+
* from the top node down, the node last, as Cascader's `filter` is. A
|
|
124
|
+
* match's ancestors stay either way. The search runs again when the search
|
|
125
|
+
* text or `data` changes, not when only this does, so one written inline
|
|
126
|
+
* costs nothing.
|
|
127
|
+
*/
|
|
128
|
+
filter?: (query: string, item: TreeItemData, path: TreeItemData[]) => boolean;
|
|
129
|
+
/** What the panel shows when the search matches nothing, such as "No folders match". Announced once. */
|
|
130
|
+
empty?: React.ReactNode;
|
|
131
|
+
/** Renders a row's content in place of its label. The field and the tags still show the label. */
|
|
132
|
+
itemTemplate?: (item: TreeItemData) => React.ReactNode;
|
|
133
|
+
/** What the field shows while nothing is picked. */
|
|
134
|
+
placeholder?: string;
|
|
135
|
+
/** A form field name. A hidden input posts the value, or one per value in the checkbox modes. */
|
|
136
|
+
name?: string;
|
|
137
|
+
/** The id of the form the hidden inputs belong to, when it isn't an ancestor. */
|
|
138
|
+
form?: string;
|
|
139
|
+
/**
|
|
140
|
+
* A value is needed: the field is `aria-required`, and the form won't
|
|
141
|
+
* submit while nothing is picked. The browser's message points at the
|
|
142
|
+
* field, which shows focus, and the next key goes to it.
|
|
143
|
+
*/
|
|
144
|
+
required?: boolean;
|
|
145
|
+
/** The field can't be used: it can't be focused or opened, its tags lose their buttons, and its hidden inputs don't post. */
|
|
146
|
+
disabled?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Shows a clear button at the field's inline end while something it can
|
|
149
|
+
* take off is picked. It leaves checked disabled items, which no control
|
|
150
|
+
* unchecks.
|
|
151
|
+
*/
|
|
152
|
+
clearable?: boolean;
|
|
153
|
+
/** Bulma color modifier for the field. */
|
|
154
|
+
color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';
|
|
155
|
+
/** The field's size, which the tree in the panel follows. */
|
|
156
|
+
size?: 'small' | 'medium' | 'large';
|
|
157
|
+
/** Rounds the field's corners (Bulma's `is-rounded`). */
|
|
158
|
+
isRounded?: boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Where the panel opens, relative to the field, as on the pickers.
|
|
161
|
+
* @defaultValue 'bottom-left'
|
|
162
|
+
*/
|
|
163
|
+
position?: PickerPosition;
|
|
164
|
+
/** Renders the panel through a portal, into a `ConfigProvider`'s `portalContainer`, `document.body` by default. */
|
|
165
|
+
appendToBody?: boolean;
|
|
166
|
+
/** The visible and accessible strings, in your app's language. */
|
|
167
|
+
labels?: TreeSelectLabels;
|
|
168
|
+
}
|
|
169
|
+
/** Props for a TreeSelect that picks one item. */
|
|
170
|
+
export interface TreeSelectSingleProps extends TreeSelectBaseProps {
|
|
171
|
+
/**
|
|
172
|
+
* `'single'`: one item, picked with Enter, Space or a click on its row.
|
|
173
|
+
* `'checkbox'`: any number, with a box on every item. A check reaches every
|
|
174
|
+
* enabled item under it, and a parent with some of them checked is mixed.
|
|
175
|
+
* `'checkbox-independent'`: any number, each box checking its own item, so
|
|
176
|
+
* a parent means the parent alone (Mantine's and Ant Design's
|
|
177
|
+
* `checkStrictly`). The checkbox modes show the value as tags.
|
|
178
|
+
*/
|
|
179
|
+
selectionMode?: 'single';
|
|
180
|
+
/**
|
|
181
|
+
* The value when you hold the state: in `'single'` the picked item's
|
|
182
|
+
* value, or `null` for none, and in the checkbox modes the checked values.
|
|
183
|
+
* In `'checkbox'` a parent's value checks its whole branch, so the list any
|
|
184
|
+
* `checkedStrategy` gives checks the same boxes.
|
|
185
|
+
*/
|
|
186
|
+
value?: string | null;
|
|
187
|
+
/** The value to begin with, when TreeSelect holds its own state: a value or `null`, or a list in the checkbox modes. */
|
|
188
|
+
defaultValue?: string | null;
|
|
189
|
+
/**
|
|
190
|
+
* Called with the new value: in `'single'` the picked item's value, or
|
|
191
|
+
* `null` when it's cleared, and in the checkbox modes the new list, after a
|
|
192
|
+
* check, an uncheck, a tag's button or the clear button, each shaped by
|
|
193
|
+
* `checkedStrategy`. A reset of the field's form calls it too, with
|
|
194
|
+
* `defaultValue` as it was given, or with `null` or `[]` when you hold
|
|
195
|
+
* the value, for you to set.
|
|
196
|
+
*/
|
|
197
|
+
onChange?: (value: string | null) => void;
|
|
198
|
+
/**
|
|
199
|
+
* A parent's row picks the parent. `false` makes the row, Enter and Space
|
|
200
|
+
* open it instead, so only leaves are picked.
|
|
201
|
+
* @defaultValue true
|
|
202
|
+
*/
|
|
203
|
+
parentsSelectable?: boolean;
|
|
204
|
+
/**
|
|
205
|
+
* Closes the panel after a pick and puts focus back on the field.
|
|
206
|
+
* @defaultValue true
|
|
207
|
+
*/
|
|
208
|
+
closeOnSelect?: boolean;
|
|
209
|
+
/** @internal Read with the checkbox modes only. */
|
|
210
|
+
checkedStrategy?: never;
|
|
211
|
+
/** @internal Read with the checkbox modes only. */
|
|
212
|
+
ariaCloseLabel?: never;
|
|
213
|
+
}
|
|
214
|
+
/** Props for a TreeSelect with a box on every item. */
|
|
215
|
+
export interface TreeSelectCheckboxProps extends TreeSelectBaseProps {
|
|
216
|
+
/**
|
|
217
|
+
* `'checkbox'`: a check reaches every enabled item under it, and a parent
|
|
218
|
+
* with some of them checked is mixed. `'checkbox-independent'`: each box
|
|
219
|
+
* checks its own item, so a parent means the parent alone.
|
|
220
|
+
*/
|
|
221
|
+
selectionMode: 'checkbox' | 'checkbox-independent';
|
|
222
|
+
/**
|
|
223
|
+
* The checked values when you hold the state. In `'checkbox'`, a parent's
|
|
224
|
+
* value checks its whole branch, so the list any `checkedStrategy` gives
|
|
225
|
+
* checks the same boxes.
|
|
226
|
+
*/
|
|
227
|
+
value?: string[];
|
|
228
|
+
/** The values checked to begin with, when TreeSelect holds its own state. */
|
|
229
|
+
defaultValue?: string[];
|
|
230
|
+
/**
|
|
231
|
+
* Called with the new list after a check, an uncheck, a tag's button or
|
|
232
|
+
* the clear button, shaped by `checkedStrategy`, and after a reset of the
|
|
233
|
+
* field's form, with `defaultValue` as given, or `[]` when you hold the
|
|
234
|
+
* value.
|
|
235
|
+
*/
|
|
236
|
+
onChange?: (value: string[]) => void;
|
|
237
|
+
/**
|
|
238
|
+
* What a checked branch puts in the value, in `'checkbox'`: `'child'` its
|
|
239
|
+
* leaves, `'parent'` its topmost checked item, `'all'` every checked item,
|
|
240
|
+
* parents included. A checked disabled item is in all three, since only
|
|
241
|
+
* its own value checks it. It shapes the value a check, an uncheck, a
|
|
242
|
+
* tag's button or the clear button makes, which `onChange` reports, and
|
|
243
|
+
* not `defaultValue`, a value you pass or the one a form reset puts back.
|
|
244
|
+
* The tags and the hidden
|
|
245
|
+
* inputs show the value as it's held, so a value you pass shows as you
|
|
246
|
+
* pass it, and a branch that loads later changes nothing the form posts.
|
|
247
|
+
* `'checkbox-independent'` always reports exactly the checked items.
|
|
248
|
+
* @defaultValue 'child'
|
|
249
|
+
*/
|
|
250
|
+
checkedStrategy?: TreeSelectCheckedStrategy;
|
|
251
|
+
/** Names each tag's button, in place of "Remove" and the item's label, as on Combobox. */
|
|
252
|
+
ariaCloseLabel?: string;
|
|
253
|
+
/** @internal Read with `'single'` only. */
|
|
254
|
+
parentsSelectable?: never;
|
|
255
|
+
/** @internal Read with `'single'` only: the panel stays open while boxes are checked. */
|
|
256
|
+
closeOnSelect?: never;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Props for the TreeSelect component. The helper props and the other
|
|
260
|
+
* attributes land on the `div.tree-select` around the field, and the `ref`
|
|
261
|
+
* on the field. It renders the `Field` and the label itself, unless an outer
|
|
262
|
+
* `Field` already does.
|
|
263
|
+
*
|
|
264
|
+
* @extraProp {React.Ref<HTMLInputElement>} [ref] - Ref forwarded to the field, the read-only `<input role="combobox">`.
|
|
265
|
+
*/
|
|
266
|
+
export type TreeSelectProps = TreeSelectSingleProps | TreeSelectCheckboxProps;
|
|
267
|
+
/**
|
|
268
|
+
* The `TreeSelect` component is a form field whose options are a tree, such as categories, places or teams: it opens a panel holding a real `TreeView`, picks one item or checks a branch at a time, and searches labels.
|
|
269
|
+
*
|
|
270
|
+
* The field is a read-only `role="combobox"` that opens a dialog, wired as
|
|
271
|
+
* DateInput's is, so focus moves into the tree for real and the tree keeps
|
|
272
|
+
* TreeView's keys, type-ahead and spoken output. The tree is given as `data`,
|
|
273
|
+
* so the field and the tags can name what's picked while the panel is shut,
|
|
274
|
+
* and on the server.
|
|
275
|
+
*
|
|
276
|
+
* `selectionMode` picks the kind. `'single'` picks one item and closes. With
|
|
277
|
+
* `'checkbox'`, a check reaches every enabled item under it, closed or hidden
|
|
278
|
+
* by a search, and `checkedStrategy` decides what the value holds: the
|
|
279
|
+
* leaves, the topmost checked items or every one. With
|
|
280
|
+
* `'checkbox-independent'`, each box is its own item's, so a parent means
|
|
281
|
+
* itself alone (Mantine's and Ant Design's `checkStrictly`). The value shows
|
|
282
|
+
* as tags under the field.
|
|
283
|
+
*
|
|
284
|
+
* A value no node has is kept and shown as it is, with a warning in
|
|
285
|
+
* development, so a value under a branch that hasn't loaded survives until
|
|
286
|
+
* it does.
|
|
287
|
+
*
|
|
288
|
+
* @function
|
|
289
|
+
* @param {TreeSelectProps} props - Props for the TreeSelect component.
|
|
290
|
+
* @param {React.Ref<HTMLInputElement>} ref - Forwarded ref to the field.
|
|
291
|
+
* @returns {JSX.Element} The field, its tags and its panel, in a `Field` with the label unless one is around it.
|
|
292
|
+
* @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/combobox/ | APG Combobox Pattern}
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* <TreeSelect
|
|
296
|
+
* label="Save to"
|
|
297
|
+
* data={[
|
|
298
|
+
* { value: 'docs', label: 'Documents', children: [{ value: 'invoices', label: 'Invoices' }] },
|
|
299
|
+
* { value: 'photos', label: 'Photos' },
|
|
300
|
+
* ]}
|
|
301
|
+
* searchable
|
|
302
|
+
* />
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* <TreeSelect label="Regions" selectionMode="checkbox" checkedStrategy="parent" data={regions} />
|
|
306
|
+
*/
|
|
307
|
+
export declare const TreeSelect: React.ForwardRefExoticComponent<TreeSelectProps & React.RefAttributes<HTMLInputElement>>;
|
|
308
|
+
export default TreeSelect;
|
|
@@ -35,6 +35,14 @@ export interface PickerPopoverProps {
|
|
|
35
35
|
* `LocaleProvider`'s: the picker's own, from `usePickerLocaleScope`.
|
|
36
36
|
*/
|
|
37
37
|
localeScope?: PortalLocale;
|
|
38
|
+
/**
|
|
39
|
+
* At least as wide as the anchor: in place through its partial's
|
|
40
|
+
* `has-anchor-width` rule, which needs the anchor to be the element it's
|
|
41
|
+
* placed against, and portaled through the anchor's width set inline.
|
|
42
|
+
*/
|
|
43
|
+
matchWidth?: boolean;
|
|
44
|
+
/** Placed again after each render, for content that changes size while it's open. */
|
|
45
|
+
followContent?: boolean;
|
|
38
46
|
}
|
|
39
47
|
export declare const PickerPopover: React.FC<PickerPopoverProps>;
|
|
40
48
|
export default PickerPopover;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type BulmaClassesProps } from '../../helpers/useBulmaClasses.js';
|
|
3
|
+
import type { FormFieldProps } from '../fieldProps.js';
|
|
4
|
+
import { type PickerPosition } from '../_pickerInternals/pickerTypes.js';
|
|
5
|
+
/** What names the panel, for what's in it to take as well. */
|
|
6
|
+
export interface PanelName {
|
|
7
|
+
'aria-label'?: string;
|
|
8
|
+
'aria-labelledby'?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Props for the field a tree picker opens its panel from. */
|
|
11
|
+
export interface DialogSelectProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'onChange' | 'defaultValue' | 'children'>, Omit<BulmaClassesProps, 'color'>, FormFieldProps {
|
|
12
|
+
/** The component's name, for development warnings. */
|
|
13
|
+
component: string;
|
|
14
|
+
/** The root's own class, before any prefix, such as `tree-select`. */
|
|
15
|
+
rootClass: string;
|
|
16
|
+
/** The panel's own class, beside `picker-popover`, before any prefix. */
|
|
17
|
+
panelClass: string;
|
|
18
|
+
/** What the field shows. */
|
|
19
|
+
text: string;
|
|
20
|
+
/** What `name` posts, a hidden input each. */
|
|
21
|
+
values: string[];
|
|
22
|
+
/** Something is picked: `required` is met, and the clear button shows. */
|
|
23
|
+
hasValue: boolean;
|
|
24
|
+
/** Whether the panel is open. */
|
|
25
|
+
open: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Asked to open or close the panel: by a click on the field, its keys,
|
|
28
|
+
* Escape, Alt+Up, a press outside and the clear button.
|
|
29
|
+
*/
|
|
30
|
+
onOpenChange: (open: boolean) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Called once a reset of the field's form has gone ahead, so the picker
|
|
33
|
+
* can put its value back.
|
|
34
|
+
*/
|
|
35
|
+
onFormReset: () => void;
|
|
36
|
+
/**
|
|
37
|
+
* A printable key on the field. Returns whether it used the key, as a
|
|
38
|
+
* search box opening with it does.
|
|
39
|
+
*/
|
|
40
|
+
onPrintableKey?: (key: string) => boolean;
|
|
41
|
+
/** Empties the value, from the clear button. */
|
|
42
|
+
onClear: () => void;
|
|
43
|
+
/** Shows the clear button while something is picked. */
|
|
44
|
+
clearable?: boolean;
|
|
45
|
+
/** Names the clear button. */
|
|
46
|
+
clearLabel: string;
|
|
47
|
+
/** Names the panel in place of the field's label. */
|
|
48
|
+
chooseLabel?: string;
|
|
49
|
+
placeholder?: string;
|
|
50
|
+
name?: string;
|
|
51
|
+
form?: string;
|
|
52
|
+
required?: boolean;
|
|
53
|
+
/** Already including a disabled `Fieldset` around it. */
|
|
54
|
+
disabled: boolean;
|
|
55
|
+
color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';
|
|
56
|
+
size?: 'small' | 'medium' | 'large';
|
|
57
|
+
isRounded?: boolean;
|
|
58
|
+
position?: PickerPosition;
|
|
59
|
+
appendToBody?: boolean;
|
|
60
|
+
/** Holds the field, which focus goes back to. */
|
|
61
|
+
inputRef: React.RefObject<HTMLInputElement | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Set on the field: the picker's callback that fills `inputRef` and the
|
|
64
|
+
* ref its caller gave.
|
|
65
|
+
*/
|
|
66
|
+
fieldRef: React.RefCallback<HTMLInputElement>;
|
|
67
|
+
/** The ids of the tags that describe the field. */
|
|
68
|
+
describedBy?: string;
|
|
69
|
+
/** Shown under the field, inside its Field: the tags. */
|
|
70
|
+
below?: React.ReactNode;
|
|
71
|
+
/** Selects what takes focus as the panel opens. */
|
|
72
|
+
initialFocusSelector?: string;
|
|
73
|
+
/** The panel's content, handed the panel's name. */
|
|
74
|
+
children: (name: PanelName) => React.ReactNode;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A read-only `role="combobox"` field, wired as the date pickers' are, that
|
|
78
|
+
* opens a `PickerPopover` dialog panel: in a `Field` of its own unless one is
|
|
79
|
+
* around it, with a chevron at its inline end, a clear button, the hidden
|
|
80
|
+
* inputs for `name` and what the browser's `required` check reads. A click,
|
|
81
|
+
* Enter, Space, Down or Alt+Down opens the panel, which holds focus, as the
|
|
82
|
+
* date pickers' does: Tab and Shift+Tab wrap inside it. Escape and Alt+Up
|
|
83
|
+
* close it and put focus back on the field, and a press outside closes it
|
|
84
|
+
* where the press put focus.
|
|
85
|
+
*/
|
|
86
|
+
export declare function DialogSelect({ component, rootClass, panelClass, text, values, hasValue, open, onOpenChange, onFormReset, onPrintableKey, onClear, clearable, clearLabel, chooseLabel, placeholder, name, form, required, disabled, color, size, isRounded, position, appendToBody, inputRef, fieldRef, describedBy, below, initialFocusSelector, children, label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName, className, id, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, ...props }: DialogSelectProps): React.JSX.Element;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** Props for the tags of a field holding several values. */
|
|
2
|
+
export interface ValueTagsProps {
|
|
3
|
+
/** The values, in the order they show. */
|
|
4
|
+
values: string[];
|
|
5
|
+
/** The id of each tag's label, from `tagIds`, which the field's description lists. */
|
|
6
|
+
ids: string[];
|
|
7
|
+
/** What a value shows. */
|
|
8
|
+
labelFor: (value: string) => string;
|
|
9
|
+
/** The field can't be used, so the tags have no buttons. */
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Names each button in place of "Remove" and the value's label. The
|
|
13
|
+
* button is then described by its tag's label, so it still says which.
|
|
14
|
+
*/
|
|
15
|
+
ariaCloseLabel?: string;
|
|
16
|
+
/** Called with a value when its tag's button is pressed. */
|
|
17
|
+
onRemove: (value: string) => void;
|
|
18
|
+
/** Whether a value's tag has a button. Every tag has one without it. */
|
|
19
|
+
removable?: (value: string) => boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The values of a field holding several, as Bulma tags under it, each with a
|
|
23
|
+
* `Delete` that takes its value off. Nothing while there are none.
|
|
24
|
+
*/
|
|
25
|
+
export declare function ValueTags({ values, ids, labelFor, disabled, ariaCloseLabel, onRemove, removable, }: ValueTagsProps): import("react").JSX.Element | null;
|
|
26
|
+
/** The ids `ValueTags` gives its labels, built from one id of the field's. */
|
|
27
|
+
export declare const tagIds: (base: string, values: string[]) => string[];
|
|
28
|
+
/** Props for the hidden inputs that post a field's values. */
|
|
29
|
+
export interface HiddenValuesProps {
|
|
30
|
+
/** The form field name. Nothing renders without one. */
|
|
31
|
+
name?: string;
|
|
32
|
+
/** One hidden input each. */
|
|
33
|
+
values: string[];
|
|
34
|
+
/** The id of the form they post with, for a field outside it. */
|
|
35
|
+
form?: string;
|
|
36
|
+
/** They don't post, as a disabled field's value doesn't. */
|
|
37
|
+
disabled?: boolean;
|
|
38
|
+
}
|
|
39
|
+
/** A hidden input for each value, so a form posts them under `name`. */
|
|
40
|
+
export declare function HiddenValues({ name, values, form, disabled, }: HiddenValuesProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A check mark, 1em square and drawn in `currentColor`, so it takes the text
|
|
3
|
+
* color around it, the system's in forced colors included. Combobox draws it
|
|
4
|
+
* beside a chosen item, and CopyButton after a copy. It's decorative: put it
|
|
5
|
+
* inside something `aria-hidden`.
|
|
6
|
+
*
|
|
7
|
+
* @function CheckIcon
|
|
8
|
+
* @returns The check mark's `<svg>`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function CheckIcon(): import("react").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* INTERNAL, deliberately not exported from `src/index.ts`. Whether a prop
|
|
4
|
+
* was given something to render: `undefined`, `null`, a boolean and `''`
|
|
5
|
+
* weren't, and `0` was, since React renders it.
|
|
6
|
+
*/
|
|
7
|
+
export declare const isGiven: (node: ReactNode) => boolean;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { TreeItemData, TreeSelectCheckedStrategy } from '../form/TreeSelect.js';
|
|
2
|
+
import { type TreeViewItemRecord } from './useTreeView.js';
|
|
3
|
+
/** A node, and the values of the nodes above it, from the top. */
|
|
4
|
+
export interface TreeNodeEntry {
|
|
5
|
+
node: TreeItemData;
|
|
6
|
+
path: string[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Every node by its value, in the order the tree reads from top to bottom.
|
|
10
|
+
* Values are meant to be unique, and the first node with a value wins.
|
|
11
|
+
*/
|
|
12
|
+
export declare function indexTree(data: TreeItemData[]): Map<string, TreeNodeEntry>;
|
|
13
|
+
/** What a node is called: its `label`, or its `value` when that's empty. */
|
|
14
|
+
export declare const nodeLabel: (node: TreeItemData) => string;
|
|
15
|
+
/** The nodes under a node, none when it has no `children`. */
|
|
16
|
+
export declare const childNodes: (node: TreeItemData) => TreeItemData[];
|
|
17
|
+
/** Whether a node is a parent: it has children, or `hasChildren` says it will. */
|
|
18
|
+
export declare const isParentNode: (node: TreeItemData) => boolean;
|
|
19
|
+
/**
|
|
20
|
+
* The records TreeView's check rules read, built from the nodes rather than
|
|
21
|
+
* from the items on the page, so the checked list can be worked out while
|
|
22
|
+
* the tree isn't there.
|
|
23
|
+
*/
|
|
24
|
+
export declare function checkRecords(index: Map<string, TreeNodeEntry>): Map<string, TreeViewItemRecord>;
|
|
25
|
+
/**
|
|
26
|
+
* The checked list a `checkedStrategy` reports for the items `listed` checks
|
|
27
|
+
* by TreeView's rules, in the tree's order. `all` is every checked item;
|
|
28
|
+
* `child` the checked items with no enabled item under them; `parent` the
|
|
29
|
+
* checked items whose parent isn't. A disabled item is checked by its own
|
|
30
|
+
* value only, so a checked one is in every list. Values no node has are
|
|
31
|
+
* kept, at the end. Passed back in, each list checks the same items.
|
|
32
|
+
*/
|
|
33
|
+
export declare function checkedByStrategy(records: Map<string, TreeViewItemRecord>, listed: string[], strategy: TreeSelectCheckedStrategy): string[];
|
|
34
|
+
/** What a search leaves of a tree. */
|
|
35
|
+
export interface TreeSearch {
|
|
36
|
+
/** The values of the nodes it hides. */
|
|
37
|
+
hidden: Set<string>;
|
|
38
|
+
/** The values of the nodes with a match under them, which open. */
|
|
39
|
+
open: string[];
|
|
40
|
+
/** Whether anything matched. */
|
|
41
|
+
found: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* What a search shows of a tree: the nodes that match, the nodes above them,
|
|
45
|
+
* so the results stay a tree, and the nodes under them, so a matching branch
|
|
46
|
+
* can still be opened.
|
|
47
|
+
*/
|
|
48
|
+
export declare function searchTree(data: TreeItemData[], matches: (node: TreeItemData, path: TreeItemData[]) => boolean): TreeSearch;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** Options for useClipboard. */
|
|
2
|
+
export interface UseClipboardOptions {
|
|
3
|
+
/**
|
|
4
|
+
* How long `copied` stays `true` after a copy, in milliseconds. Another
|
|
5
|
+
* copy restarts it. `0` turns the timer off, as Toast's `0` does, so
|
|
6
|
+
* `copied` stays `true` until a later copy fails. A missing or `NaN` value
|
|
7
|
+
* uses the default, a negative one ends it at once, and `Infinity`, or
|
|
8
|
+
* anything longer than the longest delay `setTimeout` takes (2147483647 ms,
|
|
9
|
+
* about 24.8 days), is that longest delay.
|
|
10
|
+
* @defaultValue 2000
|
|
11
|
+
*/
|
|
12
|
+
duration?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Called with `true` after each copy that worked, a repeat included, and
|
|
15
|
+
* with `false` when `duration` runs out or a later copy fails.
|
|
16
|
+
*/
|
|
17
|
+
onCopiedChange?: (copied: boolean) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Called when neither the Clipboard API nor the copy command could write,
|
|
20
|
+
* with the Clipboard API's own error when it refused, or an `Error` saying
|
|
21
|
+
* neither could.
|
|
22
|
+
*/
|
|
23
|
+
onCopyError?: (error: Error) => void;
|
|
24
|
+
}
|
|
25
|
+
/** What useClipboard returns. */
|
|
26
|
+
export interface UseClipboardResult {
|
|
27
|
+
/**
|
|
28
|
+
* Writes `text` to the clipboard, and resolves `true` once it's written or
|
|
29
|
+
* `false` when it couldn't be. It never rejects. Call it from a click or a
|
|
30
|
+
* key press, with no `await` before it: browsers only allow a write
|
|
31
|
+
* shortly after one. A call that a later one overtakes leaves `copied`,
|
|
32
|
+
* `error` and the callbacks to the later one, and doesn't fall back to the
|
|
33
|
+
* copy command once the later one has started.
|
|
34
|
+
*/
|
|
35
|
+
copy: (text: string) => Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* `true` for `duration` after a copy that worked, or, with a `duration` of
|
|
38
|
+
* `0`, until a later copy fails.
|
|
39
|
+
*/
|
|
40
|
+
copied: boolean;
|
|
41
|
+
/** Why the last copy failed, or `null` after one that worked. */
|
|
42
|
+
error: Error | null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Copies text to the clipboard through the Clipboard API, falling back to the copy command where that's missing or refused, and keeps a `copied` flag for `duration` after a copy.
|
|
46
|
+
*
|
|
47
|
+
* It announces nothing. A trigger of your own says "Copied" in a
|
|
48
|
+
* `role="status"` region that's in the page before the click; `CopyButton`
|
|
49
|
+
* is this hook with the button, the label and the announcement built in.
|
|
50
|
+
*
|
|
51
|
+
* A failed copy sets `error`, calls `onCopyError`, and ends `copied` if a
|
|
52
|
+
* copy before it had set it. When copies overlap, only the latest one's
|
|
53
|
+
* outcome sets the state and fires the callbacks, whichever finishes first.
|
|
54
|
+
* Nothing changes and no callback fires once the component using it has
|
|
55
|
+
* unmounted, though a write already under way still finishes.
|
|
56
|
+
*
|
|
57
|
+
* @function useClipboard
|
|
58
|
+
* @param options - How long `copied` lasts, and the callbacks.
|
|
59
|
+
* @returns `copy`, which writes, and the `copied` and `error` state.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* const { copy, copied } = useClipboard();
|
|
63
|
+
* <Button onClick={() => copy(url)}>{copied ? 'Copied' : 'Copy link'}</Button>
|
|
64
|
+
*/
|
|
65
|
+
export declare function useClipboard(options?: UseClipboardOptions): UseClipboardResult;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A value the caller holds, or one this hook holds when the caller doesn't:
|
|
3
|
+
* the `x` / `defaultX` pair of a component's props. The caller holds it
|
|
4
|
+
* whenever `controlled` isn't `undefined`, so `null` is a held value. The
|
|
5
|
+
* setter changes only the value held here, so a held one changes when the
|
|
6
|
+
* caller passes the new value, and it reports nothing: the component calls
|
|
7
|
+
* its own `onXChange`.
|
|
8
|
+
*
|
|
9
|
+
* @function useControlled
|
|
10
|
+
* @param controlled - The caller's value, or `undefined` to hold one here.
|
|
11
|
+
* @param initial - The value held here to begin with.
|
|
12
|
+
* @returns The current value, and the setter for the one held here.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useControlled<T>(controlled: T | undefined, initial: T): readonly [T, (next: T) => void];
|
|
@@ -37,6 +37,36 @@ export interface TreeViewItemState {
|
|
|
37
37
|
selected?: boolean;
|
|
38
38
|
checked?: TreeViewCheckState;
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* The values of the items a tree hides while they stay in it, as TreeSelect's
|
|
42
|
+
* search hides the items that don't match. A hidden item renders as one under
|
|
43
|
+
* a closed parent does: nothing on the page, and in a `checkbox` tree it and
|
|
44
|
+
* its children still register, so a check still reaches them. Internal, for
|
|
45
|
+
* the components that put a TreeView inside them.
|
|
46
|
+
*/
|
|
47
|
+
export declare const TreeViewHiddenContext: React.Context<ReadonlySet<string>>;
|
|
48
|
+
/**
|
|
49
|
+
* Every known item's check state, by the rules in #1096:
|
|
50
|
+
*
|
|
51
|
+
* - a disabled item is checked only when its own value is listed;
|
|
52
|
+
* - an enabled item with no enabled items anywhere under it is checked when
|
|
53
|
+
* it, or any item above it, is listed;
|
|
54
|
+
* - any other enabled item follows the items of that second kind in its
|
|
55
|
+
* branch: checked when they all are, unchecked when none is, mixed between.
|
|
56
|
+
*
|
|
57
|
+
* Also returns the items of the second kind, which are what a toggle sets.
|
|
58
|
+
*/
|
|
59
|
+
export declare function readChecks(records: Map<string, TreeViewItemRecord>, listed: Set<string>): {
|
|
60
|
+
states: Map<string, TreeViewCheckState>;
|
|
61
|
+
ends: string[];
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* The list a toggle of `value` leaves: it and every enabled item under it
|
|
65
|
+
* take the opposite of its state (a mixed one checks), and the rest is read
|
|
66
|
+
* back by the rules. That's every item that shows checked, parents
|
|
67
|
+
* included, plus any listed value no item has.
|
|
68
|
+
*/
|
|
69
|
+
export declare function toggledList(records: Map<string, TreeViewItemRecord>, list: string[], value: string): string[];
|
|
40
70
|
/** Options for `useTreeView`: the TreeView's own props. */
|
|
41
71
|
export interface TreeViewOptions {
|
|
42
72
|
mode: TreeViewSelectionMode;
|