@allxsmith/bestax-bulma 5.39.1 → 5.40.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.
@@ -1,18 +1,21 @@
1
1
  /* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
2
- import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
- import React, { createContext, forwardRef, useCallback, useEffect, useContext, useId, useRef, useMemo } from 'react';
2
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
+ import React, { createContext, forwardRef, useCallback, useEffect, useState, useContext, useId, useRef, useMemo } from 'react';
4
4
  import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
5
5
  import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
6
6
  import { withSubComponents } from '../helpers/withSubComponents.js';
7
7
  import { warnOnce } from '../helpers/devWarnings.js';
8
8
  import { useClientLayoutEffect } from '../helpers/useClientLayoutEffect.js';
9
9
  import { useTreeView } from '../helpers/useTreeView.js';
10
+ import { StatusRegion, spokenText } from '../helpers/statusRegion.js';
10
11
  import { Checkbox } from '../form/Checkbox.js';
11
12
  import { Icon } from '../elements/Icon.js';
12
13
 
13
14
  const validTreeViewSizes = ['small', 'medium', 'large'];
14
15
  // Not exported, so they stay out of the public API that `index.ts` re-exports.
15
16
  const TreeViewContext = createContext(null);
17
+ const sayLoading = (name) => `Loading ${name}`;
18
+ const sayLoaded = (name) => `${name} loaded`;
16
19
  const TOP = { path: [], hidden: false };
17
20
  const BranchContext = createContext(TOP);
18
21
  /** The box's input lets the row's click toggle it, so a change on its own does nothing. */
@@ -55,7 +58,7 @@ const isGiven = (node) => node !== undefined &&
55
58
  * <TreeView.Item value="package.json" label="package.json" icon="file" />
56
59
  * </TreeView>
57
60
  */
58
- const TreeViewRoot = forwardRef(function TreeView({ children, selectionMode = 'none', selected, defaultSelected = null, onSelectedChange, checked, defaultChecked = [], onCheckedChange, expanded, defaultExpanded = [], onExpandedChange, size, className, ...props }, ref) {
61
+ const TreeViewRoot = forwardRef(function TreeView({ children, selectionMode = 'none', selected, defaultSelected = null, onSelectedChange, checked, defaultChecked = [], onCheckedChange, expanded, defaultExpanded = [], onExpandedChange, size, loadingLabel = 'Loading…', retryLabel = 'Retry', loadingAnnouncement, loadedAnnouncement, className, ...props }, ref) {
59
62
  const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });
60
63
  const engine = useTreeView({
61
64
  mode: selectionMode,
@@ -88,9 +91,28 @@ const TreeViewRoot = forwardRef(function TreeView({ children, selectionMode = 'n
88
91
  const rootClass = usePrefixedClassNames('tree-view', {
89
92
  [`is-${size}`]: !!size && validTreeViewSizes.includes(size),
90
93
  });
94
+ // What each open item's load says, in the order they started saying it.
95
+ const [announcements, setAnnouncements] = useState([]);
96
+ const announce = useCallback((key, announcement) => {
97
+ setAnnouncements(current => {
98
+ const others = current.filter(said => said.key !== key);
99
+ return announcement ? [...others, announcement] : others;
100
+ });
101
+ }, []);
102
+ const describe = useCallback(({ kind, name, message }) => {
103
+ if (kind === 'error')
104
+ return message;
105
+ const say = kind === 'loading'
106
+ ? (loadingAnnouncement ?? sayLoading)
107
+ : (loadedAnnouncement ?? sayLoaded);
108
+ return say(name);
109
+ }, [loadingAnnouncement, loadedAnnouncement]);
91
110
  // The props are spread first, so the role and the attributes the tree
92
- // owns win over anything a caller passes along.
93
- return (jsx(TreeViewContext.Provider, { value: engine, children: jsx(BranchContext.Provider, { value: TOP, children: jsx("ul", { ...rest, ref: setRefs, className: classNames(rootClass, bulmaHelperClasses, className), role: "tree", "aria-multiselectable": engine.rendersClosed || undefined, children: children }) }) }));
111
+ // owns win over anything a caller passes along. The live region sits
112
+ // beside the tree, since a tree holds items and groups only, and it's
113
+ // there from the start, so a screen reader is listening to it before
114
+ // anything is written into it.
115
+ return (jsxs(TreeViewContext.Provider, { value: { ...engine, announce, loadingLabel, retryLabel }, children: [jsx(BranchContext.Provider, { value: TOP, children: jsx("ul", { ...rest, ref: setRefs, className: classNames(rootClass, bulmaHelperClasses, className), role: "tree", "aria-multiselectable": engine.rendersClosed || undefined, children: children }) }), jsx(StatusRegion, { items: announcements, describe: describe })] }));
94
116
  });
95
117
  /**
96
118
  * 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.
@@ -100,14 +122,53 @@ const TreeViewRoot = forwardRef(function TreeView({ children, selectionMode = 'n
100
122
  * @param {React.Ref<HTMLLIElement>} ref - Forwarded ref to the `<li>`.
101
123
  * @returns {JSX.Element | null} The rendered item, or nothing under a closed one.
102
124
  */
103
- const TreeViewItem = forwardRef(function TreeViewItem({ value, label, icon, children, hasChildren = false, disabled = false, className, onClick, onKeyDown, onFocus, onBlur, ...props }, ref) {
125
+ const TreeViewItem = forwardRef(function TreeViewItem({ value, label, icon, children, hasChildren = false, isLoading = false, loadError, onRetry, disabled = false, className, onClick, onKeyDown, onFocus, onBlur, ...props }, ref) {
104
126
  const tree = useContext(TreeViewContext);
105
127
  const branch = useContext(BranchContext);
128
+ // Also the item's key in the live region.
106
129
  const labelId = useId();
107
130
  const hasItems = React.Children.toArray(children).length > 0;
108
131
  const isParent = hasItems || hasChildren;
109
132
  const open = isParent && !!tree?.isOpen(value);
110
133
  const parent = branch.path[branch.path.length - 1] ?? null;
134
+ // The row at the end of its group, while it's open and on the page.
135
+ const shown = open && !branch.hidden;
136
+ const status = !shown
137
+ ? null
138
+ : isLoading
139
+ ? 'loading'
140
+ : isGiven(loadError)
141
+ ? 'error'
142
+ : null;
143
+ const labelRef = useRef(null);
144
+ const statusLabelRef = useRef(null);
145
+ // What the live region says follows the row: it's loading, or it failed,
146
+ // while the row says so, and it's loaded once the row goes with the item
147
+ // still open, whichever row it was, until the item closes or loads again.
148
+ // A closed item says nothing, loading or not.
149
+ const phase = shown ? (status ?? 'open') : 'closed';
150
+ const lastPhaseRef = useRef(phase);
151
+ const announce = tree?.announce;
152
+ useEffect(() => {
153
+ const was = lastPhaseRef.current;
154
+ lastPhaseRef.current = phase;
155
+ const kind = phase === 'loading' || phase === 'error'
156
+ ? phase
157
+ : phase === 'open' && (was === 'loading' || was === 'error')
158
+ ? 'loaded'
159
+ : null;
160
+ if (!kind)
161
+ return undefined;
162
+ // Only an item inside a tree can be open.
163
+ announce(labelId, {
164
+ key: labelId,
165
+ id: `${labelId}:${kind}`,
166
+ kind,
167
+ name: spokenText(labelRef.current),
168
+ message: kind === 'error' ? spokenText(statusLabelRef.current) : '',
169
+ });
170
+ return () => announce(labelId, null);
171
+ }, [phase, announce, labelId]);
111
172
  const itemClass = usePrefixedClassNames('tree-view-item');
112
173
  const groupClass = usePrefixedClassNames('tree-view-group');
113
174
  const toggleClass = usePrefixedClassNames('tree-view-toggle');
@@ -183,9 +244,55 @@ const TreeViewItem = forwardRef(function TreeViewItem({ value, label, icon, chil
183
244
  if (!(event.target instanceof HTMLInputElement)) {
184
245
  event.preventDefault();
185
246
  }
186
- }, children: jsx(Checkbox, { tabIndex: -1, checked: checked === true, indeterminate: checked === 'mixed', disabled: disabled, onChange: ignoreChange }) })), isGiven(icon) && (jsx("span", { className: iconClass, "aria-hidden": "true", children: typeof icon === 'string' ? jsx(Icon, { name: icon }) : icon })), jsx("span", { className: labelClass, id: labelId, children: label })] }), open && hasItems ? (jsx("ul", { className: groupClass, role: "group", children: items })) : (items)] }));
247
+ }, children: jsx(Checkbox, { tabIndex: -1, checked: checked === true, indeterminate: checked === 'mixed', disabled: disabled, onChange: ignoreChange }) })), isGiven(icon) && (jsx("span", { className: iconClass, "aria-hidden": "true", children: typeof icon === 'string' ? jsx(Icon, { name: icon }) : icon })), jsx("span", { className: labelClass, id: labelId, ref: labelRef, children: label })] }), open && (hasItems || status) ? (jsxs("ul", { className: groupClass, role: "group", children: [items, status && (jsx(StatusRow, { kind: status, parent: value, level: branch.path.length + 2, message: loadError, onRetry: onRetry, labelRef: statusLabelRef }))] })) : (items)] }));
187
248
  });
188
249
  TreeViewItem.displayName = 'TreeView.Item';
250
+ /**
251
+ * The row at the end of a loading item's group, or of one whose load failed.
252
+ * It's a `treeitem` the keys reach, the way they reach a disabled item, so a
253
+ * screen reader finds it. It has no value and no record, so it's never
254
+ * selected or checked, and a check never counts it. A failed load's row with
255
+ * `onRetry` retries with Enter, Space or a click, and any other is disabled.
256
+ * The Retry button is drawn, hidden from assistive tech and out of the tab
257
+ * order, the way an item's box is: the row is what's pressed, and its name
258
+ * says so. Rendered in one place, a failed load's row that starts loading
259
+ * again is the same element, so focus stays on it.
260
+ */
261
+ function StatusRow({ kind, parent, level, message, onRetry, labelRef, }) {
262
+ // Only an item inside a tree renders a group.
263
+ const tree = useContext(TreeViewContext);
264
+ // Also its key in the registry and for the tab stop, where an item has its value.
265
+ const labelId = useId();
266
+ const retryId = useId();
267
+ const retry = kind === 'error' ? onRetry : undefined;
268
+ const itemClass = usePrefixedClassNames('tree-view-item');
269
+ const rowClass = usePrefixedClassNames('tree-view-row', {
270
+ 'is-disabled': !retry,
271
+ });
272
+ const toggleClass = usePrefixedClassNames('tree-view-toggle');
273
+ const labelClass = usePrefixedClassNames('tree-view-label');
274
+ const loaderClass = usePrefixedClassNames('loader');
275
+ const retryClass = usePrefixedClassNames('button', { 'is-small': true });
276
+ const { setElement } = tree;
277
+ const setRef = useCallback((node) => setElement(labelId, node), [setElement, labelId]);
278
+ const info = {
279
+ value: labelId,
280
+ parent,
281
+ disabled: !retry,
282
+ isParent: false,
283
+ open: false,
284
+ retry,
285
+ };
286
+ return (jsx("li", { ref: setRef, className: itemClass, role: "treeitem", "aria-labelledby": retry ? `${labelId} ${retryId}` : labelId, "aria-level": level, "aria-disabled": !retry || undefined, tabIndex: tree.tabStop === labelId ? 0 : -1, onKeyDown: event => tree.onKeyDown(event, info), onFocus: event => {
287
+ // Focus in something the message holds isn't the row's.
288
+ if (event.target === event.currentTarget) {
289
+ tree.onFocus(labelId, event.currentTarget);
290
+ }
291
+ }, onBlur: event => {
292
+ if (event.target === event.currentTarget)
293
+ tree.onBlur();
294
+ }, onClick: event => tree.onClick(event.currentTarget, info, false), children: jsxs("div", { className: rowClass, children: [jsx("span", { className: toggleClass, "aria-hidden": "true", children: kind === 'loading' && jsx("span", { className: loaderClass }) }), jsx("span", { className: labelClass, id: labelId, ref: labelRef, children: kind === 'loading' ? tree.loadingLabel : message }), retry && (jsx("span", { className: retryClass, id: retryId, "aria-hidden": "true", children: tree.retryLabel }))] }) }));
295
+ }
189
296
  const TreeView = withSubComponents(TreeViewRoot, { Item: TreeViewItem }, 'TreeView');
190
297
 
191
298
  export { TreeView, TreeViewItem };
@@ -1 +1 @@
1
- {"version":3,"file":"TreeView.js","sources":["../../../src/components/TreeView.tsx"],"sourcesContent":["import React, {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { warnOnce } from '../helpers/devWarnings';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\nimport { useTreeView, type TreeViewEngine } from '../helpers/useTreeView';\nimport { Checkbox } from '../form/Checkbox';\nimport { Icon } from '../elements/Icon';\n\n/**\n * How items are picked: `none`, nothing is; `single`, one item at a time;\n * `checkbox`, any number, with a box on every item and mixed parents.\n */\nexport type TreeViewSelectionMode = 'none' | 'single' | 'checkbox';\n\nconst validTreeViewSizes = ['small', 'medium', 'large'] as const;\n\n// Not exported, so they stay out of the public API that `index.ts` re-exports.\nconst TreeViewContext = createContext<TreeViewEngine | null>(null);\n\n/** Where an item sits: the values of the items above it, and whether one of them is closed. */\ninterface Branch {\n path: string[];\n hidden: boolean;\n}\n\nconst TOP: Branch = { path: [], hidden: false };\nconst BranchContext = createContext<Branch>(TOP);\n\n/** The box's input lets the row's click toggle it, so a change on its own does nothing. */\nconst ignoreChange = () => {};\n\n/** Whether an `icon` was given something to render. */\nconst isGiven = (node: React.ReactNode) =>\n node !== undefined &&\n node !== null &&\n typeof node !== 'boolean' &&\n node !== '';\n\n/**\n * Props for the TreeView component. The helper props, the other attributes\n * and the `ref` land on the `<ul role=\"tree\">`.\n *\n * @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.\n * @extraProp {string} [aria-labelledby] - The id of a visible heading or label that names the tree, in place of `aria-label`.\n * @extraProp {React.Ref<HTMLUListElement>} [ref] - Ref forwarded to the `<ul>`.\n */\nexport interface TreeViewProps\n extends\n Omit<\n React.HTMLAttributes<HTMLUListElement>,\n | keyof BulmaClassesProps\n | 'role'\n | 'onSelect'\n | 'defaultValue'\n | 'defaultChecked'\n >,\n BulmaClassesProps {\n /**\n * `TreeView.Item`s, nested inside each other for their children. Render\n * an item's children whenever you have them, open or not: the tree hides\n * them while it's closed.\n */\n children?: React.ReactNode;\n /**\n * `none`: nothing is picked, and Enter and Space open and close a parent.\n * `single`: one item, picked with Enter, Space or a click.\n * `checkbox`: any number, checked with Space or a click. A check reaches\n * every enabled item under it, and a parent with some of them checked is mixed.\n */\n selectionMode?: TreeViewSelectionMode;\n /**\n * The selected item's value when you hold the state, or `null` for none.\n * Read with `single` only. Picking an item then only calls\n * `onSelectedChange`, and nothing changes until you pass the new value.\n */\n selected?: string | null;\n /** The item selected to begin with, when the tree holds its own state. Read with `single` only. */\n defaultSelected?: string | null;\n /**\n * Called with the value of the item picked. Not called for the one\n * already selected, and moving focus never calls it.\n */\n onSelectedChange?: (value: string) => void;\n /**\n * The checked items' values when you hold the state. Read with `checkbox`\n * only. A value checks its item, and an enabled item also counts as checked\n * when any item above it is in the list, so a parent's value stands for its\n * whole branch, loaded or not. A disabled item is checked only by its own value.\n */\n checked?: string[];\n /** The values checked to begin with, when the tree holds its own state. Read with `checkbox` only. */\n defaultChecked?: string[];\n /**\n * Called after a check or an uncheck with every item that now shows\n * checked, parents included, plus any earlier value that matches no item\n * the tree knows, left as it was. The order means nothing. Passed back as\n * `checked`, the list shows the same boxes.\n */\n onCheckedChange?: (checked: string[]) => void;\n /**\n * The open items' values when you hold the state. A value stays in the\n * list while its item's parent is closed, so the item reopens as it was.\n */\n expanded?: string[];\n /** The items open to begin with, when the tree holds its own state. */\n defaultExpanded?: string[];\n /** Called with the new list whenever an item opens or closes, `*` included. */\n onExpandedChange?: (expanded: string[]) => void;\n /** The text size, as Bulma's menu sizes it. The rows, the indent and the chevron scale with it. */\n size?: 'small' | 'medium' | 'large';\n}\n\n/**\n * Props for TreeView.Item, one row and, nested in it, its children. The other\n * attributes and the `ref` land on its `<li role=\"treeitem\">`.\n *\n * @extraProp {React.Ref<HTMLLIElement>} [ref] - Ref forwarded to the `<li>`.\n */\nexport interface TreeViewItemProps extends Omit<\n React.LiHTMLAttributes<HTMLLIElement>,\n 'role' | 'value' | 'onSelect' | 'children'\n> {\n /** **Required.** Identifies the item in `selected`, `checked` and `expanded`. Unique in the tree. */\n value: string;\n /**\n * **Required.** What the row shows, and the item's name for assistive\n * tech. Nothing in it should be a link or a button: a tree item does one\n * thing, and nothing else in its row takes focus.\n */\n label: React.ReactNode;\n /** A picture before the label: an `Icon` name, or a node. Hidden from assistive tech. */\n icon?: React.ReactNode;\n /**\n * `TreeView.Item`s under this one. Render them whenever you have them,\n * open or not: the tree hides them while it's closed, and a checkbox tree\n * needs them to know what a check reaches.\n */\n children?: React.ReactNode;\n /** Shows the item as a parent before its children are known, such as a folder that loads when it opens. */\n hasChildren?: boolean;\n /**\n * Reachable with the arrow keys, Home, End and type-ahead, so a screen\n * reader finds it, but never selected, checked, opened or closed. One\n * that's already open stays open.\n */\n disabled?: boolean;\n}\n\n/**\n * The `TreeView` component renders a tree of items you browse and pick from, the way a file explorer works: one tab stop, the arrow keys to move, and Right and Left to open and close.\n *\n * It's the APG Tree View pattern, drawn to look like Bulma's menu. It isn't\n * for site navigation: items aren't links, and a sidebar whose sections open\n * and close is `Menu`'s job. The root owns which items are open, through\n * `expanded`, `defaultExpanded` and `onExpandedChange`.\n *\n * `selectionMode` picks one of three trees. With `none`, nothing is picked.\n * With `single`, one item is, and `selected` says which. With `checkbox`,\n * each item has a box, a check reaches every enabled item under it, closed\n * branches included, and a parent with some of its items checked is mixed.\n * `selected` is read in a `single` tree only, and `checked` in a `checkbox`\n * tree only. Selection never follows focus.\n *\n * Disabled items stay reachable from the keys, so a screen reader finds\n * them. The tree needs a name, from `aria-label` or `aria-labelledby`, and a\n * development build warns when it has neither.\n *\n * @function\n * @param {TreeViewProps} props - Props for the TreeView component.\n * @param {React.Ref<HTMLUListElement>} ref - Forwarded ref to the `<ul>`.\n * @returns {JSX.Element} The rendered tree.\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/treeview/ | APG Tree View Pattern}\n *\n * @example\n * <TreeView aria-label=\"Files\" selectionMode=\"single\" defaultExpanded={['src']}>\n * <TreeView.Item value=\"src\" label=\"src\" icon=\"folder\">\n * <TreeView.Item value=\"src/index.ts\" label=\"index.ts\" icon=\"file\" />\n * </TreeView.Item>\n * <TreeView.Item value=\"package.json\" label=\"package.json\" icon=\"file\" />\n * </TreeView>\n */\nconst TreeViewRoot = forwardRef<HTMLUListElement, TreeViewProps>(\n function TreeView(\n {\n children,\n selectionMode = 'none',\n selected,\n defaultSelected = null,\n onSelectedChange,\n checked,\n defaultChecked = [],\n onCheckedChange,\n expanded,\n defaultExpanded = [],\n onExpandedChange,\n size,\n className,\n ...props\n },\n ref\n ) {\n const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });\n const engine = useTreeView({\n mode: selectionMode,\n selected,\n defaultSelected,\n onSelectedChange,\n checked,\n defaultChecked,\n onCheckedChange,\n expanded,\n defaultExpanded,\n onExpandedChange,\n });\n\n const { treeRef } = engine;\n const setRefs = useCallback(\n (node: HTMLUListElement | null) => {\n treeRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [ref, treeRef]\n );\n\n const named = Boolean(rest['aria-label'] || rest['aria-labelledby']);\n useEffect(() => {\n if (!named) {\n warnOnce(\n 'TreeView:unnamed',\n '[bestax-bulma] <TreeView> has no accessible name. Pass ' +\n 'aria-label or aria-labelledby, so a screen reader can say what ' +\n 'the tree holds.'\n );\n }\n }, [named]);\n\n const rootClass = usePrefixedClassNames('tree-view', {\n [`is-${size}`]:\n !!size && (validTreeViewSizes as readonly string[]).includes(size),\n });\n\n // The props are spread first, so the role and the attributes the tree\n // owns win over anything a caller passes along.\n return (\n <TreeViewContext.Provider value={engine}>\n <BranchContext.Provider value={TOP}>\n <ul\n {...rest}\n ref={setRefs}\n className={classNames(rootClass, bulmaHelperClasses, className)}\n role=\"tree\"\n aria-multiselectable={engine.rendersClosed || undefined}\n >\n {children}\n </ul>\n </BranchContext.Provider>\n </TreeViewContext.Provider>\n );\n }\n);\n\n/**\n * 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.\n *\n * @function\n * @param {TreeViewItemProps} props - Props for TreeView.Item.\n * @param {React.Ref<HTMLLIElement>} ref - Forwarded ref to the `<li>`.\n * @returns {JSX.Element | null} The rendered item, or nothing under a closed one.\n */\nexport const TreeViewItem = forwardRef<HTMLLIElement, TreeViewItemProps>(\n function TreeViewItem(\n {\n value,\n label,\n icon,\n children,\n hasChildren = false,\n disabled = false,\n className,\n onClick,\n onKeyDown,\n onFocus,\n onBlur,\n ...props\n },\n ref\n ) {\n const tree = useContext(TreeViewContext);\n const branch = useContext(BranchContext);\n const labelId = useId();\n const hasItems = React.Children.toArray(children).length > 0;\n const isParent = hasItems || hasChildren;\n const open = isParent && !!tree?.isOpen(value);\n const parent = branch.path[branch.path.length - 1] ?? null;\n\n const itemClass = usePrefixedClassNames('tree-view-item');\n const groupClass = usePrefixedClassNames('tree-view-group');\n const toggleClass = usePrefixedClassNames('tree-view-toggle');\n const checkClass = usePrefixedClassNames('tree-view-check');\n const iconClass = usePrefixedClassNames('tree-view-icon');\n const labelClass = usePrefixedClassNames('tree-view-label');\n\n const register = tree?.register;\n useClientLayoutEffect(() => {\n if (!register) {\n warnOnce(\n 'TreeView.Item:outside',\n '[bestax-bulma] <TreeView.Item> is outside a <TreeView>, so it ' +\n 'renders nothing. Put it inside one.'\n );\n return undefined;\n }\n return register(value, { parent, disabled, isParent });\n }, [register, value, parent, disabled, isParent]);\n\n const setElement = tree?.setElement;\n const setRefs = useCallback(\n (node: HTMLLIElement | null) => {\n // Only an item inside a tree renders an element to hand over.\n setElement!(value, node);\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [setElement, value, ref]\n );\n const rowRef = useRef<HTMLDivElement | null>(null);\n const toggleRef = useRef<HTMLSpanElement | null>(null);\n\n const childBranch = useMemo(\n () => ({\n path: [...branch.path, value],\n hidden: branch.hidden || !open,\n }),\n [branch, value, open]\n );\n\n const { selected, checked } =\n tree?.stateOf(value, branch.path, disabled) ?? {};\n const rowClass = usePrefixedClassNames('tree-view-row', {\n 'is-selected': selected,\n 'is-disabled': disabled,\n });\n\n if (!tree) return null;\n\n // While it's open the children render in its group. In a checkbox tree\n // they render while it's closed too, drawing nothing, so a check knows\n // what's under it.\n const items = (open || tree.rendersClosed) && (\n <BranchContext.Provider value={childBranch}>\n {children}\n </BranchContext.Provider>\n );\n if (branch.hidden) return <>{items}</>;\n\n const info = { value, parent, disabled, isParent, open };\n\n return (\n <li\n {...props}\n ref={setRefs}\n className={classNames(itemClass, className)}\n role=\"treeitem\"\n aria-labelledby={labelId}\n aria-level={branch.path.length + 1}\n aria-expanded={isParent ? open : undefined}\n aria-disabled={disabled || undefined}\n aria-selected={selected}\n aria-checked={checked}\n tabIndex={tree.tabStop === value ? 0 : -1}\n onKeyDown={event => {\n onKeyDown?.(event);\n tree.onKeyDown(event, info);\n }}\n onFocus={event => {\n onFocus?.(event);\n if (event.target === event.currentTarget) {\n tree.onFocus(value, event.currentTarget);\n }\n }}\n onBlur={event => {\n onBlur?.(event);\n if (event.target === event.currentTarget) tree.onBlur();\n }}\n onClick={event => {\n onClick?.(event);\n // A click in its row is its own, and so is one on the item itself,\n // as a test's click on the treeitem is. One in its group belongs\n // to the item inside it, or to nothing. The chevron's box is on\n // every row, but it's a chevron only on a parent: on a leaf it's\n // more of the row.\n const target = event.target as Node;\n if (\n target === event.currentTarget ||\n rowRef.current!.contains(target)\n ) {\n tree.onClick(\n event.currentTarget,\n info,\n isParent && toggleRef.current!.contains(target)\n );\n }\n }}\n >\n <div className={rowClass} ref={rowRef}>\n <span className={toggleClass} aria-hidden=\"true\" ref={toggleRef} />\n {checked !== undefined && (\n <span\n className={checkClass}\n aria-hidden=\"true\"\n onClick={event => {\n // A click on the box's label is followed by one on its\n // input, and both reach the item. The label's is cancelled,\n // so the item toggles once.\n if (!(event.target instanceof HTMLInputElement)) {\n event.preventDefault();\n }\n }}\n >\n <Checkbox\n tabIndex={-1}\n checked={checked === true}\n indeterminate={checked === 'mixed'}\n disabled={disabled}\n onChange={ignoreChange}\n />\n </span>\n )}\n {isGiven(icon) && (\n <span className={iconClass} aria-hidden=\"true\">\n {typeof icon === 'string' ? <Icon name={icon} /> : icon}\n </span>\n )}\n <span className={labelClass} id={labelId}>\n {label}\n </span>\n </div>\n {open && hasItems ? (\n <ul className={groupClass} role=\"group\">\n {items}\n </ul>\n ) : (\n items\n )}\n </li>\n );\n }\n);\n\nTreeViewItem.displayName = 'TreeView.Item';\n\nexport const TreeView = withSubComponents(\n TreeViewRoot,\n { Item: TreeViewItem },\n 'TreeView'\n);\n\nexport default TreeView;\n"],"names":["_jsx","_Fragment","_jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"TreeView.js","sources":["../../../src/components/TreeView.tsx"],"sourcesContent":["import React, {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { warnOnce } from '../helpers/devWarnings';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\nimport { useTreeView, type TreeViewEngine } from '../helpers/useTreeView';\nimport { StatusRegion, spokenText } from '../helpers/statusRegion';\nimport { Checkbox } from '../form/Checkbox';\nimport { Icon } from '../elements/Icon';\n\n/**\n * How items are picked: `none`, nothing is; `single`, one item at a time;\n * `checkbox`, any number, with a box on every item and mixed parents.\n */\nexport type TreeViewSelectionMode = 'none' | 'single' | 'checkbox';\n\nconst validTreeViewSizes = ['small', 'medium', 'large'] as const;\n\n/** What an open item's load says in the tree's live region. */\ninterface LoadAnnouncement {\n /** The item's key, so what it says next replaces this. */\n key: string;\n /** The key and the kind: the region says it once each time it appears. */\n id: string;\n kind: 'loading' | 'loaded' | 'error';\n /** The item's name, read off its label. */\n name: string;\n /** A failed load's message, read off its row. */\n message: string;\n}\n\n/** What the root hands its items: the engine, the live region, and the rows' words. */\ninterface TreeContextValue extends TreeViewEngine {\n /** Puts what an item's load says in the live region, or takes it out with `null`. */\n announce: (key: string, announcement: LoadAnnouncement | null) => void;\n loadingLabel: string;\n retryLabel: string;\n}\n\n// Not exported, so they stay out of the public API that `index.ts` re-exports.\nconst TreeViewContext = createContext<TreeContextValue | null>(null);\n\nconst sayLoading = (name: string) => `Loading ${name}`;\nconst sayLoaded = (name: string) => `${name} loaded`;\n\n/** Where an item sits: the values of the items above it, and whether one of them is closed. */\ninterface Branch {\n path: string[];\n hidden: boolean;\n}\n\nconst TOP: Branch = { path: [], hidden: false };\nconst BranchContext = createContext<Branch>(TOP);\n\n/** The box's input lets the row's click toggle it, so a change on its own does nothing. */\nconst ignoreChange = () => {};\n\n/** Whether an `icon` was given something to render. */\nconst isGiven = (node: React.ReactNode) =>\n node !== undefined &&\n node !== null &&\n typeof node !== 'boolean' &&\n node !== '';\n\n/**\n * Props for the TreeView component. The helper props, the other attributes\n * and the `ref` land on the `<ul role=\"tree\">`.\n *\n * @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.\n * @extraProp {string} [aria-labelledby] - The id of a visible heading or label that names the tree, in place of `aria-label`.\n * @extraProp {React.Ref<HTMLUListElement>} [ref] - Ref forwarded to the `<ul>`.\n */\nexport interface TreeViewProps\n extends\n Omit<\n React.HTMLAttributes<HTMLUListElement>,\n | keyof BulmaClassesProps\n | 'role'\n | 'onSelect'\n | 'defaultValue'\n | 'defaultChecked'\n >,\n BulmaClassesProps {\n /**\n * `TreeView.Item`s, nested inside each other for their children. Render\n * an item's children whenever you have them, open or not: the tree hides\n * them while it's closed.\n */\n children?: React.ReactNode;\n /**\n * `none`: nothing is picked, and Enter and Space open and close a parent.\n * `single`: one item, picked with Enter, Space or a click.\n * `checkbox`: any number, checked with Space or a click. A check reaches\n * every enabled item under it, and a parent with some of them checked is mixed.\n */\n selectionMode?: TreeViewSelectionMode;\n /**\n * The selected item's value when you hold the state, or `null` for none.\n * Read with `single` only. Picking an item then only calls\n * `onSelectedChange`, and nothing changes until you pass the new value.\n */\n selected?: string | null;\n /** The item selected to begin with, when the tree holds its own state. Read with `single` only. */\n defaultSelected?: string | null;\n /**\n * Called with the value of the item picked. Not called for the one\n * already selected, and moving focus never calls it.\n */\n onSelectedChange?: (value: string) => void;\n /**\n * The checked items' values when you hold the state. Read with `checkbox`\n * only. A value checks its item, and an enabled item also counts as checked\n * when any item above it is in the list, so a parent's value stands for its\n * whole branch, loaded or not. A disabled item is checked only by its own value.\n */\n checked?: string[];\n /** The values checked to begin with, when the tree holds its own state. Read with `checkbox` only. */\n defaultChecked?: string[];\n /**\n * Called after a check or an uncheck with every item that now shows\n * checked, parents included, plus any earlier value that matches no item\n * the tree knows, left as it was. The order means nothing. Passed back as\n * `checked`, the list shows the same boxes.\n */\n onCheckedChange?: (checked: string[]) => void;\n /**\n * The open items' values when you hold the state. A value stays in the\n * list while its item's parent is closed, so the item reopens as it was.\n */\n expanded?: string[];\n /** The items open to begin with, when the tree holds its own state. */\n defaultExpanded?: string[];\n /** Called with the new list whenever an item opens or closes, `*` included. */\n onExpandedChange?: (expanded: string[]) => void;\n /** The text size, as Bulma's menu sizes it. The rows, the indent and the chevron scale with it. */\n size?: 'small' | 'medium' | 'large';\n /** What the row in a loading item's group says. In your app's language. */\n loadingLabel?: string;\n /** The Retry button's text on a failed load's row. In your app's language. */\n retryLabel?: string;\n /**\n * What the live region says when an open item starts loading, built from\n * the item's name. In your app's language. Default: `` `Loading ${name}` ``.\n */\n loadingAnnouncement?: (name: string) => string;\n /**\n * What the live region says when that load finishes. In your app's\n * language. Default: `` `${name} loaded` ``.\n */\n loadedAnnouncement?: (name: string) => string;\n}\n\n/**\n * Props for TreeView.Item, one row and, nested in it, its children. The other\n * attributes and the `ref` land on its `<li role=\"treeitem\">`.\n *\n * @extraProp {React.Ref<HTMLLIElement>} [ref] - Ref forwarded to the `<li>`.\n */\nexport interface TreeViewItemProps extends Omit<\n React.LiHTMLAttributes<HTMLLIElement>,\n 'role' | 'value' | 'onSelect' | 'children'\n> {\n /** **Required.** Identifies the item in `selected`, `checked` and `expanded`. Unique in the tree. */\n value: string;\n /**\n * **Required.** What the row shows, and the item's name for assistive\n * tech. Nothing in it should be a link or a button: a tree item does one\n * thing, and nothing else in its row takes focus.\n */\n label: React.ReactNode;\n /** A picture before the label: an `Icon` name, or a node. Hidden from assistive tech. */\n icon?: React.ReactNode;\n /**\n * `TreeView.Item`s under this one. Render them whenever you have them,\n * open or not: the tree hides them while it's closed, and a checkbox tree\n * needs them to know what a check reaches.\n */\n children?: React.ReactNode;\n /** Shows the item as a parent before its children are known, such as a folder that loads when it opens. */\n hasChildren?: boolean;\n /**\n * Its children are on their way. While it's open, its group ends in a row\n * that says so, and the tree's live region says it's loading, then that\n * it's loaded once this goes back to `false`. A parent only: pair it with\n * `hasChildren`, or with the children it already has.\n */\n isLoading?: boolean;\n /**\n * Its children didn't load. While it's open, its group ends in a row with\n * this message, and a Retry button when there's an `onRetry`, and the live\n * region reads the message out, so name the item in it (\"Couldn't load\n * src\"), then says it's loaded once this goes with the item still open. A\n * parent only, like `isLoading`. Nothing in it should be a link or a\n * button: the row is what's pressed. `isLoading` wins while both are given.\n */\n loadError?: React.ReactNode;\n /**\n * Called by the Retry button on a failed load's row, and by Enter or Space\n * there. Set `isLoading` while the retry runs, so the live region says it's\n * loading, and reads the message out again if it fails again. The same\n * message passed a second time with no loading between is no change the\n * tree can see.\n */\n onRetry?: () => void;\n /**\n * Reachable with the arrow keys, Home, End and type-ahead, so a screen\n * reader finds it, but never selected, checked, opened or closed. One\n * that's already open stays open.\n */\n disabled?: boolean;\n}\n\n/**\n * The `TreeView` component renders a tree of items you browse and pick from, the way a file explorer works: one tab stop, the arrow keys to move, and Right and Left to open and close.\n *\n * It's the APG Tree View pattern, drawn to look like Bulma's menu. It isn't\n * for site navigation: items aren't links, and a sidebar whose sections open\n * and close is `Menu`'s job. The root owns which items are open, through\n * `expanded`, `defaultExpanded` and `onExpandedChange`.\n *\n * `selectionMode` picks one of three trees. With `none`, nothing is picked.\n * With `single`, one item is, and `selected` says which. With `checkbox`,\n * each item has a box, a check reaches every enabled item under it, closed\n * branches included, and a parent with some of its items checked is mixed.\n * `selected` is read in a `single` tree only, and `checked` in a `checkbox`\n * tree only. Selection never follows focus.\n *\n * Disabled items stay reachable from the keys, so a screen reader finds\n * them. The tree needs a name, from `aria-label` or `aria-labelledby`, and a\n * development build warns when it has neither.\n *\n * @function\n * @param {TreeViewProps} props - Props for the TreeView component.\n * @param {React.Ref<HTMLUListElement>} ref - Forwarded ref to the `<ul>`.\n * @returns {JSX.Element} The rendered tree.\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/treeview/ | APG Tree View Pattern}\n *\n * @example\n * <TreeView aria-label=\"Files\" selectionMode=\"single\" defaultExpanded={['src']}>\n * <TreeView.Item value=\"src\" label=\"src\" icon=\"folder\">\n * <TreeView.Item value=\"src/index.ts\" label=\"index.ts\" icon=\"file\" />\n * </TreeView.Item>\n * <TreeView.Item value=\"package.json\" label=\"package.json\" icon=\"file\" />\n * </TreeView>\n */\nconst TreeViewRoot = forwardRef<HTMLUListElement, TreeViewProps>(\n function TreeView(\n {\n children,\n selectionMode = 'none',\n selected,\n defaultSelected = null,\n onSelectedChange,\n checked,\n defaultChecked = [],\n onCheckedChange,\n expanded,\n defaultExpanded = [],\n onExpandedChange,\n size,\n loadingLabel = 'Loading…',\n retryLabel = 'Retry',\n loadingAnnouncement,\n loadedAnnouncement,\n className,\n ...props\n },\n ref\n ) {\n const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });\n const engine = useTreeView({\n mode: selectionMode,\n selected,\n defaultSelected,\n onSelectedChange,\n checked,\n defaultChecked,\n onCheckedChange,\n expanded,\n defaultExpanded,\n onExpandedChange,\n });\n\n const { treeRef } = engine;\n const setRefs = useCallback(\n (node: HTMLUListElement | null) => {\n treeRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [ref, treeRef]\n );\n\n const named = Boolean(rest['aria-label'] || rest['aria-labelledby']);\n useEffect(() => {\n if (!named) {\n warnOnce(\n 'TreeView:unnamed',\n '[bestax-bulma] <TreeView> has no accessible name. Pass ' +\n 'aria-label or aria-labelledby, so a screen reader can say what ' +\n 'the tree holds.'\n );\n }\n }, [named]);\n\n const rootClass = usePrefixedClassNames('tree-view', {\n [`is-${size}`]:\n !!size && (validTreeViewSizes as readonly string[]).includes(size),\n });\n\n // What each open item's load says, in the order they started saying it.\n const [announcements, setAnnouncements] = useState<LoadAnnouncement[]>([]);\n const announce = useCallback(\n (key: string, announcement: LoadAnnouncement | null) => {\n setAnnouncements(current => {\n const others = current.filter(said => said.key !== key);\n return announcement ? [...others, announcement] : others;\n });\n },\n []\n );\n const describe = useCallback(\n ({ kind, name, message }: LoadAnnouncement) => {\n if (kind === 'error') return message;\n const say =\n kind === 'loading'\n ? (loadingAnnouncement ?? sayLoading)\n : (loadedAnnouncement ?? sayLoaded);\n return say(name);\n },\n [loadingAnnouncement, loadedAnnouncement]\n );\n\n // The props are spread first, so the role and the attributes the tree\n // owns win over anything a caller passes along. The live region sits\n // beside the tree, since a tree holds items and groups only, and it's\n // there from the start, so a screen reader is listening to it before\n // anything is written into it.\n return (\n <TreeViewContext.Provider\n value={{ ...engine, announce, loadingLabel, retryLabel }}\n >\n <BranchContext.Provider value={TOP}>\n <ul\n {...rest}\n ref={setRefs}\n className={classNames(rootClass, bulmaHelperClasses, className)}\n role=\"tree\"\n aria-multiselectable={engine.rendersClosed || undefined}\n >\n {children}\n </ul>\n </BranchContext.Provider>\n <StatusRegion items={announcements} describe={describe} />\n </TreeViewContext.Provider>\n );\n }\n);\n\n/**\n * 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.\n *\n * @function\n * @param {TreeViewItemProps} props - Props for TreeView.Item.\n * @param {React.Ref<HTMLLIElement>} ref - Forwarded ref to the `<li>`.\n * @returns {JSX.Element | null} The rendered item, or nothing under a closed one.\n */\nexport const TreeViewItem = forwardRef<HTMLLIElement, TreeViewItemProps>(\n function TreeViewItem(\n {\n value,\n label,\n icon,\n children,\n hasChildren = false,\n isLoading = false,\n loadError,\n onRetry,\n disabled = false,\n className,\n onClick,\n onKeyDown,\n onFocus,\n onBlur,\n ...props\n },\n ref\n ) {\n const tree = useContext(TreeViewContext);\n const branch = useContext(BranchContext);\n // Also the item's key in the live region.\n const labelId = useId();\n const hasItems = React.Children.toArray(children).length > 0;\n const isParent = hasItems || hasChildren;\n const open = isParent && !!tree?.isOpen(value);\n const parent = branch.path[branch.path.length - 1] ?? null;\n\n // The row at the end of its group, while it's open and on the page.\n const shown = open && !branch.hidden;\n const status = !shown\n ? null\n : isLoading\n ? 'loading'\n : isGiven(loadError)\n ? 'error'\n : null;\n const labelRef = useRef<HTMLSpanElement | null>(null);\n const statusLabelRef = useRef<HTMLSpanElement | null>(null);\n\n // What the live region says follows the row: it's loading, or it failed,\n // while the row says so, and it's loaded once the row goes with the item\n // still open, whichever row it was, until the item closes or loads again.\n // A closed item says nothing, loading or not.\n const phase = shown ? (status ?? 'open') : 'closed';\n const lastPhaseRef = useRef(phase);\n const announce = tree?.announce;\n useEffect(() => {\n const was = lastPhaseRef.current;\n lastPhaseRef.current = phase;\n const kind =\n phase === 'loading' || phase === 'error'\n ? phase\n : phase === 'open' && (was === 'loading' || was === 'error')\n ? 'loaded'\n : null;\n if (!kind) return undefined;\n // Only an item inside a tree can be open.\n announce!(labelId, {\n key: labelId,\n id: `${labelId}:${kind}`,\n kind,\n name: spokenText(labelRef.current!),\n message: kind === 'error' ? spokenText(statusLabelRef.current!) : '',\n });\n return () => announce!(labelId, null);\n }, [phase, announce, labelId]);\n\n const itemClass = usePrefixedClassNames('tree-view-item');\n const groupClass = usePrefixedClassNames('tree-view-group');\n const toggleClass = usePrefixedClassNames('tree-view-toggle');\n const checkClass = usePrefixedClassNames('tree-view-check');\n const iconClass = usePrefixedClassNames('tree-view-icon');\n const labelClass = usePrefixedClassNames('tree-view-label');\n\n const register = tree?.register;\n useClientLayoutEffect(() => {\n if (!register) {\n warnOnce(\n 'TreeView.Item:outside',\n '[bestax-bulma] <TreeView.Item> is outside a <TreeView>, so it ' +\n 'renders nothing. Put it inside one.'\n );\n return undefined;\n }\n return register(value, { parent, disabled, isParent });\n }, [register, value, parent, disabled, isParent]);\n\n const setElement = tree?.setElement;\n const setRefs = useCallback(\n (node: HTMLLIElement | null) => {\n // Only an item inside a tree renders an element to hand over.\n setElement!(value, node);\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [setElement, value, ref]\n );\n const rowRef = useRef<HTMLDivElement | null>(null);\n const toggleRef = useRef<HTMLSpanElement | null>(null);\n\n const childBranch = useMemo(\n () => ({\n path: [...branch.path, value],\n hidden: branch.hidden || !open,\n }),\n [branch, value, open]\n );\n\n const { selected, checked } =\n tree?.stateOf(value, branch.path, disabled) ?? {};\n const rowClass = usePrefixedClassNames('tree-view-row', {\n 'is-selected': selected,\n 'is-disabled': disabled,\n });\n\n if (!tree) return null;\n\n // While it's open the children render in its group. In a checkbox tree\n // they render while it's closed too, drawing nothing, so a check knows\n // what's under it.\n const items = (open || tree.rendersClosed) && (\n <BranchContext.Provider value={childBranch}>\n {children}\n </BranchContext.Provider>\n );\n if (branch.hidden) return <>{items}</>;\n\n const info = { value, parent, disabled, isParent, open };\n\n return (\n <li\n {...props}\n ref={setRefs}\n className={classNames(itemClass, className)}\n role=\"treeitem\"\n aria-labelledby={labelId}\n aria-level={branch.path.length + 1}\n aria-expanded={isParent ? open : undefined}\n aria-disabled={disabled || undefined}\n aria-selected={selected}\n aria-checked={checked}\n tabIndex={tree.tabStop === value ? 0 : -1}\n onKeyDown={event => {\n onKeyDown?.(event);\n tree.onKeyDown(event, info);\n }}\n onFocus={event => {\n onFocus?.(event);\n if (event.target === event.currentTarget) {\n tree.onFocus(value, event.currentTarget);\n }\n }}\n onBlur={event => {\n onBlur?.(event);\n if (event.target === event.currentTarget) tree.onBlur();\n }}\n onClick={event => {\n onClick?.(event);\n // A click in its row is its own, and so is one on the item itself,\n // as a test's click on the treeitem is. One in its group belongs\n // to the item inside it, or to nothing. The chevron's box is on\n // every row, but it's a chevron only on a parent: on a leaf it's\n // more of the row.\n const target = event.target as Node;\n if (\n target === event.currentTarget ||\n rowRef.current!.contains(target)\n ) {\n tree.onClick(\n event.currentTarget,\n info,\n isParent && toggleRef.current!.contains(target)\n );\n }\n }}\n >\n <div className={rowClass} ref={rowRef}>\n <span className={toggleClass} aria-hidden=\"true\" ref={toggleRef} />\n {checked !== undefined && (\n <span\n className={checkClass}\n aria-hidden=\"true\"\n onClick={event => {\n // A click on the box's label is followed by one on its\n // input, and both reach the item. The label's is cancelled,\n // so the item toggles once.\n if (!(event.target instanceof HTMLInputElement)) {\n event.preventDefault();\n }\n }}\n >\n <Checkbox\n tabIndex={-1}\n checked={checked === true}\n indeterminate={checked === 'mixed'}\n disabled={disabled}\n onChange={ignoreChange}\n />\n </span>\n )}\n {isGiven(icon) && (\n <span className={iconClass} aria-hidden=\"true\">\n {typeof icon === 'string' ? <Icon name={icon} /> : icon}\n </span>\n )}\n <span className={labelClass} id={labelId} ref={labelRef}>\n {label}\n </span>\n </div>\n {open && (hasItems || status) ? (\n <ul className={groupClass} role=\"group\">\n {items}\n {status && (\n <StatusRow\n kind={status}\n parent={value}\n level={branch.path.length + 2}\n message={loadError}\n onRetry={onRetry}\n labelRef={statusLabelRef}\n />\n )}\n </ul>\n ) : (\n items\n )}\n </li>\n );\n }\n);\n\nTreeViewItem.displayName = 'TreeView.Item';\n\n/** Props for the row at the end of a loading item's group, or a failed load's. */\ninterface StatusRowProps {\n /** `loading`, or `error` for a load that failed. */\n kind: 'loading' | 'error';\n /** The value of the item it's in. */\n parent: string;\n /** Its `aria-level`, one under the item it's in. */\n level: number;\n /** A failed load's message. */\n message: React.ReactNode;\n /** Retries a failed load. */\n onRetry?: () => void;\n /** For its label, which the item reads a failed load's message off. */\n labelRef: React.Ref<HTMLSpanElement>;\n}\n\n/**\n * The row at the end of a loading item's group, or of one whose load failed.\n * It's a `treeitem` the keys reach, the way they reach a disabled item, so a\n * screen reader finds it. It has no value and no record, so it's never\n * selected or checked, and a check never counts it. A failed load's row with\n * `onRetry` retries with Enter, Space or a click, and any other is disabled.\n * The Retry button is drawn, hidden from assistive tech and out of the tab\n * order, the way an item's box is: the row is what's pressed, and its name\n * says so. Rendered in one place, a failed load's row that starts loading\n * again is the same element, so focus stays on it.\n */\nfunction StatusRow({\n kind,\n parent,\n level,\n message,\n onRetry,\n labelRef,\n}: StatusRowProps) {\n // Only an item inside a tree renders a group.\n const tree = useContext(TreeViewContext)!;\n // Also its key in the registry and for the tab stop, where an item has its value.\n const labelId = useId();\n const retryId = useId();\n const retry = kind === 'error' ? onRetry : undefined;\n\n const itemClass = usePrefixedClassNames('tree-view-item');\n const rowClass = usePrefixedClassNames('tree-view-row', {\n 'is-disabled': !retry,\n });\n const toggleClass = usePrefixedClassNames('tree-view-toggle');\n const labelClass = usePrefixedClassNames('tree-view-label');\n const loaderClass = usePrefixedClassNames('loader');\n const retryClass = usePrefixedClassNames('button', { 'is-small': true });\n\n const { setElement } = tree;\n const setRef = useCallback(\n (node: HTMLLIElement | null) => setElement(labelId, node),\n [setElement, labelId]\n );\n const info = {\n value: labelId,\n parent,\n disabled: !retry,\n isParent: false,\n open: false,\n retry,\n };\n\n return (\n <li\n ref={setRef}\n className={itemClass}\n role=\"treeitem\"\n aria-labelledby={retry ? `${labelId} ${retryId}` : labelId}\n aria-level={level}\n aria-disabled={!retry || undefined}\n tabIndex={tree.tabStop === labelId ? 0 : -1}\n onKeyDown={event => tree.onKeyDown(event, info)}\n onFocus={event => {\n // Focus in something the message holds isn't the row's.\n if (event.target === event.currentTarget) {\n tree.onFocus(labelId, event.currentTarget);\n }\n }}\n onBlur={event => {\n if (event.target === event.currentTarget) tree.onBlur();\n }}\n onClick={event => tree.onClick(event.currentTarget, info, false)}\n >\n <div className={rowClass}>\n <span className={toggleClass} aria-hidden=\"true\">\n {kind === 'loading' && <span className={loaderClass} />}\n </span>\n <span className={labelClass} id={labelId} ref={labelRef}>\n {kind === 'loading' ? tree.loadingLabel : message}\n </span>\n {retry && (\n <span className={retryClass} id={retryId} aria-hidden=\"true\">\n {tree.retryLabel}\n </span>\n )}\n </div>\n </li>\n );\n}\n\nexport const TreeView = withSubComponents(\n TreeViewRoot,\n { Item: TreeViewItem },\n 'TreeView'\n);\n\nexport default TreeView;\n"],"names":["_jsxs","_jsx","_Fragment"],"mappings":"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"}
@@ -213,6 +213,13 @@ function useTreeView(options) {
213
213
  if (!item.disabled)
214
214
  list.forEach(action => run[action](item));
215
215
  };
216
+ /** Enter, Space and a click on the row: a failed load's row retries. */
217
+ const press = (item, list) => {
218
+ if (item.retry)
219
+ item.retry();
220
+ else
221
+ act(item, list);
222
+ };
216
223
  // After every render, put the stop where it belongs. While focus is in
217
224
  // the tree it's the focused item. Otherwise it's the selected item, or the
218
225
  // first checked one on the page, and failing that it stays where it was.
@@ -328,11 +335,11 @@ function useTreeView(options) {
328
335
  // A held key acts once.
329
336
  case 'Enter':
330
337
  if (!event.repeat)
331
- act(item, actions.enter);
338
+ press(item, actions.enter);
332
339
  break;
333
340
  case ' ':
334
341
  if (!event.repeat)
335
- act(item, actions.space);
342
+ press(item, actions.space);
336
343
  break;
337
344
  case '*': {
338
345
  const closed = [];
@@ -359,7 +366,10 @@ function useTreeView(options) {
359
366
  };
360
367
  const onClick = (element, item, onToggle) => {
361
368
  element.focus();
362
- act(item, onToggle ? ['open'] : actions.click);
369
+ if (onToggle)
370
+ act(item, ['open']);
371
+ else
372
+ press(item, actions.click);
363
373
  };
364
374
  return {
365
375
  treeRef,
@@ -1 +1 @@
1
- {"version":3,"file":"useTreeView.js","sources":["../../../src/helpers/useTreeView.ts"],"sourcesContent":["// INTERNAL: deliberately not exported from src/index.ts.\nimport { useCallback, useReducer, useRef, useState } from 'react';\nimport type React from 'react';\nimport type { TreeViewSelectionMode } from '../components/TreeView';\nimport { useClientLayoutEffect } from './useClientLayoutEffect';\nimport { getActiveElementInTree } from './shadowDom';\nimport { typeaheadMatch, typeaheadText, useTypeahead } from './typeahead';\n\n/** What an item tells the tree about itself when it registers. */\nexport interface TreeViewItemRecord {\n /** The value of the item it's in, or `null` at the top. */\n parent: string | null;\n disabled: boolean;\n /** It has children, or `hasChildren` says it will. */\n isParent: boolean;\n}\n\n/** An item as a key or a click on it sees it. */\nexport interface TreeViewItemInfo extends TreeViewItemRecord {\n value: string;\n open: boolean;\n}\n\n/** A box's state: checked, unchecked or mixed. */\nexport type TreeViewCheckState = boolean | 'mixed';\n\n/**\n * What an item shows of the selection: `selected` in a `single` tree,\n * `checked` in a `checkbox` tree, and neither with `none`.\n */\nexport interface TreeViewItemState {\n selected?: boolean;\n checked?: TreeViewCheckState;\n}\n\ntype Action = 'open' | 'select' | 'check';\n\n/**\n * What Enter, Space and a click on the row do in each mode, from the tables\n * in #1096. `open` opens or closes a parent and does nothing on a leaf. A\n * click on the chevron only ever opens or closes.\n */\nconst MODES: Record<\n TreeViewSelectionMode,\n { enter: Action[]; space: Action[]; click: Action[] }\n> = {\n none: { enter: ['open'], space: ['open'], click: ['open'] },\n single: { enter: ['select'], space: ['select'], click: ['select', 'open'] },\n checkbox: { enter: ['open'], space: ['check'], click: ['check'] },\n};\n\n/** Left and Right, swapped for a right-to-left page. */\nconst MIRRORED: Record<string, string> = {\n ArrowLeft: 'ArrowRight',\n ArrowRight: 'ArrowLeft',\n};\n\n/** An IME is composing, so the key belongs to it (`keyCode` 229 is Safari's word for it). */\nconst isComposing = (event: React.KeyboardEvent): boolean =>\n event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229;\n\n/** The items a tree knows, and their elements while they're on the page. */\ninterface Registry {\n records: Map<string, TreeViewItemRecord>;\n // By value, for an item whose ref lets go, which hands over no element.\n elements: Map<string, HTMLLIElement>;\n // Weak, so an element that leaves the page needn't be forgotten by hand.\n values: WeakMap<Element, string>;\n}\n\n/** The registry's items on the page, in document order. */\nconst shownIn = (tree: Element, { values }: Registry): HTMLElement[] =>\n Array.from(tree.querySelectorAll<HTMLElement>('[role=\"treeitem\"]')).filter(\n element => values.has(element)\n );\n\n/** The item an item on the page sits in: its group's `<li>`, or none at the top. */\nfunction parentItemOf(element: Element): HTMLElement | null {\n const group = element.parentElement!;\n return group.getAttribute('role') === 'group' ? group.parentElement : null;\n}\n\n/** The values of the items an item on the page is in, from the top. */\nfunction pathOf(element: Element, { values }: Registry): string[] {\n const path: string[] = [];\n for (let at = parentItemOf(element); at; at = parentItemOf(at)) {\n path.unshift(values.get(at)!);\n }\n return path;\n}\n\n/**\n * Every known item's check state, by the rules in #1096:\n *\n * - a disabled item is checked only when its own value is listed;\n * - an enabled item with no enabled items anywhere under it is checked when\n * it, or any item above it, is listed;\n * - any other enabled item follows the items of that second kind in its\n * branch: checked when they all are, unchecked when none is, mixed between.\n *\n * Also returns the items of the second kind, which are what a toggle sets.\n */\nfunction readChecks(\n records: Map<string, TreeViewItemRecord>,\n listed: Set<string>\n): { states: Map<string, TreeViewCheckState>; ends: string[] } {\n const kids = new Map<string | null, string[]>();\n records.forEach(({ parent }, value) => {\n kids.set(parent, [...(kids.get(parent) ?? []), value]);\n });\n const states = new Map<string, TreeViewCheckState>();\n const ends: string[] = [];\n // How many enabled ends the branch holds, and how many are checked.\n const visit = (value: string, above: boolean): [number, number] => {\n const marked = above || listed.has(value);\n let total = 0;\n let on = 0;\n for (const kid of kids.get(value) ?? []) {\n const [t, o] = visit(kid, marked);\n total += t;\n on += o;\n }\n if (records.get(value)!.disabled) {\n states.set(value, listed.has(value));\n return [total, on];\n }\n if (total === 0) {\n states.set(value, marked);\n ends.push(value);\n return [1, marked ? 1 : 0];\n }\n states.set(value, on === total ? true : on > 0 && 'mixed');\n return [total, on];\n };\n for (const top of kids.get(null) ?? []) visit(top, false);\n return { states, ends };\n}\n\n/**\n * The list a toggle of `value` leaves: it and every enabled item under it\n * take the opposite of its state (a mixed one checks), and the rest is read\n * back by the rules. That's every item that shows checked, parents\n * included, plus any listed value no item has.\n */\nfunction toggledList(\n records: Map<string, TreeViewItemRecord>,\n list: string[],\n value: string\n): string[] {\n const { states, ends } = readChecks(records, new Set(list));\n const to = states.get(value) !== true;\n // An end was reached from the top, so everything above it is known.\n const under = (end: string) => {\n for (let at: string | null = end; at !== null;) {\n if (at === value) return true;\n at = records.get(at)!.parent;\n }\n return false;\n };\n const seed = new Set(\n ends.filter(end => (under(end) ? to : states.get(end) === true))\n );\n records.forEach(({ disabled }, item) => {\n if (disabled && states.get(item) === true) seed.add(item);\n });\n const after = readChecks(records, seed).states;\n return [\n ...Array.from(after)\n .filter(([, state]) => state === true)\n .map(([item]) => item),\n ...list.filter(item => !records.has(item)),\n ];\n}\n\n/** A value the caller holds, or one this hook holds when the caller doesn't. */\nfunction useControlled<T>(controlled: T | undefined, initial: T) {\n const [own, setOwn] = useState(initial);\n const isControlled = controlled !== undefined;\n const set = (next: T) => {\n if (!isControlled) setOwn(next);\n };\n return [isControlled ? controlled : own, set] as const;\n}\n\n/** Options for `useTreeView`: the TreeView's own props. */\nexport interface TreeViewOptions {\n mode: TreeViewSelectionMode;\n selected?: string | null;\n defaultSelected: string | null;\n onSelectedChange?: (value: string) => void;\n checked?: string[];\n defaultChecked: string[];\n onCheckedChange?: (checked: string[]) => void;\n expanded?: string[];\n defaultExpanded: string[];\n onExpandedChange?: (expanded: string[]) => void;\n}\n\n/** What `useTreeView` hands the root and its items. */\nexport interface TreeViewEngine {\n /** For the `<ul role=\"tree\">`. */\n treeRef: React.MutableRefObject<HTMLUListElement | null>;\n /**\n * Whether a closed item still renders its children, drawing nothing, so a\n * check knows everything under it. Only a checkbox tree needs to.\n */\n rendersClosed: boolean;\n /** The item that holds `tabIndex={0}`. */\n tabStop: string | null;\n isOpen: (value: string) => boolean;\n /**\n * What the item shows of the selection. `path` is the values of the items\n * above it, which decide its box until the items have registered, as on\n * the server.\n */\n stateOf: (\n value: string,\n path: string[],\n disabled: boolean\n ) => TreeViewItemState;\n /** Records an item from its layout effect. Returns the function that forgets it. */\n register: (value: string, record: TreeViewItemRecord) => () => void;\n /** For each item's `<li>` ref: records it, and notices focus leaving with it. */\n setElement: (value: string, element: HTMLLIElement | null) => void;\n /** Focus arrived on the item's own `<li>`. */\n onFocus: (value: string, element: HTMLLIElement) => void;\n /** Focus left the item's own `<li>`. */\n onBlur: () => void;\n /** A key on the item's `<li>`, after its own `onKeyDown`. */\n onKeyDown: (\n event: React.KeyboardEvent<HTMLLIElement>,\n item: TreeViewItemInfo\n ) => void;\n /**\n * A click on the item's row, or with `onToggle` on its chevron. Focus and\n * the tab stop move to the item.\n */\n onClick: (\n element: HTMLLIElement,\n item: TreeViewItemInfo,\n onToggle: boolean\n ) => void;\n}\n\n/**\n * The open state, the selection, the keys, the tab stop and the registry of\n * a TreeView (#1096). Focus moves for real, with a roving tabindex, rather\n * than through `aria-activedescendant`.\n *\n * Every item registers its value, its parent and whether it's disabled from\n * a layout effect. In a checkbox tree a closed item's children still render\n * and register while drawing nothing, so the registry knows every item and a\n * check reaches all of them. The keys read the items on the page, in\n * document order, each time they need them.\n *\n * @function useTreeView\n * @param options - The TreeView's props.\n * @returns The state and handlers the root and its items wire up.\n */\nexport function useTreeView(options: TreeViewOptions): TreeViewEngine {\n // An own key only, so a name every object inherits, like `toString`, is a\n // mode the tree doesn't know too.\n const mode = Object.prototype.hasOwnProperty.call(MODES, options.mode)\n ? options.mode\n : 'none';\n const actions = MODES[mode];\n\n const [expanded, setExpanded] = useControlled(\n options.expanded,\n options.defaultExpanded\n );\n const [selection, setSelection] = useControlled(\n options.selected,\n options.defaultSelected\n );\n const [checkedList, setChecked] = useControlled(\n options.checked,\n options.defaultChecked\n );\n // Each is read in its own mode only.\n const selected = mode === 'single' ? selection : null;\n const listed = new Set(mode === 'checkbox' ? checkedList : []);\n\n const treeRef = useRef<HTMLUListElement | null>(null);\n const registryRef = useRef<Registry>({\n records: new Map(),\n elements: new Map(),\n values: new WeakMap(),\n });\n // Items register from their own effects, so they ask for a render to be read.\n const [, refresh] = useReducer((n: number) => n + 1, 0);\n const typeahead = useTypeahead();\n\n // The item with focus, and where the stop rests while focus is elsewhere:\n // `undefined` until the tree has mounted. With the values above it, for\n // when it goes away.\n const [focused, setFocused] = useState<string | null>(null);\n const [resting, setResting] = useState<string | null | undefined>();\n const restingPathRef = useRef<string[]>([]);\n // The values above an item that left the page with focus in it.\n const lostRef = useRef<string[] | null>(null);\n\n const { records } = registryRef.current;\n const checks =\n mode === 'checkbox'\n ? // eslint-disable-next-line react-hooks/refs -- read in render on purpose: items write the registry from their layout effects and then ask for this render with `refresh`\n readChecks(records, listed).states\n : undefined;\n const tabStop = focused ?? (resting === undefined ? selected : resting);\n\n const isOpen = (value: string) => expanded.includes(value);\n\n const stateOf = (\n value: string,\n path: string[],\n disabled: boolean\n ): TreeViewItemState => {\n if (mode === 'single') {\n return disabled ? {} : { selected: value === selected };\n }\n if (checks) {\n // Until the items register, a value stands for its branch, and a\n // parent can't know it's mixed.\n const fromList =\n listed.has(value) || (!disabled && path.some(v => listed.has(v)));\n return { checked: checks.get(value) ?? fromList };\n }\n return {};\n };\n\n const changeOpen = (next: string[]) => {\n setExpanded(next);\n options.onExpandedChange?.(next);\n };\n\n const run: Record<Action, (item: TreeViewItemInfo) => void> = {\n open: ({ value, isParent, open }) => {\n if (isParent) {\n changeOpen(\n open ? expanded.filter(v => v !== value) : [...expanded, value]\n );\n }\n },\n select: ({ value }) => {\n if (value === selected) return;\n setSelection(value);\n options.onSelectedChange?.(value);\n },\n check: ({ value }) => {\n const next = toggledList(records, checkedList, value);\n setChecked(next);\n options.onCheckedChange?.(next);\n },\n };\n\n /** Disabled items are never selected, checked, opened or closed. */\n const act = (item: TreeViewItemInfo, list: Action[]) => {\n if (!item.disabled) list.forEach(action => run[action](item));\n };\n\n // After every render, put the stop where it belongs. While focus is in\n // the tree it's the focused item. Otherwise it's the selected item, or the\n // first checked one on the page, and failing that it stays where it was.\n // An item that goes away hands it to its nearest ancestor on the page, or\n // to the first item, and focus goes with it if it had focus.\n // eslint-disable-next-line react-hooks/exhaustive-deps -- after every render on purpose: it reads the page, and sets state only when what it reads has changed\n useClientLayoutEffect(() => {\n const tree = treeRef.current!;\n const registry = registryRef.current;\n // Each item's element is read off the page with its value, rather than\n // out of `elements`, which holds one element per value: two items\n // sharing a value, which they shouldn't, can leave it without one the\n // page still has.\n const shown = shownIn(tree, registry);\n const onPage = shown.map(element => registry.values.get(element)!);\n const elementOf = (value: string) => shown[onPage.indexOf(value)];\n const isShown = (value: string | null | undefined): value is string =>\n value != null && onPage.includes(value);\n const heir = (path: string[]) =>\n [...path].reverse().find(isShown) ?? onPage[0] ?? null;\n\n const lost = lostRef.current;\n lostRef.current = null;\n if (lost && !tree.contains(getActiveElementInTree(tree))) {\n const to = heir(lost);\n if (to) elementOf(to).focus();\n return;\n }\n if (focused !== null && !isShown(focused)) setFocused(null);\n\n const preferred = onPage.find(\n value => value === selected || checks?.get(value) === true\n );\n const next =\n preferred ?? (isShown(resting) ? resting : heir(restingPathRef.current));\n if (next !== resting) {\n setResting(next);\n restingPathRef.current = next ? pathOf(elementOf(next), registry) : [];\n }\n });\n\n const register = useCallback((value: string, record: TreeViewItemRecord) => {\n const { records: known } = registryRef.current;\n known.set(value, record);\n refresh();\n return () => {\n if (known.get(value) !== record) return;\n known.delete(value);\n refresh();\n };\n }, []);\n\n const setElement = useCallback(\n (value: string, element: HTMLLIElement | null) => {\n const registry = registryRef.current;\n if (element) {\n registry.elements.set(value, element);\n registry.values.set(element, value);\n return;\n }\n const gone = registry.elements.get(value);\n if (!gone) return;\n // The ref lets go before the element leaves the page, so it can still\n // say whether focus was in it, and where it sat.\n if (!lostRef.current && gone.contains(getActiveElementInTree(gone))) {\n lostRef.current = [...pathOf(gone, registry), value];\n }\n registry.elements.delete(value);\n },\n []\n );\n\n const onFocus = (value: string, element: HTMLLIElement) => {\n setFocused(value);\n setResting(value);\n restingPathRef.current = pathOf(element, registryRef.current);\n };\n\n const onBlur = () => setFocused(null);\n\n const onKeyDown = (\n event: React.KeyboardEvent<HTMLLIElement>,\n item: TreeViewItemInfo\n ) => {\n const element = event.currentTarget;\n // A key on an item inside this one bubbles here too, and is its own.\n if (\n event.target !== element ||\n event.defaultPrevented ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n isComposing(event)\n ) {\n return;\n }\n const registry = registryRef.current;\n const items = shownIn(treeRef.current!, registry);\n const at = items.indexOf(element);\n const rtl = getComputedStyle(element).direction === 'rtl';\n const key = (rtl && MIRRORED[event.key]) || event.key;\n\n switch (key) {\n case 'ArrowDown':\n items[at + 1]?.focus();\n break;\n case 'ArrowUp':\n items[at - 1]?.focus();\n break;\n case 'Home':\n items[0].focus();\n break;\n case 'End':\n items[items.length - 1].focus();\n break;\n case 'ArrowRight': {\n const next = items[at + 1];\n if (!item.open) act(item, ['open']);\n else if (next && parentItemOf(next) === element) next.focus();\n break;\n }\n case 'ArrowLeft':\n if (item.open && !item.disabled) act(item, ['open']);\n else parentItemOf(element)?.focus();\n break;\n // A held key acts once.\n case 'Enter':\n if (!event.repeat) act(item, actions.enter);\n break;\n case ' ':\n if (!event.repeat) act(item, actions.space);\n break;\n case '*': {\n const closed: string[] = [];\n registry.records.forEach((record, value) => {\n if (\n record.parent === item.parent &&\n record.isParent &&\n !record.disabled &&\n !expanded.includes(value)\n ) {\n closed.push(value);\n }\n });\n if (closed.length) changeOpen([...expanded, ...closed]);\n break;\n }\n default:\n // Type-ahead takes a printable character. Anything else, Escape and\n // Tab included, is left to whatever is around the tree.\n if (event.key.length !== 1) return;\n typeaheadMatch(items, typeahead.type(event.key), at, el =>\n typeaheadText(el.firstElementChild!)\n )?.focus();\n }\n event.preventDefault();\n };\n\n const onClick = (\n element: HTMLLIElement,\n item: TreeViewItemInfo,\n onToggle: boolean\n ) => {\n element.focus();\n act(item, onToggle ? ['open'] : actions.click);\n };\n\n return {\n treeRef,\n rendersClosed: mode === 'checkbox',\n tabStop,\n isOpen,\n stateOf,\n register,\n setElement,\n onFocus,\n onBlur,\n onKeyDown,\n onClick,\n };\n}\n"],"names":["isComposing"],"mappings":"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"}
1
+ {"version":3,"file":"useTreeView.js","sources":["../../../src/helpers/useTreeView.ts"],"sourcesContent":["// INTERNAL: deliberately not exported from src/index.ts.\nimport { useCallback, useReducer, useRef, useState } from 'react';\nimport type React from 'react';\nimport type { TreeViewSelectionMode } from '../components/TreeView';\nimport { useClientLayoutEffect } from './useClientLayoutEffect';\nimport { getActiveElementInTree } from './shadowDom';\nimport { typeaheadMatch, typeaheadText, useTypeahead } from './typeahead';\n\n/** What an item tells the tree about itself when it registers. */\nexport interface TreeViewItemRecord {\n /** The value of the item it's in, or `null` at the top. */\n parent: string | null;\n disabled: boolean;\n /** It has children, or `hasChildren` says it will. */\n isParent: boolean;\n}\n\n/** An item as a key or a click on it sees it. */\nexport interface TreeViewItemInfo extends TreeViewItemRecord {\n value: string;\n open: boolean;\n /**\n * A failed load's row: what Enter, Space and a click on it do, in place of\n * what the mode says.\n */\n retry?: () => void;\n}\n\n/** A box's state: checked, unchecked or mixed. */\nexport type TreeViewCheckState = boolean | 'mixed';\n\n/**\n * What an item shows of the selection: `selected` in a `single` tree,\n * `checked` in a `checkbox` tree, and neither with `none`.\n */\nexport interface TreeViewItemState {\n selected?: boolean;\n checked?: TreeViewCheckState;\n}\n\ntype Action = 'open' | 'select' | 'check';\n\n/**\n * What Enter, Space and a click on the row do in each mode, from the tables\n * in #1096. `open` opens or closes a parent and does nothing on a leaf. A\n * click on the chevron only ever opens or closes.\n */\nconst MODES: Record<\n TreeViewSelectionMode,\n { enter: Action[]; space: Action[]; click: Action[] }\n> = {\n none: { enter: ['open'], space: ['open'], click: ['open'] },\n single: { enter: ['select'], space: ['select'], click: ['select', 'open'] },\n checkbox: { enter: ['open'], space: ['check'], click: ['check'] },\n};\n\n/** Left and Right, swapped for a right-to-left page. */\nconst MIRRORED: Record<string, string> = {\n ArrowLeft: 'ArrowRight',\n ArrowRight: 'ArrowLeft',\n};\n\n/** An IME is composing, so the key belongs to it (`keyCode` 229 is Safari's word for it). */\nconst isComposing = (event: React.KeyboardEvent): boolean =>\n event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229;\n\n/**\n * The items a tree knows, and their elements while they're on the page. A\n * loading item's row, or a failed load's, hands over its element under a key\n * of its own and has no record, so the keys reach it and nothing else counts it.\n */\ninterface Registry {\n records: Map<string, TreeViewItemRecord>;\n // By value, for an item whose ref lets go, which hands over no element.\n elements: Map<string, HTMLLIElement>;\n // Weak, so an element that leaves the page needn't be forgotten by hand.\n values: WeakMap<Element, string>;\n}\n\n/** The registry's items on the page, in document order. */\nconst shownIn = (tree: Element, { values }: Registry): HTMLElement[] =>\n Array.from(tree.querySelectorAll<HTMLElement>('[role=\"treeitem\"]')).filter(\n element => values.has(element)\n );\n\n/** The item an item on the page sits in: its group's `<li>`, or none at the top. */\nfunction parentItemOf(element: Element): HTMLElement | null {\n const group = element.parentElement!;\n return group.getAttribute('role') === 'group' ? group.parentElement : null;\n}\n\n/** The values of the items an item on the page is in, from the top. */\nfunction pathOf(element: Element, { values }: Registry): string[] {\n const path: string[] = [];\n for (let at = parentItemOf(element); at; at = parentItemOf(at)) {\n path.unshift(values.get(at)!);\n }\n return path;\n}\n\n/**\n * Every known item's check state, by the rules in #1096:\n *\n * - a disabled item is checked only when its own value is listed;\n * - an enabled item with no enabled items anywhere under it is checked when\n * it, or any item above it, is listed;\n * - any other enabled item follows the items of that second kind in its\n * branch: checked when they all are, unchecked when none is, mixed between.\n *\n * Also returns the items of the second kind, which are what a toggle sets.\n */\nfunction readChecks(\n records: Map<string, TreeViewItemRecord>,\n listed: Set<string>\n): { states: Map<string, TreeViewCheckState>; ends: string[] } {\n const kids = new Map<string | null, string[]>();\n records.forEach(({ parent }, value) => {\n kids.set(parent, [...(kids.get(parent) ?? []), value]);\n });\n const states = new Map<string, TreeViewCheckState>();\n const ends: string[] = [];\n // How many enabled ends the branch holds, and how many are checked.\n const visit = (value: string, above: boolean): [number, number] => {\n const marked = above || listed.has(value);\n let total = 0;\n let on = 0;\n for (const kid of kids.get(value) ?? []) {\n const [t, o] = visit(kid, marked);\n total += t;\n on += o;\n }\n if (records.get(value)!.disabled) {\n states.set(value, listed.has(value));\n return [total, on];\n }\n if (total === 0) {\n states.set(value, marked);\n ends.push(value);\n return [1, marked ? 1 : 0];\n }\n states.set(value, on === total ? true : on > 0 && 'mixed');\n return [total, on];\n };\n for (const top of kids.get(null) ?? []) visit(top, false);\n return { states, ends };\n}\n\n/**\n * The list a toggle of `value` leaves: it and every enabled item under it\n * take the opposite of its state (a mixed one checks), and the rest is read\n * back by the rules. That's every item that shows checked, parents\n * included, plus any listed value no item has.\n */\nfunction toggledList(\n records: Map<string, TreeViewItemRecord>,\n list: string[],\n value: string\n): string[] {\n const { states, ends } = readChecks(records, new Set(list));\n const to = states.get(value) !== true;\n // An end was reached from the top, so everything above it is known.\n const under = (end: string) => {\n for (let at: string | null = end; at !== null;) {\n if (at === value) return true;\n at = records.get(at)!.parent;\n }\n return false;\n };\n const seed = new Set(\n ends.filter(end => (under(end) ? to : states.get(end) === true))\n );\n records.forEach(({ disabled }, item) => {\n if (disabled && states.get(item) === true) seed.add(item);\n });\n const after = readChecks(records, seed).states;\n return [\n ...Array.from(after)\n .filter(([, state]) => state === true)\n .map(([item]) => item),\n ...list.filter(item => !records.has(item)),\n ];\n}\n\n/** A value the caller holds, or one this hook holds when the caller doesn't. */\nfunction useControlled<T>(controlled: T | undefined, initial: T) {\n const [own, setOwn] = useState(initial);\n const isControlled = controlled !== undefined;\n const set = (next: T) => {\n if (!isControlled) setOwn(next);\n };\n return [isControlled ? controlled : own, set] as const;\n}\n\n/** Options for `useTreeView`: the TreeView's own props. */\nexport interface TreeViewOptions {\n mode: TreeViewSelectionMode;\n selected?: string | null;\n defaultSelected: string | null;\n onSelectedChange?: (value: string) => void;\n checked?: string[];\n defaultChecked: string[];\n onCheckedChange?: (checked: string[]) => void;\n expanded?: string[];\n defaultExpanded: string[];\n onExpandedChange?: (expanded: string[]) => void;\n}\n\n/** What `useTreeView` hands the root and its items. */\nexport interface TreeViewEngine {\n /** For the `<ul role=\"tree\">`. */\n treeRef: React.MutableRefObject<HTMLUListElement | null>;\n /**\n * Whether a closed item still renders its children, drawing nothing, so a\n * check knows everything under it. Only a checkbox tree needs to.\n */\n rendersClosed: boolean;\n /** The item that holds `tabIndex={0}`. */\n tabStop: string | null;\n isOpen: (value: string) => boolean;\n /**\n * What the item shows of the selection. `path` is the values of the items\n * above it, which decide its box until the items have registered, as on\n * the server.\n */\n stateOf: (\n value: string,\n path: string[],\n disabled: boolean\n ) => TreeViewItemState;\n /** Records an item from its layout effect. Returns the function that forgets it. */\n register: (value: string, record: TreeViewItemRecord) => () => void;\n /** For each item's `<li>` ref: records it, and notices focus leaving with it. */\n setElement: (value: string, element: HTMLLIElement | null) => void;\n /** Focus arrived on the item's own `<li>`. */\n onFocus: (value: string, element: HTMLLIElement) => void;\n /** Focus left the item's own `<li>`. */\n onBlur: () => void;\n /** A key on the item's `<li>`, after its own `onKeyDown`. */\n onKeyDown: (\n event: React.KeyboardEvent<HTMLLIElement>,\n item: TreeViewItemInfo\n ) => void;\n /**\n * A click on the item's row, or with `onToggle` on its chevron. Focus and\n * the tab stop move to the item.\n */\n onClick: (\n element: HTMLLIElement,\n item: TreeViewItemInfo,\n onToggle: boolean\n ) => void;\n}\n\n/**\n * The open state, the selection, the keys, the tab stop and the registry of\n * a TreeView (#1096). Focus moves for real, with a roving tabindex, rather\n * than through `aria-activedescendant`.\n *\n * Every item registers its value, its parent and whether it's disabled from\n * a layout effect. In a checkbox tree a closed item's children still render\n * and register while drawing nothing, so the registry knows every item and a\n * check reaches all of them. The keys read the items on the page, in\n * document order, each time they need them.\n *\n * @function useTreeView\n * @param options - The TreeView's props.\n * @returns The state and handlers the root and its items wire up.\n */\nexport function useTreeView(options: TreeViewOptions): TreeViewEngine {\n // An own key only, so a name every object inherits, like `toString`, is a\n // mode the tree doesn't know too.\n const mode = Object.prototype.hasOwnProperty.call(MODES, options.mode)\n ? options.mode\n : 'none';\n const actions = MODES[mode];\n\n const [expanded, setExpanded] = useControlled(\n options.expanded,\n options.defaultExpanded\n );\n const [selection, setSelection] = useControlled(\n options.selected,\n options.defaultSelected\n );\n const [checkedList, setChecked] = useControlled(\n options.checked,\n options.defaultChecked\n );\n // Each is read in its own mode only.\n const selected = mode === 'single' ? selection : null;\n const listed = new Set(mode === 'checkbox' ? checkedList : []);\n\n const treeRef = useRef<HTMLUListElement | null>(null);\n const registryRef = useRef<Registry>({\n records: new Map(),\n elements: new Map(),\n values: new WeakMap(),\n });\n // Items register from their own effects, so they ask for a render to be read.\n const [, refresh] = useReducer((n: number) => n + 1, 0);\n const typeahead = useTypeahead();\n\n // The item with focus, and where the stop rests while focus is elsewhere:\n // `undefined` until the tree has mounted. With the values above it, for\n // when it goes away.\n const [focused, setFocused] = useState<string | null>(null);\n const [resting, setResting] = useState<string | null | undefined>();\n const restingPathRef = useRef<string[]>([]);\n // The values above an item that left the page with focus in it.\n const lostRef = useRef<string[] | null>(null);\n\n const { records } = registryRef.current;\n const checks =\n mode === 'checkbox'\n ? // eslint-disable-next-line react-hooks/refs -- read in render on purpose: items write the registry from their layout effects and then ask for this render with `refresh`\n readChecks(records, listed).states\n : undefined;\n const tabStop = focused ?? (resting === undefined ? selected : resting);\n\n const isOpen = (value: string) => expanded.includes(value);\n\n const stateOf = (\n value: string,\n path: string[],\n disabled: boolean\n ): TreeViewItemState => {\n if (mode === 'single') {\n return disabled ? {} : { selected: value === selected };\n }\n if (checks) {\n // Until the items register, a value stands for its branch, and a\n // parent can't know it's mixed.\n const fromList =\n listed.has(value) || (!disabled && path.some(v => listed.has(v)));\n return { checked: checks.get(value) ?? fromList };\n }\n return {};\n };\n\n const changeOpen = (next: string[]) => {\n setExpanded(next);\n options.onExpandedChange?.(next);\n };\n\n const run: Record<Action, (item: TreeViewItemInfo) => void> = {\n open: ({ value, isParent, open }) => {\n if (isParent) {\n changeOpen(\n open ? expanded.filter(v => v !== value) : [...expanded, value]\n );\n }\n },\n select: ({ value }) => {\n if (value === selected) return;\n setSelection(value);\n options.onSelectedChange?.(value);\n },\n check: ({ value }) => {\n const next = toggledList(records, checkedList, value);\n setChecked(next);\n options.onCheckedChange?.(next);\n },\n };\n\n /** Disabled items are never selected, checked, opened or closed. */\n const act = (item: TreeViewItemInfo, list: Action[]) => {\n if (!item.disabled) list.forEach(action => run[action](item));\n };\n\n /** Enter, Space and a click on the row: a failed load's row retries. */\n const press = (item: TreeViewItemInfo, list: Action[]) => {\n if (item.retry) item.retry();\n else act(item, list);\n };\n\n // After every render, put the stop where it belongs. While focus is in\n // the tree it's the focused item. Otherwise it's the selected item, or the\n // first checked one on the page, and failing that it stays where it was.\n // An item that goes away hands it to its nearest ancestor on the page, or\n // to the first item, and focus goes with it if it had focus.\n // eslint-disable-next-line react-hooks/exhaustive-deps -- after every render on purpose: it reads the page, and sets state only when what it reads has changed\n useClientLayoutEffect(() => {\n const tree = treeRef.current!;\n const registry = registryRef.current;\n // Each item's element is read off the page with its value, rather than\n // out of `elements`, which holds one element per value: two items\n // sharing a value, which they shouldn't, can leave it without one the\n // page still has.\n const shown = shownIn(tree, registry);\n const onPage = shown.map(element => registry.values.get(element)!);\n const elementOf = (value: string) => shown[onPage.indexOf(value)];\n const isShown = (value: string | null | undefined): value is string =>\n value != null && onPage.includes(value);\n const heir = (path: string[]) =>\n [...path].reverse().find(isShown) ?? onPage[0] ?? null;\n\n const lost = lostRef.current;\n lostRef.current = null;\n if (lost && !tree.contains(getActiveElementInTree(tree))) {\n const to = heir(lost);\n if (to) elementOf(to).focus();\n return;\n }\n if (focused !== null && !isShown(focused)) setFocused(null);\n\n const preferred = onPage.find(\n value => value === selected || checks?.get(value) === true\n );\n const next =\n preferred ?? (isShown(resting) ? resting : heir(restingPathRef.current));\n if (next !== resting) {\n setResting(next);\n restingPathRef.current = next ? pathOf(elementOf(next), registry) : [];\n }\n });\n\n const register = useCallback((value: string, record: TreeViewItemRecord) => {\n const { records: known } = registryRef.current;\n known.set(value, record);\n refresh();\n return () => {\n if (known.get(value) !== record) return;\n known.delete(value);\n refresh();\n };\n }, []);\n\n const setElement = useCallback(\n (value: string, element: HTMLLIElement | null) => {\n const registry = registryRef.current;\n if (element) {\n registry.elements.set(value, element);\n registry.values.set(element, value);\n return;\n }\n const gone = registry.elements.get(value);\n if (!gone) return;\n // The ref lets go before the element leaves the page, so it can still\n // say whether focus was in it, and where it sat.\n if (!lostRef.current && gone.contains(getActiveElementInTree(gone))) {\n lostRef.current = [...pathOf(gone, registry), value];\n }\n registry.elements.delete(value);\n },\n []\n );\n\n const onFocus = (value: string, element: HTMLLIElement) => {\n setFocused(value);\n setResting(value);\n restingPathRef.current = pathOf(element, registryRef.current);\n };\n\n const onBlur = () => setFocused(null);\n\n const onKeyDown = (\n event: React.KeyboardEvent<HTMLLIElement>,\n item: TreeViewItemInfo\n ) => {\n const element = event.currentTarget;\n // A key on an item inside this one bubbles here too, and is its own.\n if (\n event.target !== element ||\n event.defaultPrevented ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n isComposing(event)\n ) {\n return;\n }\n const registry = registryRef.current;\n const items = shownIn(treeRef.current!, registry);\n const at = items.indexOf(element);\n const rtl = getComputedStyle(element).direction === 'rtl';\n const key = (rtl && MIRRORED[event.key]) || event.key;\n\n switch (key) {\n case 'ArrowDown':\n items[at + 1]?.focus();\n break;\n case 'ArrowUp':\n items[at - 1]?.focus();\n break;\n case 'Home':\n items[0].focus();\n break;\n case 'End':\n items[items.length - 1].focus();\n break;\n case 'ArrowRight': {\n const next = items[at + 1];\n if (!item.open) act(item, ['open']);\n else if (next && parentItemOf(next) === element) next.focus();\n break;\n }\n case 'ArrowLeft':\n if (item.open && !item.disabled) act(item, ['open']);\n else parentItemOf(element)?.focus();\n break;\n // A held key acts once.\n case 'Enter':\n if (!event.repeat) press(item, actions.enter);\n break;\n case ' ':\n if (!event.repeat) press(item, actions.space);\n break;\n case '*': {\n const closed: string[] = [];\n registry.records.forEach((record, value) => {\n if (\n record.parent === item.parent &&\n record.isParent &&\n !record.disabled &&\n !expanded.includes(value)\n ) {\n closed.push(value);\n }\n });\n if (closed.length) changeOpen([...expanded, ...closed]);\n break;\n }\n default:\n // Type-ahead takes a printable character. Anything else, Escape and\n // Tab included, is left to whatever is around the tree.\n if (event.key.length !== 1) return;\n typeaheadMatch(items, typeahead.type(event.key), at, el =>\n typeaheadText(el.firstElementChild!)\n )?.focus();\n }\n event.preventDefault();\n };\n\n const onClick = (\n element: HTMLLIElement,\n item: TreeViewItemInfo,\n onToggle: boolean\n ) => {\n element.focus();\n if (onToggle) act(item, ['open']);\n else press(item, actions.click);\n };\n\n return {\n treeRef,\n rendersClosed: mode === 'checkbox',\n tabStop,\n isOpen,\n stateOf,\n register,\n setElement,\n onFocus,\n onBlur,\n onKeyDown,\n onClick,\n };\n}\n"],"names":["isComposing"],"mappings":"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"}