ant-design/components/form/FormItem/StatusProvider.tsx
二货爱吃白萝卜 0396899ff6
fix: Form.Item noStyle support validation status (#44576)
* fix: FormItem.useStatus can not get status

* fix: noStyle not patch style

* fix: noStyle inhreit logic

* docs: update docs

* test: add test case

* refactor: nostyle block status

* fix: coverage
2023-09-04 10:03:12 +08:00

91 lines
2.6 KiB
TypeScript

import * as React from 'react';
import CheckCircleFilled from '@ant-design/icons/CheckCircleFilled';
import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';
import ExclamationCircleFilled from '@ant-design/icons/ExclamationCircleFilled';
import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
import classNames from 'classnames';
import type { Meta } from 'rc-field-form/lib/interface';
import type { ValidateStatus } from '.';
import { FormItemInputContext, type FormItemStatusContextProps } from '../context';
import { getStatus } from '../util';
const iconMap = {
success: CheckCircleFilled,
warning: ExclamationCircleFilled,
error: CloseCircleFilled,
validating: LoadingOutlined,
};
export interface StatusProviderProps {
children?: React.ReactNode;
validateStatus?: ValidateStatus;
prefixCls: string;
meta: Meta;
errors: React.ReactNode[];
warnings: React.ReactNode[];
hasFeedback?: boolean;
noStyle?: boolean;
}
export default function StatusProvider({
children,
errors,
warnings,
hasFeedback,
validateStatus,
prefixCls,
meta,
noStyle,
}: StatusProviderProps) {
const itemPrefixCls = `${prefixCls}-item`;
const mergedValidateStatus = getStatus(errors, warnings, meta, null, hasFeedback, validateStatus);
const { isFormItemInput: parentIsFormItemInput, status: parentStatus } =
React.useContext(FormItemInputContext);
// ====================== Context =======================
const formItemStatusContext = React.useMemo<FormItemStatusContextProps>(() => {
let feedbackIcon: React.ReactNode;
if (hasFeedback) {
const IconNode = mergedValidateStatus && iconMap[mergedValidateStatus];
feedbackIcon = IconNode ? (
<span
className={classNames(
`${itemPrefixCls}-feedback-icon`,
`${itemPrefixCls}-feedback-icon-${mergedValidateStatus}`,
)}
>
<IconNode />
</span>
) : null;
}
let isFormItemInput: boolean | undefined = true;
let status: ValidateStatus = mergedValidateStatus || '';
// No style will follow parent context
if (noStyle) {
isFormItemInput = parentIsFormItemInput;
status = (mergedValidateStatus ?? parentStatus) || '';
}
return {
status,
errors,
warnings,
hasFeedback,
feedbackIcon,
isFormItemInput,
};
}, [mergedValidateStatus, hasFeedback, noStyle, parentIsFormItemInput, parentStatus]);
// ======================= Render =======================
return (
<FormItemInputContext.Provider value={formItemStatusContext}>
{children}
</FormItemInputContext.Provider>
);
}