From 82cac24c833f4e7eb977b694e7eeb8f7b61acd8b Mon Sep 17 00:00:00 2001 From: flavien Date: Fri, 27 Sep 2024 10:04:33 +0200 Subject: [PATCH] [TreeView] Rework how items are being rendering in Rich Tree View components --- .../src/RichTreeViewPro/RichTreeViewPro.tsx | 76 ++-------------- .../src/RichTreeView/RichTreeView.tsx | 52 ++--------- .../components/RichTreeViewItems.tsx | 91 +++++++++++++++++++ packages/x-tree-view/src/internals/index.ts | 2 + .../plugins/useTreeViewItems/index.ts | 1 + .../useTreeViewItems.types.ts | 12 +-- 6 files changed, 114 insertions(+), 120 deletions(-) create mode 100644 packages/x-tree-view/src/internals/components/RichTreeViewItems.tsx diff --git a/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.tsx b/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.tsx index 0cb18fa82006c..d9b8754e8d071 100644 --- a/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.tsx +++ b/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.tsx @@ -5,7 +5,7 @@ import composeClasses from '@mui/utils/composeClasses'; import { useLicenseVerifier, Watermark } from '@mui/x-license'; import useSlotProps from '@mui/utils/useSlotProps'; import { TreeItem, TreeItemProps } from '@mui/x-tree-view/TreeItem'; -import { useTreeView, TreeViewProvider } from '@mui/x-tree-view/internals'; +import { useTreeView, TreeViewProvider, RichTreeViewItems } from '@mui/x-tree-view/internals'; import { warnOnce } from '@mui/x-internals/warning'; import { styled, createUseThemeProps } from '../internals/zero-styled'; import { getRichTreeViewProUtilityClass } from './richTreeViewProClasses'; @@ -46,52 +46,6 @@ type RichTreeViewProComponent = ( & React.RefAttributes, ) => React.JSX.Element) & { propTypes?: any }; -function WrappedTreeItem({ - slots, - slotProps, - label, - id, - itemId, - children, -}: Pick, 'slots' | 'slotProps'> & - Pick & { label: string }) { - const Item = slots?.item ?? TreeItem; - const itemProps = useSlotProps({ - elementType: Item, - externalSlotProps: slotProps?.item, - additionalProps: { itemId, id, label }, - ownerState: { itemId, label }, - }); - - return {children}; -} - -WrappedTreeItem.propTypes = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the TypeScript types and run "pnpm proptypes" | - // ---------------------------------------------------------------------- - /** - * The content of the component. - */ - children: PropTypes.node, - /** - * The id of the item. - */ - itemId: PropTypes.string.isRequired, - label: PropTypes.string.isRequired, - /** - * The props used for each component slot. - * @default {} - */ - slotProps: PropTypes.object, - /** - * Overridable component slots. - * @default {} - */ - slots: PropTypes.object, -} as any; - const releaseInfo = getReleaseInfo(); /** @@ -143,32 +97,14 @@ const RichTreeViewPro = React.forwardRef(function RichTreeViewPro< ownerState: props as RichTreeViewProProps, }); - const itemsToRender = instance.getItemsToRender(); - - const renderItem = ({ - label, - itemId, - id, - children, - }: ReturnType[number]) => { - return ( - - {children?.map(renderItem)} - - ); - }; - return ( - {itemsToRender.map(renderItem)} + diff --git a/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx b/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx index 755b5f8213619..d030df14bd9a0 100644 --- a/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx +++ b/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx @@ -10,7 +10,7 @@ import { styled, createUseThemeProps } from '../internals/zero-styled'; import { useTreeView } from '../internals/useTreeView'; import { TreeViewProvider } from '../internals/TreeViewProvider'; import { RICH_TREE_VIEW_PLUGINS, RichTreeViewPluginSignatures } from './RichTreeView.plugins'; -import { TreeItem, TreeItemProps } from '../TreeItem'; +import { RichTreeViewItems } from '../internals/components/RichTreeViewItems'; const useThemeProps = createUseThemeProps('MuiRichTreeView'); @@ -42,26 +42,6 @@ type RichTreeViewComponent = ( & React.RefAttributes, ) => React.JSX.Element) & { propTypes?: any }; -function WrappedTreeItem({ - slots, - slotProps, - label, - id, - itemId, - children, -}: Pick, 'slots' | 'slotProps'> & - Pick & { label: string }) { - const Item = slots?.item ?? TreeItem; - const itemProps = useSlotProps({ - elementType: Item, - externalSlotProps: slotProps?.item, - additionalProps: { itemId, id, label }, - ownerState: { itemId, label }, - }); - - return {children}; -} - /** * * Demos: @@ -109,31 +89,15 @@ const RichTreeView = React.forwardRef(function RichTreeView< ownerState: props as RichTreeViewProps, }); - const itemsToRender = instance.getItemsToRender(); - - const renderItem = ({ - label, - itemId, - id, - children, - }: ReturnType[number]) => { - return ( - - {children?.map(renderItem)} - - ); - }; - return ( - {itemsToRender.map(renderItem)} + + + ); }) as RichTreeViewComponent; diff --git a/packages/x-tree-view/src/internals/components/RichTreeViewItems.tsx b/packages/x-tree-view/src/internals/components/RichTreeViewItems.tsx new file mode 100644 index 0000000000000..9fc112bca9a7c --- /dev/null +++ b/packages/x-tree-view/src/internals/components/RichTreeViewItems.tsx @@ -0,0 +1,91 @@ +import * as React from 'react'; +import useSlotProps from '@mui/utils/useSlotProps'; +import { SlotComponentProps } from '@mui/utils'; + +import { TreeItem, TreeItemProps } from '../../TreeItem'; +import { TreeItem2Props } from '../../TreeItem2'; +import { TreeViewItemId } from '../../models'; +import { TreeViewItemToRenderProps } from '../plugins/useTreeViewItems'; + +interface RichTreeViewItemsOwnerState { + itemId: TreeViewItemId; + label: string; +} + +export interface RichTreeViewItemsSlots { + /** + * Custom component for the item. + * @default TreeItem. + */ + item?: React.JSXElementConstructor | React.JSXElementConstructor; +} + +export interface RichTreeViewItemsSlotProps { + item?: SlotComponentProps; +} + +export interface RichTreeViewItemsProps { + itemsToRender: TreeViewItemToRenderProps[]; + /** + * Overridable component slots. + * @default {} + */ + slots?: RichTreeViewItemsSlots; + /** + * The props used for each component slot. + * @default {} + */ + slotProps?: RichTreeViewItemsSlotProps; +} + +function WrappedTreeItem({ + slots, + slotProps, + label, + id, + itemId, + itemsToRender, +}: Pick & + Pick & { + label: string; + isContentHidden?: boolean; + itemsToRender: TreeViewItemToRenderProps[] | undefined; + }) { + const Item = slots?.item ?? TreeItem; + const { ownerState, ...itemProps } = useSlotProps({ + elementType: Item, + externalSlotProps: slotProps?.item, + additionalProps: { itemId, id, label }, + ownerState: { itemId, label }, + }); + + const children = React.useMemo( + () => + itemsToRender ? ( + + ) : null, + [itemsToRender, slots, slotProps], + ); + + return {children}; +} + +export function RichTreeViewItems(props: RichTreeViewItemsProps) { + const { itemsToRender, slots, slotProps } = props; + + return ( + + {itemsToRender.map((item) => ( + + ))} + + ); +} diff --git a/packages/x-tree-view/src/internals/index.ts b/packages/x-tree-view/src/internals/index.ts index 515113988bab3..6fd119a8ffb92 100644 --- a/packages/x-tree-view/src/internals/index.ts +++ b/packages/x-tree-view/src/internals/index.ts @@ -1,6 +1,8 @@ export { useTreeView } from './useTreeView'; export { TreeViewProvider, useTreeViewContext } from './TreeViewProvider'; +export { RichTreeViewItems } from './components/RichTreeViewItems'; + export { unstable_resetCleanupTracking } from './hooks/useInstanceEventHandler'; export type { diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewItems/index.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewItems/index.ts index b98e025875365..2ab1e49635281 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewItems/index.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewItems/index.ts @@ -4,5 +4,6 @@ export type { UseTreeViewItemsParameters, UseTreeViewItemsDefaultizedParameters, UseTreeViewItemsState, + TreeViewItemToRenderProps, } from './useTreeViewItems.types'; export { buildSiblingIndexes, TREE_VIEW_ROOT_PARENT_ID } from './useTreeViewItems.utils'; diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.types.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.types.ts index 956f8861f4c47..93761ead527e8 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.types.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.types.ts @@ -2,11 +2,11 @@ import * as React from 'react'; import { TreeViewItemMeta, DefaultizedProps, TreeViewPluginSignature } from '../../models'; import { TreeViewBaseItem, TreeViewItemId } from '../../../models'; -interface TreeViewItemProps { +export interface TreeViewItemToRenderProps { label: string; itemId: string; id: string | undefined; - children?: TreeViewItemProps[]; + children?: TreeViewItemToRenderProps[]; } export interface UseTreeViewItemsPublicAPI { @@ -33,7 +33,7 @@ export interface UseTreeViewItemsPublicAPI { getItemOrderedChildrenIds: (itemId: TreeViewItemId | null) => TreeViewItemId[]; /** * Get all the items in the same format as provided by `props.items`. - * @returns {TreeViewItemProps[]} The items in the tree. + * @returns {TreeViewItemToRenderProps[]} The items in the tree. */ getItemTree: () => TreeViewBaseItem[]; } @@ -49,10 +49,10 @@ export interface UseTreeViewItemsInstance extends UseTreeViewItems /** * Get the item that should be rendered. * This method is only used on Rich Tree View components. - * Check the `TreeViewItemProps` type for more information. - * @returns {TreeViewItemProps[]} The items to render. + * Check the `TreeViewItemToRenderProps` type for more information. + * @returns {TreeViewItemToRenderProps[]} The items to render. */ - getItemsToRender: () => TreeViewItemProps[]; + getItemsToRender: () => TreeViewItemToRenderProps[]; /** * Check if a given item is disabled. * An item is disabled if it was marked as disabled or if one of its ancestors is disabled.