import {ChangeEvent, FocusEvent, KeyboardEvent, MouseEvent} from 'react' import {Input} from '@befe/brick-comp-input' import {createRef, safeInvoke} from '@befe/brick-utils' import {Dayjs} from 'dayjs' import {throughDisabledCheck} from '../utils/through-disabled-check' import {createInnerDatePicker, Type_InnerDatePicker} from './create-inner-date-picker' import {handleUserInputChange} from './handle-user-input-change' import {SingleInputCloseableIcon} from './partial-input-closable-icon' import {CalendarIcon} from './partial-calender-icon' export function createDatePickerUserInput( comp: InstanceType> & Type_InnerDatePicker, defaultIconOpts: CalendarIcon['opts'] ) { const inputRef = createRef() const calendarIcon = new CalendarIcon(defaultIconOpts) function formatInputValue(value: Dayjs | null) { return value ? value.format(comp.computedItemFormat) : '' } function getDisplayedValue() { if (comp.state.isUserInput) { return comp.state.userInputText } const value = comp.state.value return formatInputValue(value) } function renderCalendarIcon() { return calendarIcon.render({ iconSvg: comp.props.iconSvg, iconNode: comp.props.iconNode, onClick: comp.handleCalendarIconClick, }) } const closeableIcon = new SingleInputCloseableIcon(comp, { hoverState: 'isHoverOverCalendar', isClearable: () => !!comp.props.clearable, isDisabled: () => !!comp.props.disabled, hasValue: () => !!getDisplayedValue(), // eslint-disable-next-line @typescript-eslint/no-use-before-define renderNode: renderCalendarIcon, isFocus: () => comp.state.isUserInput, onClear: () => { const showTime = Boolean(comp.props.showTime) comp.setState({ value: null, isUserInput: showTime, open: false, userInputText: '', timeState: { hour: undefined, minute: undefined, second: undefined, }, }) comp.setOpen(showTime, null) comp.changeValue(null) comp.processOpenStatus({ open: showTime, isUserInput: showTime, }) }, }) function renderSuffix() { return closeableIcon.render() } const startUserInput = (e: FocusEvent) => { const onFocus = comp.props.onFocus onFocus && onFocus(e) comp.setState({ isUserInput: true, isZooming: false, userInputText: getDisplayedValue(), }) comp.setOpen(true) comp.processOpenStatus({ open: true, isUserInput: true, }) inputRef.elem!.elemInput.select() } // eslint-disable-next-line @typescript-eslint/no-unused-vars const completeUserInput = (e: FocusEvent) => { comp.setState({ open: false, isUserInput: false, }) comp.processOpenStatus({ open: false, isUserInput: false, }) const onBlur = comp.props.onBlur onBlur && onBlur(e) } const handleChange = (e: ChangeEvent) => { /** * @note: 有任何的更改, 需要确保 isUserInput 被打开, 因为可能被用户用 `Enter` 关闭面板了 */ comp.setState({ isUserInput: true, }); handleUserInputChange({ e, comp, itemFormatProp: 'computedItemFormat', valueProp: 'value', displayedProp: 'displayedDate', inputTextProp: 'userInputText', isInputProp: 'isUserInput', onCustomChange: (value, displayedDate) => { const getDisabledItem = comp.props.getDisabledItem value = throughDisabledCheck(value, getDisabledItem) comp.setState({ value, displayedDate, }) comp.changeValue(value, { onStateChanged: () => { comp.tryScrollToSelectedTime() }, }) }, }) } const handleKeyDown = (e: KeyboardEvent) => { const code = e.nativeEvent.code; if (code === 'Tab' || code === 'Enter') { comp.setState({ open: false, isUserInput: false, }) comp.processOpenStatus({ open: false, isUserInput: false, }) } } const iconHooks = closeableIcon.hooks const handleMouseDown = () => { if (inputRef.elem?.elemInput === document.activeElement) { comp.setState({ isUserInput: true, }) } } const handleMouseEnter = (e: MouseEvent) => { safeInvoke(comp.props.onMouseEnter, e) iconHooks.mouseEnter() } const handleMouseLeave = (e: MouseEvent) => { safeInvoke(comp.props.onMouseLeave, e) iconHooks.mouseLeave() } return { renderInput() { const size = comp.size; const { placeholder, status, disabled, autoFocus, } = comp.props return ( ) }, formatInputValue, get inputElem() { return inputRef.elem ? inputRef.elem.elemInput : undefined }, } }