import BaseFoundation, { DefaultAdapter } from '../base/foundation'; import { strings } from './constants'; import type { ArrayElement } from '../utils/type'; import type { Type, DateInputFoundationProps, InsetInputValue } from './inputFoundation'; import type { MonthsGridFoundationProps } from './monthsGridFoundation'; import type { WeekStartNumber } from './_utils/getMonthTable'; export type ValidateStatus = ArrayElement; export type InputSize = ArrayElement; export type Position = ArrayElement; export type PresetPosition = ArrayElement; export type BaseValueType = string | number | Date; export type DayStatusType = { isToday?: boolean; isSelected?: boolean; isDisabled?: boolean; isSelectedStart?: boolean; isSelectedEnd?: boolean; isInRange?: boolean; isHover?: boolean; isOffsetRangeStart?: boolean; isOffsetRangeEnd?: boolean; isHoverInOffsetRange?: boolean; }; export type DisabledDateOptions = { rangeStart?: string; rangeEnd?: string; /** * current select of range type */ rangeInputFocus?: 'rangeStart' | 'rangeEnd' | false; }; export type PresetType = { start?: BaseValueType | (() => BaseValueType); end?: BaseValueType | (() => BaseValueType); text?: string; }; export type TriggerRenderProps = { [x: string]: any; value?: ValueType; inputValue?: string; placeholder?: string | string[]; autoFocus?: boolean; size?: InputSize; disabled?: boolean; inputReadOnly?: boolean; componentProps?: DatePickerFoundationProps; }; export type DateOffsetType = (selectedDate?: Date) => Date; export type DensityType = 'default' | 'compact'; export type DisabledDateType = (date?: Date, options?: DisabledDateOptions) => boolean; export type DisabledTimeType = (date?: Date | Date[], panelType?: string) => ({ disabledHours?: () => number[]; disabledMinutes?: (hour: number) => number[]; disabledSeconds?: (hour: number, minute: number) => number[]; }); export type OnCancelType = (date: Date | Date[], dateStr: string | string[]) => void; export type OnPanelChangeType = (date: Date | Date[], dateStr: string | string[]) => void; export type OnChangeType = (date?: Date | Date[] | string | string[], dateStr?: string | string[] | Date | Date[]) => void; export type OnConfirmType = (date: Date | Date[], dateStr: string | string[]) => void; export type OnPresetClickType = (item: PresetType, e: any) => void; export type PresetsType = Array PresetType)>; export type RenderDateType = (dayNumber?: number, fullDate?: string) => any; export type RenderFullDateType = (dayNumber?: number, fullDate?: string, dayStatus?: DayStatusType) => any; export type TriggerRenderType = (props: TriggerRenderProps) => any; export type ValueType = BaseValueType | BaseValueType[]; export interface ElementProps { bottomSlot?: any; insetLabel?: any; prefix?: any; topSlot?: any; } export interface RenderProps { renderDate?: RenderDateType; renderFullDate?: RenderFullDateType; triggerRender?: TriggerRenderType; } export type RangeType = 'rangeStart' | 'rangeEnd' | false; export interface EventHandlerProps { onCancel?: OnCancelType; onChange?: OnChangeType; onOpenChange?: (status: boolean) => void; onPanelChange?: OnPanelChangeType; onConfirm?: OnConfirmType; onBlur?: (e: any) => void; onClear?: (e: any) => void; onFocus?: (e: any, rangType: RangeType) => void; onPresetClick?: OnPresetClickType; onClickOutSide?: (e: any) => void; } export interface DatePickerFoundationProps extends ElementProps, RenderProps, EventHandlerProps, Pick { autoAdjustOverflow?: boolean; autoFocus?: boolean; autoSwitchDate?: boolean; borderless?: boolean; className?: string; defaultOpen?: boolean; defaultPickerValue?: ValueType; defaultValue?: ValueType; density?: DensityType; disabled?: boolean; disabledDate?: DisabledDateType; disabledTime?: DisabledTimeType; dropdownClassName?: string; dropdownStyle?: Record; endDateOffset?: DateOffsetType; format?: string; getPopupContainer?: () => HTMLElement; inputReadOnly?: boolean; inputStyle?: Record; max?: number; motion?: boolean; multiple?: boolean; needConfirm?: boolean; onChangeWithDateFirst?: boolean; open?: boolean; placeholder?: string | string[]; position?: Position; prefixCls?: string; presets?: PresetsType; presetPosition?: PresetPosition; showClear?: boolean; size?: InputSize; spacing?: number; startDateOffset?: DateOffsetType; stopPropagation?: boolean | string; style?: Record; timePickerOpts?: any; timeZone?: string | number; type?: Type; validateStatus?: ValidateStatus; value?: ValueType; weekStartsOn?: WeekStartNumber; zIndex?: number; syncSwitchMonth?: boolean; hideDisabledOptions?: MonthsGridFoundationProps['hideDisabledOptions']; disabledTimePicker?: MonthsGridFoundationProps['disabledTimePicker']; locale?: any; dateFnsLocale?: any; localeCode?: string; rangeSeparator?: string; insetInput?: DateInputFoundationProps['insetInput']; preventScroll?: boolean; } export interface DatePickerFoundationState { panelShow: boolean; isRange: boolean; /** value of trigger input */ inputValue: string; value: Date[]; cachedSelectedValue: (Date | null)[]; prevTimeZone: string | number; rangeInputFocus: RangeType; autofocus: boolean; /** value of inset input */ insetInputValue: InsetInputValue; triggerDisabled: boolean; } export { Type, DateInputFoundationProps }; export interface DatePickerAdapter extends DefaultAdapter { togglePanel: (panelShow: boolean, cb?: () => void) => void; registerClickOutSide: () => void; unregisterClickOutSide: () => void; notifyBlur: DatePickerFoundationProps['onBlur']; notifyFocus: DatePickerFoundationProps['onFocus']; notifyClear: DatePickerFoundationProps['onClear']; notifyChange: DatePickerFoundationProps['onChange']; notifyCancel: DatePickerFoundationProps['onCancel']; notifyConfirm: DatePickerFoundationProps['onConfirm']; notifyOpenChange: DatePickerFoundationProps['onOpenChange']; notifyPresetsClick: DatePickerFoundationProps['onPresetClick']; updateValue: (value: Date[]) => void; updatePrevTimezone: (prevTimeZone: string | number) => void; updateCachedSelectedValue: (cachedSelectedValue: Date[]) => void; updateInputValue: (inputValue: string) => void; needConfirm: () => boolean; typeIsYearOrMonth: () => boolean; setRangeInputFocus: (rangeInputFocus: DatePickerFoundationState['rangeInputFocus']) => void; couldPanelClosed: () => boolean; isEventTarget: (e: any) => boolean; updateInsetInputValue: (insetInputValue: InsetInputValue) => void; setInsetInputFocus: () => void; setTriggerDisabled: (disabled: boolean) => void; setInputFocus: () => void; setInputBlur: () => void; setRangeInputBlur: () => void; } /** * The datePicker foundation.js is responsible for maintaining the date value and the input box value, as well as the callback of both * task 1. Accept the selected date change, update the date value, and update the input box value according to the date = > Notify the change * task 2. When the input box changes, update the date value = > Notify the change */ export default class DatePickerFoundation extends BaseFoundation { constructor(adapter: DatePickerAdapter); init(): void; initFromProps({ value, timeZone, prevTimeZone }: Pick & { prevTimeZone?: string | number; }): void; /** * 如果用户传了一个空的 value,需要把 range input focus 设置为 rangeStart,这样用户可以清除完之后继续从开始选择 * * If the user passes an empty value, you need to set the range input focus to rangeStart, so that the user can continue to select from the beginning after clearing */ initRangeInputFocus(result: Date[]): void; /** * value 可能是 UTC value 也可能是 zoned value * * UTC value -> 受控传入的 value * * zoned value -> statue.value,保存的是当前计算机时区下选择的日期 * * 如果是时区变化,则需要将旧 zoned value 转为新时区下的 zoned value * * 如果是 value 变化,则不需要传入之前的时区,将 UTC value 转为 zoned value 即可 * */ parseWithTimezone(value: ValueType, timeZone: string | number, prevTimeZone: string | number): Date[]; _isMultiple(): boolean; /** * * Verify and parse the following three format inputs * 1. Date object 2. ISO 9601-compliant string 3. ts timestamp Unified here to format the incoming value and output it as a Date object * */ _parseValue(value: BaseValueType): Date; destroy(): void; initPanelOpenStatus(defaultOpen?: boolean): void; openPanel(): void; /** * clear inset input value when close panel */ clearInsetInputValue(): void; /** * call it when change state value or input value */ resetCachedSelectedValue(willUpdateDates?: Date[]): void; /** * timing to call closePanel * 1. click confirm button * 2. click cancel button * 3. select date, time, year, month * - date type and not multiple, close panel after select date * - dateRange type, close panel after select rangeStart and rangeEnd * 4. click outside */ closePanel(): void; open(): void; close(): void; focus(focusType?: Exclude): void; blur(): void; /** * reset cachedSelectedValue, inputValue when close panel */ resetInnerSelectedStates(): void; resetFocus(e?: any): void; /** * cachedSelectedValue can be `(Date|null)[]` or `null` */ isCachedSelectedValueValid(dates: Date[]): boolean; /** * 将输入框内容置空 */ clearInputValue(): void; /** * clear range input focus when open is controlled * fixed github 1375 */ clearRangeInputFocus: () => void; /** * Callback when the content of the input box changes * Update the date panel if the changed value is a legal date, otherwise only update the input box * @param {String} input The value of the input box after the change * @param {Event} e */ handleInputChange(input: string, e: any): void; /** * inset input 变化时需要更新以下 state 状态 * - insetInputValue(总是) * - inputValue(可以解析为合法日期时) * - value(可以解析为合法日期时) */ handleInsetInputChange(options: { insetInputStr: string; format: string; insetInputValue: InsetInputValue; }): void; /** * when input change we reset cached selected value */ _updateCachedSelectedValueFromInput(input: string): void; /** * Input box blur * @param {String} input * @param {Event} e */ handleInputBlur(input?: string, e?: any): void; /** * called when range type rangeEnd input tab press * @param {Event} e */ handleRangeEndTabPress(e: any): void; /** * called when the input box is focused * @param {Event} e input focus event * @param {String} range 'rangeStart' or 'rangeEnd', use when type is range */ handleInputFocus(e: any, range: 'rangeStart' | 'rangeEnd'): void; handleSetRangeFocus(rangeInputFocus: RangeType): void; handleInputClear(e: any): void; /** * 范围选择清除按钮回调 * 因为清除按钮没有集成在Input内,因此需要手动清除 value、inputValue、cachedValue * * callback of range input clear button * Since the clear button is not integrated in Input, you need to manually clear value, inputValue, cachedValue */ handleRangeInputClear(e: any): void; handleRangeInputBlur(value: any, e: any): void; handleInputComplete(input?: any): void; /** * Parse the input, return the time object if it is valid, * otherwise return " * * @param {string} input * @returns {Date [] | '} */ parseInput(input?: string, format?: string): Date[]; /** * get date which may include null from input */ getLooseDateFromInput(input: string): Array; /** * parse input into `Array`, loose means return value includes `null` * * @example * ```javascript * parseInputLoose('2022-03-15 ~ '); // [Date, null] * parseInputLoose(' ~ 2022-03-15 '); // [null, Date] * parseInputLoose(''); // [] * parseInputLoose('2022-03- ~ 2022-0'); // [null, null] * ``` */ parseInputLoose(input?: string): Array; /** * parse multiple into `Array`, loose means return value includes `null` * * @example * ```javascript * parseMultipleInputLoose('2021-01-01,2021-10-15'); // [Date, Date]; * parseMultipleInputLoose('2021-01-01,2021-10-'); // [Date, null]; * parseMultipleInputLoose(''); // []; * ``` */ parseMultipleInputLoose(input?: string, separator?: string, needDedupe?: boolean): Date[]; /** * Parses the input when multiple is true, if valid, * returns a list of time objects, otherwise returns an array * * @param {string} [input=''] * @param {string} [separator=','] * @param {boolean} [needDedupe=false] * @returns {Date[]} */ parseMultipleInput(input?: string, separator?: string, needDedupe?: boolean): Date[]; /** * dates[] => string * * @param {Date[]} dates * @returns {string} */ formatDates(dates?: Date[], customFormat?: string): string; /** * dates[] => string * * @param {Date[]} dates * @returns {string} */ formatMultipleDates(dates?: Date[], separator?: string, customFormat?: string): string; /** * Update date value and the value of the input box * 1. Select Update * 2. Input Update * @param {Date|''} value * @param {Boolean} forceUpdateValue * @param {String} input */ _updateValueAndInput(value: Date | Array, forceUpdateValue?: boolean, input?: string): void; /** * when changing the selected value through the date panel * @param {*} value * @param {*} options */ handleSelectedChange(value: Date[], options?: { fromPreset?: boolean; needCheckFocusRecord?: boolean; }): void; /** * when changing the year and month through the panel when the type is year or month or monthRange * @param {*} item */ handleYMSelectedChange(item?: { currentMonth?: { left: number; right: number; }; currentYear?: { left: number; right: number; }; }): void; handleConfirm(): void; handleCancel(): void; handlePresetClick(item: PresetType, e: any): void; /** * 根据 type 处理 onChange 返回的参数 * * - 返回的日期需要把用户时间转换为设置的时区时间 * - 用户时间:用户计算机系统时间 * - 时区时间:通过 ConfigProvider 设置的 timeZone * - 例子:用户设置时区为+9,计算机所在时区为+8区,然后用户选择了22:00 * - DatePicker 内部保存日期 state 为 +8 的 22:00 => a = new Date("2021-05-25 22:00:00") * - 传出去时,需要把 +8 的 22:00 => +9 的 22:00 => b = zonedTimeToUtc(a, "+09:00"); * * According to the type processing onChange returned parameters * * - the returned date needs to convert the user time to the set time zone time * - user time: user computer system time * - time zone time: timeZone set by ConfigProvider * - example: the user sets the time zone to + 9, the computer's time zone is + 8 zone, and then the user selects 22:00 * - DatePicker internal save date state is + 8 22:00 = > a = new Date ("2021-05-25 22:00:00") * - when passed out, you need to + 8 22:00 = > + 9 22:00 = > b = zonedTimeToUtc (a, "+ 09:00"); * * e.g. * let a = new Date ("2021-05-25 22:00:00"); * = > Tue May 25 2021 22:00:00 GMT + 0800 (China Standard Time) * let b = zonedTimeToUtc (a, "+ 09:00"); * = > Tue May 25 2021 21:00:00 GMT + 0800 (China Standard Time) * * @param {Date|Date[]} value * @return {{ notifyDate: Date|Date[], notifyValue: string|string[]}} */ disposeCallbackArgs(value: Date | Date[]): { notifyValue: any; notifyDate: any; }; /** * Notice: Check whether the date is the same as the state value before calling * @param {Date[]} value */ _notifyChange(value: Date[]): void; /** * Get the date changed through the date panel or enter */ _getChangedDates(dates: Date[]): any[]; /** * Whether a date is disabled * @param value The date that needs to be judged whether to disable * @param selectedValue Selected date, when selecting a range, pass this date to the second parameter of `disabledDate` */ _someDateDisabled(value: Date[], selectedValue: Date[]): boolean; /** * Format locale date * locale get from LocaleProvider * @param {Date} date * @param {String} token */ localeFormat(date: Date, token: string): string; _isRangeType: () => boolean; _isRangeValueComplete: (value: Date[] | Date) => boolean; /** * Convert computer date to UTC date * Before passing the date to the user, you need to convert the date to UTC time * dispose date from computer date to utc date * When given timeZone prop, you should convert computer date to utc date before passing to user * @param {(date: Date) => Boolean} fn * @param {Date|Date[]} date * @returns {Boolean} */ disposeDateFn(fn: (date: Date, ...rest: any) => boolean, date: Date | Date[], ...rest: any[]): boolean; /** * Determine whether the date is disabled * Whether the date is disabled * @param {Date} date * @returns {Boolean} */ disabledDisposeDate(date: Date, ...rest: any[]): boolean; /** * Determine whether the date is disabled * Whether the date time is disabled * @param {Date|Date[]} date * @returns {Object} */ disabledDisposeTime(date: Date | Date[], ...rest: any[]): boolean; /** * Trigger wrapper needs to do two things: * 1. Open Panel when clicking trigger; * 2. When clicking on a child but the child does not listen to the focus event, manually trigger focus * * @param {Event} e * @returns */ handleTriggerWrapperClick(e: any): void; handlePanelVisibleChange(visible: boolean): void; }