@mui/x-tree-view 7.4.0 → 7.5.1

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 (65) hide show
  1. package/CHANGELOG.md +132 -5395
  2. package/RichTreeView/RichTreeView.js +7 -2
  3. package/SimpleTreeView/SimpleTreeView.js +7 -2
  4. package/TreeItem/TreeItem.js +8 -3
  5. package/TreeItem/TreeItemContent.d.ts +2 -0
  6. package/TreeItem/TreeItemContent.js +19 -2
  7. package/TreeItem/treeItemClasses.d.ts +2 -0
  8. package/TreeItem/treeItemClasses.js +1 -1
  9. package/TreeItem/useTreeItemState.d.ts +4 -1
  10. package/TreeItem/useTreeItemState.js +18 -2
  11. package/TreeItem2/TreeItem2.d.ts +4 -0
  12. package/TreeItem2/TreeItem2.js +34 -4
  13. package/TreeItem2/TreeItem2.types.d.ts +6 -0
  14. package/TreeItem2/index.d.ts +1 -1
  15. package/TreeItem2/index.js +1 -1
  16. package/TreeItem2Icon/TreeItem2Icon.js +1 -1
  17. package/TreeItem2Provider/TreeItem2Provider.js +1 -1
  18. package/TreeView/TreeView.js +7 -2
  19. package/hooks/useTreeItem2Utils/useTreeItem2Utils.d.ts +1 -0
  20. package/hooks/useTreeItem2Utils/useTreeItem2Utils.js +18 -3
  21. package/index.js +1 -1
  22. package/internals/models/plugin.d.ts +0 -6
  23. package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +1 -0
  24. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +3 -3
  25. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +18 -6
  26. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +16 -4
  27. package/internals/useTreeView/useTreeViewModels.d.ts +1 -1
  28. package/internals/useTreeView/useTreeViewModels.js +1 -1
  29. package/modern/RichTreeView/RichTreeView.js +7 -2
  30. package/modern/SimpleTreeView/SimpleTreeView.js +7 -2
  31. package/modern/TreeItem/TreeItem.js +8 -3
  32. package/modern/TreeItem/TreeItemContent.js +19 -2
  33. package/modern/TreeItem/treeItemClasses.js +1 -1
  34. package/modern/TreeItem/useTreeItemState.js +18 -2
  35. package/modern/TreeItem2/TreeItem2.js +34 -4
  36. package/modern/TreeItem2/index.js +1 -1
  37. package/modern/TreeItem2Icon/TreeItem2Icon.js +1 -1
  38. package/modern/TreeItem2Provider/TreeItem2Provider.js +1 -1
  39. package/modern/TreeView/TreeView.js +7 -2
  40. package/modern/hooks/useTreeItem2Utils/useTreeItem2Utils.js +18 -3
  41. package/modern/index.js +1 -1
  42. package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +3 -3
  43. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +18 -6
  44. package/modern/internals/useTreeView/useTreeViewModels.js +1 -1
  45. package/modern/useTreeItem2/useTreeItem2.js +32 -3
  46. package/node/RichTreeView/RichTreeView.js +7 -2
  47. package/node/SimpleTreeView/SimpleTreeView.js +7 -2
  48. package/node/TreeItem/TreeItem.js +8 -3
  49. package/node/TreeItem/TreeItemContent.js +19 -2
  50. package/node/TreeItem/treeItemClasses.js +1 -1
  51. package/node/TreeItem/useTreeItemState.js +18 -2
  52. package/node/TreeItem2/TreeItem2.js +35 -5
  53. package/node/TreeItem2/index.js +6 -0
  54. package/node/TreeItem2Icon/TreeItem2Icon.js +1 -1
  55. package/node/TreeItem2Provider/TreeItem2Provider.js +1 -1
  56. package/node/TreeView/TreeView.js +7 -2
  57. package/node/hooks/useTreeItem2Utils/useTreeItem2Utils.js +18 -3
  58. package/node/index.js +1 -1
  59. package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +3 -3
  60. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +18 -6
  61. package/node/internals/useTreeView/useTreeViewModels.js +1 -1
  62. package/node/useTreeItem2/useTreeItem2.js +34 -3
  63. package/package.json +2 -2
  64. package/useTreeItem2/useTreeItem2.js +32 -3
  65. package/useTreeItem2/useTreeItem2.types.d.ts +15 -0
@@ -131,7 +131,7 @@ const RichTreeView = /*#__PURE__*/React.forwardRef(function RichTreeView(inProps
131
131
  process.env.NODE_ENV !== "production" ? RichTreeView.propTypes = {
132
132
  // ----------------------------- Warning --------------------------------
133
133
  // | These PropTypes are generated from the TypeScript type definitions |
134
- // | To update them edit the TypeScript types and run "yarn proptypes" |
134
+ // | To update them edit the TypeScript types and run "pnpm proptypes" |
135
135
  // ----------------------------------------------------------------------
136
136
  /**
137
137
  * The ref object that allows Tree View manipulation. Can be instantiated with `useTreeViewApiRef()`.
@@ -143,6 +143,11 @@ process.env.NODE_ENV !== "production" ? RichTreeView.propTypes = {
143
143
  setItemExpansion: PropTypes.func.isRequired
144
144
  })
145
145
  }),
146
+ /**
147
+ * If `true`, the tree view renders a checkbox at the left of its label that allows selecting it.
148
+ * @default false
149
+ */
150
+ checkboxSelection: PropTypes.bool,
146
151
  /**
147
152
  * Override or extend the styles applied to the component.
148
153
  */
@@ -207,7 +212,7 @@ process.env.NODE_ENV !== "production" ? RichTreeView.propTypes = {
207
212
  isItemDisabled: PropTypes.func,
208
213
  items: PropTypes.array.isRequired,
209
214
  /**
210
- * If true `ctrl` and `shift` will trigger multiselect.
215
+ * If `true`, `ctrl` and `shift` will trigger multiselect.
211
216
  * @default false
212
217
  */
213
218
  multiSelect: PropTypes.bool,
@@ -89,7 +89,7 @@ const SimpleTreeView = /*#__PURE__*/React.forwardRef(function SimpleTreeView(inP
89
89
  process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
90
90
  // ----------------------------- Warning --------------------------------
91
91
  // | These PropTypes are generated from the TypeScript type definitions |
92
- // | To update them edit the TypeScript types and run "yarn proptypes" |
92
+ // | To update them edit the TypeScript types and run "pnpm proptypes" |
93
93
  // ----------------------------------------------------------------------
94
94
  /**
95
95
  * The ref object that allows Tree View manipulation. Can be instantiated with `useTreeViewApiRef()`.
@@ -101,6 +101,11 @@ process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
101
101
  setItemExpansion: PropTypes.func.isRequired
102
102
  })
103
103
  }),
104
+ /**
105
+ * If `true`, the tree view renders a checkbox at the left of its label that allows selecting it.
106
+ * @default false
107
+ */
108
+ checkboxSelection: PropTypes.bool,
104
109
  /**
105
110
  * The content of the component.
106
111
  */
@@ -143,7 +148,7 @@ process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
143
148
  */
144
149
  id: PropTypes.string,
145
150
  /**
146
- * If true `ctrl` and `shift` will trigger multiselect.
151
+ * If `true`, `ctrl` and `shift` will trigger multiselect.
147
152
  * @default false
148
153
  */
149
154
  multiSelect: PropTypes.bool,
@@ -32,6 +32,7 @@ const useUtilityClasses = ownerState => {
32
32
  focused: ['focused'],
33
33
  disabled: ['disabled'],
34
34
  iconContainer: ['iconContainer'],
35
+ checkbox: ['checkbox'],
35
36
  label: ['label'],
36
37
  groupTransition: ['groupTransition']
37
38
  };
@@ -113,7 +114,10 @@ const StyledTreeItemContent = styled(TreeItemContent, {
113
114
  // fixes overflow - see https://github.com/mui/material-ui/issues/27372
114
115
  minWidth: 0,
115
116
  position: 'relative'
116
- }, theme.typography.body1)
117
+ }, theme.typography.body1),
118
+ [`& .${treeItemClasses.checkbox}`]: {
119
+ padding: 0
120
+ }
117
121
  }));
118
122
  const TreeItemGroup = styled(Collapse, {
119
123
  name: 'MuiTreeItem',
@@ -296,7 +300,8 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
296
300
  focused: classes.focused,
297
301
  disabled: classes.disabled,
298
302
  iconContainer: classes.iconContainer,
299
- label: classes.label
303
+ label: classes.label,
304
+ checkbox: classes.checkbox
300
305
  },
301
306
  label: label,
302
307
  itemId: itemId,
@@ -319,7 +324,7 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
319
324
  process.env.NODE_ENV !== "production" ? TreeItem.propTypes = {
320
325
  // ----------------------------- Warning --------------------------------
321
326
  // | These PropTypes are generated from the TypeScript type definitions |
322
- // | To update them edit the TypeScript types and run "yarn proptypes" |
327
+ // | To update them edit the TypeScript types and run "pnpm proptypes" |
323
328
  // ----------------------------------------------------------------------
324
329
  /**
325
330
  * The content of the component.
@@ -19,6 +19,8 @@ export interface TreeItemContentProps extends React.HTMLAttributes<HTMLElement>
19
19
  iconContainer: string;
20
20
  /** Styles applied to the label element. */
21
21
  label: string;
22
+ /** Styles applied to the checkbox element. */
23
+ checkbox: string;
22
24
  };
23
25
  /**
24
26
  * The tree item label.
@@ -4,6 +4,7 @@ const _excluded = ["classes", "className", "displayIcon", "expansionIcon", "icon
4
4
  import * as React from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
  import clsx from 'clsx';
7
+ import Checkbox from '@mui/material/Checkbox';
7
8
  import { useTreeItemState } from './useTreeItemState';
8
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
10
  /**
@@ -27,11 +28,15 @@ const TreeItemContent = /*#__PURE__*/React.forwardRef(function TreeItemContent(p
27
28
  expanded,
28
29
  selected,
29
30
  focused,
31
+ disableSelection,
32
+ checkboxSelection,
30
33
  handleExpansion,
31
34
  handleSelection,
35
+ handleCheckboxSelection,
32
36
  preventSelection
33
37
  } = useTreeItemState(itemId);
34
38
  const icon = iconProp || expansionIcon || displayIcon;
39
+ const checkboxRef = React.useRef(null);
35
40
  const handleMouseDown = event => {
36
41
  preventSelection(event);
37
42
  if (onMouseDown) {
@@ -39,8 +44,13 @@ const TreeItemContent = /*#__PURE__*/React.forwardRef(function TreeItemContent(p
39
44
  }
40
45
  };
41
46
  const handleClick = event => {
47
+ if (checkboxRef.current?.contains(event.target)) {
48
+ return;
49
+ }
42
50
  handleExpansion(event);
43
- handleSelection(event);
51
+ if (!checkboxSelection) {
52
+ handleSelection(event);
53
+ }
44
54
  if (onClick) {
45
55
  onClick(event);
46
56
  }
@@ -56,6 +66,13 @@ const TreeItemContent = /*#__PURE__*/React.forwardRef(function TreeItemContent(p
56
66
  children: [/*#__PURE__*/_jsx("div", {
57
67
  className: classes.iconContainer,
58
68
  children: icon
69
+ }), checkboxSelection && /*#__PURE__*/_jsx(Checkbox, {
70
+ className: classes.checkbox,
71
+ checked: selected,
72
+ onChange: handleCheckboxSelection,
73
+ disabled: disabled || disableSelection,
74
+ ref: checkboxRef,
75
+ tabIndex: -1
59
76
  }), /*#__PURE__*/_jsx("div", {
60
77
  className: classes.label,
61
78
  children: label
@@ -66,7 +83,7 @@ const TreeItemContent = /*#__PURE__*/React.forwardRef(function TreeItemContent(p
66
83
  process.env.NODE_ENV !== "production" ? TreeItemContent.propTypes = {
67
84
  // ----------------------------- Warning --------------------------------
68
85
  // | These PropTypes are generated from the TypeScript type definitions |
69
- // | To update them edit the TypeScript types and run "yarn proptypes" |
86
+ // | To update them edit the TypeScript types and run "pnpm proptypes" |
70
87
  // ----------------------------------------------------------------------
71
88
  /**
72
89
  * Override or extend the styles applied to the component.
@@ -17,6 +17,8 @@ export interface TreeItemClasses {
17
17
  iconContainer: string;
18
18
  /** Styles applied to the label element. */
19
19
  label: string;
20
+ /** Styles applied to the checkbox element. */
21
+ checkbox: string;
20
22
  }
21
23
  export type TreeItemClassKey = keyof TreeItemClasses;
22
24
  export declare function getTreeItemUtilityClass(slot: string): string;
@@ -3,4 +3,4 @@ import generateUtilityClasses from '@mui/utils/generateUtilityClasses';
3
3
  export function getTreeItemUtilityClass(slot) {
4
4
  return generateUtilityClass('MuiTreeItem', slot);
5
5
  }
6
- export const treeItemClasses = generateUtilityClasses('MuiTreeItem', ['root', 'groupTransition', 'content', 'expanded', 'selected', 'focused', 'disabled', 'iconContainer', 'label']);
6
+ export const treeItemClasses = generateUtilityClasses('MuiTreeItem', ['root', 'groupTransition', 'content', 'expanded', 'selected', 'focused', 'disabled', 'iconContainer', 'label', 'checkbox']);
@@ -4,7 +4,10 @@ export declare function useTreeItemState(itemId: string): {
4
4
  expanded: boolean;
5
5
  selected: boolean;
6
6
  focused: boolean;
7
+ disableSelection: boolean;
8
+ checkboxSelection: boolean;
7
9
  handleExpansion: (event: React.MouseEvent<HTMLDivElement>) => void;
8
- handleSelection: (event: React.MouseEvent<HTMLDivElement>) => void;
10
+ handleSelection: (event: React.MouseEvent) => void;
11
+ handleCheckboxSelection: (event: React.ChangeEvent<HTMLInputElement>) => void;
9
12
  preventSelection: (event: React.MouseEvent<HTMLDivElement>) => void;
10
13
  };
@@ -3,7 +3,9 @@ export function useTreeItemState(itemId) {
3
3
  const {
4
4
  instance,
5
5
  selection: {
6
- multiSelect
6
+ multiSelect,
7
+ checkboxSelection,
8
+ disableSelection
7
9
  }
8
10
  } = useTreeViewContext();
9
11
  const expandable = instance.isItemExpandable(itemId);
@@ -37,10 +39,21 @@ export function useTreeItemState(itemId) {
37
39
  instance.selectItem(event, itemId, true);
38
40
  }
39
41
  } else {
40
- instance.selectItem(event, itemId);
42
+ instance.selectItem(event, itemId, false);
41
43
  }
42
44
  }
43
45
  };
46
+ const handleCheckboxSelection = event => {
47
+ if (disableSelection || disabled) {
48
+ return;
49
+ }
50
+ const hasShift = event.nativeEvent.shiftKey;
51
+ if (multiSelect && hasShift) {
52
+ instance.expandSelectionRange(event, itemId);
53
+ } else {
54
+ instance.selectItem(event, itemId, multiSelect, event.target.checked);
55
+ }
56
+ };
44
57
  const preventSelection = event => {
45
58
  if (event.shiftKey || event.ctrlKey || event.metaKey || disabled) {
46
59
  // Prevent text selection
@@ -52,8 +65,11 @@ export function useTreeItemState(itemId) {
52
65
  expanded,
53
66
  selected,
54
67
  focused,
68
+ disableSelection,
69
+ checkboxSelection,
55
70
  handleExpansion,
56
71
  handleSelection,
72
+ handleCheckboxSelection,
57
73
  preventSelection
58
74
  };
59
75
  }
@@ -1,10 +1,14 @@
1
1
  import * as React from 'react';
2
+ import { CheckboxProps } from '@mui/material/Checkbox';
2
3
  import { TreeItem2Props } from './TreeItem2.types';
3
4
  export declare const TreeItem2Root: import("@emotion/styled").StyledComponent<import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme>, Pick<React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, keyof React.ClassAttributes<HTMLLIElement> | keyof React.LiHTMLAttributes<HTMLLIElement>>, {}>;
4
5
  export declare const TreeItem2Content: import("@emotion/styled").StyledComponent<import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme>, React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
5
6
  export declare const TreeItem2Label: import("@emotion/styled").StyledComponent<import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme>, Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.ClassAttributes<HTMLDivElement> | keyof React.HTMLAttributes<HTMLDivElement>>, {}>;
6
7
  export declare const TreeItem2IconContainer: import("@emotion/styled").StyledComponent<import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme>, Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.ClassAttributes<HTMLDivElement> | keyof React.HTMLAttributes<HTMLDivElement>>, {}>;
7
8
  export declare const TreeItem2GroupTransition: import("@emotion/styled").StyledComponent<Pick<import("@mui/material/Collapse").CollapseProps, keyof import("@mui/material/Collapse").CollapseProps> & import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme>, {}, {}>;
9
+ export declare const TreeItem2Checkbox: import("@emotion/styled").StyledComponent<Pick<Omit<CheckboxProps & {
10
+ visible: boolean;
11
+ }, "ref"> & React.RefAttributes<HTMLButtonElement>, "hidden" | "visible" | "color" | "content" | "size" | "style" | "icon" | "translate" | "disabled" | "form" | "slot" | "title" | "suppressHydrationWarning" | "className" | "id" | "lang" | "name" | "role" | "tabIndex" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onResize" | "onResizeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "accessKey" | "autoFocus" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "nonce" | "spellCheck" | "radioGroup" | "about" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "resource" | "rev" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "value" | "readOnly" | "required" | "action" | "checked" | "component" | "sx" | "classes" | "onFocusVisible" | "inputRef" | "centerRipple" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "TouchRippleProps" | "touchRippleRef" | "disableFocusRipple" | "edge" | "checkedIcon" | "inputProps" | "indeterminate" | "indeterminateIcon" | keyof React.RefAttributes<HTMLButtonElement>> & import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme>, {}, {}>;
8
12
  type TreeItem2Component = ((props: TreeItem2Props & React.RefAttributes<HTMLLIElement>) => React.JSX.Element) & {
9
13
  propTypes?: any;
10
14
  };
@@ -1,12 +1,14 @@
1
1
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
2
2
  import _extends from "@babel/runtime/helpers/esm/extends";
3
- const _excluded = ["id", "itemId", "label", "disabled", "children", "slots", "slotProps"];
3
+ const _excluded = ["visible"],
4
+ _excluded2 = ["id", "itemId", "label", "disabled", "children", "slots", "slotProps"];
4
5
  import * as React from 'react';
5
6
  import PropTypes from 'prop-types';
6
7
  import clsx from 'clsx';
7
8
  import unsupportedProp from '@mui/utils/unsupportedProp';
8
9
  import { alpha, styled, useThemeProps } from '@mui/material/styles';
9
10
  import Collapse from '@mui/material/Collapse';
11
+ import MuiCheckbox from '@mui/material/Checkbox';
10
12
  import { useSlotProps } from '@mui/base/utils';
11
13
  import { shouldForwardProp } from '@mui/system';
12
14
  import composeClasses from '@mui/utils/composeClasses';
@@ -129,6 +131,24 @@ export const TreeItem2GroupTransition = styled(Collapse, {
129
131
  padding: 0,
130
132
  paddingLeft: 12
131
133
  });
134
+ export const TreeItem2Checkbox = styled( /*#__PURE__*/React.forwardRef((props, ref) => {
135
+ const {
136
+ visible
137
+ } = props,
138
+ other = _objectWithoutPropertiesLoose(props, _excluded);
139
+ if (!visible) {
140
+ return null;
141
+ }
142
+ return /*#__PURE__*/_jsx(MuiCheckbox, _extends({}, other, {
143
+ ref: ref
144
+ }));
145
+ }), {
146
+ name: 'MuiTreeItem2',
147
+ slot: 'Checkbox',
148
+ overridesResolver: (props, styles) => styles.checkbox
149
+ })({
150
+ padding: 0
151
+ });
132
152
  const useUtilityClasses = ownerState => {
133
153
  const {
134
154
  classes
@@ -141,6 +161,7 @@ const useUtilityClasses = ownerState => {
141
161
  focused: ['focused'],
142
162
  disabled: ['disabled'],
143
163
  iconContainer: ['iconContainer'],
164
+ checkbox: ['checkbox'],
144
165
  label: ['label'],
145
166
  groupTransition: ['groupTransition']
146
167
  };
@@ -170,11 +191,12 @@ export const TreeItem2 = /*#__PURE__*/React.forwardRef(function TreeItem2(inProp
170
191
  slots = {},
171
192
  slotProps = {}
172
193
  } = props,
173
- other = _objectWithoutPropertiesLoose(props, _excluded);
194
+ other = _objectWithoutPropertiesLoose(props, _excluded2);
174
195
  const {
175
196
  getRootProps,
176
197
  getContentProps,
177
198
  getIconContainerProps,
199
+ getCheckboxProps,
178
200
  getLabelProps,
179
201
  getGroupTransitionProps,
180
202
  status
@@ -223,6 +245,14 @@ export const TreeItem2 = /*#__PURE__*/React.forwardRef(function TreeItem2(inProp
223
245
  ownerState: {},
224
246
  className: classes.label
225
247
  });
248
+ const Checkbox = slots.checkbox ?? TreeItem2Checkbox;
249
+ const checkboxProps = useSlotProps({
250
+ elementType: Checkbox,
251
+ getSlotProps: getCheckboxProps,
252
+ externalSlotProps: slotProps.checkbox,
253
+ ownerState: {},
254
+ className: classes.checkbox
255
+ });
226
256
  const GroupTransition = slots.groupTransition ?? undefined;
227
257
  const groupTransitionProps = useSlotProps({
228
258
  elementType: GroupTransition,
@@ -241,7 +271,7 @@ export const TreeItem2 = /*#__PURE__*/React.forwardRef(function TreeItem2(inProp
241
271
  slots: slots,
242
272
  slotProps: slotProps
243
273
  })
244
- })), /*#__PURE__*/_jsx(Label, _extends({}, labelProps))]
274
+ })), /*#__PURE__*/_jsx(Checkbox, _extends({}, checkboxProps)), /*#__PURE__*/_jsx(Label, _extends({}, labelProps))]
245
275
  })), children && /*#__PURE__*/_jsx(TreeItem2GroupTransition, _extends({
246
276
  as: GroupTransition
247
277
  }, groupTransitionProps))]
@@ -251,7 +281,7 @@ export const TreeItem2 = /*#__PURE__*/React.forwardRef(function TreeItem2(inProp
251
281
  process.env.NODE_ENV !== "production" ? TreeItem2.propTypes = {
252
282
  // ----------------------------- Warning --------------------------------
253
283
  // | These PropTypes are generated from the TypeScript type definitions |
254
- // | To update them edit the TypeScript types and run "yarn proptypes" |
284
+ // | To update them edit the TypeScript types and run "pnpm proptypes" |
255
285
  // ----------------------------------------------------------------------
256
286
  /**
257
287
  * The content of the component.
@@ -25,6 +25,11 @@ export interface TreeItem2Slots extends TreeItem2IconSlots {
25
25
  * @default TreeItem2IconContainer
26
26
  */
27
27
  iconContainer?: React.ElementType;
28
+ /**
29
+ * The component that renders the item checkbox for selection.
30
+ * @default TreeItem2Checkbox
31
+ */
32
+ checkbox?: React.ElementType;
28
33
  /**
29
34
  * The component that renders the item label.
30
35
  * @default TreeItem2Label
@@ -36,6 +41,7 @@ export interface TreeItem2SlotProps extends TreeItem2IconSlotProps {
36
41
  content?: SlotComponentProps<'div', {}, {}>;
37
42
  groupTransition?: SlotComponentProps<'div', {}, {}>;
38
43
  iconContainer?: SlotComponentProps<'div', {}, {}>;
44
+ checkbox?: SlotComponentProps<'button', {}, {}>;
39
45
  label?: SlotComponentProps<'div', {}, {}>;
40
46
  }
41
47
  export interface TreeItem2Props extends Omit<UseTreeItem2Parameters, 'rootRef'>, Omit<React.HTMLAttributes<HTMLLIElement>, 'onFocus'> {
@@ -1,2 +1,2 @@
1
- export { TreeItem2, TreeItem2Root, TreeItem2Content, TreeItem2IconContainer, TreeItem2GroupTransition, TreeItem2Label, } from './TreeItem2';
1
+ export { TreeItem2, TreeItem2Root, TreeItem2Content, TreeItem2IconContainer, TreeItem2GroupTransition, TreeItem2Checkbox, TreeItem2Label, } from './TreeItem2';
2
2
  export type { TreeItem2Props, TreeItem2Slots, TreeItem2SlotProps } from './TreeItem2.types';
@@ -1 +1 @@
1
- export { TreeItem2, TreeItem2Root, TreeItem2Content, TreeItem2IconContainer, TreeItem2GroupTransition, TreeItem2Label } from './TreeItem2';
1
+ export { TreeItem2, TreeItem2Root, TreeItem2Content, TreeItem2IconContainer, TreeItem2GroupTransition, TreeItem2Checkbox, TreeItem2Label } from './TreeItem2';
@@ -44,7 +44,7 @@ function TreeItem2Icon(props) {
44
44
  process.env.NODE_ENV !== "production" ? TreeItem2Icon.propTypes = {
45
45
  // ----------------------------- Warning --------------------------------
46
46
  // | These PropTypes are generated from the TypeScript type definitions |
47
- // | To update them edit the TypeScript types and run "yarn proptypes" |
47
+ // | To update them edit the TypeScript types and run "pnpm proptypes" |
48
48
  // ----------------------------------------------------------------------
49
49
  /**
50
50
  * The props used for each component slot.
@@ -16,7 +16,7 @@ function TreeItem2Provider(props) {
16
16
  TreeItem2Provider.propTypes = {
17
17
  // ----------------------------- Warning --------------------------------
18
18
  // | These PropTypes are generated from the TypeScript type definitions |
19
- // | To update them edit the TypeScript types and run "yarn proptypes" |
19
+ // | To update them edit the TypeScript types and run "pnpm proptypes" |
20
20
  // ----------------------------------------------------------------------
21
21
  children: PropTypes.node,
22
22
  itemId: PropTypes.string.isRequired
@@ -62,7 +62,7 @@ const TreeView = /*#__PURE__*/React.forwardRef(function TreeView(inProps, ref) {
62
62
  process.env.NODE_ENV !== "production" ? TreeView.propTypes = {
63
63
  // ----------------------------- Warning --------------------------------
64
64
  // | These PropTypes are generated from the TypeScript type definitions |
65
- // | To update them edit the TypeScript types and run "yarn proptypes" |
65
+ // | To update them edit the TypeScript types and run "pnpm proptypes" |
66
66
  // ----------------------------------------------------------------------
67
67
  /**
68
68
  * The ref object that allows Tree View manipulation. Can be instantiated with `useTreeViewApiRef()`.
@@ -74,6 +74,11 @@ process.env.NODE_ENV !== "production" ? TreeView.propTypes = {
74
74
  setItemExpansion: PropTypes.func.isRequired
75
75
  })
76
76
  }),
77
+ /**
78
+ * If `true`, the tree view renders a checkbox at the left of its label that allows selecting it.
79
+ * @default false
80
+ */
81
+ checkboxSelection: PropTypes.bool,
77
82
  /**
78
83
  * The content of the component.
79
84
  */
@@ -116,7 +121,7 @@ process.env.NODE_ENV !== "production" ? TreeView.propTypes = {
116
121
  */
117
122
  id: PropTypes.string,
118
123
  /**
119
- * If true `ctrl` and `shift` will trigger multiselect.
124
+ * If `true`, `ctrl` and `shift` will trigger multiselect.
120
125
  * @default false
121
126
  */
122
127
  multiSelect: PropTypes.bool,
@@ -3,6 +3,7 @@ import type { UseTreeItem2Status } from '../../useTreeItem2';
3
3
  interface UseTreeItem2Interactions {
4
4
  handleExpansion: (event: React.MouseEvent) => void;
5
5
  handleSelection: (event: React.MouseEvent) => void;
6
+ handleCheckboxSelection: (event: React.ChangeEvent<HTMLInputElement>) => void;
6
7
  }
7
8
  interface UseTreeItem2UtilsReturnValue {
8
9
  interactions: UseTreeItem2Interactions;
@@ -1,4 +1,10 @@
1
1
  import { useTreeViewContext } from '../../internals/TreeViewProvider/useTreeViewContext';
2
+ const isItemExpandable = reactChildren => {
3
+ if (Array.isArray(reactChildren)) {
4
+ return reactChildren.length > 0 && reactChildren.some(isItemExpandable);
5
+ }
6
+ return Boolean(reactChildren);
7
+ };
2
8
  export const useTreeItem2Utils = ({
3
9
  itemId,
4
10
  children
@@ -10,7 +16,7 @@ export const useTreeItem2Utils = ({
10
16
  }
11
17
  } = useTreeViewContext();
12
18
  const status = {
13
- expandable: Boolean(Array.isArray(children) ? children.length : children),
19
+ expandable: isItemExpandable(children),
14
20
  expanded: instance.isItemExpanded(itemId),
15
21
  focused: instance.isItemFocused(itemId),
16
22
  selected: instance.isItemSelected(itemId),
@@ -45,12 +51,21 @@ export const useTreeItem2Utils = ({
45
51
  instance.selectItem(event, itemId, true);
46
52
  }
47
53
  } else {
48
- instance.selectItem(event, itemId);
54
+ instance.selectItem(event, itemId, false);
55
+ }
56
+ };
57
+ const handleCheckboxSelection = event => {
58
+ const hasShift = event.nativeEvent.shiftKey;
59
+ if (multiSelect && hasShift) {
60
+ instance.expandSelectionRange(event, itemId);
61
+ } else {
62
+ instance.selectItem(event, itemId, multiSelect, event.target.checked);
49
63
  }
50
64
  };
51
65
  const interactions = {
52
66
  handleExpansion,
53
- handleSelection
67
+ handleSelection,
68
+ handleCheckboxSelection
54
69
  };
55
70
  return {
56
71
  interactions,
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-tree-view v7.4.0
2
+ * @mui/x-tree-view v7.5.1
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -104,12 +104,6 @@ export type TreeViewUsedInstance<TSignature extends TreeViewAnyPluginSignature>
104
104
  */
105
105
  $$signature: TSignature;
106
106
  };
107
- export type TreeViewUsedPublicAPI<TSignature extends TreeViewAnyPluginSignature> = TSignature['publicAPI'] & MergePluginsProperty<TreeViewUsedPlugins<TSignature>, 'publicAPI'> & {
108
- /**
109
- * Private property only defined in TypeScript to be able to access the plugin signature from the publicAPI object.
110
- */
111
- $$signature: TSignature;
112
- };
113
107
  type TreeViewUsedState<TSignature extends TreeViewAnyPluginSignature> = TSignature['state'] & MergePluginsProperty<TreeViewUsedPlugins<TSignature>, 'state'>;
114
108
  type RemoveSetValue<Models extends Record<string, TreeViewModel<any>>> = {
115
109
  [K in keyof Models]: Omit<Models[K], 'setValue'>;
@@ -9,6 +9,7 @@ interface TreeViewItemProps {
9
9
  export interface UseTreeViewItemsPublicAPI<R extends {}> {
10
10
  /**
11
11
  * Get the item with the given id.
12
+ * When used in the `SimpleTreeView`, it returns an object with the `id` and `label` properties.
12
13
  * @param {string} itemId The id of the item to return.
13
14
  * @returns {R} The item with the given id.
14
15
  */
@@ -61,7 +61,7 @@ export const useTreeViewKeyboardNavigation = ({
61
61
  if (event.defaultMuiPrevented) {
62
62
  return;
63
63
  }
64
- if (event.altKey || event.currentTarget !== event.target) {
64
+ if (event.altKey || event.currentTarget !== event.target.closest('*[role="treeitem"]')) {
65
65
  return;
66
66
  }
67
67
  const ctrlPressed = event.ctrlKey || event.metaKey;
@@ -78,7 +78,7 @@ export const useTreeViewKeyboardNavigation = ({
78
78
  } else if (params.multiSelect) {
79
79
  instance.selectItem(event, itemId, true);
80
80
  } else {
81
- instance.selectItem(event, itemId);
81
+ instance.selectItem(event, itemId, false);
82
82
  }
83
83
  break;
84
84
  }
@@ -95,7 +95,7 @@ export const useTreeViewKeyboardNavigation = ({
95
95
  event.preventDefault();
96
96
  instance.selectItem(event, itemId, true);
97
97
  } else if (!instance.isItemSelected(itemId)) {
98
- instance.selectItem(event, itemId);
98
+ instance.selectItem(event, itemId, false);
99
99
  event.preventDefault();
100
100
  }
101
101
  }
@@ -46,20 +46,28 @@ export const useTreeViewSelection = ({
46
46
  models.selectedItems.setControlledValue(newSelectedItems);
47
47
  };
48
48
  const isItemSelected = itemId => selectedItemsMap.has(itemId);
49
- const selectItem = (event, itemId, multiple = false) => {
49
+ const selectItem = (event, itemId, keepExistingSelection, newValue) => {
50
50
  if (params.disableSelection) {
51
51
  return;
52
52
  }
53
53
  let newSelected;
54
- if (multiple) {
54
+ if (keepExistingSelection) {
55
55
  const cleanSelectedItems = convertSelectedItemsToArray(models.selectedItems.value);
56
- if (instance.isItemSelected(itemId)) {
56
+ const isSelectedBefore = instance.isItemSelected(itemId);
57
+ if (isSelectedBefore && (newValue === false || newValue == null)) {
57
58
  newSelected = cleanSelectedItems.filter(id => id !== itemId);
58
- } else {
59
+ } else if (!isSelectedBefore && (newValue === true || newValue == null)) {
59
60
  newSelected = [itemId].concat(cleanSelectedItems);
61
+ } else {
62
+ newSelected = cleanSelectedItems;
60
63
  }
61
64
  } else {
62
- newSelected = params.multiSelect ? [itemId] : itemId;
65
+ // eslint-disable-next-line no-lonely-if
66
+ if (newValue === false) {
67
+ newSelected = params.multiSelect ? [] : null;
68
+ } else {
69
+ newSelected = params.multiSelect ? [itemId] : itemId;
70
+ }
63
71
  }
64
72
  setSelectedItems(event, newSelected);
65
73
  lastSelectedItem.current = itemId;
@@ -145,7 +153,9 @@ export const useTreeViewSelection = ({
145
153
  },
146
154
  contextValue: {
147
155
  selection: {
148
- multiSelect: params.multiSelect
156
+ multiSelect: params.multiSelect,
157
+ checkboxSelection: params.checkboxSelection,
158
+ disableSelection: params.disableSelection
149
159
  }
150
160
  }
151
161
  };
@@ -159,11 +169,13 @@ const DEFAULT_SELECTED_ITEMS = [];
159
169
  useTreeViewSelection.getDefaultizedParams = params => _extends({}, params, {
160
170
  disableSelection: params.disableSelection ?? false,
161
171
  multiSelect: params.multiSelect ?? false,
172
+ checkboxSelection: params.checkboxSelection ?? false,
162
173
  defaultSelectedItems: params.defaultSelectedItems ?? (params.multiSelect ? DEFAULT_SELECTED_ITEMS : null)
163
174
  });
164
175
  useTreeViewSelection.params = {
165
176
  disableSelection: true,
166
177
  multiSelect: true,
178
+ checkboxSelection: true,
167
179
  defaultSelectedItems: true,
168
180
  selectedItems: true,
169
181
  onSelectedItemsChange: true,