import React, { useState, useEffect, useRef, useCallback } from "react"; import classNames from "classnames"; import moment, { Moment } from "moment"; import CalendarPart from "../calendar/CalendarPart"; import { ControlledProps, useDefaultValue } from "../form/controlled"; import { CalendarTable } from "../calendar/CalendarTable"; import { Input } from "../input/Input"; import { DropdownBox } from "../dropdown"; import { CommonDatePickerProps } from "./DatePickerProps"; import { useTranslation } from "../i18n"; import { CalendarTableType, DateChangeContext } from "../calendar/DateProps"; import { Popover } from "../popover/Popover"; import { DatePickerTrigger, isAfter, isBefore } from "./util"; import { useDefault } from "../_util/use-default"; import { useConfig } from "../_util/config-context"; import { Icon } from "../icon"; import { noop } from "../_util/noop"; import { forwardRefWithStatics } from "../_util/forward-ref-with-statics"; import { mergeEventProps } from "../_util/merge-event-props"; import { KeyMap } from "../_util/key-map"; export interface QuarterPickerProps extends CommonDatePickerProps, ControlledProps { /** * 设置不可选季度 * * - `true` 可选 * - `false` 不可选 */ disabledQuarter?: (date: Moment) => boolean; } export const QuarterPicker = forwardRefWithStatics( function QuarterPicker( props: QuarterPickerProps, ref: React.Ref ) { const t = useTranslation(moment); const { classPrefix } = useConfig(); const { header, className, style, value, onChange, onInputValueChange = noop, disabled, format = "YYYY", placeholder = t.selectDate, defaultOpen = false, open, onOpenChange = noop, placement = "bottom-start", placementOffset = 5, closeOnScroll = true, escapeWithReference, popupContainer, overlayClassName, overlayStyle, clearable, } = useDefaultValue(props); const [hover, setHover] = useState(false); // 当前面板类型 const [type, setType] = useState("quarter"); // 当前面板展示时间 const [curViewMoment, setCurViewMoment] = useState( moment.isMoment(value) ? value : getDefaultViewMoment() ); // 当前选中日期 const [curValue, setCurValue] = useState(value); // 选择器是否展开 const [active, setActive] = useDefault(open, defaultOpen, onOpenChange); useEffect(() => { setCurValue(value); // eslint-disable-next-line react-hooks/exhaustive-deps }, [active]); // 输入框显示值 const inputRef = useRef(null); const getInputValue = useCallback( value => { return moment.isMoment(value) ? `${value.locale(t.locale).format(format)}-Q${value .locale(t.locale) .quarter()}` : ""; }, [t.locale, format] ); const [inputValue, setInputValue] = useState( getInputValue(curValue) ); const syncInputValue = useCallback( (value: Moment) => { const inputValue = getInputValue(value); setInputValue(inputValue); onInputValueChange(inputValue, { valid: true }); }, // eslint-disable-next-line react-hooks/exhaustive-deps [getInputValue] ); useEffect(() => { setCurValue(value); syncInputValue(value); }, [format, value, getInputValue, syncInputValue]); useEffect(() => { setCurViewMoment(curValue); }, [curValue, getInputValue]); function getDefaultViewMoment(): Moment { const { range } = props; const m = moment(); // range 判断 if (Array.isArray(range)) { let [start, end] = range; if (!moment.isMoment(start)) { start = moment(0); } if (!moment.isMoment(end)) { end = moment(2 ** 52); } if (isBefore(end, m, "year")) { return end; } if (isAfter(start, m, "year")) { return start; } } return m; } function handleChange(value: Moment, context: DateChangeContext) { setCurValue(value); syncInputValue(value); onChange(value, context); handleClose(); } function handleOpen() { if (disabled) { return; } setActive(true); setType("quarter"); } function handleClose() { syncInputValue(value); setActive(false); } function handleInputChange(content: string) { setInputValue(content); const value = moment(content, format, true); console.log("value: ", moment.isMoment(value)); if (!value.isValid()) { onInputValueChange(content, { valid: false }); return; } // TODO 判断 console.log("getInputValue(value): ", getInputValue(value)); setCurValue(value); onInputValueChange(content, { valid: true }); } function handleKeyDown(event: React.KeyboardEvent) { if (!active) { handleOpen(); return; } switch (event.key) { case KeyMap.Enter: onChange(curValue, { event }); handleClose(); break; case KeyMap.Esc: handleClose(); break; } } return ( {!!header && {header}} } >
setHover(true)} onMouseLeave={() => setHover(false)} > inputRef.current.blur()} onClick={(event: React.MouseEvent) => { if (active) { event.stopPropagation(); } }} /> {clearable && !disabled && ( { event.stopPropagation(); onChange(null, { event }); }} /> )}
); }, { defaultLabelAlign: "middle", } ); QuarterPicker.displayName = "QuarterPicker";