@mui/x-tree-view 8.21.0 → 8.23.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.
Files changed (80) hide show
  1. package/CHANGELOG.md +339 -1
  2. package/RichTreeView/RichTreeView.js +8 -1
  3. package/RichTreeView/RichTreeView.types.d.ts +1 -1
  4. package/SimpleTreeView/SimpleTreeView.js +1 -1
  5. package/SimpleTreeView/SimpleTreeView.plugins.d.ts +1 -1
  6. package/SimpleTreeView/SimpleTreeView.types.d.ts +1 -1
  7. package/TreeItem/TreeItem.js +9 -2
  8. package/esm/RichTreeView/RichTreeView.js +8 -1
  9. package/esm/RichTreeView/RichTreeView.types.d.ts +1 -1
  10. package/esm/SimpleTreeView/SimpleTreeView.js +1 -1
  11. package/esm/SimpleTreeView/SimpleTreeView.plugins.d.ts +1 -1
  12. package/esm/SimpleTreeView/SimpleTreeView.types.d.ts +1 -1
  13. package/esm/TreeItem/TreeItem.js +9 -2
  14. package/esm/hooks/index.d.ts +4 -2
  15. package/esm/hooks/index.js +4 -2
  16. package/esm/hooks/useApplyPropagationToSelectedItemsOnMount.js +1 -1
  17. package/esm/hooks/useRichTreeViewApiRef.d.ts +8 -0
  18. package/esm/hooks/useRichTreeViewApiRef.js +7 -0
  19. package/esm/hooks/useSimpleTreeViewApiRef.d.ts +8 -0
  20. package/esm/hooks/useSimpleTreeViewApiRef.js +7 -0
  21. package/esm/hooks/useTreeItemUtils/useTreeItemUtils.js +1 -1
  22. package/esm/hooks/useTreeViewApiRef.d.ts +1 -0
  23. package/esm/hooks/useTreeViewApiRef.js +1 -0
  24. package/esm/index.js +1 -1
  25. package/esm/internals/models/treeView.d.ts +1 -0
  26. package/esm/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +6 -6
  27. package/esm/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +4 -4
  28. package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.js +13 -8
  29. package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.d.ts +4 -0
  30. package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js +5 -1
  31. package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +7 -0
  32. package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.utils.d.ts +1 -1
  33. package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +1 -0
  34. package/esm/internals/plugins/useTreeViewJSXItems/itemPlugin.js +6 -4
  35. package/esm/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +3 -3
  36. package/esm/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +4 -4
  37. package/esm/internals/plugins/useTreeViewLabel/useTreeViewLabel.js +1 -1
  38. package/esm/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.types.d.ts +2 -2
  39. package/esm/internals/plugins/useTreeViewSelection/itemPlugin.js +5 -5
  40. package/esm/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +3 -2
  41. package/esm/internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.d.ts +6 -1
  42. package/esm/internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.js +7 -2
  43. package/esm/internals/useTreeView/useTreeView.js +2 -2
  44. package/esm/models/items.d.ts +4 -1
  45. package/esm/useTreeItem/useTreeItem.js +1 -1
  46. package/esm/useTreeItem/useTreeItem.types.d.ts +5 -0
  47. package/hooks/index.d.ts +4 -2
  48. package/hooks/index.js +16 -2
  49. package/hooks/useApplyPropagationToSelectedItemsOnMount.js +1 -1
  50. package/hooks/useRichTreeViewApiRef.d.ts +8 -0
  51. package/hooks/useRichTreeViewApiRef.js +14 -0
  52. package/hooks/useSimpleTreeViewApiRef.d.ts +8 -0
  53. package/hooks/useSimpleTreeViewApiRef.js +14 -0
  54. package/hooks/useTreeItemUtils/useTreeItemUtils.js +1 -1
  55. package/hooks/useTreeViewApiRef.d.ts +1 -0
  56. package/hooks/useTreeViewApiRef.js +1 -0
  57. package/index.js +1 -1
  58. package/internals/models/treeView.d.ts +1 -0
  59. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +6 -6
  60. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +4 -4
  61. package/internals/plugins/useTreeViewItems/useTreeViewItems.js +13 -8
  62. package/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.d.ts +4 -0
  63. package/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js +5 -1
  64. package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +7 -0
  65. package/internals/plugins/useTreeViewItems/useTreeViewItems.utils.d.ts +1 -1
  66. package/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +1 -0
  67. package/internals/plugins/useTreeViewJSXItems/itemPlugin.js +6 -4
  68. package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +3 -3
  69. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +4 -4
  70. package/internals/plugins/useTreeViewLabel/useTreeViewLabel.js +1 -1
  71. package/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.types.d.ts +2 -2
  72. package/internals/plugins/useTreeViewSelection/itemPlugin.js +5 -5
  73. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +3 -2
  74. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.d.ts +6 -1
  75. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.js +7 -2
  76. package/internals/useTreeView/useTreeView.js +2 -2
  77. package/models/items.d.ts +4 -1
  78. package/package.json +3 -3
  79. package/useTreeItem/useTreeItem.js +1 -1
  80. package/useTreeItem/useTreeItem.types.d.ts +5 -0
@@ -8,6 +8,7 @@ export interface TreeViewItemMeta {
8
8
  parentId: string | null;
9
9
  expandable: boolean;
10
10
  disabled: boolean;
11
+ selectable: boolean;
11
12
  /**
12
13
  * Only defined for `<RichTreeView />` and `<RichTreeViewPro />`.
13
14
  */
@@ -1,7 +1,7 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import { useAssertModelConsistency } from '@mui/x-internals/useAssertModelConsistency';
3
- import { useEventCallback } from '@base-ui-components/utils/useEventCallback';
4
- import { useIsoLayoutEffect } from '@base-ui-components/utils/useIsoLayoutEffect';
3
+ import { useStableCallback } from '@base-ui/utils/useStableCallback';
4
+ import { useIsoLayoutEffect } from '@base-ui/utils/useIsoLayoutEffect';
5
5
  import { expansionSelectors } from "./useTreeViewExpansion.selectors.js";
6
6
  import { getExpansionTrigger } from "./useTreeViewExpansion.utils.js";
7
7
  import { itemsSelectors } from "../useTreeViewItems/useTreeViewItems.selectors.js";
@@ -37,10 +37,10 @@ export const useTreeViewExpansion = ({
37
37
  }
38
38
  params.onExpandedItemsChange?.(event, value);
39
39
  };
40
- const resetItemExpansion = useEventCallback(() => {
40
+ const resetItemExpansion = useStableCallback(() => {
41
41
  setExpandedItems(null, []);
42
42
  });
43
- const applyItemExpansion = useEventCallback(({
43
+ const applyItemExpansion = useStableCallback(({
44
44
  itemId,
45
45
  event,
46
46
  shouldBeExpanded
@@ -57,7 +57,7 @@ export const useTreeViewExpansion = ({
57
57
  }
58
58
  setExpandedItems(event, newExpanded);
59
59
  });
60
- const setItemExpansion = useEventCallback(({
60
+ const setItemExpansion = useStableCallback(({
61
61
  itemId,
62
62
  event = null,
63
63
  shouldBeExpanded
@@ -83,7 +83,7 @@ export const useTreeViewExpansion = ({
83
83
  shouldBeExpanded: cleanShouldBeExpanded
84
84
  });
85
85
  });
86
- const isItemExpanded = useEventCallback(itemId => {
86
+ const isItemExpanded = useStableCallback(itemId => {
87
87
  return expansionSelectors.isItemExpanded(store.state, itemId);
88
88
  });
89
89
  const expandAllSiblings = (event, itemId) => {
@@ -1,5 +1,5 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
- import { useEventCallback } from '@base-ui-components/utils/useEventCallback';
2
+ import { useStableCallback } from '@base-ui/utils/useStableCallback';
3
3
  import { useStoreEffect } from '@mui/x-internals/store';
4
4
  import { focusSelectors } from "./useTreeViewFocus.selectors.js";
5
5
  import { expansionSelectors } from "../useTreeViewExpansion/useTreeViewExpansion.selectors.js";
@@ -9,7 +9,7 @@ export const useTreeViewFocus = ({
9
9
  params,
10
10
  store
11
11
  }) => {
12
- const setFocusedItemId = useEventCallback(itemId => {
12
+ const setFocusedItemId = useStableCallback(itemId => {
13
13
  const focusedItemId = focusSelectors.focusedItemId(store.state);
14
14
  if (focusedItemId === itemId) {
15
15
  return;
@@ -32,13 +32,13 @@ export const useTreeViewFocus = ({
32
32
  params.onItemFocus(event, itemId);
33
33
  }
34
34
  };
35
- const focusItem = useEventCallback((event, itemId) => {
35
+ const focusItem = useStableCallback((event, itemId) => {
36
36
  // If we receive an itemId, and it is visible, the focus will be set to it
37
37
  if (isItemVisible(itemId)) {
38
38
  innerFocusItem(event, itemId);
39
39
  }
40
40
  });
41
- const removeFocusedItem = useEventCallback(() => {
41
+ const removeFocusedItem = useStableCallback(() => {
42
42
  const focusedItemId = focusSelectors.focusedItemId(store.state);
43
43
  if (focusedItemId == null) {
44
44
  return;
@@ -2,13 +2,14 @@
2
2
 
3
3
  import _extends from "@babel/runtime/helpers/esm/extends";
4
4
  import * as React from 'react';
5
- import { useEventCallback } from '@base-ui-components/utils/useEventCallback';
5
+ import { useStableCallback } from '@base-ui/utils/useStableCallback';
6
6
  import { buildItemsLookups, buildItemsState, TREE_VIEW_ROOT_PARENT_ID } from "./useTreeViewItems.utils.js";
7
7
  import { TreeViewItemDepthContext } from "../../TreeViewItemDepthContext/index.js";
8
8
  import { itemsSelectors } from "./useTreeViewItems.selectors.js";
9
9
  import { idSelectors } from "../../corePlugins/useTreeViewId/index.js";
10
10
  import { generateTreeItemIdAttribute } from "../../corePlugins/useTreeViewId/useTreeViewId.utils.js";
11
11
  import { jsx as _jsx } from "react/jsx-runtime";
12
+ const defaultIsItemSelectionDisabled = item => item.disableSelection === true;
12
13
  export const useTreeViewItems = ({
13
14
  instance,
14
15
  params,
@@ -16,16 +17,17 @@ export const useTreeViewItems = ({
16
17
  }) => {
17
18
  const itemsConfig = React.useMemo(() => ({
18
19
  isItemDisabled: params.isItemDisabled,
20
+ isItemSelectionDisabled: params.isItemSelectionDisabled,
19
21
  getItemLabel: params.getItemLabel,
20
22
  getItemChildren: params.getItemChildren,
21
23
  getItemId: params.getItemId
22
- }), [params.isItemDisabled, params.getItemLabel, params.getItemChildren, params.getItemId]);
24
+ }), [params.isItemDisabled, params.isItemSelectionDisabled, params.getItemLabel, params.getItemChildren, params.getItemId]);
23
25
  const getItem = React.useCallback(itemId => itemsSelectors.itemModel(store.state, itemId), [store]);
24
26
  const getParentId = React.useCallback(itemId => {
25
27
  const itemMeta = itemsSelectors.itemMeta(store.state, itemId);
26
28
  return itemMeta?.parentId || null;
27
29
  }, [store]);
28
- const setIsItemDisabled = useEventCallback(({
30
+ const setIsItemDisabled = useStableCallback(({
29
31
  itemId,
30
32
  shouldBeDisabled
31
33
  }) => {
@@ -104,7 +106,7 @@ export const useTreeViewItems = ({
104
106
  };
105
107
  store.set('items', _extends({}, store.state.items, lookups));
106
108
  };
107
- const removeChildren = useEventCallback(parentId => {
109
+ const removeChildren = useStableCallback(parentId => {
108
110
  const newMetaMap = Object.keys(store.state.items.itemMetaLookup).reduce((acc, key) => {
109
111
  const item = store.state.items.itemMetaLookup[key];
110
112
  if (item.parentId === parentId) {
@@ -125,7 +127,7 @@ export const useTreeViewItems = ({
125
127
  itemChildrenIndexesLookup: newItemChildrenIndexesLookup
126
128
  }));
127
129
  });
128
- const addExpandableItems = useEventCallback(items => {
130
+ const addExpandableItems = useStableCallback(items => {
129
131
  const newItemMetaLookup = _extends({}, store.state.items.itemMetaLookup);
130
132
  for (const itemId of items) {
131
133
  newItemMetaLookup[itemId] = _extends({}, newItemMetaLookup[itemId], {
@@ -148,8 +150,8 @@ export const useTreeViewItems = ({
148
150
  store.set('items', _extends({}, store.state.items, newState));
149
151
  }, [instance, store, params.items, params.disabledItemsFocusable, itemsConfig]);
150
152
 
151
- // Wrap `props.onItemClick` with `useEventCallback` to prevent unneeded context updates.
152
- const handleItemClick = useEventCallback((event, itemId) => {
153
+ // Wrap `props.onItemClick` with `useStableCallback` to prevent unneeded context updates.
154
+ const handleItemClick = useStableCallback((event, itemId) => {
153
155
  if (params.onItemClick) {
154
156
  params.onItemClick(event, itemId);
155
157
  }
@@ -185,6 +187,7 @@ useTreeViewItems.getInitialState = params => ({
185
187
  disabledItemsFocusable: params.disabledItemsFocusable,
186
188
  config: {
187
189
  isItemDisabled: params.isItemDisabled,
190
+ isItemSelectionDisabled: params.isItemSelectionDisabled,
188
191
  getItemId: params.getItemId,
189
192
  getItemLabel: params.getItemLabel,
190
193
  getItemChildren: params.getItemChildren
@@ -195,7 +198,8 @@ useTreeViewItems.applyDefaultValuesToParams = ({
195
198
  params
196
199
  }) => _extends({}, params, {
197
200
  disabledItemsFocusable: params.disabledItemsFocusable ?? false,
198
- itemChildrenIndentation: params.itemChildrenIndentation ?? '12px'
201
+ itemChildrenIndentation: params.itemChildrenIndentation ?? '12px',
202
+ isItemSelectionDisabled: params.isItemSelectionDisabled ?? defaultIsItemSelectionDisabled
199
203
  });
200
204
  useTreeViewItems.wrapRoot = ({
201
205
  children
@@ -210,6 +214,7 @@ useTreeViewItems.params = {
210
214
  disabledItemsFocusable: true,
211
215
  items: true,
212
216
  isItemDisabled: true,
217
+ isItemSelectionDisabled: true,
213
218
  getItemLabel: true,
214
219
  getItemChildren: true,
215
220
  getItemId: true,
@@ -53,4 +53,8 @@ export declare const itemsSelectors: {
53
53
  * Checks whether an item can be focused.
54
54
  */
55
55
  canItemBeFocused: (state: TreeViewState<[UseTreeViewItemsSignature]>, itemId: string) => boolean;
56
+ /**
57
+ * Checks whether an item is selectable based on the `isItemSelectionDisabled` prop.
58
+ */
59
+ isItemSelectable: (state: TreeViewState<[UseTreeViewItemsSignature]>, itemId: string) => boolean;
56
60
  };
@@ -56,5 +56,9 @@ export const itemsSelectors = {
56
56
  /**
57
57
  * Checks whether an item can be focused.
58
58
  */
59
- canItemBeFocused: createSelector((state, itemId) => state.items.disabledItemsFocusable || !isItemDisabled(state.items.itemMetaLookup, itemId))
59
+ canItemBeFocused: createSelector((state, itemId) => state.items.disabledItemsFocusable || !isItemDisabled(state.items.itemMetaLookup, itemId)),
60
+ /**
61
+ * Checks whether an item is selectable based on the `isItemSelectionDisabled` prop.
62
+ */
63
+ isItemSelectable: createSelector((state, itemId) => state.items.itemMetaLookup[itemId]?.selectable ?? true)
60
64
  };
@@ -100,6 +100,13 @@ export interface UseTreeViewItemsParameters<R extends {
100
100
  * @returns {boolean} `true` if the item should be disabled.
101
101
  */
102
102
  isItemDisabled?: (item: R) => boolean;
103
+ /**
104
+ * Used to determine if a given item should have selection disabled.
105
+ * @template R
106
+ * @param {R} item The item to check.
107
+ * @returns {boolean} `true` if the item should have selection disabled.
108
+ */
109
+ isItemSelectionDisabled?: (item: R) => boolean;
103
110
  /**
104
111
  * Used to determine the string label for a given item.
105
112
  *
@@ -45,5 +45,5 @@ interface BuildItemsLookupsParameters {
45
45
  [itemId: string]: TreeViewItemMeta;
46
46
  };
47
47
  }
48
- export interface BuildItemsLookupConfig extends Pick<UseTreeViewItemsParametersWithDefaults<TreeViewBaseItem>, 'isItemDisabled' | 'getItemLabel' | 'getItemChildren' | 'getItemId'> {}
48
+ export interface BuildItemsLookupConfig extends Pick<UseTreeViewItemsParametersWithDefaults<TreeViewBaseItem>, 'isItemDisabled' | 'isItemSelectionDisabled' | 'getItemLabel' | 'getItemChildren' | 'getItemId'> {}
49
49
  export {};
@@ -120,6 +120,7 @@ export function buildItemsLookups(parameters) {
120
120
  idAttribute: undefined,
121
121
  expandable: isItemExpandable(item, children),
122
122
  disabled: config.isItemDisabled ? config.isItemDisabled(item) : false,
123
+ selectable: config.isItemSelectionDisabled ? !config.isItemSelectionDisabled(item) : true,
123
124
  depth
124
125
  };
125
126
  orderedChildrenIds.push(id);
@@ -2,8 +2,8 @@
2
2
 
3
3
  import * as React from 'react';
4
4
  import { useStore } from '@mui/x-internals/store';
5
- import { useMergedRefs } from '@base-ui-components/utils/useMergedRefs';
6
- import { useIsoLayoutEffect } from '@base-ui-components/utils/useIsoLayoutEffect';
5
+ import { useMergedRefs } from '@base-ui/utils/useMergedRefs';
6
+ import { useIsoLayoutEffect } from '@base-ui/utils/useIsoLayoutEffect';
7
7
  import { useTreeViewContext } from "../../TreeViewProvider/index.js";
8
8
  import { TreeViewChildrenItemContext } from "../../TreeViewProvider/TreeViewChildrenItemProvider.js";
9
9
  import { itemHasChildren } from "../../../hooks/useTreeItemUtils/useTreeItemUtils.js";
@@ -21,6 +21,7 @@ export const useTreeViewJSXItemsItemPlugin = ({
21
21
  const {
22
22
  children,
23
23
  disabled = false,
24
+ disableSelection = false,
24
25
  label,
25
26
  itemId,
26
27
  id
@@ -58,9 +59,10 @@ export const useTreeViewJSXItemsItemPlugin = ({
58
59
  idAttribute: id,
59
60
  parentId,
60
61
  expandable,
61
- disabled
62
+ disabled,
63
+ selectable: !disableSelection
62
64
  });
63
- }, [instance, parentId, itemId, expandable, disabled, id]);
65
+ }, [instance, parentId, itemId, expandable, disabled, disableSelection, id]);
64
66
  React.useEffect(() => {
65
67
  if (label) {
66
68
  return instance.mapLabelFromJSX(itemId, (pluginContentRef.current?.textContent ?? '').toLowerCase());
@@ -2,7 +2,7 @@
2
2
 
3
3
  import _extends from "@babel/runtime/helpers/esm/extends";
4
4
  import * as React from 'react';
5
- import { useEventCallback } from '@base-ui-components/utils/useEventCallback';
5
+ import { useStableCallback } from '@base-ui/utils/useStableCallback';
6
6
  import { TreeViewChildrenItemProvider } from "../../TreeViewProvider/TreeViewChildrenItemProvider.js";
7
7
  import { buildSiblingIndexes, TREE_VIEW_ROOT_PARENT_ID } from "../useTreeViewItems/useTreeViewItems.utils.js";
8
8
  import { TreeViewItemDepthContext } from "../../TreeViewItemDepthContext/index.js";
@@ -13,7 +13,7 @@ export const useTreeViewJSXItems = ({
13
13
  store
14
14
  }) => {
15
15
  instance.preventItemUpdates();
16
- const insertJSXItem = useEventCallback(item => {
16
+ const insertJSXItem = useStableCallback(item => {
17
17
  if (store.state.items.itemMetaLookup[item.id] != null) {
18
18
  throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', `Two items were provided with the same id in the \`items\` prop: "${item.id}"`].join('\n'));
19
19
  }
@@ -51,7 +51,7 @@ export const useTreeViewJSXItems = ({
51
51
  })
52
52
  }));
53
53
  };
54
- const mapLabelFromJSX = useEventCallback((itemId, label) => {
54
+ const mapLabelFromJSX = useStableCallback((itemId, label) => {
55
55
  instance.updateLabelMap(labelMap => {
56
56
  labelMap[itemId] = label;
57
57
  return labelMap;
@@ -3,8 +3,8 @@
3
3
  import * as React from 'react';
4
4
  import { useStore } from '@mui/x-internals/store';
5
5
  import { useRtl } from '@mui/system/RtlProvider';
6
- import { useTimeout } from '@base-ui-components/utils/useTimeout';
7
- import { useEventCallback } from '@base-ui-components/utils/useEventCallback';
6
+ import { useTimeout } from '@base-ui/utils/useTimeout';
7
+ import { useStableCallback } from '@base-ui/utils/useStableCallback';
8
8
  import { getFirstNavigableItem, getLastNavigableItem, getNextNavigableItem, getPreviousNavigableItem, isTargetInDescendants } from "../../utils/tree.js";
9
9
  import { hasPlugin } from "../../utils/plugins.js";
10
10
  import { useTreeViewLabel } from "../useTreeViewLabel/index.js";
@@ -25,7 +25,7 @@ export const useTreeViewKeyboardNavigation = ({
25
25
  const labelMap = React.useRef({});
26
26
  const typeaheadQueryRef = React.useRef('');
27
27
  const typeaheadTimeout = useTimeout();
28
- const updateLabelMap = useEventCallback(callback => {
28
+ const updateLabelMap = useStableCallback(callback => {
29
29
  labelMap.current = callback(labelMap.current);
30
30
  });
31
31
  const itemMetaLookup = useStore(store, itemsSelectors.itemMetaLookup);
@@ -85,7 +85,7 @@ export const useTreeViewKeyboardNavigation = ({
85
85
  typeaheadQueryRef.current = '';
86
86
  return null;
87
87
  };
88
- const canToggleItemSelection = itemId => selectionSelectors.enabled(store.state) && !itemsSelectors.isItemDisabled(store.state, itemId);
88
+ const canToggleItemSelection = itemId => selectionSelectors.canItemBeSelected(store.state, itemId);
89
89
  const canToggleItemExpansion = itemId => {
90
90
  return !itemsSelectors.isItemDisabled(store.state, itemId) && expansionSelectors.isItemExpandable(store.state, itemId);
91
91
  };
@@ -1,5 +1,5 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
- import { useIsoLayoutEffect } from '@base-ui-components/utils/useIsoLayoutEffect';
2
+ import { useIsoLayoutEffect } from '@base-ui/utils/useIsoLayoutEffect';
3
3
  import { useTreeViewLabelItemPlugin } from "./itemPlugin.js";
4
4
  import { labelSelectors } from "./useTreeViewLabel.selectors.js";
5
5
  export const useTreeViewLabel = ({
@@ -30,10 +30,10 @@ export interface UseTreeViewLazyLoadingPublicAPI {
30
30
  * Method used for updating an item's children.
31
31
  * Only relevant for lazy-loaded tree views.
32
32
  *
33
- * @param {TreeViewItemId} itemId The The id of the item to update the children of.
33
+ * @param {TreeViewItemId | null} itemId The id of the item to update the children of. If null is passed, it will update the root's children.
34
34
  * @returns {Promise<void>} The promise resolved when the items are fetched.
35
35
  */
36
- updateItemChildren: (itemId: TreeViewItemId) => Promise<void>;
36
+ updateItemChildren: (itemId: TreeViewItemId | null) => Promise<void>;
37
37
  }
38
38
  export interface UseTreeViewLazyLoadingInstance extends UseTreeViewLazyLoadingPublicAPI {
39
39
  /**
@@ -44,9 +44,9 @@ export const useTreeViewSelectionItemPlugin = ({
44
44
  store
45
45
  } = useTreeViewContext();
46
46
  const isCheckboxSelectionEnabled = useStore(store, selectionSelectors.isCheckboxSelectionEnabled);
47
- const isItemSelectionEnabled = useStore(store, selectionSelectors.canItemBeSelected, itemId);
47
+ const isFeatureEnabledForItem = useStore(store, selectionSelectors.isFeatureEnabledForItem, itemId);
48
+ const canItemBeSelected = useStore(store, selectionSelectors.canItemBeSelected, itemId);
48
49
  const selectionStatus = useStore(store, selectorCheckboxSelectionStatus, itemId);
49
- const isSelectionEnabledForItem = useStore(store, selectionSelectors.canItemBeSelected, itemId);
50
50
  return {
51
51
  propsEnhancers: {
52
52
  root: () => {
@@ -57,7 +57,7 @@ export const useTreeViewSelectionItemPlugin = ({
57
57
  ariaChecked = true;
58
58
  } else if (selectionStatus === 'indeterminate') {
59
59
  ariaChecked = 'mixed';
60
- } else if (!isSelectionEnabledForItem) {
60
+ } else if (!canItemBeSelected) {
61
61
  // - if the tree contains nodes that are not selectable, aria-checked is not present on those nodes.
62
62
  ariaChecked = undefined;
63
63
  } else {
@@ -85,8 +85,8 @@ export const useTreeViewSelectionItemPlugin = ({
85
85
  return {
86
86
  tabIndex: -1,
87
87
  onChange: handleChange,
88
- visible: isCheckboxSelectionEnabled,
89
- disabled: !isItemSelectionEnabled,
88
+ visible: isCheckboxSelectionEnabled && isFeatureEnabledForItem,
89
+ disabled: !canItemBeSelected,
90
90
  checked: selectionStatus === 'checked',
91
91
  indeterminate: selectionStatus === 'indeterminate'
92
92
  };
@@ -1,10 +1,11 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
3
  import { useAssertModelConsistency } from '@mui/x-internals/useAssertModelConsistency';
4
- import { useIsoLayoutEffect } from '@base-ui-components/utils/useIsoLayoutEffect';
4
+ import { useIsoLayoutEffect } from '@base-ui/utils/useIsoLayoutEffect';
5
5
  import { findOrderInTremauxTree, getAllNavigableItems, getFirstNavigableItem, getLastNavigableItem, getNonDisabledItemsInRange } from "../../utils/tree.js";
6
6
  import { propagateSelection, getAddedAndRemovedItems, getLookupFromArray } from "./useTreeViewSelection.utils.js";
7
7
  import { selectionSelectors } from "./useTreeViewSelection.selectors.js";
8
+ import { itemsSelectors } from "../useTreeViewItems/useTreeViewItems.selectors.js";
8
9
  import { useTreeViewSelectionItemPlugin } from "./itemPlugin.js";
9
10
  export const useTreeViewSelection = ({
10
11
  store,
@@ -115,7 +116,7 @@ export const useTreeViewSelection = ({
115
116
 
116
117
  // Add to the model the items that are part of the new range and not already part of the model.
117
118
  const selectedItemsLookup = getLookupFromArray(newSelectedItems);
118
- const range = getNonDisabledItemsInRange(store.state, start, end);
119
+ const range = getNonDisabledItemsInRange(store.state, start, end).filter(id => itemsSelectors.isItemSelectable(store.state, id));
119
120
  const itemsToAddToModel = range.filter(id => !selectedItemsLookup[id]);
120
121
  newSelectedItems = newSelectedItems.concat(itemsToAddToModel);
121
122
  setSelectedItems(event, newSelectedItems);
@@ -34,7 +34,12 @@ export declare const selectionSelectors: {
34
34
  */
35
35
  isItemSelected: (args_0: import("../../corePlugins/useTreeViewId/useTreeViewId.types.js").UseTreeViewIdState & import("./useTreeViewSelection.types.js").UseTreeViewSelectionState & Partial<{}>, itemId: string) => boolean;
36
36
  /**
37
- * Checks whether an item can be selected (if selection is enabled and if the item is not disabled).
37
+ * Checks whether the selection feature is enabled for an item.
38
+ * Returns `true` when selection is enabled on the Tree View and the item is selectable (even if the item is disabled).
39
+ */
40
+ isFeatureEnabledForItem: (args_0: import("../../corePlugins/useTreeViewId/useTreeViewId.types.js").UseTreeViewIdState & import("./useTreeViewSelection.types.js").UseTreeViewSelectionState & Partial<{}>, _itemId: string) => boolean;
41
+ /**
42
+ * Checks whether an item can be selected (if selection is enabled, if the item is not disabled, and if the item is selectable).
38
43
  */
39
44
  canItemBeSelected: (args_0: import("../../corePlugins/useTreeViewId/useTreeViewId.types.js").UseTreeViewIdState & import("./useTreeViewSelection.types.js").UseTreeViewSelectionState & Partial<{}>, _itemId: string) => boolean;
40
45
  };
@@ -50,7 +50,12 @@ export const selectionSelectors = {
50
50
  */
51
51
  isItemSelected: createSelector(selectedItemsMapSelector, (selectedItemsMap, itemId) => selectedItemsMap.has(itemId)),
52
52
  /**
53
- * Checks whether an item can be selected (if selection is enabled and if the item is not disabled).
53
+ * Checks whether the selection feature is enabled for an item.
54
+ * Returns `true` when selection is enabled on the Tree View and the item is selectable (even if the item is disabled).
54
55
  */
55
- canItemBeSelected: createSelector(itemsSelectors.isItemDisabled, state => state.selection.isEnabled, (isItemDisabled, isSelectionEnabled, _itemId) => isSelectionEnabled && !isItemDisabled)
56
+ isFeatureEnabledForItem: createSelector(itemsSelectors.isItemSelectable, state => state.selection.isEnabled, (isItemSelectable, isSelectionEnabled, _itemId) => isSelectionEnabled && isItemSelectable),
57
+ /**
58
+ * Checks whether an item can be selected (if selection is enabled, if the item is not disabled, and if the item is selectable).
59
+ */
60
+ canItemBeSelected: createSelector(itemsSelectors.isItemDisabled, itemsSelectors.isItemSelectable, state => state.selection.isEnabled, (isItemDisabled, isItemSelectable, isSelectionEnabled, _itemId) => isSelectionEnabled && !isItemDisabled && isItemSelectable)
56
61
  };
@@ -1,8 +1,8 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
- import { useRefWithInit } from '@base-ui-components/utils/useRefWithInit';
3
+ import { useRefWithInit } from '@base-ui/utils/useRefWithInit';
4
4
  import { Store } from '@mui/x-internals/store';
5
- import { useMergedRefs } from '@base-ui-components/utils/useMergedRefs';
5
+ import { useMergedRefs } from '@base-ui/utils/useMergedRefs';
6
6
  import { TREE_VIEW_CORE_PLUGINS } from "../corePlugins/index.js";
7
7
  import { useExtractPluginParamsFromProps } from "./useExtractPluginParamsFromProps.js";
8
8
  import { useTreeViewBuildContext } from "./useTreeViewBuildContext.js";
@@ -4,9 +4,12 @@ export type TreeViewDefaultItemModelProperties = {
4
4
  label: string;
5
5
  children?: TreeViewDefaultItemModelProperties[];
6
6
  };
7
- export type TreeViewBaseItem<R extends {} = TreeViewDefaultItemModelProperties> = R & {
7
+ export type TreeViewBaseItem<R extends object = TreeViewDefaultItemModelProperties> = R & {
8
8
  children?: TreeViewBaseItem<R>[];
9
9
  };
10
+ export type TreeViewValidItem<R extends object> = {
11
+ children?: R[];
12
+ };
10
13
  export type TreeViewItemsReorderingAction = 'reorder-above' | 'reorder-below' | 'make-child' | 'move-to-parent';
11
14
  export interface TreeViewSelectionPropagation {
12
15
  descendants?: boolean;
@@ -4,7 +4,7 @@ import _extends from "@babel/runtime/helpers/esm/extends";
4
4
  import * as React from 'react';
5
5
  import { useStore } from '@mui/x-internals/store';
6
6
  import extractEventHandlers from '@mui/utils/extractEventHandlers';
7
- import { useMergedRefs } from '@base-ui-components/utils/useMergedRefs';
7
+ import { useMergedRefs } from '@base-ui/utils/useMergedRefs';
8
8
  import { useTreeViewContext } from "../internals/TreeViewProvider/index.js";
9
9
  import { useTreeItemUtils } from "../hooks/useTreeItemUtils/index.js";
10
10
  import { TreeViewItemDepthContext } from "../internals/TreeViewItemDepthContext/index.js";
@@ -18,6 +18,11 @@ export interface UseTreeItemParameters {
18
18
  * @default false
19
19
  */
20
20
  disabled?: boolean;
21
+ /**
22
+ * If `true`, the item cannot be selected.
23
+ * @default false
24
+ */
25
+ disableSelection?: boolean;
21
26
  /**
22
27
  * The id of the item.
23
28
  * Must be unique.
package/hooks/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
- export { useTreeViewApiRef } from "./useTreeViewApiRef.js";
2
1
  export { useTreeItemUtils } from "./useTreeItemUtils/index.js";
3
2
  export { useTreeItemModel } from "./useTreeItemModel.js";
4
- export { useApplyPropagationToSelectedItemsOnMount } from "./useApplyPropagationToSelectedItemsOnMount.js";
3
+ export { useApplyPropagationToSelectedItemsOnMount } from "./useApplyPropagationToSelectedItemsOnMount.js";
4
+ export { useTreeViewApiRef } from "./useTreeViewApiRef.js";
5
+ export { useRichTreeViewApiRef } from "./useRichTreeViewApiRef.js";
6
+ export { useSimpleTreeViewApiRef } from "./useSimpleTreeViewApiRef.js";
package/hooks/index.js CHANGED
@@ -9,6 +9,18 @@ Object.defineProperty(exports, "useApplyPropagationToSelectedItemsOnMount", {
9
9
  return _useApplyPropagationToSelectedItemsOnMount.useApplyPropagationToSelectedItemsOnMount;
10
10
  }
11
11
  });
12
+ Object.defineProperty(exports, "useRichTreeViewApiRef", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _useRichTreeViewApiRef.useRichTreeViewApiRef;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "useSimpleTreeViewApiRef", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _useSimpleTreeViewApiRef.useSimpleTreeViewApiRef;
22
+ }
23
+ });
12
24
  Object.defineProperty(exports, "useTreeItemModel", {
13
25
  enumerable: true,
14
26
  get: function () {
@@ -27,7 +39,9 @@ Object.defineProperty(exports, "useTreeViewApiRef", {
27
39
  return _useTreeViewApiRef.useTreeViewApiRef;
28
40
  }
29
41
  });
30
- var _useTreeViewApiRef = require("./useTreeViewApiRef");
31
42
  var _useTreeItemUtils = require("./useTreeItemUtils");
32
43
  var _useTreeItemModel = require("./useTreeItemModel");
33
- var _useApplyPropagationToSelectedItemsOnMount = require("./useApplyPropagationToSelectedItemsOnMount");
44
+ var _useApplyPropagationToSelectedItemsOnMount = require("./useApplyPropagationToSelectedItemsOnMount");
45
+ var _useTreeViewApiRef = require("./useTreeViewApiRef");
46
+ var _useRichTreeViewApiRef = require("./useRichTreeViewApiRef");
47
+ var _useSimpleTreeViewApiRef = require("./useSimpleTreeViewApiRef");
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.useApplyPropagationToSelectedItemsOnMount = useApplyPropagationToSelectedItemsOnMount;
7
- var _useRefWithInit = require("@base-ui-components/utils/useRefWithInit");
7
+ var _useRefWithInit = require("@base-ui/utils/useRefWithInit");
8
8
  var _useTreeViewSelection = require("../internals/plugins/useTreeViewSelection/useTreeViewSelection.utils");
9
9
  const defaultGetItemId = item => item.id;
10
10
  const defaultGetItemChildren = item => item.children;
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+ import { TreeViewDefaultItemModelProperties, TreeViewValidItem } from "../models/index.js";
3
+ import { TreeViewPublicAPI } from "../internals/models/index.js";
4
+ import { RichTreeViewPluginSignatures } from "../RichTreeView/RichTreeView.plugins.js";
5
+ /**
6
+ * Creates the ref to pass to the `apiRef` prop of the `RichTreeView` component.
7
+ */
8
+ export declare function useRichTreeViewApiRef<R extends TreeViewValidItem<R> = TreeViewDefaultItemModelProperties>(): React.RefObject<TreeViewPublicAPI<RichTreeViewPluginSignatures> | undefined>;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useRichTreeViewApiRef = useRichTreeViewApiRef;
8
+ var React = _interopRequireWildcard(require("react"));
9
+ /**
10
+ * Creates the ref to pass to the `apiRef` prop of the `RichTreeView` component.
11
+ */
12
+ function useRichTreeViewApiRef() {
13
+ return React.useRef(undefined);
14
+ }
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+ import { TreeViewDefaultItemModelProperties, TreeViewValidItem } from "../models/index.js";
3
+ import { TreeViewPublicAPI } from "../internals/models/index.js";
4
+ import { SimpleTreeViewPluginSignatures } from "../SimpleTreeView/SimpleTreeView.plugins.js";
5
+ /**
6
+ * Creates the ref to pass to the `apiRef` prop of the `SimpleTreeView` component.
7
+ */
8
+ export declare function useSimpleTreeViewApiRef<R extends TreeViewValidItem<R> = TreeViewDefaultItemModelProperties>(): React.RefObject<TreeViewPublicAPI<SimpleTreeViewPluginSignatures> | undefined>;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useSimpleTreeViewApiRef = useSimpleTreeViewApiRef;
8
+ var React = _interopRequireWildcard(require("react"));
9
+ /**
10
+ * Creates the ref to pass to the `apiRef` prop of the `SimpleTreeView` component.
11
+ */
12
+ function useSimpleTreeViewApiRef() {
13
+ return React.useRef(undefined);
14
+ }
@@ -79,7 +79,7 @@ const useTreeItemUtils = ({
79
79
  }
80
80
  };
81
81
  const handleSelection = event => {
82
- if (status.disabled) {
82
+ if (!_useTreeViewSelection.selectionSelectors.canItemBeSelected(store.state, itemId)) {
83
83
  return;
84
84
  }
85
85
  if (!status.focused && !status.editing) {
@@ -3,5 +3,6 @@ import { TreeViewAnyPluginSignature, TreeViewPublicAPI } from "../internals/mode
3
3
  import { RichTreeViewPluginSignatures } from "../RichTreeView/RichTreeView.plugins.js";
4
4
  /**
5
5
  * Hook that instantiates a [[TreeViewApiRef]].
6
+ * @deprecated Use `useRichTreeViewApiRef()`, `useRichTreeViewProApiRef()` or `useSimpleTreeViewApiRef()` instead.
6
7
  */
7
8
  export declare const useTreeViewApiRef: <TSignatures extends readonly TreeViewAnyPluginSignature[] = RichTreeViewPluginSignatures>() => React.RefObject<TreeViewPublicAPI<TSignatures> | undefined>;
@@ -9,6 +9,7 @@ exports.useTreeViewApiRef = void 0;
9
9
  var React = _interopRequireWildcard(require("react"));
10
10
  /**
11
11
  * Hook that instantiates a [[TreeViewApiRef]].
12
+ * @deprecated Use `useRichTreeViewApiRef()`, `useRichTreeViewProApiRef()` or `useSimpleTreeViewApiRef()` instead.
12
13
  */
13
14
  const useTreeViewApiRef = () => React.useRef(undefined);
14
15
  exports.useTreeViewApiRef = useTreeViewApiRef;
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-tree-view v8.21.0
2
+ * @mui/x-tree-view v8.23.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -8,6 +8,7 @@ export interface TreeViewItemMeta {
8
8
  parentId: string | null;
9
9
  expandable: boolean;
10
10
  disabled: boolean;
11
+ selectable: boolean;
11
12
  /**
12
13
  * Only defined for `<RichTreeView />` and `<RichTreeViewPro />`.
13
14
  */