@mui/x-tree-view 7.7.1 → 7.9.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 (60) hide show
  1. package/CHANGELOG.md +166 -1
  2. package/RichTreeView/RichTreeView.js +12 -5
  3. package/SimpleTreeView/SimpleTreeView.js +12 -5
  4. package/TreeItem/TreeItem.js +19 -4
  5. package/TreeItem/TreeItemContent.js +5 -2
  6. package/TreeItem/useTreeItemState.d.ts +1 -0
  7. package/TreeItem/useTreeItemState.js +21 -4
  8. package/TreeItem2/TreeItem2.d.ts +3 -3
  9. package/TreeItem2Provider/TreeItem2Provider.d.ts +0 -1
  10. package/TreeView/TreeView.js +12 -5
  11. package/hooks/useTreeItem2Utils/useTreeItem2Utils.js +16 -3
  12. package/index.js +1 -1
  13. package/internals/hooks/useInstanceEventHandler.d.ts +2 -2
  14. package/internals/models/plugin.d.ts +5 -1
  15. package/internals/models/treeView.d.ts +1 -3
  16. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +13 -1
  17. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +17 -7
  18. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +1 -2
  19. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +2 -2
  20. package/internals/plugins/useTreeViewItems/useTreeViewItems.js +10 -1
  21. package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +7 -1
  22. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +15 -5
  23. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +12 -4
  24. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +25 -16
  25. package/internals/useTreeView/useTreeViewModels.d.ts +1 -1
  26. package/internals/utils/cleanupTracking/TimerBasedCleanupTracking.d.ts +0 -1
  27. package/internals/utils/publishTreeViewEvent.d.ts +1 -1
  28. package/internals/utils/warning.d.ts +1 -1
  29. package/modern/RichTreeView/RichTreeView.js +12 -5
  30. package/modern/SimpleTreeView/SimpleTreeView.js +12 -5
  31. package/modern/TreeItem/TreeItem.js +19 -4
  32. package/modern/TreeItem/TreeItemContent.js +5 -2
  33. package/modern/TreeItem/useTreeItemState.js +21 -4
  34. package/modern/TreeView/TreeView.js +12 -5
  35. package/modern/hooks/useTreeItem2Utils/useTreeItem2Utils.js +16 -3
  36. package/modern/index.js +1 -1
  37. package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +13 -1
  38. package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +1 -2
  39. package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.js +10 -1
  40. package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +15 -5
  41. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +12 -4
  42. package/modern/useTreeItem2/useTreeItem2.js +18 -2
  43. package/node/RichTreeView/RichTreeView.js +12 -5
  44. package/node/SimpleTreeView/SimpleTreeView.js +12 -5
  45. package/node/TreeItem/TreeItem.js +19 -4
  46. package/node/TreeItem/TreeItemContent.js +5 -2
  47. package/node/TreeItem/useTreeItemState.js +21 -4
  48. package/node/TreeView/TreeView.js +12 -5
  49. package/node/hooks/useTreeItem2Utils/useTreeItem2Utils.js +16 -3
  50. package/node/index.js +1 -1
  51. package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +13 -1
  52. package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +1 -2
  53. package/node/internals/plugins/useTreeViewItems/useTreeViewItems.js +10 -1
  54. package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +15 -5
  55. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +12 -4
  56. package/node/useTreeItem2/useTreeItem2.js +18 -2
  57. package/package.json +3 -3
  58. package/useTreeItem2/useTreeItem2.d.ts +2 -2
  59. package/useTreeItem2/useTreeItem2.js +18 -2
  60. package/useTreeItem2/useTreeItem2.types.d.ts +3 -0
@@ -53,6 +53,12 @@ export const useTreeViewExpansion = ({
53
53
  setExpandedItems(event, newExpanded);
54
54
  }
55
55
  };
56
+ const expansionTrigger = React.useMemo(() => {
57
+ if (params.expansionTrigger) {
58
+ return params.expansionTrigger;
59
+ }
60
+ return 'content';
61
+ }, [params.expansionTrigger]);
56
62
  return {
57
63
  publicAPI: {
58
64
  setItemExpansion
@@ -63,6 +69,11 @@ export const useTreeViewExpansion = ({
63
69
  setItemExpansion,
64
70
  toggleItemExpansion,
65
71
  expandAllSiblings
72
+ },
73
+ contextValue: {
74
+ expansion: {
75
+ expansionTrigger
76
+ }
66
77
  }
67
78
  };
68
79
  };
@@ -79,5 +90,6 @@ useTreeViewExpansion.params = {
79
90
  expandedItems: true,
80
91
  defaultExpandedItems: true,
81
92
  onExpandedItemsChange: true,
82
- onItemExpansionToggle: true
93
+ onItemExpansionToggle: true,
94
+ expansionTrigger: true
83
95
  };
@@ -5,9 +5,9 @@ import { TreeViewItemId } from '../../../models';
5
5
  export interface UseTreeViewExpansionPublicAPI {
6
6
  /**
7
7
  * Change the expansion status of a given item.
8
- * @param {React.SyntheticEvent} event The UI event that triggered the change.
9
- * @param {string} itemId The id of the item to modify.
10
- * @param {boolean} isExpanded The new expansion status of the given item.
8
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
9
+ * @param {string} itemId The id of the item to expand of collapse.
10
+ * @param {boolean} isExpanded If `true` the item will be expanded. If `false` the item will be collapsed.
11
11
  */
12
12
  setItemExpansion: (event: React.SyntheticEvent, itemId: string, isExpanded: boolean) => void;
13
13
  }
@@ -29,13 +29,13 @@ export interface UseTreeViewExpansionInstance extends UseTreeViewExpansionPublic
29
29
  /**
30
30
  * Toggle the current expansion of an item.
31
31
  * If it is expanded, it will be collapsed, and vice versa.
32
- * @param {React.SyntheticEvent} event The UI event that triggered the change.
32
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
33
33
  * @param {TreeViewItemId} itemId The id of the item to toggle.
34
34
  */
35
35
  toggleItemExpansion: (event: React.SyntheticEvent, itemId: TreeViewItemId) => void;
36
36
  /**
37
37
  * Expand all the siblings (i.e.: the items that have the same parent) of a given item.
38
- * @param {React.SyntheticEvent} event The UI event that triggered the change.
38
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
39
39
  * @param {TreeViewItemId} itemId The id of the item whose siblings will be expanded.
40
40
  */
41
41
  expandAllSiblings: (event: React.KeyboardEvent, itemId: TreeViewItemId) => void;
@@ -54,24 +54,34 @@ export interface UseTreeViewExpansionParameters {
54
54
  defaultExpandedItems?: string[];
55
55
  /**
56
56
  * Callback fired when tree items are expanded/collapsed.
57
- * @param {React.SyntheticEvent} event The event source of the callback.
57
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
58
58
  * @param {array} itemIds The ids of the expanded items.
59
59
  */
60
60
  onExpandedItemsChange?: (event: React.SyntheticEvent, itemIds: string[]) => void;
61
61
  /**
62
62
  * Callback fired when a tree item is expanded or collapsed.
63
- * @param {React.SyntheticEvent} event The event source of the callback.
63
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
64
64
  * @param {array} itemId The itemId of the modified item.
65
65
  * @param {array} isExpanded `true` if the item has just been expanded, `false` if it has just been collapsed.
66
66
  */
67
67
  onItemExpansionToggle?: (event: React.SyntheticEvent, itemId: string, isExpanded: boolean) => void;
68
+ /**
69
+ * The slot that triggers the item's expansion when clicked.
70
+ * @default 'content'
71
+ */
72
+ expansionTrigger?: 'content' | 'iconContainer';
68
73
  }
69
74
  export type UseTreeViewExpansionDefaultizedParameters = DefaultizedProps<UseTreeViewExpansionParameters, 'defaultExpandedItems'>;
75
+ interface UseTreeViewExpansionContextValue {
76
+ expansion: Pick<UseTreeViewExpansionParameters, 'expansionTrigger'>;
77
+ }
70
78
  export type UseTreeViewExpansionSignature = TreeViewPluginSignature<{
71
79
  params: UseTreeViewExpansionParameters;
72
80
  defaultizedParams: UseTreeViewExpansionDefaultizedParameters;
73
81
  instance: UseTreeViewExpansionInstance;
74
82
  publicAPI: UseTreeViewExpansionPublicAPI;
75
83
  modelNames: 'expandedItems';
84
+ contextValue: UseTreeViewExpansionContextValue;
76
85
  dependencies: [UseTreeViewItemsSignature];
77
86
  }>;
87
+ export {};
@@ -43,8 +43,7 @@ export const useTreeViewFocus = ({
43
43
  return itemMeta && (itemMeta.parentId == null || instance.isItemExpanded(itemMeta.parentId));
44
44
  };
45
45
  const innerFocusItem = (event, itemId) => {
46
- const itemMeta = instance.getItemMeta(itemId);
47
- const itemElement = document.getElementById(instance.getTreeItemIdAttribute(itemId, itemMeta.idAttribute));
46
+ const itemElement = instance.getItemDOMElement(itemId);
48
47
  if (itemElement) {
49
48
  itemElement.focus();
50
49
  }
@@ -10,7 +10,7 @@ export interface UseTreeViewFocusPublicAPI {
10
10
  *
11
11
  * If the item is the child of a collapsed item, then this method will do nothing.
12
12
  * Make sure to expand the ancestors of the item before calling this method if needed.
13
- * @param {React.SyntheticEvent} event The event source of the action.
13
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
14
14
  * @param {TreeViewItemId} itemId The id of the item to focus.
15
15
  */
16
16
  focusItem: (event: React.SyntheticEvent, itemId: string) => void;
@@ -38,7 +38,7 @@ export interface UseTreeViewFocusInstance extends UseTreeViewFocusPublicAPI {
38
38
  export interface UseTreeViewFocusParameters {
39
39
  /**
40
40
  * Callback fired when tree items are focused.
41
- * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event.
41
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change. **Warning**: This is a generic event not a focus event.
42
42
  * @param {string} itemId The id of the focused item.
43
43
  * @param {string} value of the focused item.
44
44
  */
@@ -92,6 +92,13 @@ export const useTreeViewItems = ({
92
92
  return state.items.itemChildrenIndexes[parentId][itemId];
93
93
  }, [instance, state.items.itemChildrenIndexes]);
94
94
  const getItemOrderedChildrenIds = React.useCallback(itemId => state.items.itemOrderedChildrenIds[itemId ?? TREE_VIEW_ROOT_PARENT_ID] ?? [], [state.items.itemOrderedChildrenIds]);
95
+ const getItemDOMElement = itemId => {
96
+ const itemMeta = instance.getItemMeta(itemId);
97
+ if (itemMeta == null) {
98
+ return null;
99
+ }
100
+ return document.getElementById(instance.getTreeItemIdAttribute(itemId, itemMeta.idAttribute));
101
+ };
95
102
  const isItemNavigable = itemId => {
96
103
  if (params.disabledItemsFocusable) {
97
104
  return true;
@@ -145,13 +152,15 @@ export const useTreeViewItems = ({
145
152
  }
146
153
  }),
147
154
  publicAPI: {
148
- getItem
155
+ getItem,
156
+ getItemDOMElement
149
157
  },
150
158
  instance: {
151
159
  getItemMeta,
152
160
  getItem,
153
161
  getItemsToRender,
154
162
  getItemIndex,
163
+ getItemDOMElement,
155
164
  getItemOrderedChildrenIds,
156
165
  isItemDisabled,
157
166
  isItemNavigable,
@@ -10,10 +10,16 @@ export interface UseTreeViewItemsPublicAPI<R extends {}> {
10
10
  /**
11
11
  * Get the item with the given id.
12
12
  * When used in the `SimpleTreeView`, it returns an object with the `id` and `label` properties.
13
- * @param {string} itemId The id of the item to return.
13
+ * @param {string} itemId The id of the item to retrieve.
14
14
  * @returns {R} The item with the given id.
15
15
  */
16
16
  getItem: (itemId: TreeViewItemId) => R;
17
+ /**
18
+ * Get the DOM element of the item with the given id.
19
+ * @param {TreeViewItemId} itemId The id of the item to get the DOM element of.
20
+ * @returns {HTMLElement | null} The DOM element of the item with the given id.
21
+ */
22
+ getItemDOMElement: (itemId: TreeViewItemId) => HTMLElement | null;
17
23
  }
18
24
  export interface UseTreeViewItemsInstance<R extends {}> extends UseTreeViewItemsPublicAPI<R> {
19
25
  /**
@@ -74,10 +74,13 @@ export const useTreeViewKeyboardNavigation = ({
74
74
  event.preventDefault();
75
75
  if (params.multiSelect && event.shiftKey) {
76
76
  instance.expandSelectionRange(event, itemId);
77
- } else if (params.multiSelect) {
78
- instance.selectItem(event, itemId, true);
79
77
  } else {
80
- instance.selectItem(event, itemId, false);
78
+ instance.selectItem({
79
+ event,
80
+ itemId,
81
+ keepExistingSelection: params.multiSelect,
82
+ shouldBeSelected: params.multiSelect ? undefined : true
83
+ });
81
84
  }
82
85
  break;
83
86
  }
@@ -92,9 +95,16 @@ export const useTreeViewKeyboardNavigation = ({
92
95
  } else if (canToggleItemSelection(itemId)) {
93
96
  if (params.multiSelect) {
94
97
  event.preventDefault();
95
- instance.selectItem(event, itemId, true);
98
+ instance.selectItem({
99
+ event,
100
+ itemId,
101
+ keepExistingSelection: true
102
+ });
96
103
  } else if (!instance.isItemSelected(itemId)) {
97
- instance.selectItem(event, itemId, false);
104
+ instance.selectItem({
105
+ event,
106
+ itemId
107
+ });
98
108
  event.preventDefault();
99
109
  }
100
110
  }
@@ -46,7 +46,12 @@ export const useTreeViewSelection = ({
46
46
  models.selectedItems.setControlledValue(newSelectedItems);
47
47
  };
48
48
  const isItemSelected = itemId => selectedItemsMap.has(itemId);
49
- const selectItem = (event, itemId, keepExistingSelection, newValue) => {
49
+ const selectItem = ({
50
+ event,
51
+ itemId,
52
+ keepExistingSelection = false,
53
+ shouldBeSelected
54
+ }) => {
50
55
  if (params.disableSelection) {
51
56
  return;
52
57
  }
@@ -54,16 +59,16 @@ export const useTreeViewSelection = ({
54
59
  if (keepExistingSelection) {
55
60
  const cleanSelectedItems = convertSelectedItemsToArray(models.selectedItems.value);
56
61
  const isSelectedBefore = instance.isItemSelected(itemId);
57
- if (isSelectedBefore && (newValue === false || newValue == null)) {
62
+ if (isSelectedBefore && (shouldBeSelected === false || shouldBeSelected == null)) {
58
63
  newSelected = cleanSelectedItems.filter(id => id !== itemId);
59
- } else if (!isSelectedBefore && (newValue === true || newValue == null)) {
64
+ } else if (!isSelectedBefore && (shouldBeSelected === true || shouldBeSelected == null)) {
60
65
  newSelected = [itemId].concat(cleanSelectedItems);
61
66
  } else {
62
67
  newSelected = cleanSelectedItems;
63
68
  }
64
69
  } else {
65
70
  // eslint-disable-next-line no-lonely-if
66
- if (newValue === false) {
71
+ if (shouldBeSelected === false || shouldBeSelected == null && instance.isItemSelected(itemId)) {
67
72
  newSelected = params.multiSelect ? [] : null;
68
73
  } else {
69
74
  newSelected = params.multiSelect ? [itemId] : itemId;
@@ -142,6 +147,9 @@ export const useTreeViewSelection = ({
142
147
  getRootProps: () => ({
143
148
  'aria-multiselectable': params.multiSelect
144
149
  }),
150
+ publicAPI: {
151
+ selectItem
152
+ },
145
153
  instance: {
146
154
  isItemSelected,
147
155
  selectItem,
@@ -2,47 +2,55 @@ import * as React from 'react';
2
2
  import type { DefaultizedProps, TreeViewPluginSignature } from '../../models';
3
3
  import { UseTreeViewItemsSignature } from '../useTreeViewItems';
4
4
  import { UseTreeViewExpansionSignature } from '../useTreeViewExpansion';
5
- export interface UseTreeViewSelectionInstance {
5
+ export interface UseTreeViewSelectionPublicAPI {
6
+ /**
7
+ * Select or deselect an item.
8
+ * @param {object} params The params of the method.
9
+ * @param {React.SyntheticEvent} params.event The DOM event that triggered the change.
10
+ * @param {string} params.itemId The id of the item to select or deselect.
11
+ * @param {boolean} params.keepExistingSelection If `true`, the other already selected items will remain selected, otherwise, they will be deselected. This parameter is only relevant when `multiSelect` is `true`
12
+ * @param {boolean | undefined} params.shouldBeSelected If `true` the item will be selected. If `false` the item will be deselected. If not defined, the item's new selection status will be the opposite of its current one.
13
+ */
14
+ selectItem: (params: {
15
+ event: React.SyntheticEvent;
16
+ itemId: string;
17
+ keepExistingSelection?: boolean;
18
+ shouldBeSelected?: boolean;
19
+ }) => void;
20
+ }
21
+ export interface UseTreeViewSelectionInstance extends UseTreeViewSelectionPublicAPI {
6
22
  /**
7
23
  * Check if an item is selected.
8
24
  * @param {TreeViewItemId} itemId The id of the item to check.
9
25
  * @returns {boolean} `true` if the item is selected, `false` otherwise.
10
26
  */
11
27
  isItemSelected: (itemId: string) => boolean;
12
- /**
13
- * Select or deselect an item.
14
- * @param {React.SyntheticEvent} event The event source of the callback.
15
- * @param {string} itemId The id of the item to select or deselect.
16
- * @param {boolean} keepExistingSelection If `true`, don't remove the other selected items.
17
- * @param {boolean | undefined} newValue The new selection status of the item. If not defined, the new state will be the opposite of the current state.
18
- */
19
- selectItem: (event: React.SyntheticEvent, itemId: string, keepExistingSelection: boolean, newValue?: boolean) => void;
20
28
  /**
21
29
  * Select all the navigable items in the tree.
22
- * @param {React.SyntheticEvent} event The event source of the callback.
30
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
23
31
  */
24
32
  selectAllNavigableItems: (event: React.SyntheticEvent) => void;
25
33
  /**
26
34
  * Expand the current selection range up to the given item.
27
- * @param {React.SyntheticEvent} event The event source of the callback.
35
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
28
36
  * @param {string} itemId The id of the item to expand the selection to.
29
37
  */
30
38
  expandSelectionRange: (event: React.SyntheticEvent, itemId: string) => void;
31
39
  /**
32
40
  * Expand the current selection range from the first navigable item to the given item.
33
- * @param {React.SyntheticEvent} event The event source of the callback.
41
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
34
42
  * @param {string} itemId The id of the item up to which the selection range should be expanded.
35
43
  */
36
44
  selectRangeFromStartToItem: (event: React.SyntheticEvent, itemId: string) => void;
37
45
  /**
38
46
  * Expand the current selection range from the given item to the last navigable item.
39
- * @param {React.SyntheticEvent} event The event source of the callback.
47
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
40
48
  * @param {string} itemId The id of the item from which the selection range should be expanded.
41
49
  */
42
50
  selectRangeFromItemToEnd: (event: React.SyntheticEvent, itemId: string) => void;
43
51
  /**
44
52
  * Update the selection when navigating with ArrowUp / ArrowDown keys.
45
- * @param {React.SyntheticEvent} event The event source of the callback.
53
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
46
54
  * @param {string} currentItemId The id of the active item before the keyboard navigation.
47
55
  * @param {string} nextItemId The id of the active item after the keyboard navigation.
48
56
  */
@@ -78,14 +86,14 @@ export interface UseTreeViewSelectionParameters<Multiple extends boolean | undef
78
86
  checkboxSelection?: boolean;
79
87
  /**
80
88
  * Callback fired when tree items are selected/deselected.
81
- * @param {React.SyntheticEvent} event The event source of the callback
89
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
82
90
  * @param {string[] | string} itemIds The ids of the selected items.
83
91
  * When `multiSelect` is `true`, this is an array of strings; when false (default) a string.
84
92
  */
85
93
  onSelectedItemsChange?: (event: React.SyntheticEvent, itemIds: TreeViewSelectionValue<Multiple>) => void;
86
94
  /**
87
95
  * Callback fired when a tree item is selected or deselected.
88
- * @param {React.SyntheticEvent} event The event source of the callback.
96
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
89
97
  * @param {array} itemId The itemId of the modified item.
90
98
  * @param {array} isSelected `true` if the item has just been selected, `false` if it has just been deselected.
91
99
  */
@@ -99,6 +107,7 @@ export type UseTreeViewSelectionSignature = TreeViewPluginSignature<{
99
107
  params: UseTreeViewSelectionParameters<any>;
100
108
  defaultizedParams: UseTreeViewSelectionDefaultizedParameters<any>;
101
109
  instance: UseTreeViewSelectionInstance;
110
+ publicAPI: UseTreeViewSelectionPublicAPI;
102
111
  contextValue: UseTreeViewSelectionContextValue;
103
112
  modelNames: 'selectedItems';
104
113
  dependencies: [
@@ -4,4 +4,4 @@ import { TreeViewCorePluginSignatures } from '../corePlugins';
4
4
  * Implements the same behavior as `useControlled` but for several models.
5
5
  * The controlled models are never stored in the state, and the state is only updated if the model is not controlled.
6
6
  */
7
- export declare const useTreeViewModels: <TSignatures extends readonly TreeViewAnyPluginSignature[]>(plugins: ConvertSignaturesIntoPlugins<readonly [...TreeViewCorePluginSignatures, ...TSignatures]>, props: MergeSignaturesProperty<TSignatures, 'defaultizedParams'>) => MergeSignaturesProperty<TSignatures, "models">;
7
+ export declare const useTreeViewModels: <TSignatures extends readonly TreeViewAnyPluginSignature[]>(plugins: ConvertSignaturesIntoPlugins<readonly [...TreeViewCorePluginSignatures, ...TSignatures]>, props: MergeSignaturesProperty<TSignatures, "defaultizedParams">) => MergeSignaturesProperty<TSignatures, "models">;
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import { CleanupTracking, UnregisterToken, UnsubscribeFn } from './CleanupTracking';
3
2
  export declare class TimerBasedCleanupTracking implements CleanupTracking {
4
3
  timeouts?: Map<number, NodeJS.Timeout> | undefined;
@@ -2,4 +2,4 @@ import { UseTreeViewInstanceEventsInstance } from '../corePlugins/useTreeViewIns
2
2
  import { TreeViewAnyPluginSignature, TreeViewUsedEvents } from '../models';
3
3
  export declare const publishTreeViewEvent: <Instance extends UseTreeViewInstanceEventsInstance & {
4
4
  $$signature: TreeViewAnyPluginSignature;
5
- }, E extends keyof Instance["$$signature"]["events"] | keyof import("../models").MergeSignaturesProperty<[import("../corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.types").UseTreeViewInstanceEventsSignature, import("../corePlugins/useTreeViewId").UseTreeViewIdSignature, ...Instance["$$signature"]["dependencies"]], "events">>(instance: Instance, eventName: E, params: TreeViewUsedEvents<Instance['$$signature']>[E]['params']) => void;
5
+ }, E extends keyof TreeViewUsedEvents<Instance["$$signature"]>>(instance: Instance, eventName: E, params: TreeViewUsedEvents<Instance["$$signature"]>[E]["params"]) => void;
@@ -1 +1 @@
1
- export declare const buildWarning: (message: string | string[], gravity?: 'warning' | 'error') => () => void;
1
+ export declare const buildWarning: (message: string | string[], gravity?: "warning" | "error") => () => void;
@@ -137,6 +137,8 @@ process.env.NODE_ENV !== "production" ? RichTreeView.propTypes = {
137
137
  current: PropTypes.shape({
138
138
  focusItem: PropTypes.func.isRequired,
139
139
  getItem: PropTypes.func.isRequired,
140
+ getItemDOMElement: PropTypes.func.isRequired,
141
+ selectItem: PropTypes.func.isRequired,
140
142
  setItemExpansion: PropTypes.func.isRequired
141
143
  })
142
144
  }),
@@ -177,6 +179,11 @@ process.env.NODE_ENV !== "production" ? RichTreeView.propTypes = {
177
179
  * Used when the item's expansion is controlled.
178
180
  */
179
181
  expandedItems: PropTypes.arrayOf(PropTypes.string),
182
+ /**
183
+ * The slot that triggers the item's expansion when clicked.
184
+ * @default 'content'
185
+ */
186
+ expansionTrigger: PropTypes.oneOf(['content', 'iconContainer']),
180
187
  /**
181
188
  * Unstable features, breaking changes might be introduced.
182
189
  * For each feature, if the flag is not explicitly set to `true`,
@@ -229,34 +236,34 @@ process.env.NODE_ENV !== "production" ? RichTreeView.propTypes = {
229
236
  multiSelect: PropTypes.bool,
230
237
  /**
231
238
  * Callback fired when tree items are expanded/collapsed.
232
- * @param {React.SyntheticEvent} event The event source of the callback.
239
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
233
240
  * @param {array} itemIds The ids of the expanded items.
234
241
  */
235
242
  onExpandedItemsChange: PropTypes.func,
236
243
  /**
237
244
  * Callback fired when a tree item is expanded or collapsed.
238
- * @param {React.SyntheticEvent} event The event source of the callback.
245
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
239
246
  * @param {array} itemId The itemId of the modified item.
240
247
  * @param {array} isExpanded `true` if the item has just been expanded, `false` if it has just been collapsed.
241
248
  */
242
249
  onItemExpansionToggle: PropTypes.func,
243
250
  /**
244
251
  * Callback fired when tree items are focused.
245
- * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event.
252
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change. **Warning**: This is a generic event not a focus event.
246
253
  * @param {string} itemId The id of the focused item.
247
254
  * @param {string} value of the focused item.
248
255
  */
249
256
  onItemFocus: PropTypes.func,
250
257
  /**
251
258
  * Callback fired when a tree item is selected or deselected.
252
- * @param {React.SyntheticEvent} event The event source of the callback.
259
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
253
260
  * @param {array} itemId The itemId of the modified item.
254
261
  * @param {array} isSelected `true` if the item has just been selected, `false` if it has just been deselected.
255
262
  */
256
263
  onItemSelectionToggle: PropTypes.func,
257
264
  /**
258
265
  * Callback fired when tree items are selected/deselected.
259
- * @param {React.SyntheticEvent} event The event source of the callback
266
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
260
267
  * @param {string[] | string} itemIds The ids of the selected items.
261
268
  * When `multiSelect` is `true`, this is an array of strings; when false (default) a string.
262
269
  */
@@ -95,6 +95,8 @@ process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
95
95
  current: PropTypes.shape({
96
96
  focusItem: PropTypes.func.isRequired,
97
97
  getItem: PropTypes.func.isRequired,
98
+ getItemDOMElement: PropTypes.func.isRequired,
99
+ selectItem: PropTypes.func.isRequired,
98
100
  setItemExpansion: PropTypes.func.isRequired
99
101
  })
100
102
  }),
@@ -139,6 +141,11 @@ process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
139
141
  * Used when the item's expansion is controlled.
140
142
  */
141
143
  expandedItems: PropTypes.arrayOf(PropTypes.string),
144
+ /**
145
+ * The slot that triggers the item's expansion when clicked.
146
+ * @default 'content'
147
+ */
148
+ expansionTrigger: PropTypes.oneOf(['content', 'iconContainer']),
142
149
  /**
143
150
  * Unstable features, breaking changes might be introduced.
144
151
  * For each feature, if the flag is not explicitly set to `true`,
@@ -165,34 +172,34 @@ process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
165
172
  multiSelect: PropTypes.bool,
166
173
  /**
167
174
  * Callback fired when tree items are expanded/collapsed.
168
- * @param {React.SyntheticEvent} event The event source of the callback.
175
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
169
176
  * @param {array} itemIds The ids of the expanded items.
170
177
  */
171
178
  onExpandedItemsChange: PropTypes.func,
172
179
  /**
173
180
  * Callback fired when a tree item is expanded or collapsed.
174
- * @param {React.SyntheticEvent} event The event source of the callback.
181
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
175
182
  * @param {array} itemId The itemId of the modified item.
176
183
  * @param {array} isExpanded `true` if the item has just been expanded, `false` if it has just been collapsed.
177
184
  */
178
185
  onItemExpansionToggle: PropTypes.func,
179
186
  /**
180
187
  * Callback fired when tree items are focused.
181
- * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event.
188
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change. **Warning**: This is a generic event not a focus event.
182
189
  * @param {string} itemId The id of the focused item.
183
190
  * @param {string} value of the focused item.
184
191
  */
185
192
  onItemFocus: PropTypes.func,
186
193
  /**
187
194
  * Callback fired when a tree item is selected or deselected.
188
- * @param {React.SyntheticEvent} event The event source of the callback.
195
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
189
196
  * @param {array} itemId The itemId of the modified item.
190
197
  * @param {array} isSelected `true` if the item has just been selected, `false` if it has just been deselected.
191
198
  */
192
199
  onItemSelectionToggle: PropTypes.func,
193
200
  /**
194
201
  * Callback fired when tree items are selected/deselected.
195
- * @param {React.SyntheticEvent} event The event source of the callback
202
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
196
203
  * @param {string[] | string} itemIds The ids of the selected items.
197
204
  * When `multiSelect` is `true`, this is an array of strings; when false (default) a string.
198
205
  */
@@ -22,6 +22,7 @@ import { useTreeViewContext } from '../internals/TreeViewProvider/useTreeViewCon
22
22
  import { TreeViewCollapseIcon, TreeViewExpandIcon } from '../icons';
23
23
  import { TreeItem2Provider } from '../TreeItem2Provider';
24
24
  import { TreeViewItemDepthContext } from '../internals/TreeViewItemDepthContext';
25
+ import { useTreeItemState } from './useTreeItemState';
25
26
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
26
27
  const useThemeProps = createUseThemeProps('MuiTreeItem');
27
28
  const useUtilityClasses = ownerState => {
@@ -168,6 +169,9 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
168
169
  selection: {
169
170
  multiSelect
170
171
  },
172
+ expansion: {
173
+ expansionTrigger
174
+ },
171
175
  disabledItemsFocusable,
172
176
  indentationAtItemLevel,
173
177
  instance
@@ -193,6 +197,13 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
193
197
  onKeyDown
194
198
  } = props,
195
199
  other = _objectWithoutPropertiesLoose(props, _excluded);
200
+ const {
201
+ expanded,
202
+ focused,
203
+ selected,
204
+ disabled,
205
+ handleExpansion
206
+ } = useTreeItemState(itemId);
196
207
  const {
197
208
  contentRef,
198
209
  rootRef
@@ -213,10 +224,6 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
213
224
  return Boolean(reactChildren);
214
225
  };
215
226
  const expandable = isExpandable(children);
216
- const expanded = instance.isItemExpanded(itemId);
217
- const focused = instance.isItemFocused(itemId);
218
- const selected = instance.isItemSelected(itemId);
219
- const disabled = instance.isItemDisabled(itemId);
220
227
  const ownerState = _extends({}, props, {
221
228
  expanded,
222
229
  focused,
@@ -240,6 +247,11 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
240
247
  } : {}),
241
248
  className: classes.groupTransition
242
249
  });
250
+ const handleIconContainerClick = event => {
251
+ if (expansionTrigger === 'iconContainer') {
252
+ handleExpansion(event);
253
+ }
254
+ };
243
255
  const ExpansionIcon = expanded ? slots.collapseIcon : slots.expandIcon;
244
256
  const _useSlotProps = useSlotProps({
245
257
  elementType: ExpansionIcon,
@@ -249,6 +261,9 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
249
261
  return _extends({}, resolveComponentProps(contextIcons.slotProps.collapseIcon, tempOwnerState), resolveComponentProps(inSlotProps?.collapseIcon, tempOwnerState));
250
262
  }
251
263
  return _extends({}, resolveComponentProps(contextIcons.slotProps.expandIcon, tempOwnerState), resolveComponentProps(inSlotProps?.expandIcon, tempOwnerState));
264
+ },
265
+ additionalProps: {
266
+ onClick: handleIconContainerClick
252
267
  }
253
268
  }),
254
269
  expansionIconProps = _objectWithoutPropertiesLoose(_useSlotProps, _excluded2);
@@ -33,7 +33,8 @@ const TreeItemContent = /*#__PURE__*/React.forwardRef(function TreeItemContent(p
33
33
  handleExpansion,
34
34
  handleSelection,
35
35
  handleCheckboxSelection,
36
- preventSelection
36
+ preventSelection,
37
+ expansionTrigger
37
38
  } = useTreeItemState(itemId);
38
39
  const icon = iconProp || expansionIcon || displayIcon;
39
40
  const checkboxRef = React.useRef(null);
@@ -47,7 +48,9 @@ const TreeItemContent = /*#__PURE__*/React.forwardRef(function TreeItemContent(p
47
48
  if (checkboxRef.current?.contains(event.target)) {
48
49
  return;
49
50
  }
50
- handleExpansion(event);
51
+ if (expansionTrigger === 'content') {
52
+ handleExpansion(event);
53
+ }
51
54
  if (!checkboxSelection) {
52
55
  handleSelection(event);
53
56
  }
@@ -6,6 +6,9 @@ export function useTreeItemState(itemId) {
6
6
  multiSelect,
7
7
  checkboxSelection,
8
8
  disableSelection
9
+ },
10
+ expansion: {
11
+ expansionTrigger
9
12
  }
10
13
  } = useTreeViewContext();
11
14
  const expandable = instance.isItemExpandable(itemId);
@@ -36,10 +39,18 @@ export function useTreeItemState(itemId) {
36
39
  if (event.shiftKey) {
37
40
  instance.expandSelectionRange(event, itemId);
38
41
  } else {
39
- instance.selectItem(event, itemId, true);
42
+ instance.selectItem({
43
+ event,
44
+ itemId,
45
+ keepExistingSelection: true
46
+ });
40
47
  }
41
48
  } else {
42
- instance.selectItem(event, itemId, false);
49
+ instance.selectItem({
50
+ event,
51
+ itemId,
52
+ shouldBeSelected: true
53
+ });
43
54
  }
44
55
  }
45
56
  };
@@ -51,7 +62,12 @@ export function useTreeItemState(itemId) {
51
62
  if (multiSelect && hasShift) {
52
63
  instance.expandSelectionRange(event, itemId);
53
64
  } else {
54
- instance.selectItem(event, itemId, multiSelect, event.target.checked);
65
+ instance.selectItem({
66
+ event,
67
+ itemId,
68
+ keepExistingSelection: multiSelect,
69
+ shouldBeSelected: event.target.checked
70
+ });
55
71
  }
56
72
  };
57
73
  const preventSelection = event => {
@@ -70,6 +86,7 @@ export function useTreeItemState(itemId) {
70
86
  handleExpansion,
71
87
  handleSelection,
72
88
  handleCheckboxSelection,
73
- preventSelection
89
+ preventSelection,
90
+ expansionTrigger
74
91
  };
75
92
  }