import { defineComponent, toRefs, ref, onMounted, computed, watch, nextTick, openBlock, createBlock, unref, mergeProps, withKeys, withCtx, renderSlot, createVNode } from 'vue';
import { useVModel } from '@vueuse/core';
import { n as getDefaultDate, h as hasTime, b as isBefore } from '../date/comparators.js';
import { u as useLocale } from '../shared/useLocale.js';
import { u as useDirection } from '../shared/useDirection.js';
import { u as useDateFormatter } from '../shared/useDateFormatter.js';
import { u as usePrimitiveElement } from '../Primitive/usePrimitiveElement.js';
import { g as getSegmentElements, i as isSegmentNavigationKey } from '../date/segment.js';
import { i as initializeSegmentValues, s as syncSegmentValues, c as createContent } from '../date/parser.js';
import { P as Primitive } from '../Primitive/Primitive.js';
import { _ as _sfc_main$1 } from '../VisuallyHidden/VisuallyHidden.js';
import { c as createContext } from '../shared/createContext.js';
import { u as useKbd } from '../shared/useKbd.js';
import { i as isNullish } from '../shared/nullish.js';

const [injectDateFieldRootContext, provideDateFieldRootContext] = createContext("DateFieldRoot");
const _sfc_main = /* @__PURE__ */ defineComponent({
  ...{
    inheritAttrs: false
  },
  __name: "DateFieldRoot",
  props: {
    defaultValue: { default: undefined },
    defaultPlaceholder: {},
    placeholder: { default: undefined },
    modelValue: {},
    hourCycle: {},
    granularity: {},
    hideTimeZone: { type: Boolean },
    maxValue: {},
    minValue: {},
    locale: {},
    disabled: { type: Boolean, default: false },
    readonly: { type: Boolean, default: false },
    isDateUnavailable: { type: Function, default: undefined },
    id: {},
    dir: {},
    asChild: { type: Boolean },
    as: {},
    name: {},
    required: { type: Boolean }
  },
  emits: ["update:modelValue", "update:placeholder"],
  setup(__props, { expose: __expose, emit: __emit }) {
    const props = __props;
    const emits = __emit;
    const { disabled, readonly, isDateUnavailable: propsIsDateUnavailable, granularity, defaultValue, dir: propDir, locale: propLocale } = toRefs(props);
    const locale = useLocale(propLocale);
    const dir = useDirection(propDir);
    const formatter = useDateFormatter(locale.value);
    const { primitiveElement, currentElement: parentElement } = usePrimitiveElement();
    const segmentElements = ref(/* @__PURE__ */ new Set());
    onMounted(() => {
      getSegmentElements(parentElement.value).forEach((item) => segmentElements.value.add(item));
    });
    const modelValue = useVModel(props, "modelValue", emits, {
      defaultValue: defaultValue.value,
      passive: props.modelValue === undefined
    });
    const defaultDate = getDefaultDate({
      defaultPlaceholder: props.placeholder,
      granularity: granularity.value,
      defaultValue: modelValue.value,
      locale: props.locale
    });
    const placeholder = useVModel(props, "placeholder", emits, {
      defaultValue: props.defaultPlaceholder ?? defaultDate.copy(),
      passive: props.placeholder === undefined
    });
    const inferredGranularity = computed(() => {
      if (props.granularity)
        return !hasTime(placeholder.value) ? "day" : props.granularity;
      return hasTime(placeholder.value) ? "minute" : "day";
    });
    const isInvalid = computed(() => {
      if (!modelValue.value)
        return false;
      if (propsIsDateUnavailable.value?.(modelValue.value))
        return true;
      if (props.minValue && isBefore(modelValue.value, props.minValue))
        return true;
      if (props.maxValue && isBefore(props.maxValue, modelValue.value))
        return true;
      return false;
    });
    const initialSegments = initializeSegmentValues(inferredGranularity.value);
    const segmentValues = ref(modelValue.value ? { ...syncSegmentValues({ value: modelValue.value, formatter }) } : { ...initialSegments });
    const allSegmentContent = computed(() => createContent({
      granularity: inferredGranularity.value,
      dateRef: placeholder.value,
      formatter,
      hideTimeZone: props.hideTimeZone,
      hourCycle: props.hourCycle,
      segmentValues: segmentValues.value,
      locale
    }));
    const segmentContents = computed(() => allSegmentContent.value.arr);
    const editableSegmentContents = computed(() => segmentContents.value.filter(({ part }) => part !== "literal"));
    watch(locale, (value) => {
      if (formatter.getLocale() !== value) {
        formatter.setLocale(value);
        nextTick(() => {
          segmentElements.value.clear();
          getSegmentElements(parentElement.value).forEach((item) => segmentElements.value.add(item));
        });
      }
    });
    watch(modelValue, (_modelValue) => {
      if (!isNullish(_modelValue) && placeholder.value.compare(_modelValue) !== 0) {
        placeholder.value = _modelValue.copy();
      }
    });
    watch([modelValue, locale], ([_modelValue]) => {
      if (!isNullish(_modelValue)) {
        segmentValues.value = { ...syncSegmentValues({ value: _modelValue, formatter }) };
      } else if (Object.values(segmentValues.value).every((value) => value !== null) && isNullish(_modelValue)) {
        segmentValues.value = { ...initialSegments };
      }
    });
    const currentFocusedElement = ref(null);
    const currentSegmentIndex = computed(() => Array.from(segmentElements.value).findIndex((el) => el.getAttribute("data-reka-date-field-segment") === currentFocusedElement.value?.getAttribute("data-reka-date-field-segment")));
    const nextFocusableSegment = computed(() => {
      const sign = dir.value === "rtl" ? -1 : 1;
      const nextCondition = sign < 0 ? currentSegmentIndex.value < 0 : currentSegmentIndex.value > segmentElements.value.size - 1;
      if (nextCondition)
        return null;
      const segmentToFocus = Array.from(segmentElements.value)[currentSegmentIndex.value + sign];
      return segmentToFocus;
    });
    const prevFocusableSegment = computed(() => {
      const sign = dir.value === "rtl" ? -1 : 1;
      const prevCondition = sign > 0 ? currentSegmentIndex.value < 0 : currentSegmentIndex.value > segmentElements.value.size - 1;
      if (prevCondition)
        return null;
      const segmentToFocus = Array.from(segmentElements.value)[currentSegmentIndex.value - sign];
      return segmentToFocus;
    });
    const kbd = useKbd();
    function handleKeydown(e) {
      if (!isSegmentNavigationKey(e.key))
        return;
      if (e.key === kbd.ARROW_LEFT)
        prevFocusableSegment.value?.focus();
      if (e.key === kbd.ARROW_RIGHT)
        nextFocusableSegment.value?.focus();
    }
    function setFocusedElement(el) {
      currentFocusedElement.value = el;
    }
    provideDateFieldRootContext({
      isDateUnavailable: propsIsDateUnavailable.value,
      locale,
      modelValue,
      placeholder,
      disabled,
      formatter,
      hourCycle: props.hourCycle,
      readonly,
      segmentValues,
      isInvalid,
      segmentContents: editableSegmentContents,
      elements: segmentElements,
      setFocusedElement,
      focusNext() {
        nextFocusableSegment.value?.focus();
      }
    });
    __expose({
      /** Helper to set the focused element inside the DateField */
      setFocusedElement
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(unref(Primitive), mergeProps(_ctx.$attrs, {
        ref_key: "primitiveElement",
        ref: primitiveElement,
        role: "group",
        "aria-disabled": unref(disabled) ? true : undefined,
        "data-disabled": unref(disabled) ? "" : undefined,
        "data-readonly": unref(readonly) ? "" : undefined,
        "data-invalid": isInvalid.value ? "" : undefined,
        dir: unref(dir),
        onKeydown: withKeys(handleKeydown, ["left", "right"])
      }), {
        default: withCtx(() => [
          renderSlot(_ctx.$slots, "default", {
            modelValue: unref(modelValue),
            segments: segmentContents.value,
            isInvalid: isInvalid.value
          }),
          createVNode(unref(_sfc_main$1), {
            id: _ctx.id,
            as: "input",
            feature: "focusable",
            tabindex: "-1",
            value: unref(modelValue) ? unref(modelValue).toString() : "",
            name: _ctx.name,
            disabled: unref(disabled),
            required: _ctx.required,
            onFocus: _cache[0] || (_cache[0] = ($event) => Array.from(segmentElements.value)?.[0]?.focus())
          }, null, 8, ["id", "value", "name", "disabled", "required"])
        ]),
        _: 3
      }, 16, ["aria-disabled", "data-disabled", "data-readonly", "data-invalid", "dir"]);
    };
  }
});

export { _sfc_main as _, injectDateFieldRootContext as i };
//# sourceMappingURL=DateFieldRoot.js.map
