UNPKG

@dialpad/dialtone

Version:

Dialpad's Dialtone design system monorepo

1 lines 15.5 kB
{"version":3,"file":"combobox.cjs","sources":["../../../components/combobox/combobox.vue"],"sourcesContent":["<!-- eslint-disable vuejs-accessibility/no-static-element-interactions -->\n<template>\n <div\n @keydown.esc.stop=\"onKeyValidation($event, 'onEscapeKey')\"\n @keydown.enter.exact=\"onKeyValidation($event, 'onEnterKey')\"\n @keydown.up.stop.prevent=\"onKeyValidation($event, 'onUpKey')\"\n @keydown.down.stop.prevent=\"onKeyValidation($event, 'onDownKey')\"\n @keydown.home.stop.prevent=\"onKeyValidation($event, 'onHomeKey')\"\n @keydown.end.stop.prevent=\"onKeyValidation($event, 'onEndKey')\"\n >\n <div data-qa=\"dt-combobox-input-wrapper\">\n <!-- @slot Slot for the combobox input element -->\n <slot\n name=\"input\"\n :input-props=\"inputProps\"\n />\n </div>\n\n <div\n v-if=\"showList\"\n ref=\"listWrapper\"\n data-qa=\"dt-combobox-list-wrapper\"\n @mouseleave=\"clearHighlightIndex\"\n @focusout=\"clearHighlightIndex\"\n @mousemove.capture=\"onMouseHighlight\"\n >\n <combobox-loading-list\n v-if=\"loading && !listRenderedOutside\"\n v-bind=\"listProps\"\n />\n <combobox-empty-list\n v-else-if=\"emptyList && (emptyStateMessage || hasSlotContent($slots.emptyListItem)) && !listRenderedOutside\"\n v-bind=\"listProps\"\n :message=\"emptyStateMessage\"\n :item-class=\"emptyStateClass\"\n >\n <slot name=\"emptyListItem\" />\n </combobox-empty-list>\n <!-- @slot Slot for the combobox list element -->\n <slot\n v-else\n name=\"list\"\n :list-props=\"listProps\"\n :opened=\"onOpen\"\n :clear-highlight-index=\"clearHighlightIndex\"\n />\n </div>\n </div>\n</template>\n\n<script>\nimport KeyboardNavigation from '@/common/mixins/keyboard_list_navigation';\nimport { getUniqueString, hasSlotContent } from '@/common/utils';\nimport ComboboxLoadingList from './combobox_loading-list.vue';\nimport ComboboxEmptyList from './combobox_empty-list.vue';\nimport { LABEL_SIZES } from '@/components/combobox/combobox_constants';\n\n/**\n * A combobox is a semantic component that displays an input element combined with a listbox,\n * which enables the user to select items from the list.\n * @see https://dialtone.dialpad.com/components/combobox.html\n */\nexport default {\n compatConfig: { MODE: 3 },\n name: 'DtCombobox',\n\n components: {\n ComboboxLoadingList,\n ComboboxEmptyList,\n },\n\n mixins: [\n KeyboardNavigation({\n indexKey: 'highlightIndex',\n idKey: 'highlightId',\n listElementKey: 'getListElement',\n afterHighlightMethod: 'afterHighlight',\n beginningOfListMethod: 'beginningOfListMethod',\n endOfListMethod: 'endOfListMethod',\n activeItemKey: 'activeItemEl',\n }),\n ],\n\n props: {\n /**\n * String to use for the input label.\n */\n label: {\n type: String,\n required: true,\n },\n\n /**\n * Determines visibility of input label.\n * @values true, false\n */\n labelVisible: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Size of the input, one of `xs`, `sm`, `md`, `lg`, `xl`\n * @values null, xs, sm, md, lg, xl\n */\n size: {\n type: String,\n default: null,\n validator: (t) => Object.values(LABEL_SIZES).includes(t),\n },\n\n /**\n * Description for the input\n */\n description: {\n type: String,\n default: '',\n },\n\n /**\n * Sets an ID on the list element of the component. Used by several aria attributes\n * as well as when deriving the IDs for each item.\n */\n listId: {\n type: String,\n default () { return getUniqueString(); },\n },\n\n /**\n * A method that will be called when the selection goes past the beginning of the list.\n */\n onBeginningOfList: {\n type: Function,\n default: null,\n },\n\n /**\n * A method that will be called when the selection goes past the end of the list.\n */\n onEndOfList: {\n type: Function,\n default: null,\n },\n\n /**\n * Determines when to show the list element and also controls the aria-expanded attribute.\n * @values true, false\n */\n showList: {\n type: Boolean,\n default: false,\n },\n\n /**\n * If the list is rendered outside the component, like when using popover as the list wrapper.\n * @values true, false\n */\n listRenderedOutside: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Determines when to show the skeletons and also controls aria-busy attribute.\n * @values true, false\n */\n loading: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Sets the list to an empty state, and displays the message from prop `emptyStateMessage`.\n * @values true, false\n */\n emptyList: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Message to show when the list is empty\n */\n emptyStateMessage: {\n type: String,\n default: '',\n },\n\n /**\n * Additional class name for the empty list element.\n * Can accept all of String, Object, and Array, i.e. has the\n * same api as Vue's built-in handling of the class attribute.\n */\n emptyStateClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * Programmatically click on the active list item element when a selection\n * comes from keyboard navigation, i.e. pressing the \"Enter\" key.\n * @values true, false\n */\n clickOnSelect: {\n type: Boolean,\n default: false,\n },\n },\n\n emits: [\n /**\n * Event fired when item selected\n *\n * @event select\n * @type {Number}\n */\n 'select',\n\n /**\n * Event fired when pressing escape\n *\n * @event escape\n */\n 'escape',\n\n /**\n * Event fired when the highlight changes\n *\n * @event highlight\n * @type {Number}\n */\n 'highlight',\n\n /**\n * Event fired when list is shown or hidden\n *\n * @event opened\n * @type {Boolean}\n */\n 'opened',\n ],\n\n data () {\n return {\n // If the list is rendered at the root, rather than as a child\n // of this component, this is the ref to that dom element. Set\n // by the onOpen method.\n outsideRenderedListRef: null,\n hasSlotContent,\n };\n },\n\n computed: {\n inputProps () {\n return {\n label: this.label,\n labelVisible: this.labelVisible,\n size: this.size,\n description: this.description,\n role: 'combobox',\n 'aria-label': this.label,\n 'aria-expanded': this.showList.toString(),\n 'aria-owns': this.listId,\n 'aria-haspopup': 'listbox',\n 'aria-activedescendant': this.activeItemId,\n 'aria-controls': this.listId,\n };\n },\n\n listProps () {\n return {\n role: 'listbox',\n id: this.listId,\n // The list has to be positioned relatively so that the auto-scroll can\n // calculate the correct offset for the list items.\n class: 'd-ps-relative',\n 'aria-label': this.label,\n };\n },\n\n beginningOfListMethod () {\n return this.onBeginningOfList || this.jumpToEnd;\n },\n\n endOfListMethod () {\n return this.onEndOfList || this.jumpToBeginning;\n },\n\n activeItemId () {\n if (!this.showList || this.highlightIndex < 0 || this.loading) {\n return;\n }\n return this.highlightId;\n },\n\n activeItemEl () {\n if (!this.highlightId) return '';\n return this.getListElement().querySelector('#' + this.highlightId);\n },\n },\n\n watch: {\n showList (showList) {\n // When the list's visibility changes reset the highlight index.\n\n if (!this.listRenderedOutside) {\n this.setInitialHighlightIndex();\n this.$emit('opened', showList);\n }\n\n if (!showList && this.outsideRenderedListRef) {\n this.outsideRenderedListRef.removeEventListener('mousemove', this.onMouseHighlight);\n this.outsideRenderedListRef = null;\n }\n },\n\n loading (loading) {\n this.$nextTick(() => {\n this.setInitialHighlightIndex();\n });\n },\n\n $props: {\n deep: true,\n immediate: true,\n handler () {\n this.validateEmptyListProps();\n },\n },\n },\n\n created () {\n this.validateEmptyListProps();\n },\n\n methods: {\n onMouseHighlight (e) {\n if (this.loading) return;\n\n const liElement = e.target.closest('li');\n\n if (liElement && this.highlightId !== liElement.id) {\n this.setHighlightId(liElement.id);\n }\n },\n\n getListElement () {\n return this.outsideRenderedListRef ?? this.$refs.listWrapper?.querySelector(`#${this.listId}`);\n },\n\n clearHighlightIndex () {\n if (this.showList) {\n this.setHighlightIndex(-1);\n }\n },\n\n afterHighlight () {\n if (this.loading) return;\n this.$emit('highlight', this.highlightIndex);\n },\n\n onEnterKey () {\n if (this.loading || this.emptyList) return;\n\n if (this.highlightIndex >= 0) {\n this.$emit('select', this.highlightIndex);\n\n if (this.clickOnSelect) {\n this.activeItemEl?.click();\n }\n }\n },\n\n onEscapeKey () {\n this.$emit('escape');\n },\n\n onOpen (open, contentRef) {\n this.outsideRenderedListRef = contentRef;\n this.outsideRenderedListRef?.addEventListener('mousemove', this.onMouseHighlight);\n this.$emit('opened', open);\n\n if (open) {\n this.setInitialHighlightIndex();\n }\n },\n\n onKeyValidation (e, eventHandler) {\n if (!this.showList || !this.getListElement()) return;\n\n this[eventHandler](e);\n },\n\n setInitialHighlightIndex () {\n if (!this.showList) return;\n this.$nextTick(() => {\n // When the list's is shown, reset the highlight index.\n // If the list is loading, set to -1\n this.setHighlightIndex(this.loading ? -1 : 0);\n });\n },\n\n validateEmptyListProps () {\n if (this.$slots.emptyListItem) { return; }\n\n if (this.emptyList && !this.emptyStateMessage) {\n console.error(`Invalid props: you must pass both props emptyList and emptyStateMessage to show the\n empty message.`);\n }\n },\n },\n};\n</script>\n"],"names":["_sfc_main","ComboboxLoadingList","ComboboxEmptyList","KeyboardNavigation","t","LABEL_SIZES","getUniqueString","hasSlotContent","showList","loading","e","liElement","_a","open","contentRef","eventHandler","_hoisted_1","_createElementBlock","_withKeys","_withModifiers","$event","$options","_createElementVNode","_renderSlot","_ctx","$props","args","_cache","_openBlock","_createBlock","_component_combobox_loading_list","_normalizeProps","_mergeProps","$data","_component_combobox_empty_list","_withCtx","_createCommentVNode"],"mappings":"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"}