perf: form item (#1171)
Co-authored-by: sealday <sealday@gmail.com> Reviewed-on: daoyoucloud/tachybase#1171
This commit is contained in:
parent
c1d1a70eaf
commit
943db605c8
@ -1,7 +1,9 @@
|
||||
import { observer, RecursionField, useField, useFieldSchema } from '@tachybase/schema';
|
||||
import { Input, Select } from 'antd';
|
||||
import { differenceBy, unionBy } from 'lodash';
|
||||
import React, { useContext, useMemo, useState } from 'react';
|
||||
import { observer, RecursionField, useField, useFieldSchema } from '@tachybase/schema';
|
||||
|
||||
import { Select, Space } from 'antd';
|
||||
import { differenceBy, unionBy } from 'lodash';
|
||||
|
||||
import {
|
||||
FormProvider,
|
||||
RecordPickerContext,
|
||||
@ -9,7 +11,7 @@ import {
|
||||
SchemaComponentOptions,
|
||||
useActionContext,
|
||||
} from '../..';
|
||||
import { CollectionProvider_deprecated, RecordProvider, useFormBlockContext, useCollectionRecordData } from '../../../';
|
||||
import { CollectionProvider_deprecated, RecordProvider, useCollectionRecordData, useFormBlockContext } from '../../../';
|
||||
import {
|
||||
TableSelectorParamsProvider,
|
||||
useTableSelectorProps as useTsp,
|
||||
@ -133,7 +135,7 @@ export const InternalPicker = observer(
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Input.Group compact style={{ display: 'flex', lineHeight: '32px' }}>
|
||||
<Space.Compact style={{ display: 'flex', lineHeight: '32px' }}>
|
||||
<div style={{ width: '100%' }}>
|
||||
<Select
|
||||
role="button"
|
||||
@ -181,7 +183,7 @@ export const InternalPicker = observer(
|
||||
/>
|
||||
</RecordProvider>
|
||||
)}
|
||||
</Input.Group>
|
||||
</Space.Compact>
|
||||
<ActionContextProvider
|
||||
value={{
|
||||
openSize: fieldSchema['x-component-props']?.['openSize'] || openSize,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { FormItem as Item } from '@tachybase/components';
|
||||
import { Field, observer, useField, useFieldSchema } from '@tachybase/schema';
|
||||
import { Field, useField, useFieldSchema } from '@tachybase/schema';
|
||||
|
||||
import { createStyles } from 'antd-style';
|
||||
import cx from 'classnames';
|
||||
@ -39,68 +39,67 @@ const useStyles = createStyles(({ css }) => {
|
||||
};
|
||||
});
|
||||
|
||||
export const FormItem: any = observer(
|
||||
(props: any) => {
|
||||
const { styles } = useStyles();
|
||||
const { layoutDirection: selfLayoutDirection } = props;
|
||||
const field = useField<Field>();
|
||||
const schema = useFieldSchema();
|
||||
const contextVariable = useContextVariable();
|
||||
const variables = useVariables();
|
||||
const { addActiveFieldName } = useFormActiveFields() || {};
|
||||
const { layoutDirection } = useContextConfigSetting();
|
||||
export const FormItem = (props: any) => {
|
||||
const { styles } = useStyles();
|
||||
const { layoutDirection: selfLayoutDirection } = props;
|
||||
const field = useField<Field>();
|
||||
const schema = useFieldSchema();
|
||||
const contextVariable = useContextVariable();
|
||||
const variables = useVariables();
|
||||
const { addActiveFieldName } = useFormActiveFields() || {};
|
||||
const { layoutDirection } = useContextConfigSetting();
|
||||
|
||||
const finishLayoutDirection = selfLayoutDirection ?? layoutDirection;
|
||||
const finishLayoutDirection = selfLayoutDirection ?? layoutDirection;
|
||||
|
||||
useEffect(() => {
|
||||
variables?.registerVariable(contextVariable);
|
||||
}, [contextVariable]);
|
||||
useEffect(() => {
|
||||
variables?.registerVariable(contextVariable);
|
||||
}, [contextVariable]);
|
||||
|
||||
// 需要放在注冊完变量之后
|
||||
useParseDefaultValue();
|
||||
useLazyLoadDisplayAssociationFieldsOfForm();
|
||||
// 需要放在注冊完变量之后
|
||||
useParseDefaultValue();
|
||||
useLazyLoadDisplayAssociationFieldsOfForm();
|
||||
|
||||
useEffect(() => {
|
||||
addActiveFieldName?.(schema.name as string);
|
||||
}, [addActiveFieldName, schema.name]);
|
||||
useEffect(() => {
|
||||
addActiveFieldName?.(schema.name as string);
|
||||
}, [addActiveFieldName, schema.name]);
|
||||
|
||||
const showTitle = schema['x-decorator-props']?.showTitle ?? true;
|
||||
const showTitle = schema['x-decorator-props']?.showTitle ?? true;
|
||||
|
||||
const extra = useMemo(() => {
|
||||
return typeof field.description === 'string' ? (
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: HTMLEncode(field.description).split('\n').join('<br/>'),
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
field.description
|
||||
);
|
||||
}, [field.description]);
|
||||
const className = useMemo(() => {
|
||||
return cx(
|
||||
styles.space,
|
||||
{
|
||||
[styles.hide]: showTitle === false,
|
||||
},
|
||||
{
|
||||
[styles.row]: finishLayoutDirection === 'row',
|
||||
},
|
||||
);
|
||||
}, [showTitle]);
|
||||
|
||||
return (
|
||||
<CollectionFieldProvider allowNull={true}>
|
||||
<BlockItem className={'tb-form-item'}>
|
||||
<ACLCollectionFieldProvider>
|
||||
<Item className={className} {...props} extra={extra} />
|
||||
</ACLCollectionFieldProvider>
|
||||
</BlockItem>
|
||||
</CollectionFieldProvider>
|
||||
const extra = useMemo(() => {
|
||||
return typeof field.description === 'string' ? (
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: HTMLEncode(field.description).split('\n').join('<br/>'),
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
field.description
|
||||
);
|
||||
},
|
||||
{ displayName: 'FormItem' },
|
||||
);
|
||||
}, [field.description]);
|
||||
const className = useMemo(() => {
|
||||
return cx(
|
||||
styles.space,
|
||||
{
|
||||
[styles.hide]: showTitle === false,
|
||||
},
|
||||
{
|
||||
[styles.row]: finishLayoutDirection === 'row',
|
||||
},
|
||||
);
|
||||
}, [showTitle]);
|
||||
|
||||
return (
|
||||
<CollectionFieldProvider allowNull={true}>
|
||||
<BlockItem className={'tb-form-item'}>
|
||||
<ACLCollectionFieldProvider>
|
||||
<Item className={className} {...props} extra={extra} />
|
||||
</ACLCollectionFieldProvider>
|
||||
</BlockItem>
|
||||
</CollectionFieldProvider>
|
||||
);
|
||||
};
|
||||
|
||||
FormItem.displayName = 'FormItem';
|
||||
|
||||
FormItem.Designer = function Designer() {
|
||||
const app = useApp();
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { Input, Select } from 'antd';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import { Select, Space } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { useFormBlockContext } from '../../block-provider';
|
||||
import { useRecord } from '../../record-provider';
|
||||
import { Variable } from '.././../schema-component';
|
||||
import { useCompatOldVariables } from '../VariableInput/VariableInput';
|
||||
import { useVariableOptions } from '../VariableInput/hooks/useVariableOptions';
|
||||
import { useCompatOldVariables } from '../VariableInput/VariableInput';
|
||||
import { DynamicComponent } from './DynamicComponent';
|
||||
|
||||
const { Option } = Select;
|
||||
@ -104,7 +106,7 @@ export const ValueDynamicComponent = (props: ValueDynamicComponentProps) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Input.Group compact>
|
||||
<Space.Compact>
|
||||
<Select
|
||||
// @ts-ignore
|
||||
role="button"
|
||||
@ -123,6 +125,6 @@ export const ValueDynamicComponent = (props: ValueDynamicComponentProps) => {
|
||||
<Option value="empty">{t('Empty')}</Option>
|
||||
</Select>
|
||||
{modeMap[mode]}
|
||||
</Input.Group>
|
||||
</Space.Compact>
|
||||
);
|
||||
};
|
||||
|
@ -1293,7 +1293,7 @@ export const SchemaSettingsLinkageRules = function LinkageRules(props) {
|
||||
'x-use-component-props': () => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const options = useLinkageCollectionFilterOptions(collectionName);
|
||||
return {
|
||||
const result = {
|
||||
options,
|
||||
defaultValues: gridSchema?.['x-linkage-rules'] || fieldSchema?.['x-linkage-rules'],
|
||||
type,
|
||||
@ -1306,6 +1306,7 @@ export const SchemaSettingsLinkageRules = function LinkageRules(props) {
|
||||
record,
|
||||
formBlockType,
|
||||
};
|
||||
return result;
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1,11 +1,13 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { CheckCircleOutlined, CloseCircleOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
|
||||
import { isVoidField } from '@formily/core';
|
||||
import { connect, mapProps, ReactFC } from '@formily/react';
|
||||
import { Popover, Tooltip } from 'antd';
|
||||
import cls from 'classnames';
|
||||
import React, { useState } from 'react';
|
||||
import { FormLayoutShallowContext } from '../form-layout';
|
||||
import cx from 'classnames';
|
||||
|
||||
import { pickDataProps, usePrefixCls } from '../__builtins__';
|
||||
import { FormLayoutShallowContext } from '../form-layout';
|
||||
import { useFormItemLayout, useOverflow } from './hooks';
|
||||
import useStyle from './style';
|
||||
import { IFormItemProps } from './types';
|
||||
@ -88,7 +90,7 @@ export const BaseItem: React.FC<React.PropsWithChildren<IFormItemProps>> = ({ ch
|
||||
placement="top"
|
||||
content={
|
||||
<div
|
||||
className={cls({
|
||||
className={cx({
|
||||
[`${prefixCls}-${feedbackStatus}-help`]: !!feedbackStatus,
|
||||
[`${prefixCls}-help`]: true,
|
||||
})}
|
||||
@ -155,7 +157,7 @@ export const BaseItem: React.FC<React.PropsWithChildren<IFormItemProps>> = ({ ch
|
||||
if (!label) return null;
|
||||
return (
|
||||
<div
|
||||
className={cls({
|
||||
className={cx({
|
||||
[`${prefixCls}-label`]: true,
|
||||
[`${prefixCls}-label-tooltip`]: (tooltip && tooltipLayout === 'text') || overflow,
|
||||
[`${prefixCls}-item-col-${labelCol}`]: enableCol && !!labelCol,
|
||||
@ -177,7 +179,7 @@ export const BaseItem: React.FC<React.PropsWithChildren<IFormItemProps>> = ({ ch
|
||||
...gridStyles,
|
||||
}}
|
||||
data-grid-span={props.gridSpan}
|
||||
className={cls(
|
||||
className={cx(
|
||||
props.className,
|
||||
{
|
||||
[`${prefixCls}`]: true,
|
||||
@ -211,28 +213,28 @@ export const BaseItem: React.FC<React.PropsWithChildren<IFormItemProps>> = ({ ch
|
||||
>
|
||||
{renderLabel()}
|
||||
<div
|
||||
className={cls({
|
||||
className={cx({
|
||||
[`${prefixCls}-control`]: true,
|
||||
[`${prefixCls}-item-col-${wrapperCol}`]: enableCol && !!wrapperCol && label,
|
||||
})}
|
||||
>
|
||||
<div className={cls(`${prefixCls}-control-content`)}>
|
||||
{addonBefore && <div className={cls(`${prefixCls}-addon-before`)}>{addonBefore}</div>}
|
||||
<div className={cx(`${prefixCls}-control-content`)}>
|
||||
{addonBefore && <div className={cx(`${prefixCls}-addon-before`)}>{addonBefore}</div>}
|
||||
<div
|
||||
style={wrapperStyle}
|
||||
className={cls({
|
||||
className={cx({
|
||||
[`${prefixCls}-control-content-component`]: true,
|
||||
[`${prefixCls}-control-content-component-has-feedback-icon`]: !!feedbackIcon,
|
||||
})}
|
||||
>
|
||||
<FormLayoutShallowContext.Provider value={{}}>{formatChildren}</FormLayoutShallowContext.Provider>
|
||||
{feedbackIcon && <div className={cls(`${prefixCls}-feedback-icon`)}>{feedbackIcon}</div>}
|
||||
{feedbackIcon && <div className={cx(`${prefixCls}-feedback-icon`)}>{feedbackIcon}</div>}
|
||||
</div>
|
||||
{addonAfter && <div className={cls(`${prefixCls}-addon-after`)}>{addonAfter}</div>}
|
||||
{addonAfter && <div className={cx(`${prefixCls}-addon-after`)}>{addonAfter}</div>}
|
||||
</div>
|
||||
{!!feedbackText && feedbackLayout !== 'popover' && feedbackLayout !== 'none' && (
|
||||
<div
|
||||
className={cls({
|
||||
className={cx({
|
||||
[`${prefixCls}-${feedbackStatus}-help`]: !!feedbackStatus,
|
||||
[`${prefixCls}-help`]: true,
|
||||
[`${prefixCls}-help-enter`]: true,
|
||||
@ -242,7 +244,7 @@ export const BaseItem: React.FC<React.PropsWithChildren<IFormItemProps>> = ({ ch
|
||||
{feedbackText}
|
||||
</div>
|
||||
)}
|
||||
{extra && <div className={cls(`${prefixCls}-extra`)}>{extra}</div>}
|
||||
{extra && <div className={cx(`${prefixCls}-extra`)}>{extra}</div>}
|
||||
</div>
|
||||
</div>,
|
||||
);
|
||||
|
@ -3,7 +3,7 @@ import { css, useCollectionManager_deprecated, useRecord, useRequest, useToken }
|
||||
import { connect } from '@tachybase/schema';
|
||||
import { CollectionsGraph, lodash } from '@tachybase/utils/client';
|
||||
|
||||
import { App, Col, Input, Row, Select, Spin, Table, Tag } from 'antd';
|
||||
import { App, Col, Input, Row, Select, Space, Spin, Table, Tag } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const excludeCollections = ['users', 'roles', 'applications'];
|
||||
@ -232,7 +232,7 @@ export const TableTransfer = connect((props) => {
|
||||
`}
|
||||
>
|
||||
<strong style={{ fontSize: token.fontSizeLG, color: token.colorText }}>{t('Unshared collections')}</strong>
|
||||
<Input.Group compact style={{ width: 360 }}>
|
||||
<Space.Compact style={{ width: 360 }}>
|
||||
<Select
|
||||
popupMatchSelectWidth={false}
|
||||
onChange={(value) => {
|
||||
@ -251,7 +251,7 @@ export const TableTransfer = connect((props) => {
|
||||
placeholder={t('Enter name or title...')}
|
||||
allowClear
|
||||
/>
|
||||
</Input.Group>
|
||||
</Space.Compact>
|
||||
</div>
|
||||
<Table
|
||||
bordered
|
||||
@ -317,7 +317,7 @@ export const TableTransfer = connect((props) => {
|
||||
`}
|
||||
>
|
||||
<strong style={{ fontSize: token.fontSizeLG, color: token.colorText }}>{t('Shared collections')}</strong>
|
||||
<Input.Group compact style={{ width: 360 }}>
|
||||
<Space.Compact style={{ width: 360 }}>
|
||||
<Select
|
||||
popupMatchSelectWidth={false}
|
||||
onChange={(value) => {
|
||||
@ -336,7 +336,7 @@ export const TableTransfer = connect((props) => {
|
||||
placeholder={t('Enter name or title...')}
|
||||
allowClear
|
||||
/>
|
||||
</Input.Group>
|
||||
</Space.Compact>
|
||||
</div>
|
||||
<Table
|
||||
bordered
|
||||
|
Loading…
Reference in New Issue
Block a user