From 0bc6f8a73545f24c2b0b5c65d82e299b70a93794 Mon Sep 17 00:00:00 2001 From: delangle Date: Wed, 5 Jun 2024 13:32:54 +0200 Subject: [PATCH 1/8] [TreeView] Improve TypeScript for plugins --- .../headless/LogExpandedItems.tsx | 2 +- .../rich-tree-view/headless/headless.md | 2 +- .../src/RichTreeViewPro/RichTreeViewPro.tsx | 2 +- .../src/internals/plugins/defaultPlugins.ts | 6 +-- .../src/RichTreeView/RichTreeView.tsx | 2 +- .../src/RichTreeView/RichTreeView.types.ts | 6 +-- .../src/SimpleTreeView/SimpleTreeView.tsx | 2 +- .../x-tree-view/src/TreeItem/TreeItem.tsx | 4 +- .../src/TreeItem/useTreeItemState.ts | 4 +- .../useTreeItem2Utils/useTreeItem2Utils.tsx | 4 +- .../src/hooks/useTreeViewApiRef.tsx | 7 ++-- .../TreeViewProvider/TreeViewProvider.tsx | 4 +- .../TreeViewProvider.types.ts | 18 ++++---- .../TreeViewProvider/useTreeViewContext.ts | 4 +- .../src/internals/corePlugins/corePlugins.ts | 4 +- packages/x-tree-view/src/internals/index.ts | 4 +- .../src/internals/models/helpers.ts | 41 +++++++++++-------- .../src/internals/models/plugin.ts | 14 +++---- .../src/internals/models/treeView.ts | 8 ++-- .../src/internals/plugins/defaultPlugins.ts | 15 ++++--- .../src/internals/plugins/index.ts | 2 +- .../src/internals/useTreeView/useTreeView.ts | 32 +++++++++------ .../useTreeView/useTreeView.types.ts | 35 ++++++++-------- .../useTreeView/useTreeViewModels.ts | 8 ++-- .../utils/extractPluginParamsFromProps.ts | 11 ++--- .../src/useTreeItem2/useTreeItem2.ts | 10 +++-- .../src/useTreeItem2/useTreeItem2.types.ts | 6 ++- .../describeTreeView/describeTreeView.tsx | 22 +++++----- .../describeTreeView.types.ts | 31 +++++++------- 29 files changed, 167 insertions(+), 143 deletions(-) diff --git a/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx b/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx index 75c05b7c6b9ab..554ebb231a2da 100644 --- a/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx +++ b/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx @@ -97,7 +97,7 @@ function TreeView( plugins: TREE_VIEW_PLUGINS, }); - const { getRootProps, contextValue, instance } = useTreeView(pluginParams); + const { getRootProps, contextValue, instance } = useTreeView(pluginParams); const rootProps = useSlotProps({ elementType: RichTreeViewRoot, diff --git a/docs/data/tree-view/rich-tree-view/headless/headless.md b/docs/data/tree-view/rich-tree-view/headless/headless.md index 99955f9962855..86ca7bfccbc56 100644 --- a/docs/data/tree-view/rich-tree-view/headless/headless.md +++ b/docs/data/tree-view/rich-tree-view/headless/headless.md @@ -237,7 +237,7 @@ function useTreeItemState(itemId: string) { const { customPlugin, // ...other elements returned by the context - } = useTreeViewContext(); + } = useTreeViewContext(); // ...rest of the `useTreeItemState` hook content diff --git a/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.tsx b/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.tsx index c2699d8d82c26..fc3e56b02737d 100644 --- a/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.tsx +++ b/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.tsx @@ -110,7 +110,7 @@ const RichTreeViewPro = React.forwardRef(function RichTreeViewPro< rootRef: ref, }); - const { getRootProps, contextValue, instance } = useTreeView(pluginParams); + const { getRootProps, contextValue, instance } = useTreeView(pluginParams); const classes = useUtilityClasses(props); diff --git a/packages/x-tree-view-pro/src/internals/plugins/defaultPlugins.ts b/packages/x-tree-view-pro/src/internals/plugins/defaultPlugins.ts index 8f12846c5043a..0f43e55f3a7ce 100644 --- a/packages/x-tree-view-pro/src/internals/plugins/defaultPlugins.ts +++ b/packages/x-tree-view-pro/src/internals/plugins/defaultPlugins.ts @@ -13,7 +13,7 @@ import { useTreeViewIcons, UseTreeViewIconsParameters, ConvertPluginsIntoSignatures, - MergePluginsProperty, + MergeSignaturesProperty, } from '@mui/x-tree-view/internals'; export const DEFAULT_TREE_VIEW_PRO_PLUGINS = [ @@ -30,12 +30,12 @@ export type DefaultTreeViewProPlugins = ConvertPluginsIntoSignatures< typeof DEFAULT_TREE_VIEW_PRO_PLUGINS >; -export type DefaultTreeViewProPluginSlots = MergePluginsProperty< +export type DefaultTreeViewProPluginSlots = MergeSignaturesProperty< DefaultTreeViewProPlugins, 'slots' >; -export type DefaultTreeViewProPluginSlotProps = MergePluginsProperty< +export type DefaultTreeViewProPluginSlotProps = MergeSignaturesProperty< DefaultTreeViewProPlugins, 'slotProps' >; diff --git a/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx b/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx index 15cea0fe567f1..4ae7a15a2a427 100644 --- a/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx +++ b/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx @@ -99,7 +99,7 @@ const RichTreeView = React.forwardRef(function RichTreeView< rootRef: ref, }); - const { getRootProps, contextValue, instance } = useTreeView(pluginParams); + const { getRootProps, contextValue, instance } = useTreeView(pluginParams); const classes = useUtilityClasses(props); diff --git a/packages/x-tree-view/src/RichTreeView/RichTreeView.types.ts b/packages/x-tree-view/src/RichTreeView/RichTreeView.types.ts index 974a665b69a46..9b71ae3c7a579 100644 --- a/packages/x-tree-view/src/RichTreeView/RichTreeView.types.ts +++ b/packages/x-tree-view/src/RichTreeView/RichTreeView.types.ts @@ -7,7 +7,7 @@ import { DefaultTreeViewPluginParameters, DefaultTreeViewPluginSlotProps, DefaultTreeViewPluginSlots, - DefaultTreeViewPlugins, + DefaultTreeViewPluginSignatures, } from '../internals/plugins/defaultPlugins'; import { TreeItemProps } from '../TreeItem'; import { TreeItem2Props } from '../TreeItem2'; @@ -47,7 +47,7 @@ export interface RichTreeViewSlotProps | undefined + TreeViewPublicAPI | undefined >; export interface RichTreeViewPropsBase extends React.HTMLAttributes { @@ -84,5 +84,5 @@ export interface RichTreeViewProps; + experimentalFeatures?: TreeViewExperimentalFeatures; } diff --git a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx index 297792cd511cf..83deccd1fc5b5 100644 --- a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx +++ b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx @@ -84,7 +84,7 @@ const SimpleTreeView = React.forwardRef(function SimpleTreeView< rootRef: ref, }); - const { getRootProps, contextValue } = useTreeView(pluginParams); + const { getRootProps, contextValue } = useTreeView(pluginParams); const classes = useUtilityClasses(props); diff --git a/packages/x-tree-view/src/TreeItem/TreeItem.tsx b/packages/x-tree-view/src/TreeItem/TreeItem.tsx index a330de1af8d98..853f0371cffaf 100644 --- a/packages/x-tree-view/src/TreeItem/TreeItem.tsx +++ b/packages/x-tree-view/src/TreeItem/TreeItem.tsx @@ -14,7 +14,7 @@ import { TreeItemContent } from './TreeItemContent'; import { treeItemClasses, getTreeItemUtilityClass } from './treeItemClasses'; import { TreeItemOwnerState, TreeItemProps } from './TreeItem.types'; import { useTreeViewContext } from '../internals/TreeViewProvider/useTreeViewContext'; -import { DefaultTreeViewPlugins } from '../internals/plugins'; +import { DefaultTreeViewPluginSignatures } from '../internals/plugins'; import { TreeViewCollapseIcon, TreeViewExpandIcon } from '../icons'; import { TreeItem2Provider } from '../TreeItem2Provider'; import { TreeViewItemDepthContext } from '../internals/TreeViewItemDepthContext'; @@ -183,7 +183,7 @@ export const TreeItem = React.forwardRef(function TreeItem( disabledItemsFocusable, indentationAtItemLevel, instance, - } = useTreeViewContext(); + } = useTreeViewContext(); const depthContext = React.useContext(TreeViewItemDepthContext); const props = useThemeProps({ props: inProps, name: 'MuiTreeItem' }); diff --git a/packages/x-tree-view/src/TreeItem/useTreeItemState.ts b/packages/x-tree-view/src/TreeItem/useTreeItemState.ts index f429ac981d20b..0da618865f953 100644 --- a/packages/x-tree-view/src/TreeItem/useTreeItemState.ts +++ b/packages/x-tree-view/src/TreeItem/useTreeItemState.ts @@ -1,12 +1,12 @@ import * as React from 'react'; import { useTreeViewContext } from '../internals/TreeViewProvider/useTreeViewContext'; -import { DefaultTreeViewPlugins } from '../internals/plugins'; +import { DefaultTreeViewPluginSignatures } from '../internals/plugins'; export function useTreeItemState(itemId: string) { const { instance, selection: { multiSelect, checkboxSelection, disableSelection }, - } = useTreeViewContext(); + } = useTreeViewContext(); const expandable = instance.isItemExpandable(itemId); const expanded = instance.isItemExpanded(itemId); diff --git a/packages/x-tree-view/src/hooks/useTreeItem2Utils/useTreeItem2Utils.tsx b/packages/x-tree-view/src/hooks/useTreeItem2Utils/useTreeItem2Utils.tsx index 911322d477666..deff0a1d89e5c 100644 --- a/packages/x-tree-view/src/hooks/useTreeItem2Utils/useTreeItem2Utils.tsx +++ b/packages/x-tree-view/src/hooks/useTreeItem2Utils/useTreeItem2Utils.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { useTreeViewContext } from '../../internals/TreeViewProvider/useTreeViewContext'; -import { DefaultTreeViewPlugins } from '../../internals/plugins'; +import { DefaultTreeViewPluginSignatures } from '../../internals/plugins'; import type { UseTreeItem2Status } from '../../useTreeItem2'; interface UseTreeItem2Interactions { @@ -31,7 +31,7 @@ export const useTreeItem2Utils = ({ const { instance, selection: { multiSelect }, - } = useTreeViewContext(); + } = useTreeViewContext(); const status: UseTreeItem2Status = { expandable: isItemExpandable(children), diff --git a/packages/x-tree-view/src/hooks/useTreeViewApiRef.tsx b/packages/x-tree-view/src/hooks/useTreeViewApiRef.tsx index 8ef984c577967..b27410f757376 100644 --- a/packages/x-tree-view/src/hooks/useTreeViewApiRef.tsx +++ b/packages/x-tree-view/src/hooks/useTreeViewApiRef.tsx @@ -1,10 +1,11 @@ import * as React from 'react'; import { TreeViewAnyPluginSignature, TreeViewPublicAPI } from '../internals/models'; -import { DefaultTreeViewPlugins } from '../internals'; +import { DefaultTreeViewPluginSignatures } from '../internals'; /** * Hook that instantiates a [[TreeViewApiRef]]. */ export const useTreeViewApiRef = < - TPlugins extends readonly TreeViewAnyPluginSignature[] = DefaultTreeViewPlugins, ->() => React.useRef(undefined) as React.MutableRefObject | undefined>; + TSignatures extends readonly TreeViewAnyPluginSignature[] = DefaultTreeViewPluginSignatures, +>() => + React.useRef(undefined) as React.MutableRefObject | undefined>; diff --git a/packages/x-tree-view/src/internals/TreeViewProvider/TreeViewProvider.tsx b/packages/x-tree-view/src/internals/TreeViewProvider/TreeViewProvider.tsx index de246ec61ea3c..d855127369500 100644 --- a/packages/x-tree-view/src/internals/TreeViewProvider/TreeViewProvider.tsx +++ b/packages/x-tree-view/src/internals/TreeViewProvider/TreeViewProvider.tsx @@ -8,8 +8,8 @@ import { TreeViewAnyPluginSignature } from '../models'; * * @ignore - do not document. */ -export function TreeViewProvider( - props: TreeViewProviderProps, +export function TreeViewProvider( + props: TreeViewProviderProps, ) { const { value, children } = props; diff --git a/packages/x-tree-view/src/internals/TreeViewProvider/TreeViewProvider.types.ts b/packages/x-tree-view/src/internals/TreeViewProvider/TreeViewProvider.types.ts index 2d42554e5d8d5..06a056725d520 100644 --- a/packages/x-tree-view/src/internals/TreeViewProvider/TreeViewProvider.types.ts +++ b/packages/x-tree-view/src/internals/TreeViewProvider/TreeViewProvider.types.ts @@ -1,6 +1,6 @@ import * as React from 'react'; import { - MergePluginsProperty, + MergeSignaturesProperty, TreeItemWrapper, TreeRootWrapper, TreeViewAnyPluginSignature, @@ -9,17 +9,17 @@ import { TreeViewPublicAPI, } from '../models'; -export type TreeViewContextValue = - MergePluginsProperty & { - instance: TreeViewInstance; - publicAPI: TreeViewPublicAPI; +export type TreeViewContextValue = + MergeSignaturesProperty & { + instance: TreeViewInstance; + publicAPI: TreeViewPublicAPI; rootRef: React.RefObject; - wrapItem: TreeItemWrapper; - wrapRoot: TreeRootWrapper; + wrapItem: TreeItemWrapper; + wrapRoot: TreeRootWrapper; runItemPlugins: (props: TProps) => Required; }; -export interface TreeViewProviderProps { - value: TreeViewContextValue; +export interface TreeViewProviderProps { + value: TreeViewContextValue; children: React.ReactNode; } diff --git a/packages/x-tree-view/src/internals/TreeViewProvider/useTreeViewContext.ts b/packages/x-tree-view/src/internals/TreeViewProvider/useTreeViewContext.ts index 8da83b9b56ebb..62fbce3ad7397 100644 --- a/packages/x-tree-view/src/internals/TreeViewProvider/useTreeViewContext.ts +++ b/packages/x-tree-view/src/internals/TreeViewProvider/useTreeViewContext.ts @@ -3,8 +3,8 @@ import { TreeViewAnyPluginSignature } from '../models'; import { TreeViewContext } from './TreeViewContext'; import { TreeViewContextValue } from './TreeViewProvider.types'; -export const useTreeViewContext = () => { - const context = React.useContext(TreeViewContext) as TreeViewContextValue; +export const useTreeViewContext = () => { + const context = React.useContext(TreeViewContext) as TreeViewContextValue; if (context == null) { throw new Error( [ diff --git a/packages/x-tree-view/src/internals/corePlugins/corePlugins.ts b/packages/x-tree-view/src/internals/corePlugins/corePlugins.ts index feb26ae78c804..caf26f546d7a3 100644 --- a/packages/x-tree-view/src/internals/corePlugins/corePlugins.ts +++ b/packages/x-tree-view/src/internals/corePlugins/corePlugins.ts @@ -1,5 +1,5 @@ import { useTreeViewInstanceEvents } from './useTreeViewInstanceEvents'; -import { ConvertPluginsIntoSignatures, MergePlugins } from '../models'; +import { ConvertPluginsIntoSignatures, MergePluginsSignature } from '../models'; /** * Internal plugins that create the tools used by the other plugins. @@ -7,6 +7,6 @@ import { ConvertPluginsIntoSignatures, MergePlugins } from '../models'; */ export const TREE_VIEW_CORE_PLUGINS = [useTreeViewInstanceEvents] as const; -export type TreeViewCorePluginsSignature = MergePlugins< +export type TreeViewCorePluginsSignature = MergePluginsSignature< ConvertPluginsIntoSignatures >; diff --git a/packages/x-tree-view/src/internals/index.ts b/packages/x-tree-view/src/internals/index.ts index 9500d00e37f34..752818a77fa09 100644 --- a/packages/x-tree-view/src/internals/index.ts +++ b/packages/x-tree-view/src/internals/index.ts @@ -7,7 +7,7 @@ export type { TreeViewPlugin, TreeViewPluginSignature, ConvertPluginsIntoSignatures, - MergePluginsProperty, + MergeSignaturesProperty, TreeViewPublicAPI, TreeViewExperimentalFeatures, } from './models'; @@ -15,7 +15,7 @@ export type { // Plugins export { DEFAULT_TREE_VIEW_PLUGINS } from './plugins/defaultPlugins'; export type { - DefaultTreeViewPlugins, + DefaultTreeViewPluginSignatures, DefaultTreeViewPluginSlots, DefaultTreeViewPluginSlotProps, } from './plugins/defaultPlugins'; diff --git a/packages/x-tree-view/src/internals/models/helpers.ts b/packages/x-tree-view/src/internals/models/helpers.ts index d8b259e45f467..e2268dd92783e 100644 --- a/packages/x-tree-view/src/internals/models/helpers.ts +++ b/packages/x-tree-view/src/internals/models/helpers.ts @@ -22,12 +22,12 @@ export type OptionalIfEmpty = keyof B extends never ? Partial> : Record; -export type MergePluginsProperty< - TPlugins extends readonly any[], +export type MergeSignaturesProperty< + TSignatures extends readonly any[], TProperty extends keyof TreeViewAnyPluginSignature, -> = TPlugins extends readonly [plugin: infer P, ...otherPlugin: infer R] +> = TSignatures extends readonly [plugin: infer P, ...otherPlugin: infer R] ? P extends TreeViewAnyPluginSignature - ? P[TProperty] & MergePluginsProperty + ? P[TProperty] & MergeSignaturesProperty : {} : {}; @@ -38,17 +38,24 @@ export type ConvertPluginsIntoSignatures = : ConvertPluginsIntoSignatures : []; -export interface MergePlugins { - state: MergePluginsProperty; - instance: MergePluginsProperty; - publicAPI: MergePluginsProperty; - params: MergePluginsProperty; - defaultizedParams: MergePluginsProperty; - dependantPlugins: MergePluginsProperty; - contextValue: MergePluginsProperty; - slots: MergePluginsProperty; - slotProps: MergePluginsProperty; - events: MergePluginsProperty; - models: MergePluginsProperty; - experimentalFeatures: MergePluginsProperty; +export type ConvertSignaturesIntoPlugins = + TSignatures extends readonly [plugin: infer S, ...otherPlugin: infer R] + ? S extends TreeViewAnyPluginSignature + ? [TreeViewPlugin, ...ConvertSignaturesIntoPlugins] + : ConvertSignaturesIntoPlugins + : []; + +export interface MergePluginsSignature { + state: MergeSignaturesProperty; + instance: MergeSignaturesProperty; + publicAPI: MergeSignaturesProperty; + params: MergeSignaturesProperty; + defaultizedParams: MergeSignaturesProperty; + dependantPlugins: MergeSignaturesProperty; + contextValue: MergeSignaturesProperty; + slots: MergeSignaturesProperty; + slotProps: MergeSignaturesProperty; + events: MergeSignaturesProperty; + models: MergeSignaturesProperty; + experimentalFeatures: MergeSignaturesProperty; } diff --git a/packages/x-tree-view/src/internals/models/plugin.ts b/packages/x-tree-view/src/internals/models/plugin.ts index 0d85c8b61754d..a451c03ad0e9e 100644 --- a/packages/x-tree-view/src/internals/models/plugin.ts +++ b/packages/x-tree-view/src/internals/models/plugin.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { EventHandlers } from '@mui/base/utils'; import { TreeViewExperimentalFeatures, TreeViewInstance, TreeViewModel } from './treeView'; -import type { MergePluginsProperty, OptionalIfEmpty } from './helpers'; +import type { MergeSignaturesProperty, OptionalIfEmpty } from './helpers'; import { TreeViewEventLookupElement } from './events'; import type { TreeViewCorePluginsSignature } from '../corePlugins'; import { TreeViewItemId } from '../../models'; @@ -91,15 +91,15 @@ type TreeViewUsedPlugins = [ ]; export type TreeViewUsedParams = - TSignature['params'] & MergePluginsProperty, 'params'>; + TSignature['params'] & MergeSignaturesProperty, 'params'>; type TreeViewUsedDefaultizedParams = TSignature['defaultizedParams'] & - MergePluginsProperty, 'defaultizedParams'>; + MergeSignaturesProperty, 'defaultizedParams'>; export type TreeViewUsedInstance = TSignature['instance'] & - MergePluginsProperty, 'instance'> & { + MergeSignaturesProperty, 'instance'> & { /** * Private property only defined in TypeScript to be able to access the plugin signature from the instance object. */ @@ -107,7 +107,7 @@ export type TreeViewUsedInstance }; type TreeViewUsedState = TSignature['state'] & - MergePluginsProperty, 'state'>; + MergeSignaturesProperty, 'state'>; type TreeViewUsedExperimentalFeatures = TreeViewExperimentalFeatures<[TSignature, ...TSignature['dependantPlugins']]>; @@ -118,10 +118,10 @@ type RemoveSetValue>> = { export type TreeViewUsedModels = TSignature['models'] & - RemoveSetValue, 'models'>>; + RemoveSetValue, 'models'>>; export type TreeViewUsedEvents = - TSignature['events'] & MergePluginsProperty, 'events'>; + TSignature['events'] & MergeSignaturesProperty, 'events'>; export interface TreeViewItemPluginOptions extends TreeViewItemPluginResponse { props: TProps; diff --git a/packages/x-tree-view/src/internals/models/treeView.ts b/packages/x-tree-view/src/internals/models/treeView.ts index 80937aa10b554..c09e681286801 100644 --- a/packages/x-tree-view/src/internals/models/treeView.ts +++ b/packages/x-tree-view/src/internals/models/treeView.ts @@ -1,5 +1,5 @@ import type { TreeViewAnyPluginSignature } from './plugin'; -import type { MergePluginsProperty } from './helpers'; +import type { MergeSignaturesProperty } from './helpers'; export interface TreeViewItemMeta { id: string; @@ -24,11 +24,11 @@ export interface TreeViewModel { } export type TreeViewInstance = - MergePluginsProperty; + MergeSignaturesProperty; export type TreeViewPublicAPI = - MergePluginsProperty; + MergeSignaturesProperty; export type TreeViewExperimentalFeatures< TSignatures extends readonly TreeViewAnyPluginSignature[], -> = { [key in MergePluginsProperty]?: boolean }; +> = { [key in MergeSignaturesProperty]?: boolean }; diff --git a/packages/x-tree-view/src/internals/plugins/defaultPlugins.ts b/packages/x-tree-view/src/internals/plugins/defaultPlugins.ts index f737c5dcc8c9b..c6b376aac744b 100644 --- a/packages/x-tree-view/src/internals/plugins/defaultPlugins.ts +++ b/packages/x-tree-view/src/internals/plugins/defaultPlugins.ts @@ -5,7 +5,7 @@ import { useTreeViewSelection, UseTreeViewSelectionParameters } from './useTreeV import { useTreeViewFocus, UseTreeViewFocusParameters } from './useTreeViewFocus'; import { useTreeViewKeyboardNavigation } from './useTreeViewKeyboardNavigation'; import { useTreeViewIcons, UseTreeViewIconsParameters } from './useTreeViewIcons'; -import { ConvertPluginsIntoSignatures, MergePluginsProperty } from '../models'; +import { ConvertPluginsIntoSignatures, MergeSignaturesProperty } from '../models'; export const DEFAULT_TREE_VIEW_PLUGINS = [ useTreeViewId, @@ -17,12 +17,17 @@ export const DEFAULT_TREE_VIEW_PLUGINS = [ useTreeViewIcons, ] as const; -export type DefaultTreeViewPlugins = ConvertPluginsIntoSignatures; +export type DefaultTreeViewPluginSignatures = ConvertPluginsIntoSignatures< + typeof DEFAULT_TREE_VIEW_PLUGINS +>; -export type DefaultTreeViewPluginSlots = MergePluginsProperty; +export type DefaultTreeViewPluginSlots = MergeSignaturesProperty< + DefaultTreeViewPluginSignatures, + 'slots' +>; -export type DefaultTreeViewPluginSlotProps = MergePluginsProperty< - DefaultTreeViewPlugins, +export type DefaultTreeViewPluginSlotProps = MergeSignaturesProperty< + DefaultTreeViewPluginSignatures, 'slotProps' >; diff --git a/packages/x-tree-view/src/internals/plugins/index.ts b/packages/x-tree-view/src/internals/plugins/index.ts index 8b18e513cab0a..75445ff5057c8 100644 --- a/packages/x-tree-view/src/internals/plugins/index.ts +++ b/packages/x-tree-view/src/internals/plugins/index.ts @@ -1,2 +1,2 @@ export { DEFAULT_TREE_VIEW_PLUGINS } from './defaultPlugins'; -export type { DefaultTreeViewPlugins } from './defaultPlugins'; +export type { DefaultTreeViewPluginSignatures } from './defaultPlugins'; diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts index 464da635e65e2..7f46f809a54fd 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts @@ -6,7 +6,7 @@ import { TreeViewInstance, TreeViewPlugin, ConvertPluginsIntoSignatures, - MergePluginsProperty, + MergeSignaturesProperty, TreeItemWrapper, TreeRootWrapper, TreeViewPublicAPI, @@ -36,11 +36,15 @@ export function useTreeViewApiInitialization( return fallbackPublicApiRef.current; } -export const useTreeView = []>( - inParams: UseTreeViewParameters, -): UseTreeViewReturnValue> => { +export const useTreeView = < + TPlugins extends readonly TreeViewPlugin[], +>( + inParams: UseTreeViewParameters>, +): UseTreeViewReturnValue> => { const plugins = [...TREE_VIEW_CORE_PLUGINS, ...inParams.plugins]; - type Signatures = ConvertPluginsIntoSignatures; + + type TSignatures = ConvertPluginsIntoSignatures + type SignaturesWithCorePlugins = ConvertPluginsIntoSignatures; const params = plugins.reduce((acc, plugin) => { if (plugin.getDefaultizedParams) { @@ -48,24 +52,26 @@ export const useTreeView = ; + }, inParams) as unknown as UseTreeViewDefaultizedParameters; const models = useTreeViewModels( plugins, - params as MergePluginsProperty, + params as MergeSignaturesProperty, ); - const instanceRef = React.useRef>( - {} as TreeViewInstance, + const instanceRef = React.useRef>( + {} as TreeViewInstance, ); - const instance = instanceRef.current as TreeViewInstance; + const instance = instanceRef.current as TreeViewInstance; - const publicAPI = useTreeViewApiInitialization>(inParams.apiRef); + const publicAPI = useTreeViewApiInitialization>( + inParams.apiRef, + ); const innerRootRef: React.RefObject = React.useRef(null); const handleRootRef = useForkRef(innerRootRef, inParams.rootRef); const [state, setState] = React.useState(() => { - const temp = {} as MergePluginsProperty; + const temp = {} as MergeSignaturesProperty; plugins.forEach((plugin) => { if (plugin.getInitialState) { Object.assign( @@ -85,7 +91,7 @@ export const useTreeView = , rootRef: innerRootRef, - } as TreeViewContextValue; + } as TreeViewContextValue; const runPlugin = (plugin: TreeViewPlugin) => { const pluginResponse = plugin({ diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts index a4221edcf5f46..06417ec9c18af 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts @@ -3,36 +3,35 @@ import { EventHandlers } from '@mui/base/utils'; import type { TreeViewContextValue } from '../TreeViewProvider'; import { TreeViewAnyPluginSignature, - TreeViewPlugin, - ConvertPluginsIntoSignatures, - MergePluginsProperty, + ConvertSignaturesIntoPlugins, + MergeSignaturesProperty, TreeViewInstance, TreeViewPublicAPI, TreeViewExperimentalFeatures, } from '../models'; export type UseTreeViewParameters< - TPlugins extends readonly TreeViewPlugin[], -> = UseTreeViewBaseParameters & - MergePluginsProperty, 'params'>; + TSignatures extends readonly TreeViewAnyPluginSignature[], +> = UseTreeViewBaseParameters & + MergeSignaturesProperty; export interface UseTreeViewBaseParameters< - TPlugins extends readonly TreeViewPlugin[], + TSignatures extends readonly TreeViewAnyPluginSignature[], > { apiRef: - | React.MutableRefObject>> + | React.MutableRefObject> | undefined; rootRef?: React.Ref | undefined; - plugins: TPlugins; - slots: MergePluginsProperty, 'slots'>; - slotProps: MergePluginsProperty, 'slotProps'>; - experimentalFeatures: TreeViewExperimentalFeatures>; + plugins: ConvertSignaturesIntoPlugins; + slots: MergeSignaturesProperty; + slotProps: MergeSignaturesProperty; + experimentalFeatures: TreeViewExperimentalFeatures; } export type UseTreeViewDefaultizedParameters< - TPlugins extends readonly TreeViewPlugin[], -> = UseTreeViewBaseParameters & - MergePluginsProperty, 'defaultizedParams'>; + TSignatures extends readonly TreeViewAnyPluginSignature[], +> = UseTreeViewBaseParameters & + MergeSignaturesProperty; export interface UseTreeViewRootSlotProps extends Pick< @@ -42,11 +41,11 @@ export interface UseTreeViewRootSlotProps ref: React.Ref; } -export interface UseTreeViewReturnValue { +export interface UseTreeViewReturnValue { getRootProps: ( otherHandlers?: TOther, ) => UseTreeViewRootSlotProps; rootRef: React.RefCallback | null; - contextValue: TreeViewContextValue; - instance: TreeViewInstance; + contextValue: TreeViewContextValue; + instance: TreeViewInstance; } diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeViewModels.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeViewModels.ts index 4e785b9b08dac..cca7a4f99a365 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeViewModels.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeViewModels.ts @@ -3,7 +3,7 @@ import { TreeViewAnyPluginSignature, TreeViewPlugin, ConvertPluginsIntoSignatures, - MergePluginsProperty, + MergeSignaturesProperty, } from '../models'; /** @@ -14,9 +14,9 @@ export const useTreeViewModels = < TPlugins extends readonly TreeViewPlugin[], >( plugins: TPlugins, - props: MergePluginsProperty, 'defaultizedParams'>, + props: MergeSignaturesProperty, 'defaultizedParams'>, ) => { - type DefaultizedParams = MergePluginsProperty< + type DefaultizedParams = MergeSignaturesProperty< ConvertPluginsIntoSignatures, 'defaultizedParams' >; @@ -65,7 +65,7 @@ export const useTreeViewModels = < }, ]; }), - ) as MergePluginsProperty, 'models'>; + ) as MergeSignaturesProperty, 'models'>; // We know that `modelsRef` do not vary across renders. /* eslint-disable react-hooks/rules-of-hooks, react-hooks/exhaustive-deps */ diff --git a/packages/x-tree-view/src/internals/utils/extractPluginParamsFromProps.ts b/packages/x-tree-view/src/internals/utils/extractPluginParamsFromProps.ts index 2f1f139aeb048..1d7cd82706562 100644 --- a/packages/x-tree-view/src/internals/utils/extractPluginParamsFromProps.ts +++ b/packages/x-tree-view/src/internals/utils/extractPluginParamsFromProps.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { ConvertPluginsIntoSignatures, - MergePluginsProperty, + MergeSignaturesProperty, TreeViewExperimentalFeatures, TreeViewPlugin, TreeViewPublicAPI, @@ -10,8 +10,8 @@ import { UseTreeViewBaseParameters } from '../useTreeView/useTreeView.types'; export const extractPluginParamsFromProps = < TPlugins extends readonly TreeViewPlugin[], - TSlots extends MergePluginsProperty, - TSlotProps extends MergePluginsProperty, + TSlots extends MergeSignaturesProperty, 'slots'>, + TSlotProps extends MergeSignaturesProperty, 'slotProps'>, TProps extends { slots?: TSlots; slotProps?: TSlotProps; @@ -29,7 +29,8 @@ export const extractPluginParamsFromProps = < plugins: TPlugins; rootRef?: React.Ref; }) => { - type PluginParams = MergePluginsProperty, 'params'>; + type Signatures = ConvertPluginsIntoSignatures; + type PluginParams = MergeSignaturesProperty; const paramsLookup = {} as Record; plugins.forEach((plugin) => { @@ -43,7 +44,7 @@ export const extractPluginParamsFromProps = < slotProps: slotProps ?? {}, experimentalFeatures: experimentalFeatures ?? {}, apiRef, - } as UseTreeViewBaseParameters & PluginParams; + } as UseTreeViewBaseParameters & PluginParams; const otherProps = {} as Omit; Object.keys(props).forEach((propName) => { diff --git a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts index 7efc38056a9d4..479e022efa9cc 100644 --- a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts +++ b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts @@ -12,14 +12,16 @@ import { UseTreeItem2CheckboxSlotProps, } from './useTreeItem2.types'; import { useTreeViewContext } from '../internals/TreeViewProvider/useTreeViewContext'; -import { DefaultTreeViewPlugins } from '../internals/plugins/defaultPlugins'; +import { DefaultTreeViewPluginSignatures } from '../internals/plugins/defaultPlugins'; import { MuiCancellableEvent } from '../internals/models/MuiCancellableEvent'; import { useTreeItem2Utils } from '../hooks/useTreeItem2Utils'; import { TreeViewItemDepthContext } from '../internals/TreeViewItemDepthContext'; -export const useTreeItem2 = ( +export const useTreeItem2 = < + TSignatures extends DefaultTreeViewPluginSignatures = DefaultTreeViewPluginSignatures, +>( parameters: UseTreeItem2Parameters, -): UseTreeItem2ReturnValue => { +): UseTreeItem2ReturnValue => { const { runItemPlugins, selection: { multiSelect, disableSelection, checkboxSelection }, @@ -27,7 +29,7 @@ export const useTreeItem2 = (); + } = useTreeViewContext(); const depthContext = React.useContext(TreeViewItemDepthContext); const { id, itemId, label, children, rootRef } = parameters; diff --git a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts index 1caae45592dbf..530c0db1ec4d6 100644 --- a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts +++ b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts @@ -110,7 +110,9 @@ export interface UseTreeItem2Status { disabled: boolean; } -export interface UseTreeItem2ReturnValue { +export interface UseTreeItem2ReturnValue< + TSignatures extends readonly TreeViewAnyPluginSignature[], +> { /** * Resolver for the root slot's props. * @param {ExternalProps} externalProps Additional props for the root slot @@ -170,5 +172,5 @@ export interface UseTreeItem2ReturnValue; + publicAPI: TreeViewPublicAPI; } diff --git a/test/utils/tree-view/describeTreeView/describeTreeView.tsx b/test/utils/tree-view/describeTreeView/describeTreeView.tsx index 7cb6c9a9c8e82..82feb196b5435 100644 --- a/test/utils/tree-view/describeTreeView/describeTreeView.tsx +++ b/test/utils/tree-view/describeTreeView/describeTreeView.tsx @@ -16,9 +16,9 @@ import { DescribeTreeViewRendererUtils, } from './describeTreeView.types'; -const innerDescribeTreeView = ( +const innerDescribeTreeView = ( message: string, - testRunner: DescribeTreeViewTestRunner, + testRunner: DescribeTreeViewTestRunner, ): void => { const { render } = createRenderer(); @@ -89,7 +89,7 @@ const innerDescribeTreeView = ( TreeViewComponent: typeof RichTreeView, TreeItemComponent: typeof TreeItem | typeof TreeItem2, ) => { - const objectRenderer: DescribeTreeViewRenderer = ({ + const objectRenderer: DescribeTreeViewRenderer = ({ items: rawItems, withErrorBoundary, slotProps, @@ -132,7 +132,7 @@ const innerDescribeTreeView = ( return { setProps: result.setProps, setItems: (newItems) => result.setProps({ items: newItems }), - apiRef: apiRef as unknown as { current: TreeViewPublicAPI }, + apiRef: apiRef as unknown as { current: TreeViewPublicAPI }, ...getUtils(result), }; }; @@ -147,7 +147,7 @@ const innerDescribeTreeView = ( TreeViewComponent: typeof SimpleTreeView, TreeItemComponent: typeof TreeItem | typeof TreeItem2, ) => { - const objectRenderer: DescribeTreeViewRenderer = ({ + const objectRenderer: DescribeTreeViewRenderer = ({ items: rawItems, withErrorBoundary, slots, @@ -182,7 +182,7 @@ const innerDescribeTreeView = ( return { setProps: result.setProps, setItems: (newItems) => result.setProps({ children: newItems.map(renderItem) }), - apiRef: apiRef as unknown as { current: TreeViewPublicAPI }, + apiRef: apiRef as unknown as { current: TreeViewPublicAPI }, ...getUtils(result), }; }; @@ -262,15 +262,15 @@ const innerDescribeTreeView = ( }); }; -type Params = [ +type Params = [ string, - DescribeTreeViewTestRunner, + DescribeTreeViewTestRunner, ]; type DescribeTreeView = { - (...args: Params): void; - skip: (...args: Params) => void; - only: (...args: Params) => void; + (...args: Params): void; + skip: (...args: Params) => void; + only: (...args: Params) => void; }; /** diff --git a/test/utils/tree-view/describeTreeView/describeTreeView.types.ts b/test/utils/tree-view/describeTreeView/describeTreeView.types.ts index daf2330aa115e..8aff13f693ed9 100644 --- a/test/utils/tree-view/describeTreeView/describeTreeView.types.ts +++ b/test/utils/tree-view/describeTreeView/describeTreeView.types.ts @@ -1,14 +1,14 @@ import * as React from 'react'; import { - MergePluginsProperty, + MergeSignaturesProperty, TreeViewAnyPluginSignature, TreeViewPublicAPI, } from '@mui/x-tree-view/internals/models'; import { TreeItemProps } from '@mui/x-tree-view/TreeItem'; import { TreeItem2Props } from '@mui/x-tree-view/TreeItem2'; -export type DescribeTreeViewTestRunner = ( - params: DescribeTreeViewTestRunnerParams, +export type DescribeTreeViewTestRunner = ( + params: DescribeTreeViewTestRunnerParams, ) => void; export interface DescribeTreeViewRendererUtils { @@ -85,17 +85,18 @@ export interface DescribeTreeViewRendererUtils { getSelectedTreeItems: () => string[]; } -export interface DescribeTreeViewRendererReturnValue - extends DescribeTreeViewRendererUtils { +export interface DescribeTreeViewRendererReturnValue< + TSignatures extends TreeViewAnyPluginSignature[], +> extends DescribeTreeViewRendererUtils { /** * The ref object that allows Tree View manipulation. */ - apiRef: { current: TreeViewPublicAPI }; + apiRef: { current: TreeViewPublicAPI }; /** * Passes new props to the Tree View. - * @param {Partial>} props A subset of the props accepted by the Tree View. + * @param {Partial>} props A subset of the props accepted by the Tree View. */ - setProps: (props: Partial>) => void; + setProps: (props: Partial>) => void; /** * Passes new items to the Tree View. * @param {readyonly DescribeTreeViewItem[]} items The new items. @@ -103,7 +104,7 @@ export interface DescribeTreeViewRendererReturnValue void; } -export type DescribeTreeViewRenderer = < +export type DescribeTreeViewRenderer = < R extends DescribeTreeViewItem, >( params: { @@ -112,15 +113,15 @@ export type DescribeTreeViewRenderer, 'slots' | 'slotProps'> & { - slots?: MergePluginsProperty & { + } & Omit, 'slots' | 'slotProps'> & { + slots?: MergeSignaturesProperty & { item?: React.ElementType; }; - slotProps?: MergePluginsProperty & { + slotProps?: MergeSignaturesProperty & { item?: Partial | Partial; }; }, -) => DescribeTreeViewRendererReturnValue; +) => DescribeTreeViewRendererReturnValue; export type DescribeTreeViewJSXRenderer = ( element: React.ReactElement, @@ -129,7 +130,7 @@ export type DescribeTreeViewJSXRenderer = ( type TreeViewComponentName = 'RichTreeView' | 'RichTreeViewPro' | 'SimpleTreeView'; type TreeItemComponentName = 'TreeItem' | 'TreeItem2'; -interface DescribeTreeViewTestRunnerParams { +interface DescribeTreeViewTestRunnerParams { /** * Render the Tree View with its props and items defined as parameters of the "render" function as follows: * @@ -140,7 +141,7 @@ interface DescribeTreeViewTestRunnerParams; + render: DescribeTreeViewRenderer; /** * Render the Tree View by passing the JSX element to the renderFromJSX function as follows: * From fe4c198f22569d904b517fe85b774ceceecfac8e Mon Sep 17 00:00:00 2001 From: delangle Date: Wed, 5 Jun 2024 13:43:53 +0200 Subject: [PATCH 2/8] Work --- .../headless/LogExpandedItems.tsx | 2 +- .../src/RichTreeViewPro/RichTreeViewPro.tsx | 9 ++++-- .../RichTreeViewPro/RichTreeViewPro.types.ts | 6 ++-- .../src/internals/plugins/defaultPlugins.ts | 6 ++-- .../src/internals/plugins/index.ts | 2 +- .../src/RichTreeView/RichTreeView.tsx | 6 ++-- .../SimpleTreeView/SimpleTreeView.plugins.ts | 4 ++- .../src/SimpleTreeView/SimpleTreeView.tsx | 8 +++--- .../SimpleTreeView/SimpleTreeView.types.ts | 6 ++-- .../src/TreeItem/TreeItem.test.tsx | 4 +-- .../src/internals/models/helpers.ts | 8 +++--- .../src/internals/useTreeView/useTreeView.ts | 28 ++++++++----------- .../useTreeView/useTreeView.types.ts | 12 +++----- .../utils/extractPluginParamsFromProps.ts | 23 +++++++-------- 14 files changed, 59 insertions(+), 65 deletions(-) diff --git a/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx b/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx index 554ebb231a2da..75c05b7c6b9ab 100644 --- a/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx +++ b/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx @@ -97,7 +97,7 @@ function TreeView( plugins: TREE_VIEW_PLUGINS, }); - const { getRootProps, contextValue, instance } = useTreeView(pluginParams); + const { getRootProps, contextValue, instance } = useTreeView(pluginParams); const rootProps = useSlotProps({ elementType: RichTreeViewRoot, diff --git a/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.tsx b/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.tsx index fc3e56b02737d..5e5111eccb959 100644 --- a/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.tsx +++ b/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.tsx @@ -16,7 +16,10 @@ import { RichTreeViewProSlotProps, RichTreeViewProSlots, } from './RichTreeViewPro.types'; -import { DEFAULT_TREE_VIEW_PRO_PLUGINS } from '../internals/plugins'; +import { + DEFAULT_TREE_VIEW_PRO_PLUGINS, + DefaultTreeViewProPluginSignatures, +} from '../internals/plugins'; import { getReleaseInfo } from '../internals/utils/releaseInfo'; const useUtilityClasses = ( @@ -100,7 +103,7 @@ const RichTreeViewPro = React.forwardRef(function RichTreeViewPro< } const { pluginParams, slots, slotProps, otherProps } = extractPluginParamsFromProps< - typeof DEFAULT_TREE_VIEW_PRO_PLUGINS, + DefaultTreeViewProPluginSignatures, RichTreeViewProSlots, RichTreeViewProSlotProps, RichTreeViewProProps @@ -110,7 +113,7 @@ const RichTreeViewPro = React.forwardRef(function RichTreeViewPro< rootRef: ref, }); - const { getRootProps, contextValue, instance } = useTreeView(pluginParams); + const { getRootProps, contextValue, instance } = useTreeView(pluginParams); const classes = useUtilityClasses(props); diff --git a/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.types.ts b/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.types.ts index 7603b6fde12d8..c0df5ad46263e 100644 --- a/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.types.ts +++ b/packages/x-tree-view-pro/src/RichTreeViewPro/RichTreeViewPro.types.ts @@ -11,7 +11,7 @@ import { DefaultTreeViewProPluginParameters, DefaultTreeViewProPluginSlotProps, DefaultTreeViewProPluginSlots, - DefaultTreeViewProPlugins, + DefaultTreeViewProPluginSignatures, } from '../internals/plugins/defaultPlugins'; interface RichTreeViewItemProSlotOwnerState { @@ -39,7 +39,7 @@ export interface RichTreeViewProSlotProps | undefined + TreeViewPublicAPI | undefined >; export interface RichTreeViewProPropsBase extends React.HTMLAttributes { @@ -76,5 +76,5 @@ export interface RichTreeViewProProps; + experimentalFeatures?: TreeViewExperimentalFeatures; } diff --git a/packages/x-tree-view-pro/src/internals/plugins/defaultPlugins.ts b/packages/x-tree-view-pro/src/internals/plugins/defaultPlugins.ts index 0f43e55f3a7ce..d720b60872666 100644 --- a/packages/x-tree-view-pro/src/internals/plugins/defaultPlugins.ts +++ b/packages/x-tree-view-pro/src/internals/plugins/defaultPlugins.ts @@ -26,17 +26,17 @@ export const DEFAULT_TREE_VIEW_PRO_PLUGINS = [ useTreeViewIcons, ] as const; -export type DefaultTreeViewProPlugins = ConvertPluginsIntoSignatures< +export type DefaultTreeViewProPluginSignatures = ConvertPluginsIntoSignatures< typeof DEFAULT_TREE_VIEW_PRO_PLUGINS >; export type DefaultTreeViewProPluginSlots = MergeSignaturesProperty< - DefaultTreeViewProPlugins, + DefaultTreeViewProPluginSignatures, 'slots' >; export type DefaultTreeViewProPluginSlotProps = MergeSignaturesProperty< - DefaultTreeViewProPlugins, + DefaultTreeViewProPluginSignatures, 'slotProps' >; diff --git a/packages/x-tree-view-pro/src/internals/plugins/index.ts b/packages/x-tree-view-pro/src/internals/plugins/index.ts index 43574e246824a..96523fc228141 100644 --- a/packages/x-tree-view-pro/src/internals/plugins/index.ts +++ b/packages/x-tree-view-pro/src/internals/plugins/index.ts @@ -1,2 +1,2 @@ export { DEFAULT_TREE_VIEW_PRO_PLUGINS } from './defaultPlugins'; -export type { DefaultTreeViewProPlugins } from './defaultPlugins'; +export type { DefaultTreeViewProPluginSignatures } from './defaultPlugins'; diff --git a/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx b/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx index 4ae7a15a2a427..6493a4abf9020 100644 --- a/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx +++ b/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx @@ -7,7 +7,7 @@ import { getRichTreeViewUtilityClass } from './richTreeViewClasses'; import { RichTreeViewProps, RichTreeViewSlotProps, RichTreeViewSlots } from './RichTreeView.types'; import { useTreeView } from '../internals/useTreeView'; import { TreeViewProvider } from '../internals/TreeViewProvider'; -import { DEFAULT_TREE_VIEW_PLUGINS } from '../internals/plugins'; +import { DEFAULT_TREE_VIEW_PLUGINS, DefaultTreeViewPluginSignatures } from '../internals/plugins'; import { TreeItem, TreeItemProps } from '../TreeItem'; import { buildWarning } from '../internals/utils/warning'; import { extractPluginParamsFromProps } from '../internals/utils/extractPluginParamsFromProps'; @@ -89,7 +89,7 @@ const RichTreeView = React.forwardRef(function RichTreeView< } const { pluginParams, slots, slotProps, otherProps } = extractPluginParamsFromProps< - typeof DEFAULT_TREE_VIEW_PLUGINS, + DefaultTreeViewPluginSignatures, RichTreeViewSlots, RichTreeViewSlotProps, RichTreeViewProps @@ -99,7 +99,7 @@ const RichTreeView = React.forwardRef(function RichTreeView< rootRef: ref, }); - const { getRootProps, contextValue, instance } = useTreeView(pluginParams); + const { getRootProps, contextValue, instance } = useTreeView(pluginParams); const classes = useUtilityClasses(props); diff --git a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.plugins.ts b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.plugins.ts index 7d2cabef636fe..f380f55d4cdad 100644 --- a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.plugins.ts +++ b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.plugins.ts @@ -12,7 +12,9 @@ export const SIMPLE_TREE_VIEW_PLUGINS = [ useTreeViewJSXItems, ] as const; -export type SimpleTreeViewPlugins = ConvertPluginsIntoSignatures; +export type SimpleTreeViewPluginSignatures = ConvertPluginsIntoSignatures< + typeof SIMPLE_TREE_VIEW_PLUGINS +>; export type SimpleTreeViewPluginSlots = DefaultTreeViewPluginSlots; diff --git a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx index 83deccd1fc5b5..f16185817fd17 100644 --- a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx +++ b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx @@ -6,12 +6,12 @@ import { useSlotProps } from '@mui/base/utils'; import { getSimpleTreeViewUtilityClass } from './simpleTreeViewClasses'; import { SimpleTreeViewProps, - SimpleTreeViewSlotProps, SimpleTreeViewSlots, + SimpleTreeViewSlotProps, } from './SimpleTreeView.types'; import { useTreeView } from '../internals/useTreeView'; import { TreeViewProvider } from '../internals/TreeViewProvider'; -import { SIMPLE_TREE_VIEW_PLUGINS } from './SimpleTreeView.plugins'; +import { SIMPLE_TREE_VIEW_PLUGINS, SimpleTreeViewPluginSignatures } from './SimpleTreeView.plugins'; import { buildWarning } from '../internals/utils/warning'; import { extractPluginParamsFromProps } from '../internals/utils/extractPluginParamsFromProps'; @@ -74,7 +74,7 @@ const SimpleTreeView = React.forwardRef(function SimpleTreeView< } const { pluginParams, slots, slotProps, otherProps } = extractPluginParamsFromProps< - typeof SIMPLE_TREE_VIEW_PLUGINS, + SimpleTreeViewPluginSignatures, SimpleTreeViewSlots, SimpleTreeViewSlotProps, SimpleTreeViewProps & { items: any } @@ -84,7 +84,7 @@ const SimpleTreeView = React.forwardRef(function SimpleTreeView< rootRef: ref, }); - const { getRootProps, contextValue } = useTreeView(pluginParams); + const { getRootProps, contextValue } = useTreeView(pluginParams); const classes = useUtilityClasses(props); diff --git a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.types.ts b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.types.ts index b7e0ddcbbcdb2..958dbcbf83482 100644 --- a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.types.ts +++ b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.types.ts @@ -7,7 +7,7 @@ import { SimpleTreeViewPluginParameters, SimpleTreeViewPluginSlotProps, SimpleTreeViewPluginSlots, - SimpleTreeViewPlugins, + SimpleTreeViewPluginSignatures, } from './SimpleTreeView.plugins'; import { TreeViewExperimentalFeatures, TreeViewPublicAPI } from '../internals/models'; @@ -24,7 +24,7 @@ export interface SimpleTreeViewSlotProps extends SimpleTreeViewPluginSlotProps { } export type SimpleTreeViewApiRef = React.MutableRefObject< - TreeViewPublicAPI | undefined + TreeViewPublicAPI | undefined >; export interface SimpleTreeViewProps @@ -60,5 +60,5 @@ export interface SimpleTreeViewProps * 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; + experimentalFeatures?: TreeViewExperimentalFeatures; } diff --git a/packages/x-tree-view/src/TreeItem/TreeItem.test.tsx b/packages/x-tree-view/src/TreeItem/TreeItem.test.tsx index 6256ac0bb6a75..49a9702b6f238 100644 --- a/packages/x-tree-view/src/TreeItem/TreeItem.test.tsx +++ b/packages/x-tree-view/src/TreeItem/TreeItem.test.tsx @@ -2,14 +2,14 @@ import * as React from 'react'; import { expect } from 'chai'; import PropTypes from 'prop-types'; import { createRenderer } from '@mui/internal-test-utils'; -import { SimpleTreeViewPlugins } from '@mui/x-tree-view/SimpleTreeView/SimpleTreeView.plugins'; +import { SimpleTreeViewPluginSignatures } from '@mui/x-tree-view/SimpleTreeView/SimpleTreeView.plugins'; import { TreeItem, treeItemClasses as classes } from '@mui/x-tree-view/TreeItem'; import { TreeViewContextValue } from '@mui/x-tree-view/internals/TreeViewProvider'; import { TreeViewContext } from '@mui/x-tree-view/internals/TreeViewProvider/TreeViewContext'; import { describeConformance } from 'test/utils/describeConformance'; import { describeTreeView } from 'test/utils/tree-view/describeTreeView'; -const TEST_TREE_VIEW_CONTEXT_VALUE: TreeViewContextValue = { +const TEST_TREE_VIEW_CONTEXT_VALUE: TreeViewContextValue = { instance: { isItemExpandable: () => false, isItemExpanded: () => false, diff --git a/packages/x-tree-view/src/internals/models/helpers.ts b/packages/x-tree-view/src/internals/models/helpers.ts index e2268dd92783e..fffa7347cefb0 100644 --- a/packages/x-tree-view/src/internals/models/helpers.ts +++ b/packages/x-tree-view/src/internals/models/helpers.ts @@ -34,16 +34,16 @@ export type MergeSignaturesProperty< export type ConvertPluginsIntoSignatures = TPlugins extends readonly [plugin: infer P, ...otherPlugin: infer R] ? P extends TreeViewPlugin - ? [TSignature, ...ConvertPluginsIntoSignatures] + ? readonly [TSignature, ...ConvertPluginsIntoSignatures] : ConvertPluginsIntoSignatures - : []; + : readonly []; export type ConvertSignaturesIntoPlugins = TSignatures extends readonly [plugin: infer S, ...otherPlugin: infer R] ? S extends TreeViewAnyPluginSignature - ? [TreeViewPlugin, ...ConvertSignaturesIntoPlugins] + ? readonly [TreeViewPlugin, ...ConvertSignaturesIntoPlugins] : ConvertSignaturesIntoPlugins - : []; + : readonly []; export interface MergePluginsSignature { state: MergeSignaturesProperty; diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts index 7f46f809a54fd..a462da513e8ff 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts @@ -36,15 +36,11 @@ export function useTreeViewApiInitialization( return fallbackPublicApiRef.current; } -export const useTreeView = < - TPlugins extends readonly TreeViewPlugin[], ->( - inParams: UseTreeViewParameters>, -): UseTreeViewReturnValue> => { +export const useTreeView = ( + inParams: UseTreeViewParameters, +): UseTreeViewReturnValue => { const plugins = [...TREE_VIEW_CORE_PLUGINS, ...inParams.plugins]; - - type TSignatures = ConvertPluginsIntoSignatures - type SignaturesWithCorePlugins = ConvertPluginsIntoSignatures; + type TSignaturesWithCorePlugins = ConvertPluginsIntoSignatures; const params = plugins.reduce((acc, plugin) => { if (plugin.getDefaultizedParams) { @@ -52,18 +48,18 @@ export const useTreeView = < } return acc; - }, inParams) as unknown as UseTreeViewDefaultizedParameters; + }, inParams) as unknown as UseTreeViewDefaultizedParameters; const models = useTreeViewModels( plugins, - params as MergeSignaturesProperty, + params as MergeSignaturesProperty, ); - const instanceRef = React.useRef>( - {} as TreeViewInstance, + const instanceRef = React.useRef>( + {} as TreeViewInstance, ); - const instance = instanceRef.current as TreeViewInstance; + const instance = instanceRef.current as TreeViewInstance; - const publicAPI = useTreeViewApiInitialization>( + const publicAPI = useTreeViewApiInitialization>( inParams.apiRef, ); @@ -71,7 +67,7 @@ export const useTreeView = < const handleRootRef = useForkRef(innerRootRef, inParams.rootRef); const [state, setState] = React.useState(() => { - const temp = {} as MergeSignaturesProperty; + const temp = {} as MergeSignaturesProperty; plugins.forEach((plugin) => { if (plugin.getInitialState) { Object.assign( @@ -91,7 +87,7 @@ export const useTreeView = < publicAPI, instance: instance as TreeViewInstance, rootRef: innerRootRef, - } as TreeViewContextValue; + } as TreeViewContextValue; const runPlugin = (plugin: TreeViewPlugin) => { const pluginResponse = plugin({ diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts index 06417ec9c18af..6f415f07ad680 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts @@ -10,17 +10,13 @@ import { TreeViewExperimentalFeatures, } from '../models'; -export type UseTreeViewParameters< - TSignatures extends readonly TreeViewAnyPluginSignature[], -> = UseTreeViewBaseParameters & - MergeSignaturesProperty; +export type UseTreeViewParameters = + UseTreeViewBaseParameters & MergeSignaturesProperty; export interface UseTreeViewBaseParameters< TSignatures extends readonly TreeViewAnyPluginSignature[], > { - apiRef: - | React.MutableRefObject> - | undefined; + apiRef: React.MutableRefObject> | undefined; rootRef?: React.Ref | undefined; plugins: ConvertSignaturesIntoPlugins; slots: MergeSignaturesProperty; @@ -29,7 +25,7 @@ export interface UseTreeViewBaseParameters< } export type UseTreeViewDefaultizedParameters< - TSignatures extends readonly TreeViewAnyPluginSignature[], + TSignatures extends readonly TreeViewAnyPluginSignature[], > = UseTreeViewBaseParameters & MergeSignaturesProperty; diff --git a/packages/x-tree-view/src/internals/utils/extractPluginParamsFromProps.ts b/packages/x-tree-view/src/internals/utils/extractPluginParamsFromProps.ts index 1d7cd82706562..facfbd3bc3d00 100644 --- a/packages/x-tree-view/src/internals/utils/extractPluginParamsFromProps.ts +++ b/packages/x-tree-view/src/internals/utils/extractPluginParamsFromProps.ts @@ -1,24 +1,22 @@ import * as React from 'react'; import { - ConvertPluginsIntoSignatures, + ConvertSignaturesIntoPlugins, MergeSignaturesProperty, + TreeViewAnyPluginSignature, TreeViewExperimentalFeatures, - TreeViewPlugin, TreeViewPublicAPI, } from '../models'; import { UseTreeViewBaseParameters } from '../useTreeView/useTreeView.types'; export const extractPluginParamsFromProps = < - TPlugins extends readonly TreeViewPlugin[], - TSlots extends MergeSignaturesProperty, 'slots'>, - TSlotProps extends MergeSignaturesProperty, 'slotProps'>, + TSignatures extends readonly TreeViewAnyPluginSignature[], + TSlots extends MergeSignaturesProperty, + TSlotProps extends MergeSignaturesProperty, TProps extends { slots?: TSlots; slotProps?: TSlotProps; - apiRef?: React.MutableRefObject< - TreeViewPublicAPI> | undefined - >; - experimentalFeatures?: TreeViewExperimentalFeatures>; + apiRef?: React.MutableRefObject | undefined>; + experimentalFeatures?: TreeViewExperimentalFeatures; }, >({ props: { slots, slotProps, apiRef, experimentalFeatures, ...props }, @@ -26,11 +24,10 @@ export const extractPluginParamsFromProps = < rootRef, }: { props: TProps; - plugins: TPlugins; + plugins: ConvertSignaturesIntoPlugins; rootRef?: React.Ref; }) => { - type Signatures = ConvertPluginsIntoSignatures; - type PluginParams = MergeSignaturesProperty; + type PluginParams = MergeSignaturesProperty; const paramsLookup = {} as Record; plugins.forEach((plugin) => { @@ -44,7 +41,7 @@ export const extractPluginParamsFromProps = < slotProps: slotProps ?? {}, experimentalFeatures: experimentalFeatures ?? {}, apiRef, - } as UseTreeViewBaseParameters & PluginParams; + } as UseTreeViewBaseParameters & PluginParams; const otherProps = {} as Omit; Object.keys(props).forEach((propName) => { From fbf2bebe18a17279614f775c1b7e73c65174f11d Mon Sep 17 00:00:00 2001 From: delangle Date: Thu, 6 Jun 2024 10:25:28 +0200 Subject: [PATCH 3/8] Work --- .../src/internals/useTreeView/useTreeView.ts | 37 ++++++++++--------- .../useTreeView/useTreeView.types.ts | 3 +- .../useTreeView/useTreeViewModels.ts | 18 +++------ 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts index a462da513e8ff..4f42b9091ee2a 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts @@ -5,11 +5,11 @@ import { TreeViewAnyPluginSignature, TreeViewInstance, TreeViewPlugin, - ConvertPluginsIntoSignatures, MergeSignaturesProperty, TreeItemWrapper, TreeRootWrapper, TreeViewPublicAPI, + ConvertSignaturesIntoPlugins, MergePluginsSignature, } from '../models'; import { UseTreeViewDefaultizedParameters, @@ -19,7 +19,7 @@ import { } from './useTreeView.types'; import { useTreeViewModels } from './useTreeViewModels'; import { TreeViewContextValue } from '../TreeViewProvider'; -import { TREE_VIEW_CORE_PLUGINS } from '../corePlugins'; +import { TREE_VIEW_CORE_PLUGINS, TreeViewCorePluginsSignature } from '../corePlugins'; export function useTreeViewApiInitialization( inputApiRef: React.MutableRefObject | undefined, @@ -39,8 +39,14 @@ export function useTreeViewApiInitialization( export const useTreeView = ( inParams: UseTreeViewParameters, ): UseTreeViewReturnValue => { - const plugins = [...TREE_VIEW_CORE_PLUGINS, ...inParams.plugins]; - type TSignaturesWithCorePlugins = ConvertPluginsIntoSignatures; + type TSignaturesWithCorePluginSignatures = readonly MergePluginsSignature<[ + ...TSignatures, + TreeViewCorePluginsSignature, + ]>[]; + const plugins = [ + ...TREE_VIEW_CORE_PLUGINS, + ...inParams.plugins, + ] as unknown as ConvertSignaturesIntoPlugins; const params = plugins.reduce((acc, plugin) => { if (plugin.getDefaultizedParams) { @@ -48,26 +54,23 @@ export const useTreeView = ; + }, inParams) as unknown as UseTreeViewDefaultizedParameters; - const models = useTreeViewModels( - plugins, - params as MergeSignaturesProperty, + const models = useTreeViewModels(plugins, params); + const instanceRef = React.useRef>( + {} as TreeViewInstance, ); - const instanceRef = React.useRef>( - {} as TreeViewInstance, - ); - const instance = instanceRef.current as TreeViewInstance; + const instance = instanceRef.current as TreeViewInstance; - const publicAPI = useTreeViewApiInitialization>( - inParams.apiRef, - ); + const publicAPI = useTreeViewApiInitialization< + TreeViewPublicAPI + >(inParams.apiRef); const innerRootRef: React.RefObject = React.useRef(null); const handleRootRef = useForkRef(innerRootRef, inParams.rootRef); const [state, setState] = React.useState(() => { - const temp = {} as MergeSignaturesProperty; + const temp = {} as MergeSignaturesProperty; plugins.forEach((plugin) => { if (plugin.getInitialState) { Object.assign( @@ -87,7 +90,7 @@ export const useTreeView = , rootRef: innerRootRef, - } as TreeViewContextValue; + } as TreeViewContextValue; const runPlugin = (plugin: TreeViewPlugin) => { const pluginResponse = plugin({ diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts index 6f415f07ad680..6eca3b1966941 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts @@ -11,7 +11,8 @@ import { } from '../models'; export type UseTreeViewParameters = - UseTreeViewBaseParameters & MergeSignaturesProperty; + UseTreeViewBaseParameters & + Omit, keyof UseTreeViewBaseParameters>; export interface UseTreeViewBaseParameters< TSignatures extends readonly TreeViewAnyPluginSignature[], diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeViewModels.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeViewModels.ts index cca7a4f99a365..42d861fb7fa22 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeViewModels.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeViewModels.ts @@ -1,8 +1,7 @@ import * as React from 'react'; import { TreeViewAnyPluginSignature, - TreeViewPlugin, - ConvertPluginsIntoSignatures, + ConvertSignaturesIntoPlugins, MergeSignaturesProperty, } from '../models'; @@ -10,16 +9,11 @@ import { * Implements the same behavior as `useControlled` but for several models. * The controlled models are never stored in the state, and the state is only updated if the model is not controlled. */ -export const useTreeViewModels = < - TPlugins extends readonly TreeViewPlugin[], ->( - plugins: TPlugins, - props: MergeSignaturesProperty, 'defaultizedParams'>, +export const useTreeViewModels = ( + plugins: ConvertSignaturesIntoPlugins, + props: MergeSignaturesProperty, ) => { - type DefaultizedParams = MergeSignaturesProperty< - ConvertPluginsIntoSignatures, - 'defaultizedParams' - >; + type DefaultizedParams = MergeSignaturesProperty; const modelsRef = React.useRef<{ [modelName: string]: { @@ -65,7 +59,7 @@ export const useTreeViewModels = < }, ]; }), - ) as MergeSignaturesProperty, 'models'>; + ) as MergeSignaturesProperty; // We know that `modelsRef` do not vary across renders. /* eslint-disable react-hooks/rules-of-hooks, react-hooks/exhaustive-deps */ From 160c8eba9d3bc09b418804fc6c80633310da3add Mon Sep 17 00:00:00 2001 From: delangle Date: Thu, 6 Jun 2024 11:20:40 +0200 Subject: [PATCH 4/8] Work --- .../headless/LogExpandedItems.tsx | 3 +- .../src/internals/corePlugins/corePlugins.ts | 6 ++-- .../src/internals/corePlugins/index.ts | 2 +- .../src/internals/models/helpers.ts | 15 ---------- .../src/internals/models/plugin.ts | 4 +-- .../src/internals/models/treeView.ts | 5 ++-- .../src/internals/useTreeView/useTreeView.ts | 28 ++++++++----------- 7 files changed, 23 insertions(+), 40 deletions(-) diff --git a/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx b/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx index 75c05b7c6b9ab..c1a70f335c0e6 100644 --- a/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx +++ b/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx @@ -21,6 +21,7 @@ import { extractPluginParamsFromProps, useTreeView, TreeViewProvider, + ConvertPluginsIntoSignatures, } from '@mui/x-tree-view/internals'; interface TreeViewLogExpandedParameters { @@ -88,7 +89,7 @@ function TreeView( const ownerState = themeProps as TreeViewProps; const { pluginParams, otherProps } = extractPluginParamsFromProps< - typeof TREE_VIEW_PLUGINS, + ConvertPluginsIntoSignatures, DefaultTreeViewPluginSlots, DefaultTreeViewPluginSlotProps, TreeViewProps diff --git a/packages/x-tree-view/src/internals/corePlugins/corePlugins.ts b/packages/x-tree-view/src/internals/corePlugins/corePlugins.ts index caf26f546d7a3..0d55e29829ab0 100644 --- a/packages/x-tree-view/src/internals/corePlugins/corePlugins.ts +++ b/packages/x-tree-view/src/internals/corePlugins/corePlugins.ts @@ -1,5 +1,5 @@ import { useTreeViewInstanceEvents } from './useTreeViewInstanceEvents'; -import { ConvertPluginsIntoSignatures, MergePluginsSignature } from '../models'; +import { ConvertPluginsIntoSignatures } from '../models'; /** * Internal plugins that create the tools used by the other plugins. @@ -7,6 +7,6 @@ import { ConvertPluginsIntoSignatures, MergePluginsSignature } from '../models'; */ export const TREE_VIEW_CORE_PLUGINS = [useTreeViewInstanceEvents] as const; -export type TreeViewCorePluginsSignature = MergePluginsSignature< - ConvertPluginsIntoSignatures +export type TreeViewCorePluginSignatures = ConvertPluginsIntoSignatures< + typeof TREE_VIEW_CORE_PLUGINS >; diff --git a/packages/x-tree-view/src/internals/corePlugins/index.ts b/packages/x-tree-view/src/internals/corePlugins/index.ts index 556277c739cec..55cb778e2bd98 100644 --- a/packages/x-tree-view/src/internals/corePlugins/index.ts +++ b/packages/x-tree-view/src/internals/corePlugins/index.ts @@ -1,2 +1,2 @@ export { TREE_VIEW_CORE_PLUGINS } from './corePlugins'; -export type { TreeViewCorePluginsSignature } from './corePlugins'; +export type { TreeViewCorePluginSignatures } from './corePlugins'; diff --git a/packages/x-tree-view/src/internals/models/helpers.ts b/packages/x-tree-view/src/internals/models/helpers.ts index fffa7347cefb0..86adb3e2ddd6c 100644 --- a/packages/x-tree-view/src/internals/models/helpers.ts +++ b/packages/x-tree-view/src/internals/models/helpers.ts @@ -44,18 +44,3 @@ export type ConvertSignaturesIntoPlugins = ? readonly [TreeViewPlugin, ...ConvertSignaturesIntoPlugins] : ConvertSignaturesIntoPlugins : readonly []; - -export interface MergePluginsSignature { - state: MergeSignaturesProperty; - instance: MergeSignaturesProperty; - publicAPI: MergeSignaturesProperty; - params: MergeSignaturesProperty; - defaultizedParams: MergeSignaturesProperty; - dependantPlugins: MergeSignaturesProperty; - contextValue: MergeSignaturesProperty; - slots: MergeSignaturesProperty; - slotProps: MergeSignaturesProperty; - events: MergeSignaturesProperty; - models: MergeSignaturesProperty; - experimentalFeatures: MergeSignaturesProperty; -} diff --git a/packages/x-tree-view/src/internals/models/plugin.ts b/packages/x-tree-view/src/internals/models/plugin.ts index a451c03ad0e9e..fd26dd4c42d7a 100644 --- a/packages/x-tree-view/src/internals/models/plugin.ts +++ b/packages/x-tree-view/src/internals/models/plugin.ts @@ -3,7 +3,7 @@ import { EventHandlers } from '@mui/base/utils'; import { TreeViewExperimentalFeatures, TreeViewInstance, TreeViewModel } from './treeView'; import type { MergeSignaturesProperty, OptionalIfEmpty } from './helpers'; import { TreeViewEventLookupElement } from './events'; -import type { TreeViewCorePluginsSignature } from '../corePlugins'; +import type { TreeViewCorePluginSignatures } from '../corePlugins'; import { TreeViewItemId } from '../../models'; export interface TreeViewPluginOptions { @@ -86,7 +86,7 @@ export type TreeViewAnyPluginSignature = { }; type TreeViewUsedPlugins = [ - TreeViewCorePluginsSignature, + ...TreeViewCorePluginSignatures, ...TSignature['dependantPlugins'], ]; diff --git a/packages/x-tree-view/src/internals/models/treeView.ts b/packages/x-tree-view/src/internals/models/treeView.ts index c09e681286801..e513e0f8bff52 100644 --- a/packages/x-tree-view/src/internals/models/treeView.ts +++ b/packages/x-tree-view/src/internals/models/treeView.ts @@ -1,5 +1,6 @@ import type { TreeViewAnyPluginSignature } from './plugin'; import type { MergeSignaturesProperty } from './helpers'; +import type { TreeViewCorePluginSignatures } from '../corePlugins'; export interface TreeViewItemMeta { id: string; @@ -24,10 +25,10 @@ export interface TreeViewModel { } export type TreeViewInstance = - MergeSignaturesProperty; + MergeSignaturesProperty<[...TreeViewCorePluginSignatures, ...TSignatures], 'instance'>; export type TreeViewPublicAPI = - MergeSignaturesProperty; + MergeSignaturesProperty<[...TreeViewCorePluginSignatures, ...TSignatures], 'publicAPI'>; export type TreeViewExperimentalFeatures< TSignatures extends readonly TreeViewAnyPluginSignature[], diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts index 4f42b9091ee2a..2285094066cb9 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts @@ -9,7 +9,7 @@ import { TreeItemWrapper, TreeRootWrapper, TreeViewPublicAPI, - ConvertSignaturesIntoPlugins, MergePluginsSignature, + ConvertSignaturesIntoPlugins, } from '../models'; import { UseTreeViewDefaultizedParameters, @@ -19,7 +19,7 @@ import { } from './useTreeView.types'; import { useTreeViewModels } from './useTreeViewModels'; import { TreeViewContextValue } from '../TreeViewProvider'; -import { TREE_VIEW_CORE_PLUGINS, TreeViewCorePluginsSignature } from '../corePlugins'; +import { TREE_VIEW_CORE_PLUGINS, TreeViewCorePluginSignatures } from '../corePlugins'; export function useTreeViewApiInitialization( inputApiRef: React.MutableRefObject | undefined, @@ -39,10 +39,10 @@ export function useTreeViewApiInitialization( export const useTreeView = ( inParams: UseTreeViewParameters, ): UseTreeViewReturnValue => { - type TSignaturesWithCorePluginSignatures = readonly MergePluginsSignature<[ + type TSignaturesWithCorePluginSignatures = readonly [ + ...TreeViewCorePluginSignatures, ...TSignatures, - TreeViewCorePluginsSignature, - ]>[]; + ]; const plugins = [ ...TREE_VIEW_CORE_PLUGINS, ...inParams.plugins, @@ -50,21 +50,17 @@ export const useTreeView = { if (plugin.getDefaultizedParams) { - return plugin.getDefaultizedParams(acc); + return plugin.getDefaultizedParams(acc) as typeof acc; } return acc; }, inParams) as unknown as UseTreeViewDefaultizedParameters; const models = useTreeViewModels(plugins, params); - const instanceRef = React.useRef>( - {} as TreeViewInstance, - ); - const instance = instanceRef.current as TreeViewInstance; + const instanceRef = React.useRef({} as TreeViewInstance); + const instance = instanceRef.current as TreeViewInstance; - const publicAPI = useTreeViewApiInitialization< - TreeViewPublicAPI - >(inParams.apiRef); + const publicAPI = useTreeViewApiInitialization>(inParams.apiRef); const innerRootRef: React.RefObject = React.useRef(null); const handleRootRef = useForkRef(innerRootRef, inParams.rootRef); @@ -90,7 +86,7 @@ export const useTreeView = , rootRef: innerRootRef, - } as TreeViewContextValue; + } as TreeViewContextValue; const runPlugin = (plugin: TreeViewPlugin) => { const pluginResponse = plugin({ @@ -198,7 +194,7 @@ export const useTreeView = Date: Thu, 6 Jun 2024 11:23:27 +0200 Subject: [PATCH 5/8] Fix --- packages/x-tree-view/src/internals/useTreeView/useTreeView.ts | 2 +- .../x-tree-view/src/internals/useTreeView/useTreeView.types.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts index 2285094066cb9..9b5a0d78e8cee 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts @@ -54,7 +54,7 @@ export const useTreeView = ; + }, inParams) as unknown as UseTreeViewDefaultizedParameters; const models = useTreeViewModels(plugins, params); const instanceRef = React.useRef({} as TreeViewInstance); diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts index 6eca3b1966941..8feb3d80a6cf2 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts @@ -9,6 +9,7 @@ import { TreeViewPublicAPI, TreeViewExperimentalFeatures, } from '../models'; +import { TreeViewCorePluginSignatures } from '@mui/x-tree-view/internals/corePlugins'; export type UseTreeViewParameters = UseTreeViewBaseParameters & @@ -28,7 +29,7 @@ export interface UseTreeViewBaseParameters< export type UseTreeViewDefaultizedParameters< TSignatures extends readonly TreeViewAnyPluginSignature[], > = UseTreeViewBaseParameters & - MergeSignaturesProperty; + MergeSignaturesProperty<[...TreeViewCorePluginSignatures, ...TSignatures], 'defaultizedParams'>; export interface UseTreeViewRootSlotProps extends Pick< From 7ca19ba8f84a17dcb2c0a9e768b3e1ec97d13c7a Mon Sep 17 00:00:00 2001 From: delangle Date: Thu, 6 Jun 2024 11:36:05 +0200 Subject: [PATCH 6/8] Work --- .../src/internals/models/helpers.ts | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/packages/x-tree-view/src/internals/models/helpers.ts b/packages/x-tree-view/src/internals/models/helpers.ts index 86adb3e2ddd6c..f94a5d92f2627 100644 --- a/packages/x-tree-view/src/internals/models/helpers.ts +++ b/packages/x-tree-view/src/internals/models/helpers.ts @@ -31,16 +31,22 @@ export type MergeSignaturesProperty< : {} : {}; -export type ConvertPluginsIntoSignatures = - TPlugins extends readonly [plugin: infer P, ...otherPlugin: infer R] - ? P extends TreeViewPlugin +export type ConvertPluginsIntoSignatures< + TPlugins extends readonly TreeViewPlugin[], +> = TPlugins extends readonly [plugin: infer TPlugin, ...otherPlugin: infer R] + ? R extends readonly TreeViewPlugin[] + ? TPlugin extends TreeViewPlugin ? readonly [TSignature, ...ConvertPluginsIntoSignatures] - : ConvertPluginsIntoSignatures - : readonly []; + : never + : never + : never; -export type ConvertSignaturesIntoPlugins = - TSignatures extends readonly [plugin: infer S, ...otherPlugin: infer R] - ? S extends TreeViewAnyPluginSignature - ? readonly [TreeViewPlugin, ...ConvertSignaturesIntoPlugins] - : ConvertSignaturesIntoPlugins - : readonly []; +export type ConvertSignaturesIntoPlugins< + TSignatures extends readonly TreeViewAnyPluginSignature[], +> = TSignatures extends readonly [signature: infer TSignature, ...otherSignatures: infer R] + ? R extends readonly TreeViewAnyPluginSignature[] + ? TSignature extends TreeViewAnyPluginSignature + ? readonly [TreeViewPlugin, ...ConvertSignaturesIntoPlugins] + : never + : never + : never; From fa5ae4efbf0f67dadc00259cd89848b53cf6cf3f Mon Sep 17 00:00:00 2001 From: delangle Date: Thu, 6 Jun 2024 12:38:21 +0200 Subject: [PATCH 7/8] Work --- .../TreeViewProvider.types.ts | 6 +- .../src/internals/TreeViewProvider/index.ts | 6 +- .../src/internals/models/helpers.ts | 6 +- .../src/internals/useTreeView/useTreeView.ts | 116 +++++++++--------- 4 files changed, 72 insertions(+), 62 deletions(-) diff --git a/packages/x-tree-view/src/internals/TreeViewProvider/TreeViewProvider.types.ts b/packages/x-tree-view/src/internals/TreeViewProvider/TreeViewProvider.types.ts index 06a056725d520..f0af466f0f215 100644 --- a/packages/x-tree-view/src/internals/TreeViewProvider/TreeViewProvider.types.ts +++ b/packages/x-tree-view/src/internals/TreeViewProvider/TreeViewProvider.types.ts @@ -9,6 +9,10 @@ import { TreeViewPublicAPI, } from '../models'; +export type TreeViewItemPluginsRunner = ( + props: TProps, +) => Required; + export type TreeViewContextValue = MergeSignaturesProperty & { instance: TreeViewInstance; @@ -16,7 +20,7 @@ export type TreeViewContextValue; wrapItem: TreeItemWrapper; wrapRoot: TreeRootWrapper; - runItemPlugins: (props: TProps) => Required; + runItemPlugins: TreeViewItemPluginsRunner; }; export interface TreeViewProviderProps { diff --git a/packages/x-tree-view/src/internals/TreeViewProvider/index.ts b/packages/x-tree-view/src/internals/TreeViewProvider/index.ts index 28aff7c61d46f..ffee8fb725aa3 100644 --- a/packages/x-tree-view/src/internals/TreeViewProvider/index.ts +++ b/packages/x-tree-view/src/internals/TreeViewProvider/index.ts @@ -1,2 +1,6 @@ export { TreeViewProvider } from './TreeViewProvider'; -export type { TreeViewProviderProps, TreeViewContextValue } from './TreeViewProvider.types'; +export type { + TreeViewProviderProps, + TreeViewContextValue, + TreeViewItemPluginsRunner, +} from './TreeViewProvider.types'; diff --git a/packages/x-tree-view/src/internals/models/helpers.ts b/packages/x-tree-view/src/internals/models/helpers.ts index f94a5d92f2627..f404e670cd90a 100644 --- a/packages/x-tree-view/src/internals/models/helpers.ts +++ b/packages/x-tree-view/src/internals/models/helpers.ts @@ -34,12 +34,12 @@ export type MergeSignaturesProperty< export type ConvertPluginsIntoSignatures< TPlugins extends readonly TreeViewPlugin[], > = TPlugins extends readonly [plugin: infer TPlugin, ...otherPlugin: infer R] - ? R extends readonly TreeViewPlugin[] + ? R extends readonly TreeViewPlugin[] ? TPlugin extends TreeViewPlugin ? readonly [TSignature, ...ConvertPluginsIntoSignatures] : never : never - : never; + : []; export type ConvertSignaturesIntoPlugins< TSignatures extends readonly TreeViewAnyPluginSignature[], @@ -49,4 +49,4 @@ export type ConvertSignaturesIntoPlugins< ? readonly [TreeViewPlugin, ...ConvertSignaturesIntoPlugins] : never : never - : never; + : []; diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts index 9b5a0d78e8cee..1bc1b6ed22797 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts @@ -18,7 +18,7 @@ import { UseTreeViewRootSlotProps, } from './useTreeView.types'; import { useTreeViewModels } from './useTreeViewModels'; -import { TreeViewContextValue } from '../TreeViewProvider'; +import { TreeViewContextValue, TreeViewItemPluginsRunner } from '../TreeViewProvider'; import { TREE_VIEW_CORE_PLUGINS, TreeViewCorePluginSignatures } from '../corePlugins'; export function useTreeViewApiInitialization( @@ -79,48 +79,33 @@ export const useTreeView = ( - otherHandlers: TOther, - ) => React.HTMLAttributes)[] = []; - const contextValue = { - publicAPI, - instance: instance as TreeViewInstance, - rootRef: innerRootRef, - } as TreeViewContextValue; - - const runPlugin = (plugin: TreeViewPlugin) => { - const pluginResponse = plugin({ - instance, - params, - slots: params.slots, - slotProps: params.slotProps, - experimentalFeatures: params.experimentalFeatures, - state, - setState, - rootRef: innerRootRef, - models, + const itemWrappers = plugins + .map((plugin) => plugin.wrapItem) + .filter((wrapItem): wrapItem is TreeItemWrapper => !!wrapItem); + const wrapItem: TreeItemWrapper = ({ itemId, children }) => { + let finalChildren: React.ReactNode = children; + itemWrappers.forEach((itemWrapper) => { + finalChildren = itemWrapper({ itemId, children: finalChildren, instance }); }); - if (pluginResponse.getRootProps) { - rootPropsGetters.push(pluginResponse.getRootProps); - } - - if (pluginResponse.publicAPI) { - Object.assign(publicAPI, pluginResponse.publicAPI); - } + return finalChildren; + }; - if (pluginResponse.instance) { - Object.assign(instance, pluginResponse.instance); - } + const rootWrappers = plugins + .map((plugin) => plugin.wrapRoot) + .filter((wrapRoot): wrapRoot is TreeRootWrapper => !!wrapRoot) + // The wrappers are reversed to ensure that the first wrapper is the outermost one. + .reverse(); + const wrapRoot: TreeRootWrapper = ({ children }) => { + let finalChildren: React.ReactNode = children; + rootWrappers.forEach((rootWrapper) => { + finalChildren = rootWrapper({ children: finalChildren, instance }); + }); - if (pluginResponse.contextValue) { - Object.assign(contextValue, pluginResponse.contextValue); - } + return finalChildren; }; - plugins.forEach(runPlugin); - - contextValue.runItemPlugins = (itemPluginProps) => { + const runItemPlugins: TreeViewItemPluginsRunner = (itemPluginProps) => { let finalRootRef: React.RefCallback | null = null; let finalContentRef: React.RefCallback | null = null; @@ -148,33 +133,50 @@ export const useTreeView = plugin.wrapItem) - .filter((wrapItem): wrapItem is TreeItemWrapper => !!wrapItem); - contextValue.wrapItem = ({ itemId, children }) => { - let finalChildren: React.ReactNode = children; - itemWrappers.forEach((itemWrapper) => { - finalChildren = itemWrapper({ itemId, children: finalChildren, instance }); + const contextValue = { + publicAPI, + wrapItem, + wrapRoot, + runItemPlugins, + instance: instance as TreeViewInstance, + rootRef: innerRootRef, + } as TreeViewContextValue; + + const rootPropsGetters: (( + otherHandlers: TOther, + ) => React.HTMLAttributes)[] = []; + const runPlugin = (plugin: TreeViewPlugin) => { + const pluginResponse = plugin({ + instance, + params, + slots: params.slots, + slotProps: params.slotProps, + experimentalFeatures: params.experimentalFeatures, + state, + setState, + rootRef: innerRootRef, + models, }); - return finalChildren; - }; + if (pluginResponse.getRootProps) { + rootPropsGetters.push(pluginResponse.getRootProps); + } - const rootWrappers = plugins - .map((plugin) => plugin.wrapRoot) - .filter((wrapRoot): wrapRoot is TreeRootWrapper => !!wrapRoot) - // The wrappers are reversed to ensure that the first wrapper is the outermost one. - .reverse(); + if (pluginResponse.publicAPI) { + Object.assign(publicAPI, pluginResponse.publicAPI); + } - contextValue.wrapRoot = ({ children }) => { - let finalChildren: React.ReactNode = children; - rootWrappers.forEach((rootWrapper) => { - finalChildren = rootWrapper({ children: finalChildren, instance }); - }); + if (pluginResponse.instance) { + Object.assign(instance, pluginResponse.instance); + } - return finalChildren; + if (pluginResponse.contextValue) { + Object.assign(contextValue, pluginResponse.contextValue); + } }; + plugins.forEach(runPlugin); + const getRootProps = ( otherHandlers: TOther = {} as TOther, ) => { From 6a8e5010208e3b3bbba8c9ffd0e8d1bb29274ed8 Mon Sep 17 00:00:00 2001 From: delangle Date: Thu, 6 Jun 2024 12:47:56 +0200 Subject: [PATCH 8/8] Fix --- .../x-tree-view/src/internals/useTreeView/useTreeView.types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts index 8feb3d80a6cf2..e01053f06b07e 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeView.types.ts @@ -9,7 +9,7 @@ import { TreeViewPublicAPI, TreeViewExperimentalFeatures, } from '../models'; -import { TreeViewCorePluginSignatures } from '@mui/x-tree-view/internals/corePlugins'; +import { TreeViewCorePluginSignatures } from '../corePlugins'; export type UseTreeViewParameters = UseTreeViewBaseParameters &