@allxsmith/bestax-bulma 5.36.1 → 5.37.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 -2
- package/dist/esm/components/Timeline.js +5 -5
- package/dist/esm/components/Timeline.js.map +1 -1
- package/dist/esm/components/TreeView.js +192 -0
- package/dist/esm/components/TreeView.js.map +1 -0
- package/dist/esm/helpers/typeahead.js +82 -0
- package/dist/esm/helpers/typeahead.js.map +1 -0
- package/dist/esm/helpers/useMenuKeys.js +8 -58
- package/dist/esm/helpers/useMenuKeys.js.map +1 -1
- package/dist/esm/helpers/useTreeView.js +380 -0
- package/dist/esm/helpers/useTreeView.js.map +1 -0
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +1945 -1368
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +1 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/types/components/TreeView.d.ts +115 -0
- package/dist/types/helpers/typeahead.d.ts +41 -0
- package/dist/types/helpers/useMenuKeys.d.ts +1 -2
- package/dist/types/helpers/useTreeView.d.ts +88 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types-cjs/components/TreeView.d.ts +115 -0
- package/dist/types-cjs/helpers/typeahead.d.ts +41 -0
- package/dist/types-cjs/helpers/useMenuKeys.d.ts +1 -2
- package/dist/types-cjs/helpers/useTreeView.d.ts +88 -0
- package/dist/types-cjs/index.d.ts +1 -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/components/_index.scss +1 -0
- package/src/scss/components/_treeview.scss +252 -0
package/dist/index.esm.js
CHANGED
|
@@ -30,6 +30,7 @@ export { Toast, ToastContainer, toast } from './esm/components/Toast.js';
|
|
|
30
30
|
export { Dialog, DialogContainer, dialog } from './esm/components/Dialog.js';
|
|
31
31
|
export { Carousel, CarouselItem } from './esm/components/Carousel.js';
|
|
32
32
|
export { Reveal } from './esm/components/Reveal.js';
|
|
33
|
+
export { TreeView, TreeViewItem } from './esm/components/TreeView.js';
|
|
33
34
|
export { Block } from './esm/elements/Block.js';
|
|
34
35
|
export { Box } from './esm/elements/Box.js';
|
|
35
36
|
export { Button } from './esm/elements/Button.js';
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { BulmaClassesProps } from '../helpers/useBulmaClasses.js';
|
|
3
|
+
/**
|
|
4
|
+
* How items are picked: `none`, nothing is; `single`, one item at a time;
|
|
5
|
+
* `checkbox`, any number, with a box on every item and mixed parents.
|
|
6
|
+
*/
|
|
7
|
+
export type TreeViewSelectionMode = 'none' | 'single' | 'checkbox';
|
|
8
|
+
/**
|
|
9
|
+
* Props for the TreeView component. The helper props, the other attributes
|
|
10
|
+
* and the `ref` land on the `<ul role="tree">`.
|
|
11
|
+
*
|
|
12
|
+
* @extraProp {string} [aria-label] - Names the tree, such as "Files". A tree needs a name, so pass this or `aria-labelledby`, and a development build warns when it has neither.
|
|
13
|
+
* @extraProp {string} [aria-labelledby] - The id of a visible heading or label that names the tree, in place of `aria-label`.
|
|
14
|
+
* @extraProp {React.Ref<HTMLUListElement>} [ref] - Ref forwarded to the `<ul>`.
|
|
15
|
+
*/
|
|
16
|
+
export interface TreeViewProps extends Omit<React.HTMLAttributes<HTMLUListElement>, keyof BulmaClassesProps | 'role' | 'onSelect' | 'defaultValue' | 'defaultChecked'>, BulmaClassesProps {
|
|
17
|
+
/**
|
|
18
|
+
* `TreeView.Item`s, nested inside each other for their children. Render
|
|
19
|
+
* an item's children whenever you have them, open or not: the tree hides
|
|
20
|
+
* them while it's closed.
|
|
21
|
+
*/
|
|
22
|
+
children?: React.ReactNode;
|
|
23
|
+
/**
|
|
24
|
+
* `none`: nothing is picked, and Enter and Space open and close a parent.
|
|
25
|
+
* `single`: one item, picked with Enter, Space or a click.
|
|
26
|
+
* `checkbox`: any number, checked with Space or a click. A check reaches
|
|
27
|
+
* every enabled item under it, and a parent with some of them checked is mixed.
|
|
28
|
+
*/
|
|
29
|
+
selectionMode?: TreeViewSelectionMode;
|
|
30
|
+
/**
|
|
31
|
+
* The selected item's value when you hold the state, or `null` for none.
|
|
32
|
+
* Read with `single` only. Picking an item then only calls
|
|
33
|
+
* `onSelectedChange`, and nothing changes until you pass the new value.
|
|
34
|
+
*/
|
|
35
|
+
selected?: string | null;
|
|
36
|
+
/** The item selected to begin with, when the tree holds its own state. Read with `single` only. */
|
|
37
|
+
defaultSelected?: string | null;
|
|
38
|
+
/**
|
|
39
|
+
* Called with the value of the item picked. Not called for the one
|
|
40
|
+
* already selected, and moving focus never calls it.
|
|
41
|
+
*/
|
|
42
|
+
onSelectedChange?: (value: string) => void;
|
|
43
|
+
/**
|
|
44
|
+
* The checked items' values when you hold the state. Read with `checkbox`
|
|
45
|
+
* only. A value checks its item, and an enabled item also counts as checked
|
|
46
|
+
* when any item above it is in the list, so a parent's value stands for its
|
|
47
|
+
* whole branch, loaded or not. A disabled item is checked only by its own value.
|
|
48
|
+
*/
|
|
49
|
+
checked?: string[];
|
|
50
|
+
/** The values checked to begin with, when the tree holds its own state. Read with `checkbox` only. */
|
|
51
|
+
defaultChecked?: string[];
|
|
52
|
+
/**
|
|
53
|
+
* Called after a check or an uncheck with every item that now shows
|
|
54
|
+
* checked, parents included, plus any earlier value that matches no item
|
|
55
|
+
* the tree knows, left as it was. The order means nothing. Passed back as
|
|
56
|
+
* `checked`, the list shows the same boxes.
|
|
57
|
+
*/
|
|
58
|
+
onCheckedChange?: (checked: string[]) => void;
|
|
59
|
+
/**
|
|
60
|
+
* The open items' values when you hold the state. A value stays in the
|
|
61
|
+
* list while its item's parent is closed, so the item reopens as it was.
|
|
62
|
+
*/
|
|
63
|
+
expanded?: string[];
|
|
64
|
+
/** The items open to begin with, when the tree holds its own state. */
|
|
65
|
+
defaultExpanded?: string[];
|
|
66
|
+
/** Called with the new list whenever an item opens or closes, `*` included. */
|
|
67
|
+
onExpandedChange?: (expanded: string[]) => void;
|
|
68
|
+
/** The text size, as Bulma's menu sizes it. The rows, the indent and the chevron scale with it. */
|
|
69
|
+
size?: 'small' | 'medium' | 'large';
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Props for TreeView.Item, one row and, nested in it, its children. The other
|
|
73
|
+
* attributes and the `ref` land on its `<li role="treeitem">`.
|
|
74
|
+
*
|
|
75
|
+
* @extraProp {React.Ref<HTMLLIElement>} [ref] - Ref forwarded to the `<li>`.
|
|
76
|
+
*/
|
|
77
|
+
export interface TreeViewItemProps extends Omit<React.LiHTMLAttributes<HTMLLIElement>, 'role' | 'value' | 'onSelect' | 'children'> {
|
|
78
|
+
/** **Required.** Identifies the item in `selected`, `checked` and `expanded`. Unique in the tree. */
|
|
79
|
+
value: string;
|
|
80
|
+
/**
|
|
81
|
+
* **Required.** What the row shows, and the item's name for assistive
|
|
82
|
+
* tech. Nothing in it should be a link or a button: a tree item does one
|
|
83
|
+
* thing, and nothing else in its row takes focus.
|
|
84
|
+
*/
|
|
85
|
+
label: React.ReactNode;
|
|
86
|
+
/** A picture before the label: an `Icon` name, or a node. Hidden from assistive tech. */
|
|
87
|
+
icon?: React.ReactNode;
|
|
88
|
+
/**
|
|
89
|
+
* `TreeView.Item`s under this one. Render them whenever you have them,
|
|
90
|
+
* open or not: the tree hides them while it's closed, and a checkbox tree
|
|
91
|
+
* needs them to know what a check reaches.
|
|
92
|
+
*/
|
|
93
|
+
children?: React.ReactNode;
|
|
94
|
+
/** Shows the item as a parent before its children are known, such as a folder that loads when it opens. */
|
|
95
|
+
hasChildren?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Reachable with the arrow keys, Home, End and type-ahead, so a screen
|
|
98
|
+
* reader finds it, but never selected, checked, opened or closed. One
|
|
99
|
+
* that's already open stays open.
|
|
100
|
+
*/
|
|
101
|
+
disabled?: boolean;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* One item in the tree: a row with its chevron, its box, its icon and its label, and, while it's open, a group of the items under it.
|
|
105
|
+
*
|
|
106
|
+
* @function
|
|
107
|
+
* @param {TreeViewItemProps} props - Props for TreeView.Item.
|
|
108
|
+
* @param {React.Ref<HTMLLIElement>} ref - Forwarded ref to the `<li>`.
|
|
109
|
+
* @returns {JSX.Element | null} The rendered item, or nothing under a closed one.
|
|
110
|
+
*/
|
|
111
|
+
export declare const TreeViewItem: React.ForwardRefExoticComponent<TreeViewItemProps & React.RefAttributes<HTMLLIElement>>;
|
|
112
|
+
export declare const TreeView: React.ForwardRefExoticComponent<TreeViewProps & React.RefAttributes<HTMLUListElement>> & {
|
|
113
|
+
Item: React.ForwardRefExoticComponent<TreeViewItemProps & React.RefAttributes<HTMLLIElement>>;
|
|
114
|
+
};
|
|
115
|
+
export default TreeView;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** How long typed characters keep adding up to one search, in milliseconds. */
|
|
2
|
+
export declare const TYPEAHEAD_TIMEOUT = 500;
|
|
3
|
+
/**
|
|
4
|
+
* The text typing finds an element by: what it says, without what's hidden
|
|
5
|
+
* from assistive technology, such as an icon whose glyph is a ligature's name.
|
|
6
|
+
*/
|
|
7
|
+
export declare function typeaheadText(element: Element): string;
|
|
8
|
+
/**
|
|
9
|
+
* The item typing `search` moves to, or none. A single character looks from
|
|
10
|
+
* the item after the focused one, so typing the same letter again cycles
|
|
11
|
+
* through the items that start with it, and so does a run of one letter
|
|
12
|
+
* ("dd"). A longer search looks from the focused item, so typing more of
|
|
13
|
+
* its own text keeps it.
|
|
14
|
+
*
|
|
15
|
+
* @param items - The items typing can reach, in the order they're shown.
|
|
16
|
+
* @param search - What's been typed, lowercased.
|
|
17
|
+
* @param current - The focused item's index in `items`, or -1 for none.
|
|
18
|
+
* @param textOf - The text an item is found by. By default it's the item's
|
|
19
|
+
* own, read by `typeaheadText`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function typeaheadMatch<T extends Element>(items: T[], search: string, current: number, textOf?: (item: T) => string): T | undefined;
|
|
22
|
+
/** What `useTypeahead` returns. */
|
|
23
|
+
export interface Typeahead {
|
|
24
|
+
/**
|
|
25
|
+
* Adds a typed character to the search and returns the whole search,
|
|
26
|
+
* lowercased. Characters typed within `TYPEAHEAD_TIMEOUT` of each other
|
|
27
|
+
* add up, and after that the next one starts a new search.
|
|
28
|
+
*/
|
|
29
|
+
type: (char: string) => string;
|
|
30
|
+
/** Forgets what has been typed, so the next character starts a new search. */
|
|
31
|
+
reset: () => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Keeps what has been typed for a type-ahead search, and forgets it once
|
|
35
|
+
* `TYPEAHEAD_TIMEOUT` passes with nothing typed. Pair it with
|
|
36
|
+
* `typeaheadMatch` to find the item the search names.
|
|
37
|
+
*
|
|
38
|
+
* @function useTypeahead
|
|
39
|
+
* @returns A way to add a character to the search, and a way to forget it.
|
|
40
|
+
*/
|
|
41
|
+
export declare function useTypeahead(): Typeahead;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { KeyboardEvent } from 'react';
|
|
2
|
+
export { TYPEAHEAD_TIMEOUT } from './typeahead.js';
|
|
2
3
|
/**
|
|
3
4
|
* Every menu-item role, so an item a caller gives `menuitemcheckbox` or
|
|
4
5
|
* `menuitemradio` (a filter or sort menu) stays reachable.
|
|
@@ -11,8 +12,6 @@ export declare const MENU_ITEM_SELECTOR = "[role=\"menuitem\"], [role=\"menuitem
|
|
|
11
12
|
export declare function isEnabledMenuItem(item: Element): boolean;
|
|
12
13
|
/** The items in `menu` the keys reach, in document order. */
|
|
13
14
|
export declare function enabledMenuItems(menu: Element): HTMLElement[];
|
|
14
|
-
/** How long typed characters keep adding up to one search, in milliseconds. */
|
|
15
|
-
export declare const TYPEAHEAD_TIMEOUT = 500;
|
|
16
15
|
/** What `useMenuKeys` returns. */
|
|
17
16
|
export interface MenuKeys {
|
|
18
17
|
/** The `keydown` handler for the `role="menu"` element. */
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { TreeViewSelectionMode } from '../components/TreeView.js';
|
|
3
|
+
/** What an item tells the tree about itself when it registers. */
|
|
4
|
+
export interface TreeViewItemRecord {
|
|
5
|
+
/** The value of the item it's in, or `null` at the top. */
|
|
6
|
+
parent: string | null;
|
|
7
|
+
disabled: boolean;
|
|
8
|
+
/** It has children, or `hasChildren` says it will. */
|
|
9
|
+
isParent: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** An item as a key or a click on it sees it. */
|
|
12
|
+
export interface TreeViewItemInfo extends TreeViewItemRecord {
|
|
13
|
+
value: string;
|
|
14
|
+
open: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** A box's state: checked, unchecked or mixed. */
|
|
17
|
+
export type TreeViewCheckState = boolean | 'mixed';
|
|
18
|
+
/**
|
|
19
|
+
* What an item shows of the selection: `selected` in a `single` tree,
|
|
20
|
+
* `checked` in a `checkbox` tree, and neither with `none`.
|
|
21
|
+
*/
|
|
22
|
+
export interface TreeViewItemState {
|
|
23
|
+
selected?: boolean;
|
|
24
|
+
checked?: TreeViewCheckState;
|
|
25
|
+
}
|
|
26
|
+
/** Options for `useTreeView`: the TreeView's own props. */
|
|
27
|
+
export interface TreeViewOptions {
|
|
28
|
+
mode: TreeViewSelectionMode;
|
|
29
|
+
selected?: string | null;
|
|
30
|
+
defaultSelected: string | null;
|
|
31
|
+
onSelectedChange?: (value: string) => void;
|
|
32
|
+
checked?: string[];
|
|
33
|
+
defaultChecked: string[];
|
|
34
|
+
onCheckedChange?: (checked: string[]) => void;
|
|
35
|
+
expanded?: string[];
|
|
36
|
+
defaultExpanded: string[];
|
|
37
|
+
onExpandedChange?: (expanded: string[]) => void;
|
|
38
|
+
}
|
|
39
|
+
/** What `useTreeView` hands the root and its items. */
|
|
40
|
+
export interface TreeViewEngine {
|
|
41
|
+
/** For the `<ul role="tree">`. */
|
|
42
|
+
treeRef: React.MutableRefObject<HTMLUListElement | null>;
|
|
43
|
+
/**
|
|
44
|
+
* Whether a closed item still renders its children, drawing nothing, so a
|
|
45
|
+
* check knows everything under it. Only a checkbox tree needs to.
|
|
46
|
+
*/
|
|
47
|
+
rendersClosed: boolean;
|
|
48
|
+
/** The item that holds `tabIndex={0}`. */
|
|
49
|
+
tabStop: string | null;
|
|
50
|
+
isOpen: (value: string) => boolean;
|
|
51
|
+
/**
|
|
52
|
+
* What the item shows of the selection. `path` is the values of the items
|
|
53
|
+
* above it, which decide its box until the items have registered, as on
|
|
54
|
+
* the server.
|
|
55
|
+
*/
|
|
56
|
+
stateOf: (value: string, path: string[], disabled: boolean) => TreeViewItemState;
|
|
57
|
+
/** Records an item from its layout effect. Returns the function that forgets it. */
|
|
58
|
+
register: (value: string, record: TreeViewItemRecord) => () => void;
|
|
59
|
+
/** For each item's `<li>` ref: records it, and notices focus leaving with it. */
|
|
60
|
+
setElement: (value: string, element: HTMLLIElement | null) => void;
|
|
61
|
+
/** Focus arrived on the item's own `<li>`. */
|
|
62
|
+
onFocus: (value: string, element: HTMLLIElement) => void;
|
|
63
|
+
/** Focus left the item's own `<li>`. */
|
|
64
|
+
onBlur: () => void;
|
|
65
|
+
/** A key on the item's `<li>`, after its own `onKeyDown`. */
|
|
66
|
+
onKeyDown: (event: React.KeyboardEvent<HTMLLIElement>, item: TreeViewItemInfo) => void;
|
|
67
|
+
/**
|
|
68
|
+
* A click on the item's row, or with `onToggle` on its chevron. Focus and
|
|
69
|
+
* the tab stop move to the item.
|
|
70
|
+
*/
|
|
71
|
+
onClick: (element: HTMLLIElement, item: TreeViewItemInfo, onToggle: boolean) => void;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The open state, the selection, the keys, the tab stop and the registry of
|
|
75
|
+
* a TreeView (#1096). Focus moves for real, with a roving tabindex, rather
|
|
76
|
+
* than through `aria-activedescendant`.
|
|
77
|
+
*
|
|
78
|
+
* Every item registers its value, its parent and whether it's disabled from
|
|
79
|
+
* a layout effect. In a checkbox tree a closed item's children still render
|
|
80
|
+
* and register while drawing nothing, so the registry knows every item and a
|
|
81
|
+
* check reaches all of them. The keys read the items on the page, in
|
|
82
|
+
* document order, each time they need them.
|
|
83
|
+
*
|
|
84
|
+
* @function useTreeView
|
|
85
|
+
* @param options - The TreeView's props.
|
|
86
|
+
* @returns The state and handlers the root and its items wire up.
|
|
87
|
+
*/
|
|
88
|
+
export declare function useTreeView(options: TreeViewOptions): TreeViewEngine;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export * from './components/Toast.js';
|
|
|
29
29
|
export * from './components/Dialog.js';
|
|
30
30
|
export * from './components/Carousel.js';
|
|
31
31
|
export * from './components/Reveal.js';
|
|
32
|
+
export * from './components/TreeView.js';
|
|
32
33
|
export * from './elements/Block.js';
|
|
33
34
|
export * from './elements/Box.js';
|
|
34
35
|
export * from './elements/Button.js';
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { BulmaClassesProps } from '../helpers/useBulmaClasses.js';
|
|
3
|
+
/**
|
|
4
|
+
* How items are picked: `none`, nothing is; `single`, one item at a time;
|
|
5
|
+
* `checkbox`, any number, with a box on every item and mixed parents.
|
|
6
|
+
*/
|
|
7
|
+
export type TreeViewSelectionMode = 'none' | 'single' | 'checkbox';
|
|
8
|
+
/**
|
|
9
|
+
* Props for the TreeView component. The helper props, the other attributes
|
|
10
|
+
* and the `ref` land on the `<ul role="tree">`.
|
|
11
|
+
*
|
|
12
|
+
* @extraProp {string} [aria-label] - Names the tree, such as "Files". A tree needs a name, so pass this or `aria-labelledby`, and a development build warns when it has neither.
|
|
13
|
+
* @extraProp {string} [aria-labelledby] - The id of a visible heading or label that names the tree, in place of `aria-label`.
|
|
14
|
+
* @extraProp {React.Ref<HTMLUListElement>} [ref] - Ref forwarded to the `<ul>`.
|
|
15
|
+
*/
|
|
16
|
+
export interface TreeViewProps extends Omit<React.HTMLAttributes<HTMLUListElement>, keyof BulmaClassesProps | 'role' | 'onSelect' | 'defaultValue' | 'defaultChecked'>, BulmaClassesProps {
|
|
17
|
+
/**
|
|
18
|
+
* `TreeView.Item`s, nested inside each other for their children. Render
|
|
19
|
+
* an item's children whenever you have them, open or not: the tree hides
|
|
20
|
+
* them while it's closed.
|
|
21
|
+
*/
|
|
22
|
+
children?: React.ReactNode;
|
|
23
|
+
/**
|
|
24
|
+
* `none`: nothing is picked, and Enter and Space open and close a parent.
|
|
25
|
+
* `single`: one item, picked with Enter, Space or a click.
|
|
26
|
+
* `checkbox`: any number, checked with Space or a click. A check reaches
|
|
27
|
+
* every enabled item under it, and a parent with some of them checked is mixed.
|
|
28
|
+
*/
|
|
29
|
+
selectionMode?: TreeViewSelectionMode;
|
|
30
|
+
/**
|
|
31
|
+
* The selected item's value when you hold the state, or `null` for none.
|
|
32
|
+
* Read with `single` only. Picking an item then only calls
|
|
33
|
+
* `onSelectedChange`, and nothing changes until you pass the new value.
|
|
34
|
+
*/
|
|
35
|
+
selected?: string | null;
|
|
36
|
+
/** The item selected to begin with, when the tree holds its own state. Read with `single` only. */
|
|
37
|
+
defaultSelected?: string | null;
|
|
38
|
+
/**
|
|
39
|
+
* Called with the value of the item picked. Not called for the one
|
|
40
|
+
* already selected, and moving focus never calls it.
|
|
41
|
+
*/
|
|
42
|
+
onSelectedChange?: (value: string) => void;
|
|
43
|
+
/**
|
|
44
|
+
* The checked items' values when you hold the state. Read with `checkbox`
|
|
45
|
+
* only. A value checks its item, and an enabled item also counts as checked
|
|
46
|
+
* when any item above it is in the list, so a parent's value stands for its
|
|
47
|
+
* whole branch, loaded or not. A disabled item is checked only by its own value.
|
|
48
|
+
*/
|
|
49
|
+
checked?: string[];
|
|
50
|
+
/** The values checked to begin with, when the tree holds its own state. Read with `checkbox` only. */
|
|
51
|
+
defaultChecked?: string[];
|
|
52
|
+
/**
|
|
53
|
+
* Called after a check or an uncheck with every item that now shows
|
|
54
|
+
* checked, parents included, plus any earlier value that matches no item
|
|
55
|
+
* the tree knows, left as it was. The order means nothing. Passed back as
|
|
56
|
+
* `checked`, the list shows the same boxes.
|
|
57
|
+
*/
|
|
58
|
+
onCheckedChange?: (checked: string[]) => void;
|
|
59
|
+
/**
|
|
60
|
+
* The open items' values when you hold the state. A value stays in the
|
|
61
|
+
* list while its item's parent is closed, so the item reopens as it was.
|
|
62
|
+
*/
|
|
63
|
+
expanded?: string[];
|
|
64
|
+
/** The items open to begin with, when the tree holds its own state. */
|
|
65
|
+
defaultExpanded?: string[];
|
|
66
|
+
/** Called with the new list whenever an item opens or closes, `*` included. */
|
|
67
|
+
onExpandedChange?: (expanded: string[]) => void;
|
|
68
|
+
/** The text size, as Bulma's menu sizes it. The rows, the indent and the chevron scale with it. */
|
|
69
|
+
size?: 'small' | 'medium' | 'large';
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Props for TreeView.Item, one row and, nested in it, its children. The other
|
|
73
|
+
* attributes and the `ref` land on its `<li role="treeitem">`.
|
|
74
|
+
*
|
|
75
|
+
* @extraProp {React.Ref<HTMLLIElement>} [ref] - Ref forwarded to the `<li>`.
|
|
76
|
+
*/
|
|
77
|
+
export interface TreeViewItemProps extends Omit<React.LiHTMLAttributes<HTMLLIElement>, 'role' | 'value' | 'onSelect' | 'children'> {
|
|
78
|
+
/** **Required.** Identifies the item in `selected`, `checked` and `expanded`. Unique in the tree. */
|
|
79
|
+
value: string;
|
|
80
|
+
/**
|
|
81
|
+
* **Required.** What the row shows, and the item's name for assistive
|
|
82
|
+
* tech. Nothing in it should be a link or a button: a tree item does one
|
|
83
|
+
* thing, and nothing else in its row takes focus.
|
|
84
|
+
*/
|
|
85
|
+
label: React.ReactNode;
|
|
86
|
+
/** A picture before the label: an `Icon` name, or a node. Hidden from assistive tech. */
|
|
87
|
+
icon?: React.ReactNode;
|
|
88
|
+
/**
|
|
89
|
+
* `TreeView.Item`s under this one. Render them whenever you have them,
|
|
90
|
+
* open or not: the tree hides them while it's closed, and a checkbox tree
|
|
91
|
+
* needs them to know what a check reaches.
|
|
92
|
+
*/
|
|
93
|
+
children?: React.ReactNode;
|
|
94
|
+
/** Shows the item as a parent before its children are known, such as a folder that loads when it opens. */
|
|
95
|
+
hasChildren?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Reachable with the arrow keys, Home, End and type-ahead, so a screen
|
|
98
|
+
* reader finds it, but never selected, checked, opened or closed. One
|
|
99
|
+
* that's already open stays open.
|
|
100
|
+
*/
|
|
101
|
+
disabled?: boolean;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* One item in the tree: a row with its chevron, its box, its icon and its label, and, while it's open, a group of the items under it.
|
|
105
|
+
*
|
|
106
|
+
* @function
|
|
107
|
+
* @param {TreeViewItemProps} props - Props for TreeView.Item.
|
|
108
|
+
* @param {React.Ref<HTMLLIElement>} ref - Forwarded ref to the `<li>`.
|
|
109
|
+
* @returns {JSX.Element | null} The rendered item, or nothing under a closed one.
|
|
110
|
+
*/
|
|
111
|
+
export declare const TreeViewItem: React.ForwardRefExoticComponent<TreeViewItemProps & React.RefAttributes<HTMLLIElement>>;
|
|
112
|
+
export declare const TreeView: React.ForwardRefExoticComponent<TreeViewProps & React.RefAttributes<HTMLUListElement>> & {
|
|
113
|
+
Item: React.ForwardRefExoticComponent<TreeViewItemProps & React.RefAttributes<HTMLLIElement>>;
|
|
114
|
+
};
|
|
115
|
+
export default TreeView;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** How long typed characters keep adding up to one search, in milliseconds. */
|
|
2
|
+
export declare const TYPEAHEAD_TIMEOUT = 500;
|
|
3
|
+
/**
|
|
4
|
+
* The text typing finds an element by: what it says, without what's hidden
|
|
5
|
+
* from assistive technology, such as an icon whose glyph is a ligature's name.
|
|
6
|
+
*/
|
|
7
|
+
export declare function typeaheadText(element: Element): string;
|
|
8
|
+
/**
|
|
9
|
+
* The item typing `search` moves to, or none. A single character looks from
|
|
10
|
+
* the item after the focused one, so typing the same letter again cycles
|
|
11
|
+
* through the items that start with it, and so does a run of one letter
|
|
12
|
+
* ("dd"). A longer search looks from the focused item, so typing more of
|
|
13
|
+
* its own text keeps it.
|
|
14
|
+
*
|
|
15
|
+
* @param items - The items typing can reach, in the order they're shown.
|
|
16
|
+
* @param search - What's been typed, lowercased.
|
|
17
|
+
* @param current - The focused item's index in `items`, or -1 for none.
|
|
18
|
+
* @param textOf - The text an item is found by. By default it's the item's
|
|
19
|
+
* own, read by `typeaheadText`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function typeaheadMatch<T extends Element>(items: T[], search: string, current: number, textOf?: (item: T) => string): T | undefined;
|
|
22
|
+
/** What `useTypeahead` returns. */
|
|
23
|
+
export interface Typeahead {
|
|
24
|
+
/**
|
|
25
|
+
* Adds a typed character to the search and returns the whole search,
|
|
26
|
+
* lowercased. Characters typed within `TYPEAHEAD_TIMEOUT` of each other
|
|
27
|
+
* add up, and after that the next one starts a new search.
|
|
28
|
+
*/
|
|
29
|
+
type: (char: string) => string;
|
|
30
|
+
/** Forgets what has been typed, so the next character starts a new search. */
|
|
31
|
+
reset: () => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Keeps what has been typed for a type-ahead search, and forgets it once
|
|
35
|
+
* `TYPEAHEAD_TIMEOUT` passes with nothing typed. Pair it with
|
|
36
|
+
* `typeaheadMatch` to find the item the search names.
|
|
37
|
+
*
|
|
38
|
+
* @function useTypeahead
|
|
39
|
+
* @returns A way to add a character to the search, and a way to forget it.
|
|
40
|
+
*/
|
|
41
|
+
export declare function useTypeahead(): Typeahead;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { KeyboardEvent } from 'react';
|
|
2
|
+
export { TYPEAHEAD_TIMEOUT } from './typeahead.js';
|
|
2
3
|
/**
|
|
3
4
|
* Every menu-item role, so an item a caller gives `menuitemcheckbox` or
|
|
4
5
|
* `menuitemradio` (a filter or sort menu) stays reachable.
|
|
@@ -11,8 +12,6 @@ export declare const MENU_ITEM_SELECTOR = "[role=\"menuitem\"], [role=\"menuitem
|
|
|
11
12
|
export declare function isEnabledMenuItem(item: Element): boolean;
|
|
12
13
|
/** The items in `menu` the keys reach, in document order. */
|
|
13
14
|
export declare function enabledMenuItems(menu: Element): HTMLElement[];
|
|
14
|
-
/** How long typed characters keep adding up to one search, in milliseconds. */
|
|
15
|
-
export declare const TYPEAHEAD_TIMEOUT = 500;
|
|
16
15
|
/** What `useMenuKeys` returns. */
|
|
17
16
|
export interface MenuKeys {
|
|
18
17
|
/** The `keydown` handler for the `role="menu"` element. */
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { TreeViewSelectionMode } from '../components/TreeView.js';
|
|
3
|
+
/** What an item tells the tree about itself when it registers. */
|
|
4
|
+
export interface TreeViewItemRecord {
|
|
5
|
+
/** The value of the item it's in, or `null` at the top. */
|
|
6
|
+
parent: string | null;
|
|
7
|
+
disabled: boolean;
|
|
8
|
+
/** It has children, or `hasChildren` says it will. */
|
|
9
|
+
isParent: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** An item as a key or a click on it sees it. */
|
|
12
|
+
export interface TreeViewItemInfo extends TreeViewItemRecord {
|
|
13
|
+
value: string;
|
|
14
|
+
open: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** A box's state: checked, unchecked or mixed. */
|
|
17
|
+
export type TreeViewCheckState = boolean | 'mixed';
|
|
18
|
+
/**
|
|
19
|
+
* What an item shows of the selection: `selected` in a `single` tree,
|
|
20
|
+
* `checked` in a `checkbox` tree, and neither with `none`.
|
|
21
|
+
*/
|
|
22
|
+
export interface TreeViewItemState {
|
|
23
|
+
selected?: boolean;
|
|
24
|
+
checked?: TreeViewCheckState;
|
|
25
|
+
}
|
|
26
|
+
/** Options for `useTreeView`: the TreeView's own props. */
|
|
27
|
+
export interface TreeViewOptions {
|
|
28
|
+
mode: TreeViewSelectionMode;
|
|
29
|
+
selected?: string | null;
|
|
30
|
+
defaultSelected: string | null;
|
|
31
|
+
onSelectedChange?: (value: string) => void;
|
|
32
|
+
checked?: string[];
|
|
33
|
+
defaultChecked: string[];
|
|
34
|
+
onCheckedChange?: (checked: string[]) => void;
|
|
35
|
+
expanded?: string[];
|
|
36
|
+
defaultExpanded: string[];
|
|
37
|
+
onExpandedChange?: (expanded: string[]) => void;
|
|
38
|
+
}
|
|
39
|
+
/** What `useTreeView` hands the root and its items. */
|
|
40
|
+
export interface TreeViewEngine {
|
|
41
|
+
/** For the `<ul role="tree">`. */
|
|
42
|
+
treeRef: React.MutableRefObject<HTMLUListElement | null>;
|
|
43
|
+
/**
|
|
44
|
+
* Whether a closed item still renders its children, drawing nothing, so a
|
|
45
|
+
* check knows everything under it. Only a checkbox tree needs to.
|
|
46
|
+
*/
|
|
47
|
+
rendersClosed: boolean;
|
|
48
|
+
/** The item that holds `tabIndex={0}`. */
|
|
49
|
+
tabStop: string | null;
|
|
50
|
+
isOpen: (value: string) => boolean;
|
|
51
|
+
/**
|
|
52
|
+
* What the item shows of the selection. `path` is the values of the items
|
|
53
|
+
* above it, which decide its box until the items have registered, as on
|
|
54
|
+
* the server.
|
|
55
|
+
*/
|
|
56
|
+
stateOf: (value: string, path: string[], disabled: boolean) => TreeViewItemState;
|
|
57
|
+
/** Records an item from its layout effect. Returns the function that forgets it. */
|
|
58
|
+
register: (value: string, record: TreeViewItemRecord) => () => void;
|
|
59
|
+
/** For each item's `<li>` ref: records it, and notices focus leaving with it. */
|
|
60
|
+
setElement: (value: string, element: HTMLLIElement | null) => void;
|
|
61
|
+
/** Focus arrived on the item's own `<li>`. */
|
|
62
|
+
onFocus: (value: string, element: HTMLLIElement) => void;
|
|
63
|
+
/** Focus left the item's own `<li>`. */
|
|
64
|
+
onBlur: () => void;
|
|
65
|
+
/** A key on the item's `<li>`, after its own `onKeyDown`. */
|
|
66
|
+
onKeyDown: (event: React.KeyboardEvent<HTMLLIElement>, item: TreeViewItemInfo) => void;
|
|
67
|
+
/**
|
|
68
|
+
* A click on the item's row, or with `onToggle` on its chevron. Focus and
|
|
69
|
+
* the tab stop move to the item.
|
|
70
|
+
*/
|
|
71
|
+
onClick: (element: HTMLLIElement, item: TreeViewItemInfo, onToggle: boolean) => void;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The open state, the selection, the keys, the tab stop and the registry of
|
|
75
|
+
* a TreeView (#1096). Focus moves for real, with a roving tabindex, rather
|
|
76
|
+
* than through `aria-activedescendant`.
|
|
77
|
+
*
|
|
78
|
+
* Every item registers its value, its parent and whether it's disabled from
|
|
79
|
+
* a layout effect. In a checkbox tree a closed item's children still render
|
|
80
|
+
* and register while drawing nothing, so the registry knows every item and a
|
|
81
|
+
* check reaches all of them. The keys read the items on the page, in
|
|
82
|
+
* document order, each time they need them.
|
|
83
|
+
*
|
|
84
|
+
* @function useTreeView
|
|
85
|
+
* @param options - The TreeView's props.
|
|
86
|
+
* @returns The state and handlers the root and its items wire up.
|
|
87
|
+
*/
|
|
88
|
+
export declare function useTreeView(options: TreeViewOptions): TreeViewEngine;
|
|
@@ -29,6 +29,7 @@ export * from './components/Toast.js';
|
|
|
29
29
|
export * from './components/Dialog.js';
|
|
30
30
|
export * from './components/Carousel.js';
|
|
31
31
|
export * from './components/Reveal.js';
|
|
32
|
+
export * from './components/TreeView.js';
|
|
32
33
|
export * from './elements/Block.js';
|
|
33
34
|
export * from './elements/Box.js';
|
|
34
35
|
export * from './elements/Button.js';
|