{"version":3,"file":"useOctopusDropdown-bjkTWvTa.mjs","names":[],"sources":["../src/components/composable/form/useOctopusDropdown.ts"],"sourcesContent":["import { computed, getCurrentInstance, nextTick, ref } from 'vue';\nimport { type MaybeElementRef, onClickOutside } from '@vueuse/core';\nimport { useI18n } from 'vue-i18n';\n\nexport interface OctopusDropdownProps<T> {\n    options: T[];\n    optionLabel?: keyof T & string;\n    optionKey?: keyof T;\n    isDisabled?: boolean;\n    placeholder?: string;\n}\n\nexport function useOctopusDropdown<T>(\n    props: OctopusDropdownProps<T>,\n    emitSearch: (query: string) => void,\n    idPrefix: string = 'octopus-dropdown',\n    // Extra elements to exclude from the click-outside check.\n    // Needed when the dropdown is teleported outside containerRef (e.g. to body):\n    // without this, clicking inside the teleported dropdown triggers closeDropdown\n    // because it is no longer a DOM descendant of containerRef.\n    ignore?: MaybeElementRef[]\n) {\n    const { t } = useI18n();\n    const instance = getCurrentInstance();\n\n    const searchQuery = ref('');\n    const isOpen = ref(false);\n    const isHovered = ref(false);\n    const containerRef = ref<HTMLElement | null>(null);\n    const inputRef = ref<HTMLInputElement | null>(null);\n    // Where the dropdown/options list (teleported out of normal flow) should land. Defaults\n    // to the app root, but when this component is used inside a ClassicPopover, teleporting\n    // there instead keeps the dropdown a real DOM descendant of it — otherwise both end up as\n    // siblings under the same teleport target, and ClassicPopover's outside-click/blur checks\n    // (which rely on DOM containment) see clicks inside the dropdown as \"outside\" and close it.\n    const teleportTarget = ref<string | HTMLElement>('.octopus-app');\n\n    const computedId = computed(() => `${idPrefix}-${instance?.uid}`);\n\n    // vnode.props contains the raw parent-provided props before defineEmits strips them\n    // from attrs, so onSearch is present whenever the parent writes @search=\"...\".\n    const hasSearchListener = computed(() => !!instance?.vnode.props?.onSearch);\n\n    const displayedOptions = computed((): T[] => {\n        if (hasSearchListener.value) {\n            return props.options;\n        }\n        const query = searchQuery.value.toLowerCase();\n        if (!query) {\n            return props.options;\n        }\n        return props.options.filter((option) =>\n            getLabel(option).toLowerCase().includes(query)\n        );\n    });\n\n    const inputPlaceholder = computed(() => props.placeholder ?? t('Search'));\n\n    function getLabel(option: T): string {\n        if (props.optionLabel) {\n            return option[props.optionLabel] as string;\n        }\n        return option as unknown as string;\n    }\n\n    function openDropdown(): void {\n        if (props.isDisabled) {\n            return;\n        }\n        teleportTarget.value = containerRef.value?.closest<HTMLElement>('.octopus-popover') ?? '.octopus-app';\n        isOpen.value = true;\n        nextTick(() => {\n            inputRef.value?.focus();\n        });\n    }\n\n    function closeDropdown(): void {\n        isOpen.value = false;\n        searchQuery.value = '';\n    }\n\n    function toggleDropdown(): void {\n        if (isOpen.value) {\n            closeDropdown();\n        } else {\n            openDropdown();\n        }\n    }\n\n    function handleInput(): void {\n        if (hasSearchListener.value) {\n            emitSearch(searchQuery.value);\n        }\n    }\n\n    onClickOutside(containerRef, closeDropdown, ignore?.length ? { ignore } : undefined);\n\n    return {\n        searchQuery,\n        isOpen,\n        isHovered,\n        containerRef,\n        inputRef,\n        teleportTarget,\n        computedId,\n        hasSearchListener,\n        displayedOptions,\n        inputPlaceholder,\n        getLabel,\n        openDropdown,\n        closeDropdown,\n        toggleDropdown,\n        handleInput,\n    };\n}\n"],"mappings":";;;;AAYA,SAAgB,mBACZ,OACA,YACA,WAAmB,oBAKnB,QACF;CACE,MAAM,EAAE,MAAM,QAAQ;CACtB,MAAM,WAAW,mBAAmB;CAEpC,MAAM,cAAc,IAAI,EAAE;CAC1B,MAAM,SAAS,IAAI,KAAK;CACxB,MAAM,YAAY,IAAI,KAAK;CAC3B,MAAM,eAAe,IAAwB,IAAI;CACjD,MAAM,WAAW,IAA6B,IAAI;CAMlD,MAAM,iBAAiB,IAA0B,cAAc;CAE/D,MAAM,aAAa,eAAe,GAAG,SAAS,GAAG,UAAU,KAAK;CAIhE,MAAM,oBAAoB,eAAe,CAAC,CAAC,UAAU,MAAM,OAAO,QAAQ;CAE1E,MAAM,mBAAmB,eAAoB;EACzC,IAAI,kBAAkB,OAClB,OAAO,MAAM;EAEjB,MAAM,QAAQ,YAAY,MAAM,YAAY;EAC5C,IAAI,CAAC,OACD,OAAO,MAAM;EAEjB,OAAO,MAAM,QAAQ,QAAQ,WACzB,SAAS,MAAM,EAAE,YAAY,EAAE,SAAS,KAAK,CACjD;CACJ,CAAC;CAED,MAAM,mBAAmB,eAAe,MAAM,eAAe,EAAE,QAAQ,CAAC;CAExE,SAAS,SAAS,QAAmB;EACjC,IAAI,MAAM,aACN,OAAO,OAAO,MAAM;EAExB,OAAO;CACX;CAEA,SAAS,eAAqB;EAC1B,IAAI,MAAM,YACN;EAEJ,eAAe,QAAQ,aAAa,OAAO,QAAqB,kBAAkB,KAAK;EACvF,OAAO,QAAQ;EACf,eAAe;GACX,SAAS,OAAO,MAAM;EAC1B,CAAC;CACL;CAEA,SAAS,gBAAsB;EAC3B,OAAO,QAAQ;EACf,YAAY,QAAQ;CACxB;CAEA,SAAS,iBAAuB;EAC5B,IAAI,OAAO,OACP,cAAc;OAEd,aAAa;CAErB;CAEA,SAAS,cAAoB;EACzB,IAAI,kBAAkB,OAClB,WAAW,YAAY,KAAK;CAEpC;CAEA,eAAe,cAAc,eAAe,QAAQ,SAAS,EAAE,OAAO,IAAI,KAAA,CAAS;CAEnF,OAAO;EACH;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACJ;AACJ"}