Skip to content

Commit

Permalink
[TreeView] Refacto the tree view internals to prepare for headless API
Browse files Browse the repository at this point in the history
  • Loading branch information
flaviendelangle committed May 30, 2024
1 parent ab83d35 commit cd5aaad
Show file tree
Hide file tree
Showing 39 changed files with 495 additions and 430 deletions.
25 changes: 10 additions & 15 deletions docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ import { useSlotProps } from '@mui/base/utils';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';

import { RichTreeViewRoot } from '@mui/x-tree-view/RichTreeView';
import { TreeItem } from '@mui/x-tree-view/TreeItem';
import {
DEFAULT_TREE_VIEW_PLUGINS,
extractPluginParamsFromProps,
useTreeView,
TreeViewProvider,
} from '@mui/x-tree-view/internals';
RichTreeViewRoot,
RICH_TREE_VIEW_PLUGINS,
} from '@mui/x-tree-view/RichTreeView';
import { TreeItem } from '@mui/x-tree-view/TreeItem';
import { useTreeView, TreeViewProvider } from '@mui/x-tree-view/internals';

const useTreeViewLogExpanded = ({ params, models }) => {
const expandedStr = JSON.stringify(models.expandedItems.value);
Expand All @@ -36,23 +34,20 @@ useTreeViewLogExpanded.params = {
logMessage: true,
};

const TREE_VIEW_PLUGINS = [...DEFAULT_TREE_VIEW_PLUGINS, useTreeViewLogExpanded];
const TREE_VIEW_PLUGINS = [...RICH_TREE_VIEW_PLUGINS, useTreeViewLogExpanded];

function TreeView(inProps) {
const themeProps = useThemeProps({ props: inProps, name: 'HeadlessTreeView' });
const ownerState = themeProps;
const props = useThemeProps({ props: inProps, name: 'HeadlessTreeView' });
const ownerState = props;

const { pluginParams, otherProps } = extractPluginParamsFromProps({
props: themeProps,
const { getRootProps, contextValue, instance } = useTreeView({
plugins: TREE_VIEW_PLUGINS,
props,
});

const { getRootProps, contextValue, instance } = useTreeView(pluginParams);

const rootProps = useSlotProps({
elementType: RichTreeViewRoot,
externalSlotProps: {},
externalForwardedProps: otherProps,
getSlotProps: getRootProps,
ownerState,
});
Expand Down
45 changes: 20 additions & 25 deletions docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
import * as React from 'react';
import { useThemeProps } from '@mui/material/styles';
import { Theme, useThemeProps } from '@mui/material/styles';
import { useSlotProps } from '@mui/base/utils';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { TreeViewBaseItem } from '@mui/x-tree-view/models';
import {
RichTreeViewPropsBase,
RichTreeViewRoot,
RICH_TREE_VIEW_PLUGINS,
RichTreeViewPluginParameters,
} from '@mui/x-tree-view/RichTreeView';
import { TreeItem } from '@mui/x-tree-view/TreeItem';
import {
UseTreeViewExpansionSignature,
TreeViewPlugin,
TreeViewPluginSignature,
DefaultTreeViewPluginParameters,
DefaultTreeViewPluginSlotProps,
DefaultTreeViewPluginSlots,
DEFAULT_TREE_VIEW_PLUGINS,
extractPluginParamsFromProps,
useTreeView,
TreeViewProvider,
ConvertPluginsIntoSignatures,
TreeViewPublicAPI,
} from '@mui/x-tree-view/internals';
import { SxProps } from '@mui/system';

interface TreeViewLogExpandedParameters {
areLogsEnabled?: boolean;
Expand Down Expand Up @@ -68,40 +67,36 @@ useTreeViewLogExpanded.params = {
};

export interface TreeViewProps<R extends {}, Multiple extends boolean | undefined>
extends DefaultTreeViewPluginParameters<R, Multiple>,
TreeViewLogExpandedParameters,
RichTreeViewPropsBase {
slots?: DefaultTreeViewPluginSlots;
slotProps?: DefaultTreeViewPluginSlotProps;
extends RichTreeViewPluginParameters<R, Multiple>,
TreeViewLogExpandedParameters {
sx?: SxProps<Theme>;
apiRef?: React.MutableRefObject<TreeViewPublicAPI<TreeViewSignatures> | undefined>;
}

const TREE_VIEW_PLUGINS = [
...DEFAULT_TREE_VIEW_PLUGINS,
...RICH_TREE_VIEW_PLUGINS,
useTreeViewLogExpanded,
] as const;

type TreeViewSignatures = ConvertPluginsIntoSignatures<typeof TREE_VIEW_PLUGINS>;

function TreeView<R extends {}, Multiple extends boolean | undefined>(
inProps: TreeViewProps<R, Multiple>,
) {
const themeProps = useThemeProps({ props: inProps, name: 'HeadlessTreeView' });
const ownerState = themeProps as TreeViewProps<any, any>;

const { pluginParams, otherProps } = extractPluginParamsFromProps<
typeof TREE_VIEW_PLUGINS,
DefaultTreeViewPluginSlots,
DefaultTreeViewPluginSlotProps,
TreeViewProps<R, Multiple>
const props = useThemeProps({ props: inProps, name: 'HeadlessTreeView' });
const ownerState = props as TreeViewProps<any, any>;

const { getRootProps, contextValue, instance } = useTreeView<
TreeViewSignatures,
typeof props
>({
props: themeProps,
plugins: TREE_VIEW_PLUGINS,
props,
});

const { getRootProps, contextValue, instance } = useTreeView(pluginParams);

const rootProps = useSlotProps({
elementType: RichTreeViewRoot,
externalSlotProps: {},
externalForwardedProps: otherProps,
getSlotProps: getRootProps,
ownerState,
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import * as React from 'react';
import {
ConvertPluginsIntoSignatures,
MergeSignaturesProperty,
TreeViewPublicAPI,
useTreeViewId,
UseTreeViewIdParameters,
useTreeViewItems,
Expand All @@ -12,11 +16,9 @@ import {
useTreeViewKeyboardNavigation,
useTreeViewIcons,
UseTreeViewIconsParameters,
ConvertPluginsIntoSignatures,
MergePluginsProperty,
} from '@mui/x-tree-view/internals';

export const DEFAULT_TREE_VIEW_PRO_PLUGINS = [
export const RICH_TREE_VIEW_PRO_PLUGINS = [
useTreeViewId,
useTreeViewItems,
useTreeViewExpansion,
Expand All @@ -26,27 +28,28 @@ export const DEFAULT_TREE_VIEW_PRO_PLUGINS = [
useTreeViewIcons,
] as const;

export type DefaultTreeViewProPlugins = ConvertPluginsIntoSignatures<
typeof DEFAULT_TREE_VIEW_PRO_PLUGINS
export type RichTreeViewProSignatures = ConvertPluginsIntoSignatures<
typeof RICH_TREE_VIEW_PRO_PLUGINS
>;

export type DefaultTreeViewProPluginSlots = MergePluginsProperty<
DefaultTreeViewProPlugins,
export type RichTreeViewProPluginSlots = MergeSignaturesProperty<
RichTreeViewProSignatures,
'slots'
>;

export type DefaultTreeViewProPluginSlotProps = MergePluginsProperty<
DefaultTreeViewProPlugins,
export type RichTreeViewProPluginSlotProps = MergeSignaturesProperty<
RichTreeViewProSignatures,
'slotProps'
>;

// We can't infer this type from the plugin, otherwise we would lose the generics.
export interface DefaultTreeViewProPluginParameters<
R extends {},
Multiple extends boolean | undefined,
> extends UseTreeViewIdParameters,
export interface RichTreeViewProPluginParameters<R extends {}, Multiple extends boolean | undefined>
extends UseTreeViewIdParameters,
UseTreeViewItemsParameters<R>,
UseTreeViewExpansionParameters,
UseTreeViewFocusParameters,
UseTreeViewSelectionParameters<Multiple>,
UseTreeViewIconsParameters {}

export type RichTreeViewProApiRef = React.MutableRefObject<
TreeViewPublicAPI<RichTreeViewProSignatures> | undefined
>;
31 changes: 9 additions & 22 deletions packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,10 @@ import composeClasses from '@mui/utils/composeClasses';
import { useLicenseVerifier, Watermark } from '@mui/x-license';
import { useSlotProps } from '@mui/base/utils';
import { TreeItem, TreeItemProps } from '@mui/x-tree-view/TreeItem';
import {
useTreeView,
TreeViewProvider,
buildWarning,
extractPluginParamsFromProps,
} from '@mui/x-tree-view/internals';
import { useTreeView, TreeViewProvider, buildWarning } from '@mui/x-tree-view/internals';
import { getRichTreeViewProUtilityClass } from './richTreeViewProClasses';
import {
RichTreeViewProProps,
RichTreeViewProSlotProps,
RichTreeViewProSlots,
} from './RichTreeViewPro.types';
import { DEFAULT_TREE_VIEW_PRO_PLUGINS } from '../internals/plugins';
import { RichTreeViewProProps } from './RichTreeViewPro.types';
import { RICH_TREE_VIEW_PRO_PLUGINS, RichTreeViewProSignatures } from './RichTreeViewPro.plugins';
import { getReleaseInfo } from '../internals/utils/releaseInfo';

const useUtilityClasses = <R extends {}, Multiple extends boolean | undefined>(
Expand Down Expand Up @@ -99,26 +90,22 @@ const RichTreeViewPro = React.forwardRef(function RichTreeViewPro<
}
}

const { pluginParams, slots, slotProps, otherProps } = extractPluginParamsFromProps<
typeof DEFAULT_TREE_VIEW_PRO_PLUGINS,
RichTreeViewProSlots,
RichTreeViewProSlotProps<R, Multiple>,
RichTreeViewProProps<R, Multiple>
const { getRootProps, contextValue, instance } = useTreeView<
RichTreeViewProSignatures,
typeof props
>({
props,
plugins: DEFAULT_TREE_VIEW_PRO_PLUGINS,
plugins: RICH_TREE_VIEW_PRO_PLUGINS,
rootRef: ref,
props,
});

const { getRootProps, contextValue, instance } = useTreeView(pluginParams);

const { slots, slotProps } = props;
const classes = useUtilityClasses(props);

const Root = slots?.root ?? RichTreeViewProRoot;
const rootProps = useSlotProps({
elementType: Root,
externalSlotProps: slotProps?.root,
externalForwardedProps: otherProps,
className: classes.root,
getSlotProps: getRootProps,
ownerState: props as RichTreeViewProProps<any, any>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@ import { SlotComponentProps } from '@mui/base/utils';
import { TreeItem, TreeItemProps } from '@mui/x-tree-view/TreeItem';
import { TreeItem2Props } from '@mui/x-tree-view/TreeItem2';
import { TreeViewItemId } from '@mui/x-tree-view/models';
import { TreeViewPublicAPI, TreeViewExperimentalFeatures } from '@mui/x-tree-view/internals';
import { TreeViewExperimentalFeatures } from '@mui/x-tree-view/internals';
import { RichTreeViewProClasses } from './richTreeViewProClasses';
import {
DefaultTreeViewProPluginParameters,
DefaultTreeViewProPluginSlotProps,
DefaultTreeViewProPluginSlots,
DefaultTreeViewProPlugins,
} from '../internals/plugins/defaultPlugins';
RichTreeViewProSignatures,
RichTreeViewProPluginParameters,
RichTreeViewProPluginSlotProps,
RichTreeViewProPluginSlots,
RichTreeViewProApiRef,
} from './RichTreeViewPro.plugins';

interface RichTreeViewItemProSlotOwnerState {
itemId: TreeViewItemId;
label: string;
}

export interface RichTreeViewProSlots extends DefaultTreeViewProPluginSlots {
export interface RichTreeViewProSlots extends RichTreeViewProPluginSlots {
/**
* Element rendered at the root.
* @default RichTreeViewProRoot
Expand All @@ -33,15 +34,11 @@ export interface RichTreeViewProSlots extends DefaultTreeViewProPluginSlots {
}

export interface RichTreeViewProSlotProps<R extends {}, Multiple extends boolean | undefined>
extends DefaultTreeViewProPluginSlotProps {
extends RichTreeViewProPluginSlotProps {
root?: SlotComponentProps<'ul', {}, RichTreeViewProProps<R, Multiple>>;
item?: SlotComponentProps<typeof TreeItem, {}, RichTreeViewItemProSlotOwnerState>;
}

export type RichTreeViewProApiRef = React.MutableRefObject<
TreeViewPublicAPI<DefaultTreeViewProPlugins> | undefined
>;

export interface RichTreeViewProPropsBase extends React.HTMLAttributes<HTMLUListElement> {
className?: string;
/**
Expand All @@ -55,7 +52,7 @@ export interface RichTreeViewProPropsBase extends React.HTMLAttributes<HTMLUList
}

export interface RichTreeViewProProps<R extends {}, Multiple extends boolean | undefined>
extends DefaultTreeViewProPluginParameters<R, Multiple>,
extends RichTreeViewProPluginParameters<R, Multiple>,
RichTreeViewProPropsBase {
/**
* Overridable component slots.
Expand All @@ -76,5 +73,5 @@ export interface RichTreeViewProProps<R extends {}, Multiple extends boolean | u
* 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.
*/
experimentalFeatures?: TreeViewExperimentalFeatures<DefaultTreeViewProPlugins>;
experimentalFeatures?: TreeViewExperimentalFeatures<RichTreeViewProSignatures>;
}
2 changes: 0 additions & 2 deletions packages/x-tree-view-pro/src/internals/plugins/index.ts

This file was deleted.

60 changes: 60 additions & 0 deletions packages/x-tree-view/src/RichTreeView/RichTreeView.plugins.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import * as React from 'react';
import {
ConvertPluginsIntoSignatures,
MergeSignaturesProperty,
TreeViewPublicAPI,
} from '../internals/models';
import { useTreeViewId, UseTreeViewIdParameters } from '../internals/plugins/useTreeViewId';
import {
useTreeViewItems,
UseTreeViewItemsParameters,
} from '../internals/plugins/useTreeViewItems';
import {
useTreeViewExpansion,
UseTreeViewExpansionParameters,
} from '../internals/plugins/useTreeViewExpansion';
import {
useTreeViewSelection,
UseTreeViewSelectionParameters,
} from '../internals/plugins/useTreeViewSelection';
import {
useTreeViewFocus,
UseTreeViewFocusParameters,
} from '../internals/plugins/useTreeViewFocus';
import { useTreeViewKeyboardNavigation } from '../internals/plugins/useTreeViewKeyboardNavigation';
import {
useTreeViewIcons,
UseTreeViewIconsParameters,
} from '../internals/plugins/useTreeViewIcons';

export const RICH_TREE_VIEW_PLUGINS = [
useTreeViewId,
useTreeViewItems,
useTreeViewExpansion,
useTreeViewSelection,
useTreeViewFocus,
useTreeViewKeyboardNavigation,
useTreeViewIcons,
] as const;

export type RichTreeViewSignatures = ConvertPluginsIntoSignatures<typeof RICH_TREE_VIEW_PLUGINS>;

export type RichTreeViewPluginSlots = MergeSignaturesProperty<RichTreeViewSignatures, 'slots'>;

export type RichTreeViewPluginSlotProps = MergeSignaturesProperty<
RichTreeViewSignatures,
'slotProps'
>;

// We can't infer this type from the plugin, otherwise we would lose the generics.
export interface RichTreeViewPluginParameters<R extends {}, Multiple extends boolean | undefined>
extends UseTreeViewIdParameters,
UseTreeViewItemsParameters<R>,
UseTreeViewExpansionParameters,
UseTreeViewFocusParameters,
UseTreeViewSelectionParameters<Multiple>,
UseTreeViewIconsParameters {}

export type RichTreeViewApiRef = React.MutableRefObject<
TreeViewPublicAPI<RichTreeViewSignatures> | undefined
>;
Loading

0 comments on commit cd5aaad

Please sign in to comment.