From 4aeca650676785524202574b357cf2a7d6ec038a Mon Sep 17 00:00:00 2001 From: noraleonte Date: Tue, 18 Jun 2024 13:34:18 +0300 Subject: [PATCH 1/9] add expansionTrigger prop --- .../useTreeViewExpansion/useTreeViewExpansion.ts | 15 +++++++++++++++ .../useTreeViewExpansion.types.ts | 12 +++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts index d463f24e85bb..4a26290bdb0e 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts @@ -83,6 +83,14 @@ export const useTreeViewExpansion: TreeViewPlugin } }; + const expansionTrigger = React.useMemo(() => { + if (params.expansionTrigger) { + return params.expansionTrigger; + } + + return 'content'; + }, [params.expansionTrigger]); + return { publicAPI: { setItemExpansion, @@ -94,6 +102,11 @@ export const useTreeViewExpansion: TreeViewPlugin toggleItemExpansion, expandAllSiblings, }, + contextValue: { + expansion: { + expansionTrigger, + }, + }, }; }; @@ -108,6 +121,7 @@ const DEFAULT_EXPANDED_ITEMS: string[] = []; useTreeViewExpansion.getDefaultizedParams = (params) => ({ ...params, defaultExpandedItems: params.defaultExpandedItems ?? DEFAULT_EXPANDED_ITEMS, + expansionTrigger: params.expansionTrigger ?? 'content', }); useTreeViewExpansion.params = { @@ -115,4 +129,5 @@ useTreeViewExpansion.params = { defaultExpandedItems: true, onExpandedItemsChange: true, onItemExpansionToggle: true, + expansionTrigger: true, }; diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts index 1eabf3ce9daf..41bfa8b38761 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts @@ -72,13 +72,22 @@ export interface UseTreeViewExpansionParameters { itemId: string, isExpanded: boolean, ) => void; + /** + * The slot that triggers the item's expansion when clicked. + * @default 'content' + */ + expansionTrigger?: 'content' | 'iconContainer'; } export type UseTreeViewExpansionDefaultizedParameters = DefaultizedProps< UseTreeViewExpansionParameters, - 'defaultExpandedItems' + 'defaultExpandedItems' | 'expansionTrigger' >; +interface UseTreeViewExpansionContextValue { + expansion: Pick; +} + export type UseTreeViewExpansionSignature = TreeViewPluginSignature<{ params: UseTreeViewExpansionParameters; defaultizedParams: UseTreeViewExpansionDefaultizedParameters; @@ -86,4 +95,5 @@ export type UseTreeViewExpansionSignature = TreeViewPluginSignature<{ publicAPI: UseTreeViewExpansionPublicAPI; modelNames: 'expandedItems'; dependantPlugins: [UseTreeViewItemsSignature]; + contextValue: UseTreeViewExpansionContextValue; }>; From 6d68dc6b74a1a0141debf3f65ec11fd1df1c46e9 Mon Sep 17 00:00:00 2001 From: noraleonte Date: Tue, 18 Jun 2024 18:51:11 +0300 Subject: [PATCH 2/9] add to treeItem2 --- .../useTreeViewExpansion.types.ts | 2 +- .../src/useTreeItem2/useTreeItem2.ts | 17 ++++++++++++++++- .../src/useTreeItem2/useTreeItem2.types.ts | 6 +++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts index 41bfa8b38761..1cfe798a96e7 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts @@ -94,6 +94,6 @@ export type UseTreeViewExpansionSignature = TreeViewPluginSignature<{ instance: UseTreeViewExpansionInstance; publicAPI: UseTreeViewExpansionPublicAPI; modelNames: 'expandedItems'; - dependantPlugins: [UseTreeViewItemsSignature]; contextValue: UseTreeViewExpansionContextValue; + dependantPlugins: [UseTreeViewItemsSignature]; }>; diff --git a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts index 72fd74f6d23c..7d9bd270f00a 100644 --- a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts +++ b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts @@ -25,6 +25,7 @@ export const useTreeItem2 = < const { runItemPlugins, selection: { multiSelect, disableSelection, checkboxSelection }, + expansion: { expansionTrigger }, disabledItemsFocusable, indentationAtItemLevel, instance, @@ -83,7 +84,9 @@ export const useTreeItem2 = < return; } - interactions.handleExpansion(event); + if (expansionTrigger === 'content') { + interactions.handleExpansion(event); + } if (!checkboxSelection) { interactions.handleSelection(event); @@ -118,6 +121,17 @@ export const useTreeItem2 = < interactions.handleCheckboxSelection(event); }; + const createIconContainerHandleClick = + (otherHandlers: EventHandlers) => (event: React.MouseEvent & MuiCancellableEvent) => { + otherHandlers.onClick?.(event); + if (event.defaultMuiPrevented) { + return; + } + if (expansionTrigger === 'iconContainer') { + interactions.handleExpansion(event); + } + }; + const getRootProps = = {}>( externalProps: ExternalProps = {} as ExternalProps, ): UseTreeItem2RootSlotProps => { @@ -225,6 +239,7 @@ export const useTreeItem2 = < return { ...externalEventHandlers, ...externalProps, + onClick: createIconContainerHandleClick(externalEventHandlers), }; }; diff --git a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts index 08651b015ad3..0e0099b2b9ff 100644 --- a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts +++ b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts @@ -7,6 +7,7 @@ import { UseTreeViewItemsSignature } from '../internals/plugins/useTreeViewItems import { UseTreeViewIdSignature } from '../internals/plugins/useTreeViewId'; import { UseTreeViewFocusSignature } from '../internals/plugins/useTreeViewFocus'; import { UseTreeViewKeyboardNavigationSignature } from '../internals/plugins/useTreeViewKeyboardNavigation'; +import { UseTreeViewExpansionSignature } from '../internals'; export interface UseTreeItem2Parameters { /** @@ -68,7 +69,9 @@ export interface UseTreeItem2ContentSlotOwnProps { export type UseTreeItem2ContentSlotProps = ExternalProps & UseTreeItem2ContentSlotOwnProps; -export interface UseTreeItem2IconContainerSlotOwnProps {} +export interface UseTreeItem2IconContainerSlotOwnProps { + onClick: MuiCancellableEventHandler; +} export type UseTreeItemIconContainerSlotProps = ExternalProps & UseTreeItem2IconContainerSlotOwnProps; @@ -182,6 +185,7 @@ export interface UseTreeItem2ReturnValue< export type UseTreeItem2MinimalPlugins = readonly [ UseTreeViewSelectionSignature, + UseTreeViewExpansionSignature, UseTreeViewItemsSignature, UseTreeViewIdSignature, UseTreeViewFocusSignature, From fcf666460564b707bd84cea91d76662a9e463137 Mon Sep 17 00:00:00 2001 From: noraleonte Date: Tue, 18 Jun 2024 18:58:50 +0300 Subject: [PATCH 3/9] update docs --- .../customization/IconExpansionTreeView.js | 35 ++-------- .../customization/IconExpansionTreeView.tsx | 40 ++--------- .../IconExpansionTreeView.tsx.preview | 6 +- .../customization/IconExpansionTreeView.js | 61 +++++------------ .../customization/IconExpansionTreeView.tsx | 66 +++++-------------- .../src/RichTreeView/RichTreeView.tsx | 5 ++ .../src/SimpleTreeView/SimpleTreeView.tsx | 5 ++ .../x-tree-view/src/TreeView/TreeView.tsx | 5 ++ 8 files changed, 64 insertions(+), 159 deletions(-) diff --git a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.js b/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.js index fa2935769a63..2fff0beb5b9c 100644 --- a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.js +++ b/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.js @@ -1,8 +1,6 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; -import { useTreeItem2Utils } from '@mui/x-tree-view/hooks'; - import { TreeItem2 } from '@mui/x-tree-view/TreeItem2'; const MUI_X_PRODUCTS = [ @@ -35,37 +33,14 @@ const MUI_X_PRODUCTS = [ }, ]; -const CustomTreeItem = React.forwardRef(function MyTreeItem(props, ref) { - const { interactions } = useTreeItem2Utils({ - itemId: props.itemId, - children: props.children, - }); - - const handleContentClick = (event) => { - event.defaultMuiPrevented = true; - interactions.handleSelection(event); - }; - - const handleIconContainerClick = (event) => { - interactions.handleExpansion(event); - }; - - return ( - - ); -}); - export default function IconExpansionTreeView() { return ( - + ); } diff --git a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx b/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx index 0d7345a1047d..89ed303455ad 100644 --- a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx +++ b/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx @@ -1,9 +1,7 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; -import { useTreeItem2Utils } from '@mui/x-tree-view/hooks'; -import { UseTreeItem2ContentSlotOwnProps } from '@mui/x-tree-view/useTreeItem2'; -import { TreeItem2, TreeItem2Props } from '@mui/x-tree-view/TreeItem2'; +import { TreeItem2 } from '@mui/x-tree-view/TreeItem2'; import { TreeViewBaseItem } from '@mui/x-tree-view/models'; const MUI_X_PRODUCTS: TreeViewBaseItem[] = [ @@ -36,40 +34,14 @@ const MUI_X_PRODUCTS: TreeViewBaseItem[] = [ }, ]; -const CustomTreeItem = React.forwardRef(function MyTreeItem( - props: TreeItem2Props, - ref: React.Ref, -) { - const { interactions } = useTreeItem2Utils({ - itemId: props.itemId, - children: props.children, - }); - - const handleContentClick: UseTreeItem2ContentSlotOwnProps['onClick'] = (event) => { - event.defaultMuiPrevented = true; - interactions.handleSelection(event); - }; - - const handleIconContainerClick = (event: React.MouseEvent) => { - interactions.handleExpansion(event); - }; - - return ( - - ); -}); - export default function IconExpansionTreeView() { return ( - + ); } diff --git a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview b/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview index 660542f7bf2c..1e526e35fc3a 100644 --- a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview +++ b/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview @@ -1 +1,5 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js b/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js index 36e9e200da11..24c43a5b6774 100644 --- a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js +++ b/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js @@ -1,56 +1,27 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; -import { useTreeItem2Utils } from '@mui/x-tree-view/hooks'; - import { TreeItem2 } from '@mui/x-tree-view/TreeItem2'; -const CustomTreeItem = React.forwardRef(function MyTreeItem(props, ref) { - const { interactions } = useTreeItem2Utils({ - itemId: props.itemId, - children: props.children, - }); - - const handleContentClick = (event) => { - event.defaultMuiPrevented = true; - interactions.handleSelection(event); - }; - - const handleIconContainerClick = (event) => { - interactions.handleExpansion(event); - }; - - return ( - - ); -}); - export default function IconExpansionTreeView() { return ( - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + ); diff --git a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx b/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx index f0a5de292e60..24c43a5b6774 100644 --- a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx +++ b/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx @@ -1,59 +1,27 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; -import { useTreeItem2Utils } from '@mui/x-tree-view/hooks'; -import { UseTreeItem2ContentSlotOwnProps } from '@mui/x-tree-view/useTreeItem2'; -import { TreeItem2, TreeItem2Props } from '@mui/x-tree-view/TreeItem2'; - -const CustomTreeItem = React.forwardRef(function MyTreeItem( - props: TreeItem2Props, - ref: React.Ref, -) { - const { interactions } = useTreeItem2Utils({ - itemId: props.itemId, - children: props.children, - }); - - const handleContentClick: UseTreeItem2ContentSlotOwnProps['onClick'] = (event) => { - event.defaultMuiPrevented = true; - interactions.handleSelection(event); - }; - - const handleIconContainerClick = (event: React.MouseEvent) => { - interactions.handleExpansion(event); - }; - - return ( - - ); -}); +import { TreeItem2 } from '@mui/x-tree-view/TreeItem2'; export default function IconExpansionTreeView() { return ( - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + ); diff --git a/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx b/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx index 5f94c0db2be7..1af8e390626f 100644 --- a/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx +++ b/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx @@ -191,6 +191,11 @@ RichTreeView.propTypes = { * Used when the item's expansion is controlled. */ expandedItems: PropTypes.arrayOf(PropTypes.string), + /** + * The slot that triggers the item's expansion when clicked. + * @default 'content' + */ + expansionTrigger: PropTypes.oneOf(['content', 'iconContainer']), /** * Unstable features, breaking changes might be introduced. * For each feature, if the flag is not explicitly set to `true`, diff --git a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx index 472bf6208f58..9993677439e3 100644 --- a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx +++ b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx @@ -154,6 +154,11 @@ SimpleTreeView.propTypes = { * Used when the item's expansion is controlled. */ expandedItems: PropTypes.arrayOf(PropTypes.string), + /** + * The slot that triggers the item's expansion when clicked. + * @default 'content' + */ + expansionTrigger: PropTypes.oneOf(['content', 'iconContainer']), /** * Unstable features, breaking changes might be introduced. * For each feature, if the flag is not explicitly set to `true`, diff --git a/packages/x-tree-view/src/TreeView/TreeView.tsx b/packages/x-tree-view/src/TreeView/TreeView.tsx index 2149524f39fd..55d215de6183 100644 --- a/packages/x-tree-view/src/TreeView/TreeView.tsx +++ b/packages/x-tree-view/src/TreeView/TreeView.tsx @@ -139,6 +139,11 @@ TreeView.propTypes = { * Used when the item's expansion is controlled. */ expandedItems: PropTypes.arrayOf(PropTypes.string), + /** + * The slot that triggers the item's expansion when clicked. + * @default 'content' + */ + expansionTrigger: PropTypes.oneOf(['content', 'iconContainer']), /** * Unstable features, breaking changes might be introduced. * For each feature, if the flag is not explicitly set to `true`, From 35a2663f92019264528ad690c1769960f7094437 Mon Sep 17 00:00:00 2001 From: noraleonte Date: Tue, 18 Jun 2024 19:24:14 +0300 Subject: [PATCH 4/9] add to treeitem --- docs/pages/x/api/tree-view/rich-tree-view.json | 4 ++++ docs/pages/x/api/tree-view/simple-tree-view.json | 4 ++++ docs/pages/x/api/tree-view/tree-view.json | 4 ++++ .../tree-view/rich-tree-view/rich-tree-view.json | 3 +++ .../tree-view/simple-tree-view/simple-tree-view.json | 3 +++ .../api-docs/tree-view/tree-view/tree-view.json | 3 +++ packages/x-tree-view/src/TreeItem/TreeItem.tsx | 12 ++++++++++++ .../x-tree-view/src/TreeItem/TreeItemContent.tsx | 5 ++++- .../x-tree-view/src/TreeItem/useTreeItemState.ts | 2 ++ 9 files changed, 39 insertions(+), 1 deletion(-) diff --git a/docs/pages/x/api/tree-view/rich-tree-view.json b/docs/pages/x/api/tree-view/rich-tree-view.json index 7da4e28d56f0..302a091490e7 100644 --- a/docs/pages/x/api/tree-view/rich-tree-view.json +++ b/docs/pages/x/api/tree-view/rich-tree-view.json @@ -16,6 +16,10 @@ "disabledItemsFocusable": { "type": { "name": "bool" }, "default": "false" }, "disableSelection": { "type": { "name": "bool" }, "default": "false" }, "expandedItems": { "type": { "name": "arrayOf", "description": "Array<string>" } }, + "expansionTrigger": { + "type": { "name": "enum", "description": "'content'
| 'iconContainer'" }, + "default": "'content'" + }, "experimentalFeatures": { "type": { "name": "shape", "description": "{ indentationAtItemLevel?: bool }" } }, diff --git a/docs/pages/x/api/tree-view/simple-tree-view.json b/docs/pages/x/api/tree-view/simple-tree-view.json index 1c52f9e03646..24df95176eb5 100644 --- a/docs/pages/x/api/tree-view/simple-tree-view.json +++ b/docs/pages/x/api/tree-view/simple-tree-view.json @@ -17,6 +17,10 @@ "disabledItemsFocusable": { "type": { "name": "bool" }, "default": "false" }, "disableSelection": { "type": { "name": "bool" }, "default": "false" }, "expandedItems": { "type": { "name": "arrayOf", "description": "Array<string>" } }, + "expansionTrigger": { + "type": { "name": "enum", "description": "'content'
| 'iconContainer'" }, + "default": "'content'" + }, "experimentalFeatures": { "type": { "name": "shape", "description": "{ indentationAtItemLevel?: bool }" } }, diff --git a/docs/pages/x/api/tree-view/tree-view.json b/docs/pages/x/api/tree-view/tree-view.json index a528b9927844..b2eead268281 100644 --- a/docs/pages/x/api/tree-view/tree-view.json +++ b/docs/pages/x/api/tree-view/tree-view.json @@ -17,6 +17,10 @@ "disabledItemsFocusable": { "type": { "name": "bool" }, "default": "false" }, "disableSelection": { "type": { "name": "bool" }, "default": "false" }, "expandedItems": { "type": { "name": "arrayOf", "description": "Array<string>" } }, + "expansionTrigger": { + "type": { "name": "enum", "description": "'content'
| 'iconContainer'" }, + "default": "'content'" + }, "experimentalFeatures": { "type": { "name": "shape", "description": "{ indentationAtItemLevel?: bool }" } }, diff --git a/docs/translations/api-docs/tree-view/rich-tree-view/rich-tree-view.json b/docs/translations/api-docs/tree-view/rich-tree-view/rich-tree-view.json index b866f4dcc07a..42345574e68d 100644 --- a/docs/translations/api-docs/tree-view/rich-tree-view/rich-tree-view.json +++ b/docs/translations/api-docs/tree-view/rich-tree-view/rich-tree-view.json @@ -21,6 +21,9 @@ "expandedItems": { "description": "Expanded item ids. Used when the item's expansion is controlled." }, + "expansionTrigger": { + "description": "The slot that triggers the item's expansion when clicked." + }, "experimentalFeatures": { "description": "Unstable features, breaking changes might be introduced. For each feature, if the flag is not explicitly set to true, the feature will be fully disabled and any property / method call will not have any effect." }, diff --git a/docs/translations/api-docs/tree-view/simple-tree-view/simple-tree-view.json b/docs/translations/api-docs/tree-view/simple-tree-view/simple-tree-view.json index a12a98351778..8d0b15e73d6a 100644 --- a/docs/translations/api-docs/tree-view/simple-tree-view/simple-tree-view.json +++ b/docs/translations/api-docs/tree-view/simple-tree-view/simple-tree-view.json @@ -22,6 +22,9 @@ "expandedItems": { "description": "Expanded item ids. Used when the item's expansion is controlled." }, + "expansionTrigger": { + "description": "The slot that triggers the item's expansion when clicked." + }, "experimentalFeatures": { "description": "Unstable features, breaking changes might be introduced. For each feature, if the flag is not explicitly set to true, the feature will be fully disabled and any property / method call will not have any effect." }, diff --git a/docs/translations/api-docs/tree-view/tree-view/tree-view.json b/docs/translations/api-docs/tree-view/tree-view/tree-view.json index c29df2121733..f61dba71a60a 100644 --- a/docs/translations/api-docs/tree-view/tree-view/tree-view.json +++ b/docs/translations/api-docs/tree-view/tree-view/tree-view.json @@ -22,6 +22,9 @@ "expandedItems": { "description": "Expanded item ids. Used when the item's expansion is controlled." }, + "expansionTrigger": { + "description": "The slot that triggers the item's expansion when clicked." + }, "experimentalFeatures": { "description": "Unstable features, breaking changes might be introduced. For each feature, if the flag is not explicitly set to true, the feature will be fully disabled and any property / method call will not have any effect." }, diff --git a/packages/x-tree-view/src/TreeItem/TreeItem.tsx b/packages/x-tree-view/src/TreeItem/TreeItem.tsx index f4224825ec58..5d10fc2117ee 100644 --- a/packages/x-tree-view/src/TreeItem/TreeItem.tsx +++ b/packages/x-tree-view/src/TreeItem/TreeItem.tsx @@ -18,6 +18,7 @@ import { useTreeViewContext } from '../internals/TreeViewProvider/useTreeViewCon import { TreeViewCollapseIcon, TreeViewExpandIcon } from '../icons'; import { TreeItem2Provider } from '../TreeItem2Provider'; import { TreeViewItemDepthContext } from '../internals/TreeViewItemDepthContext'; +import { useTreeItemState } from './useTreeItemState'; const useThemeProps = createUseThemeProps('MuiTreeItem'); @@ -182,6 +183,7 @@ export const TreeItem = React.forwardRef(function TreeItem( icons: contextIcons, runItemPlugins, selection: { multiSelect }, + expansion: { expansionTrigger }, disabledItemsFocusable, indentationAtItemLevel, instance, @@ -208,6 +210,8 @@ export const TreeItem = React.forwardRef(function TreeItem( ...other } = props; + const { handleExpansion } = useTreeItemState(itemId); + const { contentRef, rootRef } = runItemPlugins(props); const handleRootRef = useForkRef(inRef, rootRef); const handleContentRef = useForkRef(ContentProps?.ref, contentRef); @@ -258,6 +262,11 @@ export const TreeItem = React.forwardRef(function TreeItem( className: classes.groupTransition, }); + const handleIconContainerClick = (event: React.MouseEvent) => { + if (expansionTrigger === 'iconContainer') { + handleExpansion(event); + } + }; const ExpansionIcon = expanded ? slots.collapseIcon : slots.expandIcon; const { ownerState: expansionIconOwnerState, ...expansionIconProps } = useSlotProps({ elementType: ExpansionIcon, @@ -275,6 +284,9 @@ export const TreeItem = React.forwardRef(function TreeItem( ...resolveComponentProps(inSlotProps?.expandIcon, tempOwnerState), }; }, + additionalProps: { + onClick: handleIconContainerClick, + }, }); const expansionIcon = expandable && !!ExpansionIcon ? : null; diff --git a/packages/x-tree-view/src/TreeItem/TreeItemContent.tsx b/packages/x-tree-view/src/TreeItem/TreeItemContent.tsx index 11c31e401cee..c04b65ed08ea 100644 --- a/packages/x-tree-view/src/TreeItem/TreeItemContent.tsx +++ b/packages/x-tree-view/src/TreeItem/TreeItemContent.tsx @@ -82,6 +82,7 @@ const TreeItemContent = React.forwardRef(function TreeItemContent( handleSelection, handleCheckboxSelection, preventSelection, + expansionTrigger, } = useTreeItemState(itemId); const icon = iconProp || expansionIcon || displayIcon; @@ -100,7 +101,9 @@ const TreeItemContent = React.forwardRef(function TreeItemContent( return; } - handleExpansion(event); + if (expansionTrigger === 'content') { + handleExpansion(event); + } if (!checkboxSelection) { handleSelection(event); diff --git a/packages/x-tree-view/src/TreeItem/useTreeItemState.ts b/packages/x-tree-view/src/TreeItem/useTreeItemState.ts index fea40a777a0f..1b8e9231438b 100644 --- a/packages/x-tree-view/src/TreeItem/useTreeItemState.ts +++ b/packages/x-tree-view/src/TreeItem/useTreeItemState.ts @@ -16,6 +16,7 @@ export function useTreeItemState(itemId: string) { const { instance, selection: { multiSelect, checkboxSelection, disableSelection }, + expansion: { expansionTrigger }, } = useTreeViewContext(); const expandable = instance.isItemExpandable(itemId); @@ -90,5 +91,6 @@ export function useTreeItemState(itemId: string) { handleSelection, handleCheckboxSelection, preventSelection, + expansionTrigger, }; } From 12fd9cc1ccfbb9449787a6d90548e5d6a91035b9 Mon Sep 17 00:00:00 2001 From: noraleonte Date: Wed, 19 Jun 2024 14:58:09 +0300 Subject: [PATCH 5/9] move demos --- .../IconExpansionTreeView.tsx.preview | 5 ---- .../customization/customization.md | 6 ---- .../IconExpansionTreeView.js | 7 +---- .../IconExpansionTreeView.tsx | 7 +---- .../IconExpansionTreeView.tsx.preview | 1 + .../rich-tree-view/expansion/expansion.md | 6 ++++ .../customization/IconExpansionTreeView.js | 28 ------------------- .../customization/IconExpansionTreeView.tsx | 28 ------------------- .../customization/customization.md | 13 --------- .../expansion/IconExpansionTreeView.js | 28 +++++++++++++++++++ .../expansion/IconExpansionTreeView.tsx | 28 +++++++++++++++++++ .../simple-tree-view/expansion/expansion.md | 6 ++++ .../x-tree-view/src/TreeItem/TreeItem.tsx | 6 +--- test/utils/tree-view/fakeContextValue.ts | 1 + 14 files changed, 73 insertions(+), 97 deletions(-) delete mode 100644 docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview rename docs/data/tree-view/rich-tree-view/{customization => expansion}/IconExpansionTreeView.js (83%) rename docs/data/tree-view/rich-tree-view/{customization => expansion}/IconExpansionTreeView.tsx (84%) create mode 100644 docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx.preview delete mode 100644 docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js delete mode 100644 docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx create mode 100644 docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.js create mode 100644 docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.tsx diff --git a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview b/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview deleted file mode 100644 index 1e526e35fc3a..000000000000 --- a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file diff --git a/docs/data/tree-view/rich-tree-view/customization/customization.md b/docs/data/tree-view/rich-tree-view/customization/customization.md index 8f1552b6f0df..4bedda31d764 100644 --- a/docs/data/tree-view/rich-tree-view/customization/customization.md +++ b/docs/data/tree-view/rich-tree-view/customization/customization.md @@ -64,12 +64,6 @@ The demo below shows how to add an avatar and custom typography elements. ## Common examples -### Limit expansion to icon container - -The demo below shows how to trigger the expansion interaction just by clicking on the icon container instead of the whole Tree Item surface. - -{{"demo": "IconExpansionTreeView.js", "defaultCodeOpen": false}} - ### File explorer :::warning diff --git a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.js b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.js similarity index 83% rename from docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.js rename to docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.js index 2fff0beb5b9c..db2d29f0fcfa 100644 --- a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.js +++ b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.js @@ -1,7 +1,6 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; -import { TreeItem2 } from '@mui/x-tree-view/TreeItem2'; const MUI_X_PRODUCTS = [ { @@ -36,11 +35,7 @@ const MUI_X_PRODUCTS = [ export default function IconExpansionTreeView() { return ( - + ); } diff --git a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx similarity index 84% rename from docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx rename to docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx index 89ed303455ad..94b9816b9a89 100644 --- a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx +++ b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; -import { TreeItem2 } from '@mui/x-tree-view/TreeItem2'; import { TreeViewBaseItem } from '@mui/x-tree-view/models'; const MUI_X_PRODUCTS: TreeViewBaseItem[] = [ @@ -37,11 +36,7 @@ const MUI_X_PRODUCTS: TreeViewBaseItem[] = [ export default function IconExpansionTreeView() { return ( - + ); } diff --git a/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx.preview b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx.preview new file mode 100644 index 000000000000..49f8c4e18162 --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/tree-view/rich-tree-view/expansion/expansion.md b/docs/data/tree-view/rich-tree-view/expansion/expansion.md index e36fe65d20c1..2ed754b3ea2d 100644 --- a/docs/data/tree-view/rich-tree-view/expansion/expansion.md +++ b/docs/data/tree-view/rich-tree-view/expansion/expansion.md @@ -33,6 +33,12 @@ Use the `onItemExpansionToggle` prop if you want to react to an item expansion c {{"demo": "TrackItemExpansionToggle.js"}} +## Limit expansion to icon container + +The demo below shows how to trigger the expansion interaction just by clicking on the icon container instead of the whole Tree Item content. + +{{"demo": "IconExpansionTreeView.js", "defaultCodeOpen": false}} + ## Imperative API :::success diff --git a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js b/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js deleted file mode 100644 index 24c43a5b6774..000000000000 --- a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js +++ /dev/null @@ -1,28 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/material/Box'; -import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; -import { TreeItem2 } from '@mui/x-tree-view/TreeItem2'; - -export default function IconExpansionTreeView() { - return ( - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx b/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx deleted file mode 100644 index 24c43a5b6774..000000000000 --- a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/material/Box'; -import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; -import { TreeItem2 } from '@mui/x-tree-view/TreeItem2'; - -export default function IconExpansionTreeView() { - return ( - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/docs/data/tree-view/simple-tree-view/customization/customization.md b/docs/data/tree-view/simple-tree-view/customization/customization.md index e5e70b9e4aa8..7cf009836436 100644 --- a/docs/data/tree-view/simple-tree-view/customization/customization.md +++ b/docs/data/tree-view/simple-tree-view/customization/customization.md @@ -70,19 +70,6 @@ Target the `treeItemClasses.groupTransition` class to add connection borders bet {{"demo": "BorderedTreeView.js", "defaultCodeOpen": false}} -### Limit expansion to icon container - -:::warning -This example is built using the new `TreeItem2` component -which adds several slots to modify the content of the Tree Item or change its behavior. - -You can learn more about this new component in the [Overview page](/x/react-tree-view/#tree-item-components). -::: - -The demo below shows how to trigger the expansion interaction just by clicking on the icon container instead of the whole Tree Item surface. - -{{"demo": "IconExpansionTreeView.js", "defaultCodeOpen": false}} - ### Gmail clone :::warning diff --git a/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.js b/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.js new file mode 100644 index 000000000000..3a046031d357 --- /dev/null +++ b/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.js @@ -0,0 +1,28 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; +import { TreeItem } from '@mui/x-tree-view/TreeItem'; + +export default function IconExpansionTreeView() { + return ( + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.tsx b/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.tsx new file mode 100644 index 000000000000..3a046031d357 --- /dev/null +++ b/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; +import { TreeItem } from '@mui/x-tree-view/TreeItem'; + +export default function IconExpansionTreeView() { + return ( + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/docs/data/tree-view/simple-tree-view/expansion/expansion.md b/docs/data/tree-view/simple-tree-view/expansion/expansion.md index a6b0a3f4e46a..da787b2d1c99 100644 --- a/docs/data/tree-view/simple-tree-view/expansion/expansion.md +++ b/docs/data/tree-view/simple-tree-view/expansion/expansion.md @@ -32,6 +32,12 @@ Use the `onItemExpansionToggle` prop to trigger an action upon an item being exp {{"demo": "TrackItemExpansionToggle.js"}} +## Limit expansion to icon container + +The demo below shows how to trigger the expansion interaction just by clicking on the icon container instead of the whole Tree Item content. + +{{"demo": "IconExpansionTreeView.js", "defaultCodeOpen": false}} + ## Imperative API :::success diff --git a/packages/x-tree-view/src/TreeItem/TreeItem.tsx b/packages/x-tree-view/src/TreeItem/TreeItem.tsx index 5d10fc2117ee..9966fbfa3d12 100644 --- a/packages/x-tree-view/src/TreeItem/TreeItem.tsx +++ b/packages/x-tree-view/src/TreeItem/TreeItem.tsx @@ -210,7 +210,7 @@ export const TreeItem = React.forwardRef(function TreeItem( ...other } = props; - const { handleExpansion } = useTreeItemState(itemId); + const { expanded, focused, selected, disabled, handleExpansion } = useTreeItemState(itemId); const { contentRef, rootRef } = runItemPlugins(props); const handleRootRef = useForkRef(inRef, rootRef); @@ -231,10 +231,6 @@ export const TreeItem = React.forwardRef(function TreeItem( return Boolean(reactChildren); }; const expandable = isExpandable(children); - const expanded = instance.isItemExpanded(itemId); - const focused = instance.isItemFocused(itemId); - const selected = instance.isItemSelected(itemId); - const disabled = instance.isItemDisabled(itemId); const ownerState: TreeItemOwnerState = { ...props, diff --git a/test/utils/tree-view/fakeContextValue.ts b/test/utils/tree-view/fakeContextValue.ts index 5f4e44545102..f31059052035 100644 --- a/test/utils/tree-view/fakeContextValue.ts +++ b/test/utils/tree-view/fakeContextValue.ts @@ -39,4 +39,5 @@ export const getFakeContextValue = ( rootRef: { current: null, }, + expansion: { expansionTrigger: 'content' }, }); From ebc20650a42b12d19ed61a7eea26774ab189559d Mon Sep 17 00:00:00 2001 From: noraleonte Date: Wed, 19 Jun 2024 15:00:01 +0300 Subject: [PATCH 6/9] remove default value --- .../plugins/useTreeViewExpansion/useTreeViewExpansion.ts | 1 - .../useTreeViewExpansion/useTreeViewExpansion.types.ts | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts index 4a26290bdb0e..3fd669acf55f 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts @@ -121,7 +121,6 @@ const DEFAULT_EXPANDED_ITEMS: string[] = []; useTreeViewExpansion.getDefaultizedParams = (params) => ({ ...params, defaultExpandedItems: params.defaultExpandedItems ?? DEFAULT_EXPANDED_ITEMS, - expansionTrigger: params.expansionTrigger ?? 'content', }); useTreeViewExpansion.params = { diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts index 1cfe798a96e7..6b1e2cd56031 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts @@ -81,11 +81,11 @@ export interface UseTreeViewExpansionParameters { export type UseTreeViewExpansionDefaultizedParameters = DefaultizedProps< UseTreeViewExpansionParameters, - 'defaultExpandedItems' | 'expansionTrigger' + 'defaultExpandedItems' >; interface UseTreeViewExpansionContextValue { - expansion: Pick; + expansion: Pick; } export type UseTreeViewExpansionSignature = TreeViewPluginSignature<{ From 65852850192a3a891de4e01b74cca5ee57f09320 Mon Sep 17 00:00:00 2001 From: noraleonte Date: Wed, 19 Jun 2024 15:02:58 +0300 Subject: [PATCH 7/9] fix import --- packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts index 797a3d7b6081..c4abbc7d2220 100644 --- a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts +++ b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts @@ -7,7 +7,7 @@ import { UseTreeViewItemsSignature } from '../internals/plugins/useTreeViewItems import { UseTreeViewIdSignature } from '../internals/plugins/useTreeViewId'; import { UseTreeViewFocusSignature } from '../internals/plugins/useTreeViewFocus'; import { UseTreeViewKeyboardNavigationSignature } from '../internals/plugins/useTreeViewKeyboardNavigation'; -import { UseTreeViewExpansionSignature } from '../internals'; +import { UseTreeViewExpansionSignature } from '../internals/plugins/useTreeViewExpansion'; export interface UseTreeItem2Parameters { /** From 5c33e266ac2c7e4b430fafc8882f5ea4a79eb502 Mon Sep 17 00:00:00 2001 From: Nora <72460825+noraleonte@users.noreply.github.com> Date: Tue, 25 Jun 2024 17:16:56 +0300 Subject: [PATCH 8/9] Apply suggestions from code review - Flavien Co-authored-by: Flavien DELANGLE Signed-off-by: Nora <72460825+noraleonte@users.noreply.github.com> --- docs/data/tree-view/rich-tree-view/expansion/expansion.md | 4 ++-- docs/data/tree-view/simple-tree-view/expansion/expansion.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/data/tree-view/rich-tree-view/expansion/expansion.md b/docs/data/tree-view/rich-tree-view/expansion/expansion.md index 2ed754b3ea2d..47897f4c9170 100644 --- a/docs/data/tree-view/rich-tree-view/expansion/expansion.md +++ b/docs/data/tree-view/rich-tree-view/expansion/expansion.md @@ -35,9 +35,9 @@ Use the `onItemExpansionToggle` prop if you want to react to an item expansion c ## Limit expansion to icon container -The demo below shows how to trigger the expansion interaction just by clicking on the icon container instead of the whole Tree Item content. +You can use the `expansionTrigger` prop to decide if the expansion interaction should be triggered by clicking on the icon container instead of the whole Tree Item content. -{{"demo": "IconExpansionTreeView.js", "defaultCodeOpen": false}} +{{"demo": "IconExpansionTreeView.js"}} ## Imperative API diff --git a/docs/data/tree-view/simple-tree-view/expansion/expansion.md b/docs/data/tree-view/simple-tree-view/expansion/expansion.md index da787b2d1c99..86824e7e3298 100644 --- a/docs/data/tree-view/simple-tree-view/expansion/expansion.md +++ b/docs/data/tree-view/simple-tree-view/expansion/expansion.md @@ -34,7 +34,7 @@ Use the `onItemExpansionToggle` prop to trigger an action upon an item being exp ## Limit expansion to icon container -The demo below shows how to trigger the expansion interaction just by clicking on the icon container instead of the whole Tree Item content. +You can use the `expansionTrigger` prop to decide if the expansion interaction should be triggered by clicking on the icon container instead of the whole Tree Item content. {{"demo": "IconExpansionTreeView.js", "defaultCodeOpen": false}} From ba4531971b73eca81c48a8ca7d32440e70afe2b3 Mon Sep 17 00:00:00 2001 From: Nora <72460825+noraleonte@users.noreply.github.com> Date: Tue, 25 Jun 2024 17:17:50 +0300 Subject: [PATCH 9/9] Show demo by default Signed-off-by: Nora <72460825+noraleonte@users.noreply.github.com> --- docs/data/tree-view/simple-tree-view/expansion/expansion.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data/tree-view/simple-tree-view/expansion/expansion.md b/docs/data/tree-view/simple-tree-view/expansion/expansion.md index 86824e7e3298..a3648bd3697f 100644 --- a/docs/data/tree-view/simple-tree-view/expansion/expansion.md +++ b/docs/data/tree-view/simple-tree-view/expansion/expansion.md @@ -36,7 +36,7 @@ Use the `onItemExpansionToggle` prop to trigger an action upon an item being exp You can use the `expansionTrigger` prop to decide if the expansion interaction should be triggered by clicking on the icon container instead of the whole Tree Item content. -{{"demo": "IconExpansionTreeView.js", "defaultCodeOpen": false}} +{{"demo": "IconExpansionTreeView.js"}} ## Imperative API