import type { DSize } from '../../utils/types';
import React from 'react';
import { getClassName } from '@react-devui/utils';
import { registerComponentMate } from '../../utils';
import { useComponentConfig, usePrefixConfig } from '../root';
import { DFormGroup } from './FormGroup';
import { DFormItem } from './FormItem';
import { DFormUpdateContext } from './hooks';
export interface DFormContextData {
gLabelWidth: NonNullable<DFormProps['dLabelWidth']>;
gLabelColon: NonNullable<DFormProps['dLabelColon']>;
gRequiredType: NonNullable<DFormProps['dRequiredType']>;
gLayout: NonNullable<DFormProps['dLayout']>;
gInlineSpan: NonNullable<DFormProps['dInlineSpan']>;
gFeedbackIcon: NonNullable<DFormProps['dFeedbackIcon']>;
gSize?: DSize;
}
export const DFormContext = React.createContext<DFormContextData | null>(null);
export interface DFormProps extends React.FormHTMLAttributes<HTMLFormElement> {
dUpdate: () => void;
dLabelWidth?: number | string;
dLabelColon?: boolean;
dRequiredType?: 'required' | 'optional' | 'hidden';
dLayout?: 'horizontal' | 'vertical' | 'inline';
dInlineSpan?: number | true;
dFeedbackIcon?:
| boolean
| {
success?: React.ReactNode;
warning?: React.ReactNode;
error?: React.ReactNode;
pending?: React.ReactNode;
};
dSize?: DSize;
}
const { COMPONENT_NAME } = registerComponentMate({ COMPONENT_NAME: 'DForm' as const });
export const DForm: {
(props: DFormProps): JSX.Element | null;
Group: typeof DFormGroup;
Item: typeof DFormItem;
} = (props) => {
const {
children,
dUpdate,
dLabelWidth,
dLabelColon,
dRequiredType = 'required',
dLayout = 'horizontal',
dInlineSpan = 6,
dFeedbackIcon = false,
dSize,
...restProps
} = useComponentConfig(COMPONENT_NAME, props);
const dPrefix = usePrefixConfig();
return (
<DFormContext.Provider
value={{
gLabelWidth: dLabelWidth ?? (dLayout === 'vertical' ? '100%' : 150),
gLabelColon: dLabelColon ?? (dLayout === 'vertical' ? false : true),
gRequiredType: dRequiredType,
gLayout: dLayout,
gInlineSpan: dInlineSpan,
gFeedbackIcon: dFeedbackIcon,
gSize: dSize,
}}
>
<DFormUpdateContext.Provider value={dUpdate}>
<form
{...restProps}
className={getClassName(restProps.className, `${dPrefix}form`, {
[`${dPrefix}form--${dSize}`]: dSize,
[`${dPrefix}form--${dLayout}`]: dLayout,
})}
autoComplete={restProps.autoComplete ?? 'off'}
onSubmit={(e) => {
restProps.onSubmit?.(e);
e.preventDefault();
e.stopPropagation();
}}
>
{children}
</form>
</DFormUpdateContext.Provider>
</DFormContext.Provider>
);
};
DForm.Group = DFormGroup;
DForm.Item = DFormItem;