| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 | 
							- /* eslint-disable prefer-template, max-len, @typescript-eslint/no-unused-vars */
 
- import React from 'react';
 
- import classNames from 'classnames';
 
- import PropTypes from 'prop-types';
 
- import FormFoundation, { BaseFormAdapter } from '@douyinfe/semi-foundation/form/foundation';
 
- import { strings, cssClasses } from '@douyinfe/semi-foundation/form/constants';
 
- import { getUuidv4 } from '@douyinfe/semi-foundation/utils/uuid';
 
- import warning from '@douyinfe/semi-foundation/utils/warning';
 
- import BaseComponent from '../_base/baseComponent';
 
- import { FormStateContext, FormApiContext, FormUpdaterContext } from './context';
 
- import { isEmptyChildren } from '../_base/reactUtils';
 
- import Row from '../grid/row';
 
- import { cloneDeep } from '../_utils/index';
 
- import Slot from './slot';
 
- import Section from './section';
 
- import Label from './label';
 
- import ErrorMessage from './errorMessage';
 
- import FormInputGroup from './group';
 
- import { noop } from 'lodash';
 
- import '@douyinfe/semi-foundation/form/form.scss';
 
- import {
 
-     FormInput,
 
-     FormInputNumber,
 
-     FormTextArea,
 
-     FormSelect,
 
-     FormCheckboxGroup,
 
-     FormCheckbox,
 
-     FormRadioGroup,
 
-     FormRadio,
 
-     FormDatePicker,
 
-     FormSwitch,
 
-     FormSlider,
 
-     FormTimePicker,
 
-     FormTreeSelect,
 
-     FormCascader,
 
-     FormRating,
 
-     FormAutoComplete,
 
-     FormUpload,
 
-     FormTagInput } from './field';
 
- import {
 
-     BaseFormProps,
 
-     FormState,
 
-     FormApi,
 
-     ErrorMsg
 
- } from './interface';
 
- const prefix = cssClasses.PREFIX;
 
- interface BaseFormState {
 
-     formId: string;
 
- }
 
- class Form extends BaseComponent<BaseFormProps, BaseFormState> {
 
-     static propTypes = {
 
-         'aria-label': PropTypes.string,
 
-         onSubmit: PropTypes.func,
 
-         onSubmitFail: PropTypes.func,
 
-         /* Triggered from update, including field mount/unmount/value change/blur/verification status change/error prompt change, input parameter is formState, currentField */
 
-         onChange: PropTypes.func,
 
-         onReset: PropTypes.func,
 
-         // Triggered when the value of the form is updated, only when the value of the subfield changes. The entry parameter is formState.values
 
-         onValueChange: PropTypes.func,
 
-         initValues: PropTypes.object,
 
-         getFormApi: PropTypes.func,
 
-         component: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
 
-         render: PropTypes.func,
 
-         validateFields: PropTypes.func,
 
-         style: PropTypes.object,
 
-         className: PropTypes.string,
 
-         layout: PropTypes.oneOf(strings.LAYOUT),
 
-         labelPosition: PropTypes.oneOf(strings.LABEL_POS),
 
-         labelWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
 
-         labelAlign: PropTypes.oneOf(strings.LABEL_ALIGN),
 
-         labelCol: PropTypes.object, // Control labelCol {span: number, offset: number} for all field child nodes
 
-         wrapperCol: PropTypes.object, // Control wrapperCol {span: number, offset: number} for all field child nodes
 
-         allowEmpty: PropTypes.bool,
 
-         autoScrollToError: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
 
-         disabled: PropTypes.bool,
 
-         showValidateIcon: PropTypes.bool,
 
-         extraTextPosition: PropTypes.oneOf(strings.EXTRA_POS),
 
-         id: PropTypes.string,
 
-     };
 
-     static defaultProps = {
 
-         onChange: noop,
 
-         onSubmitFail: noop,
 
-         onSubmit: noop,
 
-         onReset: noop,
 
-         onValueChange: noop,
 
-         layout: 'vertical',
 
-         labelPosition: 'top',
 
-         allowEmpty: false,
 
-         autoScrollToError: false,
 
-         showValidateIcon: true,
 
-     };
 
-     static Input = FormInput;
 
-     static TextArea = FormTextArea;
 
-     static InputNumber = FormInputNumber;
 
-     static Select = FormSelect;
 
-     static Checkbox = FormCheckbox;
 
-     static CheckboxGroup = FormCheckboxGroup;
 
-     static Radio = FormRadio;
 
-     static RadioGroup = FormRadioGroup;
 
-     static DatePicker = FormDatePicker;
 
-     static TimePicker = FormTimePicker;
 
-     static Switch = FormSwitch;
 
-     static Slider = FormSlider;
 
-     static TreeSelect = FormTreeSelect;
 
-     static Cascader = FormCascader;
 
-     static Rating = FormRating;
 
-     static AutoComplete = FormAutoComplete;
 
-     static Upload = FormUpload;
 
-     static TagInput = FormTagInput;
 
-     static Slot = Slot;
 
-     static ErrorMessage = ErrorMessage;
 
-     static InputGroup = FormInputGroup;
 
-     static Label = Label;
 
-     static Section = Section;
 
-     formApi: FormApi;
 
-     constructor(props: BaseFormProps) {
 
-         super(props);
 
-         this.state = {
 
-             formId: '',
 
-         };
 
-         warning(
 
-             Boolean(props.component && props.render),
 
-             '[Semi Form] You should not use <Form component> and <Form render> in ths same time; <Form render> will be ignored'
 
-         );
 
-         warning(
 
-             props.component && props.children && !isEmptyChildren(props.children),
 
-             '[Semi Form] You should not use <Form component> and <Form>{children}</Form> in ths same time; <Form>{children}</Form> will be ignored'
 
-         );
 
-         warning(
 
-             props.render && props.children && !isEmptyChildren(props.children),
 
-             '[Semi Form] You should not use <Form render> and <Form>{children}</Form> in ths same time; <Form>{children}</Form> will be ignored'
 
-         );
 
-         this.submit = this.submit.bind(this);
 
-         this.reset = this.reset.bind(this);
 
-         this.foundation = new FormFoundation(this.adapter);
 
-         this.formApi = this.foundation.getFormApi();
 
-         if (this.props.getFormApi) {
 
-             this.props.getFormApi(this.formApi);
 
-         }
 
-     }
 
-     componentDidMount() {
 
-         this.foundation.init();
 
-     }
 
-     componentWillUnmount() {
 
-         this.foundation.destroy();
 
-     }
 
-     get adapter(): BaseFormAdapter<BaseFormProps, BaseFormState> {
 
-         return {
 
-             ...super.adapter,
 
-             cloneDeep,
 
-             notifySubmit: (values: any) => {
 
-                 this.props.onSubmit(values);
 
-             },
 
-             notifySubmitFail: (errors: ErrorMsg, values: any) => {
 
-                 this.props.onSubmitFail(errors, values);
 
-             },
 
-             forceUpdate: (callback?: () => void) => {
 
-                 this.forceUpdate(callback);
 
-             },
 
-             notifyChange: (formState: FormState) => {
 
-                 this.props.onChange(formState);
 
-             },
 
-             notifyValueChange: (values: any, changedValues: any) => {
 
-                 this.props.onValueChange(values, changedValues);
 
-             },
 
-             notifyReset: () => {
 
-                 this.props.onReset();
 
-             },
 
-             initFormId: () => {
 
-                 this.setState({
 
-                     formId: getUuidv4()
 
-                 });
 
-             },
 
-             getInitValues: () => this.props.initValues,
 
-             getFormProps: (keys: undefined | string | Array<string>) => {
 
-                 if (typeof keys === 'undefined') {
 
-                     return this.props;
 
-                 } else if (typeof keys === 'string') {
 
-                     return this.props[keys];
 
-                 } else {
 
-                     const props = {};
 
-                     keys.forEach(key => {
 
-                         props[key] = this.props[key];
 
-                     });
 
-                     return props;
 
-                 }
 
-             },
 
-             getAllErrorDOM: () => {
 
-                 const { formId } = this.state;
 
-                 return document.querySelectorAll(
 
-                     `form[x-form-id="${formId}"] .${cssClasses.PREFIX}-field-error-message`
 
-                 );
 
-             },
 
-             getFieldDOM: (field: string) =>
 
-                 document.querySelector(`.${cssClasses.PREFIX}-field[x-field-id="${field}"]`),
 
-         };
 
-     }
 
-     get content() {
 
-         const { children, component, render } = this.props;
 
-         const formState = this.foundation.getFormState();
 
-         const props = {
 
-             formState,
 
-             formApi: this.foundation.getFormApi(),
 
-             values: formState.values,
 
-         };
 
-         if (component) {
 
-             return React.createElement(component, props);
 
-         }
 
-         if (render) {
 
-             return render(props);
 
-         }
 
-         if (typeof children === 'function') {
 
-             return children(props);
 
-         }
 
-         return children;
 
-     }
 
-     submit(e: React.FormEvent<HTMLFormElement>) {
 
-         e.preventDefault();
 
-         this.foundation.submit();
 
-     }
 
-     reset(e: React.FormEvent<HTMLFormElement>) {
 
-         e.preventDefault();
 
-         this.foundation.reset();
 
-     }
 
-     render() {
 
-         const needClone = false;
 
-         const formState = this.foundation.getFormState(needClone);
 
-         const updaterApi = this.foundation.getModifyFormStateApi();
 
-         const { formId } = this.state;
 
-         const {
 
-             children,
 
-             getFormApi,
 
-             onChange,
 
-             onSubmit,
 
-             onSubmitFail,
 
-             onValueChange,
 
-             component,
 
-             render,
 
-             validateFields,
 
-             initValues,
 
-             layout,
 
-             style,
 
-             className,
 
-             labelPosition,
 
-             labelWidth,
 
-             labelAlign,
 
-             labelCol,
 
-             wrapperCol,
 
-             allowEmpty,
 
-             autoScrollToError,
 
-             showValidateIcon,
 
-             extraTextPosition,
 
-             ...rest
 
-         } = this.props;
 
-         const formCls = classNames(prefix, className, {
 
-             [prefix + '-vertical']: layout === 'vertical',
 
-             [prefix + '-horizontal']: layout === 'horizontal',
 
-         });
 
-         const showldAppendRow = wrapperCol && labelCol;
 
-         const formContent = (
 
-             <form
 
-                 style={style}
 
-                 {...rest}
 
-                 onReset={this.reset}
 
-                 onSubmit={this.submit}
 
-                 className={formCls}
 
-                 x-form-id={formId}
 
-             >
 
-                 {this.content}
 
-             </form>
 
-         );
 
-         const withRowForm = <Row>{formContent}</Row>;
 
-         return (
 
-             <FormUpdaterContext.Provider value={updaterApi}>
 
-                 <FormApiContext.Provider value={this.formApi}>
 
-                     <FormStateContext.Provider value={formState}>
 
-                         {showldAppendRow ? withRowForm : formContent}
 
-                     </FormStateContext.Provider>
 
-                 </FormApiContext.Provider>
 
-             </FormUpdaterContext.Provider>
 
-         );
 
-     }
 
- }
 
- export default Form;
 
 
  |