Skip to content

Commit

Permalink
Work
Browse files Browse the repository at this point in the history
  • Loading branch information
flaviendelangle committed Jun 6, 2024
1 parent 7ca19ba commit fa5ae4e
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ import {
TreeViewPublicAPI,
} from '../models';

export type TreeViewItemPluginsRunner = <TProps extends {}>(
props: TProps,
) => Required<TreeViewItemPluginResponse>;

export type TreeViewContextValue<TSignatures extends readonly TreeViewAnyPluginSignature[]> =
MergeSignaturesProperty<TSignatures, 'contextValue'> & {
instance: TreeViewInstance<TSignatures>;
publicAPI: TreeViewPublicAPI<TSignatures>;
rootRef: React.RefObject<HTMLUListElement>;
wrapItem: TreeItemWrapper<TSignatures>;
wrapRoot: TreeRootWrapper<TSignatures>;
runItemPlugins: <TProps extends {}>(props: TProps) => Required<TreeViewItemPluginResponse>;
runItemPlugins: TreeViewItemPluginsRunner;
};

export interface TreeViewProviderProps<TSignatures extends readonly TreeViewAnyPluginSignature[]> {
Expand Down
6 changes: 5 additions & 1 deletion packages/x-tree-view/src/internals/TreeViewProvider/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
export { TreeViewProvider } from './TreeViewProvider';
export type { TreeViewProviderProps, TreeViewContextValue } from './TreeViewProvider.types';
export type {
TreeViewProviderProps,
TreeViewContextValue,
TreeViewItemPluginsRunner,
} from './TreeViewProvider.types';
6 changes: 3 additions & 3 deletions packages/x-tree-view/src/internals/models/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ export type MergeSignaturesProperty<
export type ConvertPluginsIntoSignatures<
TPlugins extends readonly TreeViewPlugin<TreeViewAnyPluginSignature>[],
> = TPlugins extends readonly [plugin: infer TPlugin, ...otherPlugin: infer R]
? R extends readonly TreeViewPlugin<TreeViewAnyPluginSignature>[]
? R extends readonly TreeViewPlugin<any>[]
? TPlugin extends TreeViewPlugin<infer TSignature>
? readonly [TSignature, ...ConvertPluginsIntoSignatures<R>]
: never
: never
: never;
: [];

export type ConvertSignaturesIntoPlugins<
TSignatures extends readonly TreeViewAnyPluginSignature[],
Expand All @@ -49,4 +49,4 @@ export type ConvertSignaturesIntoPlugins<
? readonly [TreeViewPlugin<TSignature>, ...ConvertSignaturesIntoPlugins<R>]
: never
: never
: never;
: [];
116 changes: 59 additions & 57 deletions packages/x-tree-view/src/internals/useTreeView/useTreeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>(
Expand Down Expand Up @@ -79,48 +79,33 @@ export const useTreeView = <TSignatures extends readonly TreeViewAnyPluginSignat
return temp;
});

const rootPropsGetters: (<TOther extends EventHandlers = {}>(
otherHandlers: TOther,
) => React.HTMLAttributes<HTMLUListElement>)[] = [];
const contextValue = {
publicAPI,
instance: instance as TreeViewInstance<any>,
rootRef: innerRootRef,
} as TreeViewContextValue<TSignatures>;

const runPlugin = (plugin: TreeViewPlugin<TreeViewAnyPluginSignature>) => {
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<any> => !!wrapItem);
const wrapItem: TreeItemWrapper<TSignatures> = ({ 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<any> => !!wrapRoot)
// The wrappers are reversed to ensure that the first wrapper is the outermost one.
.reverse();
const wrapRoot: TreeRootWrapper<TSignatures> = ({ 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<HTMLLIElement> | null = null;
let finalContentRef: React.RefCallback<HTMLElement> | null = null;

Expand Down Expand Up @@ -148,33 +133,50 @@ export const useTreeView = <TSignatures extends readonly TreeViewAnyPluginSignat
};
};

const itemWrappers = plugins
.map((plugin) => plugin.wrapItem)
.filter((wrapItem): wrapItem is TreeItemWrapper<any> => !!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<any>,
rootRef: innerRootRef,
} as TreeViewContextValue<TSignatures>;

const rootPropsGetters: (<TOther extends EventHandlers = {}>(
otherHandlers: TOther,
) => React.HTMLAttributes<HTMLUListElement>)[] = [];
const runPlugin = (plugin: TreeViewPlugin<TreeViewAnyPluginSignature>) => {
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<any> => !!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 = <TOther extends EventHandlers = {}>(
otherHandlers: TOther = {} as TOther,
) => {
Expand Down

0 comments on commit fa5ae4e

Please sign in to comment.