<script setup>
import { computed, ref, nextTick, watch, onMounted, onBeforeUnmount } from "vue";
import { useNamespace, useFormItem, useId, useLocale } from "@yh-ui/hooks";
import { useComponentTheme } from "@yh-ui/theme";
import { useConfig } from "@yh-ui/hooks";
import TimeSpinner from "./time-spinner.vue";
import { parseTimeValue, formatTimeState, getCurrentTimeState } from "./time-picker";
defineOptions({
  name: "YhTimePicker"
});
const props = defineProps({
  modelValue: { type: [String, Date, Number, null, Array], required: false },
  disabled: { type: Boolean, required: false, default: false },
  editable: { type: Boolean, required: false, default: true },
  clearable: { type: Boolean, required: false, default: true },
  size: { type: String, required: false, default: void 0 },
  placeholder: { type: String, required: false, default: "" },
  startPlaceholder: { type: String, required: false, default: "" },
  endPlaceholder: { type: String, required: false, default: "" },
  name: { type: String, required: false },
  isRange: { type: Boolean, required: false, default: false },
  format: { type: String, required: false, default: "HH:mm:ss" },
  valueFormat: { type: String, required: false },
  prefixIcon: { type: null, required: false },
  clearIcon: { type: null, required: false },
  use12Hours: { type: Boolean, required: false, default: false },
  showSeconds: { type: Boolean, required: false, default: true },
  hourStep: { type: Number, required: false, default: 1 },
  minuteStep: { type: Number, required: false, default: 1 },
  secondStep: { type: Number, required: false, default: 1 },
  disabledTime: { type: Object, required: false },
  popperClass: { type: String, required: false },
  popperStyle: { type: [String, Object], required: false },
  teleported: { type: Boolean, required: false, default: true },
  validateEvent: { type: Boolean, required: false, default: true },
  popperOffset: { type: Number, required: false, default: 4 },
  rangeSeparator: { type: String, required: false, default: "-" },
  defaultValue: { type: [String, Date, Number, null, Array], required: false },
  hourOptions: { type: Array, required: false },
  minuteOptions: { type: Array, required: false },
  secondOptions: { type: Array, required: false },
  hideOnBlur: { type: Boolean, required: false, default: true },
  confirmText: { type: String, required: false, default: "" },
  cancelText: { type: String, required: false, default: "" },
  nowText: { type: String, required: false, default: "" },
  showFooter: { type: Boolean, required: false, default: true },
  showNow: { type: Boolean, required: false, default: true },
  arrowControl: { type: Boolean, required: false, default: false },
  tabindex: { type: [Number, String], required: false, default: 0 },
  id: { type: String, required: false },
  orderOnConfirm: { type: Boolean, required: false, default: false },
  themeOverrides: { type: null, required: false }
});
const emit = defineEmits(["update:modelValue", "change", "focus", "blur", "clear", "visible-change", "confirm", "cancel"]);
const ns = useNamespace("time-picker");
const { t } = useLocale();
const inputId = useId();
const { themeStyle } = useComponentTheme(
  "time-picker",
  computed(() => props.themeOverrides)
);
const { form, formItem, validate: triggerValidate } = useFormItem();
const { globalSize } = useConfig();
const selectSize = computed(
  () => props.size || formItem?.size || form?.size || globalSize.value || "default"
);
const wrapperRef = ref();
const inputRef = ref();
const startInputRef = ref();
const endInputRef = ref();
const visible = ref(false);
const focused = ref(false);
const hovering = ref(false);
const isClickingPanel = ref(false);
const internalTimeState = ref({ hours: 0, minutes: 0, seconds: 0 });
const internalStartTimeState = ref({ hours: 0, minutes: 0, seconds: 0 });
const internalEndTimeState = ref({ hours: 0, minutes: 0, seconds: 0 });
const dropdownStyle = ref({});
const parsedValue = computed(() => {
  if (props.isRange) {
    const rangeValue = props.modelValue;
    if (!rangeValue || !Array.isArray(rangeValue)) return [null, null];
    return [
      parseTimeValue(rangeValue[0], props.format),
      parseTimeValue(rangeValue[1], rangeValue.length > 1 ? props.format : void 0)
    ];
  }
  return parseTimeValue(props.modelValue, props.format);
});
const displayValue = computed(() => {
  if (props.isRange) {
    return "";
  }
  return formatTimeState(parsedValue.value, props.format, props.use12Hours);
});
const rangeStartDisplayValue = computed(() => {
  if (!props.isRange) return "";
  const [start] = parsedValue.value;
  return formatTimeState(start, props.format, props.use12Hours);
});
const rangeEndDisplayValue = computed(() => {
  if (!props.isRange) return "";
  const [, end] = parsedValue.value;
  return formatTimeState(end, props.format, props.use12Hours);
});
const hasValue = computed(() => {
  if (props.isRange) {
    const rangeValue = props.modelValue;
    return rangeValue && rangeValue[0] !== null && rangeValue[1] !== null;
  }
  return props.modelValue !== null && props.modelValue !== void 0 && props.modelValue !== "";
});
const showClear = computed(
  () => props.clearable && !props.disabled && hasValue.value && (focused.value || hovering.value)
);
const wrapperClasses = computed(() => [
  ns.b(),
  ns.m(selectSize.value),
  ns.is("disabled", props.disabled),
  ns.is("focused", focused.value || visible.value),
  ns.is("range", props.isRange)
]);
const updateDropdownPosition = () => {
  if (!wrapperRef.value || !props.teleported) return;
  const rect = wrapperRef.value.getBoundingClientRect();
  const spaceBelow = window.innerHeight - rect.bottom;
  const panelHeight = 320;
  const showAbove = spaceBelow < panelHeight && rect.top > spaceBelow;
  const styles = window.getComputedStyle(wrapperRef.value);
  const primary = styles.getPropertyValue("--yh-color-primary").trim();
  const primaryRgb = styles.getPropertyValue("--yh-color-primary-rgb").trim();
  dropdownStyle.value = {
    position: "fixed",
    left: `${rect.left}px`,
    minWidth: `${rect.width}px`,
    zIndex: "2000",
    "--yh-color-primary": primary,
    "--yh-color-primary-rgb": primaryRgb,
    ...showAbove ? { bottom: `${window.innerHeight - rect.top + props.popperOffset}px` } : { top: `${rect.bottom + props.popperOffset}px` }
  };
};
const syncInternalState = () => {
  if (props.isRange) {
    const [start, end] = parsedValue.value;
    internalStartTimeState.value = start || { hours: 0, minutes: 0, seconds: 0 };
    internalEndTimeState.value = end || { hours: 0, minutes: 0, seconds: 0 };
  } else {
    const state = parsedValue.value;
    internalTimeState.value = state || (props.defaultValue ? parseTimeValue(props.defaultValue, props.format) : null) || { hours: 0, minutes: 0, seconds: 0 };
  }
};
const getDisabledStartTime = (originalConfig) => {
  if (props.orderOnConfirm || !props.isRange) return originalConfig;
  return {
    ...originalConfig,
    disabledHours: () => {
      return originalConfig?.disabledHours?.() || [];
    },
    disabledMinutes: (h) => originalConfig?.disabledMinutes?.(h) || [],
    disabledSeconds: (h, m) => originalConfig?.disabledSeconds?.(h, m) || []
  };
};
const getDisabledEndTime = (originalConfig) => {
  if (props.orderOnConfirm || !props.isRange) return originalConfig;
  return {
    ...originalConfig,
    disabledHours: () => {
      const hours = originalConfig?.disabledHours?.() || [];
      const startHour = internalStartTimeState.value.hours;
      for (let i = 0; i < startHour; i++) {
        if (!hours.includes(i)) hours.push(i);
      }
      return hours;
    },
    disabledMinutes: (h) => {
      const minutes = originalConfig?.disabledMinutes?.(h) || [];
      const startHour = internalStartTimeState.value.hours;
      const startMin = internalStartTimeState.value.minutes;
      if (h === startHour) {
        for (let i = 0; i < startMin; i++) {
          if (!minutes.includes(i)) minutes.push(i);
        }
      }
      return minutes;
    },
    disabledSeconds: (h, m) => {
      const seconds = originalConfig?.disabledSeconds?.(h, m) || [];
      const startHour = internalStartTimeState.value.hours;
      const startMin = internalStartTimeState.value.minutes;
      const startSec = internalStartTimeState.value.seconds;
      if (h === startHour && m === startMin) {
        for (let i = 0; i < startSec; i++) {
          if (!seconds.includes(i)) seconds.push(i);
        }
      }
      return seconds;
    }
  };
};
const openPanel = () => {
  if (props.disabled) return;
  visible.value = true;
  syncInternalState();
  if (props.teleported) {
    nextTick(updateDropdownPosition);
  }
  emit("visible-change", true);
};
const closePanel = () => {
  visible.value = false;
  emit("visible-change", false);
};
const handleInputChange = (event) => {
  const target = event.target;
  const value = target.value;
  if (!value) {
    emit("update:modelValue", null);
    emit("change", null);
    return;
  }
  const parsed = parseTimeValue(value, props.format);
  if (parsed) {
    const formatted = formatTimeState(parsed, props.valueFormat || props.format);
    emit("update:modelValue", formatted);
    emit("change", formatted);
    internalTimeState.value = parsed;
  } else {
    target.value = displayValue.value;
  }
};
const handleStartInputChange = (event) => {
  const target = event.target;
  const value = target.value;
  const rangeValue = props.modelValue || [null, null];
  if (!value) {
    const newVal = [null, rangeValue[1]];
    emit("update:modelValue", newVal);
    emit("change", newVal);
    return;
  }
  const parsed = parseTimeValue(value, props.format);
  if (parsed) {
    const formatted = formatTimeState(parsed, props.valueFormat || props.format);
    const newVal = [formatted, rangeValue[1]];
    emit("update:modelValue", newVal);
    emit("change", newVal);
    internalStartTimeState.value = parsed;
  } else {
    target.value = rangeStartDisplayValue.value;
  }
};
const handleEndInputChange = (event) => {
  const target = event.target;
  const value = target.value;
  const rangeValue = props.modelValue || [null, null];
  if (!value) {
    const newVal = [rangeValue[0], null];
    emit("update:modelValue", newVal);
    emit("change", newVal);
    return;
  }
  const parsed = parseTimeValue(value, props.format);
  if (parsed) {
    const formatted = formatTimeState(parsed, props.valueFormat || props.format);
    const newVal = [rangeValue[0], formatted];
    emit("update:modelValue", newVal);
    emit("change", newVal);
    internalEndTimeState.value = parsed;
  } else {
    target.value = rangeEndDisplayValue.value;
  }
};
const handleConfirm = () => {
  let valueToEmit;
  if (props.isRange) {
    const startSec = internalStartTimeState.value.hours * 3600 + internalStartTimeState.value.minutes * 60 + internalStartTimeState.value.seconds;
    const endSec = internalEndTimeState.value.hours * 3600 + internalEndTimeState.value.minutes * 60 + internalEndTimeState.value.seconds;
    let finalStart = { ...internalStartTimeState.value };
    let finalEnd = { ...internalEndTimeState.value };
    if (startSec > endSec) {
      if (props.orderOnConfirm) {
        finalStart = { ...internalEndTimeState.value };
        finalEnd = { ...internalStartTimeState.value };
      } else {
        return;
      }
    }
    valueToEmit = [
      formatTimeState(finalStart, props.valueFormat || props.format),
      formatTimeState(finalEnd, props.valueFormat || props.format)
    ];
  } else {
    valueToEmit = formatTimeState(internalTimeState.value, props.valueFormat || props.format);
  }
  emit("update:modelValue", valueToEmit);
  emit("change", valueToEmit);
  emit("confirm", valueToEmit);
  if (props.validateEvent) {
    triggerValidate("change");
  }
  closePanel();
};
const handleCancel = () => {
  syncInternalState();
  emit("cancel");
  closePanel();
};
const handleNow = () => {
  const now = getCurrentTimeState();
  if (props.isRange) {
    internalStartTimeState.value = { ...now };
    internalEndTimeState.value = { ...now };
  } else {
    internalTimeState.value = { ...now };
  }
};
const handleClear = (event) => {
  event.stopPropagation();
  const value = props.isRange ? [null, null] : null;
  emit("update:modelValue", value);
  emit("change", value);
  emit("clear");
  if (props.validateEvent) {
    triggerValidate("change");
  }
};
const togglePanel = () => {
  if (props.disabled) return;
  if (visible.value) {
    closePanel();
  } else {
    openPanel();
  }
};
const handleFocus = (event) => {
  focused.value = true;
  emit("focus", event);
};
const handleBlur = (event) => {
  if (isClickingPanel.value) return;
  focused.value = false;
  if (props.hideOnBlur) {
    closePanel();
  }
  emit("blur", event);
  if (props.validateEvent) {
    triggerValidate("blur");
  }
};
const handlePanelMousedown = (event) => {
  event.preventDefault();
  isClickingPanel.value = true;
};
const handlePanelMouseup = () => {
  setTimeout(() => {
    isClickingPanel.value = false;
  }, 0);
};
const handleMouseEnter = () => {
  hovering.value = true;
};
const handleMouseLeave = () => {
  hovering.value = false;
};
const handleKeydown = (event) => {
  switch (event.key) {
    case "Enter":
      if (visible.value) {
        handleConfirm();
      } else {
        openPanel();
      }
      break;
    case "Escape":
      handleCancel();
      break;
    case "Tab":
      if (visible.value) {
        closePanel();
      }
      break;
  }
};
watch(visible, (val) => {
  if (val && props.teleported) {
    nextTick(updateDropdownPosition);
  }
});
onMounted(() => {
  if (props.teleported) {
    window.addEventListener("scroll", updateDropdownPosition, true);
    window.addEventListener("resize", updateDropdownPosition);
  }
});
onBeforeUnmount(() => {
  if (props.teleported) {
    window.removeEventListener("scroll", updateDropdownPosition, true);
    window.removeEventListener("resize", updateDropdownPosition);
  }
});
const focus = () => {
  if (props.isRange) {
    startInputRef.value?.focus();
  } else {
    inputRef.value?.focus();
  }
};
const blur = () => {
  if (props.isRange) {
    startInputRef.value?.blur();
    endInputRef.value?.blur();
  } else {
    inputRef.value?.blur();
  }
};
defineExpose({
  focus,
  blur,
  open: openPanel,
  close: closePanel,
  inputRef
});
</script>

<template>
  <div
    ref="wrapperRef"
    :class="wrapperClasses"
    :style="themeStyle"
    @mouseenter="handleMouseEnter"
    @mouseleave="handleMouseLeave"
    @click="togglePanel"
  >
    <!-- 输入区域 -->
    <div :class="ns.e('wrapper')">
      <!-- 前缀图标 -->
      <span :class="ns.e('prefix')">
        <slot name="prefix">
          <component :is="prefixIcon" v-if="prefixIcon" :class="ns.e('icon')" />
          <svg v-else viewBox="0 0 1024 1024" width="1em" height="1em" :class="ns.e('icon')">
            <path
              fill="currentColor"
              d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm0 64a384 384 0 1 0 0 768 384 384 0 0 0 0-768zm0 128a32 32 0 0 1 32 32v192l128 64a32 32 0 0 1-28.864 57.088l-144-72A32 32 0 0 1 480 512V288a32 32 0 0 1 32-32z"
            />
          </svg>
        </slot>
      </span>

      <!-- 单选输入框 -->
      <template v-if="!isRange">
        <input
          ref="inputRef"
          :id="id || inputId"
          :class="ns.e('inner')"
          :value="displayValue"
          :placeholder="placeholder || t('timepicker.placeholder')"
          :disabled="disabled"
          :readonly="!editable"
          :name="name"
          :tabindex="tabindex"
          autocomplete="off"
          role="combobox"
          :aria-expanded="visible"
          @focus="handleFocus"
          @blur="handleBlur"
          @keydown="handleKeydown"
          @change="handleInputChange"
        />
      </template>

      <!-- 范围选择输入框 -->
      <template v-else>
        <input
          ref="startInputRef"
          :class="ns.e('range-input')"
          :value="rangeStartDisplayValue"
          :placeholder="startPlaceholder || t('timepicker.startPlaceholder')"
          :disabled="disabled"
          :readonly="!editable"
          :tabindex="tabindex"
          autocomplete="off"
          @focus="handleFocus"
          @blur="handleBlur"
          @keydown="handleKeydown"
          @change="handleStartInputChange"
        />
        <span :class="ns.e('range-separator')">
          <slot name="rangeSeparator">{{ rangeSeparator }}</slot>
        </span>
        <input
          ref="endInputRef"
          :class="ns.e('range-input')"
          :value="rangeEndDisplayValue"
          :placeholder="endPlaceholder || t('timepicker.endPlaceholder')"
          :disabled="disabled"
          :readonly="!editable"
          :tabindex="tabindex"
          autocomplete="off"
          @focus="handleFocus"
          @blur="handleBlur"
          @keydown="handleKeydown"
          @change="handleEndInputChange"
        />
      </template>

      <!-- 后缀图标 -->
      <span :class="ns.e('suffix')">
        <!-- 清空按钮 -->
        <span v-if="showClear" :class="[ns.e('icon'), ns.e('clear')]" @click.stop="handleClear">
          <component :is="clearIcon" v-if="clearIcon" />
          <svg v-else viewBox="0 0 1024 1024" width="1em" height="1em">
            <path
              fill="currentColor"
              d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm0 393.664L407.936 353.6a38.4 38.4 0 1 0-54.336 54.336L457.664 512 353.6 616.064a38.4 38.4 0 1 0 54.336 54.336L512 566.336 616.064 670.4a38.4 38.4 0 1 0 54.336-54.336L566.336 512 670.4 407.936a38.4 38.4 0 1 0-54.336-54.336L512 457.664z"
            />
          </svg>
        </span>

        <!-- 箭头图标 -->
        <span :class="[ns.e('icon'), ns.e('arrow'), {
  'is-reverse': visible
}]">
          <svg viewBox="0 0 1024 1024" width="1em" height="1em">
            <path
              fill="currentColor"
              d="M831.872 340.864L512 652.672 192.128 340.864a30.592 30.592 0 0 0-42.752 0 29.12 29.12 0 0 0 0 41.6L489.664 714.24a32 32 0 0 0 44.672 0l340.288-331.712a29.12 29.12 0 0 0 0-41.728 30.592 30.592 0 0 0-42.752 0z"
            />
          </svg>
        </span>
      </span>
    </div>

    <!-- 下拉面板 -->
    <Teleport to="body" :disabled="!teleported">
      <Transition :name="ns.b('panel')">
        <div
          v-if="visible"
          :class="[ns.e('panel'), popperClass]"
          :style="teleported ? dropdownStyle : {}"
          @mousedown="handlePanelMousedown"
          @mouseup="handlePanelMouseup"
        >
          <!-- 单选面板 -->
          <template v-if="!isRange">
            <TimeSpinner
              v-model="internalTimeState"
              :show-seconds="showSeconds"
              :arrow-control="arrowControl"
              :hour-step="hourStep"
              :minute-step="minuteStep"
              :second-step="secondStep"
              :disabled-time="disabledTime"
              :use12-hours="use12Hours"
              :hour-options="hourOptions"
              :minute-options="minuteOptions"
              :second-options="secondOptions"
            />
          </template>

          <!-- 范围选择面板 -->
          <template v-else>
            <div :class="ns.e('range-panel')">
              <div :class="ns.e('range-panel-item')">
                <div :class="ns.e('range-panel-title')">
                  {{ startPlaceholder ?? t("timepicker.startPlaceholder") }}
                </div>
                <TimeSpinner
                  v-model="internalStartTimeState"
                  :show-seconds="showSeconds"
                  :arrow-control="arrowControl"
                  :hour-step="hourStep"
                  :minute-step="minuteStep"
                  :second-step="secondStep"
                  :disabled-time="getDisabledStartTime(disabledTime)"
                  :use12-hours="use12Hours"
                />
              </div>
              <div :class="ns.e('range-panel-separator')">
                <svg viewBox="0 0 1024 1024" width="1em" height="1em">
                  <path fill="currentColor" d="M384 512l256-256v512z" />
                </svg>
              </div>
              <div :class="ns.e('range-panel-item')">
                <div :class="ns.e('range-panel-title')">
                  {{ endPlaceholder ?? t("timepicker.endPlaceholder") }}
                </div>
                <TimeSpinner
                  v-model="internalEndTimeState"
                  :show-seconds="showSeconds"
                  :arrow-control="arrowControl"
                  :hour-step="hourStep"
                  :minute-step="minuteStep"
                  :second-step="secondStep"
                  :disabled-time="getDisabledEndTime(disabledTime)"
                  :use12-hours="use12Hours"
                />
              </div>
            </div>
          </template>

          <!-- 底部操作栏 -->
          <div v-if="showFooter" :class="ns.e('footer')">
            <button v-if="showNow" type="button" :class="ns.e('footer-btn')" @click="handleNow">
              {{ nowText || t("timepicker.now") }}
            </button>
            <div :class="ns.e('footer-actions')">
              <button
                type="button"
                :class="[ns.e('footer-btn'), ns.e('footer-btn--cancel')]"
                @click="handleCancel"
              >
                {{ cancelText || t("timepicker.cancel") }}
              </button>
              <button
                type="button"
                :class="[ns.e('footer-btn'), ns.e('footer-btn--confirm')]"
                @click="handleConfirm"
              >
                {{ confirmText || t("timepicker.confirm") }}
              </button>
            </div>
          </div>
        </div>
      </Transition>
    </Teleport>
  </div>
</template>

<style>
@charset "UTF-8";
/**
 * YH-UI Sass Variables
 * 原具体的 CSS 变量输出规则 (:root, html.dark 等) 已移至 root.scss，以防止各组件样式编译时产生重复的全局变量 CSS 冗余。
 */
:root {
  --yh-time-picker-width: 220px;
  --yh-time-picker-range-width: 360px;
  --yh-time-picker-active-color: var(--yh-color-primary);
  --yh-time-picker-active-bg: var(--yh-color-primary-light-9);
  --yh-time-picker-hover-bg: var(--yh-fill-color-light);
  --yh-time-picker-panel-bg: var(--yh-bg-color);
  --yh-time-picker-border-radius: var(--yh-radius-md);
}

.yh-time-picker {
  position: relative;
  display: inline-flex;
  width: var(--yh-time-picker-width);
  font-size: 14px;
  line-height: 1.5;
  cursor: pointer;
}
.yh-time-picker--large {
  width: 240px;
  font-size: 16px;
}
.yh-time-picker--large .yh-time-picker__wrapper {
  padding: 10px 12px;
}

.yh-time-picker--large .yh-time-picker__inner, .yh-time-picker--large .yh-time-picker__range-input {
  font-size: 16px;
}

.yh-time-picker--small {
  width: 180px;
  font-size: 12px;
}
.yh-time-picker--small .yh-time-picker__wrapper {
  padding: 4px 8px;
}

.yh-time-picker--small .yh-time-picker__inner, .yh-time-picker--small .yh-time-picker__range-input {
  font-size: 12px;
}

.yh-time-picker.is-range {
  width: var(--yh-time-picker-range-width);
}
.yh-time-picker.is-range .yh-time-picker__wrapper {
  justify-content: space-between;
}

.yh-time-picker.is-disabled {
  cursor: not-allowed;
}
.yh-time-picker.is-disabled .yh-time-picker__wrapper {
  background-color: var(--yh-fill-color-light);
  border-color: var(--yh-border-color-light);
}

.yh-time-picker.is-disabled .yh-time-picker__inner, .yh-time-picker.is-disabled .yh-time-picker__range-input {
  color: var(--yh-text-color-disabled);
  cursor: not-allowed;
}

.yh-time-picker.is-focused .yh-time-picker__wrapper {
  border-color: var(--yh-color-primary);
  box-shadow: 0 0 0 2px rgba(var(--yh-color-primary-rgb), 0.15);
}

.yh-time-picker__wrapper {
  display: flex;
  align-items: center;
  width: 100%;
  padding: 6px 10px;
  background-color: var(--yh-bg-color);
  border: 1px solid var(--yh-border-color);
  border-radius: var(--yh-border-radius-base);
  transition: all 0.2s;
}
.yh-time-picker__wrapper:hover {
  border-color: var(--yh-border-color-hover);
}

.yh-time-picker__prefix {
  display: flex;
  align-items: center;
  margin-right: 8px;
  color: var(--yh-text-color-placeholder);
}

.yh-time-picker__inner {
  flex: 1;
  width: 100%;
  min-width: 0;
  padding: 0;
  margin: 0;
  font-size: inherit;
  font-family: inherit;
  color: var(--yh-text-color-regular);
  background: transparent;
  border: none;
  outline: none;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}
.yh-time-picker__inner::placeholder {
  color: var(--yh-text-color-placeholder);
}

.yh-time-picker__range-input {
  flex: 1;
  width: 0;
  min-width: 60px;
  padding: 0;
  margin: 0;
  font-size: inherit;
  font-family: inherit;
  text-align: center;
  color: var(--yh-text-color-regular);
  background: transparent;
  border: none;
  outline: none;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}
.yh-time-picker__range-input::placeholder {
  color: var(--yh-text-color-placeholder);
}

.yh-time-picker__range-separator {
  display: inline-flex;
  align-items: center;
  padding: 0 8px;
  color: var(--yh-text-color-secondary);
  font-weight: 500;
  flex-shrink: 0;
}

.yh-time-picker__suffix {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
  margin-left: 8px;
  width: 40px;
  flex-shrink: 0;
}

.yh-time-picker__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  font-size: 14px;
  color: var(--yh-text-color-placeholder);
  transition: color 0.2s;
  flex-shrink: 0;
}

.yh-time-picker__clear {
  cursor: pointer;
}
.yh-time-picker__clear:hover {
  color: var(--yh-text-color-regular);
}

.yh-time-picker__arrow {
  transition: transform 0.2s;
}
.yh-time-picker__arrow.is-reverse {
  transform: rotate(180deg);
}

.yh-time-picker__panel {
  position: absolute;
  z-index: var(--yh-z-index-popup);
  min-width: 200px;
  padding: 8px 0;
  background-color: var(--yh-bg-color);
  border-radius: var(--yh-border-radius-base);
  box-shadow: var(--yh-box-shadow-light);
  border: 1px solid var(--yh-border-color-light);
}
.yh-time-picker__panel-enter-active, .yh-time-picker__panel-leave-active {
  transition: opacity 0.2s, transform 0.2s;
}
.yh-time-picker__panel-enter-from, .yh-time-picker__panel-leave-to {
  opacity: 0;
  transform: translateY(-8px);
}

.yh-time-picker__range-panel {
  display: flex;
  align-items: flex-start;
  padding: 0 8px;
}

.yh-time-picker__range-panel-item {
  flex: 1;
}

.yh-time-picker__range-panel-title {
  padding: 8px 0;
  font-size: 12px;
  font-weight: 500;
  color: var(--yh-text-color-secondary);
  text-align: center;
}

.yh-time-picker__range-panel-separator {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 60px 16px 0;
  color: var(--yh-text-color-placeholder);
}
.yh-time-picker__range-panel-separator svg {
  width: 16px;
  height: 16px;
}

.yh-time-picker__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  border-top: 1px solid var(--yh-border-color-lighter);
  margin-top: 8px;
}

.yh-time-picker__footer-actions {
  display: flex;
  gap: 8px;
}

.yh-time-picker__footer-btn {
  padding: 6px 16px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--yh-text-color-regular);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--yh-border-radius-base);
  cursor: pointer;
  transition: all 0.2s;
}
.yh-time-picker__footer-btn:hover {
  color: var(--yh-color-primary);
}
.yh-time-picker__footer-btn--cancel {
  border-color: var(--yh-border-color);
  background-color: var(--yh-bg-color);
}
.yh-time-picker__footer-btn--cancel:hover {
  border-color: var(--yh-color-primary);
  color: var(--yh-color-primary);
}

.yh-time-picker__footer-btn--confirm {
  color: var(--yh-color-white) !important;
  font-weight: 600;
  background-color: var(--yh-color-primary);
  border-color: var(--yh-color-primary);
  box-shadow: var(--yh-shadow-sm);
}
.yh-time-picker__footer-btn--confirm:hover {
  background-color: var(--yh-color-primary-light-3) !important;
  border-color: var(--yh-color-primary-light-3) !important;
  color: var(--yh-color-white) !important;
  box-shadow: var(--yh-shadow-md);
  transform: translateY(-1px);
}
.yh-time-picker__footer-btn--confirm:active {
  background-color: var(--yh-color-primary-dark-2) !important;
  border-color: var(--yh-color-primary-dark-2) !important;
  transform: translateY(0);
}
</style>
