@mui/x-tree-view 7.0.0-beta.7 → 7.0.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/CHANGELOG.md +195 -12
- package/README.md +1 -1
- package/RichTreeView/RichTreeView.js +12 -14
- package/RichTreeView/RichTreeView.types.d.ts +1 -1
- package/SimpleTreeView/SimpleTreeView.js +3 -4
- package/TreeItem/TreeItem.js +43 -35
- package/TreeItem/TreeItem.types.d.ts +3 -3
- package/TreeItem/TreeItemContent.d.ts +7 -7
- package/TreeItem/TreeItemContent.js +10 -10
- package/TreeItem/useTreeItemState.d.ts +1 -1
- package/TreeItem/useTreeItemState.js +13 -13
- package/TreeItem2/TreeItem2.js +16 -17
- package/TreeItem2Icon/TreeItem2Icon.js +5 -6
- package/TreeItem2Provider/TreeItem2Provider.js +3 -3
- package/TreeItem2Provider/TreeItem2Provider.types.d.ts +1 -1
- package/TreeView/TreeView.d.ts +1 -1
- package/TreeView/TreeView.js +1 -1
- package/hooks/useTreeItem2Utils/useTreeItem2Utils.d.ts +2 -2
- package/hooks/useTreeItem2Utils/useTreeItem2Utils.js +12 -12
- package/index.js +1 -1
- package/internals/hooks/useInstanceEventHandler.js +5 -10
- package/internals/models/plugin.d.ts +1 -1
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +11 -18
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +3 -3
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +59 -43
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +6 -5
- package/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
- package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +1 -1
- package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +17 -18
- package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.types.d.ts +2 -2
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +70 -77
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +4 -1
- package/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +24 -29
- package/internals/plugins/useTreeViewNodes/useTreeViewNodes.types.d.ts +11 -11
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +18 -21
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +4 -4
- package/internals/useTreeView/useTreeView.js +5 -6
- package/internals/useTreeView/useTreeView.utils.d.ts +2 -2
- package/internals/useTreeView/useTreeView.utils.js +22 -22
- package/internals/utils/extractPluginParamsFromProps.js +2 -2
- package/internals/utils/utils.js +1 -0
- package/modern/RichTreeView/RichTreeView.js +7 -7
- package/modern/SimpleTreeView/SimpleTreeView.js +1 -1
- package/modern/TreeItem/TreeItem.js +31 -22
- package/modern/TreeItem/TreeItemContent.js +10 -10
- package/modern/TreeItem/useTreeItemState.js +13 -13
- package/modern/TreeItem2/TreeItem2.js +11 -11
- package/modern/TreeItem2Provider/TreeItem2Provider.js +3 -3
- package/modern/TreeView/TreeView.js +1 -1
- package/modern/hooks/useTreeItem2Utils/useTreeItem2Utils.js +12 -12
- package/modern/index.js +1 -1
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +7 -7
- package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +57 -38
- package/modern/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
- package/modern/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +17 -17
- package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +69 -74
- package/modern/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +19 -20
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +13 -13
- package/modern/internals/useTreeView/useTreeView.js +3 -4
- package/modern/internals/useTreeView/useTreeView.utils.js +22 -22
- package/modern/internals/utils/utils.js +1 -0
- package/modern/useTreeItem2/useTreeItem2.js +23 -12
- package/node/RichTreeView/RichTreeView.js +7 -7
- package/node/SimpleTreeView/SimpleTreeView.js +1 -1
- package/node/TreeItem/TreeItem.js +31 -22
- package/node/TreeItem/TreeItemContent.js +10 -10
- package/node/TreeItem/useTreeItemState.js +13 -13
- package/node/TreeItem2/TreeItem2.js +11 -11
- package/node/TreeItem2Provider/TreeItem2Provider.js +3 -3
- package/node/TreeView/TreeView.js +1 -1
- package/node/hooks/useTreeItem2Utils/useTreeItem2Utils.js +12 -12
- package/node/index.js +1 -1
- package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +7 -7
- package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +57 -38
- package/node/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
- package/node/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +17 -17
- package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +69 -74
- package/node/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +19 -20
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +13 -13
- package/node/internals/useTreeView/useTreeView.js +3 -4
- package/node/internals/useTreeView/useTreeView.utils.js +22 -22
- package/node/internals/utils/utils.js +1 -0
- package/node/useTreeItem2/useTreeItem2.js +23 -12
- package/package.json +5 -5
- package/useTreeItem2/useTreeItem2.js +26 -18
- package/useTreeItem2/useTreeItem2.types.d.ts +9 -7
|
@@ -1,45 +1,45 @@
|
|
|
1
1
|
import { useTreeViewContext } from '../internals/TreeViewProvider/useTreeViewContext';
|
|
2
|
-
export function useTreeItemState(
|
|
2
|
+
export function useTreeItemState(itemId) {
|
|
3
3
|
const {
|
|
4
4
|
instance,
|
|
5
5
|
selection: {
|
|
6
6
|
multiSelect
|
|
7
7
|
}
|
|
8
8
|
} = useTreeViewContext();
|
|
9
|
-
const expandable = instance.isNodeExpandable(
|
|
10
|
-
const expanded = instance.isNodeExpanded(
|
|
11
|
-
const focused = instance.isNodeFocused(
|
|
12
|
-
const selected = instance.isNodeSelected(
|
|
13
|
-
const disabled = instance.isNodeDisabled(
|
|
9
|
+
const expandable = instance.isNodeExpandable(itemId);
|
|
10
|
+
const expanded = instance.isNodeExpanded(itemId);
|
|
11
|
+
const focused = instance.isNodeFocused(itemId);
|
|
12
|
+
const selected = instance.isNodeSelected(itemId);
|
|
13
|
+
const disabled = instance.isNodeDisabled(itemId);
|
|
14
14
|
const handleExpansion = event => {
|
|
15
15
|
if (!disabled) {
|
|
16
16
|
if (!focused) {
|
|
17
|
-
instance.focusItem(event,
|
|
17
|
+
instance.focusItem(event, itemId);
|
|
18
18
|
}
|
|
19
19
|
const multiple = multiSelect && (event.shiftKey || event.ctrlKey || event.metaKey);
|
|
20
20
|
|
|
21
21
|
// If already expanded and trying to toggle selection don't close
|
|
22
|
-
if (expandable && !(multiple && instance.isNodeExpanded(
|
|
23
|
-
instance.toggleNodeExpansion(event,
|
|
22
|
+
if (expandable && !(multiple && instance.isNodeExpanded(itemId))) {
|
|
23
|
+
instance.toggleNodeExpansion(event, itemId);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
const handleSelection = event => {
|
|
28
28
|
if (!disabled) {
|
|
29
29
|
if (!focused) {
|
|
30
|
-
instance.focusItem(event,
|
|
30
|
+
instance.focusItem(event, itemId);
|
|
31
31
|
}
|
|
32
32
|
const multiple = multiSelect && (event.shiftKey || event.ctrlKey || event.metaKey);
|
|
33
33
|
if (multiple) {
|
|
34
34
|
if (event.shiftKey) {
|
|
35
35
|
instance.selectRange(event, {
|
|
36
|
-
end:
|
|
36
|
+
end: itemId
|
|
37
37
|
});
|
|
38
38
|
} else {
|
|
39
|
-
instance.selectNode(event,
|
|
39
|
+
instance.selectNode(event, itemId, true);
|
|
40
40
|
}
|
|
41
41
|
} else {
|
|
42
|
-
instance.selectNode(event,
|
|
42
|
+
instance.selectNode(event, itemId);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
2
2
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
3
|
-
const _excluded = ["id", "
|
|
3
|
+
const _excluded = ["id", "itemId", "label", "disabled", "children", "slots", "slotProps"];
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import PropTypes from 'prop-types';
|
|
6
6
|
import clsx from 'clsx';
|
|
@@ -165,7 +165,7 @@ export const TreeItem2 = /*#__PURE__*/React.forwardRef(function TreeItem2(inProp
|
|
|
165
165
|
});
|
|
166
166
|
const {
|
|
167
167
|
id,
|
|
168
|
-
|
|
168
|
+
itemId,
|
|
169
169
|
label,
|
|
170
170
|
disabled,
|
|
171
171
|
children,
|
|
@@ -182,7 +182,7 @@ export const TreeItem2 = /*#__PURE__*/React.forwardRef(function TreeItem2(inProp
|
|
|
182
182
|
status
|
|
183
183
|
} = useTreeItem2({
|
|
184
184
|
id,
|
|
185
|
-
|
|
185
|
+
itemId,
|
|
186
186
|
children,
|
|
187
187
|
label,
|
|
188
188
|
disabled
|
|
@@ -234,7 +234,7 @@ export const TreeItem2 = /*#__PURE__*/React.forwardRef(function TreeItem2(inProp
|
|
|
234
234
|
className: classes.groupTransition
|
|
235
235
|
});
|
|
236
236
|
return /*#__PURE__*/_jsx(TreeItem2Provider, {
|
|
237
|
-
|
|
237
|
+
itemId: itemId,
|
|
238
238
|
children: /*#__PURE__*/_jsxs(Root, _extends({}, rootProps, {
|
|
239
239
|
children: [/*#__PURE__*/_jsxs(Content, _extends({}, contentProps, {
|
|
240
240
|
children: [/*#__PURE__*/_jsx(IconContainer, _extends({}, iconContainerProps, {
|
|
@@ -265,23 +265,23 @@ process.env.NODE_ENV !== "production" ? TreeItem2.propTypes = {
|
|
|
265
265
|
classes: PropTypes.object,
|
|
266
266
|
className: PropTypes.string,
|
|
267
267
|
/**
|
|
268
|
-
* If `true`, the
|
|
268
|
+
* If `true`, the item is disabled.
|
|
269
269
|
* @default false
|
|
270
270
|
*/
|
|
271
271
|
disabled: PropTypes.bool,
|
|
272
272
|
/**
|
|
273
|
-
* The id attribute of the
|
|
273
|
+
* The id attribute of the item. If not provided, it will be generated.
|
|
274
274
|
*/
|
|
275
275
|
id: PropTypes.string,
|
|
276
276
|
/**
|
|
277
|
-
* The
|
|
277
|
+
* The id of the item.
|
|
278
|
+
* Must be unique.
|
|
278
279
|
*/
|
|
279
|
-
|
|
280
|
+
itemId: PropTypes.string.isRequired,
|
|
280
281
|
/**
|
|
281
|
-
* The
|
|
282
|
-
* Must be unique.
|
|
282
|
+
* The label of the item.
|
|
283
283
|
*/
|
|
284
|
-
|
|
284
|
+
label: PropTypes.node,
|
|
285
285
|
/**
|
|
286
286
|
* This prop isn't supported.
|
|
287
287
|
* Use the `onItemFocus` callback on the tree if you need to monitor a item's focus.
|
|
@@ -3,14 +3,14 @@ import { useTreeViewContext } from '../internals/TreeViewProvider/useTreeViewCon
|
|
|
3
3
|
function TreeItem2Provider(props) {
|
|
4
4
|
const {
|
|
5
5
|
children,
|
|
6
|
-
|
|
6
|
+
itemId
|
|
7
7
|
} = props;
|
|
8
8
|
const {
|
|
9
9
|
wrapItem
|
|
10
10
|
} = useTreeViewContext();
|
|
11
11
|
return wrapItem({
|
|
12
12
|
children,
|
|
13
|
-
|
|
13
|
+
itemId
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
TreeItem2Provider.propTypes = {
|
|
@@ -19,6 +19,6 @@ TreeItem2Provider.propTypes = {
|
|
|
19
19
|
// | To update them edit the TypeScript types and run "yarn proptypes" |
|
|
20
20
|
// ----------------------------------------------------------------------
|
|
21
21
|
children: PropTypes.node,
|
|
22
|
-
|
|
22
|
+
itemId: PropTypes.string.isRequired
|
|
23
23
|
};
|
|
24
24
|
export { TreeItem2Provider };
|
|
@@ -30,7 +30,7 @@ const warn = () => {
|
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* This component has been deprecated in favor of the new `SimpleTreeView` component.
|
|
33
|
-
* You can have a look at how to migrate to the new component in the v7 [migration guide](https://
|
|
33
|
+
* You can have a look at how to migrate to the new component in the v7 [migration guide](https://mui.com/x/migration/migration-tree-view-v6/#use-simpletreeview-instead-of-treeview)
|
|
34
34
|
*
|
|
35
35
|
* Demos:
|
|
36
36
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useTreeViewContext } from '../../internals/TreeViewProvider/useTreeViewContext';
|
|
2
2
|
export const useTreeItem2Utils = ({
|
|
3
|
-
|
|
3
|
+
itemId,
|
|
4
4
|
children
|
|
5
5
|
}) => {
|
|
6
6
|
const {
|
|
@@ -11,23 +11,23 @@ export const useTreeItem2Utils = ({
|
|
|
11
11
|
} = useTreeViewContext();
|
|
12
12
|
const status = {
|
|
13
13
|
expandable: Boolean(Array.isArray(children) ? children.length : children),
|
|
14
|
-
expanded: instance.isNodeExpanded(
|
|
15
|
-
focused: instance.isNodeFocused(
|
|
16
|
-
selected: instance.isNodeSelected(
|
|
17
|
-
disabled: instance.isNodeDisabled(
|
|
14
|
+
expanded: instance.isNodeExpanded(itemId),
|
|
15
|
+
focused: instance.isNodeFocused(itemId),
|
|
16
|
+
selected: instance.isNodeSelected(itemId),
|
|
17
|
+
disabled: instance.isNodeDisabled(itemId)
|
|
18
18
|
};
|
|
19
19
|
const handleExpansion = event => {
|
|
20
20
|
if (status.disabled) {
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
if (!status.focused) {
|
|
24
|
-
instance.focusItem(event,
|
|
24
|
+
instance.focusItem(event, itemId);
|
|
25
25
|
}
|
|
26
26
|
const multiple = multiSelect && (event.shiftKey || event.ctrlKey || event.metaKey);
|
|
27
27
|
|
|
28
28
|
// If already expanded and trying to toggle selection don't close
|
|
29
|
-
if (status.expandable && !(multiple && instance.isNodeExpanded(
|
|
30
|
-
instance.toggleNodeExpansion(event,
|
|
29
|
+
if (status.expandable && !(multiple && instance.isNodeExpanded(itemId))) {
|
|
30
|
+
instance.toggleNodeExpansion(event, itemId);
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
const handleSelection = event => {
|
|
@@ -35,19 +35,19 @@ export const useTreeItem2Utils = ({
|
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
if (!status.focused) {
|
|
38
|
-
instance.focusItem(event,
|
|
38
|
+
instance.focusItem(event, itemId);
|
|
39
39
|
}
|
|
40
40
|
const multiple = multiSelect && (event.shiftKey || event.ctrlKey || event.metaKey);
|
|
41
41
|
if (multiple) {
|
|
42
42
|
if (event.shiftKey) {
|
|
43
43
|
instance.selectRange(event, {
|
|
44
|
-
end:
|
|
44
|
+
end: itemId
|
|
45
45
|
});
|
|
46
46
|
} else {
|
|
47
|
-
instance.selectNode(event,
|
|
47
|
+
instance.selectNode(event, itemId, true);
|
|
48
48
|
}
|
|
49
49
|
} else {
|
|
50
|
-
instance.selectNode(event,
|
|
50
|
+
instance.selectNode(event, itemId);
|
|
51
51
|
}
|
|
52
52
|
};
|
|
53
53
|
const interactions = {
|
package/modern/index.js
CHANGED
|
@@ -11,10 +11,10 @@ export const useTreeViewExpansion = ({
|
|
|
11
11
|
params.onExpandedItemsChange?.(event, value);
|
|
12
12
|
models.expandedItems.setControlledValue(value);
|
|
13
13
|
};
|
|
14
|
-
const isNodeExpanded = React.useCallback(
|
|
15
|
-
return Array.isArray(models.expandedItems.value) ? models.expandedItems.value.indexOf(
|
|
14
|
+
const isNodeExpanded = React.useCallback(itemId => {
|
|
15
|
+
return Array.isArray(models.expandedItems.value) ? models.expandedItems.value.indexOf(itemId) !== -1 : false;
|
|
16
16
|
}, [models.expandedItems.value]);
|
|
17
|
-
const isNodeExpandable = React.useCallback(
|
|
17
|
+
const isNodeExpandable = React.useCallback(itemId => !!instance.getNode(itemId)?.expandable, [instance]);
|
|
18
18
|
const toggleNodeExpansion = useEventCallback((event, itemId) => {
|
|
19
19
|
if (itemId == null) {
|
|
20
20
|
return;
|
|
@@ -31,15 +31,15 @@ export const useTreeViewExpansion = ({
|
|
|
31
31
|
}
|
|
32
32
|
setExpandedItems(event, newExpanded);
|
|
33
33
|
});
|
|
34
|
-
const expandAllSiblings = (event,
|
|
35
|
-
const node = instance.getNode(
|
|
34
|
+
const expandAllSiblings = (event, itemId) => {
|
|
35
|
+
const node = instance.getNode(itemId);
|
|
36
36
|
const siblings = instance.getChildrenIds(node.parentId);
|
|
37
37
|
const diff = siblings.filter(child => instance.isNodeExpandable(child) && !instance.isNodeExpanded(child));
|
|
38
38
|
const newExpanded = models.expandedItems.value.concat(diff);
|
|
39
39
|
if (diff.length > 0) {
|
|
40
40
|
if (params.onItemExpansionToggle) {
|
|
41
|
-
diff.forEach(
|
|
42
|
-
params.onItemExpansionToggle(event,
|
|
41
|
+
diff.forEach(newlyExpandedItemId => {
|
|
42
|
+
params.onItemExpansionToggle(event, newlyExpandedItemId, true);
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
setExpandedItems(event, newExpanded);
|
|
@@ -5,6 +5,22 @@ import ownerDocument from '@mui/utils/ownerDocument';
|
|
|
5
5
|
import { populateInstance, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
|
|
6
6
|
import { useInstanceEventHandler } from '../../hooks/useInstanceEventHandler';
|
|
7
7
|
import { getActiveElement } from '../../utils/utils';
|
|
8
|
+
const useTabbableItemId = (instance, selectedItems) => {
|
|
9
|
+
const isItemVisible = itemId => {
|
|
10
|
+
const node = instance.getNode(itemId);
|
|
11
|
+
return node && (node.parentId == null || instance.isNodeExpanded(node.parentId));
|
|
12
|
+
};
|
|
13
|
+
let tabbableItemId;
|
|
14
|
+
if (Array.isArray(selectedItems)) {
|
|
15
|
+
tabbableItemId = selectedItems.find(isItemVisible);
|
|
16
|
+
} else if (selectedItems != null && isItemVisible(selectedItems)) {
|
|
17
|
+
tabbableItemId = selectedItems;
|
|
18
|
+
}
|
|
19
|
+
if (tabbableItemId == null) {
|
|
20
|
+
tabbableItemId = instance.getNavigableChildrenIds(null)[0];
|
|
21
|
+
}
|
|
22
|
+
return tabbableItemId;
|
|
23
|
+
};
|
|
8
24
|
export const useTreeViewFocus = ({
|
|
9
25
|
instance,
|
|
10
26
|
publicAPI,
|
|
@@ -14,30 +30,36 @@ export const useTreeViewFocus = ({
|
|
|
14
30
|
models,
|
|
15
31
|
rootRef
|
|
16
32
|
}) => {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
33
|
+
const tabbableItemId = useTabbableItemId(instance, models.selectedItems.value);
|
|
34
|
+
const setFocusedItemId = useEventCallback(itemId => {
|
|
35
|
+
const cleanItemId = typeof itemId === 'function' ? itemId(state.focusedNodeId) : itemId;
|
|
36
|
+
if (state.focusedNodeId !== cleanItemId) {
|
|
20
37
|
setState(prevState => _extends({}, prevState, {
|
|
21
|
-
focusedNodeId:
|
|
38
|
+
focusedNodeId: cleanItemId
|
|
22
39
|
}));
|
|
23
40
|
}
|
|
24
41
|
});
|
|
25
|
-
const isTreeViewFocused = React.useCallback(() => !!rootRef.current && rootRef.current
|
|
26
|
-
const isNodeFocused = React.useCallback(
|
|
27
|
-
const isNodeVisible =
|
|
28
|
-
const node = instance.getNode(
|
|
42
|
+
const isTreeViewFocused = React.useCallback(() => !!rootRef.current && rootRef.current.contains(getActiveElement(ownerDocument(rootRef.current))), [rootRef]);
|
|
43
|
+
const isNodeFocused = React.useCallback(itemId => state.focusedNodeId === itemId && isTreeViewFocused(), [state.focusedNodeId, isTreeViewFocused]);
|
|
44
|
+
const isNodeVisible = itemId => {
|
|
45
|
+
const node = instance.getNode(itemId);
|
|
29
46
|
return node && (node.parentId == null || instance.isNodeExpanded(node.parentId));
|
|
30
47
|
};
|
|
48
|
+
const innerFocusItem = (event, itemId) => {
|
|
49
|
+
const node = instance.getNode(itemId);
|
|
50
|
+
const itemElement = document.getElementById(instance.getTreeItemId(itemId, node.idAttribute));
|
|
51
|
+
if (itemElement) {
|
|
52
|
+
itemElement.focus();
|
|
53
|
+
}
|
|
54
|
+
setFocusedItemId(itemId);
|
|
55
|
+
if (params.onItemFocus) {
|
|
56
|
+
params.onItemFocus(event, itemId);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
31
59
|
const focusItem = useEventCallback((event, nodeId) => {
|
|
32
|
-
//
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
instance.focusRoot();
|
|
36
|
-
}
|
|
37
|
-
setFocusedNodeId(nodeId);
|
|
38
|
-
if (params.onItemFocus) {
|
|
39
|
-
params.onItemFocus(event, nodeId);
|
|
40
|
-
}
|
|
60
|
+
// If we receive a nodeId, and it is visible, the focus will be set to it
|
|
61
|
+
if (isNodeVisible(nodeId)) {
|
|
62
|
+
innerFocusItem(event, nodeId);
|
|
41
63
|
}
|
|
42
64
|
});
|
|
43
65
|
const focusDefaultNode = useEventCallback(event => {
|
|
@@ -50,21 +72,26 @@ export const useTreeViewFocus = ({
|
|
|
50
72
|
if (nodeToFocusId == null) {
|
|
51
73
|
nodeToFocusId = instance.getNavigableChildrenIds(null)[0];
|
|
52
74
|
}
|
|
53
|
-
|
|
54
|
-
if (params.onItemFocus) {
|
|
55
|
-
params.onItemFocus(event, nodeToFocusId);
|
|
56
|
-
}
|
|
75
|
+
innerFocusItem(event, nodeToFocusId);
|
|
57
76
|
});
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
77
|
+
const removeFocusedItem = useEventCallback(() => {
|
|
78
|
+
if (state.focusedNodeId == null) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const node = instance.getNode(state.focusedNodeId);
|
|
82
|
+
const itemElement = document.getElementById(instance.getTreeItemId(state.focusedNodeId, node.idAttribute));
|
|
83
|
+
if (itemElement) {
|
|
84
|
+
itemElement.blur();
|
|
85
|
+
}
|
|
86
|
+
setFocusedItemId(null);
|
|
62
87
|
});
|
|
88
|
+
const canItemBeTabbed = itemId => itemId === tabbableItemId;
|
|
63
89
|
populateInstance(instance, {
|
|
64
90
|
isNodeFocused,
|
|
91
|
+
canItemBeTabbed,
|
|
65
92
|
focusItem,
|
|
66
|
-
|
|
67
|
-
|
|
93
|
+
focusDefaultNode,
|
|
94
|
+
removeFocusedItem
|
|
68
95
|
});
|
|
69
96
|
populatePublicAPI(publicAPI, {
|
|
70
97
|
focusItem
|
|
@@ -72,12 +99,9 @@ export const useTreeViewFocus = ({
|
|
|
72
99
|
useInstanceEventHandler(instance, 'removeNode', ({
|
|
73
100
|
id
|
|
74
101
|
}) => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
return oldFocusedNodeId;
|
|
80
|
-
});
|
|
102
|
+
if (state.focusedNodeId === id) {
|
|
103
|
+
instance.focusDefaultNode(null);
|
|
104
|
+
}
|
|
81
105
|
});
|
|
82
106
|
const createHandleFocus = otherHandlers => event => {
|
|
83
107
|
otherHandlers.onFocus?.(event);
|
|
@@ -86,16 +110,11 @@ export const useTreeViewFocus = ({
|
|
|
86
110
|
instance.focusDefaultNode(event);
|
|
87
111
|
}
|
|
88
112
|
};
|
|
89
|
-
const createHandleBlur = otherHandlers => event => {
|
|
90
|
-
otherHandlers.onBlur?.(event);
|
|
91
|
-
setFocusedNodeId(null);
|
|
92
|
-
};
|
|
93
113
|
const focusedNode = instance.getNode(state.focusedNodeId);
|
|
94
114
|
const activeDescendant = focusedNode ? instance.getTreeItemId(focusedNode.id, focusedNode.idAttribute) : null;
|
|
95
115
|
return {
|
|
96
116
|
getRootProps: otherHandlers => ({
|
|
97
117
|
onFocus: createHandleFocus(otherHandlers),
|
|
98
|
-
onBlur: createHandleBlur(otherHandlers),
|
|
99
118
|
'aria-activedescendant': activeDescendant ?? undefined
|
|
100
119
|
})
|
|
101
120
|
};
|
|
@@ -6,7 +6,7 @@ export const useTreeViewId = ({
|
|
|
6
6
|
params
|
|
7
7
|
}) => {
|
|
8
8
|
const treeId = useId(params.id);
|
|
9
|
-
const getTreeItemId = React.useCallback((
|
|
9
|
+
const getTreeItemId = React.useCallback((itemId, idAttribute) => idAttribute ?? `${treeId}-${itemId}`, [treeId]);
|
|
10
10
|
populateInstance(instance, {
|
|
11
11
|
getTreeItemId
|
|
12
12
|
});
|
|
@@ -32,12 +32,12 @@ export const useTreeViewJSXNodes = ({
|
|
|
32
32
|
});
|
|
33
33
|
});
|
|
34
34
|
});
|
|
35
|
-
const removeJSXNode = useEventCallback(
|
|
35
|
+
const removeJSXNode = useEventCallback(itemId => {
|
|
36
36
|
setState(prevState => {
|
|
37
37
|
const newNodeMap = _extends({}, prevState.nodes.nodeMap);
|
|
38
38
|
const newItemMap = _extends({}, prevState.nodes.itemMap);
|
|
39
|
-
delete newNodeMap[
|
|
40
|
-
delete newItemMap[
|
|
39
|
+
delete newNodeMap[itemId];
|
|
40
|
+
delete newItemMap[itemId];
|
|
41
41
|
return _extends({}, prevState, {
|
|
42
42
|
nodes: _extends({}, prevState.nodes, {
|
|
43
43
|
nodeMap: newNodeMap,
|
|
@@ -46,18 +46,18 @@ export const useTreeViewJSXNodes = ({
|
|
|
46
46
|
});
|
|
47
47
|
});
|
|
48
48
|
publishTreeViewEvent(instance, 'removeNode', {
|
|
49
|
-
id:
|
|
49
|
+
id: itemId
|
|
50
50
|
});
|
|
51
51
|
});
|
|
52
|
-
const mapFirstCharFromJSX = useEventCallback((
|
|
52
|
+
const mapFirstCharFromJSX = useEventCallback((itemId, firstChar) => {
|
|
53
53
|
instance.updateFirstCharMap(firstCharMap => {
|
|
54
|
-
firstCharMap[
|
|
54
|
+
firstCharMap[itemId] = firstChar;
|
|
55
55
|
return firstCharMap;
|
|
56
56
|
});
|
|
57
57
|
return () => {
|
|
58
58
|
instance.updateFirstCharMap(firstCharMap => {
|
|
59
59
|
const newMap = _extends({}, firstCharMap);
|
|
60
|
-
delete newMap[
|
|
60
|
+
delete newMap[itemId];
|
|
61
61
|
return newMap;
|
|
62
62
|
});
|
|
63
63
|
};
|
|
@@ -77,7 +77,7 @@ const useTreeViewJSXNodesItemPlugin = ({
|
|
|
77
77
|
children,
|
|
78
78
|
disabled = false,
|
|
79
79
|
label,
|
|
80
|
-
|
|
80
|
+
itemId,
|
|
81
81
|
id
|
|
82
82
|
} = props;
|
|
83
83
|
const {
|
|
@@ -96,8 +96,8 @@ const useTreeViewJSXNodesItemPlugin = ({
|
|
|
96
96
|
const handleContentRef = useForkRef(pluginContentRef, contentRef);
|
|
97
97
|
const descendant = React.useMemo(() => ({
|
|
98
98
|
element: treeItemElement,
|
|
99
|
-
id:
|
|
100
|
-
}), [
|
|
99
|
+
id: itemId
|
|
100
|
+
}), [itemId, treeItemElement]);
|
|
101
101
|
const {
|
|
102
102
|
index,
|
|
103
103
|
parentId
|
|
@@ -106,23 +106,23 @@ const useTreeViewJSXNodesItemPlugin = ({
|
|
|
106
106
|
// On the first render a node's index will be -1. We want to wait for the real index.
|
|
107
107
|
if (index !== -1) {
|
|
108
108
|
instance.insertJSXNode({
|
|
109
|
-
id:
|
|
109
|
+
id: itemId,
|
|
110
110
|
idAttribute: id,
|
|
111
111
|
index,
|
|
112
112
|
parentId,
|
|
113
113
|
expandable,
|
|
114
114
|
disabled
|
|
115
115
|
});
|
|
116
|
-
return () => instance.removeJSXNode(
|
|
116
|
+
return () => instance.removeJSXNode(itemId);
|
|
117
117
|
}
|
|
118
118
|
return undefined;
|
|
119
|
-
}, [instance, parentId, index,
|
|
119
|
+
}, [instance, parentId, index, itemId, expandable, disabled, id]);
|
|
120
120
|
React.useEffect(() => {
|
|
121
121
|
if (label) {
|
|
122
|
-
return instance.mapFirstCharFromJSX(
|
|
122
|
+
return instance.mapFirstCharFromJSX(itemId, (pluginContentRef.current?.textContent ?? '').substring(0, 1).toLowerCase());
|
|
123
123
|
}
|
|
124
124
|
return undefined;
|
|
125
|
-
}, [instance,
|
|
125
|
+
}, [instance, itemId, label]);
|
|
126
126
|
return {
|
|
127
127
|
contentRef: handleContentRef,
|
|
128
128
|
rootRef: handleRootRef
|
|
@@ -131,9 +131,9 @@ const useTreeViewJSXNodesItemPlugin = ({
|
|
|
131
131
|
useTreeViewJSXNodes.itemPlugin = useTreeViewJSXNodesItemPlugin;
|
|
132
132
|
useTreeViewJSXNodes.wrapItem = ({
|
|
133
133
|
children,
|
|
134
|
-
|
|
134
|
+
itemId
|
|
135
135
|
}) => /*#__PURE__*/_jsx(DescendantProvider, {
|
|
136
|
-
id:
|
|
136
|
+
id: itemId,
|
|
137
137
|
children: children
|
|
138
138
|
});
|
|
139
139
|
useTreeViewJSXNodes.params = {};
|