Merge branch 'refactor-date' of github.com:vueComponent/ant-design-vue into refactor-date
# Conflicts: # components/vc-picker/generate/dayjs.ts # components/vc-picker/generate/moment.ts # v2-docpull/4499/head
							parent
							
								
									a501b592a2
								
							
						
					
					
						commit
						16fc2a10a9
					
				| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
export type FocusEventHandler = (e: FocusEvent) => void;
 | 
			
		||||
export type MouseEventHandler = (e: MouseEvent) => void;
 | 
			
		||||
export type KeyboardEventHandler = (e: KeyboardEvent) => void;
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
import type { Ref } from 'vue';
 | 
			
		||||
import type { Ref, WatchSource } from 'vue';
 | 
			
		||||
import { ref, watch } from 'vue';
 | 
			
		||||
 | 
			
		||||
export default function useMemo<T>(
 | 
			
		||||
  getValue: () => T,
 | 
			
		||||
  condition: any[],
 | 
			
		||||
  condition: (WatchSource<unknown> | object)[],
 | 
			
		||||
  shouldUpdate?: (prev: any[], next: any[]) => boolean,
 | 
			
		||||
) {
 | 
			
		||||
  const cacheRef: Ref<T> = ref(getValue() as any);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
import type { Ref, UnwrapRef } from 'vue';
 | 
			
		||||
import { watchEffect } from 'vue';
 | 
			
		||||
import { unref } from 'vue';
 | 
			
		||||
import { watch } from 'vue';
 | 
			
		||||
import { ref } from 'vue';
 | 
			
		||||
 | 
			
		||||
export default function useMergedState<T, R = Ref<T>>(
 | 
			
		||||
  defaultStateValue: T | (() => T),
 | 
			
		||||
  option?: {
 | 
			
		||||
    defaultValue?: T | (() => T);
 | 
			
		||||
    value?: Ref<T> | Ref<UnwrapRef<T>>;
 | 
			
		||||
    onChange?: (val: T, prevValue: T) => void;
 | 
			
		||||
    postState?: (val: T) => T;
 | 
			
		||||
  },
 | 
			
		||||
): [R, (val: T) => void] {
 | 
			
		||||
  const { defaultValue, value } = option || {};
 | 
			
		||||
  let initValue: T =
 | 
			
		||||
    typeof defaultStateValue === 'function' ? (defaultStateValue as any)() : defaultStateValue;
 | 
			
		||||
  if (value.value !== undefined) {
 | 
			
		||||
    initValue = unref(value as any) as T;
 | 
			
		||||
  }
 | 
			
		||||
  if (defaultValue !== undefined) {
 | 
			
		||||
    initValue = typeof defaultValue === 'function' ? (defaultValue as any)() : defaultValue;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const innerValue = ref(initValue) as Ref<T>;
 | 
			
		||||
  const mergedValue = ref(initValue) as Ref<T>;
 | 
			
		||||
  watchEffect(() => {
 | 
			
		||||
    let val = value.value !== undefined ? value.value : innerValue.value;
 | 
			
		||||
    if (option.postState) {
 | 
			
		||||
      val = option.postState(val as T);
 | 
			
		||||
    }
 | 
			
		||||
    mergedValue.value = val as T;
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  function triggerChange(newValue: T) {
 | 
			
		||||
    const preVal = mergedValue.value;
 | 
			
		||||
    innerValue.value = newValue;
 | 
			
		||||
    if (mergedValue.value !== newValue && option.onChange) {
 | 
			
		||||
      option.onChange(newValue, preVal);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Effect of reset value to `undefined`
 | 
			
		||||
  watch(value, () => {
 | 
			
		||||
    innerValue.value = value.value as T;
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return [mergedValue as unknown as R, triggerChange];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
import type { Ref } from 'vue';
 | 
			
		||||
import { ref } from 'vue';
 | 
			
		||||
 | 
			
		||||
export default function useState<T, R = Ref<T>>(
 | 
			
		||||
  defaultStateValue: T | (() => T),
 | 
			
		||||
): [R, (val: T) => void] {
 | 
			
		||||
  const initValue: T =
 | 
			
		||||
    typeof defaultStateValue === 'function' ? (defaultStateValue as any)() : defaultStateValue;
 | 
			
		||||
 | 
			
		||||
  const innerValue = ref(initValue) as Ref<T>;
 | 
			
		||||
 | 
			
		||||
  function triggerChange(newValue: T) {
 | 
			
		||||
    innerValue.value = newValue;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return [innerValue as unknown as R, triggerChange];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -9,22 +9,21 @@ export type ContextOperationRefProps = {
 | 
			
		|||
export type PanelContextProps = {
 | 
			
		||||
  operationRef?: Ref<ContextOperationRefProps | null>;
 | 
			
		||||
  /** Only work with time panel */
 | 
			
		||||
  hideHeader?: boolean;
 | 
			
		||||
  hideHeader?: Ref<boolean>;
 | 
			
		||||
  panelRef?: Ref<HTMLDivElement>;
 | 
			
		||||
  hidePrevBtn?: boolean;
 | 
			
		||||
  hideNextBtn?: boolean;
 | 
			
		||||
  hidePrevBtn?: Ref<boolean>;
 | 
			
		||||
  hideNextBtn?: Ref<boolean>;
 | 
			
		||||
  onDateMouseEnter?: (date: any) => void;
 | 
			
		||||
  onDateMouseLeave?: (date: any) => void;
 | 
			
		||||
  onSelect?: OnSelect<any>;
 | 
			
		||||
  hideRanges?: boolean;
 | 
			
		||||
  open?: boolean;
 | 
			
		||||
  mode?: PanelMode;
 | 
			
		||||
  hideRanges?: Ref<boolean>;
 | 
			
		||||
  open?: Ref<boolean>;
 | 
			
		||||
  mode?: Ref<PanelMode>;
 | 
			
		||||
 | 
			
		||||
  /** Only used for TimePicker and this is a deprecated prop */
 | 
			
		||||
  defaultOpenValue?: any;
 | 
			
		||||
  defaultOpenValue?: Ref<any>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const PanelContextKey: InjectionKey<PanelContextProps> = Symbol('PanelContextProps');
 | 
			
		||||
 | 
			
		||||
export const useProvidePanel = (props: PanelContextProps) => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,11 +11,6 @@
 | 
			
		|||
 * Tips: Should add faq about `datetime` mode with `defaultValue`
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import * as React from 'react';
 | 
			
		||||
import classNames from 'classnames';
 | 
			
		||||
import type { AlignType } from 'rc-trigger/lib/interface';
 | 
			
		||||
import warning from 'rc-util/lib/warning';
 | 
			
		||||
import useMergedState from 'rc-util/lib/hooks/useMergedState';
 | 
			
		||||
import type {
 | 
			
		||||
  PickerPanelBaseProps,
 | 
			
		||||
  PickerPanelDateProps,
 | 
			
		||||
| 
						 | 
				
			
			@ -33,6 +28,22 @@ import usePickerInput from './hooks/usePickerInput';
 | 
			
		|||
import useTextValueMapping from './hooks/useTextValueMapping';
 | 
			
		||||
import useValueTexts from './hooks/useValueTexts';
 | 
			
		||||
import useHoverValue from './hooks/useHoverValue';
 | 
			
		||||
import {
 | 
			
		||||
  computed,
 | 
			
		||||
  CSSProperties,
 | 
			
		||||
  defineComponent,
 | 
			
		||||
  HtmlHTMLAttributes,
 | 
			
		||||
  ref,
 | 
			
		||||
  Ref,
 | 
			
		||||
  toRef,
 | 
			
		||||
  toRefs,
 | 
			
		||||
} from 'vue';
 | 
			
		||||
import { FocusEventHandler, MouseEventHandler } from '../_util/EventInterface';
 | 
			
		||||
import { VueNode } from '../_util/type';
 | 
			
		||||
import { AlignType } from '../vc-align/interface';
 | 
			
		||||
import useMergedState from '../_util/hooks/useMergedState';
 | 
			
		||||
import { locale } from 'dayjs';
 | 
			
		||||
import { warning } from '../vc-util/warning';
 | 
			
		||||
 | 
			
		||||
export type PickerRefConfig = {
 | 
			
		||||
  focus: () => void;
 | 
			
		||||
| 
						 | 
				
			
			@ -42,13 +53,13 @@ export type PickerRefConfig = {
 | 
			
		|||
export type PickerSharedProps<DateType> = {
 | 
			
		||||
  dropdownClassName?: string;
 | 
			
		||||
  dropdownAlign?: AlignType;
 | 
			
		||||
  popupStyle?: React.CSSProperties;
 | 
			
		||||
  popupStyle?: CSSProperties;
 | 
			
		||||
  transitionName?: string;
 | 
			
		||||
  placeholder?: string;
 | 
			
		||||
  allowClear?: boolean;
 | 
			
		||||
  autoFocus?: boolean;
 | 
			
		||||
  autofocus?: boolean;
 | 
			
		||||
  disabled?: boolean;
 | 
			
		||||
  tabIndex?: number;
 | 
			
		||||
  tabindex?: number;
 | 
			
		||||
  open?: boolean;
 | 
			
		||||
  defaultOpen?: boolean;
 | 
			
		||||
  /** Make input readOnly to avoid popup keyboard in mobile */
 | 
			
		||||
| 
						 | 
				
			
			@ -59,39 +70,39 @@ export type PickerSharedProps<DateType> = {
 | 
			
		|||
  format?: string | CustomFormat<DateType> | (string | CustomFormat<DateType>)[];
 | 
			
		||||
 | 
			
		||||
  // Render
 | 
			
		||||
  suffixIcon?: React.ReactNode;
 | 
			
		||||
  clearIcon?: React.ReactNode;
 | 
			
		||||
  prevIcon?: React.ReactNode;
 | 
			
		||||
  nextIcon?: React.ReactNode;
 | 
			
		||||
  superPrevIcon?: React.ReactNode;
 | 
			
		||||
  superNextIcon?: React.ReactNode;
 | 
			
		||||
  suffixIcon?: VueNode;
 | 
			
		||||
  clearIcon?: VueNode;
 | 
			
		||||
  prevIcon?: VueNode;
 | 
			
		||||
  nextIcon?: VueNode;
 | 
			
		||||
  superPrevIcon?: VueNode;
 | 
			
		||||
  superNextIcon?: VueNode;
 | 
			
		||||
  getPopupContainer?: (node: HTMLElement) => HTMLElement;
 | 
			
		||||
  panelRender?: (originPanel: React.ReactNode) => React.ReactNode;
 | 
			
		||||
  panelRender?: (originPanel: VueNode) => VueNode;
 | 
			
		||||
 | 
			
		||||
  // Events
 | 
			
		||||
  onChange?: (value: DateType | null, dateString: string) => void;
 | 
			
		||||
  onOpenChange?: (open: boolean) => void;
 | 
			
		||||
  onFocus?: React.FocusEventHandler<HTMLInputElement>;
 | 
			
		||||
  onBlur?: React.FocusEventHandler<HTMLInputElement>;
 | 
			
		||||
  onMouseDown?: React.MouseEventHandler<HTMLDivElement>;
 | 
			
		||||
  onMouseUp?: React.MouseEventHandler<HTMLDivElement>;
 | 
			
		||||
  onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
 | 
			
		||||
  onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
 | 
			
		||||
  onClick?: React.MouseEventHandler<HTMLDivElement>;
 | 
			
		||||
  onContextMenu?: React.MouseEventHandler<HTMLDivElement>;
 | 
			
		||||
  onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>, preventDefault: () => void) => void;
 | 
			
		||||
  onFocus?: FocusEventHandler;
 | 
			
		||||
  onBlur?: FocusEventHandler;
 | 
			
		||||
  onMouseDown?: MouseEventHandler;
 | 
			
		||||
  onMouseUp?: MouseEventHandler;
 | 
			
		||||
  onMouseEnter?: MouseEventHandler;
 | 
			
		||||
  onMouseLeave?: MouseEventHandler;
 | 
			
		||||
  onClick?: MouseEventHandler;
 | 
			
		||||
  onContextMenu?: MouseEventHandler;
 | 
			
		||||
  onKeyDown?: (event: KeyboardEvent, preventDefault: () => void) => void;
 | 
			
		||||
 | 
			
		||||
  // Internal
 | 
			
		||||
  /** @private Internal usage, do not use in production mode!!! */
 | 
			
		||||
  pickerRef?: React.MutableRefObject<PickerRefConfig>;
 | 
			
		||||
  pickerRef?: Ref<PickerRefConfig>;
 | 
			
		||||
 | 
			
		||||
  // WAI-ARIA
 | 
			
		||||
  role?: string;
 | 
			
		||||
  name?: string;
 | 
			
		||||
 | 
			
		||||
  autoComplete?: string;
 | 
			
		||||
  autocomplete?: string;
 | 
			
		||||
  direction?: 'ltr' | 'rtl';
 | 
			
		||||
} & React.AriaAttributes;
 | 
			
		||||
} & HtmlHTMLAttributes;
 | 
			
		||||
 | 
			
		||||
type OmitPanelProps<Props> = Omit<
 | 
			
		||||
  Props,
 | 
			
		||||
| 
						 | 
				
			
			@ -127,435 +138,224 @@ type MergedPickerProps<DateType> = {
 | 
			
		|||
  picker?: PickerMode;
 | 
			
		||||
} & OmitType<DateType>;
 | 
			
		||||
 | 
			
		||||
function InnerPicker<DateType>(props: PickerProps<DateType>) {
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls = 'rc-picker',
 | 
			
		||||
    id,
 | 
			
		||||
    tabIndex,
 | 
			
		||||
    style,
 | 
			
		||||
    className,
 | 
			
		||||
    dropdownClassName,
 | 
			
		||||
    dropdownAlign,
 | 
			
		||||
    popupStyle,
 | 
			
		||||
    transitionName,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    locale,
 | 
			
		||||
    inputReadOnly,
 | 
			
		||||
    allowClear,
 | 
			
		||||
    autoFocus,
 | 
			
		||||
    showTime,
 | 
			
		||||
    picker = 'date',
 | 
			
		||||
    format,
 | 
			
		||||
    use12Hours,
 | 
			
		||||
    value,
 | 
			
		||||
    defaultValue,
 | 
			
		||||
    open,
 | 
			
		||||
    defaultOpen,
 | 
			
		||||
    defaultOpenValue,
 | 
			
		||||
    suffixIcon,
 | 
			
		||||
    clearIcon,
 | 
			
		||||
    disabled,
 | 
			
		||||
    disabledDate,
 | 
			
		||||
    placeholder,
 | 
			
		||||
    getPopupContainer,
 | 
			
		||||
    pickerRef,
 | 
			
		||||
    panelRender,
 | 
			
		||||
    onChange,
 | 
			
		||||
    onOpenChange,
 | 
			
		||||
    onFocus,
 | 
			
		||||
    onBlur,
 | 
			
		||||
    onMouseDown,
 | 
			
		||||
    onMouseUp,
 | 
			
		||||
    onMouseEnter,
 | 
			
		||||
    onMouseLeave,
 | 
			
		||||
    onContextMenu,
 | 
			
		||||
    onClick,
 | 
			
		||||
    onKeyDown,
 | 
			
		||||
    onSelect,
 | 
			
		||||
    direction,
 | 
			
		||||
    autoComplete = 'off',
 | 
			
		||||
  } = props as MergedPickerProps<DateType>;
 | 
			
		||||
function Picker<DateType>() {
 | 
			
		||||
  return defineComponent<MergedPickerProps<DateType>>({
 | 
			
		||||
    name: 'Picker',
 | 
			
		||||
    props: [
 | 
			
		||||
      'prefixCls',
 | 
			
		||||
      'id',
 | 
			
		||||
      'tabindex',
 | 
			
		||||
      'dropdownClassName',
 | 
			
		||||
      'dropdownAlign',
 | 
			
		||||
      'popupStyle',
 | 
			
		||||
      'transitionName',
 | 
			
		||||
      'generateConfig',
 | 
			
		||||
      'locale',
 | 
			
		||||
      'inputReadOnly',
 | 
			
		||||
      'allowClear',
 | 
			
		||||
      'autofocus',
 | 
			
		||||
      'showTime',
 | 
			
		||||
      'picker',
 | 
			
		||||
      'format',
 | 
			
		||||
      'use12Hours',
 | 
			
		||||
      'value',
 | 
			
		||||
      'defaultValue',
 | 
			
		||||
      'open',
 | 
			
		||||
      'defaultOpen',
 | 
			
		||||
      'defaultOpenValue',
 | 
			
		||||
      'suffixIcon',
 | 
			
		||||
      'clearIcon',
 | 
			
		||||
      'disabled',
 | 
			
		||||
      'disabledDate',
 | 
			
		||||
      'placeholder',
 | 
			
		||||
      'getPopupContainer',
 | 
			
		||||
      'pickerRef',
 | 
			
		||||
      'panelRender',
 | 
			
		||||
      'onChange',
 | 
			
		||||
      'onOpenChange',
 | 
			
		||||
      'onFocus',
 | 
			
		||||
      'onBlur',
 | 
			
		||||
      'onMouseDown',
 | 
			
		||||
      'onMouseUp',
 | 
			
		||||
      'onMouseEnter',
 | 
			
		||||
      'onMouseLeave',
 | 
			
		||||
      'onContextMenu',
 | 
			
		||||
      'onClick',
 | 
			
		||||
      'onKeyDown',
 | 
			
		||||
      'onSelect',
 | 
			
		||||
      'direction',
 | 
			
		||||
      'autocomplete',
 | 
			
		||||
    ] as any,
 | 
			
		||||
    inheritAttrs: false,
 | 
			
		||||
    slots: [
 | 
			
		||||
      'suffixIcon',
 | 
			
		||||
      'clearIcon',
 | 
			
		||||
      'prevIcon',
 | 
			
		||||
      'nextIcon',
 | 
			
		||||
      'superPrevIcon',
 | 
			
		||||
      'superNextIcon',
 | 
			
		||||
      'panelRender',
 | 
			
		||||
    ],
 | 
			
		||||
    setup(props, { slots, attrs, expose }) {
 | 
			
		||||
      const inputRef = ref(null);
 | 
			
		||||
      const needConfirmButton = computed(
 | 
			
		||||
        () => (props.picker === 'date' && !!props.showTime) || props.picker === 'time',
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  const inputRef = React.useRef<HTMLInputElement>(null);
 | 
			
		||||
      // ============================= State =============================
 | 
			
		||||
      const formatList = computed(() =>
 | 
			
		||||
        toArray(getDefaultFormat(props.format, props.picker, props.showTime, props.use12Hours)),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  const needConfirmButton: boolean = (picker === 'date' && !!showTime) || picker === 'time';
 | 
			
		||||
      // Panel ref
 | 
			
		||||
      const panelDivRef = ref(null);
 | 
			
		||||
      const inputDivRef = ref(null);
 | 
			
		||||
 | 
			
		||||
  // ============================= State =============================
 | 
			
		||||
  const formatList = toArray(getDefaultFormat(format, picker, showTime, use12Hours));
 | 
			
		||||
 | 
			
		||||
  // Panel ref
 | 
			
		||||
  const panelDivRef = React.useRef<HTMLDivElement>(null);
 | 
			
		||||
  const inputDivRef = React.useRef<HTMLDivElement>(null);
 | 
			
		||||
 | 
			
		||||
  // Real value
 | 
			
		||||
  const [mergedValue, setInnerValue] = useMergedState(null, {
 | 
			
		||||
    value,
 | 
			
		||||
    defaultValue,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // Selected value
 | 
			
		||||
  const [selectedValue, setSelectedValue] = React.useState<DateType | null>(mergedValue);
 | 
			
		||||
 | 
			
		||||
  // Operation ref
 | 
			
		||||
  const operationRef: React.MutableRefObject<ContextOperationRefProps | null> =
 | 
			
		||||
    React.useRef<ContextOperationRefProps>(null);
 | 
			
		||||
 | 
			
		||||
  // Open
 | 
			
		||||
  const [mergedOpen, triggerInnerOpen] = useMergedState(false, {
 | 
			
		||||
    value: open,
 | 
			
		||||
    defaultValue: defaultOpen,
 | 
			
		||||
    postState: (postOpen) => (disabled ? false : postOpen),
 | 
			
		||||
    onChange: (newOpen) => {
 | 
			
		||||
      if (onOpenChange) {
 | 
			
		||||
        onOpenChange(newOpen);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!newOpen && operationRef.current && operationRef.current.onClose) {
 | 
			
		||||
        operationRef.current.onClose();
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // ============================= Text ==============================
 | 
			
		||||
  const [valueTexts, firstValueText] = useValueTexts(selectedValue, {
 | 
			
		||||
    formatList,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    locale,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const [text, triggerTextChange, resetText] = useTextValueMapping({
 | 
			
		||||
    valueTexts,
 | 
			
		||||
    onTextChange: (newText) => {
 | 
			
		||||
      const inputDate = parseValue(newText, {
 | 
			
		||||
        locale,
 | 
			
		||||
        formatList,
 | 
			
		||||
        generateConfig,
 | 
			
		||||
      // Real value
 | 
			
		||||
      const [mergedValue, setInnerValue] = useMergedState<DateType>(null, {
 | 
			
		||||
        value: toRef(props, 'value'),
 | 
			
		||||
        defaultValue: props.defaultValue,
 | 
			
		||||
      });
 | 
			
		||||
      if (inputDate && (!disabledDate || !disabledDate(inputDate))) {
 | 
			
		||||
        setSelectedValue(inputDate);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // ============================ Trigger ============================
 | 
			
		||||
  const triggerChange = (newValue: DateType | null) => {
 | 
			
		||||
    setSelectedValue(newValue);
 | 
			
		||||
    setInnerValue(newValue);
 | 
			
		||||
      const selectedValue = ref(mergedValue.value) as Ref<DateType>;
 | 
			
		||||
      const setSelectedValue = (val: DateType) => {
 | 
			
		||||
        selectedValue.value = val;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
    if (onChange && !isEqual(generateConfig, mergedValue, newValue)) {
 | 
			
		||||
      onChange(
 | 
			
		||||
        newValue,
 | 
			
		||||
        newValue ? formatValue(newValue, { generateConfig, locale, format: formatList[0] }) : '',
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
      // Operation ref
 | 
			
		||||
      const operationRef = ref<ContextOperationRefProps>(null);
 | 
			
		||||
 | 
			
		||||
  const triggerOpen = (newOpen: boolean) => {
 | 
			
		||||
    if (disabled && newOpen) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
      // Open
 | 
			
		||||
      const [mergedOpen, triggerInnerOpen] = useMergedState(false, {
 | 
			
		||||
        value: toRef(props, 'open'),
 | 
			
		||||
        defaultValue: props.defaultOpen,
 | 
			
		||||
        postState: postOpen => (props.disabled ? false : postOpen),
 | 
			
		||||
        onChange: newOpen => {
 | 
			
		||||
          if (props.onOpenChange) {
 | 
			
		||||
            props.onOpenChange(newOpen);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
    triggerInnerOpen(newOpen);
 | 
			
		||||
  };
 | 
			
		||||
          if (!newOpen && operationRef.value && operationRef.value.onClose) {
 | 
			
		||||
            operationRef.value.onClose();
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
  const forwardKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {
 | 
			
		||||
    if (mergedOpen && operationRef.current && operationRef.current.onKeyDown) {
 | 
			
		||||
      // Let popup panel handle keyboard
 | 
			
		||||
      return operationRef.current.onKeyDown(e);
 | 
			
		||||
    }
 | 
			
		||||
      // ============================= Text ==============================
 | 
			
		||||
      const texts = useValueTexts(selectedValue, {
 | 
			
		||||
        formatList,
 | 
			
		||||
        generateConfig: toRef(props, 'generateConfig'),
 | 
			
		||||
        locale: toRef(props, 'locale'),
 | 
			
		||||
      });
 | 
			
		||||
      const valueTexts = computed(() => texts.value[0]);
 | 
			
		||||
      const firstValueText = computed(() => texts.value[1]);
 | 
			
		||||
 | 
			
		||||
    /* istanbul ignore next */
 | 
			
		||||
    /* eslint-disable no-lone-blocks */
 | 
			
		||||
    {
 | 
			
		||||
      warning(
 | 
			
		||||
        false,
 | 
			
		||||
        'Picker not correct forward KeyDown operation. Please help to fire issue about this.',
 | 
			
		||||
      );
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
      const [text, triggerTextChange, resetText] = useTextValueMapping({
 | 
			
		||||
        valueTexts,
 | 
			
		||||
        onTextChange: newText => {
 | 
			
		||||
          const inputDate = parseValue(newText, {
 | 
			
		||||
            locale: props.locale,
 | 
			
		||||
            formatList: formatList.value,
 | 
			
		||||
            generateConfig: props.generateConfig,
 | 
			
		||||
          });
 | 
			
		||||
          if (inputDate && (!props.disabledDate || !props.disabledDate(inputDate))) {
 | 
			
		||||
            setSelectedValue(inputDate);
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
  const onInternalMouseUp: React.MouseEventHandler<HTMLDivElement> = (...args) => {
 | 
			
		||||
    if (onMouseUp) {
 | 
			
		||||
      onMouseUp(...args);
 | 
			
		||||
    }
 | 
			
		||||
      // ============================ Trigger ============================
 | 
			
		||||
      const triggerChange = (newValue: DateType | null) => {
 | 
			
		||||
        const { onChange, generateConfig, locale } = props;
 | 
			
		||||
        setSelectedValue(newValue);
 | 
			
		||||
        setInnerValue(newValue);
 | 
			
		||||
 | 
			
		||||
    if (inputRef.current) {
 | 
			
		||||
      inputRef.current.focus();
 | 
			
		||||
      triggerOpen(true);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // ============================= Input =============================
 | 
			
		||||
  const [inputProps, { focused, typing }] = usePickerInput({
 | 
			
		||||
    blurToCancel: needConfirmButton,
 | 
			
		||||
    open: mergedOpen,
 | 
			
		||||
    value: text,
 | 
			
		||||
    triggerOpen,
 | 
			
		||||
    forwardKeyDown,
 | 
			
		||||
    isClickOutside: (target) =>
 | 
			
		||||
      !elementsContains([panelDivRef.current, inputDivRef.current], target as HTMLElement),
 | 
			
		||||
    onSubmit: () => {
 | 
			
		||||
      if (disabledDate && disabledDate(selectedValue)) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      triggerChange(selectedValue);
 | 
			
		||||
      triggerOpen(false);
 | 
			
		||||
      resetText();
 | 
			
		||||
      return true;
 | 
			
		||||
    },
 | 
			
		||||
    onCancel: () => {
 | 
			
		||||
      triggerOpen(false);
 | 
			
		||||
      setSelectedValue(mergedValue);
 | 
			
		||||
      resetText();
 | 
			
		||||
    },
 | 
			
		||||
    onKeyDown: (e, preventDefault) => {
 | 
			
		||||
      onKeyDown?.(e, preventDefault);
 | 
			
		||||
    },
 | 
			
		||||
    onFocus,
 | 
			
		||||
    onBlur,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // ============================= Sync ==============================
 | 
			
		||||
  // Close should sync back with text value
 | 
			
		||||
  React.useEffect(() => {
 | 
			
		||||
    if (!mergedOpen) {
 | 
			
		||||
      setSelectedValue(mergedValue);
 | 
			
		||||
 | 
			
		||||
      if (!valueTexts.length || valueTexts[0] === '') {
 | 
			
		||||
        triggerTextChange('');
 | 
			
		||||
      } else if (firstValueText !== text) {
 | 
			
		||||
        resetText();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }, [mergedOpen, valueTexts]);
 | 
			
		||||
 | 
			
		||||
  // Change picker should sync back with text value
 | 
			
		||||
  React.useEffect(() => {
 | 
			
		||||
    if (!mergedOpen) {
 | 
			
		||||
      resetText();
 | 
			
		||||
    }
 | 
			
		||||
  }, [picker]);
 | 
			
		||||
 | 
			
		||||
  // Sync innerValue with control mode
 | 
			
		||||
  React.useEffect(() => {
 | 
			
		||||
    // Sync select value
 | 
			
		||||
    setSelectedValue(mergedValue);
 | 
			
		||||
  }, [mergedValue]);
 | 
			
		||||
 | 
			
		||||
  // ============================ Private ============================
 | 
			
		||||
  if (pickerRef) {
 | 
			
		||||
    pickerRef.current = {
 | 
			
		||||
      focus: () => {
 | 
			
		||||
        if (inputRef.current) {
 | 
			
		||||
          inputRef.current.focus();
 | 
			
		||||
        if (onChange && !isEqual(generateConfig, mergedValue.value, newValue)) {
 | 
			
		||||
          onChange(
 | 
			
		||||
            newValue,
 | 
			
		||||
            newValue
 | 
			
		||||
              ? formatValue(newValue, { generateConfig, locale, format: formatList[0] })
 | 
			
		||||
              : '',
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      blur: () => {
 | 
			
		||||
        if (inputRef.current) {
 | 
			
		||||
          inputRef.current.blur();
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const triggerOpen = (newOpen: boolean) => {
 | 
			
		||||
        if (props.disabled && newOpen) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const [hoverValue, onEnter, onLeave] = useHoverValue(text, {
 | 
			
		||||
    formatList,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    locale,
 | 
			
		||||
  });
 | 
			
		||||
        triggerInnerOpen(newOpen);
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
  // ============================= Panel =============================
 | 
			
		||||
  const panelProps = {
 | 
			
		||||
    // Remove `picker` & `format` here since TimePicker is little different with other panel
 | 
			
		||||
    ...(props as Omit<MergedPickerProps<DateType>, 'picker' | 'format'>),
 | 
			
		||||
    className: undefined,
 | 
			
		||||
    style: undefined,
 | 
			
		||||
    pickerValue: undefined,
 | 
			
		||||
    onPickerValueChange: undefined,
 | 
			
		||||
    onChange: null,
 | 
			
		||||
  };
 | 
			
		||||
      const forwardKeyDown = (e: KeyboardEvent) => {
 | 
			
		||||
        if (mergedOpen && operationRef.value && operationRef.value.onKeyDown) {
 | 
			
		||||
          // Let popup panel handle keyboard
 | 
			
		||||
          return operationRef.value.onKeyDown(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
  let panelNode: React.ReactNode = (
 | 
			
		||||
    <PickerPanel<DateType>
 | 
			
		||||
      {...panelProps}
 | 
			
		||||
      generateConfig={generateConfig}
 | 
			
		||||
      class={classNames({
 | 
			
		||||
        [`${prefixCls}-panel-focused`]: !typing,
 | 
			
		||||
      })}
 | 
			
		||||
      value={selectedValue}
 | 
			
		||||
      locale={locale}
 | 
			
		||||
      tabIndex={-1}
 | 
			
		||||
      onSelect={(date) => {
 | 
			
		||||
        onSelect?.(date);
 | 
			
		||||
        setSelectedValue(date);
 | 
			
		||||
      }}
 | 
			
		||||
      direction={direction}
 | 
			
		||||
      onPanelChange={(viewDate, mode) => {
 | 
			
		||||
        const { onPanelChange } = props;
 | 
			
		||||
        onLeave(true);
 | 
			
		||||
        onPanelChange?.(viewDate, mode);
 | 
			
		||||
      }}
 | 
			
		||||
    />
 | 
			
		||||
  );
 | 
			
		||||
        /* istanbul ignore next */
 | 
			
		||||
        /* eslint-disable no-lone-blocks */
 | 
			
		||||
        {
 | 
			
		||||
          warning(
 | 
			
		||||
            false,
 | 
			
		||||
            'Picker not correct forward KeyDown operation. Please help to fire issue about this.',
 | 
			
		||||
          );
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
  if (panelRender) {
 | 
			
		||||
    panelNode = panelRender(panelNode);
 | 
			
		||||
  }
 | 
			
		||||
      const onInternalMouseUp: MouseEventHandler = (...args) => {
 | 
			
		||||
        if (props.onMouseUp) {
 | 
			
		||||
          props.onMouseUp(...args);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
  const panel = (
 | 
			
		||||
    <div
 | 
			
		||||
      class={`${prefixCls}-panel-container`}
 | 
			
		||||
      onMousedown={(e) => {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      {panelNode}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
        if (inputRef.value) {
 | 
			
		||||
          inputRef.value.focus();
 | 
			
		||||
          triggerOpen(true);
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
  let suffixNode: React.ReactNode;
 | 
			
		||||
  if (suffixIcon) {
 | 
			
		||||
    suffixNode = <span class={`${prefixCls}-suffix`}>{suffixIcon}</span>;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let clearNode: React.ReactNode;
 | 
			
		||||
  if (allowClear && mergedValue && !disabled) {
 | 
			
		||||
    clearNode = (
 | 
			
		||||
      <span
 | 
			
		||||
        onMousedown={(e) => {
 | 
			
		||||
          e.preventDefault();
 | 
			
		||||
          e.stopPropagation();
 | 
			
		||||
        }}
 | 
			
		||||
        onMouseup={(e) => {
 | 
			
		||||
          e.preventDefault();
 | 
			
		||||
          e.stopPropagation();
 | 
			
		||||
          triggerChange(null);
 | 
			
		||||
          triggerOpen(false);
 | 
			
		||||
        }}
 | 
			
		||||
        class={`${prefixCls}-clear`}
 | 
			
		||||
        role="button"
 | 
			
		||||
      >
 | 
			
		||||
        {clearIcon || <span class={`${prefixCls}-clear-btn`} />}
 | 
			
		||||
      </span>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // ============================ Warning ============================
 | 
			
		||||
  if (process.env.NODE_ENV !== 'production') {
 | 
			
		||||
    warning(
 | 
			
		||||
      !defaultOpenValue,
 | 
			
		||||
      '`defaultOpenValue` may confuse user for the current value status. Please use `defaultValue` instead.',
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // ============================ Return =============================
 | 
			
		||||
  const onContextSelect = (date: DateType, type: 'key' | 'mouse' | 'submit') => {
 | 
			
		||||
    if (type === 'submit' || (type !== 'key' && !needConfirmButton)) {
 | 
			
		||||
      // triggerChange will also update selected values
 | 
			
		||||
      triggerChange(date);
 | 
			
		||||
      triggerOpen(false);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  const popupPlacement = direction === 'rtl' ? 'bottomRight' : 'bottomLeft';
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <PanelContext.Provider
 | 
			
		||||
      value={{
 | 
			
		||||
        operationRef,
 | 
			
		||||
        hideHeader: picker === 'time',
 | 
			
		||||
        panelRef: panelDivRef,
 | 
			
		||||
        onSelect: onContextSelect,
 | 
			
		||||
      // ============================= Input =============================
 | 
			
		||||
      const [inputProps, { focused, typing }] = usePickerInput({
 | 
			
		||||
        blurToCancel: needConfirmButton,
 | 
			
		||||
        open: mergedOpen,
 | 
			
		||||
        defaultOpenValue,
 | 
			
		||||
        onDateMouseEnter: onEnter,
 | 
			
		||||
        onDateMouseLeave: onLeave,
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      <PickerTrigger
 | 
			
		||||
        visible={mergedOpen}
 | 
			
		||||
        popupElement={panel}
 | 
			
		||||
        popupStyle={popupStyle}
 | 
			
		||||
        prefixCls={prefixCls}
 | 
			
		||||
        dropdownClassName={dropdownClassName}
 | 
			
		||||
        dropdownAlign={dropdownAlign}
 | 
			
		||||
        getPopupContainer={getPopupContainer}
 | 
			
		||||
        transitionName={transitionName}
 | 
			
		||||
        popupPlacement={popupPlacement}
 | 
			
		||||
        direction={direction}
 | 
			
		||||
      >
 | 
			
		||||
        <div
 | 
			
		||||
          class={classNames(prefixCls, className, {
 | 
			
		||||
            [`${prefixCls}-disabled`]: disabled,
 | 
			
		||||
            [`${prefixCls}-focused`]: focused,
 | 
			
		||||
            [`${prefixCls}-rtl`]: direction === 'rtl',
 | 
			
		||||
          })}
 | 
			
		||||
          style={style}
 | 
			
		||||
          onMousedown={onMouseDown}
 | 
			
		||||
          onMouseup={onInternalMouseUp}
 | 
			
		||||
          onMouseenter={onMouseEnter}
 | 
			
		||||
          onMouseleave={onMouseLeave}
 | 
			
		||||
          onContextmenu={onContextMenu}
 | 
			
		||||
          onClick={onClick}
 | 
			
		||||
        >
 | 
			
		||||
          <div
 | 
			
		||||
            class={classNames(`${prefixCls}-input`, {
 | 
			
		||||
              [`${prefixCls}-input-placeholder`]: !!hoverValue,
 | 
			
		||||
            })}
 | 
			
		||||
            ref={inputDivRef}
 | 
			
		||||
          >
 | 
			
		||||
            <input
 | 
			
		||||
              id={id}
 | 
			
		||||
              tabIndex={tabIndex}
 | 
			
		||||
              disabled={disabled}
 | 
			
		||||
              readonly={inputReadOnly || typeof formatList[0] === 'function' || !typing}
 | 
			
		||||
              value={hoverValue || text}
 | 
			
		||||
              onChange={(e) => {
 | 
			
		||||
                triggerTextChange(e.target.value);
 | 
			
		||||
              }}
 | 
			
		||||
              autofocus={autoFocus}
 | 
			
		||||
              placeholder={placeholder}
 | 
			
		||||
              ref={inputRef}
 | 
			
		||||
              title={text}
 | 
			
		||||
              {...inputProps}
 | 
			
		||||
              size={getInputSize(picker, formatList[0], generateConfig)}
 | 
			
		||||
              {...getDataOrAriaProps(props)}
 | 
			
		||||
              autocomplete={autoComplete}
 | 
			
		||||
            />
 | 
			
		||||
            {suffixNode}
 | 
			
		||||
            {clearNode}
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </PickerTrigger>
 | 
			
		||||
    </PanelContext.Provider>
 | 
			
		||||
  );
 | 
			
		||||
        value: text,
 | 
			
		||||
        triggerOpen,
 | 
			
		||||
        forwardKeyDown,
 | 
			
		||||
        isClickOutside: target =>
 | 
			
		||||
          !elementsContains([panelDivRef.current, inputDivRef.current], target as HTMLElement),
 | 
			
		||||
        onSubmit: () => {
 | 
			
		||||
          if (props.disabledDate && props.disabledDate(selectedValue.value)) {
 | 
			
		||||
            return false;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          triggerChange(selectedValue.value);
 | 
			
		||||
          triggerOpen(false);
 | 
			
		||||
          resetText();
 | 
			
		||||
          return true;
 | 
			
		||||
        },
 | 
			
		||||
        onCancel: () => {
 | 
			
		||||
          triggerOpen(false);
 | 
			
		||||
          setSelectedValue(mergedValue.value);
 | 
			
		||||
          resetText();
 | 
			
		||||
        },
 | 
			
		||||
        onKeyDown: (e, preventDefault) => {
 | 
			
		||||
          props.onKeyDown?.(e, preventDefault);
 | 
			
		||||
        },
 | 
			
		||||
        onFocus: (e: FocusEvent) => {
 | 
			
		||||
          props.onFocus?.(e);
 | 
			
		||||
        },
 | 
			
		||||
        onBlur: (e: FocusEvent) => {
 | 
			
		||||
          props.onBlur?.(e);
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      return () => {
 | 
			
		||||
        return null;
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Wrap with class component to enable pass generic with instance method
 | 
			
		||||
class Picker<DateType> extends React.Component<PickerProps<DateType>> {
 | 
			
		||||
  pickerRef = React.createRef<PickerRefConfig>();
 | 
			
		||||
 | 
			
		||||
  focus = () => {
 | 
			
		||||
    if (this.pickerRef.current) {
 | 
			
		||||
      this.pickerRef.current.focus();
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  blur = () => {
 | 
			
		||||
    if (this.pickerRef.current) {
 | 
			
		||||
      this.pickerRef.current.blur();
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  render() {
 | 
			
		||||
    return (
 | 
			
		||||
      <InnerPicker<DateType>
 | 
			
		||||
        {...this.props}
 | 
			
		||||
        pickerRef={this.pickerRef as React.MutableRefObject<PickerRefConfig>}
 | 
			
		||||
      />
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default Picker;
 | 
			
		||||
export default Picker();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,12 +4,6 @@
 | 
			
		|||
 *  click will trigger `onSelect` (if value changed trigger `onChange` also).
 | 
			
		||||
 *  Panel change will not trigger `onSelect` but trigger `onPanelChange`
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import * as React from 'react';
 | 
			
		||||
import classNames from 'classnames';
 | 
			
		||||
import KeyCode from 'rc-util/lib/KeyCode';
 | 
			
		||||
import warning from 'rc-util/lib/warning';
 | 
			
		||||
import useMergedState from 'rc-util/lib/hooks/useMergedState';
 | 
			
		||||
import type { SharedTimeProps } from './panels/TimePanel';
 | 
			
		||||
import TimePanel from './panels/TimePanel';
 | 
			
		||||
import DatetimePanel from './panels/DatetimePanel';
 | 
			
		||||
| 
						 | 
				
			
			@ -30,22 +24,28 @@ import type {
 | 
			
		|||
  Components,
 | 
			
		||||
} from './interface';
 | 
			
		||||
import { isEqual } from './utils/dateUtil';
 | 
			
		||||
import PanelContext from './PanelContext';
 | 
			
		||||
import { useInjectPanel, useProvidePanel } from './PanelContext';
 | 
			
		||||
import type { DateRender } from './panels/DatePanel/DateBody';
 | 
			
		||||
import { PickerModeMap } from './utils/uiUtil';
 | 
			
		||||
import type { MonthCellRender } from './panels/MonthPanel/MonthBody';
 | 
			
		||||
import RangeContext from './RangeContext';
 | 
			
		||||
import { useInjectRange } from './RangeContext';
 | 
			
		||||
import getExtraFooter from './utils/getExtraFooter';
 | 
			
		||||
import getRanges from './utils/getRanges';
 | 
			
		||||
import { getLowerBoundTime, setDateTime, setTime } from './utils/timeUtil';
 | 
			
		||||
import { VueNode } from '../_util/type';
 | 
			
		||||
import { computed, defineComponent, ref, toRef, watch, watchEffect } from 'vue';
 | 
			
		||||
import useMergedState from '../_util/hooks/useMergedState';
 | 
			
		||||
import { warning } from '../vc-util/warning';
 | 
			
		||||
import KeyCode from '../_util/KeyCode';
 | 
			
		||||
import classNames from '../_util/classNames';
 | 
			
		||||
 | 
			
		||||
export type PickerPanelSharedProps<DateType> = {
 | 
			
		||||
  prefixCls?: string;
 | 
			
		||||
  className?: string;
 | 
			
		||||
  style?: React.CSSProperties;
 | 
			
		||||
  // className?: string;
 | 
			
		||||
  // style?: React.CSSProperties;
 | 
			
		||||
  /** @deprecated Will be removed in next big version. Please use `mode` instead */
 | 
			
		||||
  mode?: PanelMode;
 | 
			
		||||
  tabIndex?: number;
 | 
			
		||||
  tabindex?: number;
 | 
			
		||||
 | 
			
		||||
  // Locale
 | 
			
		||||
  locale: Locale;
 | 
			
		||||
| 
						 | 
				
			
			@ -65,13 +65,13 @@ export type PickerPanelSharedProps<DateType> = {
 | 
			
		|||
  // Render
 | 
			
		||||
  dateRender?: DateRender<DateType>;
 | 
			
		||||
  monthCellRender?: MonthCellRender<DateType>;
 | 
			
		||||
  renderExtraFooter?: (mode: PanelMode) => React.ReactNode;
 | 
			
		||||
  renderExtraFooter?: (mode: PanelMode) => VueNode;
 | 
			
		||||
 | 
			
		||||
  // Event
 | 
			
		||||
  onSelect?: (value: DateType) => void;
 | 
			
		||||
  onChange?: (value: DateType) => void;
 | 
			
		||||
  onPanelChange?: OnPanelChange<DateType>;
 | 
			
		||||
  onMouseDown?: React.MouseEventHandler<HTMLDivElement>;
 | 
			
		||||
  onMouseDown?: (e: MouseEvent) => void;
 | 
			
		||||
  onOk?: (date: DateType) => void;
 | 
			
		||||
 | 
			
		||||
  direction?: 'ltr' | 'rtl';
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +101,8 @@ export type PickerPanelDateProps<DateType> = {
 | 
			
		|||
 | 
			
		||||
export type PickerPanelTimeProps<DateType> = {
 | 
			
		||||
  picker: 'time';
 | 
			
		||||
} & PickerPanelSharedProps<DateType> & SharedTimeProps<DateType>;
 | 
			
		||||
} & PickerPanelSharedProps<DateType> &
 | 
			
		||||
  SharedTimeProps<DateType>;
 | 
			
		||||
 | 
			
		||||
export type PickerPanelProps<DateType> =
 | 
			
		||||
  | PickerPanelBaseProps<DateType>
 | 
			
		||||
| 
						 | 
				
			
			@ -116,454 +117,486 @@ type MergedPickerPanelProps<DateType> = {
 | 
			
		|||
  picker?: PickerMode;
 | 
			
		||||
} & OmitType<DateType>;
 | 
			
		||||
 | 
			
		||||
function PickerPanel<DateType>(props: PickerPanelProps<DateType>) {
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls = 'rc-picker',
 | 
			
		||||
    className,
 | 
			
		||||
    style,
 | 
			
		||||
    locale,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    value,
 | 
			
		||||
    defaultValue,
 | 
			
		||||
    pickerValue,
 | 
			
		||||
    defaultPickerValue,
 | 
			
		||||
    disabledDate,
 | 
			
		||||
    mode,
 | 
			
		||||
    picker = 'date',
 | 
			
		||||
    tabIndex = 0,
 | 
			
		||||
    showNow,
 | 
			
		||||
    showTime,
 | 
			
		||||
    showToday,
 | 
			
		||||
    renderExtraFooter,
 | 
			
		||||
    hideHeader,
 | 
			
		||||
    onSelect,
 | 
			
		||||
    onChange,
 | 
			
		||||
    onPanelChange,
 | 
			
		||||
    onMouseDown,
 | 
			
		||||
    onPickerValueChange,
 | 
			
		||||
    onOk,
 | 
			
		||||
    components,
 | 
			
		||||
    direction,
 | 
			
		||||
    hourStep = 1,
 | 
			
		||||
    minuteStep = 1,
 | 
			
		||||
    secondStep = 1,
 | 
			
		||||
  } = props as MergedPickerPanelProps<DateType>;
 | 
			
		||||
function PickerPanel<DateType>() {
 | 
			
		||||
  return defineComponent<MergedPickerPanelProps<DateType>>({
 | 
			
		||||
    name: 'PickerPanel',
 | 
			
		||||
    inheritAttrs: false,
 | 
			
		||||
    props: [
 | 
			
		||||
      'prefixCls',
 | 
			
		||||
      'locale',
 | 
			
		||||
      'generateConfig',
 | 
			
		||||
      'value',
 | 
			
		||||
      'defaultValue',
 | 
			
		||||
      'pickerValue',
 | 
			
		||||
      'defaultPickerValue',
 | 
			
		||||
      'disabledDate',
 | 
			
		||||
      'mode',
 | 
			
		||||
      { picker: { default: 'date' } },
 | 
			
		||||
      { tabindex: { default: 0 } },
 | 
			
		||||
      'showNow',
 | 
			
		||||
      'showTime',
 | 
			
		||||
      'showToday',
 | 
			
		||||
      'renderExtraFooter',
 | 
			
		||||
      'hideHeader',
 | 
			
		||||
      'onSelect',
 | 
			
		||||
      'onChange',
 | 
			
		||||
      'onPanelChange',
 | 
			
		||||
      'onMouseDown',
 | 
			
		||||
      'onPickerValueChange',
 | 
			
		||||
      'onOk',
 | 
			
		||||
      'components',
 | 
			
		||||
      'direction',
 | 
			
		||||
      { hourStep: { default: 1 } },
 | 
			
		||||
      { minuteStep: { default: 1 } },
 | 
			
		||||
      { secondStep: { default: 1 } },
 | 
			
		||||
    ] as any,
 | 
			
		||||
    setup(props, { attrs }) {
 | 
			
		||||
      const needConfirmButton = computed(
 | 
			
		||||
        () => (props.picker === 'date' && !!props.showTime) || props.picker === 'time',
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  const needConfirmButton: boolean = (picker === 'date' && !!showTime) || picker === 'time';
 | 
			
		||||
 | 
			
		||||
  const isHourStepValid = 24 % hourStep === 0;
 | 
			
		||||
  const isMinuteStepValid = 60 % minuteStep === 0;
 | 
			
		||||
  const isSecondStepValid = 60 % secondStep === 0;
 | 
			
		||||
 | 
			
		||||
  if (process.env.NODE_ENV !== 'production') {
 | 
			
		||||
    warning(!value || generateConfig.isValidate(value), 'Invalidate date pass to `value`.');
 | 
			
		||||
    warning(!value || generateConfig.isValidate(value), 'Invalidate date pass to `defaultValue`.');
 | 
			
		||||
    warning(isHourStepValid, `\`hourStep\` ${hourStep} is invalid. It should be a factor of 24.`);
 | 
			
		||||
    warning(
 | 
			
		||||
      isMinuteStepValid,
 | 
			
		||||
      `\`minuteStep\` ${minuteStep} is invalid. It should be a factor of 60.`,
 | 
			
		||||
    );
 | 
			
		||||
    warning(
 | 
			
		||||
      isSecondStepValid,
 | 
			
		||||
      `\`secondStep\` ${secondStep} is invalid. It should be a factor of 60.`,
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // ============================ State =============================
 | 
			
		||||
 | 
			
		||||
  const panelContext = React.useContext(PanelContext);
 | 
			
		||||
  const {
 | 
			
		||||
    operationRef,
 | 
			
		||||
    panelRef: panelDivRef,
 | 
			
		||||
    onSelect: onContextSelect,
 | 
			
		||||
    hideRanges,
 | 
			
		||||
    defaultOpenValue,
 | 
			
		||||
  } = panelContext;
 | 
			
		||||
 | 
			
		||||
  const { inRange, panelPosition, rangedValue, hoverRangedValue } = React.useContext(RangeContext);
 | 
			
		||||
  const panelRef = React.useRef<PanelRefProps>({});
 | 
			
		||||
 | 
			
		||||
  // Handle init logic
 | 
			
		||||
  const initRef = React.useRef(true);
 | 
			
		||||
 | 
			
		||||
  // Value
 | 
			
		||||
  const [mergedValue, setInnerValue] = useMergedState(null, {
 | 
			
		||||
    value,
 | 
			
		||||
    defaultValue,
 | 
			
		||||
    postState: (val) => {
 | 
			
		||||
      if (!val && defaultOpenValue && picker === 'time') {
 | 
			
		||||
        return defaultOpenValue;
 | 
			
		||||
      const isHourStepValid = computed(() => 24 % props.hourStep === 0);
 | 
			
		||||
      const isMinuteStepValid = computed(() => 60 % props.minuteStep === 0);
 | 
			
		||||
      const isSecondStepValid = computed(() => 60 % props.secondStep === 0);
 | 
			
		||||
      if (process.env.NODE_ENV !== 'production') {
 | 
			
		||||
        watchEffect(() => {
 | 
			
		||||
          const { generateConfig, value, hourStep = 1, minuteStep = 1, secondStep = 1 } = props;
 | 
			
		||||
          warning(!value || generateConfig.isValidate(value), 'Invalidate date pass to `value`.');
 | 
			
		||||
          warning(
 | 
			
		||||
            !value || generateConfig.isValidate(value),
 | 
			
		||||
            'Invalidate date pass to `defaultValue`.',
 | 
			
		||||
          );
 | 
			
		||||
          warning(
 | 
			
		||||
            isHourStepValid.value,
 | 
			
		||||
            `\`hourStep\` ${hourStep} is invalid. It should be a factor of 24.`,
 | 
			
		||||
          );
 | 
			
		||||
          warning(
 | 
			
		||||
            isMinuteStepValid.value,
 | 
			
		||||
            `\`minuteStep\` ${minuteStep} is invalid. It should be a factor of 60.`,
 | 
			
		||||
          );
 | 
			
		||||
          warning(
 | 
			
		||||
            isSecondStepValid.value,
 | 
			
		||||
            `\`secondStep\` ${secondStep} is invalid. It should be a factor of 60.`,
 | 
			
		||||
          );
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      return val;
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // View date control
 | 
			
		||||
  const [viewDate, setInnerViewDate] = useMergedState<DateType | null, DateType>(null, {
 | 
			
		||||
    value: pickerValue,
 | 
			
		||||
    defaultValue: defaultPickerValue || mergedValue,
 | 
			
		||||
    postState: (date) => {
 | 
			
		||||
      const now = generateConfig.getNow();
 | 
			
		||||
      if (!date) return now;
 | 
			
		||||
      // When value is null and set showTime
 | 
			
		||||
      if (!mergedValue && showTime) {
 | 
			
		||||
        if (typeof showTime === 'object') {
 | 
			
		||||
          return setDateTime(generateConfig, date, showTime.defaultValue || now);
 | 
			
		||||
      const panelContext = useInjectPanel();
 | 
			
		||||
      const {
 | 
			
		||||
        operationRef,
 | 
			
		||||
        panelRef: panelDivRef,
 | 
			
		||||
        onSelect: onContextSelect,
 | 
			
		||||
        hideRanges,
 | 
			
		||||
        defaultOpenValue,
 | 
			
		||||
      } = panelContext;
 | 
			
		||||
      const { inRange, panelPosition, rangedValue, hoverRangedValue } = useInjectRange();
 | 
			
		||||
      const panelRef = ref<PanelRefProps>({});
 | 
			
		||||
      // Value
 | 
			
		||||
      const [mergedValue, setInnerValue] = useMergedState<DateType | null>(null, {
 | 
			
		||||
        value: toRef(props, 'value'),
 | 
			
		||||
        defaultValue: props.defaultValue,
 | 
			
		||||
        postState: val => {
 | 
			
		||||
          if (!val && defaultOpenValue.value && props.picker === 'time') {
 | 
			
		||||
            return defaultOpenValue.value;
 | 
			
		||||
          }
 | 
			
		||||
          return val;
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      // View date control
 | 
			
		||||
      const [viewDate, setInnerViewDate] = useMergedState<DateType | null>(null, {
 | 
			
		||||
        value: toRef(props, 'pickerValue'),
 | 
			
		||||
        defaultValue: props.defaultPickerValue || mergedValue.value,
 | 
			
		||||
        postState: date => {
 | 
			
		||||
          const { generateConfig, showTime, defaultValue } = props;
 | 
			
		||||
          const now = generateConfig.getNow();
 | 
			
		||||
          if (!date) return now;
 | 
			
		||||
          // When value is null and set showTime
 | 
			
		||||
          if (!mergedValue && props.showTime) {
 | 
			
		||||
            if (typeof showTime === 'object') {
 | 
			
		||||
              return setDateTime(generateConfig, date, showTime.defaultValue || now);
 | 
			
		||||
            }
 | 
			
		||||
            if (defaultValue) {
 | 
			
		||||
              return setDateTime(generateConfig, date, defaultValue);
 | 
			
		||||
            }
 | 
			
		||||
            return setDateTime(generateConfig, date, now);
 | 
			
		||||
          }
 | 
			
		||||
          return date;
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      const setViewDate = (date: DateType) => {
 | 
			
		||||
        setInnerViewDate(date);
 | 
			
		||||
        if (props.onPickerValueChange) {
 | 
			
		||||
          props.onPickerValueChange(date);
 | 
			
		||||
        }
 | 
			
		||||
        if (defaultValue) {
 | 
			
		||||
          return setDateTime(generateConfig, date, defaultValue);
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      // Panel control
 | 
			
		||||
      const getInternalNextMode = (nextMode: PanelMode): PanelMode => {
 | 
			
		||||
        const getNextMode = PickerModeMap[props.picker!];
 | 
			
		||||
        if (getNextMode) {
 | 
			
		||||
          return getNextMode(nextMode);
 | 
			
		||||
        }
 | 
			
		||||
        return setDateTime(generateConfig, date, now);
 | 
			
		||||
      }
 | 
			
		||||
      return date;
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const setViewDate = (date: DateType) => {
 | 
			
		||||
    setInnerViewDate(date);
 | 
			
		||||
    if (onPickerValueChange) {
 | 
			
		||||
      onPickerValueChange(date);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
        return nextMode;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
  // Panel control
 | 
			
		||||
  const getInternalNextMode = (nextMode: PanelMode): PanelMode => {
 | 
			
		||||
    const getNextMode = PickerModeMap[picker!];
 | 
			
		||||
    if (getNextMode) {
 | 
			
		||||
      return getNextMode(nextMode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return nextMode;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Save panel is changed from which panel
 | 
			
		||||
  const [mergedMode, setInnerMode] = useMergedState(
 | 
			
		||||
    () => {
 | 
			
		||||
      if (picker === 'time') {
 | 
			
		||||
        return 'time';
 | 
			
		||||
      }
 | 
			
		||||
      return getInternalNextMode('date');
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      value: mode,
 | 
			
		||||
    },
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  React.useEffect(() => {
 | 
			
		||||
    setInnerMode(picker);
 | 
			
		||||
  }, [picker]);
 | 
			
		||||
 | 
			
		||||
  const [sourceMode, setSourceMode] = React.useState<PanelMode>(() => mergedMode);
 | 
			
		||||
 | 
			
		||||
  const onInternalPanelChange = (newMode: PanelMode | null, viewValue: DateType) => {
 | 
			
		||||
    const nextMode = getInternalNextMode(newMode || mergedMode);
 | 
			
		||||
    setSourceMode(mergedMode);
 | 
			
		||||
    setInnerMode(nextMode);
 | 
			
		||||
 | 
			
		||||
    if (onPanelChange && (mergedMode !== nextMode || isEqual(generateConfig, viewDate, viewDate))) {
 | 
			
		||||
      onPanelChange(viewValue, nextMode);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const triggerSelect = (
 | 
			
		||||
    date: DateType,
 | 
			
		||||
    type: 'key' | 'mouse' | 'submit',
 | 
			
		||||
    forceTriggerSelect: boolean = false,
 | 
			
		||||
  ) => {
 | 
			
		||||
    if (mergedMode === picker || forceTriggerSelect) {
 | 
			
		||||
      setInnerValue(date);
 | 
			
		||||
 | 
			
		||||
      if (onSelect) {
 | 
			
		||||
        onSelect(date);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (onContextSelect) {
 | 
			
		||||
        onContextSelect(date, type);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (onChange && !isEqual(generateConfig, date, mergedValue) && !disabledDate?.(date)) {
 | 
			
		||||
        onChange(date);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // ========================= Interactive ==========================
 | 
			
		||||
  const onInternalKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {
 | 
			
		||||
    if (panelRef.current && panelRef.current.onKeyDown) {
 | 
			
		||||
      if (
 | 
			
		||||
        [
 | 
			
		||||
          KeyCode.LEFT,
 | 
			
		||||
          KeyCode.RIGHT,
 | 
			
		||||
          KeyCode.UP,
 | 
			
		||||
          KeyCode.DOWN,
 | 
			
		||||
          KeyCode.PAGE_UP,
 | 
			
		||||
          KeyCode.PAGE_DOWN,
 | 
			
		||||
          KeyCode.ENTER,
 | 
			
		||||
        ].includes(e.which)
 | 
			
		||||
      ) {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
      }
 | 
			
		||||
      return panelRef.current.onKeyDown(e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* istanbul ignore next */
 | 
			
		||||
    /* eslint-disable no-lone-blocks */
 | 
			
		||||
    {
 | 
			
		||||
      warning(
 | 
			
		||||
        false,
 | 
			
		||||
        'Panel not correct handle keyDown event. Please help to fire issue about this.',
 | 
			
		||||
      // Save panel is changed from which panel
 | 
			
		||||
      const [mergedMode, setInnerMode] = useMergedState(
 | 
			
		||||
        () => {
 | 
			
		||||
          if (props.picker === 'time') {
 | 
			
		||||
            return 'time';
 | 
			
		||||
          }
 | 
			
		||||
          return getInternalNextMode('date');
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          value: toRef(props, 'mode'),
 | 
			
		||||
        },
 | 
			
		||||
      );
 | 
			
		||||
      watch(
 | 
			
		||||
        () => props.picker,
 | 
			
		||||
        () => {
 | 
			
		||||
          setInnerMode(props.picker);
 | 
			
		||||
        },
 | 
			
		||||
      );
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    /* eslint-enable no-lone-blocks */
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const onInternalBlur: React.FocusEventHandler<HTMLElement> = (e) => {
 | 
			
		||||
    if (panelRef.current && panelRef.current.onBlur) {
 | 
			
		||||
      panelRef.current.onBlur(e);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
      const sourceMode = ref(mergedMode.value);
 | 
			
		||||
      const setSourceMode = (val: PanelMode) => {
 | 
			
		||||
        sourceMode.value = val;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
  if (operationRef && panelPosition !== 'right') {
 | 
			
		||||
    operationRef.current = {
 | 
			
		||||
      onKeyDown: onInternalKeyDown,
 | 
			
		||||
      onClose: () => {
 | 
			
		||||
        if (panelRef.current && panelRef.current.onClose) {
 | 
			
		||||
          panelRef.current.onClose();
 | 
			
		||||
      const onInternalPanelChange = (newMode: PanelMode | null, viewValue: DateType) => {
 | 
			
		||||
        const { onPanelChange, generateConfig } = props;
 | 
			
		||||
        const nextMode = getInternalNextMode(newMode || mergedMode.value);
 | 
			
		||||
        setSourceMode(mergedMode.value);
 | 
			
		||||
        setInnerMode(nextMode);
 | 
			
		||||
 | 
			
		||||
        if (
 | 
			
		||||
          onPanelChange &&
 | 
			
		||||
          (mergedMode.value !== nextMode || isEqual(generateConfig, viewDate.value, viewDate.value))
 | 
			
		||||
        ) {
 | 
			
		||||
          onPanelChange(viewValue, nextMode);
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
  // ============================ Effect ============================
 | 
			
		||||
  React.useEffect(() => {
 | 
			
		||||
    if (value && !initRef.current) {
 | 
			
		||||
      setInnerViewDate(value);
 | 
			
		||||
    }
 | 
			
		||||
  }, [value]);
 | 
			
		||||
      const triggerSelect = (
 | 
			
		||||
        date: DateType,
 | 
			
		||||
        type: 'key' | 'mouse' | 'submit',
 | 
			
		||||
        forceTriggerSelect: boolean = false,
 | 
			
		||||
      ) => {
 | 
			
		||||
        const { picker, generateConfig, onSelect, onChange, disabledDate } = props;
 | 
			
		||||
        if (mergedMode.value === picker || forceTriggerSelect) {
 | 
			
		||||
          setInnerValue(date);
 | 
			
		||||
 | 
			
		||||
  React.useEffect(() => {
 | 
			
		||||
    initRef.current = false;
 | 
			
		||||
  }, []);
 | 
			
		||||
          if (onSelect) {
 | 
			
		||||
            onSelect(date);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
  // ============================ Panels ============================
 | 
			
		||||
  let panelNode: React.ReactNode;
 | 
			
		||||
          if (onContextSelect) {
 | 
			
		||||
            onContextSelect(date, type);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
  const pickerProps = {
 | 
			
		||||
    ...(props as MergedPickerPanelProps<DateType>),
 | 
			
		||||
    operationRef: panelRef,
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    viewDate,
 | 
			
		||||
    value: mergedValue,
 | 
			
		||||
    onViewDateChange: setViewDate,
 | 
			
		||||
    sourceMode,
 | 
			
		||||
    onPanelChange: onInternalPanelChange,
 | 
			
		||||
    disabledDate,
 | 
			
		||||
  };
 | 
			
		||||
  delete pickerProps.onChange;
 | 
			
		||||
  delete pickerProps.onSelect;
 | 
			
		||||
 | 
			
		||||
  switch (mergedMode) {
 | 
			
		||||
    case 'decade':
 | 
			
		||||
      panelNode = (
 | 
			
		||||
        <DecadePanel<DateType>
 | 
			
		||||
          {...pickerProps}
 | 
			
		||||
          onSelect={(date, type) => {
 | 
			
		||||
            setViewDate(date);
 | 
			
		||||
            triggerSelect(date, type);
 | 
			
		||||
          }}
 | 
			
		||||
        />
 | 
			
		||||
      );
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 'year':
 | 
			
		||||
      panelNode = (
 | 
			
		||||
        <YearPanel<DateType>
 | 
			
		||||
          {...pickerProps}
 | 
			
		||||
          onSelect={(date, type) => {
 | 
			
		||||
            setViewDate(date);
 | 
			
		||||
            triggerSelect(date, type);
 | 
			
		||||
          }}
 | 
			
		||||
        />
 | 
			
		||||
      );
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 'month':
 | 
			
		||||
      panelNode = (
 | 
			
		||||
        <MonthPanel<DateType>
 | 
			
		||||
          {...pickerProps}
 | 
			
		||||
          onSelect={(date, type) => {
 | 
			
		||||
            setViewDate(date);
 | 
			
		||||
            triggerSelect(date, type);
 | 
			
		||||
          }}
 | 
			
		||||
        />
 | 
			
		||||
      );
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 'quarter':
 | 
			
		||||
      panelNode = (
 | 
			
		||||
        <QuarterPanel<DateType>
 | 
			
		||||
          {...pickerProps}
 | 
			
		||||
          onSelect={(date, type) => {
 | 
			
		||||
            setViewDate(date);
 | 
			
		||||
            triggerSelect(date, type);
 | 
			
		||||
          }}
 | 
			
		||||
        />
 | 
			
		||||
      );
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 'week':
 | 
			
		||||
      panelNode = (
 | 
			
		||||
        <WeekPanel
 | 
			
		||||
          {...pickerProps}
 | 
			
		||||
          onSelect={(date, type) => {
 | 
			
		||||
            setViewDate(date);
 | 
			
		||||
            triggerSelect(date, type);
 | 
			
		||||
          }}
 | 
			
		||||
        />
 | 
			
		||||
      );
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 'time':
 | 
			
		||||
      delete pickerProps.showTime;
 | 
			
		||||
      panelNode = (
 | 
			
		||||
        <TimePanel<DateType>
 | 
			
		||||
          {...pickerProps}
 | 
			
		||||
          {...(typeof showTime === 'object' ? showTime : null)}
 | 
			
		||||
          onSelect={(date, type) => {
 | 
			
		||||
            setViewDate(date);
 | 
			
		||||
            triggerSelect(date, type);
 | 
			
		||||
          }}
 | 
			
		||||
        />
 | 
			
		||||
      );
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      if (showTime) {
 | 
			
		||||
        panelNode = (
 | 
			
		||||
          <DatetimePanel
 | 
			
		||||
            {...pickerProps}
 | 
			
		||||
            onSelect={(date, type) => {
 | 
			
		||||
              setViewDate(date);
 | 
			
		||||
              triggerSelect(date, type);
 | 
			
		||||
            }}
 | 
			
		||||
          />
 | 
			
		||||
        );
 | 
			
		||||
      } else {
 | 
			
		||||
        panelNode = (
 | 
			
		||||
          <DatePanel<DateType>
 | 
			
		||||
            {...pickerProps}
 | 
			
		||||
            onSelect={(date, type) => {
 | 
			
		||||
              setViewDate(date);
 | 
			
		||||
              triggerSelect(date, type);
 | 
			
		||||
            }}
 | 
			
		||||
          />
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // ============================ Footer ============================
 | 
			
		||||
  let extraFooter: React.ReactNode;
 | 
			
		||||
  let rangesNode: React.ReactNode;
 | 
			
		||||
 | 
			
		||||
  const onNow = () => {
 | 
			
		||||
    const now = generateConfig.getNow();
 | 
			
		||||
    const lowerBoundTime = getLowerBoundTime(
 | 
			
		||||
      generateConfig.getHour(now),
 | 
			
		||||
      generateConfig.getMinute(now),
 | 
			
		||||
      generateConfig.getSecond(now),
 | 
			
		||||
      isHourStepValid ? hourStep : 1,
 | 
			
		||||
      isMinuteStepValid ? minuteStep : 1,
 | 
			
		||||
      isSecondStepValid ? secondStep : 1,
 | 
			
		||||
    );
 | 
			
		||||
    const adjustedNow = setTime(
 | 
			
		||||
      generateConfig,
 | 
			
		||||
      now,
 | 
			
		||||
      lowerBoundTime[0], // hour
 | 
			
		||||
      lowerBoundTime[1], // minute
 | 
			
		||||
      lowerBoundTime[2], // second
 | 
			
		||||
    );
 | 
			
		||||
    triggerSelect(adjustedNow, 'submit');
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  if (!hideRanges) {
 | 
			
		||||
    extraFooter = getExtraFooter(prefixCls, mergedMode, renderExtraFooter);
 | 
			
		||||
    rangesNode = getRanges({
 | 
			
		||||
      prefixCls,
 | 
			
		||||
      components,
 | 
			
		||||
      needConfirmButton,
 | 
			
		||||
      okDisabled: !mergedValue || (disabledDate && disabledDate(mergedValue)),
 | 
			
		||||
      locale,
 | 
			
		||||
      showNow,
 | 
			
		||||
      onNow: needConfirmButton && onNow,
 | 
			
		||||
      onOk: () => {
 | 
			
		||||
        if (mergedValue) {
 | 
			
		||||
          triggerSelect(mergedValue, 'submit', true);
 | 
			
		||||
          if (onOk) {
 | 
			
		||||
            onOk(mergedValue);
 | 
			
		||||
          if (
 | 
			
		||||
            onChange &&
 | 
			
		||||
            !isEqual(generateConfig, date, mergedValue.value) &&
 | 
			
		||||
            !disabledDate?.(date)
 | 
			
		||||
          ) {
 | 
			
		||||
            onChange(date);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
  let todayNode: React.ReactNode;
 | 
			
		||||
 | 
			
		||||
  if (showToday && mergedMode === 'date' && picker === 'date' && !showTime) {
 | 
			
		||||
    const now = generateConfig.getNow();
 | 
			
		||||
    const todayCls = `${prefixCls}-today-btn`;
 | 
			
		||||
    const disabled = disabledDate && disabledDate(now);
 | 
			
		||||
    todayNode = (
 | 
			
		||||
      <a
 | 
			
		||||
        class={classNames(todayCls, disabled && `${todayCls}-disabled`)}
 | 
			
		||||
        aria-disabled={disabled}
 | 
			
		||||
        onClick={() => {
 | 
			
		||||
          if (!disabled) {
 | 
			
		||||
            triggerSelect(now, 'mouse', true);
 | 
			
		||||
      // ========================= Interactive ==========================
 | 
			
		||||
      const onInternalKeyDown = (e: KeyboardEvent) => {
 | 
			
		||||
        if (panelRef.value && panelRef.value.onKeyDown) {
 | 
			
		||||
          if (
 | 
			
		||||
            [
 | 
			
		||||
              KeyCode.LEFT,
 | 
			
		||||
              KeyCode.RIGHT,
 | 
			
		||||
              KeyCode.UP,
 | 
			
		||||
              KeyCode.DOWN,
 | 
			
		||||
              KeyCode.PAGE_UP,
 | 
			
		||||
              KeyCode.PAGE_DOWN,
 | 
			
		||||
              KeyCode.ENTER,
 | 
			
		||||
            ].includes(e.which)
 | 
			
		||||
          ) {
 | 
			
		||||
            e.preventDefault();
 | 
			
		||||
          }
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        {locale.today}
 | 
			
		||||
      </a>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
          return panelRef.value.onKeyDown(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <PanelContext.Provider
 | 
			
		||||
      value={{
 | 
			
		||||
        /* istanbul ignore next */
 | 
			
		||||
        /* eslint-disable no-lone-blocks */
 | 
			
		||||
        {
 | 
			
		||||
          warning(
 | 
			
		||||
            false,
 | 
			
		||||
            'Panel not correct handle keyDown event. Please help to fire issue about this.',
 | 
			
		||||
          );
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
        /* eslint-enable no-lone-blocks */
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const onInternalBlur = (e: FocusEvent) => {
 | 
			
		||||
        if (panelRef.value && panelRef.value.onBlur) {
 | 
			
		||||
          panelRef.value.onBlur(e);
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
      const onNow = () => {
 | 
			
		||||
        const { generateConfig, hourStep, minuteStep, secondStep } = props;
 | 
			
		||||
        const now = generateConfig.getNow();
 | 
			
		||||
        const lowerBoundTime = getLowerBoundTime(
 | 
			
		||||
          generateConfig.getHour(now),
 | 
			
		||||
          generateConfig.getMinute(now),
 | 
			
		||||
          generateConfig.getSecond(now),
 | 
			
		||||
          isHourStepValid ? hourStep : 1,
 | 
			
		||||
          isMinuteStepValid ? minuteStep : 1,
 | 
			
		||||
          isSecondStepValid ? secondStep : 1,
 | 
			
		||||
        );
 | 
			
		||||
        const adjustedNow = setTime(
 | 
			
		||||
          generateConfig,
 | 
			
		||||
          now,
 | 
			
		||||
          lowerBoundTime[0], // hour
 | 
			
		||||
          lowerBoundTime[1], // minute
 | 
			
		||||
          lowerBoundTime[2], // second
 | 
			
		||||
        );
 | 
			
		||||
        triggerSelect(adjustedNow, 'submit');
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const classString = computed(() => {
 | 
			
		||||
        const { prefixCls, direction } = props;
 | 
			
		||||
        return classNames(`${prefixCls}-panel`, {
 | 
			
		||||
          [`${prefixCls}-panel-has-range`]:
 | 
			
		||||
            rangedValue && rangedValue.value && rangedValue.value[0] && rangedValue.value[1],
 | 
			
		||||
          [`${prefixCls}-panel-has-range-hover`]:
 | 
			
		||||
            hoverRangedValue &&
 | 
			
		||||
            hoverRangedValue.value &&
 | 
			
		||||
            hoverRangedValue.value[0] &&
 | 
			
		||||
            hoverRangedValue.value[1],
 | 
			
		||||
          [`${prefixCls}-panel-rtl`]: direction === 'rtl',
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
      useProvidePanel({
 | 
			
		||||
        ...panelContext,
 | 
			
		||||
        mode: mergedMode,
 | 
			
		||||
        hideHeader: 'hideHeader' in props ? hideHeader : panelContext.hideHeader,
 | 
			
		||||
        hidePrevBtn: inRange && panelPosition === 'right',
 | 
			
		||||
        hideNextBtn: inRange && panelPosition === 'left',
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      <div
 | 
			
		||||
        tabindex={tabIndex}
 | 
			
		||||
        class={classNames(`${prefixCls}-panel`, className, {
 | 
			
		||||
          [`${prefixCls}-panel-has-range`]: rangedValue && rangedValue[0] && rangedValue[1],
 | 
			
		||||
          [`${prefixCls}-panel-has-range-hover`]:
 | 
			
		||||
            hoverRangedValue && hoverRangedValue[0] && hoverRangedValue[1],
 | 
			
		||||
          [`${prefixCls}-panel-rtl`]: direction === 'rtl',
 | 
			
		||||
        })}
 | 
			
		||||
        style={style}
 | 
			
		||||
        onKeydown={onInternalKeyDown}
 | 
			
		||||
        onBlur={onInternalBlur}
 | 
			
		||||
        onMousedown={onMouseDown}
 | 
			
		||||
        ref={panelDivRef}
 | 
			
		||||
      >
 | 
			
		||||
        {panelNode}
 | 
			
		||||
        {extraFooter || rangesNode || todayNode ? (
 | 
			
		||||
          <div class={`${prefixCls}-footer`}>
 | 
			
		||||
            {extraFooter}
 | 
			
		||||
            {rangesNode}
 | 
			
		||||
            {todayNode}
 | 
			
		||||
        hideHeader: computed(() =>
 | 
			
		||||
          props.hideHeader !== undefined ? props.hideHeader : panelContext.hideHeader?.value,
 | 
			
		||||
        ),
 | 
			
		||||
        hidePrevBtn: computed(() => inRange.value && panelPosition.value === 'right'),
 | 
			
		||||
        hideNextBtn: computed(() => inRange.value && panelPosition.value === 'left'),
 | 
			
		||||
      });
 | 
			
		||||
      return () => {
 | 
			
		||||
        const {
 | 
			
		||||
          prefixCls = 'ant-picker',
 | 
			
		||||
          locale,
 | 
			
		||||
          generateConfig,
 | 
			
		||||
          disabledDate,
 | 
			
		||||
          picker = 'date',
 | 
			
		||||
          tabindex = 0,
 | 
			
		||||
          showNow,
 | 
			
		||||
          showTime,
 | 
			
		||||
          showToday,
 | 
			
		||||
          renderExtraFooter,
 | 
			
		||||
          onMouseDown,
 | 
			
		||||
          onOk,
 | 
			
		||||
          components,
 | 
			
		||||
        } = props;
 | 
			
		||||
        if (operationRef && panelPosition.value !== 'right') {
 | 
			
		||||
          operationRef.value = {
 | 
			
		||||
            onKeyDown: onInternalKeyDown,
 | 
			
		||||
            onClose: () => {
 | 
			
		||||
              if (panelRef.value && panelRef.value.onClose) {
 | 
			
		||||
                panelRef.value.onClose();
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
          };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // ============================ Panels ============================
 | 
			
		||||
        let panelNode: VueNode;
 | 
			
		||||
 | 
			
		||||
        const pickerProps = {
 | 
			
		||||
          ...(props as MergedPickerPanelProps<DateType>),
 | 
			
		||||
          operationRef: panelRef,
 | 
			
		||||
          prefixCls,
 | 
			
		||||
          viewDate: viewDate.value,
 | 
			
		||||
          value: mergedValue.value,
 | 
			
		||||
          onViewDateChange: setViewDate,
 | 
			
		||||
          sourceMode: sourceMode.value,
 | 
			
		||||
          onPanelChange: onInternalPanelChange,
 | 
			
		||||
          disabledDate,
 | 
			
		||||
        };
 | 
			
		||||
        delete pickerProps.onChange;
 | 
			
		||||
        delete pickerProps.onSelect;
 | 
			
		||||
 | 
			
		||||
        switch (mergedMode.value) {
 | 
			
		||||
          case 'decade':
 | 
			
		||||
            panelNode = (
 | 
			
		||||
              <DecadePanel<DateType>
 | 
			
		||||
                {...pickerProps}
 | 
			
		||||
                onSelect={(date, type) => {
 | 
			
		||||
                  setViewDate(date);
 | 
			
		||||
                  triggerSelect(date, type);
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
            );
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
          case 'year':
 | 
			
		||||
            panelNode = (
 | 
			
		||||
              <YearPanel<DateType>
 | 
			
		||||
                {...pickerProps}
 | 
			
		||||
                onSelect={(date, type) => {
 | 
			
		||||
                  setViewDate(date);
 | 
			
		||||
                  triggerSelect(date, type);
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
            );
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
          case 'month':
 | 
			
		||||
            panelNode = (
 | 
			
		||||
              <MonthPanel<DateType>
 | 
			
		||||
                {...pickerProps}
 | 
			
		||||
                onSelect={(date, type) => {
 | 
			
		||||
                  setViewDate(date);
 | 
			
		||||
                  triggerSelect(date, type);
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
            );
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
          case 'quarter':
 | 
			
		||||
            panelNode = (
 | 
			
		||||
              <QuarterPanel<DateType>
 | 
			
		||||
                {...pickerProps}
 | 
			
		||||
                onSelect={(date, type) => {
 | 
			
		||||
                  setViewDate(date);
 | 
			
		||||
                  triggerSelect(date, type);
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
            );
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
          case 'week':
 | 
			
		||||
            panelNode = (
 | 
			
		||||
              <WeekPanel
 | 
			
		||||
                {...pickerProps}
 | 
			
		||||
                onSelect={(date, type) => {
 | 
			
		||||
                  setViewDate(date);
 | 
			
		||||
                  triggerSelect(date, type);
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
            );
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
          case 'time':
 | 
			
		||||
            delete pickerProps.showTime;
 | 
			
		||||
            panelNode = (
 | 
			
		||||
              <TimePanel<DateType>
 | 
			
		||||
                {...pickerProps}
 | 
			
		||||
                {...(typeof showTime === 'object' ? showTime : null)}
 | 
			
		||||
                onSelect={(date, type) => {
 | 
			
		||||
                  setViewDate(date);
 | 
			
		||||
                  triggerSelect(date, type);
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
            );
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
          default:
 | 
			
		||||
            if (showTime) {
 | 
			
		||||
              panelNode = (
 | 
			
		||||
                <DatetimePanel
 | 
			
		||||
                  {...pickerProps}
 | 
			
		||||
                  onSelect={(date, type) => {
 | 
			
		||||
                    setViewDate(date);
 | 
			
		||||
                    triggerSelect(date, type);
 | 
			
		||||
                  }}
 | 
			
		||||
                />
 | 
			
		||||
              );
 | 
			
		||||
            } else {
 | 
			
		||||
              panelNode = (
 | 
			
		||||
                <DatePanel<DateType>
 | 
			
		||||
                  {...pickerProps}
 | 
			
		||||
                  onSelect={(date, type) => {
 | 
			
		||||
                    setViewDate(date);
 | 
			
		||||
                    triggerSelect(date, type);
 | 
			
		||||
                  }}
 | 
			
		||||
                />
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // ============================ Footer ============================
 | 
			
		||||
        let extraFooter: VueNode;
 | 
			
		||||
        let rangesNode: VueNode;
 | 
			
		||||
 | 
			
		||||
        if (!hideRanges) {
 | 
			
		||||
          extraFooter = getExtraFooter(prefixCls, mergedMode.value, renderExtraFooter);
 | 
			
		||||
          rangesNode = getRanges({
 | 
			
		||||
            prefixCls,
 | 
			
		||||
            components,
 | 
			
		||||
            needConfirmButton: needConfirmButton.value,
 | 
			
		||||
            okDisabled: !mergedValue || (disabledDate && disabledDate(mergedValue.value)),
 | 
			
		||||
            locale,
 | 
			
		||||
            showNow,
 | 
			
		||||
            onNow: needConfirmButton.value && onNow,
 | 
			
		||||
            onOk: () => {
 | 
			
		||||
              if (mergedValue) {
 | 
			
		||||
                triggerSelect(mergedValue.value, 'submit', true);
 | 
			
		||||
                if (onOk) {
 | 
			
		||||
                  onOk(mergedValue.value);
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let todayNode: VueNode;
 | 
			
		||||
 | 
			
		||||
        if (showToday && mergedMode.value === 'date' && picker === 'date' && !showTime) {
 | 
			
		||||
          const now = generateConfig.getNow();
 | 
			
		||||
          const todayCls = `${prefixCls}-today-btn`;
 | 
			
		||||
          const disabled = disabledDate && disabledDate(now);
 | 
			
		||||
          todayNode = (
 | 
			
		||||
            <a
 | 
			
		||||
              class={classNames(todayCls, disabled && `${todayCls}-disabled`)}
 | 
			
		||||
              aria-disabled={disabled}
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
                if (!disabled) {
 | 
			
		||||
                  triggerSelect(now, 'mouse', true);
 | 
			
		||||
                }
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              {locale.today}
 | 
			
		||||
            </a>
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
        return (
 | 
			
		||||
          <div
 | 
			
		||||
            tabindex={tabindex}
 | 
			
		||||
            class={classNames(classString.value, attrs.class)}
 | 
			
		||||
            style={attrs.style}
 | 
			
		||||
            onKeydown={onInternalKeyDown}
 | 
			
		||||
            onBlur={onInternalBlur}
 | 
			
		||||
            onMousedown={onMouseDown}
 | 
			
		||||
            ref={panelDivRef}
 | 
			
		||||
          >
 | 
			
		||||
            {panelNode}
 | 
			
		||||
            {extraFooter || rangesNode || todayNode ? (
 | 
			
		||||
              <div class={`${prefixCls}-footer`}>
 | 
			
		||||
                {extraFooter}
 | 
			
		||||
                {rangesNode}
 | 
			
		||||
                {todayNode}
 | 
			
		||||
              </div>
 | 
			
		||||
            ) : null}
 | 
			
		||||
          </div>
 | 
			
		||||
        ) : null}
 | 
			
		||||
      </div>
 | 
			
		||||
    </PanelContext.Provider>
 | 
			
		||||
  );
 | 
			
		||||
        );
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default PickerPanel;
 | 
			
		||||
/* eslint-enable */
 | 
			
		||||
export default PickerPanel();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ import { AlignType } from '../vc-align/interface';
 | 
			
		|||
import Trigger from '../vc-trigger';
 | 
			
		||||
import classNames from '../_util/classNames';
 | 
			
		||||
import { VueNode } from '../_util/type';
 | 
			
		||||
import useMergeProps from './hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
const BUILT_IN_PLACEMENTS = {
 | 
			
		||||
  bottomLeft: {
 | 
			
		||||
| 
						 | 
				
			
			@ -56,8 +57,8 @@ export type PickerTriggerProps = {
 | 
			
		|||
  direction?: 'ltr' | 'rtl';
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function PickerTrigger(
 | 
			
		||||
  {
 | 
			
		||||
function PickerTrigger(props: PickerTriggerProps, { slots }) {
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    popupElement,
 | 
			
		||||
    popupStyle,
 | 
			
		||||
| 
						 | 
				
			
			@ -69,9 +70,7 @@ function PickerTrigger(
 | 
			
		|||
    range,
 | 
			
		||||
    popupPlacement,
 | 
			
		||||
    direction,
 | 
			
		||||
  }: PickerTriggerProps,
 | 
			
		||||
  { slots },
 | 
			
		||||
) {
 | 
			
		||||
  } = useMergeProps(props);
 | 
			
		||||
  const dropdownPrefixCls = `${prefixCls}-dropdown`;
 | 
			
		||||
 | 
			
		||||
  const getPopupPlacement = () => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
import { inject, InjectionKey, provide } from 'vue';
 | 
			
		||||
import { inject, InjectionKey, provide, Ref } from 'vue';
 | 
			
		||||
import type { NullableDateType, RangeValue } from './interface';
 | 
			
		||||
 | 
			
		||||
export type RangeContextProps = {
 | 
			
		||||
| 
						 | 
				
			
			@ -6,13 +6,12 @@ export type RangeContextProps = {
 | 
			
		|||
   * Set displayed range value style.
 | 
			
		||||
   * Panel only has one value, this is only style effect.
 | 
			
		||||
   */
 | 
			
		||||
  rangedValue?: [NullableDateType<any>, NullableDateType<any>] | null;
 | 
			
		||||
  hoverRangedValue?: RangeValue<any>;
 | 
			
		||||
  inRange?: boolean;
 | 
			
		||||
  panelPosition?: 'left' | 'right' | false;
 | 
			
		||||
  rangedValue?: Ref<[NullableDateType<any>, NullableDateType<any>] | null>;
 | 
			
		||||
  hoverRangedValue?: Ref<RangeValue<any>>;
 | 
			
		||||
  inRange?: Ref<boolean>;
 | 
			
		||||
  panelPosition?: Ref<'left' | 'right' | false>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const RangeContextKey: InjectionKey<RangeContextProps> = Symbol('RangeContextProps');
 | 
			
		||||
 | 
			
		||||
export const useProvideRange = (props: RangeContextProps) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -23,5 +22,4 @@ export const useInjectRange = () => {
 | 
			
		|||
  return inject(RangeContextKey);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export default RangeContextKey;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,10 +16,7 @@ export default function useCellClassName<DateType>({
 | 
			
		|||
}: {
 | 
			
		||||
  cellPrefixCls: string;
 | 
			
		||||
  generateConfig: GenerateConfig<DateType>;
 | 
			
		||||
  isSameCell: (
 | 
			
		||||
    current: NullableDateType<DateType>,
 | 
			
		||||
    target: NullableDateType<DateType>,
 | 
			
		||||
  ) => boolean;
 | 
			
		||||
  isSameCell: (current: NullableDateType<DateType>, target: NullableDateType<DateType>) => boolean;
 | 
			
		||||
  offsetCell: (date: DateType, offset: number) => DateType;
 | 
			
		||||
  isInView: (date: DateType) => boolean;
 | 
			
		||||
  rangedValue?: RangeValue<DateType>;
 | 
			
		||||
| 
						 | 
				
			
			@ -37,12 +34,7 @@ export default function useCellClassName<DateType>({
 | 
			
		|||
    const hoverStart = getValue(hoverRangedValue, 0);
 | 
			
		||||
    const hoverEnd = getValue(hoverRangedValue, 1);
 | 
			
		||||
 | 
			
		||||
    const isRangeHovered = isInRange(
 | 
			
		||||
      generateConfig,
 | 
			
		||||
      hoverStart,
 | 
			
		||||
      hoverEnd,
 | 
			
		||||
      currentDate,
 | 
			
		||||
    );
 | 
			
		||||
    const isRangeHovered = isInRange(generateConfig, hoverStart, hoverEnd, currentDate);
 | 
			
		||||
 | 
			
		||||
    function isRangeStart(date: DateType) {
 | 
			
		||||
      return isSameCell(rangeStart, date);
 | 
			
		||||
| 
						 | 
				
			
			@ -54,11 +46,9 @@ export default function useCellClassName<DateType>({
 | 
			
		|||
    const isHoverEnd = isSameCell(hoverEnd, currentDate);
 | 
			
		||||
 | 
			
		||||
    const isHoverEdgeStart =
 | 
			
		||||
      (isRangeHovered || isHoverEnd) &&
 | 
			
		||||
      (!isInView(prevDate) || isRangeEnd(prevDate));
 | 
			
		||||
      (isRangeHovered || isHoverEnd) && (!isInView(prevDate) || isRangeEnd(prevDate));
 | 
			
		||||
    const isHoverEdgeEnd =
 | 
			
		||||
      (isRangeHovered || isHoverStart) &&
 | 
			
		||||
      (!isInView(nextDate) || isRangeStart(nextDate));
 | 
			
		||||
      (isRangeHovered || isHoverStart) && (!isInView(nextDate) || isRangeStart(nextDate));
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      // In view
 | 
			
		||||
| 
						 | 
				
			
			@ -73,10 +63,8 @@ export default function useCellClassName<DateType>({
 | 
			
		|||
      ),
 | 
			
		||||
      [`${cellPrefixCls}-range-start`]: isRangeStart(currentDate),
 | 
			
		||||
      [`${cellPrefixCls}-range-end`]: isRangeEnd(currentDate),
 | 
			
		||||
      [`${cellPrefixCls}-range-start-single`]:
 | 
			
		||||
        isRangeStart(currentDate) && !rangeEnd,
 | 
			
		||||
      [`${cellPrefixCls}-range-end-single`]:
 | 
			
		||||
        isRangeEnd(currentDate) && !rangeStart,
 | 
			
		||||
      [`${cellPrefixCls}-range-start-single`]: isRangeStart(currentDate) && !rangeEnd,
 | 
			
		||||
      [`${cellPrefixCls}-range-end-single`]: isRangeEnd(currentDate) && !rangeStart,
 | 
			
		||||
      [`${cellPrefixCls}-range-start-near-hover`]:
 | 
			
		||||
        isRangeStart(currentDate) &&
 | 
			
		||||
        (isSameCell(prevDate, hoverStart) ||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ export default function useHoverValue<DateType>(
 | 
			
		|||
  const [value, internalSetValue] = useState<DateType>(null);
 | 
			
		||||
  const raf = useRef(null);
 | 
			
		||||
 | 
			
		||||
  function setValue(val: DateType, immediately: boolean = false) {
 | 
			
		||||
  function setValue(val: DateType, immediately = false) {
 | 
			
		||||
    cancelAnimationFrame(raf.current);
 | 
			
		||||
    if (immediately) {
 | 
			
		||||
      internalSetValue(val);
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ export default function useHoverValue<DateType>(
 | 
			
		|||
    setValue(date);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function onLeave(immediately: boolean = false) {
 | 
			
		||||
  function onLeave(immediately = false) {
 | 
			
		||||
    setValue(null, immediately);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
import type { HTMLAttributes } from 'vue';
 | 
			
		||||
import { useAttrs } from 'vue';
 | 
			
		||||
 | 
			
		||||
// 仅用在函数式组件中,不用考虑响应式问题
 | 
			
		||||
export default function useMergeProps<T>(props: T) {
 | 
			
		||||
  const attrs: HTMLAttributes = useAttrs();
 | 
			
		||||
  return { ...props, ...attrs };
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,11 @@
 | 
			
		|||
import type * as React from 'react';
 | 
			
		||||
import { useState, useEffect, useRef } from 'react';
 | 
			
		||||
import KeyCode from 'rc-util/lib/KeyCode';
 | 
			
		||||
import type { ComputedRef, HTMLAttributes, Ref } from 'vue';
 | 
			
		||||
import { onBeforeUnmount } from 'vue';
 | 
			
		||||
import { watchEffect } from 'vue';
 | 
			
		||||
import { watch } from 'vue';
 | 
			
		||||
import { ref } from 'vue';
 | 
			
		||||
import { computed } from 'vue';
 | 
			
		||||
import type { FocusEventHandler } from '../../_util/EventInterface';
 | 
			
		||||
import KeyCode from '../../_util/KeyCode';
 | 
			
		||||
import { addGlobalMouseDownEvent, getTargetFromEvent } from '../utils/uiUtil';
 | 
			
		||||
 | 
			
		||||
export default function usePickerInput({
 | 
			
		||||
| 
						 | 
				
			
			@ -16,51 +21,51 @@ export default function usePickerInput({
 | 
			
		|||
  onFocus,
 | 
			
		||||
  onBlur,
 | 
			
		||||
}: {
 | 
			
		||||
  open: boolean;
 | 
			
		||||
  value: string;
 | 
			
		||||
  open: Ref<boolean>;
 | 
			
		||||
  value: Ref<string>;
 | 
			
		||||
  isClickOutside: (clickElement: EventTarget | null) => boolean;
 | 
			
		||||
  triggerOpen: (open: boolean) => void;
 | 
			
		||||
  forwardKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => boolean;
 | 
			
		||||
  onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>, preventDefault: () => void) => void;
 | 
			
		||||
  blurToCancel?: boolean;
 | 
			
		||||
  forwardKeyDown: (e: KeyboardEvent) => boolean;
 | 
			
		||||
  onKeyDown: (e: KeyboardEvent, preventDefault: () => void) => void;
 | 
			
		||||
  blurToCancel?: ComputedRef<boolean>;
 | 
			
		||||
  onSubmit: () => void | boolean;
 | 
			
		||||
  onCancel: () => void;
 | 
			
		||||
  onFocus?: React.FocusEventHandler<HTMLInputElement>;
 | 
			
		||||
  onBlur?: React.FocusEventHandler<HTMLInputElement>;
 | 
			
		||||
}): [React.DOMAttributes<HTMLInputElement>, { focused: boolean; typing: boolean }] {
 | 
			
		||||
  const [typing, setTyping] = useState(false);
 | 
			
		||||
  const [focused, setFocused] = useState(false);
 | 
			
		||||
  onFocus?: FocusEventHandler;
 | 
			
		||||
  onBlur?: FocusEventHandler;
 | 
			
		||||
}): [ComputedRef<HTMLAttributes>, { focused: Ref<boolean>; typing: Ref<boolean> }] {
 | 
			
		||||
  const typing = ref(false);
 | 
			
		||||
  const focused = ref(false);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * We will prevent blur to handle open event when user click outside,
 | 
			
		||||
   * since this will repeat trigger `onOpenChange` event.
 | 
			
		||||
   */
 | 
			
		||||
  const preventBlurRef = useRef<boolean>(false);
 | 
			
		||||
  const preventBlurRef = ref<boolean>(false);
 | 
			
		||||
 | 
			
		||||
  const valueChangedRef = useRef<boolean>(false);
 | 
			
		||||
  const valueChangedRef = ref<boolean>(false);
 | 
			
		||||
 | 
			
		||||
  const preventDefaultRef = useRef<boolean>(false);
 | 
			
		||||
  const preventDefaultRef = ref<boolean>(false);
 | 
			
		||||
 | 
			
		||||
  const inputProps: React.DOMAttributes<HTMLInputElement> = {
 | 
			
		||||
    onMouseDown: () => {
 | 
			
		||||
      setTyping(true);
 | 
			
		||||
  const inputProps = computed<HTMLAttributes>(() => ({
 | 
			
		||||
    onMousedown: () => {
 | 
			
		||||
      typing.value = true;
 | 
			
		||||
      triggerOpen(true);
 | 
			
		||||
    },
 | 
			
		||||
    onKeyDown: (e) => {
 | 
			
		||||
    onKeydown: e => {
 | 
			
		||||
      const preventDefault = (): void => {
 | 
			
		||||
        preventDefaultRef.current = true;
 | 
			
		||||
        preventDefaultRef.value = true;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      onKeyDown(e, preventDefault);
 | 
			
		||||
 | 
			
		||||
      if (preventDefaultRef.current) return;
 | 
			
		||||
      if (preventDefaultRef.value) return;
 | 
			
		||||
 | 
			
		||||
      switch (e.which) {
 | 
			
		||||
        case KeyCode.ENTER: {
 | 
			
		||||
          if (!open) {
 | 
			
		||||
          if (!open.value) {
 | 
			
		||||
            triggerOpen(true);
 | 
			
		||||
          } else if (onSubmit() !== false) {
 | 
			
		||||
            setTyping(true);
 | 
			
		||||
            typing.value = true;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          e.preventDefault();
 | 
			
		||||
| 
						 | 
				
			
			@ -68,12 +73,12 @@ export default function usePickerInput({
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        case KeyCode.TAB: {
 | 
			
		||||
          if (typing && open && !e.shiftKey) {
 | 
			
		||||
            setTyping(false);
 | 
			
		||||
          if (typing.value && open.value && !e.shiftKey) {
 | 
			
		||||
            typing.value = false;
 | 
			
		||||
            e.preventDefault();
 | 
			
		||||
          } else if (!typing && open) {
 | 
			
		||||
          } else if (!typing.value && open.value) {
 | 
			
		||||
            if (!forwardKeyDown(e) && e.shiftKey) {
 | 
			
		||||
              setTyping(true);
 | 
			
		||||
              typing.value = true;
 | 
			
		||||
              e.preventDefault();
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
| 
						 | 
				
			
			@ -81,32 +86,32 @@ export default function usePickerInput({
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        case KeyCode.ESC: {
 | 
			
		||||
          setTyping(true);
 | 
			
		||||
          typing.value = true;
 | 
			
		||||
          onCancel();
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!open && ![KeyCode.SHIFT].includes(e.which)) {
 | 
			
		||||
      if (!open.value && ![KeyCode.SHIFT].includes(e.which)) {
 | 
			
		||||
        triggerOpen(true);
 | 
			
		||||
      } else if (!typing) {
 | 
			
		||||
      } else if (!typing.value) {
 | 
			
		||||
        // Let popup panel handle keyboard
 | 
			
		||||
        forwardKeyDown(e);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onFocus: (e) => {
 | 
			
		||||
      setTyping(true);
 | 
			
		||||
      setFocused(true);
 | 
			
		||||
    onFocus: e => {
 | 
			
		||||
      typing.value = true;
 | 
			
		||||
      focused.value = true;
 | 
			
		||||
 | 
			
		||||
      if (onFocus) {
 | 
			
		||||
        onFocus(e);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onBlur: (e) => {
 | 
			
		||||
      if (preventBlurRef.current || !isClickOutside(document.activeElement)) {
 | 
			
		||||
        preventBlurRef.current = false;
 | 
			
		||||
    onBlur: e => {
 | 
			
		||||
      if (preventBlurRef.value || !isClickOutside(document.activeElement)) {
 | 
			
		||||
        preventBlurRef.value = false;
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -121,51 +126,58 @@ export default function usePickerInput({
 | 
			
		|||
            onCancel();
 | 
			
		||||
          }
 | 
			
		||||
        }, 0);
 | 
			
		||||
      } else if (open) {
 | 
			
		||||
      } else if (open.value) {
 | 
			
		||||
        triggerOpen(false);
 | 
			
		||||
 | 
			
		||||
        if (valueChangedRef.current) {
 | 
			
		||||
        if (valueChangedRef.value) {
 | 
			
		||||
          onSubmit();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      setFocused(false);
 | 
			
		||||
      focused.value = false;
 | 
			
		||||
 | 
			
		||||
      if (onBlur) {
 | 
			
		||||
        onBlur(e);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
  }));
 | 
			
		||||
 | 
			
		||||
  // check if value changed
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    valueChangedRef.current = false;
 | 
			
		||||
  }, [open]);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    valueChangedRef.current = true;
 | 
			
		||||
  }, [value]);
 | 
			
		||||
  watch(open, () => {
 | 
			
		||||
    valueChangedRef.value = false;
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  watch(value, () => {
 | 
			
		||||
    valueChangedRef.value = true;
 | 
			
		||||
  });
 | 
			
		||||
  const globalMouseDownEvent = ref();
 | 
			
		||||
  // Global click handler
 | 
			
		||||
  useEffect(() =>
 | 
			
		||||
    addGlobalMouseDownEvent((e: MouseEvent) => {
 | 
			
		||||
      const target = getTargetFromEvent(e);
 | 
			
		||||
  watchEffect(
 | 
			
		||||
    () =>
 | 
			
		||||
      globalMouseDownEvent.value &&
 | 
			
		||||
      globalMouseDownEvent.value()(
 | 
			
		||||
        (globalMouseDownEvent.value = addGlobalMouseDownEvent((e: MouseEvent) => {
 | 
			
		||||
          const target = getTargetFromEvent(e);
 | 
			
		||||
 | 
			
		||||
      if (open) {
 | 
			
		||||
        const clickedOutside = isClickOutside(target);
 | 
			
		||||
          if (open) {
 | 
			
		||||
            const clickedOutside = isClickOutside(target);
 | 
			
		||||
 | 
			
		||||
        if (!clickedOutside) {
 | 
			
		||||
          preventBlurRef.current = true;
 | 
			
		||||
            if (!clickedOutside) {
 | 
			
		||||
              preventBlurRef.value = true;
 | 
			
		||||
 | 
			
		||||
          // Always set back in case `onBlur` prevented by user
 | 
			
		||||
          requestAnimationFrame(() => {
 | 
			
		||||
            preventBlurRef.current = false;
 | 
			
		||||
          });
 | 
			
		||||
        } else if (!focused || clickedOutside) {
 | 
			
		||||
          triggerOpen(false);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }),
 | 
			
		||||
              // Always set back in case `onBlur` prevented by user
 | 
			
		||||
              requestAnimationFrame(() => {
 | 
			
		||||
                preventBlurRef.value = false;
 | 
			
		||||
              });
 | 
			
		||||
            } else if (!focused.value || clickedOutside) {
 | 
			
		||||
              triggerOpen(false);
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        })),
 | 
			
		||||
      ),
 | 
			
		||||
  );
 | 
			
		||||
  onBeforeUnmount(() => {
 | 
			
		||||
    globalMouseDownEvent.value && globalMouseDownEvent.value();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return [inputProps, { focused, typing }];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,31 +1,36 @@
 | 
			
		|||
import * as React from 'react';
 | 
			
		||||
import type { ComputedRef, Ref } from 'vue';
 | 
			
		||||
import { ref, watch } from 'vue';
 | 
			
		||||
 | 
			
		||||
export default function useTextValueMapping({
 | 
			
		||||
  valueTexts,
 | 
			
		||||
  onTextChange,
 | 
			
		||||
}: {
 | 
			
		||||
  /** Must useMemo, to assume that `valueTexts` only match on the first change */
 | 
			
		||||
  valueTexts: string[];
 | 
			
		||||
  valueTexts: ComputedRef<string[]>;
 | 
			
		||||
  onTextChange: (text: string) => void;
 | 
			
		||||
}): [string, (text: string) => void, () => void] {
 | 
			
		||||
  const [text, setInnerText] = React.useState('');
 | 
			
		||||
  const valueTextsRef = React.useRef<string[]>([]);
 | 
			
		||||
  valueTextsRef.current = valueTexts;
 | 
			
		||||
}): [Ref<string>, (text: string) => void, () => void] {
 | 
			
		||||
  const text = ref('');
 | 
			
		||||
 | 
			
		||||
  function triggerTextChange(value: string) {
 | 
			
		||||
    setInnerText(value);
 | 
			
		||||
    text.value = value;
 | 
			
		||||
    onTextChange(value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function resetText() {
 | 
			
		||||
    setInnerText(valueTextsRef.current[0]);
 | 
			
		||||
    text.value = valueTexts.value[0];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  React.useEffect(() => {
 | 
			
		||||
    if (valueTexts.every(valText => valText !== text)) {
 | 
			
		||||
      resetText();
 | 
			
		||||
    }
 | 
			
		||||
  }, [valueTexts.join('||')]);
 | 
			
		||||
  watch(
 | 
			
		||||
    () => [...valueTexts.value],
 | 
			
		||||
    (cur, pre) => {
 | 
			
		||||
      if (
 | 
			
		||||
        cur.join('||') !== pre.join('||') &&
 | 
			
		||||
        valueTexts.value.every(valText => valText !== text.value)
 | 
			
		||||
      ) {
 | 
			
		||||
        resetText();
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return [text, triggerTextChange, resetText];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,32 +1,37 @@
 | 
			
		|||
import shallowEqual from 'shallowequal';
 | 
			
		||||
import useMemo from 'rc-util/lib/hooks/useMemo';
 | 
			
		||||
import type { ComputedRef, Ref } from 'vue';
 | 
			
		||||
import useMemo from '../../_util/hooks/useMemo';
 | 
			
		||||
import shallowequal from '../../_util/shallowequal';
 | 
			
		||||
import type { GenerateConfig } from '../generate';
 | 
			
		||||
import type { CustomFormat, Locale } from '../interface';
 | 
			
		||||
import { formatValue } from '../utils/dateUtil';
 | 
			
		||||
 | 
			
		||||
export type ValueTextConfig<DateType> = {
 | 
			
		||||
  formatList: (string | CustomFormat<DateType>)[];
 | 
			
		||||
  generateConfig: GenerateConfig<DateType>;
 | 
			
		||||
  locale: Locale;
 | 
			
		||||
  formatList: ComputedRef<(string | CustomFormat<DateType>)[]>;
 | 
			
		||||
  generateConfig: Ref<GenerateConfig<DateType>>;
 | 
			
		||||
  locale: Ref<Locale>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function useValueTexts<DateType>(
 | 
			
		||||
  value: DateType | null,
 | 
			
		||||
  value: Ref<DateType | null>,
 | 
			
		||||
  { formatList, generateConfig, locale }: ValueTextConfig<DateType>,
 | 
			
		||||
) {
 | 
			
		||||
  return useMemo<[string[], string]>(
 | 
			
		||||
    () => {
 | 
			
		||||
      if (!value) {
 | 
			
		||||
      if (!value.value) {
 | 
			
		||||
        return [[''], ''];
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // We will convert data format back to first format
 | 
			
		||||
      let firstValueText: string = '';
 | 
			
		||||
      let firstValueText = '';
 | 
			
		||||
      const fullValueTexts: string[] = [];
 | 
			
		||||
 | 
			
		||||
      for (let i = 0; i < formatList.length; i += 1) {
 | 
			
		||||
      for (let i = 0; i < formatList.value.length; i += 1) {
 | 
			
		||||
        const format = formatList[i];
 | 
			
		||||
        const formatStr = formatValue(value, { generateConfig, locale, format });
 | 
			
		||||
        const formatStr = formatValue(value.value, {
 | 
			
		||||
          generateConfig: generateConfig.value,
 | 
			
		||||
          locale: locale.value,
 | 
			
		||||
          format,
 | 
			
		||||
        });
 | 
			
		||||
        fullValueTexts.push(formatStr);
 | 
			
		||||
 | 
			
		||||
        if (i === 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +42,6 @@ export default function useValueTexts<DateType>(
 | 
			
		|||
      return [fullValueTexts, firstValueText];
 | 
			
		||||
    },
 | 
			
		||||
    [value, formatList],
 | 
			
		||||
    (prev, next) => prev[0] !== next[0] || !shallowEqual(prev[1], next[1]),
 | 
			
		||||
    (next, prev) => prev[0] !== next[0] || !shallowequal(prev[1], next[1]),
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
import type { Ref } from 'vue';
 | 
			
		||||
import type { GenerateConfig } from './generate';
 | 
			
		||||
 | 
			
		||||
export type Locale = {
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +47,7 @@ export type PickerMode = Exclude<PanelMode, 'datetime' | 'decade'>;
 | 
			
		|||
 | 
			
		||||
export type PanelRefProps = {
 | 
			
		||||
  onKeyDown?: (e: KeyboardEvent) => boolean;
 | 
			
		||||
  onBlur?: (e: FocusEvent)=> void;
 | 
			
		||||
  onBlur?: (e: FocusEvent) => void;
 | 
			
		||||
  onClose?: () => void;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -74,7 +75,7 @@ export type PanelSharedProps<DateType> = {
 | 
			
		|||
  //  * Thus, move ref into operationRef.
 | 
			
		||||
  //  * This is little hack which should refactor after typescript support.
 | 
			
		||||
  //  */
 | 
			
		||||
  // operationRef: React.MutableRefObject<PanelRefProps>;
 | 
			
		||||
  operationRef: Ref<PanelRefProps>;
 | 
			
		||||
 | 
			
		||||
  onSelect: OnSelect<DateType>;
 | 
			
		||||
  onViewDateChange: (value: DateType) => void;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
import type { GenerateConfig } from '../../generate';
 | 
			
		||||
import {
 | 
			
		||||
  WEEK_DAY_COUNT,
 | 
			
		||||
| 
						 | 
				
			
			@ -12,6 +11,7 @@ import useCellClassName from '../../hooks/useCellClassName';
 | 
			
		|||
import PanelBody from '../PanelBody';
 | 
			
		||||
import { VueNode } from '../../../_util/type';
 | 
			
		||||
import { useInjectRange } from '../../RangeContext';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type DateRender<DateType> = (currentDate: DateType, today: DateType) => VueNode;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,19 +34,12 @@ export type DateBodyProps<DateType> = {
 | 
			
		|||
  onSelect: (value: DateType) => void;
 | 
			
		||||
} & DateBodyPassProps<DateType>;
 | 
			
		||||
 | 
			
		||||
function DateBody<DateType>(props: DateBodyProps<DateType>) {
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    prefixColumn,
 | 
			
		||||
    locale,
 | 
			
		||||
    rowCount,
 | 
			
		||||
    viewDate,
 | 
			
		||||
    value,
 | 
			
		||||
    dateRender,
 | 
			
		||||
  } = props;
 | 
			
		||||
function DateBody<DateType>(_props: DateBodyProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const { prefixCls, generateConfig, prefixColumn, locale, rowCount, viewDate, value, dateRender } =
 | 
			
		||||
    props;
 | 
			
		||||
 | 
			
		||||
  const { rangedValue, hoverRangedValue } =useInjectRange()
 | 
			
		||||
  const { rangedValue, hoverRangedValue } = useInjectRange();
 | 
			
		||||
 | 
			
		||||
  const baseDate = getWeekStartDate(locale.locale, generateConfig, viewDate);
 | 
			
		||||
  const cellPrefixCls = `${prefixCls}-cell`;
 | 
			
		||||
| 
						 | 
				
			
			@ -74,8 +67,8 @@ function DateBody<DateType>(props: DateBodyProps<DateType>) {
 | 
			
		|||
    today,
 | 
			
		||||
    value,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    rangedValue: prefixColumn ? null : rangedValue,
 | 
			
		||||
    hoverRangedValue: prefixColumn ? null : hoverRangedValue,
 | 
			
		||||
    rangedValue: prefixColumn ? null : rangedValue.value,
 | 
			
		||||
    hoverRangedValue: prefixColumn ? null : hoverRangedValue.value,
 | 
			
		||||
    isSameCell: (current, target) => isSameDate(generateConfig, current, target),
 | 
			
		||||
    isInView: date => isSameMonth(generateConfig, date, viewDate),
 | 
			
		||||
    offsetCell: (date, offset) => generateConfig.addDate(date, offset),
 | 
			
		||||
| 
						 | 
				
			
			@ -105,7 +98,20 @@ function DateBody<DateType>(props: DateBodyProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DateBody.displayName = 'DateBody'
 | 
			
		||||
DateBody.displayName = 'DateBody';
 | 
			
		||||
DateBody.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
DateBody.props = [
 | 
			
		||||
  'prefixCls',
 | 
			
		||||
  'generateConfig',
 | 
			
		||||
  'value?',
 | 
			
		||||
  'viewDate',
 | 
			
		||||
  'locale',
 | 
			
		||||
  'rowCount',
 | 
			
		||||
  'onSelect',
 | 
			
		||||
  'dateRender?',
 | 
			
		||||
  'disabledDate?',
 | 
			
		||||
  // Used for week panel
 | 
			
		||||
  'prefixColumn?',
 | 
			
		||||
  'rowClassName?',
 | 
			
		||||
];
 | 
			
		||||
export default DateBody;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,10 @@
 | 
			
		|||
 | 
			
		||||
import Header from '../Header';
 | 
			
		||||
import type { Locale } from '../../interface';
 | 
			
		||||
import type { GenerateConfig } from '../../generate';
 | 
			
		||||
import { useInjectPanel } from '../../PanelContext';
 | 
			
		||||
import { formatValue } from '../../utils/dateUtil';
 | 
			
		||||
import { VueNode } from '../../../_util/type';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type DateHeaderProps<DateType> = {
 | 
			
		||||
  prefixCls: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +21,8 @@ export type DateHeaderProps<DateType> = {
 | 
			
		|||
  onMonthClick: () => void;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function DateHeader<DateType>(props: DateHeaderProps<DateType>) {
 | 
			
		||||
function DateHeader<DateType>(_props: DateHeaderProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
| 
						 | 
				
			
			@ -35,8 +36,8 @@ function DateHeader<DateType>(props: DateHeaderProps<DateType>) {
 | 
			
		|||
    onMonthClick,
 | 
			
		||||
  } = props;
 | 
			
		||||
 | 
			
		||||
  const { hideHeader } = useInjectPanel()
 | 
			
		||||
  if (hideHeader) {
 | 
			
		||||
  const { hideHeader } = useInjectPanel();
 | 
			
		||||
  if (hideHeader.value) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -100,6 +101,6 @@ function DateHeader<DateType>(props: DateHeaderProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DateHeader.displayName = 'DateHeader'
 | 
			
		||||
DateHeader.displayName = 'DateHeader';
 | 
			
		||||
DateHeader.inheritAttrs = false;
 | 
			
		||||
export default DateHeader;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
import type { DateBodyPassProps, DateRender } from './DateBody';
 | 
			
		||||
import DateBody from './DateBody';
 | 
			
		||||
import DateHeader from './DateHeader';
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +7,7 @@ import type { KeyboardConfig } from '../../utils/uiUtil';
 | 
			
		|||
import { createKeyDownHandler } from '../../utils/uiUtil';
 | 
			
		||||
import classNames from '../../../_util/classNames';
 | 
			
		||||
import { ref } from '@vue/reactivity';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
const DATE_ROW_COUNT = 6;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,14 +18,17 @@ export type DatePanelProps<DateType> = {
 | 
			
		|||
  // Used for week panel
 | 
			
		||||
  panelName?: string;
 | 
			
		||||
  keyboardConfig?: KeyboardConfig;
 | 
			
		||||
} & PanelSharedProps<DateType> & DateBodyPassProps<DateType>;
 | 
			
		||||
} & PanelSharedProps<DateType> &
 | 
			
		||||
  DateBodyPassProps<DateType>;
 | 
			
		||||
 | 
			
		||||
function DatePanel<DateType>(props: DatePanelProps<DateType>) {
 | 
			
		||||
function DatePanel<DateType>(_props: DatePanelProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    panelName = 'date',
 | 
			
		||||
    keyboardConfig,
 | 
			
		||||
    active,
 | 
			
		||||
    operationRef,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    value,
 | 
			
		||||
    viewDate,
 | 
			
		||||
| 
						 | 
				
			
			@ -34,10 +37,9 @@ function DatePanel<DateType>(props: DatePanelProps<DateType>) {
 | 
			
		|||
    onSelect,
 | 
			
		||||
  } = props;
 | 
			
		||||
  const panelPrefixCls = `${prefixCls}-${panelName}-panel`;
 | 
			
		||||
  const operationRef = ref()
 | 
			
		||||
  // ======================= Keyboard =======================
 | 
			
		||||
  operationRef.value = {
 | 
			
		||||
    onKeyDown: event =>
 | 
			
		||||
    onKeyDown: (event: KeyboardEvent) =>
 | 
			
		||||
      createKeyDownHandler(event, {
 | 
			
		||||
        onLeftRight: diff => {
 | 
			
		||||
          onSelect(generateConfig.addDate(value || viewDate, diff), 'key');
 | 
			
		||||
| 
						 | 
				
			
			@ -110,7 +112,7 @@ function DatePanel<DateType>(props: DatePanelProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DatePanel.displayName ='DatePanel'
 | 
			
		||||
DatePanel.displayName = 'DatePanel';
 | 
			
		||||
DatePanel.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
export default DatePanel;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
import type { DatePanelProps } from '../DatePanel';
 | 
			
		||||
import DatePanel from '../DatePanel';
 | 
			
		||||
import type { SharedTimeProps } from '../TimePanel';
 | 
			
		||||
| 
						 | 
				
			
			@ -9,20 +8,19 @@ import type { PanelRefProps, DisabledTime } from '../../interface';
 | 
			
		|||
import KeyCode from '../../../_util/KeyCode';
 | 
			
		||||
import classNames from '../../../_util/classNames';
 | 
			
		||||
import { ref } from '@vue/reactivity';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type DatetimePanelProps<DateType> = {
 | 
			
		||||
  disabledTime?: DisabledTime<DateType>;
 | 
			
		||||
  showTime?: boolean | SharedTimeProps<DateType>;
 | 
			
		||||
  defaultValue?: DateType;
 | 
			
		||||
} & Omit<
 | 
			
		||||
    DatePanelProps<DateType>,
 | 
			
		||||
    'disabledHours' | 'disabledMinutes' | 'disabledSeconds'
 | 
			
		||||
  >;
 | 
			
		||||
} & Omit<DatePanelProps<DateType>, 'disabledHours' | 'disabledMinutes' | 'disabledSeconds'>;
 | 
			
		||||
 | 
			
		||||
const ACTIVE_PANEL = tuple('date', 'time');
 | 
			
		||||
type ActivePanelType = typeof ACTIVE_PANEL[number];
 | 
			
		||||
 | 
			
		||||
function DatetimePanel<DateType>(props: DatetimePanelProps<DateType>) {
 | 
			
		||||
function DatetimePanel<DateType>(_props: DatetimePanelProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    operationRef,
 | 
			
		||||
| 
						 | 
				
			
			@ -34,9 +32,7 @@ function DatetimePanel<DateType>(props: DatetimePanelProps<DateType>) {
 | 
			
		|||
    onSelect,
 | 
			
		||||
  } = props;
 | 
			
		||||
  const panelPrefixCls = `${prefixCls}-datetime-panel`;
 | 
			
		||||
  const activePanel = ref<ActivePanelType | null>(
 | 
			
		||||
    null,
 | 
			
		||||
  );
 | 
			
		||||
  const activePanel = ref<ActivePanelType | null>(null);
 | 
			
		||||
 | 
			
		||||
  const dateOperationRef = ref<PanelRefProps>({});
 | 
			
		||||
  const timeOperationRef = ref<PanelRefProps>({});
 | 
			
		||||
| 
						 | 
				
			
			@ -57,12 +53,12 @@ function DatetimePanel<DateType>(props: DatetimePanelProps<DateType>) {
 | 
			
		|||
    activePanel.value = null;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  operationRef.current = {
 | 
			
		||||
    onKeyDown: event => {
 | 
			
		||||
  operationRef.value = {
 | 
			
		||||
    onKeyDown: (event: KeyboardEvent) => {
 | 
			
		||||
      // Switch active panel
 | 
			
		||||
      if (event.which === KeyCode.TAB) {
 | 
			
		||||
        const nextActivePanel = getNextActive(event.shiftKey ? -1 : 1);
 | 
			
		||||
        activePanel.value = nextActivePanel
 | 
			
		||||
        activePanel.value = nextActivePanel;
 | 
			
		||||
 | 
			
		||||
        if (nextActivePanel) {
 | 
			
		||||
          event.preventDefault();
 | 
			
		||||
| 
						 | 
				
			
			@ -73,8 +69,7 @@ function DatetimePanel<DateType>(props: DatetimePanelProps<DateType>) {
 | 
			
		|||
 | 
			
		||||
      // Operate on current active panel
 | 
			
		||||
      if (activePanel.value) {
 | 
			
		||||
        const ref =
 | 
			
		||||
          activePanel.value === 'date' ? dateOperationRef : timeOperationRef;
 | 
			
		||||
        const ref = activePanel.value === 'date' ? dateOperationRef : timeOperationRef;
 | 
			
		||||
 | 
			
		||||
        if (ref.value && ref.value.onKeyDown) {
 | 
			
		||||
          ref.value.onKeyDown(event);
 | 
			
		||||
| 
						 | 
				
			
			@ -84,12 +79,8 @@ function DatetimePanel<DateType>(props: DatetimePanelProps<DateType>) {
 | 
			
		|||
      }
 | 
			
		||||
 | 
			
		||||
      // Switch first active panel if operate without panel
 | 
			
		||||
      if (
 | 
			
		||||
        [KeyCode.LEFT, KeyCode.RIGHT, KeyCode.UP, KeyCode.DOWN].includes(
 | 
			
		||||
          event.which,
 | 
			
		||||
        )
 | 
			
		||||
      ) {
 | 
			
		||||
        activePanel.value = 'date'
 | 
			
		||||
      if ([KeyCode.LEFT, KeyCode.RIGHT, KeyCode.UP, KeyCode.DOWN].includes(event.which)) {
 | 
			
		||||
        activePanel.value = 'date';
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -118,18 +109,9 @@ function DatetimePanel<DateType>(props: DatetimePanelProps<DateType>) {
 | 
			
		|||
        generateConfig.getSecond(timeProps.defaultValue),
 | 
			
		||||
      );
 | 
			
		||||
    } else if (source === 'time' && !value && defaultValue) {
 | 
			
		||||
      selectedDate = generateConfig.setYear(
 | 
			
		||||
        selectedDate,
 | 
			
		||||
        generateConfig.getYear(defaultValue),
 | 
			
		||||
      );
 | 
			
		||||
      selectedDate = generateConfig.setMonth(
 | 
			
		||||
        selectedDate,
 | 
			
		||||
        generateConfig.getMonth(defaultValue),
 | 
			
		||||
      );
 | 
			
		||||
      selectedDate = generateConfig.setDate(
 | 
			
		||||
        selectedDate,
 | 
			
		||||
        generateConfig.getDate(defaultValue),
 | 
			
		||||
      );
 | 
			
		||||
      selectedDate = generateConfig.setYear(selectedDate, generateConfig.getYear(defaultValue));
 | 
			
		||||
      selectedDate = generateConfig.setMonth(selectedDate, generateConfig.getMonth(defaultValue));
 | 
			
		||||
      selectedDate = generateConfig.setDate(selectedDate, generateConfig.getDate(defaultValue));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (onSelect) {
 | 
			
		||||
| 
						 | 
				
			
			@ -155,9 +137,7 @@ function DatetimePanel<DateType>(props: DatetimePanelProps<DateType>) {
 | 
			
		|||
            setTime(
 | 
			
		||||
              generateConfig,
 | 
			
		||||
              date,
 | 
			
		||||
              showTime && typeof showTime === 'object'
 | 
			
		||||
                ? showTime.defaultValue
 | 
			
		||||
                : null,
 | 
			
		||||
              showTime && typeof showTime === 'object' ? showTime.defaultValue : null,
 | 
			
		||||
            ),
 | 
			
		||||
            'date',
 | 
			
		||||
          );
 | 
			
		||||
| 
						 | 
				
			
			@ -179,8 +159,7 @@ function DatetimePanel<DateType>(props: DatetimePanelProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DatetimePanel.displayName ='DatetimePanel'
 | 
			
		||||
DatetimePanel.displayName = 'DatetimePanel';
 | 
			
		||||
DatetimePanel.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
export default DatetimePanel;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
 | 
			
		||||
import type { GenerateConfig } from '../../generate';
 | 
			
		||||
import { DECADE_DISTANCE_COUNT, DECADE_UNIT_DIFF } from '.';
 | 
			
		||||
import PanelBody from '../PanelBody';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export const DECADE_COL_COUNT = 3;
 | 
			
		||||
const DECADE_ROW_COUNT = 4;
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +14,8 @@ export type YearBodyProps<DateType> = {
 | 
			
		|||
  onSelect: (value: DateType) => void;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function DecadeBody<DateType>(props: YearBodyProps<DateType>) {
 | 
			
		||||
function DecadeBody<DateType>(_props: YearBodyProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const DECADE_UNIT_DIFF_DES = DECADE_UNIT_DIFF - 1;
 | 
			
		||||
  const { prefixCls, viewDate, generateConfig } = props;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -61,8 +62,7 @@ function DecadeBody<DateType>(props: YearBodyProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DecadeBody.displayName ='DecadeBody'
 | 
			
		||||
DecadeBody.displayName = 'DecadeBody';
 | 
			
		||||
DecadeBody.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
export default DecadeBody;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
 | 
			
		||||
import Header from '../Header';
 | 
			
		||||
import type { GenerateConfig } from '../../generate';
 | 
			
		||||
import { DECADE_DISTANCE_COUNT } from '.';
 | 
			
		||||
import { useInjectPanel } from '../../PanelContext';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type YearHeaderProps<DateType> = {
 | 
			
		||||
  prefixCls: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -13,15 +13,10 @@ export type YearHeaderProps<DateType> = {
 | 
			
		|||
  onNextDecades: () => void;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function DecadeHeader<DateType>(props: YearHeaderProps<DateType>) {
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    viewDate,
 | 
			
		||||
    onPrevDecades,
 | 
			
		||||
    onNextDecades,
 | 
			
		||||
  } = props;
 | 
			
		||||
  const { hideHeader } =useInjectPanel()
 | 
			
		||||
function DecadeHeader<DateType>(_props: YearHeaderProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const { prefixCls, generateConfig, viewDate, onPrevDecades, onNextDecades } = props;
 | 
			
		||||
  const { hideHeader } = useInjectPanel();
 | 
			
		||||
  if (hideHeader) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -29,8 +24,7 @@ function DecadeHeader<DateType>(props: YearHeaderProps<DateType>) {
 | 
			
		|||
  const headerPrefixCls = `${prefixCls}-header`;
 | 
			
		||||
 | 
			
		||||
  const yearNumber = generateConfig.getYear(viewDate);
 | 
			
		||||
  const startYear =
 | 
			
		||||
    Math.floor(yearNumber / DECADE_DISTANCE_COUNT) * DECADE_DISTANCE_COUNT;
 | 
			
		||||
  const startYear = Math.floor(yearNumber / DECADE_DISTANCE_COUNT) * DECADE_DISTANCE_COUNT;
 | 
			
		||||
  const endYear = startYear + DECADE_DISTANCE_COUNT - 1;
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +39,7 @@ function DecadeHeader<DateType>(props: YearHeaderProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DecadeHeader.displayName ='DecadeHeader'
 | 
			
		||||
DecadeHeader.displayName = 'DecadeHeader';
 | 
			
		||||
DecadeHeader.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
export default DecadeHeader;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +1,16 @@
 | 
			
		|||
 | 
			
		||||
import DecadeHeader from './DecadeHeader';
 | 
			
		||||
import DecadeBody, { DECADE_COL_COUNT } from './DecadeBody';
 | 
			
		||||
import type { PanelSharedProps } from '../../interface';
 | 
			
		||||
import { createKeyDownHandler } from '../../utils/uiUtil';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type DecadePanelProps<DateType> = PanelSharedProps<DateType>;
 | 
			
		||||
 | 
			
		||||
export const DECADE_UNIT_DIFF = 10;
 | 
			
		||||
export const DECADE_DISTANCE_COUNT = DECADE_UNIT_DIFF * 10;
 | 
			
		||||
 | 
			
		||||
function DecadePanel<DateType>(props: DecadePanelProps<DateType>) {
 | 
			
		||||
function DecadePanel<DateType>(_props: DecadePanelProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    onViewDateChange,
 | 
			
		||||
| 
						 | 
				
			
			@ -23,27 +24,18 @@ function DecadePanel<DateType>(props: DecadePanelProps<DateType>) {
 | 
			
		|||
  const panelPrefixCls = `${prefixCls}-decade-panel`;
 | 
			
		||||
 | 
			
		||||
  // ======================= Keyboard =======================
 | 
			
		||||
  operationRef.current = {
 | 
			
		||||
    onKeyDown: event =>
 | 
			
		||||
  operationRef.value = {
 | 
			
		||||
    onKeyDown: (event: KeyboardEvent) =>
 | 
			
		||||
      createKeyDownHandler(event, {
 | 
			
		||||
        onLeftRight: diff => {
 | 
			
		||||
          onSelect(
 | 
			
		||||
            generateConfig.addYear(viewDate, diff * DECADE_UNIT_DIFF),
 | 
			
		||||
            'key',
 | 
			
		||||
          );
 | 
			
		||||
          onSelect(generateConfig.addYear(viewDate, diff * DECADE_UNIT_DIFF), 'key');
 | 
			
		||||
        },
 | 
			
		||||
        onCtrlLeftRight: diff => {
 | 
			
		||||
          onSelect(
 | 
			
		||||
            generateConfig.addYear(viewDate, diff * DECADE_DISTANCE_COUNT),
 | 
			
		||||
            'key',
 | 
			
		||||
          );
 | 
			
		||||
          onSelect(generateConfig.addYear(viewDate, diff * DECADE_DISTANCE_COUNT), 'key');
 | 
			
		||||
        },
 | 
			
		||||
        onUpDown: diff => {
 | 
			
		||||
          onSelect(
 | 
			
		||||
            generateConfig.addYear(
 | 
			
		||||
              viewDate,
 | 
			
		||||
              diff * DECADE_UNIT_DIFF * DECADE_COL_COUNT,
 | 
			
		||||
            ),
 | 
			
		||||
            generateConfig.addYear(viewDate, diff * DECADE_UNIT_DIFF * DECADE_COL_COUNT),
 | 
			
		||||
            'key',
 | 
			
		||||
          );
 | 
			
		||||
        },
 | 
			
		||||
| 
						 | 
				
			
			@ -55,10 +47,7 @@ function DecadePanel<DateType>(props: DecadePanelProps<DateType>) {
 | 
			
		|||
 | 
			
		||||
  // ==================== View Operation ====================
 | 
			
		||||
  const onDecadesChange = (diff: number) => {
 | 
			
		||||
    const newDate = generateConfig.addYear(
 | 
			
		||||
      viewDate,
 | 
			
		||||
      diff * DECADE_DISTANCE_COUNT,
 | 
			
		||||
    );
 | 
			
		||||
    const newDate = generateConfig.addYear(viewDate, diff * DECADE_DISTANCE_COUNT);
 | 
			
		||||
    onViewDateChange(newDate);
 | 
			
		||||
    onPanelChange(null, newDate);
 | 
			
		||||
  };
 | 
			
		||||
| 
						 | 
				
			
			@ -80,17 +69,12 @@ function DecadePanel<DateType>(props: DecadePanelProps<DateType>) {
 | 
			
		|||
          onDecadesChange(1);
 | 
			
		||||
        }}
 | 
			
		||||
      />
 | 
			
		||||
      <DecadeBody
 | 
			
		||||
        {...props}
 | 
			
		||||
        prefixCls={prefixCls}
 | 
			
		||||
        onSelect={onInternalSelect}
 | 
			
		||||
      />
 | 
			
		||||
      <DecadeBody {...props} prefixCls={prefixCls} onSelect={onInternalSelect} />
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DecadePanel.displayName ='DecadePanel'
 | 
			
		||||
DecadePanel.displayName = 'DecadePanel';
 | 
			
		||||
DecadePanel.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
export default DecadePanel;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
import { CSSProperties } from '@vue/runtime-dom';
 | 
			
		||||
import { CSSProperties } from 'vue';
 | 
			
		||||
import { VueNode } from '../../_util/type';
 | 
			
		||||
import useMergeProps from '../hooks/useMergeProps';
 | 
			
		||||
import { useInjectPanel } from '../PanelContext';
 | 
			
		||||
 | 
			
		||||
const HIDDEN_STYLE: CSSProperties = {
 | 
			
		||||
| 
						 | 
				
			
			@ -27,8 +28,9 @@ export type HeaderProps = {
 | 
			
		|||
  children?: VueNode;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function Header(
 | 
			
		||||
  {
 | 
			
		||||
function Header(_props: HeaderProps, { slots }) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    prevIcon = '\u2039',
 | 
			
		||||
    nextIcon = '\u203A',
 | 
			
		||||
| 
						 | 
				
			
			@ -38,9 +40,7 @@ function Header(
 | 
			
		|||
    onSuperNext,
 | 
			
		||||
    onPrev,
 | 
			
		||||
    onNext,
 | 
			
		||||
  }: HeaderProps,
 | 
			
		||||
  { slots },
 | 
			
		||||
) {
 | 
			
		||||
  } = props;
 | 
			
		||||
  const { hideNextBtn, hidePrevBtn } = useInjectPanel();
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +51,7 @@ function Header(
 | 
			
		|||
          onClick={onSuperPrev}
 | 
			
		||||
          tabindex={-1}
 | 
			
		||||
          class={`${prefixCls}-super-prev-btn`}
 | 
			
		||||
          style={hidePrevBtn ? HIDDEN_STYLE : {}}
 | 
			
		||||
          style={hidePrevBtn.value ? HIDDEN_STYLE : {}}
 | 
			
		||||
        >
 | 
			
		||||
          {superPrevIcon}
 | 
			
		||||
        </button>
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ function Header(
 | 
			
		|||
          onClick={onPrev}
 | 
			
		||||
          tabindex={-1}
 | 
			
		||||
          class={`${prefixCls}-prev-btn`}
 | 
			
		||||
          style={hidePrevBtn ? HIDDEN_STYLE : {}}
 | 
			
		||||
          style={hidePrevBtn.value ? HIDDEN_STYLE : {}}
 | 
			
		||||
        >
 | 
			
		||||
          {prevIcon}
 | 
			
		||||
        </button>
 | 
			
		||||
| 
						 | 
				
			
			@ -74,7 +74,7 @@ function Header(
 | 
			
		|||
          onClick={onNext}
 | 
			
		||||
          tabindex={-1}
 | 
			
		||||
          class={`${prefixCls}-next-btn`}
 | 
			
		||||
          style={hideNextBtn ? HIDDEN_STYLE : {}}
 | 
			
		||||
          style={hideNextBtn.value ? HIDDEN_STYLE : {}}
 | 
			
		||||
        >
 | 
			
		||||
          {nextIcon}
 | 
			
		||||
        </button>
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +85,7 @@ function Header(
 | 
			
		|||
          onClick={onSuperNext}
 | 
			
		||||
          tabindex={-1}
 | 
			
		||||
          class={`${prefixCls}-super-next-btn`}
 | 
			
		||||
          style={hideNextBtn ? HIDDEN_STYLE : {}}
 | 
			
		||||
          style={hideNextBtn.value ? HIDDEN_STYLE : {}}
 | 
			
		||||
        >
 | 
			
		||||
          {superNextIcon}
 | 
			
		||||
        </button>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
import type { GenerateConfig } from '../../generate';
 | 
			
		||||
import type { Locale } from '../../interface';
 | 
			
		||||
import { formatValue, isSameMonth } from '../../utils/dateUtil';
 | 
			
		||||
| 
						 | 
				
			
			@ -6,6 +5,7 @@ import { useInjectRange } from '../../RangeContext';
 | 
			
		|||
import useCellClassName from '../../hooks/useCellClassName';
 | 
			
		||||
import PanelBody from '../PanelBody';
 | 
			
		||||
import { VueNode } from '../../../_util/type';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export const MONTH_COL_COUNT = 3;
 | 
			
		||||
const MONTH_ROW_COUNT = 4;
 | 
			
		||||
| 
						 | 
				
			
			@ -23,10 +23,11 @@ export type MonthBodyProps<DateType> = {
 | 
			
		|||
  onSelect: (value: DateType) => void;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function MonthBody<DateType>(props: MonthBodyProps<DateType>) {
 | 
			
		||||
function MonthBody<DateType>(_props: MonthBodyProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const { prefixCls, locale, value, viewDate, generateConfig, monthCellRender } = props;
 | 
			
		||||
 | 
			
		||||
  const { rangedValue, hoverRangedValue } = useInjectRange()
 | 
			
		||||
  const { rangedValue, hoverRangedValue } = useInjectRange();
 | 
			
		||||
 | 
			
		||||
  const cellPrefixCls = `${prefixCls}-cell`;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,8 +35,8 @@ function MonthBody<DateType>(props: MonthBodyProps<DateType>) {
 | 
			
		|||
    cellPrefixCls,
 | 
			
		||||
    value,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    rangedValue,
 | 
			
		||||
    hoverRangedValue,
 | 
			
		||||
    rangedValue: rangedValue.value,
 | 
			
		||||
    hoverRangedValue: hoverRangedValue.value,
 | 
			
		||||
    isSameCell: (current, target) => isSameMonth(generateConfig, current, target),
 | 
			
		||||
    isInView: () => true,
 | 
			
		||||
    offsetCell: (date, offset) => generateConfig.addMonth(date, offset),
 | 
			
		||||
| 
						 | 
				
			
			@ -82,8 +83,7 @@ function MonthBody<DateType>(props: MonthBodyProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MonthBody.displayName ='MonthBody'
 | 
			
		||||
MonthBody.displayName = 'MonthBody';
 | 
			
		||||
MonthBody.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
export default MonthBody;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
 | 
			
		||||
import Header from '../Header';
 | 
			
		||||
import type { Locale } from '../../interface';
 | 
			
		||||
import type { GenerateConfig } from '../../generate';
 | 
			
		||||
import { useInjectPanel } from '../../PanelContext';
 | 
			
		||||
import { formatValue } from '../../utils/dateUtil';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type MonthHeaderProps<DateType> = {
 | 
			
		||||
  prefixCls: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -16,18 +16,12 @@ export type MonthHeaderProps<DateType> = {
 | 
			
		|||
  onYearClick: () => void;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function MonthHeader<DateType>(props: MonthHeaderProps<DateType>) {
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    locale,
 | 
			
		||||
    viewDate,
 | 
			
		||||
    onNextYear,
 | 
			
		||||
    onPrevYear,
 | 
			
		||||
    onYearClick,
 | 
			
		||||
  } = props;
 | 
			
		||||
  const { hideHeader } = useInjectPanel()
 | 
			
		||||
  if (hideHeader) {
 | 
			
		||||
function MonthHeader<DateType>(_props: MonthHeaderProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const { prefixCls, generateConfig, locale, viewDate, onNextYear, onPrevYear, onYearClick } =
 | 
			
		||||
    props;
 | 
			
		||||
  const { hideHeader } = useInjectPanel();
 | 
			
		||||
  if (hideHeader.value) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -51,8 +45,7 @@ function MonthHeader<DateType>(props: MonthHeaderProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MonthHeader.displayName ='MonthHeader'
 | 
			
		||||
MonthHeader.displayName = 'MonthHeader';
 | 
			
		||||
MonthHeader.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
export default MonthHeader;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +1,16 @@
 | 
			
		|||
 | 
			
		||||
import MonthHeader from './MonthHeader';
 | 
			
		||||
import type { MonthCellRender } from './MonthBody';
 | 
			
		||||
import MonthBody, { MONTH_COL_COUNT } from './MonthBody';
 | 
			
		||||
import type { PanelSharedProps } from '../../interface';
 | 
			
		||||
import { createKeyDownHandler } from '../../utils/uiUtil';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type MonthPanelProps<DateType> = {
 | 
			
		||||
  monthCellContentRender?: MonthCellRender<DateType>;
 | 
			
		||||
} & PanelSharedProps<DateType>;
 | 
			
		||||
 | 
			
		||||
function MonthPanel<DateType>(props: MonthPanelProps<DateType>) {
 | 
			
		||||
function MonthPanel<DateType>(_props: MonthPanelProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    operationRef,
 | 
			
		||||
| 
						 | 
				
			
			@ -24,8 +25,8 @@ function MonthPanel<DateType>(props: MonthPanelProps<DateType>) {
 | 
			
		|||
  const panelPrefixCls = `${prefixCls}-month-panel`;
 | 
			
		||||
 | 
			
		||||
  // ======================= Keyboard =======================
 | 
			
		||||
  operationRef.current = {
 | 
			
		||||
    onKeyDown: event =>
 | 
			
		||||
  operationRef.value = {
 | 
			
		||||
    onKeyDown: (event: KeyboardEvent) =>
 | 
			
		||||
      createKeyDownHandler(event, {
 | 
			
		||||
        onLeftRight: diff => {
 | 
			
		||||
          onSelect(generateConfig.addMonth(value || viewDate, diff), 'key');
 | 
			
		||||
| 
						 | 
				
			
			@ -34,10 +35,7 @@ function MonthPanel<DateType>(props: MonthPanelProps<DateType>) {
 | 
			
		|||
          onSelect(generateConfig.addYear(value || viewDate, diff), 'key');
 | 
			
		||||
        },
 | 
			
		||||
        onUpDown: diff => {
 | 
			
		||||
          onSelect(
 | 
			
		||||
            generateConfig.addMonth(value || viewDate, diff * MONTH_COL_COUNT),
 | 
			
		||||
            'key',
 | 
			
		||||
          );
 | 
			
		||||
          onSelect(generateConfig.addMonth(value || viewDate, diff * MONTH_COL_COUNT), 'key');
 | 
			
		||||
        },
 | 
			
		||||
        onEnter: () => {
 | 
			
		||||
          onPanelChange('date', value || viewDate);
 | 
			
		||||
| 
						 | 
				
			
			@ -79,8 +77,7 @@ function MonthPanel<DateType>(props: MonthPanelProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MonthPanel.displayName ='MonthPanel'
 | 
			
		||||
MonthPanel.displayName = 'MonthPanel';
 | 
			
		||||
MonthPanel.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
export default MonthPanel;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
import { useInjectPanel } from '../PanelContext';
 | 
			
		||||
import type { GenerateConfig } from '../generate';
 | 
			
		||||
import { getLastDay } from '../utils/timeUtil';
 | 
			
		||||
| 
						 | 
				
			
			@ -6,6 +5,7 @@ import type { PanelMode } from '../interface';
 | 
			
		|||
import { getCellDateDisabled } from '../utils/dateUtil';
 | 
			
		||||
import { VueNode } from '../../_util/type';
 | 
			
		||||
import classNames from '../../_util/classNames';
 | 
			
		||||
import useMergeProps from '../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type PanelBodyProps<DateType> = {
 | 
			
		||||
  prefixCls: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -30,25 +30,26 @@ export type PanelBodyProps<DateType> = {
 | 
			
		|||
  rowClassName?: (date: DateType) => string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function PanelBody<DateType>({
 | 
			
		||||
  prefixCls,
 | 
			
		||||
  disabledDate,
 | 
			
		||||
  onSelect,
 | 
			
		||||
  picker,
 | 
			
		||||
  rowNum,
 | 
			
		||||
  colNum,
 | 
			
		||||
  prefixColumn,
 | 
			
		||||
  rowClassName,
 | 
			
		||||
  baseDate,
 | 
			
		||||
  getCellClassName,
 | 
			
		||||
  getCellText,
 | 
			
		||||
  getCellNode,
 | 
			
		||||
  getCellDate,
 | 
			
		||||
  generateConfig,
 | 
			
		||||
  titleCell,
 | 
			
		||||
  headerCells,
 | 
			
		||||
}: PanelBodyProps<DateType>) {
 | 
			
		||||
  const { onDateMouseEnter, onDateMouseLeave, mode } = useInjectPanel()
 | 
			
		||||
function PanelBody<DateType>(_props: PanelBodyProps<DateType>) {
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    disabledDate,
 | 
			
		||||
    onSelect,
 | 
			
		||||
    picker,
 | 
			
		||||
    rowNum,
 | 
			
		||||
    colNum,
 | 
			
		||||
    prefixColumn,
 | 
			
		||||
    rowClassName,
 | 
			
		||||
    baseDate,
 | 
			
		||||
    getCellClassName,
 | 
			
		||||
    getCellText,
 | 
			
		||||
    getCellNode,
 | 
			
		||||
    getCellDate,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    titleCell,
 | 
			
		||||
    headerCells,
 | 
			
		||||
  } = useMergeProps(_props);
 | 
			
		||||
  const { onDateMouseEnter, onDateMouseLeave, mode } = useInjectPanel();
 | 
			
		||||
 | 
			
		||||
  const cellPrefixCls = `${prefixCls}-cell`;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +65,7 @@ function PanelBody<DateType>({
 | 
			
		|||
      const currentDate = getCellDate(baseDate, offset);
 | 
			
		||||
      const disabled = getCellDateDisabled({
 | 
			
		||||
        cellDate: currentDate,
 | 
			
		||||
        mode,
 | 
			
		||||
        mode: mode.value,
 | 
			
		||||
        disabledDate,
 | 
			
		||||
        generateConfig,
 | 
			
		||||
      });
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,10 @@
 | 
			
		|||
 | 
			
		||||
import type { GenerateConfig } from '../../generate';
 | 
			
		||||
import type { Locale } from '../../interface';
 | 
			
		||||
import { formatValue, isSameQuarter } from '../../utils/dateUtil';
 | 
			
		||||
import RangeContext, { useInjectRange } from '../../RangeContext';
 | 
			
		||||
import useCellClassName from '../../hooks/useCellClassName';
 | 
			
		||||
import PanelBody from '../PanelBody';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export const QUARTER_COL_COUNT = 4;
 | 
			
		||||
const QUARTER_ROW_COUNT = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -19,10 +19,11 @@ export type QuarterBodyProps<DateType> = {
 | 
			
		|||
  onSelect: (value: DateType) => void;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function QuarterBody<DateType>(props: QuarterBodyProps<DateType>) {
 | 
			
		||||
function QuarterBody<DateType>(_props: QuarterBodyProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const { prefixCls, locale, value, viewDate, generateConfig } = props;
 | 
			
		||||
 | 
			
		||||
  const { rangedValue, hoverRangedValue } = useInjectRange()
 | 
			
		||||
  const { rangedValue, hoverRangedValue } = useInjectRange();
 | 
			
		||||
 | 
			
		||||
  const cellPrefixCls = `${prefixCls}-cell`;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -30,8 +31,8 @@ function QuarterBody<DateType>(props: QuarterBodyProps<DateType>) {
 | 
			
		|||
    cellPrefixCls,
 | 
			
		||||
    value,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    rangedValue,
 | 
			
		||||
    hoverRangedValue,
 | 
			
		||||
    rangedValue: rangedValue.value,
 | 
			
		||||
    hoverRangedValue: hoverRangedValue.value,
 | 
			
		||||
    isSameCell: (current, target) => isSameQuarter(generateConfig, current, target),
 | 
			
		||||
    isInView: () => true,
 | 
			
		||||
    offsetCell: (date, offset) => generateConfig.addMonth(date, offset * 3),
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +66,6 @@ function QuarterBody<DateType>(props: QuarterBodyProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
QuarterBody.displayName ='QuarterBody'
 | 
			
		||||
QuarterBody.displayName = 'QuarterBody';
 | 
			
		||||
QuarterBody.inheritAttrs = false;
 | 
			
		||||
export default QuarterBody;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
 | 
			
		||||
import Header from '../Header';
 | 
			
		||||
import type { Locale } from '../../interface';
 | 
			
		||||
import type { GenerateConfig } from '../../generate';
 | 
			
		||||
import { useInjectPanel } from '../../PanelContext';
 | 
			
		||||
import { formatValue } from '../../utils/dateUtil';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type QuarterHeaderProps<DateType> = {
 | 
			
		||||
  prefixCls: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -16,18 +16,12 @@ export type QuarterHeaderProps<DateType> = {
 | 
			
		|||
  onYearClick: () => void;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function QuarterHeader<DateType>(props: QuarterHeaderProps<DateType>) {
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    locale,
 | 
			
		||||
    viewDate,
 | 
			
		||||
    onNextYear,
 | 
			
		||||
    onPrevYear,
 | 
			
		||||
    onYearClick,
 | 
			
		||||
  } = props;
 | 
			
		||||
  const { hideHeader } =useInjectPanel()
 | 
			
		||||
  if (hideHeader) {
 | 
			
		||||
function QuarterHeader<DateType>(_props: QuarterHeaderProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const { prefixCls, generateConfig, locale, viewDate, onNextYear, onPrevYear, onYearClick } =
 | 
			
		||||
    props;
 | 
			
		||||
  const { hideHeader } = useInjectPanel();
 | 
			
		||||
  if (hideHeader.value) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -50,8 +44,7 @@ function QuarterHeader<DateType>(props: QuarterHeaderProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
QuarterHeader.displayName ='QuarterHeader'
 | 
			
		||||
QuarterHeader.displayName = 'QuarterHeader';
 | 
			
		||||
QuarterHeader.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
export default QuarterHeader;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,12 +1,13 @@
 | 
			
		|||
 | 
			
		||||
import QuarterHeader from './QuarterHeader';
 | 
			
		||||
import QuarterBody from './QuarterBody';
 | 
			
		||||
import type { PanelSharedProps } from '../../interface';
 | 
			
		||||
import { createKeyDownHandler } from '../../utils/uiUtil';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type QuarterPanelProps<DateType> = {} & PanelSharedProps<DateType>;
 | 
			
		||||
 | 
			
		||||
function QuarterPanel<DateType>(props: QuarterPanelProps<DateType>) {
 | 
			
		||||
function QuarterPanel<DateType>(_props: QuarterPanelProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    operationRef,
 | 
			
		||||
| 
						 | 
				
			
			@ -21,8 +22,8 @@ function QuarterPanel<DateType>(props: QuarterPanelProps<DateType>) {
 | 
			
		|||
  const panelPrefixCls = `${prefixCls}-quarter-panel`;
 | 
			
		||||
 | 
			
		||||
  // ======================= Keyboard =======================
 | 
			
		||||
  operationRef.current = {
 | 
			
		||||
    onKeyDown: event =>
 | 
			
		||||
  operationRef.value = {
 | 
			
		||||
    onKeyDown: (event: KeyboardEvent) =>
 | 
			
		||||
      createKeyDownHandler(event, {
 | 
			
		||||
        onLeftRight: diff => {
 | 
			
		||||
          onSelect(generateConfig.addMonth(value || viewDate, diff * 3), 'key');
 | 
			
		||||
| 
						 | 
				
			
			@ -69,8 +70,7 @@ function QuarterPanel<DateType>(props: QuarterPanelProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
QuarterPanel.displayName ='QuarterPanel'
 | 
			
		||||
QuarterPanel.displayName = 'QuarterPanel';
 | 
			
		||||
QuarterPanel.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
export default QuarterPanel;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
import type { GenerateConfig } from '../../generate';
 | 
			
		||||
import type { Locale, OnSelect } from '../../interface';
 | 
			
		||||
import type { Unit } from './TimeUnitColumn';
 | 
			
		||||
| 
						 | 
				
			
			@ -8,17 +7,8 @@ import type { SharedTimeProps } from '.';
 | 
			
		|||
import { setTime as utilSetTime } from '../../utils/timeUtil';
 | 
			
		||||
import { cloneElement } from '../../../_util/vnode';
 | 
			
		||||
import { VueNode } from '../../../_util/type';
 | 
			
		||||
import { ref, Ref } from '@vue/reactivity';
 | 
			
		||||
import { computed, defineComponent, watchEffect } from '@vue/runtime-core';
 | 
			
		||||
 | 
			
		||||
function shouldUnitsUpdate(prevUnits: Unit[], nextUnits: Unit[]) {
 | 
			
		||||
  if (prevUnits.length !== nextUnits.length) return true;
 | 
			
		||||
  // if any unit's disabled status is different, the units should be re-evaluted
 | 
			
		||||
  for (let i = 0; i < prevUnits.length; i += 1) {
 | 
			
		||||
    if (prevUnits[i].disabled !== nextUnits[i].disabled) return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
import type { Ref } from 'vue';
 | 
			
		||||
import { computed, defineComponent } from 'vue';
 | 
			
		||||
 | 
			
		||||
function generateUnits(
 | 
			
		||||
  start: number,
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +41,6 @@ export type TimeBodyProps<DateType> = {
 | 
			
		|||
  operationRef: Ref<BodyOperationRef | undefined>;
 | 
			
		||||
} & SharedTimeProps<DateType>;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const TimeBody = defineComponent({
 | 
			
		||||
  name: 'TimeBody',
 | 
			
		||||
  inheritAttrs: false,
 | 
			
		||||
| 
						 | 
				
			
			@ -75,26 +64,26 @@ const TimeBody = defineComponent({
 | 
			
		|||
    'onSelect',
 | 
			
		||||
  ],
 | 
			
		||||
  setup(props) {
 | 
			
		||||
    const originHour = computed(() => props.value ? props.generateConfig.getHour(props.value) : -1);
 | 
			
		||||
    const isPM = computed(()=> {
 | 
			
		||||
    const originHour = computed(() =>
 | 
			
		||||
      props.value ? props.generateConfig.getHour(props.value) : -1,
 | 
			
		||||
    );
 | 
			
		||||
    const isPM = computed(() => {
 | 
			
		||||
      if (props.use12Hours) {
 | 
			
		||||
        return originHour.value >= 12; // -1 means should display AM
 | 
			
		||||
      } else {
 | 
			
		||||
        return false
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    let hour = computed(()=> {
 | 
			
		||||
      // Should additional logic to handle 12 hours
 | 
			
		||||
      if (props.use12Hours) {
 | 
			
		||||
        return originHour.value % 12
 | 
			
		||||
      } else {
 | 
			
		||||
        return originHour.value
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    const minute = computed(()=> props.value ? props.generateConfig.getMinute(props.value) : -1);
 | 
			
		||||
    const second = computed(()=> props.value ? props.generateConfig.getSecond(props.value) : -1);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    let hour = computed(() => {
 | 
			
		||||
      // Should additional logic to handle 12 hours
 | 
			
		||||
      if (props.use12Hours) {
 | 
			
		||||
        return originHour.value % 12;
 | 
			
		||||
      } else {
 | 
			
		||||
        return originHour.value;
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    const minute = computed(() => (props.value ? props.generateConfig.getMinute(props.value) : -1));
 | 
			
		||||
    const second = computed(() => (props.value ? props.generateConfig.getSecond(props.value) : -1));
 | 
			
		||||
 | 
			
		||||
    const setTime = (
 | 
			
		||||
      isNewPM: boolean | undefined,
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +109,9 @@ const TimeBody = defineComponent({
 | 
			
		|||
    };
 | 
			
		||||
 | 
			
		||||
    // ========================= Unit =========================
 | 
			
		||||
    const rawHours = computed(()=> generateUnits(0, 23, props.hourStep ?? 1, props.disabledHours && props.disabledHours()));
 | 
			
		||||
    const rawHours = computed(() =>
 | 
			
		||||
      generateUnits(0, 23, props.hourStep ?? 1, props.disabledHours && props.disabledHours()),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // const memorizedRawHours = useMemo(() => rawHours, rawHours, shouldUnitsUpdate);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -155,16 +146,25 @@ const TimeBody = defineComponent({
 | 
			
		|||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const minutes = computed(()=> generateUnits(0, 59, props.minuteStep ?? 1, props.disabledMinutes && props.disabledMinutes(originHour.value)));
 | 
			
		||||
    const minutes = computed(() =>
 | 
			
		||||
      generateUnits(
 | 
			
		||||
        0,
 | 
			
		||||
        59,
 | 
			
		||||
        props.minuteStep ?? 1,
 | 
			
		||||
        props.disabledMinutes && props.disabledMinutes(originHour.value),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const seconds = computed(()=> generateUnits(
 | 
			
		||||
      0,
 | 
			
		||||
      59,
 | 
			
		||||
      props.secondStep ?? 1,
 | 
			
		||||
      props.disabledSeconds && props.disabledSeconds(originHour.value, minute),
 | 
			
		||||
    ));
 | 
			
		||||
    const seconds = computed(() =>
 | 
			
		||||
      generateUnits(
 | 
			
		||||
        0,
 | 
			
		||||
        59,
 | 
			
		||||
        props.secondStep ?? 1,
 | 
			
		||||
        props.disabledSeconds && props.disabledSeconds(originHour.value, minute),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    return ()=> {
 | 
			
		||||
    return () => {
 | 
			
		||||
      const {
 | 
			
		||||
        prefixCls,
 | 
			
		||||
        operationRef,
 | 
			
		||||
| 
						 | 
				
			
			@ -188,7 +188,7 @@ const TimeBody = defineComponent({
 | 
			
		|||
 | 
			
		||||
      // ====================== Operations ======================
 | 
			
		||||
      operationRef.value = {
 | 
			
		||||
        onUpDown: diff => {
 | 
			
		||||
        onUpDown: (diff: number) => {
 | 
			
		||||
          const column = columns[activeColumnIndex];
 | 
			
		||||
          if (column) {
 | 
			
		||||
            const valueIndex = column.units.findIndex(unit => unit.value === column.value);
 | 
			
		||||
| 
						 | 
				
			
			@ -237,14 +237,26 @@ const TimeBody = defineComponent({
 | 
			
		|||
      });
 | 
			
		||||
 | 
			
		||||
      // Minute
 | 
			
		||||
      addColumnNode(showMinute, <TimeUnitColumn key="minute" />, minute.value, minutes.value, num => {
 | 
			
		||||
        onSelect(setTime(isPM.value, hour.value, num, second.value), 'mouse');
 | 
			
		||||
      });
 | 
			
		||||
      addColumnNode(
 | 
			
		||||
        showMinute,
 | 
			
		||||
        <TimeUnitColumn key="minute" />,
 | 
			
		||||
        minute.value,
 | 
			
		||||
        minutes.value,
 | 
			
		||||
        num => {
 | 
			
		||||
          onSelect(setTime(isPM.value, hour.value, num, second.value), 'mouse');
 | 
			
		||||
        },
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      // Second
 | 
			
		||||
      addColumnNode(showSecond, <TimeUnitColumn key="second" />, second.value, seconds.value, num => {
 | 
			
		||||
        onSelect(setTime(isPM.value, hour.value, minute.value, num), 'mouse');
 | 
			
		||||
      });
 | 
			
		||||
      addColumnNode(
 | 
			
		||||
        showSecond,
 | 
			
		||||
        <TimeUnitColumn key="second" />,
 | 
			
		||||
        second.value,
 | 
			
		||||
        seconds.value,
 | 
			
		||||
        num => {
 | 
			
		||||
          onSelect(setTime(isPM.value, hour.value, minute.value, num), 'mouse');
 | 
			
		||||
        },
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      // 12 Hours
 | 
			
		||||
      let PMIndex = -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -266,9 +278,8 @@ const TimeBody = defineComponent({
 | 
			
		|||
      );
 | 
			
		||||
 | 
			
		||||
      return <div class={contentPrefixCls}>{columns.map(({ node }) => node)}</div>;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default TimeBody;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
 | 
			
		||||
import Header from '../Header';
 | 
			
		||||
import type { Locale } from '../../interface';
 | 
			
		||||
import type { GenerateConfig } from '../../generate';
 | 
			
		||||
import { useInjectPanel } from '../../PanelContext';
 | 
			
		||||
import { formatValue } from '../../utils/dateUtil';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type TimeHeaderProps<DateType> = {
 | 
			
		||||
  prefixCls: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -13,9 +13,10 @@ export type TimeHeaderProps<DateType> = {
 | 
			
		|||
  format: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function TimeHeader<DateType>(props: TimeHeaderProps<DateType>) {
 | 
			
		||||
  const { hideHeader } = useInjectPanel()
 | 
			
		||||
  if (hideHeader) {
 | 
			
		||||
function TimeHeader<DateType>(_props: TimeHeaderProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const { hideHeader } = useInjectPanel();
 | 
			
		||||
  if (hideHeader.value) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -35,8 +36,7 @@ function TimeHeader<DateType>(props: TimeHeaderProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TimeHeader.displayName ='TimeHeader'
 | 
			
		||||
TimeHeader.displayName = 'TimeHeader';
 | 
			
		||||
TimeHeader.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
export default TimeHeader;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,7 +32,7 @@ function TimeUnitColumn(props: TimeUnitColumnProps) {
 | 
			
		|||
    () => props.value,
 | 
			
		||||
    () => {
 | 
			
		||||
      const li = liRefs.value.get(value!);
 | 
			
		||||
      if (li && open !== false) {
 | 
			
		||||
      if (li && open.value !== false) {
 | 
			
		||||
        scrollTo(ulRef.value!, li.offsetTop, 120);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ function TimeUnitColumn(props: TimeUnitColumnProps) {
 | 
			
		|||
 | 
			
		||||
  watch(open, () => {
 | 
			
		||||
    scrollRef.value?.();
 | 
			
		||||
    if (open) {
 | 
			
		||||
    if (open.value) {
 | 
			
		||||
      const li = liRefs.value.get(value!);
 | 
			
		||||
      if (li) {
 | 
			
		||||
        scrollRef.value = waitElementReady(li, () => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
import TimeHeader from './TimeHeader';
 | 
			
		||||
import type { BodyOperationRef } from './TimeBody';
 | 
			
		||||
import TimeBody from './TimeBody';
 | 
			
		||||
| 
						 | 
				
			
			@ -6,6 +5,7 @@ import type { PanelSharedProps, DisabledTimes } from '../../interface';
 | 
			
		|||
import { createKeyDownHandler } from '../../utils/uiUtil';
 | 
			
		||||
import classNames from '../../../_util/classNames';
 | 
			
		||||
import { ref } from '@vue/reactivity';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type SharedTimeProps<DateType> = {
 | 
			
		||||
  format?: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -24,12 +24,14 @@ export type SharedTimeProps<DateType> = {
 | 
			
		|||
export type TimePanelProps<DateType> = {
 | 
			
		||||
  format?: string;
 | 
			
		||||
  active?: boolean;
 | 
			
		||||
} & PanelSharedProps<DateType> & SharedTimeProps<DateType>;
 | 
			
		||||
} & PanelSharedProps<DateType> &
 | 
			
		||||
  SharedTimeProps<DateType>;
 | 
			
		||||
 | 
			
		||||
const countBoolean = (boolList: (boolean | undefined)[]) =>
 | 
			
		||||
  boolList.filter(bool => bool !== false).length;
 | 
			
		||||
 | 
			
		||||
function TimePanel<DateType>(props: TimePanelProps<DateType>) {
 | 
			
		||||
function TimePanel<DateType>(_props: TimePanelProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const {
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    format = 'HH:mm:ss',
 | 
			
		||||
| 
						 | 
				
			
			@ -50,27 +52,27 @@ function TimePanel<DateType>(props: TimePanelProps<DateType>) {
 | 
			
		|||
  const activeColumnIndex = ref(-1);
 | 
			
		||||
  const columnsCount = countBoolean([showHour, showMinute, showSecond, use12Hours]);
 | 
			
		||||
 | 
			
		||||
  operationRef.current = {
 | 
			
		||||
    onKeyDown: event =>
 | 
			
		||||
  operationRef.value = {
 | 
			
		||||
    onKeyDown: (event: KeyboardEvent) =>
 | 
			
		||||
      createKeyDownHandler(event, {
 | 
			
		||||
        onLeftRight: diff => {
 | 
			
		||||
          activeColumnIndex.value = (activeColumnIndex.value + diff + columnsCount) % columnsCount;
 | 
			
		||||
        },
 | 
			
		||||
        onUpDown: diff => {
 | 
			
		||||
          if (activeColumnIndex.value === -1) {
 | 
			
		||||
            activeColumnIndex.value = 0
 | 
			
		||||
            activeColumnIndex.value = 0;
 | 
			
		||||
          } else if (bodyOperationRef.value) {
 | 
			
		||||
            bodyOperationRef.value.onUpDown(diff);
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        onEnter: () => {
 | 
			
		||||
          onSelect(value || generateConfig.getNow(), 'key');
 | 
			
		||||
          activeColumnIndex.value = -1
 | 
			
		||||
          activeColumnIndex.value = -1;
 | 
			
		||||
        },
 | 
			
		||||
      }),
 | 
			
		||||
 | 
			
		||||
    onBlur: () => {
 | 
			
		||||
      activeColumnIndex.value = -1
 | 
			
		||||
      activeColumnIndex.value = -1;
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -91,8 +93,7 @@ function TimePanel<DateType>(props: TimePanelProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TimePanel.displayName ='TimePanel'
 | 
			
		||||
TimePanel.displayName = 'TimePanel';
 | 
			
		||||
TimePanel.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
export default TimePanel;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,21 +1,19 @@
 | 
			
		|||
 | 
			
		||||
import DatePanel from '../DatePanel';
 | 
			
		||||
import type { PanelSharedProps } from '../../interface';
 | 
			
		||||
import { isSameWeek } from '../../utils/dateUtil';
 | 
			
		||||
import classNames from '../../../_util/classNames';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type WeekPanelProps<DateType> = PanelSharedProps<DateType>;
 | 
			
		||||
 | 
			
		||||
function WeekPanel<DateType>(props: WeekPanelProps<DateType>) {
 | 
			
		||||
function WeekPanel<DateType>(_props: WeekPanelProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const { prefixCls, generateConfig, locale, value } = props;
 | 
			
		||||
 | 
			
		||||
  // Render additional column
 | 
			
		||||
  const cellPrefixCls = `${prefixCls}-cell`;
 | 
			
		||||
  const prefixColumn = (date: DateType) => (
 | 
			
		||||
    <td
 | 
			
		||||
      key="week"
 | 
			
		||||
      class={classNames(cellPrefixCls, `${cellPrefixCls}-week`)}
 | 
			
		||||
    >
 | 
			
		||||
    <td key="week" class={classNames(cellPrefixCls, `${cellPrefixCls}-week`)}>
 | 
			
		||||
      {generateConfig.locale.getWeek(locale.locale, date)}
 | 
			
		||||
    </td>
 | 
			
		||||
  );
 | 
			
		||||
| 
						 | 
				
			
			@ -24,12 +22,7 @@ function WeekPanel<DateType>(props: WeekPanelProps<DateType>) {
 | 
			
		|||
  const rowPrefixCls = `${prefixCls}-week-panel-row`;
 | 
			
		||||
  const rowClassName = (date: DateType) =>
 | 
			
		||||
    classNames(rowPrefixCls, {
 | 
			
		||||
      [`${rowPrefixCls}-selected`]: isSameWeek(
 | 
			
		||||
        generateConfig,
 | 
			
		||||
        locale.locale,
 | 
			
		||||
        value,
 | 
			
		||||
        date,
 | 
			
		||||
      ),
 | 
			
		||||
      [`${rowPrefixCls}-selected`]: isSameWeek(generateConfig, locale.locale, value, date),
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +38,6 @@ function WeekPanel<DateType>(props: WeekPanelProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
WeekPanel.displayName = 'WeekPanel';
 | 
			
		||||
WeekPanel.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,11 @@
 | 
			
		|||
 | 
			
		||||
import type { GenerateConfig } from '../../generate';
 | 
			
		||||
import { YEAR_DECADE_COUNT } from '.';
 | 
			
		||||
import type { Locale, NullableDateType } from '../../interface';
 | 
			
		||||
import useCellClassName from '../../hooks/useCellClassName';
 | 
			
		||||
import { formatValue, isSameYear } from '../../utils/dateUtil';
 | 
			
		||||
import RangeContext, { useInjectRange } from '../../RangeContext';
 | 
			
		||||
import { useInjectRange } from '../../RangeContext';
 | 
			
		||||
import PanelBody from '../PanelBody';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export const YEAR_COL_COUNT = 3;
 | 
			
		||||
const YEAR_ROW_COUNT = 4;
 | 
			
		||||
| 
						 | 
				
			
			@ -20,9 +20,10 @@ export type YearBodyProps<DateType> = {
 | 
			
		|||
  onSelect: (value: DateType) => void;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function YearBody<DateType>(props: YearBodyProps<DateType>) {
 | 
			
		||||
function YearBody<DateType>(_props: YearBodyProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const { prefixCls, value, viewDate, locale, generateConfig } = props;
 | 
			
		||||
  const { rangedValue, hoverRangedValue } = useInjectRange()
 | 
			
		||||
  const { rangedValue, hoverRangedValue } = useInjectRange();
 | 
			
		||||
 | 
			
		||||
  const yearPrefixCls = `${prefixCls}-cell`;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -44,8 +45,8 @@ function YearBody<DateType>(props: YearBodyProps<DateType>) {
 | 
			
		|||
    cellPrefixCls: yearPrefixCls,
 | 
			
		||||
    value,
 | 
			
		||||
    generateConfig,
 | 
			
		||||
    rangedValue,
 | 
			
		||||
    hoverRangedValue,
 | 
			
		||||
    rangedValue: rangedValue.value,
 | 
			
		||||
    hoverRangedValue: hoverRangedValue.value,
 | 
			
		||||
    isSameCell: (current, target) => isSameYear(generateConfig, current, target),
 | 
			
		||||
    isInView,
 | 
			
		||||
    offsetCell: (date, offset) => generateConfig.addYear(date, offset),
 | 
			
		||||
| 
						 | 
				
			
			@ -71,8 +72,6 @@ function YearBody<DateType>(props: YearBodyProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
YearBody.displayName = 'YearBody';
 | 
			
		||||
YearBody.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
 | 
			
		||||
import Header from '../Header';
 | 
			
		||||
import type { GenerateConfig } from '../../generate';
 | 
			
		||||
import { YEAR_DECADE_COUNT } from '.';
 | 
			
		||||
import { useInjectPanel } from '../../PanelContext';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type YearHeaderProps<DateType> = {
 | 
			
		||||
  prefixCls: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -15,10 +15,11 @@ export type YearHeaderProps<DateType> = {
 | 
			
		|||
  onDecadeClick: () => void;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function YearHeader<DateType>(props: YearHeaderProps<DateType>) {
 | 
			
		||||
function YearHeader<DateType>(_props: YearHeaderProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const { prefixCls, generateConfig, viewDate, onPrevDecade, onNextDecade, onDecadeClick } = props;
 | 
			
		||||
  const { hideHeader } = useInjectPanel()
 | 
			
		||||
  if (hideHeader) {
 | 
			
		||||
  const { hideHeader } = useInjectPanel();
 | 
			
		||||
  if (hideHeader.value) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,8 +43,6 @@ function YearHeader<DateType>(props: YearHeaderProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
YearHeader.displayName = 'YearHeader';
 | 
			
		||||
YearHeader.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
 | 
			
		||||
import YearHeader from './YearHeader';
 | 
			
		||||
import YearBody, { YEAR_COL_COUNT } from './YearBody';
 | 
			
		||||
import type { PanelSharedProps, PanelMode } from '../../interface';
 | 
			
		||||
import { createKeyDownHandler } from '../../utils/uiUtil';
 | 
			
		||||
import useMergeProps from '../../hooks/useMergeProps';
 | 
			
		||||
 | 
			
		||||
export type YearPanelProps<DateType> = {
 | 
			
		||||
  sourceMode: PanelMode;
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +10,8 @@ export type YearPanelProps<DateType> = {
 | 
			
		|||
 | 
			
		||||
export const YEAR_DECADE_COUNT = 10;
 | 
			
		||||
 | 
			
		||||
function YearPanel<DateType>(props: YearPanelProps<DateType>) {
 | 
			
		||||
function YearPanel<DateType>(_props: YearPanelProps<DateType>) {
 | 
			
		||||
  const props = useMergeProps(_props);
 | 
			
		||||
  const {
 | 
			
		||||
    prefixCls,
 | 
			
		||||
    operationRef,
 | 
			
		||||
| 
						 | 
				
			
			@ -26,29 +27,20 @@ function YearPanel<DateType>(props: YearPanelProps<DateType>) {
 | 
			
		|||
  const panelPrefixCls = `${prefixCls}-year-panel`;
 | 
			
		||||
 | 
			
		||||
  // ======================= Keyboard =======================
 | 
			
		||||
  operationRef.current = {
 | 
			
		||||
    onKeyDown: event =>
 | 
			
		||||
  operationRef.value = {
 | 
			
		||||
    onKeyDown: (event: KeyboardEvent) =>
 | 
			
		||||
      createKeyDownHandler(event, {
 | 
			
		||||
        onLeftRight: diff => {
 | 
			
		||||
          onSelect(generateConfig.addYear(value || viewDate, diff), 'key');
 | 
			
		||||
        },
 | 
			
		||||
        onCtrlLeftRight: diff => {
 | 
			
		||||
          onSelect(
 | 
			
		||||
            generateConfig.addYear(value || viewDate, diff * YEAR_DECADE_COUNT),
 | 
			
		||||
            'key',
 | 
			
		||||
          );
 | 
			
		||||
          onSelect(generateConfig.addYear(value || viewDate, diff * YEAR_DECADE_COUNT), 'key');
 | 
			
		||||
        },
 | 
			
		||||
        onUpDown: diff => {
 | 
			
		||||
          onSelect(
 | 
			
		||||
            generateConfig.addYear(value || viewDate, diff * YEAR_COL_COUNT),
 | 
			
		||||
            'key',
 | 
			
		||||
          );
 | 
			
		||||
          onSelect(generateConfig.addYear(value || viewDate, diff * YEAR_COL_COUNT), 'key');
 | 
			
		||||
        },
 | 
			
		||||
        onEnter: () => {
 | 
			
		||||
          onPanelChange(
 | 
			
		||||
            sourceMode === 'date' ? 'date' : 'month',
 | 
			
		||||
            value || viewDate,
 | 
			
		||||
          );
 | 
			
		||||
          onPanelChange(sourceMode === 'date' ? 'date' : 'month', value || viewDate);
 | 
			
		||||
        },
 | 
			
		||||
      }),
 | 
			
		||||
  };
 | 
			
		||||
| 
						 | 
				
			
			@ -87,8 +79,6 @@ function YearPanel<DateType>(props: YearPanelProps<DateType>) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
YearPanel.displayName = 'YearPanel';
 | 
			
		||||
YearPanel.inheritAttrs = false;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
import type { PanelMode } from '../interface';
 | 
			
		||||
 | 
			
		||||
export default function getExtraFooter(
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +9,5 @@ export default function getExtraFooter(
 | 
			
		|||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div class={`${prefixCls}-footer-extra`}>{renderExtraFooter(mode)}</div>
 | 
			
		||||
  );
 | 
			
		||||
  return <div class={`${prefixCls}-footer-extra`}>{renderExtraFooter(mode)}</div>;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
import { VueNode } from '../../_util/type';
 | 
			
		||||
import type { Components, RangeList, Locale } from '../interface';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,8 +51,8 @@ export function updateValues<T, R = [T | null, T | null] | null>(
 | 
			
		|||
    typeof value === 'function' ? (value as UpdateValue<T | null>)(newValues[index]) : value;
 | 
			
		||||
 | 
			
		||||
  if (!newValues[0] && !newValues[1]) {
 | 
			
		||||
    return (null as unknown) as R;
 | 
			
		||||
    return null as unknown as R;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (newValues as unknown) as R;
 | 
			
		||||
  return newValues as unknown as R;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,22 +24,12 @@ export function setDateTime<DateType>(
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  let newDate = date;
 | 
			
		||||
  newDate = generateConfig.setHour(
 | 
			
		||||
    newDate,
 | 
			
		||||
    generateConfig.getHour(defaultDate),
 | 
			
		||||
  );
 | 
			
		||||
  newDate = generateConfig.setMinute(
 | 
			
		||||
    newDate,
 | 
			
		||||
    generateConfig.getMinute(defaultDate),
 | 
			
		||||
  );
 | 
			
		||||
  newDate = generateConfig.setSecond(
 | 
			
		||||
    newDate,
 | 
			
		||||
    generateConfig.getSecond(defaultDate),
 | 
			
		||||
  );
 | 
			
		||||
  newDate = generateConfig.setHour(newDate, generateConfig.getHour(defaultDate));
 | 
			
		||||
  newDate = generateConfig.setMinute(newDate, generateConfig.getMinute(defaultDate));
 | 
			
		||||
  newDate = generateConfig.setSecond(newDate, generateConfig.getSecond(defaultDate));
 | 
			
		||||
  return newDate;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export function getLowerBoundTime(
 | 
			
		||||
  hour: number,
 | 
			
		||||
  minute: number,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -201,7 +201,7 @@ export function addGlobalMouseDownEvent(callback: ClickEventHandler) {
 | 
			
		|||
  if (!globalClickFunc && typeof window !== 'undefined' && window.addEventListener) {
 | 
			
		||||
    globalClickFunc = (e: MouseEvent) => {
 | 
			
		||||
      // Clone a new list to avoid repeat trigger events
 | 
			
		||||
      [...clickCallbacks].forEach((queueFunc) => {
 | 
			
		||||
      [...clickCallbacks].forEach(queueFunc => {
 | 
			
		||||
        queueFunc(e);
 | 
			
		||||
      });
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			@ -272,5 +272,5 @@ export function elementsContains(
 | 
			
		|||
  elements: (HTMLElement | undefined | null)[],
 | 
			
		||||
  target: HTMLElement,
 | 
			
		||||
) {
 | 
			
		||||
  return elements.some((ele) => ele && ele.contains(target));
 | 
			
		||||
  return elements.some(ele => ele && ele.contains(target));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue