{"version":3,"file":"combobox-with-popover.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        @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, COMBOBOX_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';\n\nexport default {\n  name: 'DtRecipeComboboxWithPopover',\n\n  components: {\n    DtCombobox,\n    DtPopover,\n    ComboboxLoadingList,\n    ComboboxEmptyList,\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(COMBOBOX_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":["_sfc_main","DtCombobox","DtPopover","ComboboxLoadingList","ComboboxEmptyList","t","COMBOBOX_LABEL_SIZES","getUniqueString","padding","DROPDOWN_PADDING_CLASSES","item","contentWidth","POPOVER_CONTENT_WIDTHS","appendTo","POPOVER_APPEND_TO_VALUES","show","val","value","highlightIndex","opened","_a","popoverEl","_b","comboboxEl","_c","el"],"mappings":"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"}