{"version":3,"file":"ComboboxRoot.cjs","sources":["../../src/Combobox/ComboboxRoot.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { Ref } from 'vue'\nimport type { ListboxRootProps } from '@/Listbox'\nimport { createContext, useDirection, useFilter } from '@/shared'\nimport { usePrimitiveElement } from '@/Primitive'\nimport type { AcceptableValue, GenericComponentInstance } from '@/shared/types'\n\ntype ComboboxRootContext<T> = {\n  modelValue: Ref<T | Array<T>>\n  multiple: Ref<boolean>\n  disabled: Ref<boolean>\n  open: Ref<boolean>\n  onOpenChange: (value: boolean) => void\n  isUserInputted: Ref<boolean>\n  isVirtual: Ref<boolean>\n  contentId: string\n  inputElement: Ref<HTMLInputElement | undefined>\n  onInputElementChange: (el: HTMLInputElement) => void\n  triggerElement: Ref<HTMLElement | undefined>\n  onTriggerElementChange: (el: HTMLElement) => void\n  highlightedElement: Ref<HTMLElement | undefined>\n  parentElement: Ref<HTMLElement | undefined>\n  resetSearchTermOnSelect: Ref<boolean>\n  onResetSearchTerm: EventHookOn\n  allItems: Ref<Map<string, string>>\n  allGroups: Ref<Map<string, Set<string>>>\n  filterState: {\n    search: string\n    filtered: { count: number, items: Map<string, number>, groups: Set<string> }\n  }\n  ignoreFilter: Ref<boolean>\n}\n\nexport const [injectComboboxRootContext, provideComboboxRootContext]\n  = createContext<ComboboxRootContext<AcceptableValue>>('ComboboxRoot')\n\nexport type ComboboxRootEmits<T = AcceptableValue> = {\n  /** Event handler called when the value changes. */\n  'update:modelValue': [value: T]\n  /** Event handler when highlighted element changes. */\n  'highlight': [payload: { ref: HTMLElement, value: T } | undefined]\n  /** Event handler called when the open state of the combobox changes. */\n  'update:open': [value: boolean]\n}\n\nexport interface ComboboxRootProps<T = AcceptableValue> extends Omit<ListboxRootProps<T>, 'orientation' | 'selectionBehavior' > {\n  /** The controlled open state of the Combobox. Can be binded with with `v-model:open`. */\n  open?: boolean\n  /** The open state of the combobox when it is initially rendered. <br> Use when you do not need to control its open state. */\n  defaultOpen?: boolean\n  /**\n   * Whether to reset the searchTerm when the Combobox input blurred\n   * @defaultValue `true`\n   */\n  resetSearchTermOnBlur?: boolean\n  /**\n   * Whether to reset the searchTerm when the Combobox value is selected\n   * @defaultValue `true`\n   */\n  resetSearchTermOnSelect?: boolean\n  /**\n   * When `true`, disable the default filters\n   */\n  ignoreFilter?: boolean\n}\n</script>\n\n<script setup lang=\"ts\" generic=\"T extends AcceptableValue = AcceptableValue\">\nimport { computed, getCurrentInstance, nextTick, onMounted, reactive, ref, toRefs, watch } from 'vue'\nimport { PopperRoot } from '@/Popper'\nimport { type EventHookOn, createEventHook, useVModel } from '@vueuse/core'\nimport { ListboxRoot } from '@/Listbox'\n\nconst props = withDefaults(defineProps<ComboboxRootProps<T>>(), {\n  open: undefined,\n  resetSearchTermOnBlur: true,\n  resetSearchTermOnSelect: true,\n})\nconst emits = defineEmits<ComboboxRootEmits<T>>()\n\ndefineSlots<{\n  default: (props: {\n    /** Current open state */\n    open: typeof open.value\n    /** Current active value */\n    modelValue: typeof modelValue.value\n  }) => any\n}>()\n\nconst { primitiveElement, currentElement: parentElement } = usePrimitiveElement<GenericComponentInstance<typeof ListboxRoot>>()\nconst { multiple, disabled, ignoreFilter, resetSearchTermOnSelect, dir: propDir } = toRefs(props)\n\nconst dir = useDirection(propDir)\n\nconst modelValue = useVModel(props, 'modelValue', emits, {\n  // @ts-expect-error ignore the type error here\n  defaultValue: props.defaultValue ?? (multiple.value ? [] : undefined),\n  passive: (props.modelValue === undefined) as false,\n  deep: true,\n}) as Ref<T | T[]>\n\nconst open = useVModel(props, 'open', emits, {\n  defaultValue: props.defaultOpen,\n  passive: (props.open === undefined) as false,\n}) as Ref<boolean>\n\nasync function onOpenChange(val: boolean) {\n  open.value = val\n  filterState.search = ''\n\n  if (val) {\n    // make sure dom is ready then only highlight the selected\n    await nextTick()\n    primitiveElement.value?.highlightSelected()\n    isUserInputted.value = true\n  }\n  else {\n    isUserInputted.value = false\n  }\n\n  inputElement.value?.focus()\n  setTimeout(() => {\n    if (!val && props.resetSearchTermOnBlur)\n      resetSearchTerm.trigger()\n  }, 1)\n}\n\nconst resetSearchTerm = createEventHook()\nconst isUserInputted = ref(false)\nconst isVirtual = ref(false)\nconst inputElement = ref<HTMLInputElement>()\nconst triggerElement = ref<HTMLElement>()\n\nconst highlightedElement = computed(() => primitiveElement.value?.highlightedElement ?? undefined)\n\nconst allItems = ref<Map<string, string>>(new Map())\nconst allGroups = ref<Map<string, Set<string>>>(new Map())\n\nconst { contains } = useFilter({ sensitivity: 'base' })\nconst filterState = reactive({\n  search: '',\n  filtered: {\n    /** The count of all visible items. */\n    count: 0,\n    /** Map from visible item id to its search score. */\n    items: new Map() as Map<string, number>,\n    /** Set of groups with at least one visible item. */\n    groups: new Set() as Set<string>,\n  },\n})\n\nfunction filterItems() {\n  if (!filterState.search || props.ignoreFilter || isVirtual.value) {\n    filterState.filtered.count = allItems.value.size\n    // Do nothing, each item will know to show itself because search is empty\n    return\n  }\n\n  // Reset the groups\n  filterState.filtered.groups = new Set()\n  let itemCount = 0\n\n  // Check which items should be included\n  for (const [id, value] of allItems.value) {\n    const score = contains(value, filterState.search)\n    filterState.filtered.items.set(id, score ? 1 : 0)\n    if (score)\n      itemCount++\n  }\n\n  // Check which groups have at least 1 item shown\n  for (const [groupId, group] of allGroups.value) {\n    for (const itemId of group) {\n      if (filterState.filtered.items.get(itemId)! > 0) {\n        filterState.filtered.groups.add(groupId)\n        break\n      }\n    }\n  }\n\n  filterState.filtered.count = itemCount\n}\n\nwatch([() => filterState.search, () => allItems.value.size], () => {\n  filterItems()\n}, { immediate: true })\n\nwatch(() => open.value, () => {\n  // nextTick to allow multiple items to be mounted first\n  nextTick(() => {\n    if (open.value)\n      filterItems()\n  })\n}, { flush: 'post' })\n\nconst inst = getCurrentInstance()\nonMounted(() => {\n  if (inst?.exposed) {\n    inst.exposed.highlightItem = primitiveElement.value?.highlightItem\n    inst.exposed.highlightFirstItem = primitiveElement.value?.highlightFirstItem\n    inst.exposed.highlightSelected = primitiveElement.value?.highlightSelected\n  }\n})\n\ndefineExpose({\n  filtered: computed(() => filterState.filtered),\n  highlightedElement,\n  highlightItem: primitiveElement.value?.highlightItem,\n  highlightFirstItem: primitiveElement.value?.highlightFirstItem,\n  highlightSelected: primitiveElement.value?.highlightSelected,\n})\n\nprovideComboboxRootContext({\n  modelValue,\n  multiple,\n  disabled,\n  open,\n  onOpenChange,\n  contentId: '',\n  isUserInputted,\n  isVirtual,\n  inputElement,\n  highlightedElement,\n  onInputElementChange: val => inputElement.value = val,\n  triggerElement,\n  onTriggerElementChange: val => triggerElement.value = val,\n  parentElement,\n  resetSearchTermOnSelect,\n  onResetSearchTerm: resetSearchTerm.on,\n  allItems,\n  allGroups,\n  filterState,\n  ignoreFilter,\n})\n</script>\n\n<template>\n  <PopperRoot>\n    <ListboxRoot\n      ref=\"primitiveElement\"\n      v-bind=\"$attrs\"\n      v-model=\"modelValue\"\n      :style=\"{\n        pointerEvents: open ? 'auto' : undefined,\n      }\"\n      :as=\"as\"\n      :as-child=\"asChild\"\n      :dir=\"dir\"\n      :multiple=\"multiple\"\n      :name=\"name\"\n      :required=\"required\"\n      :disabled=\"disabled\"\n      :highlight-on-hover=\"true\"\n      :by=\"props.by as any\"\n      @highlight=\"emits('highlight', $event as any)\"\n    >\n      <slot\n        :open=\"open\"\n        :model-value=\"modelValue\"\n      />\n    </ListboxRoot>\n  </PopperRoot>\n</template>\n"],"names":["createContext","usePrimitiveElement","toRefs","useDirection","useVModel","nextTick","createEventHook","ref","computed","useFilter","reactive","watch","getCurrentInstance","onMounted"],"mappings":"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"}