vue-uswds
Version:
Vue 3 implementation of the USWDS (U.S. Web Design System) component library
1 lines • 403 kB
Source Map (JSON)
{"version":3,"file":"vue-uswds.components.mjs","sources":["../src/utils/constants.js","../src/components/BaseLink/BaseLink.vue","../src/composables/useAccordion.js","../src/components/UsaAccordion/UsaAccordion.vue","../src/utils/common.js","../src/utils/unique-id.js","../src/components/UsaAccordionItem/UsaAccordionItem.vue","../src/components/UsaAlert/UsaAlert.vue","../src/composables/useToggle.js","../src/components/UsaBannerContent/UsaBannerContent.vue","../src/components/UsaBanner/UsaBanner.vue","../src/components/UsaBreadcrumbItem/UsaBreadcrumbItem.vue","../src/components/UsaBreadcrumb/UsaBreadcrumb.vue","../src/components/UsaButton/UsaButton.vue","../src/components/UsaButtonGroup/UsaButtonGroup.vue","../src/components/UsaButtonGroupItem/UsaButtonGroupItem.vue","../src/components/UsaCard/UsaCard.vue","../src/components/UsaCharacterCount/UsaCharacterCount.vue","../src/components/UsaCheckbox/UsaCheckbox.vue","../src/components/UsaChecklistItem/UsaChecklistItem.vue","../src/components/UsaCollection/UsaCollection.vue","../src/components/UsaCollectionCalendar/UsaCollectionCalendar.vue","../src/components/UsaCollectionMetaItem/UsaCollectionMetaItem.vue","../src/composables/useComboBox.js","../src/components/UsaFormGroup/UsaFormGroup.vue","../src/components/UsaLabel/UsaLabel.vue","../src/components/UsaComboBox/UsaComboBox.vue","../src/components/UsaTextInput/UsaTextInput.vue","../src/components/UsaSelect/UsaSelect.vue","../src/components/UsaDateInput/UsaDateInput.vue","../src/utils/dates.js","../node_modules/@vueuse/integrations/useFocusTrap/component.mjs","../src/components/UsaDatePickerCalendarDay/useDayPicker.js","../src/components/UsaDatePickerCalendarDay/UsaDatePickerCalendarDay.vue","../src/components/UsaDatePickerCalendarMonth/useMonthPicker.js","../src/components/UsaDatePickerCalendarMonth/UsaDatePickerCalendarMonth.vue","../src/components/UsaDatePickerCalendarYear/useYearPicker.js","../src/components/UsaDatePickerCalendarYear/UsaDatePickerCalendarYear.vue","../src/components/UsaDatePickerCalendar/UsaDatePickerCalendar.vue","../src/components/UsaDatePicker/UsaDatePicker.vue","../src/components/UsaDateRangePicker/UsaDateRangePicker.vue","../src/composables/useFileInput.js","../src/components/UsaFileInput/UsaFileInput.vue","../src/components/UsaFooter/UsaFooter.vue","../src/components/UsaFooterAddress/UsaFooterAddress.vue","../src/components/UsaFooterCollapsibleMenuSection/UsaFooterCollapsibleMenuSection.vue","../src/components/UsaFooterCollapsibleMenu/UsaFooterCollapsibleMenu.vue","../src/components/UsaFooterLogo/UsaFooterLogo.vue","../src/components/UsaFooterMenu/UsaFooterMenu.vue","../src/components/UsaFooterNav/UsaFooterNav.vue","../src/components/UsaFooterPrimarySection/UsaFooterPrimarySection.vue","../src/components/UsaFooterSecondarySection/UsaFooterSecondarySection.vue","../src/components/UsaFooterSocialLinks/UsaFooterSocialLinks.vue","../src/components/UsaGraphicList/UsaGraphicList.vue","../src/components/UsaGraphicListRow/UsaGraphicListRow.vue","../src/composables/useMobileMenu.js","../src/components/UsaHeader/UsaHeader.vue","../src/components/UsaHero/UsaHero.vue","../src/components/UsaHeroCallout/UsaHeroCallout.vue","../src/components/UsaIcon/UsaIcon.vue","../src/components/UsaIconList/UsaIconList.vue","../src/components/UsaIdentifier/UsaIdentifier.vue","../src/components/UsaInPageNav/useInPageNavigation.js","../src/components/UsaInPageNav/UsaInPageNav.vue","../src/components/UsaLanguageSelector/UsaLanguageSelector.vue","../src/components/UsaLink/UsaLink.vue","../src/components/UsaModalCloseButton/UsaModalCloseButton.vue","../src/components/UsaModal/UsaModal.vue","../node_modules/@vueuse/integrations/useFocusTrap.mjs","../src/components/UsaOverlay/UsaOverlay.vue","../src/components/UsaNav/UsaNav.vue","../src/components/UsaNavDropdown/UsaNavDropdown.vue","../src/components/UsaNavDropdownButton/UsaNavDropdownButton.vue","../src/components/UsaNavPrimaryItem/UsaNavPrimaryItem.vue","../src/components/UsaNavSubmenu/UsaNavSubmenu.vue","../src/components/UsaNavSubmenuItem/UsaNavSubmenuItem.vue","../src/components/UsaNavPrimary/UsaNavPrimary.vue","../src/components/UsaNavSecondary/UsaNavSecondary.vue","../src/components/UsaNavbar/UsaNavbar.vue","../src/composables/usePagination.js","../src/components/UsaPaginationArrow/UsaPaginationArrow.vue","../src/components/UsaPaginationItem/UsaPaginationItem.vue","../src/components/UsaPagination/UsaPagination.vue","../src/components/UsaPasswordMask/UsaPasswordMask.vue","../src/components/UsaProcessList/UsaProcessList.vue","../src/components/UsaProcessListItem/UsaProcessListItem.vue","../src/components/UsaRadio/UsaRadio.vue","../src/components/UsaRange/UsaRange.vue","../src/components/UsaSearch/UsaSearch.vue","../src/components/UsaSiteAlert/UsaSiteAlert.vue","../src/components/UsaStepIndicatorSegment/UsaStepIndicatorSegment.vue","../src/components/UsaStepIndicatorHeader/UsaStepIndicatorHeader.vue","../src/components/UsaStepIndicator/UsaStepIndicator.vue","../src/components/UsaSummaryBox/UsaSummaryBox.vue","../src/utils/sorting.js","../src/composables/useTableSort.js","../src/components/UsaTableSortButton/UsaTableSortButton.vue","../src/components/UsaTableHeaderCell/UsaTableHeaderCell.vue","../src/components/UsaTable/UsaTable.vue","../src/components/UsaTag/UsaTag.vue","../src/components/UsaTextarea/UsaTextarea.vue","../src/components/UsaTimePicker/UsaTimePicker.vue","../src/components/UsaTooltip/UsaTooltip.vue","../src/components/UsaValidation/UsaValidation.vue"],"sourcesContent":["export const PREFIX_SEPARATOR = ':'\nexport const GRID_NAMESPACE = 'grid-'\nexport const UTILITY_NAMESPACE = 'u-'\nexport const IMAGE_PATH = '/assets/img'\nexport const SVG_SPRITE_PATH = '/assets/img/sprite.svg'\nexport const ROUTER_COMPONENT_NAME = null\nexport const MOBILE_MENU_BREAKPOINT = '64em'\nexport const FOOTER_NAV_COLLAPSIBLE_BREAKPOINT = '30em'\nexport const MIN_DATE = '0000-01-01'\nexport const MAX_DATE = '9999-12-31'\nexport const USA_DATE_REGEX_PATTERN =\n /^(0[1-9]|1[0-2])\\/(0[1-9]|[12][0-9]|3[01])\\/\\d{4}$/\nexport const ISO_DATE_REGEX_PATTERN =\n /^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/\nexport const MONTH_LABELS = [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December',\n]\nexport const DAY_OF_WEEK_LABELS = [\n 'Sunday',\n 'Monday',\n 'Tuesday',\n 'Wednesday',\n 'Thursday',\n 'Friday',\n 'Saturday',\n]\nexport const DAY_OF_WEEK_ABBREVIATION_LABELS = [\n 'S',\n 'M',\n 'T',\n 'W',\n 'Th',\n 'Fr',\n 'S',\n]\nexport const YEAR_GROUP = 12\nexport const ID_PREFIX = 'vuswds-id-'\n","<script>\nimport { ROUTER_COMPONENT_NAME } from '@/utils/constants.js'\n\nexport default {\n name: 'BaseLink',\n inject: {\n globalRouterComponentName: {\n from: 'vueUswds.routerComponentName',\n default: ROUTER_COMPONENT_NAME,\n },\n },\n inheritAttrs: false,\n props: {\n href: {\n type: String,\n default: '',\n },\n to: {\n type: [String, Object],\n default: '',\n },\n routerComponentName: {\n type: [String, Object],\n default: '',\n },\n },\n data() {\n return {\n // Router link checks here instead of computed to avoid Vue warning\n // about $nuxt and $router not being defined on the instance when they\n // are not installed.\n isNuxt: this?.$nuxt,\n isVueRouter: this?.$router,\n }\n },\n computed: {\n isHrefLink() {\n return (\n !!this.href ||\n (typeof this.to === 'string' && this.to.startsWith('http'))\n )\n },\n linkComponent() {\n if (this.routerComponentName) {\n return this.routerComponentName\n }\n\n if (this.globalRouterComponentName) {\n return this.globalRouterComponentName\n }\n\n if (this.isNuxt) {\n return 'nuxt-link'\n }\n\n if (this.isVueRouter) {\n return 'router-link'\n }\n\n return 'a'\n },\n },\n methods: {\n handleSpaceKeydown(event) {\n if (this.$attrs?.class?.includes('usa-button')) {\n event.target.click()\n }\n },\n },\n}\n</script>\n\n<template>\n <a\n v-if=\"isHrefLink\"\n v-bind=\"$attrs\"\n :href=\"href || to\"\n @keydown.prevent.space=\"handleSpaceKeydown\"\n ><slot></slot\n ></a>\n <component\n :is=\"linkComponent\"\n v-else\n v-bind=\"$attrs\"\n :to=\"to\"\n @keydown.prevent.space=\"handleSpaceKeydown\"\n ><slot></slot\n ></component>\n</template>\n","import { ref, reactive } from 'vue'\n\nexport function useAccordion(_accordionItems, _multiselectable = false) {\n const multiselectable = ref(_multiselectable)\n const accordionItems = reactive(_accordionItems)\n\n const registerAccordionItem = (id, isOpen) => {\n if (accordionItems[id] === undefined) {\n accordionItems[id] = isOpen\n }\n\n if (multiselectable.value) {\n return\n }\n\n for (const accordionId in accordionItems) {\n if (accordionId !== id && isOpen) {\n accordionItems[accordionId] = false\n }\n }\n }\n\n const unregisterAccordionItem = id => {\n delete accordionItems[id]\n }\n\n const closeItem = id => {\n accordionItems[id] = false\n }\n\n const openItem = id => {\n accordionItems[id] = true\n\n if (multiselectable.value) {\n return\n }\n\n for (const accordionId in accordionItems) {\n if (accordionId !== id) {\n closeItem(accordionId)\n }\n }\n }\n\n const toggleItem = id => {\n if (accordionItems[id]) {\n closeItem(id)\n } else {\n openItem(id)\n }\n }\n\n const closeAllItems = () => {\n for (const accordionId in accordionItems) {\n closeItem(accordionId)\n }\n }\n\n return {\n registerAccordionItem,\n unregisterAccordionItem,\n openItem,\n closeItem,\n toggleItem,\n closeAllItems,\n }\n}\n","<script setup>\nimport { computed, provide, reactive, watch, toRef } from 'vue'\nimport { useAccordion } from '@/composables/useAccordion.js'\n\nconst emit = defineEmits(['update:accordionItems'])\n\nconst props = defineProps({\n bordered: {\n type: Boolean,\n default: false,\n },\n multiselectable: {\n type: Boolean,\n default: false,\n },\n headingTag: {\n type: String,\n default: 'h2',\n },\n})\n\nconst accordionItems = reactive({})\nconst isMultiSelectable = toRef(props, 'multiselectable')\n\nconst {\n registerAccordionItem,\n unregisterAccordionItem,\n openItem,\n closeItem,\n toggleItem,\n} = useAccordion(accordionItems, isMultiSelectable)\n\nwatch(accordionItems, () => {\n emit('update:accordionItems', accordionItems)\n})\n\nprovide(\n 'accordionHeadingTag',\n computed(() => props.headingTag),\n)\nprovide('registerAccordionItem', registerAccordionItem)\nprovide('unregisterAccordionItem', unregisterAccordionItem)\nprovide('toggleItem', toggleItem)\nprovide('accordionItems', accordionItems)\n\nconst classes = computed(() => [{ 'usa-accordion--bordered': props.bordered }])\n\ndefineExpose({\n openItem,\n closeItem,\n toggleItem,\n})\n</script>\n\n<template>\n <div\n class=\"usa-accordion\"\n :class=\"classes\"\n :aria-multiselectable=\"isMultiSelectable || null\"\n ><slot></slot\n ></div>\n</template>\n","import justKebabCase from 'just-kebab-case'\nimport split from 'just-split'\n\nexport const objectHasKey = (object, key) =>\n Object.prototype.hasOwnProperty.call(object, key)\n\nexport const kebabCase = value => justKebabCase(value)\n\nexport const escapeRegExp = string =>\n string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n\nexport const splitArray = (array, splitAt) => split(array, splitAt)\n","import { getCurrentInstance } from 'vue'\nimport { kebabCase } from '@/utils/common.js'\nimport { ID_PREFIX } from '@/utils/constants.js'\n\nconst idRegistry = {}\n\n// Adapted from:\n// https://github.com/wearebraid/vue-formulate/blob/master/src/Formulate.js\nexport function nextId(componentName = '') {\n const vm = getCurrentInstance()\n const route = vm?.appContext?.config?.globalProperties?.$route\n\n const pathPrefix =\n route?.path && kebabCase(route.path) ? kebabCase(route.path) : 'global'\n\n if (!idRegistry[pathPrefix]) {\n idRegistry[pathPrefix] = 0\n }\n\n return `${ID_PREFIX}${pathPrefix}-${kebabCase(componentName)}-${++idRegistry[\n pathPrefix\n ]}`\n}\n","<script setup>\nimport { computed, inject, toRef, onBeforeUnmount } from 'vue'\nimport { nextId } from '@/utils/unique-id.js'\nimport BaseHeading from '@/components/BaseHeading'\n\nconst accordionHeadingTag = inject('accordionHeadingTag')\nconst registerAccordionItem = inject('registerAccordionItem')\nconst unregisterAccordionItem = inject('unregisterAccordionItem')\nconst toggleItem = inject('toggleItem')\nconst accordionItems = inject('accordionItems')\n\nconst props = defineProps({\n id: {\n type: String,\n default: '',\n },\n label: {\n type: String,\n default: '',\n },\n open: {\n type: Boolean,\n default: false,\n },\n customClasses: {\n type: Object,\n default: () => {\n return {\n heading: [],\n button: [],\n content: [],\n }\n },\n },\n})\n\nconst computedId = computed(() => props.id || nextId('usa-accordion-item'))\nconst isOpen = toRef(accordionItems, computedId.value)\n\nregisterAccordionItem(computedId.value, props.open)\n\nonBeforeUnmount(() => {\n unregisterAccordionItem(computedId.value)\n})\n</script>\n\n<template>\n <BaseHeading\n v-bind=\"$attrs\"\n class=\"usa-accordion__heading\"\n :class=\"customClasses?.heading\"\n :tag=\"accordionHeadingTag\"\n ><button\n type=\"button\"\n class=\"usa-accordion__button\"\n :class=\"customClasses?.button\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"computedId\"\n @click=\"toggleItem(computedId)\"\n ><slot name=\"label\">{{ label }}</slot></button\n ></BaseHeading\n >\n <div\n :id=\"computedId\"\n class=\"usa-accordion__content\"\n :class=\"customClasses?.content\"\n :hidden=\"!isOpen\"\n ><slot></slot\n ></div>\n</template>\n","<script setup>\nimport { computed } from 'vue'\nimport BaseHeading from '@/components/BaseHeading'\n\nconst props = defineProps({\n variant: {\n type: String,\n default: '',\n validator(variant) {\n const isValidVariant = [\n '',\n 'info',\n 'warning',\n 'error',\n 'success',\n 'emergency',\n 'validation',\n ].includes(variant)\n\n if (!isValidVariant) {\n console.warn(`'${variant}' is not a valid alert variant`)\n }\n\n return isValidVariant\n },\n },\n slim: {\n type: Boolean,\n default: false,\n },\n noIcon: {\n type: Boolean,\n default: false,\n },\n role: {\n type: String,\n default: '',\n },\n heading: {\n type: String,\n default: '',\n },\n headingTag: {\n type: String,\n default: 'h2',\n },\n customClasses: {\n type: Object,\n default: () => {\n return {\n body: [],\n heading: [],\n }\n },\n },\n})\n\nconst classes = computed(() => {\n return {\n 'usa-alert--no-icon': props.noIcon,\n 'usa-alert--slim': props.slim,\n 'usa-alert--info':\n props.variant === 'info' || props.variant === 'validation',\n 'usa-alert--warning': props.variant === 'warning',\n 'usa-alert--error': props.variant === 'error',\n 'usa-alert--success': props.variant === 'success',\n 'usa-alert--emergency': props.variant === 'emergency',\n 'usa-alert--validation': props.variant === 'validation',\n }\n})\n\nconst ariaRole = computed(() => {\n if (props.role) {\n return props.role\n }\n\n if (!props.role && props.variant === 'error') {\n return 'alert'\n }\n\n return null\n})\n</script>\n\n<template>\n <div class=\"usa-alert\" :class=\"classes\" :role=\"ariaRole\">\n <div class=\"usa-alert__body\" :class=\"customClasses?.body\">\n <BaseHeading\n v-if=\"heading || $slots.heading\"\n :tag=\"headingTag\"\n class=\"usa-alert__heading\"\n :class=\"[{ 'usa-sr-only': slim }, customClasses?.heading]\"\n ><slot name=\"heading\">{{ heading }}</slot></BaseHeading\n >\n <slot name=\"message\">\n <p class=\"usa-alert__text\"><slot></slot></p>\n </slot>\n </div>\n </div>\n</template>\n","import { ref, computed, readonly, watch } from 'vue'\nimport { nextId } from '@/utils/unique-id.js'\n\nexport function useToggle(_id, idPrefix = '', defaultOpen = false, emit) {\n const isOpen = ref(defaultOpen)\n\n const toggleId = computed(() => _id || nextId(idPrefix))\n\n const closeContent = () => {\n isOpen.value = false\n\n if (emit) {\n emit('update:open', isOpen.value)\n }\n }\n\n const openContent = () => {\n isOpen.value = true\n\n if (emit) {\n emit('update:open', isOpen.value)\n }\n }\n\n const toggleContent = () => {\n if (isOpen.value) {\n closeContent()\n } else {\n openContent()\n }\n }\n\n watch(isOpen, newValue => {\n if (isOpen.value !== newValue) {\n toggleContent()\n }\n })\n\n return {\n isOpen: readonly(isOpen),\n toggleId: readonly(toggleId),\n closeContent,\n openContent,\n toggleContent,\n }\n}\n","<script setup>\nimport { inject, useSlots } from 'vue'\nimport {\n PREFIX_SEPARATOR,\n GRID_NAMESPACE,\n IMAGE_PATH,\n} from '@/utils/constants.js'\n\nconst slots = useSlots()\n\nif (slots?.tldIcon) {\n console.warn(`The 'tldIcon' slot is deprecated, use 'tld-icon' instead.`)\n}\n\nif (slots?.tldDescription) {\n console.warn(\n `The 'tldDescription' slot is deprecated, use 'tld-description' instead.`,\n )\n}\n\nif (slots?.httpsIcon) {\n console.warn(`The 'httpsIcon' slot is deprecated, use 'https-icon' instead.`)\n}\n\nif (slots?.httpsDescription) {\n console.warn(\n `The 'httpsDescription' slot is deprecated, use 'https-description' instead.`,\n )\n}\n\nconst prefixSeparator = inject('vueUswds.prefixSeparator', PREFIX_SEPARATOR)\nconst gridNamespace = inject('vueUswds.gridNamespace', GRID_NAMESPACE)\nconst imagePath = inject('vueUswds.imagePath', IMAGE_PATH)\n</script>\n\n<template>\n <div :class=\"`${gridNamespace}row ${gridNamespace}gap-lg`\">\n <div\n :class=\"`usa-banner__guidance tablet${prefixSeparator}${gridNamespace}col-6`\"\n >\n <slot v-if=\"$slots['tld-icon']\" name=\"tld-icon\"></slot>\n <!--\n \t@slot tldIcon\n \t\t@deprecated Use the `tld-icon` slot instead.\n \t-->\n <slot v-else-if=\"$slots.tldIcon\" name=\"tldIcon\"></slot>\n <template v-else>\n <img\n class=\"usa-banner__icon usa-media-block__img\"\n :src=\"`${imagePath}/icon-dot-gov.svg`\"\n role=\"img\"\n alt=\"\"\n aria-hidden=\"true\"\n />\n </template>\n <div class=\"usa-media-block__body\">\n <slot v-if=\"$slots['tld-description']\" name=\"tld-description\"></slot>\n <!--\n \t@slot tldDescription\n \t\t@deprecated Use the `tld-description` slot instead.\n \t-->\n <slot v-else-if=\"$slots.tldDescription\" name=\"tldDescription\"></slot>\n <template v-else>\n <p>\n <strong>Official websites use .gov</strong>\n <br />\n A <strong>.gov</strong> website belongs to an official government\n organization in the United States.\n </p>\n </template>\n </div>\n </div>\n <div\n :class=\"`usa-banner__guidance tablet${prefixSeparator}${gridNamespace}col-6`\"\n >\n <slot v-if=\"$slots['https-icon']\" name=\"https-icon\"></slot>\n <!--\n \t@slot httpsIcon\n \t\t@deprecated Use the `https-icon` slot instead.\n \t-->\n <slot v-else-if=\"$slots.httpsIcon\" name=\"httpsIcon\"></slot>\n <template v-else>\n <img\n class=\"usa-banner__icon usa-media-block__img\"\n :src=\"`${imagePath}/icon-https.svg`\"\n role=\"img\"\n alt=\"\"\n aria-hidden=\"true\"\n />\n </template>\n <div class=\"usa-media-block__body\">\n <slot\n v-if=\"$slots['https-description']\"\n name=\"https-description\"\n ></slot>\n <!--\n \t@slot httpsDescription\n \t\t@deprecated Use the `https-description` slot instead.\n \t-->\n <slot\n v-else-if=\"$slots.httpsDescription\"\n name=\"httpsDescription\"\n ></slot>\n <template v-else>\n <p>\n <strong>Secure .gov websites use HTTPS</strong>\n <br />\n A <strong>lock</strong> (\n <span class=\"icon-lock\"\n ><svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"52\"\n height=\"64\"\n viewBox=\"0 0 52 64\"\n class=\"usa-banner__lock-image\"\n role=\"img\"\n aria-labelledby=\"banner-lock-description\"\n focusable=\"false\"\n >\n <title id=\"banner-lock-title\">Lock</title>\n <desc id=\"banner-lock-description\">Locked padlock icon</desc>\n <path\n fill=\"#000000\"\n fill-rule=\"evenodd\"\n d=\"M26 0c10.493 0 19 8.507 19 19v9h3a4 4 0 0 1 4 4v28a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V32a4 4 0 0 1 4-4h3v-9C7 8.507 15.507 0 26 0zm0 8c-5.979 0-10.843 4.77-10.996 10.712L15 19v9h22v-9c0-6.075-4.925-11-11-11z\"\n ></path></svg\n ></span>\n ) or <strong>https://</strong> means you've safely connected to the\n .gov website. Share sensitive information only on official, secure\n websites.\n </p>\n </template>\n </div>\n </div>\n </div>\n</template>\n","<script setup>\nimport { computed, inject } from 'vue'\nimport {\n PREFIX_SEPARATOR,\n GRID_NAMESPACE,\n IMAGE_PATH,\n} from '@/utils/constants.js'\nimport { useToggle } from '@/composables/useToggle.js'\nimport UsaBannerContent from '@/components/UsaBannerContent'\n\nconst prefixSeparator = inject('vueUswds.prefixSeparator', PREFIX_SEPARATOR)\nconst gridNamespace = inject('vueUswds.gridNamespace', GRID_NAMESPACE)\nconst imagePath = inject('vueUswds.imagePath', IMAGE_PATH)\n\nconst emit = defineEmits(['update:open'])\n\nconst props = defineProps({\n open: {\n type: Boolean,\n default: false,\n },\n id: {\n type: String,\n default: '',\n },\n ariaLabel: {\n type: String,\n default: 'Official website of the United States government',\n },\n headerText: {\n type: String,\n default: 'An official website of the United States government',\n },\n actionText: {\n type: String,\n default: \"Here's how you know\",\n },\n customClasses: {\n type: Object,\n default: () => {\n return {\n accordion: [],\n bannerHeader: [],\n bannerInner: [],\n button: [],\n bannerContent: [],\n }\n },\n },\n})\n\nconst { isOpen, toggleId, openContent, closeContent, toggleContent } =\n useToggle(props.id, 'usa-banner', props.open, emit)\n\nconst headerClasses = computed(() => [\n { 'usa-banner__header--expanded': isOpen.value },\n ...(props.customClasses?.bannerHeader || []),\n])\n\ndefineExpose({\n openContent,\n closeContent,\n toggleContent,\n})\n</script>\n\n<template>\n <section class=\"usa-banner\" :aria-label=\"ariaLabel\">\n <div class=\"usa-accordion\" :class=\"customClasses?.accordion\">\n <header class=\"usa-banner__header\" :class=\"headerClasses\">\n <div class=\"usa-banner__inner\" :class=\"customClasses?.bannerInner\">\n <div :class=\"`${gridNamespace}col-auto`\">\n <slot name=\"flag\">\n <img\n aria-hidden=\"true\"\n class=\"usa-banner__header-flag\"\n :src=\"`${imagePath}/us_flag_small.png`\"\n alt=\"\"\n />\n </slot>\n </div>\n <div\n aria-hidden=\"true\"\n :class=\"`${gridNamespace}col-fill tablet${prefixSeparator}${gridNamespace}col-auto`\"\n >\n <p class=\"usa-banner__header-text\">{{ headerText }}</p>\n <p class=\"usa-banner__header-action\">{{ actionText }}</p>\n </div>\n <button\n type=\"button\"\n class=\"usa-accordion__button usa-banner__button\"\n :class=\"customClasses?.button\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"toggleId\"\n @click=\"toggleContent()\"\n >\n <slot name=\"button\" :is-open=\"isOpen\" :action-text=\"actionText\">\n <span class=\"usa-banner__button-text\">{{ actionText }}</span>\n </slot>\n </button>\n </div>\n </header>\n <div\n :id=\"toggleId\"\n :hidden=\"!isOpen\"\n class=\"usa-banner__content usa-accordion__content\"\n :class=\"customClasses?.bannerContent\"\n >\n <slot><UsaBannerContent /></slot>\n </div>\n </div>\n </section>\n</template>\n","<script setup>\nimport { computed } from 'vue'\nimport BaseLink from '@/components/BaseLink'\n\nconst props = defineProps({\n href: {\n type: String,\n default: '',\n },\n to: {\n type: [String, Object],\n default: '',\n },\n routerComponentName: {\n type: [String, Object],\n default: '',\n },\n current: {\n type: Boolean,\n default: false,\n },\n customClasses: {\n type: Object,\n default: () => ({\n link: [],\n span: [],\n }),\n },\n})\n\nconst ariaCurrent = computed(() => (props.current ? 'page' : null))\n</script>\n\n<template>\n <li class=\"usa-breadcrumb__list-item\" :aria-current=\"ariaCurrent\">\n <span v-if=\"current\" :class=\"customClasses?.span\"><slot></slot></span>\n <BaseLink\n v-else\n :href=\"href\"\n :to=\"to\"\n :router-component-name=\"routerComponentName\"\n class=\"usa-breadcrumb__link\"\n :class=\"customClasses?.link\"\n >\n <span :class=\"customClasses?.span\"><slot></slot></span>\n </BaseLink>\n </li>\n</template>\n","<script setup>\nimport { computed } from 'vue'\nimport UsaBreadcrumbItem from '@/components/UsaBreadcrumbItem'\n\nconst props = defineProps({\n items: {\n type: Array,\n default: () => [],\n },\n wrap: {\n type: Boolean,\n default: false,\n },\n ariaLabel: {\n type: String,\n default: 'Breadcrumbs',\n },\n customClasses: {\n type: Object,\n default: () => {\n return {\n list: [],\n item: [],\n link: [],\n span: [],\n }\n },\n },\n})\n\nconst classes = computed(() => [\n {\n 'usa-breadcrumb--wrap': props.wrap,\n },\n])\n\nconst hasCurrent = computed(() => props.items.some(item => item?.current))\n\nconst breadcrumbItems = computed(() => {\n if (!props.items.length) {\n return []\n }\n\n if (hasCurrent.value) {\n return props.items\n }\n\n const items = [...props.items]\n\n // If no breadcrumb item has the `current` prop set, automatically set the\n // last item to `current: true`.\n items[items.length - 1].current = true\n\n return items\n})\n</script>\n\n<template>\n <nav class=\"usa-breadcrumb\" :class=\"classes\" :aria-label=\"ariaLabel\">\n <ol class=\"usa-breadcrumb__list\" :class=\"customClasses?.list\">\n <slot :items=\"breadcrumbItems\">\n <UsaBreadcrumbItem\n v-for=\"item in breadcrumbItems\"\n :key=\"item?.id || item.text\"\n :class=\"customClasses?.item\"\n :to=\"item.to\"\n :href=\"item.href\"\n :router-component-name=\"item.routerComponentName\"\n :current=\"item.current\"\n :custom-classes=\"{\n link: customClasses?.link,\n span: customClasses?.span,\n }\"\n >{{ item.text }}</UsaBreadcrumbItem\n >\n </slot>\n </ol>\n </nav>\n</template>\n","<script setup>\nimport { computed } from 'vue'\n\nconst props = defineProps({\n variant: {\n type: String,\n default: '',\n validator(variant) {\n return [\n '',\n 'secondary',\n 'accent-cool',\n 'accent-warm',\n 'base',\n 'outline',\n 'inverse',\n 'unstyled',\n ].includes(variant)\n },\n },\n size: {\n type: String,\n default: '',\n validator(size) {\n return ['', 'big'].includes(size)\n },\n },\n type: {\n type: String,\n default: 'button',\n validator(type) {\n return ['button', 'submit', 'reset'].includes(type)\n },\n },\n disabled: {\n type: Boolean,\n default: false,\n },\n})\n\nconst classes = computed(() => [\n {\n 'usa-button--secondary': props.variant === 'secondary',\n 'usa-button--accent-cool': props.variant === 'accent-cool',\n 'usa-button--accent-warm': props.variant === 'accent-warm',\n 'usa-button--base': props.variant === 'base',\n 'usa-button--outline':\n props.variant === 'outline' || props.variant === 'inverse',\n 'usa-button--inverse': props.variant === 'inverse',\n 'usa-button--unstyled': props.variant === 'unstyled',\n 'usa-button--big': props.size === 'big',\n },\n])\n</script>\n\n<template>\n <button\n v-bind=\"$attrs\"\n class=\"usa-button\"\n :class=\"classes\"\n :type=\"type\"\n :disabled=\"disabled\"\n >\n <slot name=\"before\"></slot>\n <slot></slot>\n <slot name=\"after\"></slot>\n </button>\n</template>\n","<script setup>\nimport { computed } from 'vue'\n\nconst props = defineProps({\n segmented: {\n type: Boolean,\n default: false,\n },\n})\n\nconst classes = computed(() => [\n { 'usa-button-group--segmented': props.segmented },\n])\n</script>\n\n<template>\n <ul class=\"usa-button-group\" :class=\"classes\">\n <slot></slot>\n </ul>\n</template>\n","<script setup></script>\n\n<template>\n <li class=\"usa-button-group__item\"><slot></slot></li>\n</template>\n","<script setup>\nimport { computed } from 'vue'\nimport BaseHeading from '@/components/BaseHeading'\n\nconst props = defineProps({\n cardTag: {\n type: String,\n default: 'div',\n },\n heading: {\n type: String,\n default: '',\n },\n headingTag: {\n type: String,\n default: 'h2',\n },\n flag: {\n type: Boolean,\n default: false,\n },\n headerFirst: {\n type: Boolean,\n default: false,\n },\n insetMedia: {\n type: Boolean,\n default: false,\n },\n mediaPosition: {\n type: String,\n default: 'left',\n validator(mediaPosition) {\n return ['left', 'right'].includes(mediaPosition)\n },\n },\n headerExdent: {\n type: Boolean,\n default: false,\n },\n mediaExdent: {\n type: Boolean,\n default: false,\n },\n bodyExdent: {\n type: Boolean,\n default: false,\n },\n footerExdent: {\n type: Boolean,\n default: false,\n },\n customClasses: {\n type: Object,\n default: () => {\n return {\n container: [],\n header: [],\n heading: [],\n media: [],\n img: [],\n body: [],\n footer: [],\n }\n },\n },\n})\n\nconst classes = computed(() => [\n {\n 'usa-card--header-first': props.headerFirst,\n 'usa-card--flag': props.flag,\n 'usa-card--media-right': props.mediaPosition === 'right',\n },\n])\n\nconst headerClasses = computed(() => [\n { 'usa-card__header--exdent': props.headerExdent },\n ...(props.customClasses?.header || []),\n])\n\nconst mediaClasses = computed(() => [\n {\n 'usa-card__media--inset': props.insetMedia,\n 'usa-card__media--exdent': props.mediaExdent,\n },\n ...(props.customClasses?.media || []),\n])\n\nconst bodyClasses = computed(() => [\n { 'usa-card__body--exdent': props.bodyExdent },\n ...(props.customClasses?.body || []),\n])\n\nconst footerClasses = computed(() => [\n { 'usa-card__footer--exdent': props.footerExdent },\n ...(props.customClasses?.footer || []),\n])\n</script>\n\n<template>\n <component :is=\"cardTag\" class=\"usa-card\" :class=\"classes\">\n <div class=\"usa-card__container\" :class=\"customClasses?.container\">\n <header\n v-if=\"heading || $slots.heading\"\n class=\"usa-card__header\"\n :class=\"headerClasses\"\n >\n <BaseHeading\n :tag=\"headingTag\"\n class=\"usa-card__heading\"\n :class=\"customClasses?.heading\"\n ><slot name=\"heading\">{{ heading }}</slot></BaseHeading\n >\n </header>\n <div v-if=\"$slots.media\" class=\"usa-card__media\" :class=\"mediaClasses\">\n <div class=\"usa-card__img\" :class=\"customClasses?.img\"\n ><slot name=\"media\"></slot\n ></div>\n </div>\n <div v-if=\"$slots.default\" class=\"usa-card__body\" :class=\"bodyClasses\"\n ><slot></slot\n ></div>\n <div v-if=\"$slots.footer\" class=\"usa-card__footer\" :class=\"footerClasses\"\n ><slot name=\"footer\"></slot\n ></div>\n </div>\n </component>\n</template>\n","<script setup>\nimport { computed, ref, provide } from 'vue'\nimport { watchDebounced } from '@vueuse/core'\nimport { nextId } from '@/utils/unique-id.js'\n\nconst props = defineProps({\n maxlength: {\n type: Number,\n required: true,\n validator(maxLength) {\n const isValidMaxLength = maxLength > 0\n\n if (!isValidMaxLength) {\n console.warn(`${maxLength} is not a valid maxlength`)\n }\n\n return isValidMaxLength\n },\n },\n id: {\n type: String,\n default: '',\n },\n})\n\nconst statusMessageRef = ref('')\nconst srOnlyStatusMessage = ref('')\n\nconst charactersRemaining = ref(props.maxlength)\nconst charactersOver = computed(() =>\n charactersRemaining.value < 0 ? charactersRemaining.value * -1 : 0,\n)\nconst countStatus = computed(() => {\n if (charactersRemaining.value === props.maxlength) {\n return 'equal'\n } else if (charactersOver.value > 0) {\n return 'over'\n }\n\n return 'under'\n})\n\nconst computedId = computed(() => props.id || nextId('usa-character-count'))\n\nconst messageClasses = computed(() => [\n { 'usa-character-count__message--invalid': countStatus.value === 'over' },\n])\n\nconst updateCharacterCount = inputValue =>\n (charactersRemaining.value = props.maxlength - `${inputValue}`.length)\n\nwatchDebounced(\n charactersRemaining,\n () => {\n srOnlyStatusMessage.value = statusMessageRef.value?.textContent\n },\n { debounce: 1000, immediate: true },\n)\n\nprovide('updateCharacterCount', updateCharacterCount)\nprovide(\n 'characterCountMaxlength',\n computed(() => props.maxlength),\n)\nprovide(\n 'characterCountMessageId',\n computed(() => computedId.value),\n)\n</script>\n\n<template>\n <div class=\"usa-character-count\">\n <slot></slot>\n <span :id=\"computedId\" class=\"usa-character-count__message usa-sr-only\">\n <slot name=\"default-message\"\n >You can enter up to {{ maxlength }} characters</slot\n >\n </span>\n <div\n ref=\"statusMessageRef\"\n class=\"usa-character-count__status usa-hint\"\n :class=\"messageClasses\"\n aria-hidden=\"true\"\n >\n <slot\n v-if=\"countStatus === 'equal'\"\n name=\"equal-message\"\n :maxlength=\"maxlength\"\n >{{ maxlength }} character<template v-if=\"maxlength !== 1\">s</template>\n allowed</slot\n >\n <slot\n v-else-if=\"countStatus === 'under'\"\n name=\"remaining-message\"\n :characters-remaining=\"charactersRemaining\"\n :maxlength=\"maxlength\"\n >{{ charactersRemaining }} character<template\n v-if=\"charactersRemaining !== 1\"\n >s</template\n >\n left</slot\n >\n <slot\n v-else-if=\"countStatus === 'over'\"\n name=\"over-message\"\n :characters-over=\"charactersOver\"\n :maxlength=\"maxlength\"\n >{{ charactersOver }} character<template v-if=\"charactersOver !== 1\"\n >s</template\n >\n over limit</slot\n >\n </div>\n <div\n class=\"usa-character-count__sr-status usa-sr-only\"\n aria-live=\"polite\"\n >{{ srOnlyStatusMessage }}</div\n >\n </div>\n</template>\n","<script>\nexport default {\n inheritAttrs: false,\n}\n</script>\n\n<script setup>\nimport { computed } from 'vue'\nimport { nextId } from '@/utils/unique-id.js'\n\nconst emit = defineEmits(['update:modelValue'])\n\nconst props = defineProps({\n tile: {\n type: Boolean,\n default: false,\n },\n modelValue: {\n type: Boolean,\n default: false,\n },\n label: {\n type: String,\n default: '',\n },\n description: {\n type: String,\n default: '',\n },\n id: {\n type: String,\n default: '',\n },\n customClasses: {\n type: Object,\n default: () => {\n return {\n component: [],\n label: [],\n description: [],\n }\n },\n },\n})\n\nconst computedId = computed(() => props.id || nextId('usa-checkbox'))\n\nconst checkboxValue = computed({\n get() {\n return props.modelValue\n },\n set(checked) {\n emit('update:modelValue', checked)\n },\n})\n\nconst classes = computed(() => [\n {\n 'usa-checkbox__input--tile': props.tile,\n },\n])\n</script>\n\n<template>\n <div class=\"usa-checkbox\" :class=\"customClasses?.component\">\n <input\n v-bind=\"$attrs\"\n :id=\"computedId\"\n v-model=\"checkboxValue\"\n class=\"usa-checkbox__input\"\n type=\"checkbox\"\n :class=\"classes\"\n />\n <label\n class=\"usa-checkbox__label\"\n :class=\"customClasses?.label\"\n :htmlFor=\"computedId\"\n ><slot>{{ label }}</slot>\n <span\n v-if=\"description || $slots.description\"\n class=\"usa-checkbox__label-description\"\n :class=\"customClasses?.description\"\n ><slot name=\"description\">{{ description }}</slot></span\n >\n </label>\n </div>\n</template>\n","<script setup>\nimport { computed } from 'vue'\n\nconst props = defineProps({\n checked: {\n type: Boolean,\n default: false,\n },\n ariaLabel: {\n type: String,\n default: '',\n },\n})\n\nconst classes = computed(() => [\n { 'usa-checklist__item--checked': props.checked },\n])\n</script>\n\n<template>\n <li class=\"usa-checklist__item\" :aria-label=\"ariaLabel\" :class=\"classes\"\n ><slot></slot\n ></li>\n</template>\n","<script setup>\nimport { computed } from 'vue'\n\nconst props = defineProps({\n condensed: {\n type: Boolean,\n default: false,\n },\n})\n\nconst classes = computed(() => [\n { 'usa-collection--condensed': props.condensed },\n])\n</script>\n\n<template>\n <ul class=\"usa-collection\" :class=\"classes\"\n ><slot></slot\n ></ul>\n</template>\n","<script setup>\nimport { computed } from 'vue'\n\nconst props = defineProps({\n month: {\n type: String,\n required: true,\n },\n day: {\n type: [String, Number],\n required: true,\n },\n datetime: {\n type: String,\n default: '',\n },\n customClasses: {\n type: Object,\n default: () => {\n return {\n datetime: [],\n month: [],\n day: [],\n }\n },\n },\n})\n\nconst timeElement = computed(() => (props.datetime ? 'time' : 'div'))\n</script>\n\n<template>\n <div class=\"usa-collection__calendar-date\">\n <component\n :is=\"timeElement\"\n :datetime=\"datetime || null\"\n :class=\"customClasses?.datetime\"\n >\n <span\n class=\"usa-collection__calendar-date-month\"\n :class=\"customClasses?.month\"\n >{{ month }}</span\n >\n <span\n class=\"usa-collection__calendar-date-day\"\n :class=\"customClasses?.day\"\n >{{ day }}</span\n >\n </component>\n </div>\n</template>\n","<script setup></script>\n\n<template>\n <li class=\"usa-collection__meta-item\"><slot></slot></li>\n</template>\n","import { ref, computed, readonly, watch, nextTick } from 'vue'\nimport { onKeyStroke, onClickOutside, useActiveElement } from '@vueuse/core'\nimport { nextId } from '@/utils/unique-id.js'\nimport { escapeRegExp } from '@/utils/common.js'\n\nexport function useComboBox(\n _id,\n _selectedOption,\n _options,\n _disabled,\n _readonly,\n emit,\n) {\n const id = ref(_id)\n const options = ref(_options)\n const isDisabled = ref(_disabled)\n const isReadonly = ref(_readonly)\n const selectedOption = computed({\n get() {\n return _selectedOption.value\n },\n set(newSelectedValue) {\n emit('update:modelValue', newSelectedValue)\n },\n })\n\n const activeElement = useActiveElement()\n const isDirty = ref(false)\n const searchTerm = ref('')\n const highlightedOption = ref('')\n\n const isOpen = ref(false)\n\n const selectedLabel = computed(() => {\n if (selectedOption.value === '') {\n return ''\n }\n\n const foundOption = options.value.find(\n option => option.value === selectedOption.value,\n )\n\n return foundOption?.label || ''\n })\n\n watch(selectedLabel, currentLabel => {\n if (currentLabel !== '') {\n searchTerm.value = currentLabel\n }\n })\n\n watch(searchTerm, currentTerm => {\n if (isOpen.value && currentTerm !== '') {\n isDirty.value = true\n }\n })\n\n // Set the default value.\n if (selectedLabel.value) {\n searchTerm.value = selectedLabel.value\n }\n\n const filteredOptions = computed(() => {\n if (\n searchTerm.value === '' ||\n (!isDirty.value && searchTerm.value === selectedLabel.value)\n ) {\n return options.value\n }\n\n return options.value.filter(option => {\n const regex = new RegExp(escapeRegExp(searchTerm.value), 'gi')\n return regex.test(option.label)\n })\n })\n\n const totalFilteredOptions = computed(() => filteredOptions.value?.length)\n\n const computedId = computed(() => id.value || nextId('usa-combo-box'))\n const computedLabelId = computed(() => `${computedId.value}-label`)\n const computedErrorMessageId = computed(\n () => `${computedId.value}-error-message`,\n )\n const computedHintId = computed(() => `${computedId.value}-hint`)\n const computedAssistiveHintId = computed(\n () => `${computedId.value}-assistive-hint`,\n )\n const computedListId = computed(() => `${computedId.value}-list`)\n\n const getListItemIdByIndex = index =>\n `${computedListId.value}-option-${index}`\n\n const componentElement = ref(null)\n const inputElement = ref(null)\n const listElement = ref(null)\n const listItemElements = ref([])\n\n const getItemRefById = id => {\n return listItemElements.value.find(item => item.id === id)\n }\n\n const getItemRefByValue = value => {\n return listItemElements.value.find(item => item.dataset.value === value)\n }\n\n const firstOptionValue = computed(() => {\n return totalFilteredOptions.value ? filteredOptions.value[0].value : ''\n })\n\n const firstOptionRef = computed(() => {\n const firstItemId = totalFilteredOptions.value\n ? listItemElements.value[0].id\n : null\n\n return firstItemId ? getItemRefById(firstItemId) : null\n })\n\n const selectedOptionRef = computed(() => {\n if (selectedOption.value === '') {\n return null\n }\n\n const foundItemRef = listItemElements.value.find(\n itemRef => itemRef.dataset.value === selectedOption.value,\n )\n\n return foundItemRef ? foundItemRef : null\n })\n\n const highlightedOptionRef = computed(() => {\n if (highlightedOption.value === '') {\n return null\n }\n\n const foundItemRef = listItemElements.value.find(itemRef => {\n return itemRef.dataset.value === highlightedOption.value\n })\n\n return foundItemRef ? foundItemRef : null\n })\n\n const isFirstOption = computed(() => {\n const optionIndex = filteredOptions.value.findIndex(\n item => item.value === highlightedOption.value,\n )\n\n return optionIndex === 0\n })\n\n const isLastOption = computed(() => {\n const optionIndex = filteredOptions.value.findIndex(\n item => item.value === highlightedOption.value,\n )\n\n return optionIndex === totalFilteredOptions.value - 1\n })\n\n const activeDescendent = computed(() => {\n const activeOptionId = activeElement.value.id\n\n if (activeOptionId === highlightedOptionId.value) {\n return highlightedOptionId.value\n }\n\n if (\n totalFilteredOptions.value &&\n selectedOption.value !== '' &&\n isOpen.value &&\n activeOptionId === computedId.value\n ) {\n return highlightedOptionId.value\n }\n\n return null\n })\n\n const scrollList = elementRef => {\n if (!elementRef || !listElement?.value) {\n return\n }\n\n const optionBottom = elementRef.offsetTop + elementRef.offsetHeight\n const currentBottom =\n listElement.value.scrollTop + listElement.value.offsetHeight\n\n if (optionBottom > currentBottom) {\n listElement.value.scrollTop =\n optionBottom - listElement.value.offsetHeight\n }\n\n if (elementRef.offsetTop < listElement.value.scrollTop) {\n listElement.value.scrollTop = elementRef.offsetTop\n }\n }\n\n const focusInput = () => {\n inputElement.value.focus()\n }\n\n const selectOption = optionValue => {\n selectedOption.value = optionValue\n\n const option = options.value.find(option => option.value === optionValue)\n\n searchTerm.value = option?.label || ''\n\n isDirty.value = false\n }\n\n const clearSelectedOption = () => {\n selectOption('')\n }\n\n const highlightOption = optionValue => {\n highlightedOption.value = optionValue\n }\n\n const clearHighlightedOption = () => {\n highlightedOption.value = ''\n }\n\n const openList = () => {\n if (!isDisabled.value && !isReadonly.value) {\n isOpen.value = true\n }\n }\n\n const closeList = () => {\n isOpen.value = false\n isDirty.value = false\n clearHighlightedOption()\n listElement.value.scrollTop = 0\n }\n\n const listItemTabIndex = optionValue => {\n return highlightedOption.value === optionValue ||\n selectedOption.value === optionValue\n ? 0\n : -1\n }\n\n const highlightedOptionId = computed(() => {\n if (!highlightedOption.value) {\n return null\n }\n\n const highlightedOptionIndex = filteredOptions.value.findIndex(\n option => option.value === highlightedOption.value,\n )\n\n return getListItemIdByIndex(highlightedOptionIndex)\n })\n\n const clearButtonIsVisible = computed(\n () =>\n selectedOption.value !== '' &&\n searchTerm.value === selectedLabel.value &&\n !isDisabled.value &&\n !isReadonly.value,\n )\n\n const handleFilterOnInput = () => {\n if (!isOpen.value) {\n openList()\n }\n\n if (selectedOption.value !== '') {\n highlightOption(selectedOption.value)\n } else {\n highlightOption(firstOptionValue.value)\n }\n }\n\n const handleEnterOnInput = () => {\n const foundItem = filteredOptions.value.find(\n item => item.label === searchTerm.value,\n )\n\n if (searchTerm.value !== '' && foundItem.value) {\n selectOption(foundItem.value)\n }\n\n closeList()\n }\n\n const handleListToggle = () => {\n if (isOpen.value) {\n closeList()\n clearHighlightedOption()\n } else {\n openList()\n\n if (selectedOption.value !== '') {\n highlightOption(selectedOption.value)\n\n nextTick(() => {\n scrollList(selectedOptionRef.value)\n })\n } else {\n highlightOption(firstOptionValue.value)\n }\n }\n\n focusInput()\n }\n\n const handleClearInput = () => {\n clearSelectedOption()\n clearHighlightedOption()\n focusInput()\n }\n\n const handleHoverOnListOption = value => {\n highlightOption(value)\n\n if (highlightedOptionRef.value) {\n highlightedOptionRef.value.focus({ preventScroll: true })\n }\n }\n\n const handleSpaceOnListOption = value => {\n selectOption(value)\n closeList()\n focusInput()\n }\n\n const handleEnterOnListOption = value => {\n selectOption(value)\n closeList()\n focusInput()\n }\n\n const handleDownOnListOption = index => {\n if (!isLastOption.value) {\n highlightOption(filteredOptions.value[index + 1].value)\n\n const itemRef = getItemRefByValue(highlightedOption.value)\n\n scrollList(itemRef.value)\n\n if (highlightedOptionRef.value) {\n highlightedOptionRef.value.focus()\n }\n }\n }\n\n const handleUpOnListOption = index => {\n if (isFirstOption.value) {\n closeList()\n clearHighlightedOption()\n focusInput()\n } else {\n highlightOption(filteredOptions.value[index - 1].value)\n\n const itemRef = getItemRefByValue(highlightedOption.value)\n\n scrollList(itemRef.value)\n\n if (highlightedOptionRef.value) {\n highlightedOptionRef.value.focus()\n }\n }\n }\n\n const handleClickOutside = () => {\n if (isOpen.value) {\n selectOption(selectedOption.value)\n closeList()\n clearHighlightedOption()\n }\n }\n\n const handleClickOnListOption = value => {\n selectOption(value)\n closeList()\n focusInput()\n }\n\n const handleEscape = () => {\n selectOption(selectedOption.value)\n closeList()\n clearHighlightedOption()\n focusInput()\n }\n\n const handleDownOnInput = () => {\n if (!isOpen.value) {\n openList()\n }\n\n if (!totalFilteredOptions.value) {\n return\n }\n\n if (selectedOption.value) {\n highlightOption(selectedOption.value)\n\n nextTick(() => {\n selectedOptionRef.value.focus()\n\n scrollList(selectedOp