From 174c6603cfbd321e6da9acd53c980a68a30dacbe Mon Sep 17 00:00:00 2001 From: flavien Date: Wed, 18 Sep 2024 17:39:36 +0200 Subject: [PATCH 1/3] [TreeView] Apply experimental features in getDefaultizedParams instead of in the plugin render --- .../headless/LogExpandedItems.js | 2 +- .../headless/LogExpandedItems.tsx | 2 +- .../rich-tree-view/headless/headless.md | 4 +- .../useTreeViewItemsReordering.ts | 46 +++++++++---------- .../src/internals/models/plugin.ts | 7 +-- .../useTreeViewExpansion.ts | 2 +- .../useTreeViewItems/useTreeViewItems.tsx | 2 +- .../useTreeViewLabel/useTreeViewLabel.ts | 29 ++++++++---- .../useTreeViewLabel.types.ts | 9 +++- .../useTreeViewSelection.ts | 2 +- .../extractPluginParamsFromProps.ts | 10 +++- 11 files changed, 67 insertions(+), 48 deletions(-) diff --git a/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.js b/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.js index d7a4285c49c21..1b76b33540846 100644 --- a/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.js +++ b/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.js @@ -23,7 +23,7 @@ const useTreeViewLogExpanded = ({ params, models }) => { }; // Sets the default value of this plugin parameters. -useTreeViewLogExpanded.getDefaultizedParams = (params) => ({ +useTreeViewLogExpanded.getDefaultizedParams = ({ params }) => ({ ...params, areLogsEnabled: params.areLogsEnabled ?? false, }); 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 70285558cbb90..5c6942d61458b 100644 --- a/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx +++ b/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx @@ -56,7 +56,7 @@ const useTreeViewLogExpanded: TreeViewPlugin = ({ }; // Sets the default value of this plugin parameters. -useTreeViewLogExpanded.getDefaultizedParams = (params) => ({ +useTreeViewLogExpanded.getDefaultizedParams = ({ params }) => ({ ...params, areLogsEnabled: params.areLogsEnabled ?? false, }); 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 6afb2d8403a04..8d1c35ea57f04 100644 --- a/docs/data/tree-view/rich-tree-view/headless/headless.md +++ b/docs/data/tree-view/rich-tree-view/headless/headless.md @@ -56,7 +56,7 @@ const useCustomPlugin = ({ params }) => { useCustomPlugin.params = { customParam: true }; -useCustomPlugin.getDefaultizedParams = (params) => ({ +useCustomPlugin.getDefaultizedParams = ({ params }) => ({ ...params, customParam: params.customParam ?? false, }); @@ -76,7 +76,7 @@ useCustomPlugin.params = { customModel: true, }; -useCustomPlugin.getDefaultizedParams = (params) => ({ +useCustomPlugin.getDefaultizedParams = ({ params }) => ({ ...params, // ... other defaultized params defaultCustomModel: params.defaultCustomModel ?? false, diff --git a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.ts b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.ts index a840f2d074b4a..263083dce4a99 100644 --- a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.ts +++ b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.ts @@ -20,27 +20,10 @@ export const useTreeViewItemsReordering: TreeViewPlugin { - const isItemsReorderingEnabled = - params.itemsReordering && !!experimentalFeatures?.itemsReordering; - - if (process.env.NODE_ENV !== 'production') { - if ( - params.itemsReordering && - (!experimentalFeatures?.indentationAtItemLevel || !experimentalFeatures?.itemsReordering) - ) { - warnOnce([ - 'MUI X: The items reordering feature requires the `indentationAtItemLevel` and `itemsReordering` experimental features to be enabled.', - 'You can do it by passing `experimentalFeatures={{ indentationAtItemLevel: true, itemsReordering: true }}` to the `RichTreeViewPro` component.', - 'Check the documentation for more details: https://mui.com/x/react-tree-view/rich-tree-view/items/', - ]); - } - } - const canItemBeDragged = React.useCallback( (itemId: string) => { - if (!isItemsReorderingEnabled) { + if (!params.itemsReordering) { return false; } @@ -51,7 +34,7 @@ export const useTreeViewItemsReordering: TreeViewPlugin ({ - ...params, - itemsReordering: params.itemsReordering ?? false, -}); +useTreeViewItemsReordering.getDefaultizedParams = ({ params, experimentalFeatures }) => { + const canUseFeature = + experimentalFeatures?.indentationAtItemLevel && experimentalFeatures?.itemsReordering; + + if (process.env.NODE_ENV !== 'production') { + if (params.itemsReordering && !canUseFeature) { + warnOnce([ + 'MUI X: The items reordering feature requires the `indentationAtItemLevel` and `itemsReordering` experimental features to be enabled.', + 'You can do it by passing `experimentalFeatures={{ indentationAtItemLevel: true, itemsReordering: true }}` to the `RichTreeViewPro` component.', + 'Check the documentation for more details: https://mui.com/x/react-tree-view/rich-tree-view/items/', + ]); + } + } + + return { + ...params, + itemsReordering: canUseFeature ? (params.itemsReordering ?? false) : false, + }; +}; useTreeViewItemsReordering.getInitialState = () => ({ itemsReordering: null }); diff --git a/packages/x-tree-view/src/internals/models/plugin.ts b/packages/x-tree-view/src/internals/models/plugin.ts index 9dda02da75653..cb5e819e30c91 100644 --- a/packages/x-tree-view/src/internals/models/plugin.ts +++ b/packages/x-tree-view/src/internals/models/plugin.ts @@ -150,9 +150,10 @@ export type TreeRootWrapper = { (options: TreeViewPluginOptions): TreeViewResponse; - getDefaultizedParams?: ( - params: TreeViewUsedParams, - ) => TSignature['defaultizedParams']; + getDefaultizedParams?: (options: { + params: TreeViewUsedParams; + experimentalFeatures: TreeViewUsedExperimentalFeatures; + }) => TSignature['defaultizedParams']; getInitialState?: (params: TreeViewUsedDefaultizedParams) => TSignature['state']; models?: TreeViewModelsInitializer; params: Record; diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts index b9dabd1bd1a25..d01813aeab710 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts @@ -122,7 +122,7 @@ useTreeViewExpansion.models = { const DEFAULT_EXPANDED_ITEMS: string[] = []; -useTreeViewExpansion.getDefaultizedParams = (params) => ({ +useTreeViewExpansion.getDefaultizedParams = ({ params }) => ({ ...params, defaultExpandedItems: params.defaultExpandedItems ?? DEFAULT_EXPANDED_ITEMS, }); diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.tsx b/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.tsx index 01ac6d4de49c7..71b6717225542 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.tsx +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.tsx @@ -290,7 +290,7 @@ useTreeViewItems.getInitialState = (params) => ({ }), }); -useTreeViewItems.getDefaultizedParams = (params) => ({ +useTreeViewItems.getDefaultizedParams = ({ params }) => ({ ...params, disabledItemsFocusable: params.disabledItemsFocusable ?? false, itemChildrenIndentation: params.itemChildrenIndentation ?? '12px', diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.ts index 1a314fff4a9ac..90b4e28823dad 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.ts @@ -12,15 +12,6 @@ export const useTreeViewLabel: TreeViewPlugin = ({ params, experimentalFeatures, }) => { - if (process.env.NODE_ENV !== 'production') { - if (params.isItemEditable && !experimentalFeatures?.labelEditing) { - warnOnce([ - 'MUI X: The label editing feature requires the `labelEditing` experimental feature to be enabled.', - 'You can do it by passing `experimentalFeatures={{ labelEditing: true}}` to the `RichTreeViewPro` component.', - 'Check the documentation for more details: https://mui.com/x/react-tree-view/rich-tree-view/editing/', - ]); - } - } const editedItemRef = React.useRef(state.editedItemId); const isItemBeingEditedRef = (itemId: TreeViewItemId) => editedItemRef.current === itemId; @@ -32,7 +23,7 @@ export const useTreeViewLabel: TreeViewPlugin = ({ const isItemBeingEdited = (itemId: TreeViewItemId) => itemId === state.editedItemId; - const isTreeViewEditable = Boolean(params.isItemEditable) && !!experimentalFeatures.labelEditing; + const isTreeViewEditable = Boolean(params.isItemEditable); const isItemEditable = (itemId: TreeViewItemId): boolean => { if (itemId == null || !isTreeViewEditable) { @@ -95,6 +86,24 @@ export const useTreeViewLabel: TreeViewPlugin = ({ useTreeViewLabel.itemPlugin = useTreeViewLabelItemPlugin; +useTreeViewLabel.getDefaultizedParams = ({ params, experimentalFeatures }) => { + const canUseFeature = experimentalFeatures?.labelEditing; + if (process.env.NODE_ENV !== 'production') { + if (params.isItemEditable && !canUseFeature) { + warnOnce([ + 'MUI X: The label editing feature requires the `labelEditing` experimental feature to be enabled.', + 'You can do it by passing `experimentalFeatures={{ labelEditing: true}}` to the `RichTreeViewPro` component.', + 'Check the documentation for more details: https://mui.com/x/react-tree-view/rich-tree-view/editing/', + ]); + } + } + + return { + ...params, + isItemEditable: canUseFeature ? (params.isItemEditable ?? false) : false, + }; +}; + useTreeViewLabel.getInitialState = () => ({ editedItemId: null, }); diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.types.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.types.ts index 12f5296ef61ab..3f23f27ca86d1 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.types.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.types.ts @@ -1,4 +1,4 @@ -import { TreeViewPluginSignature } from '../../models'; +import { DefaultizedProps, TreeViewPluginSignature } from '../../models'; import { TreeViewItemId } from '../../../models'; import { UseTreeViewItemsSignature } from '../useTreeViewItems'; import { TreeItem2LabelInputProps } from '../../../TreeItem2LabelInput'; @@ -63,13 +63,18 @@ export interface UseTreeViewLabelParameters { isItemEditable?: boolean | ((item: R) => boolean); } +export type UseTreeViewLabelDefaultizedParameters = DefaultizedProps< + UseTreeViewLabelParameters, + 'isItemEditable' +>; + export interface UseTreeViewLabelState { editedItemId: string | null; } export type UseTreeViewLabelSignature = TreeViewPluginSignature<{ params: UseTreeViewLabelParameters; - defaultizedParams: UseTreeViewLabelParameters; + defaultizedParams: UseTreeViewLabelDefaultizedParameters; publicAPI: UseTreeViewLabelPublicAPI; instance: UseTreeViewLabelInstance; state: UseTreeViewLabelState; diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.ts index 048f429a4fe0a..c24fad0b6bbe5 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.ts @@ -226,7 +226,7 @@ useTreeViewSelection.models = { const DEFAULT_SELECTED_ITEMS: string[] = []; -useTreeViewSelection.getDefaultizedParams = (params) => ({ +useTreeViewSelection.getDefaultizedParams = ({ params }) => ({ ...params, disableSelection: params.disableSelection ?? false, multiSelect: params.multiSelect ?? false, diff --git a/packages/x-tree-view/src/internals/useTreeView/extractPluginParamsFromProps.ts b/packages/x-tree-view/src/internals/useTreeView/extractPluginParamsFromProps.ts index cc81cb92400e2..7cae34f023fad 100644 --- a/packages/x-tree-view/src/internals/useTreeView/extractPluginParamsFromProps.ts +++ b/packages/x-tree-view/src/internals/useTreeView/extractPluginParamsFromProps.ts @@ -54,10 +54,16 @@ export const extractPluginParamsFromProps = < } }); + const cleanExperimentalFeatures = + experimentalFeatures ?? ({} as NonNullable); + const defaultizedPluginParams = plugins.reduce( (acc, plugin: TreeViewPlugin) => { if (plugin.getDefaultizedParams) { - return plugin.getDefaultizedParams(acc); + return plugin.getDefaultizedParams({ + params: acc, + experimentalFeatures: cleanExperimentalFeatures, + }); } return acc; @@ -71,6 +77,6 @@ export const extractPluginParamsFromProps = < pluginParams: defaultizedPluginParams, slots: slots ?? ({} as any), slotProps: slotProps ?? ({} as any), - experimentalFeatures: experimentalFeatures ?? ({} as any), + experimentalFeatures: cleanExperimentalFeatures, }; }; From 0c5331f1c6614784b93012d8c205b7edb62ae6ef Mon Sep 17 00:00:00 2001 From: flavien Date: Thu, 19 Sep 2024 08:36:02 +0200 Subject: [PATCH 2/3] Work --- .../src/internals/plugins/useTreeViewLabel/useTreeViewLabel.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.ts index 90b4e28823dad..ef43558d8394a 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.ts @@ -10,7 +10,6 @@ export const useTreeViewLabel: TreeViewPlugin = ({ state, setState, params, - experimentalFeatures, }) => { const editedItemRef = React.useRef(state.editedItemId); From 263e71b840e8a799a9f3a887c0609baff2571fba Mon Sep 17 00:00:00 2001 From: flavien Date: Wed, 25 Sep 2024 16:28:44 +0200 Subject: [PATCH 3/3] Nora review --- .../useTreeView/extractPluginParamsFromProps.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/x-tree-view/src/internals/useTreeView/extractPluginParamsFromProps.ts b/packages/x-tree-view/src/internals/useTreeView/extractPluginParamsFromProps.ts index 7cae34f023fad..a78619a421d5a 100644 --- a/packages/x-tree-view/src/internals/useTreeView/extractPluginParamsFromProps.ts +++ b/packages/x-tree-view/src/internals/useTreeView/extractPluginParamsFromProps.ts @@ -28,7 +28,7 @@ export const extractPluginParamsFromProps = < TSignatures extends readonly TreeViewPluginSignature[], TProps extends Partial>, >({ - props: { slots, slotProps, apiRef, experimentalFeatures, ...props }, + props: { slots, slotProps, apiRef, experimentalFeatures: inExperimentalFeatures, ...props }, plugins, }: ExtractPluginParamsFromPropsParameters< TSignatures, @@ -54,15 +54,15 @@ export const extractPluginParamsFromProps = < } }); - const cleanExperimentalFeatures = - experimentalFeatures ?? ({} as NonNullable); + const experimentalFeatures = + inExperimentalFeatures ?? ({} as NonNullable); const defaultizedPluginParams = plugins.reduce( (acc, plugin: TreeViewPlugin) => { if (plugin.getDefaultizedParams) { return plugin.getDefaultizedParams({ params: acc, - experimentalFeatures: cleanExperimentalFeatures, + experimentalFeatures, }); } @@ -77,6 +77,6 @@ export const extractPluginParamsFromProps = < pluginParams: defaultizedPluginParams, slots: slots ?? ({} as any), slotProps: slotProps ?? ({} as any), - experimentalFeatures: cleanExperimentalFeatures, + experimentalFeatures, }; };