nocobase/packages/core/client/src/hoc/withDynamicSchemaProps.tsx
Zeke Zhang ef8e4aed48
fix(filter-form): fix operator not valid in block templates (#4390)
* fix(filter-form): fix operator not valid in block templates

* test: add e2e test

* test: clear data templates

* chore: fix e2e tests

* chore: stash

* chore: change import path to fix unit tests

* chore: change import path to fix unit tests

* chore: fix build
2024-05-20 16:50:34 +08:00

96 lines
2.8 KiB
TypeScript

/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { useExpressionScope } from '@formily/react';
import _ from 'lodash';
import React, { ComponentType, useMemo } from 'react';
import { useDesignable } from '../schema-component';
const useDefaultDynamicComponentProps = () => undefined;
const getHook = (str: string, scope: Record<string, any>, allText: string) => {
let res = undefined;
if (_.isFunction(str)) {
res = str;
} else {
res = scope[str];
if (!res) {
console.error(`${allText} is not registered`);
}
}
return res || useDefaultDynamicComponentProps;
};
export function useDynamicComponentProps(useComponentPropsStr?: string, props?: any) {
const scope = useExpressionScope();
const useDynamicProps = useMemo(() => {
if (!useComponentPropsStr) {
return useDefaultDynamicComponentProps;
}
if (_.isFunction(useComponentPropsStr)) {
return useComponentPropsStr;
}
const pathList = useComponentPropsStr.split('.');
let result;
for (const item of pathList) {
result = getHook(item, result || scope, useComponentPropsStr);
}
return result;
}, [useComponentPropsStr]);
const res = useDynamicProps(props);
return res;
}
interface WithSchemaHookOptions {
displayName?: string;
}
export function withDynamicSchemaProps<T = any>(
Component: React.ComponentType<T>,
options: WithSchemaHookOptions = {},
) {
const displayName = options.displayName || Component.displayName || Component.name;
const ComponentWithProps: ComponentType<T> = (props) => {
const { dn, findComponent } = useDesignable();
const useComponentPropsStr = useMemo(() => {
const xComponent = dn.getSchemaAttribute('x-component');
const xDecorator = dn.getSchemaAttribute('x-decorator');
const xUseComponentProps = dn.getSchemaAttribute('x-use-component-props');
const xUseDecoratorProps = dn.getSchemaAttribute('x-use-decorator-props');
if (xComponent && xUseComponentProps && findComponent(xComponent) === ComponentWithProps) {
return xUseComponentProps;
}
if (xDecorator && xUseDecoratorProps && findComponent(xDecorator) === ComponentWithProps) {
return xUseDecoratorProps;
}
}, [dn]);
const schemaProps = useDynamicComponentProps(useComponentPropsStr, props);
const memoProps = useMemo(() => {
return { ...props, ...schemaProps };
}, [schemaProps, props]);
return <Component {...memoProps}>{props.children}</Component>;
};
Component.displayName = displayName;
ComponentWithProps.displayName = `withSchemaProps(${displayName})`;
return ComponentWithProps;
}