{"version":3,"file":"combobox_with_popover.vue.cjs","sources":["../../../../recipes/comboboxes/combobox_with_popover/combobox_with_popover.vue"],"sourcesContent":["<template>\n  <dt-combobox\n    ref=\"combobox\"\n    :loading=\"loading\"\n    :label=\"label\"\n    :label-visible=\"labelVisible\"\n    :size=\"size\"\n    :description=\"description\"\n    :empty-list=\"emptyList\"\n    :empty-state-message=\"emptyStateMessage\"\n    :show-list=\"isListShown\"\n    :on-beginning-of-list=\"onBeginningOfList\"\n    :on-end-of-list=\"onEndOfList\"\n    :list-rendered-outside=\"true\"\n    :list-id=\"listId\"\n    data-qa=\"dt-combobox\"\n    v-on=\"comboboxListeners\"\n  >\n    <template\n      #input=\"{ inputProps }\"\n    >\n      <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n      <div\n        :id=\"externalAnchor\"\n        ref=\"input\"\n        @focusin=\"onFocusIn\"\n        @keydown.up=\"openOnArrowKeyPress($event)\"\n        @keydown.down=\"openOnArrowKeyPress($event)\"\n      >\n        <slot\n          name=\"input\"\n          :input-props=\"inputProps\"\n          :on-input=\"handleDisplayList\"\n        />\n      </div>\n    </template>\n    <template #list=\"{ opened, listProps, clearHighlightIndex }\">\n      <dt-popover\n        ref=\"popover\"\n        :open.sync=\"isListShown\"\n        :hide-on-click=\"false\"\n        :max-height=\"maxHeight\"\n        :max-width=\"maxWidth\"\n        :offset=\"popoverOffset\"\n        :sticky=\"popoverSticky\"\n        placement=\"bottom-start\"\n        initial-focus-element=\"none\"\n        padding=\"none\"\n        role=\"listbox\"\n        :external-anchor=\"externalAnchor\"\n        :content-width=\"contentWidth\"\n        :content-appear=\"true\"\n        :content-tabindex=\"null\"\n        :modal=\"false\"\n        :auto-focus=\"false\"\n        :append-to=\"appendTo\"\n        :transition=\"transition\"\n        :visually-hidden-close-label=\"visuallyHiddenCloseLabel\"\n        :visually-hidden-close=\"visuallyHiddenClose\"\n        @opened=\"opened($event, arguments[1]);\"\n      >\n        <template\n          v-if=\"$slots.header\"\n          #headerContent\n        >\n          <div\n            ref=\"header\"\n          >\n            <slot name=\"header\" />\n          </div>\n        </template>\n\n        <template #content>\n          <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n          <div\n            ref=\"listWrapper\"\n            :class=\"[\n              'd-recipe-combobox-with-popover__list',\n              DROPDOWN_PADDING_CLASSES[padding],\n              listClass,\n            ]\"\n            @mouseleave=\"clearHighlightIndex\"\n            @focusout=\"clearHighlightIndex\"\n          >\n            <combobox-loading-list\n              v-if=\"loading\"\n              v-bind=\"listProps\"\n            />\n            <combobox-empty-list\n              v-else-if=\"emptyList && emptyStateMessage\"\n              v-bind=\"listProps\"\n              :message=\"emptyStateMessage\"\n            />\n            <slot\n              v-else\n              name=\"list\"\n              :list-props=\"listProps\"\n            />\n          </div>\n        </template>\n\n        <template\n          v-if=\"$slots.footer\"\n          #footerContent\n        >\n          <div\n            ref=\"footer\"\n          >\n            <slot name=\"footer\" />\n          </div>\n        </template>\n      </dt-popover>\n    </template>\n  </dt-combobox>\n</template>\n\n<script>\nimport ComboboxLoadingList from '@/components/combobox/combobox_loading-list.vue';\nimport ComboboxEmptyList from '@/components/combobox/combobox_empty-list.vue';\nimport { DtCombobox, LABEL_SIZES } from '@/components/combobox';\nimport { DtPopover, POPOVER_APPEND_TO_VALUES, POPOVER_CONTENT_WIDTHS } from '@/components/popover';\nimport { getUniqueString } from '@/common/utils';\nimport { DROPDOWN_PADDING_CLASSES } from '@/components/dropdown';\nimport SrOnlyCloseButtonMixin from '@/common/mixins/sr_only_close_button';\n\nexport default {\n  name: 'DtRecipeComboboxWithPopover',\n\n  components: {\n    DtCombobox,\n    DtPopover,\n    ComboboxLoadingList,\n    ComboboxEmptyList,\n  },\n\n  mixins: [SrOnlyCloseButtonMixin],\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     * Determines when to show the list element and also controls the aria-expanded attribute.\n     * Leaving this null will have the combobox trigger on input focus by default.\n     * If you set this value, the default trigger behavior will be disabled and you can\n     * control it as you need.\n     */\n    showList: {\n      type: Boolean,\n      default: null,\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     * Additional class for the wrapper list element.\n     */\n    listClass: {\n      type: [String, Array, Object],\n      default: '',\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 maximum height for the popover before overflow.\n     * Possible units rem|px|em\n     */\n    maxHeight: {\n      type: String,\n      default: '',\n    },\n\n    /**\n     * Determines maximum width for the popover before overflow.\n     * Possible units rem|px|%|em\n     */\n    maxWidth: {\n      type: String,\n      default: '',\n    },\n\n    /**\n     * Vertical padding size around the list element.\n     */\n    padding: {\n      type: String,\n      default: 'small',\n      validator: (padding) => {\n        return Object.keys(DROPDOWN_PADDING_CLASSES).some((item) => item === padding);\n      },\n    },\n\n    /**\n     * Width configuration for the popover content. When its value is 'anchor',\n     * the popover content will have the same width as the anchor.\n     */\n    contentWidth: {\n      type: String,\n      default: null,\n      validator: contentWidth => POPOVER_CONTENT_WIDTHS.includes(contentWidth),\n    },\n\n    /**\n     * If the list should be shown by pressing up or down arrow key on the input element.\n     * This can be set when not passing showList prop.\n     */\n    openWithArrowKeys: {\n      type: Boolean,\n      default: false,\n    },\n\n    /**\n     *  Displaces the popover content box from its anchor element\n     *  by the specified number of pixels.\n     */\n    popoverOffset: {\n      type: Array,\n      default: () => [0, 4],\n    },\n\n    /**\n     * If the popover sticks to the input.\n     */\n    popoverSticky: {\n      type: [Boolean, String],\n      default: false,\n    },\n\n    /**\n     * Displays the list when the combobox is focused, before the user has typed anything.\n     * When this is enabled the list will not close after selection.\n     */\n    hasSuggestionList: {\n      type: Boolean,\n      default: true,\n    },\n\n    /**\n     * Determines when to show the skeletons and also controls aria-busy attribute.\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     */\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     * Sets the element to which the popover is going to append to.\n     * 'body' will append to the nearest body (supports shadow DOM).\n     * @values 'body', 'parent', HTMLElement,\n     */\n    appendTo: {\n      type: [HTMLElement, String],\n      default: 'body',\n      validator: appendTo => {\n        return POPOVER_APPEND_TO_VALUES.includes(appendTo) ||\n            (appendTo instanceof HTMLElement);\n      },\n    },\n\n    /**\n     * Named transition when the content display is toggled.\n     * @see DtLazyShow\n     */\n    transition: {\n      type: String,\n      default: 'fade',\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 'escape' key is pressed\n     *\n     * @event escape\n     */\n    'escape',\n\n    /**\n     * Event fired when an item is highlighted\n     *\n     * @event highlight\n     * @type {Number}\n     */\n    'highlight',\n\n    /**\n     * Emitted when items are shown or hidden\n     *\n     * @event opened\n     * @type {Boolean | Array}\n     */\n    'opened',\n  ],\n\n  data () {\n    return {\n      DROPDOWN_PADDING_CLASSES,\n      isListShown: false,\n      isInputFocused: false,\n      isListFocused: false,\n      externalAnchor: getUniqueString(),\n    };\n  },\n\n  computed: {\n    comboboxListeners () {\n      return {\n        ...this.$listeners,\n\n        select: this.onSelect,\n\n        escape: this.onEscape,\n\n        highlight: this.onHighlight,\n      };\n    },\n  },\n\n  watch: {\n    showList: {\n      handler: function (show) {\n        if (show !== null) {\n          this.isListShown = show;\n        }\n      },\n\n      immediate: true,\n    },\n\n    isListShown (val) {\n      if (val) {\n        window.addEventListener('mousedown', this.onFocusOut);\n      } else {\n        window.removeEventListener('mousedown', this.onFocusOut);\n      }\n      this.onOpened(val);\n    },\n  },\n\n  methods: {\n    handleDisplayList (value) {\n      if (!this.hasSuggestionList && value) { this.showComboboxList(); }\n      if (!this.hasSuggestionList && !value) { this.closeComboboxList(); }\n    },\n\n    showComboboxList () {\n      if (this.showList != null) { return; }\n      this.isListShown = true;\n    },\n\n    closeComboboxList () {\n      if (this.showList != null) { return; }\n      this.isListShown = false;\n    },\n\n    onSelect (highlightIndex) {\n      if (this.loading) return;\n\n      this.$emit('select', highlightIndex);\n      if (!this.hasSuggestionList) {\n        // we don't display the list before the user has typed anything\n        this.closeComboboxList();\n      }\n    },\n\n    onEscape () {\n      this.$emit('escape');\n      this.closeComboboxList();\n    },\n\n    onHighlight (highlightIndex) {\n      if (this.loading) return;\n\n      this.$emit('highlight', highlightIndex);\n    },\n\n    onOpened (opened) {\n      this.$emit('opened', opened);\n    },\n\n    onFocusIn (e) {\n      if (this.hasSuggestionList && e && this.$refs.input?.querySelector('input') === e.target) {\n        // only trigger if we show suggestion list when focused, and\n        // it's the input specifically that was focused\n        this.showComboboxList();\n      }\n    },\n\n    onFocusOut (e) {\n      // Check if the focus change was to another target within the combobox component\n      const popoverEl = this.$refs.popover?.tip?.popper;\n      const comboboxEl = this.$refs.input;\n\n      if (e.composedPath()?.some(el => [popoverEl, comboboxEl].includes(el))) return;\n\n      // If outside the combobox then close\n      this.closeComboboxList();\n    },\n\n    openOnArrowKeyPress () {\n      if (this.showList !== null || this.isListShown || !this.openWithArrowKeys) { return; }\n\n      this.showComboboxList();\n    },\n  },\n};\n</script>\n"],"names":["DtCombobox","DtPopover","ComboboxLoadingList","ComboboxEmptyList","SrOnlyCloseButtonMixin","LABEL_SIZES","getUniqueString","DROPDOWN_PADDING_CLASSES","POPOVER_CONTENT_WIDTHS","POPOVER_APPEND_TO_VALUES"],"mappings":"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"}