{"version":3,"file":"picker.mjs","names":[],"sources":["../../../../../../../packages/components/time-picker/src/common/picker.vue"],"sourcesContent":["<template>\n  <el-tooltip\n    ref=\"refPopper\"\n    :visible=\"pickerVisible\"\n    effect=\"light\"\n    pure\n    trigger=\"click\"\n    v-bind=\"$attrs\"\n    role=\"dialog\"\n    teleported\n    :transition=\"`${nsDate.namespace.value}-zoom-in-top`\"\n    :popper-class=\"[`${nsDate.namespace.value}-picker__popper`, popperClass!]\"\n    :popper-style=\"popperStyle\"\n    :popper-options=\"elPopperOptions\"\n    :fallback-placements=\"fallbackPlacements\"\n    :gpu-acceleration=\"false\"\n    :placement=\"placement\"\n    :stop-popper-mouse-event=\"false\"\n    :hide-after=\"0\"\n    persistent\n    @before-show=\"onBeforeShow\"\n    @show=\"onShow\"\n    @hide=\"onHide\"\n  >\n    <template #default>\n      <el-input\n        v-if=\"!isRangeInput\"\n        :id=\"\n          // https://github.com/vuejs/language-tools/issues/2104#issuecomment-3092541527\n          id as string\n        \"\n        ref=\"inputRef\"\n        container-role=\"combobox\"\n        :model-value=\"\n          // https://github.com/vuejs/language-tools/issues/2104#issuecomment-3092541527\n          displayValue as string\n        \"\n        :name=\"\n          // https://github.com/vuejs/language-tools/issues/2104#issuecomment-3092541527\n          name as string\n        \"\n        :size=\"pickerSize\"\n        :disabled=\"pickerDisabled\"\n        :placeholder=\"placeholder\"\n        :class=\"[\n          nsDate.b('editor'),\n          nsDate.bm('editor', type),\n          nsDate.is('focus', pickerVisible),\n          $attrs.class,\n        ]\"\n        :style=\"$attrs.style\"\n        :readonly=\"\n          !editable ||\n          readonly ||\n          isDatesPicker ||\n          isMonthsPicker ||\n          isYearsPicker ||\n          type === 'week'\n        \"\n        :aria-label=\"ariaLabel\"\n        :tabindex=\"tabindex\"\n        :validate-event=\"false\"\n        @input=\"onUserInput\"\n        @focus=\"handleFocus\"\n        @blur=\"handleBlur\"\n        @keydown=\"handleKeydownInput\"\n        @change=\"handleChange\"\n        @mousedown=\"onMouseDownInput\"\n        @mouseenter=\"onMouseEnter\"\n        @mouseleave=\"onMouseLeave\"\n        @touchstart.passive=\"onTouchStartInput\"\n        @click.stop\n      >\n        <template #prefix>\n          <el-icon\n            v-if=\"triggerIcon\"\n            :class=\"nsInput.e('icon')\"\n            @mousedown.prevent=\"onMouseDownInput\"\n            @touchstart.passive=\"onTouchStartInput\"\n          >\n            <component :is=\"triggerIcon\" />\n          </el-icon>\n        </template>\n        <template #suffix>\n          <el-icon\n            v-if=\"showClearBtn && clearIcon\"\n            :class=\"`${nsInput.e('icon')} clear-icon`\"\n            @mousedown.prevent=\"NOOP\"\n            @click=\"onClear\"\n          >\n            <component :is=\"clearIcon\" />\n          </el-icon>\n        </template>\n      </el-input>\n      <picker-range-trigger\n        v-else\n        :id=\"\n          // https://github.com/vuejs/language-tools/issues/2104#issuecomment-3092541527\n          id as string[]\n        \"\n        ref=\"inputRef\"\n        :model-value=\"displayValue\"\n        :name=\"\n          // https://github.com/vuejs/language-tools/issues/2104#issuecomment-3092541527\n          name as string[]\n        \"\n        :disabled=\"pickerDisabled\"\n        :readonly=\"!editable || readonly\"\n        :start-placeholder=\"startPlaceholder\"\n        :end-placeholder=\"endPlaceholder\"\n        :class=\"rangeInputKls\"\n        :style=\"$attrs.style\"\n        :aria-label=\"ariaLabel\"\n        :tabindex=\"tabindex\"\n        autocomplete=\"off\"\n        role=\"combobox\"\n        @click=\"onMouseDownInput\"\n        @focus=\"handleFocus\"\n        @blur=\"handleBlur\"\n        @start-input=\"handleStartInput\"\n        @start-change=\"handleStartChange\"\n        @end-input=\"handleEndInput\"\n        @end-change=\"handleEndChange\"\n        @mousedown=\"onMouseDownInput\"\n        @mouseenter=\"onMouseEnter\"\n        @mouseleave=\"onMouseLeave\"\n        @touchstart.passive=\"onTouchStartInput\"\n        @keydown=\"handleKeydownInput\"\n      >\n        <template #prefix>\n          <el-icon\n            v-if=\"triggerIcon\"\n            :class=\"[nsInput.e('icon'), nsRange.e('icon')]\"\n          >\n            <component :is=\"triggerIcon\" />\n          </el-icon>\n        </template>\n        <template #range-separator>\n          <slot name=\"range-separator\">\n            <span :class=\"nsRange.b('separator')\">{{ rangeSeparator }}</span>\n          </slot>\n        </template>\n        <template #suffix>\n          <el-icon\n            v-if=\"clearIcon\"\n            :class=\"clearIconKls\"\n            @mousedown.prevent=\"NOOP\"\n            @click=\"onClear\"\n          >\n            <component :is=\"clearIcon\" />\n          </el-icon>\n        </template>\n      </picker-range-trigger>\n    </template>\n    <template #content>\n      <slot\n        :visible=\"pickerVisible\"\n        :actual-visible=\"pickerActualVisible\"\n        :parsed-value=\"parsedValue\"\n        :format=\"format\"\n        :date-format=\"dateFormat\"\n        :time-format=\"timeFormat\"\n        :unlink-panels=\"unlinkPanels\"\n        :type=\"type\"\n        :default-value=\"defaultValue\"\n        :show-now=\"showNow\"\n        :show-confirm=\"showConfirm\"\n        :show-footer=\"showFooter\"\n        :show-week-number=\"showWeekNumber\"\n        @pick=\"onPick\"\n        @select-range=\"setSelectionRange\"\n        @set-picker-option=\"onSetPickerOption\"\n        @calendar-change=\"onCalendarChange\"\n        @clear=\"onClear\"\n        @panel-change=\"onPanelChange\"\n        @mousedown.stop\n      />\n    </template>\n  </el-tooltip>\n</template>\n\n<script lang=\"ts\" setup>\nimport {\n  computed,\n  inject,\n  nextTick,\n  onBeforeUnmount,\n  provide,\n  ref,\n  unref,\n  useAttrs,\n  watch,\n} from 'vue'\nimport { onClickOutside, unrefElement } from '@vueuse/core'\nimport {\n  useEmptyValues,\n  useFocusController,\n  useNamespace,\n} from '@element-plus/hooks'\nimport {\n  useFormDisabled,\n  useFormItem,\n  useFormSize,\n} from '@element-plus/components/form'\nimport ElInput from '@element-plus/components/input'\nimport ElIcon from '@element-plus/components/icon'\nimport ElTooltip from '@element-plus/components/tooltip'\nimport { NOOP, debugWarn, getEventCode, isArray } from '@element-plus/utils'\nimport {\n  CHANGE_EVENT,\n  EVENT_CODE,\n  UPDATE_MODEL_EVENT,\n} from '@element-plus/constants'\nimport { Calendar, Clock } from '@element-plus/icons-vue'\nimport { dayOrDaysToDate, valueEquals } from '../utils'\nimport {\n  PICKER_BASE_INJECTION_KEY,\n  PICKER_POPPER_OPTIONS_INJECTION_KEY,\n  ROOT_COMMON_PICKER_INJECTION_KEY,\n} from '../constants'\nimport { useCommonPicker } from '../composables/use-common-picker'\nimport { timePickerDefaultProps } from './props'\nimport PickerRangeTrigger from './picker-range-trigger.vue'\n\nimport type { InputInstance } from '@element-plus/components/input'\nimport type { Dayjs } from 'dayjs'\nimport type { ComponentPublicInstance, Ref } from 'vue'\nimport type { Options } from '@popperjs/core'\nimport type { DayOrDays, TimePickerDefaultProps, UserInput } from './props'\nimport type { TooltipInstance } from '@element-plus/components/tooltip'\n\ndefineOptions({\n  name: 'Picker',\n})\n\nconst props = defineProps(timePickerDefaultProps)\nconst emit = defineEmits([\n  UPDATE_MODEL_EVENT,\n  CHANGE_EVENT,\n  'focus',\n  'blur',\n  'clear',\n  'calendar-change',\n  'panel-change',\n  'visible-change',\n  'keydown',\n])\nconst attrs = useAttrs()\n\nconst nsDate = useNamespace('date')\nconst nsInput = useNamespace('input')\nconst nsRange = useNamespace('range')\n\nconst { formItem } = useFormItem()\nconst elPopperOptions = inject(\n  PICKER_POPPER_OPTIONS_INJECTION_KEY,\n  {} as Options\n)\nconst emptyValues = useEmptyValues(props, null)\n\nconst refPopper = ref<TooltipInstance>()\nconst inputRef = ref<InputInstance>()\nconst valueOnOpen = ref<TimePickerDefaultProps['modelValue'] | null>(null)\nlet hasJustTabExitedInput = false\n\nconst pickerDisabled = useFormDisabled()\n\nconst commonPicker = useCommonPicker(props, emit)\nconst {\n  parsedValue,\n  pickerActualVisible,\n  userInput,\n  pickerVisible,\n  pickerOptions,\n  valueIsEmpty,\n  emitInput,\n  onPick,\n  onSetPickerOption,\n  onCalendarChange,\n  onPanelChange,\n} = commonPicker\n\nconst { isFocused, handleFocus, handleBlur } = useFocusController(inputRef, {\n  disabled: pickerDisabled,\n  beforeFocus() {\n    return props.readonly\n  },\n  afterFocus() {\n    if (!props.automaticDropdown) return\n    pickerVisible.value = true\n  },\n  beforeBlur(event) {\n    return (\n      !hasJustTabExitedInput && refPopper.value?.isFocusInsideContent(event)\n    )\n  },\n  afterBlur() {\n    if (isTimePicker.value && !props.saveOnBlur) {\n      if (!valueIsEmpty.value) {\n        pickerOptions.value.handleCancel?.()\n      }\n    } else {\n      handleChange()\n    }\n    pickerVisible.value = false\n    hasJustTabExitedInput = false\n    props.validateEvent &&\n      formItem?.validate('blur').catch((err) => debugWarn(err))\n  },\n})\n\nconst hovering = ref(false)\n\nconst rangeInputKls = computed(() => [\n  nsDate.b('editor'),\n  nsDate.bm('editor', props.type),\n  nsInput.e('wrapper'),\n  nsDate.is('disabled', pickerDisabled.value),\n  nsDate.is('active', pickerVisible.value),\n  nsRange.b('editor'),\n  pickerSize ? nsRange.bm('editor', pickerSize.value) : '',\n  attrs.class,\n])\n\nconst clearIconKls = computed(() => [\n  nsInput.e('icon'),\n  nsRange.e('close-icon'),\n  !showClearBtn.value ? nsRange.em('close-icon', 'hidden') : '',\n])\n\nwatch(pickerVisible, (val) => {\n  if (!val) {\n    userInput.value = null\n    nextTick(() => {\n      emitChange(props.modelValue)\n    })\n  } else {\n    nextTick(() => {\n      if (val) {\n        valueOnOpen.value = props.modelValue\n      }\n    })\n  }\n})\nconst emitChange = (\n  val: TimePickerDefaultProps['modelValue'] | null,\n  isClear?: boolean\n) => {\n  // determine user real change only\n  if (isClear || !valueEquals(val, valueOnOpen.value)) {\n    emit(CHANGE_EVENT, val)\n    // Set the value of valueOnOpen when clearing to avoid triggering change events multiple times.\n    isClear && (valueOnOpen.value = val)\n    props.validateEvent &&\n      formItem?.validate('change').catch((err) => debugWarn(err))\n  }\n}\nconst emitKeydown = (e: KeyboardEvent) => {\n  emit('keydown', e)\n}\n\nconst refInput = computed<HTMLInputElement[]>(() => {\n  if (inputRef.value) {\n    return Array.from<HTMLInputElement>(\n      inputRef.value.$el.querySelectorAll('input')\n    )\n  }\n  return []\n})\n\n// @ts-ignore\nconst setSelectionRange = (start: number, end: number, pos?: 'min' | 'max') => {\n  const _inputs = refInput.value\n  if (!_inputs.length) return\n  if (!pos || pos === 'min') {\n    _inputs[0].setSelectionRange(start, end)\n    _inputs[0].focus()\n  } else if (pos === 'max') {\n    _inputs[1].setSelectionRange(start, end)\n    _inputs[1].focus()\n  }\n}\n\nconst onBeforeShow = () => {\n  pickerActualVisible.value = true\n}\n\nconst onShow = () => {\n  emit('visible-change', true)\n}\n\nconst onHide = () => {\n  pickerActualVisible.value = false\n  pickerVisible.value = false\n  emit('visible-change', false)\n}\n\nconst handleOpen = () => {\n  pickerVisible.value = true\n}\n\nconst handleClose = () => {\n  pickerVisible.value = false\n}\n\nconst displayValue = computed<UserInput>(() => {\n  const formattedValue = formatToString(parsedValue.value)\n  if (isArray(userInput.value)) {\n    return [\n      userInput.value[0] || (formattedValue && formattedValue[0]) || '',\n      userInput.value[1] || (formattedValue && formattedValue[1]) || '',\n    ]\n  } else if (userInput.value !== null) {\n    return userInput.value\n  }\n  if (isTimePicker.value && valueIsEmpty.value && !props.saveOnBlur) return ''\n  if (!isTimePicker.value && valueIsEmpty.value) return ''\n  if (!pickerVisible.value && valueIsEmpty.value) return ''\n  if (formattedValue) {\n    return isDatesPicker.value || isMonthsPicker.value || isYearsPicker.value\n      ? (formattedValue as Array<string>).join(', ')\n      : formattedValue\n  }\n  return ''\n})\n\nconst isTimeLikePicker = computed(() => props.type.includes('time'))\n\nconst isTimePicker = computed(() => props.type.startsWith('time'))\n\nconst isDatesPicker = computed(() => props.type === 'dates')\n\nconst isMonthsPicker = computed(() => props.type === 'months')\n\nconst isYearsPicker = computed(() => props.type === 'years')\n\nconst triggerIcon = computed(\n  () => props.prefixIcon || (isTimeLikePicker.value ? Clock : Calendar)\n)\n\nconst showClearBtn = computed(\n  () =>\n    props.clearable &&\n    !pickerDisabled.value &&\n    !props.readonly &&\n    !valueIsEmpty.value &&\n    (hovering.value || isFocused.value)\n)\n\nconst onClear = (event?: MouseEvent) => {\n  if (props.readonly || pickerDisabled.value) return\n  if (showClearBtn.value) {\n    event?.stopPropagation()\n    // When the handleClear Function was provided, emit null will be executed inside it\n    // There is no need for us to execute emit null twice. #14752\n    if (pickerOptions.value.handleClear) {\n      pickerOptions.value.handleClear()\n    } else {\n      emitInput(emptyValues.valueOnClear.value)\n    }\n    emitChange(emptyValues.valueOnClear.value, true)\n    onHide()\n  }\n  emit('clear')\n}\n\nconst onMouseDownInput = async (event: MouseEvent) => {\n  if (props.readonly || pickerDisabled.value) return\n  if (\n    (event.target as HTMLElement)?.tagName !== 'INPUT' ||\n    isFocused.value ||\n    !props.automaticDropdown\n  ) {\n    pickerVisible.value = true\n  }\n}\nconst onMouseEnter = () => {\n  if (props.readonly || pickerDisabled.value) return\n  if (!valueIsEmpty.value && props.clearable) {\n    hovering.value = true\n  }\n}\nconst onMouseLeave = () => {\n  hovering.value = false\n}\n\nconst onTouchStartInput = (event: TouchEvent) => {\n  if (props.readonly || pickerDisabled.value) return\n  if (\n    (event.touches[0].target as HTMLElement)?.tagName !== 'INPUT' ||\n    isFocused.value ||\n    !props.automaticDropdown\n  ) {\n    pickerVisible.value = true\n  }\n}\n\nconst isRangeInput = computed(() => {\n  return props.type.includes('range')\n})\n\nconst pickerSize = useFormSize()\n\nconst popperEl = computed(() => unref(refPopper)?.popperRef?.contentRef)\n\nconst stophandle = onClickOutside(\n  inputRef as Ref<ComponentPublicInstance>,\n  (e: PointerEvent) => {\n    const unrefedPopperEl = unref(popperEl)\n    const inputEl = unrefElement(inputRef as Ref<ComponentPublicInstance>)\n    if (\n      (unrefedPopperEl &&\n        (e.target === unrefedPopperEl ||\n          e.composedPath().includes(unrefedPopperEl))) ||\n      e.target === inputEl ||\n      (inputEl && e.composedPath().includes(inputEl))\n    )\n      return\n    pickerVisible.value = false\n  }\n)\n\nonBeforeUnmount(() => {\n  stophandle?.()\n})\n\nconst handleChange = () => {\n  if (isTimePicker.value && !props.saveOnBlur) return\n\n  if (userInput.value) {\n    const value = parseUserInputToDayjs(displayValue.value)\n    if (value) {\n      if (isValidValue(value)) {\n        emitInput(dayOrDaysToDate(value))\n      }\n      userInput.value = null\n    }\n  }\n  if (userInput.value === '') {\n    emitInput(emptyValues.valueOnClear.value)\n    emitChange(emptyValues.valueOnClear.value, true)\n    userInput.value = null\n  }\n}\n\nconst parseUserInputToDayjs = (value: UserInput) => {\n  if (!value) return null\n  return pickerOptions.value.parseUserInput!(value)\n}\n\nconst formatToString = (value: DayOrDays) => {\n  if (!value) return null\n  const res = isArray(value)\n    ? value.map((_) => _.format(props.format))\n    : value.format(props.format)\n  return res as UserInput\n}\n\nconst isValidValue = (value: DayOrDays) => {\n  return pickerOptions.value.isValidValue!(value)\n}\n\nconst handleKeydownInput = async (event: Event | KeyboardEvent) => {\n  if (props.readonly || pickerDisabled.value) return\n\n  const code = getEventCode(event as KeyboardEvent)\n  emitKeydown(event as KeyboardEvent)\n  if (code === EVENT_CODE.esc) {\n    if (pickerVisible.value === true) {\n      pickerVisible.value = false\n      event.preventDefault()\n      event.stopPropagation()\n    }\n    return\n  }\n\n  if (code === EVENT_CODE.down) {\n    if (pickerOptions.value.handleFocusPicker) {\n      event.preventDefault()\n      event.stopPropagation()\n    }\n    if (pickerVisible.value === false) {\n      pickerVisible.value = true\n      await nextTick()\n    }\n    if (pickerOptions.value.handleFocusPicker) {\n      pickerOptions.value.handleFocusPicker()\n      return\n    }\n  }\n\n  if (code === EVENT_CODE.tab) {\n    hasJustTabExitedInput = true\n    return\n  }\n\n  if (code === EVENT_CODE.enter || code === EVENT_CODE.numpadEnter) {\n    if (!pickerVisible.value) {\n      pickerVisible.value = true\n    } else if (\n      userInput.value === null ||\n      userInput.value === '' ||\n      isValidValue(parseUserInputToDayjs(displayValue.value) as DayOrDays)\n    ) {\n      handleChange()\n      pickerVisible.value = false\n    }\n    event.preventDefault()\n    event.stopPropagation()\n    return\n  }\n\n  // if user is typing, do not let picker handle key input\n  if (userInput.value) {\n    event.stopPropagation()\n    return\n  }\n  if (pickerOptions.value.handleKeydownInput) {\n    pickerOptions.value.handleKeydownInput(event as KeyboardEvent)\n  }\n}\nconst onUserInput = (e: string) => {\n  userInput.value = e\n  // Temporary fix when the picker is dismissed and the input box\n  // is focused, just mimic the behavior of antdesign.\n  if (!pickerVisible.value) {\n    pickerVisible.value = true\n  }\n}\n\nconst handleStartInput = (event: Event) => {\n  const target = event.target as HTMLInputElement\n  if (userInput.value) {\n    userInput.value = [target.value, userInput.value[1]]\n  } else {\n    userInput.value = [target.value, null]\n  }\n}\n\nconst handleEndInput = (event: Event) => {\n  const target = event.target as HTMLInputElement\n  if (userInput.value) {\n    userInput.value = [userInput.value[0], target.value]\n  } else {\n    userInput.value = [null, target.value]\n  }\n}\n\nconst handleStartChange = () => {\n  const values = userInput.value as string[]\n  const value = parseUserInputToDayjs(values && values[0]) as Dayjs\n  const parsedVal = unref(parsedValue) as [Dayjs, Dayjs]\n  if (value && value.isValid()) {\n    userInput.value = [\n      formatToString(value) as string,\n      displayValue.value?.[1] || null,\n    ]\n    const newValue = [value, parsedVal && (parsedVal[1] || null)] as DayOrDays\n    if (isValidValue(newValue)) {\n      emitInput(dayOrDaysToDate(newValue))\n      userInput.value = null\n    }\n  }\n}\n\nconst handleEndChange = () => {\n  const values = unref(userInput) as string[]\n  const value = parseUserInputToDayjs(values && values[1]) as Dayjs\n  const parsedVal = unref(parsedValue) as [Dayjs, Dayjs]\n  if (value && value.isValid()) {\n    userInput.value = [\n      unref(displayValue)?.[0] || null,\n      formatToString(value) as string,\n    ]\n    const newValue = [parsedVal && parsedVal[0], value] as DayOrDays\n    if (isValidValue(newValue)) {\n      emitInput(dayOrDaysToDate(newValue))\n      userInput.value = null\n    }\n  }\n}\n\nconst focus = () => {\n  inputRef.value?.focus()\n}\n\nconst blur = () => {\n  inputRef.value?.blur()\n}\n\nprovide(PICKER_BASE_INJECTION_KEY, {\n  props,\n  emptyValues,\n})\nprovide(ROOT_COMMON_PICKER_INJECTION_KEY, commonPicker)\n\ndefineExpose({\n  /**\n   * @description focus input box.\n   */\n  focus,\n  /**\n   * @description blur input box.\n   */\n  blur,\n  /**\n   * @description opens picker\n   */\n  handleOpen,\n  /**\n   * @description closes picker\n   */\n  handleClose,\n  /**\n   * @description pick item manually\n   */\n  onPick,\n})\n</script>\n"],"mappings":""}