import React, { ReactElement } from 'react' import { Observer } from 'mobx-react' import { DebouncedState, IState } from 'formstate-x' import * as base from 'react-icecream' import { InputWrapper } from './FormItem' interface CommonInputProps { value?: V } interface CommonCheckboxProps { checked?: boolean onChange?: (checked: boolean) => void } /** 从 Input 控件的 props 类型中取出 value 的类型 */ type ValueOf

= P extends CommonInputProps ? V : never export type WithState

> = Omit & { /** 当前字段所对应的状态 */ state: IState> } function isDebouncedState(state: IState): state is DebouncedState, V> { return state instanceof DebouncedState } /** Bind state to normal input components, such as `TextInput`, `Select`, ... */ export function bindInput(state: IState) { const uiState = isDebouncedState(state) ? state.$ : state return { value: uiState.value, onChange(value: V) { uiState.onChange(value) } } } function useFieldState

>( { state, ...restProps }: WithState

, render: (props: P) => ReactElement | null ) { return ( { const inputBindings = bindInput(state) const inputProps = { ...restProps, ...inputBindings } as unknown as P return render(inputProps) }} /> ) } // 用于对 common checkbox(即 Checkbox & Radio)的适配 export type WithStateForCommonCheckbox

= Omit & { /** 当前字段所对应的状态 */ state?: IState } /** Bind state to input components which use `checked` as value, such as `Checkbox`, `Radio`, `Switch` */ export function bindCheckedInput(state: IState) { const { value, onChange } = bindInput(state) return { checked: value, onChange } } function useFieldStateForCommonCheckbox

( { state, ...restProps }: WithStateForCommonCheckbox

, render: (props: P) => ReactElement | null ) { return ( { const inputBindings = state != null ? bindCheckedInput(state) : undefined const inputProps = { ...restProps, ...inputBindings } as P return render(inputProps) }} /> ) } export type TextInputProps = WithState export function TextInput(props: TextInputProps) { return useFieldState(props, inputProps => ( )) } export type PasswordInputProps = WithState export function PasswordInput(props: PasswordInputProps) { return useFieldState(props, inputProps => ( )) } export type NumberInputProps = WithState export function NumberInput(props: NumberInputProps) { return useFieldState(props, inputProps => ( )) } export type TextAreaProps = WithState export function TextArea(props: TextAreaProps) { return useFieldState(props, inputProps => ( )) } export type DatePickerProps = WithState export function DatePicker(props: DatePickerProps) { return useFieldState(props, inputProps => ( )) } export type RangeDatePickerProps = WithState export function RangeDatePicker(props: RangeDatePickerProps) { return useFieldState(props, inputProps => ( )) } export type SelectProps = WithState> export function Select(props: SelectProps) { return useFieldState>(props, inputProps => ( )) } export type MultiSelectProps = WithState> export function MultiSelect(props: MultiSelectProps) { return useFieldState>(props, inputProps => ( )) } export type CheckboxGroupProps< T extends base.CheckboxValue = base.CheckboxValue > = WithState> export function CheckboxGroup( props: CheckboxGroupProps ) { return useFieldState>(props, inputProps => ( )) } export type CheckboxProps< T extends base.CheckboxValue = base.CheckboxValue > = WithStateForCommonCheckbox> export function Checkbox( props: CheckboxProps ) { return useFieldStateForCommonCheckbox(props, inputProps => ( )) } export type RadioGroupProps = WithState> export function RadioGroup(props: RadioGroupProps) { return useFieldState>(props, inputProps => ( )) } export type RadioProps< T extends base.RadioValue = base.RadioValue > = WithStateForCommonCheckbox> export function Radio( props: RadioProps ) { return useFieldStateForCommonCheckbox(props, inputProps => ( )) } export type SwitchProps = Omit & { /** 当前字段所对应的状态 */ state: IState } function useFieldStateForSwitch

( { state, ...restProps }: SwitchProps, render: (props: P) => ReactElement | null ) { return ( { const inputBindings = bindCheckedInput(state) const inputProps = { ...restProps, ...inputBindings } as P return render(inputProps) }} /> ) } export function Switch(props: SwitchProps) { return useFieldStateForSwitch(props, inputProps => ( )) } export type CascaderProps = WithState> export function Cascader(props: CascaderProps) { return useFieldState>(props, inputProps => ( )) } export type MultiCascaderProps = WithState> export function MultiCascader(props: MultiCascaderProps) { return useFieldState>(props, inputProps => ( )) } export type AutoCompleteProps = WithState export function AutoComplete(props: AutoCompleteProps) { return useFieldState(props, inputProps => ( )) } export type TagsInputProps = WithState export function TagsInput(props: TagsInputProps) { return useFieldState(props, inputProps => ( )) } export type SliderProps = WithState export function Slider(props: SliderProps) { return useFieldState(props, inputProps => ( )) } export type UploadProps = WithState export function Upload(props: UploadProps) { return useFieldState(props, inputProps => ( )) } export type DragUploadProps = WithState export function DragUpload(props: DragUploadProps) { return useFieldState(props, inputProps => ( )) }