From 569413a7d02354105a168f7a5e6669aa08fec375 Mon Sep 17 00:00:00 2001 From: Flavien DELANGLE Date: Tue, 16 Jul 2024 14:27:08 +0200 Subject: [PATCH] [TreeView] Extract some logic outside of the `useTreeView` hook (#13845) --- .../src/internals/useTreeView/useTreeView.ts | 76 ++-------------- .../useTreeView/useTreeViewBuildContext.ts | 86 +++++++++++++++++++ .../useTreeView/useTreeViewPlugins.ts | 0 3 files changed, 94 insertions(+), 68 deletions(-) create mode 100644 packages/x-tree-view/src/internals/useTreeView/useTreeViewBuildContext.ts create mode 100644 packages/x-tree-view/src/internals/useTreeView/useTreeViewPlugins.ts diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts index fef78939ab09b..ca3022d1938ac 100644 --- a/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeView.ts @@ -6,8 +6,6 @@ import { TreeViewInstance, TreeViewPlugin, MergeSignaturesProperty, - TreeItemWrapper, - TreeRootWrapper, TreeViewPublicAPI, ConvertSignaturesIntoPlugins, } from '../models'; @@ -18,9 +16,9 @@ import { UseTreeViewRootSlotProps, } from './useTreeView.types'; import { useTreeViewModels } from './useTreeViewModels'; -import { TreeViewContextValue, TreeViewItemPluginsRunner } from '../TreeViewProvider'; import { TREE_VIEW_CORE_PLUGINS, TreeViewCorePluginSignatures } from '../corePlugins'; import { extractPluginParamsFromProps } from './extractPluginParamsFromProps'; +import { useTreeViewBuildContext } from './useTreeViewBuildContext'; export function useTreeViewApiInitialization( inputApiRef: React.MutableRefObject | undefined, @@ -63,12 +61,17 @@ export const useTreeView = < const models = useTreeViewModels(plugins, pluginParams); const instanceRef = React.useRef({} as TreeViewInstance); const instance = instanceRef.current as TreeViewInstance; - const publicAPI = useTreeViewApiInitialization>(apiRef); - const innerRootRef: React.RefObject = React.useRef(null); const handleRootRef = useForkRef(innerRootRef, rootRef); + const contextValue = useTreeViewBuildContext({ + plugins, + instance, + publicAPI, + rootRef: innerRootRef, + }); + const [state, setState] = React.useState(() => { const temp = {} as MergeSignaturesProperty; plugins.forEach((plugin) => { @@ -80,69 +83,6 @@ export const useTreeView = < return temp; }); - 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 }); - }); - - return finalChildren; - }; - - 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 }); - }); - - return finalChildren; - }; - - const runItemPlugins: TreeViewItemPluginsRunner = (itemPluginProps) => { - let finalRootRef: React.RefCallback | null = null; - let finalContentRef: React.RefCallback | null = null; - - plugins.forEach((plugin) => { - if (!plugin.itemPlugin) { - return; - } - - const itemPluginResponse = plugin.itemPlugin({ - props: itemPluginProps, - rootRef: finalRootRef, - contentRef: finalContentRef, - }); - if (itemPluginResponse?.rootRef) { - finalRootRef = itemPluginResponse.rootRef; - } - if (itemPluginResponse?.contentRef) { - finalContentRef = itemPluginResponse.contentRef; - } - }); - - return { - contentRef: finalContentRef, - rootRef: finalRootRef, - }; - }; - - const contextValue = { - publicAPI, - wrapItem, - wrapRoot, - runItemPlugins, - instance: instance as TreeViewInstance, - rootRef: innerRootRef, - } as TreeViewContextValue; - const rootPropsGetters: (( otherHandlers: TOther, ) => React.HTMLAttributes)[] = []; diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeViewBuildContext.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeViewBuildContext.ts new file mode 100644 index 0000000000000..f114dafa377a9 --- /dev/null +++ b/packages/x-tree-view/src/internals/useTreeView/useTreeViewBuildContext.ts @@ -0,0 +1,86 @@ +import * as React from 'react'; +import { TreeViewContextValue, TreeViewItemPluginsRunner } from '../TreeViewProvider'; +import { + ConvertSignaturesIntoPlugins, + TreeItemWrapper, + TreeRootWrapper, + TreeViewAnyPluginSignature, + TreeViewInstance, + TreeViewPublicAPI, +} from '../models'; +import { TreeViewCorePluginSignatures } from '../corePlugins'; + +export const useTreeViewBuildContext = ({ + plugins, + instance, + publicAPI, + rootRef, +}: { + plugins: ConvertSignaturesIntoPlugins; + instance: TreeViewInstance; + publicAPI: TreeViewPublicAPI; + rootRef: React.RefObject; +}): TreeViewContextValue => { + const runItemPlugins: TreeViewItemPluginsRunner = (itemPluginProps) => { + let finalRootRef: React.RefCallback | null = null; + let finalContentRef: React.RefCallback | null = null; + + plugins.forEach((plugin) => { + if (!plugin.itemPlugin) { + return; + } + + const itemPluginResponse = plugin.itemPlugin({ + props: itemPluginProps, + rootRef: finalRootRef, + contentRef: finalContentRef, + }); + if (itemPluginResponse?.rootRef) { + finalRootRef = itemPluginResponse.rootRef; + } + if (itemPluginResponse?.contentRef) { + finalContentRef = itemPluginResponse.contentRef; + } + }); + + return { + contentRef: finalContentRef, + rootRef: finalRootRef, + }; + }; + + const wrapItem: TreeItemWrapper = ({ itemId, children }) => { + let finalChildren: React.ReactNode = children; + // The wrappers are reversed to ensure that the first wrapper is the outermost one. + for (let i = plugins.length - 1; i >= 0; i -= 1) { + const plugin = plugins[i]; + if (plugin.wrapItem) { + finalChildren = plugin.wrapItem({ itemId, children: finalChildren, instance }); + } + } + + return finalChildren; + }; + + const wrapRoot: TreeRootWrapper = ({ children }) => { + let finalChildren: React.ReactNode = children; + // The wrappers are reversed to ensure that the first wrapper is the outermost one. + for (let i = plugins.length - 1; i >= 0; i -= 1) { + const plugin = plugins[i]; + if (plugin.wrapRoot) { + finalChildren = plugin.wrapRoot({ children: finalChildren, instance }); + } + } + + return finalChildren; + }; + + return { + runItemPlugins, + wrapItem, + wrapRoot, + instance, + rootRef, + publicAPI, + } as TreeViewContextValue; +}; diff --git a/packages/x-tree-view/src/internals/useTreeView/useTreeViewPlugins.ts b/packages/x-tree-view/src/internals/useTreeView/useTreeViewPlugins.ts new file mode 100644 index 0000000000000..e69de29bb2d1d