UNPKG

@gitlab/ui

Version:
224 lines (211 loc) • 8.5 kB
import uniqueId from 'lodash/uniqueId'; import GlDropdownItem from '../dropdown/dropdown_item'; import { tokensValidator } from './helpers'; import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js'; var script = { name: 'GlTokenSelectorDropdown', components: { GlDropdownItem }, props: { show: { type: Boolean, required: true }, menuClass: { type: [String, Array, Object], required: false, default: '' }, loading: { type: Boolean, required: false, default: false }, dropdownItems: { type: Array, // All items need to have an `id` key validator: tokensValidator, required: true }, inputText: { type: String, required: true }, userDefinedTokenCanBeAdded: { type: Boolean, required: true }, componentId: { type: String, required: true }, registerDropdownEventHandlers: { type: Function, required: true }, registerResetFocusedDropdownItem: { type: Function, required: true } }, data() { return { focusedDropdownItemIndex: 0 }; }, computed: { userDefinedToken() { return { id: uniqueId('user-defined-token'), name: this.inputText }; }, dropdownLength() { // Adds an additional dropdown item for the 'Add ... dropdown' item return this.userDefinedTokenCanBeAdded ? this.dropdownItems.length : this.dropdownItems.length - 1; }, focusedLastDropdownItem() { return this.focusedDropdownItemIndex === this.dropdownLength; }, focusedUserDefinedToken() { // User defined tokens are always the last in the list return this.userDefinedTokenCanBeAdded && this.focusedLastDropdownItem; }, focusedDropdownItem() { if (this.focusedUserDefinedToken) { return this.userDefinedToken; } return this.dropdownItems[this.focusedDropdownItemIndex]; } }, watch: { focusedDropdownItem(newValue, oldValue) { if ((newValue === null || newValue === void 0 ? void 0 : newValue.id) !== (oldValue === null || oldValue === void 0 ? void 0 : oldValue.id)) { this.$emit('input', newValue); if (!newValue) { return; } const dropdownItemRef = this.getDropdownItemRef(newValue); if (dropdownItemRef !== null && dropdownItemRef !== void 0 && dropdownItemRef.$el) { dropdownItemRef.$el.scrollIntoView({ block: 'nearest', inline: 'end' }); } } } }, created() { this.registerDropdownEventHandlers({ handleUpArrow: this.handleUpArrow, handleDownArrow: this.handleDownArrow, handleHomeKey: this.handleHomeKey, handleEndKey: this.handleEndKey }); this.registerResetFocusedDropdownItem(this.resetFocusedDropdownItem); this.$emit('input', this.focusedDropdownItem); }, methods: { handleDropdownItemClick(dropdownItem) { this.$emit('dropdown-item-click', dropdownItem); }, handleMousedown(dropdownItem) { // `event.relatedTarget` returns `null` on Safari because buttons are not focused on click (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus) // Because of this we need to manually focus on the button. We do this in `mousedown` because it is fired before the `blur` event const dropdownItemRef = this.getDropdownItemRef(dropdownItem); if (dropdownItemRef !== null && dropdownItemRef !== void 0 && dropdownItemRef.$el) { dropdownItemRef.$el.querySelector('button').focus(); } }, handleUpArrow() { if (!this.show) { return; } // First dropdown item has been reached if (this.focusedDropdownItemIndex === 0) { return; } this.focusPrevDropdownItem(); }, handleDownArrow() { if (!this.show) { this.$emit('show'); return; } // Last dropdown item has been reached if (this.focusedLastDropdownItem) { return; } this.focusNextDropdownItem(); }, handleHomeKey(event) { event.preventDefault(); this.focusFirstDropdownItem(); }, handleEndKey(event) { event.preventDefault(); this.focusLastDropdownItem(); }, focusLastDropdownItem() { this.focusedDropdownItemIndex = this.dropdownLength; }, focusFirstDropdownItem() { this.focusedDropdownItemIndex = 0; }, focusNextDropdownItem() { this.focusedDropdownItemIndex += 1; }, focusPrevDropdownItem() { this.focusedDropdownItemIndex -= 1; }, resetFocusedDropdownItem() { this.focusedDropdownItemIndex = 0; }, dropdownItemIsFocused(dropdownItem) { if (!this.focusedDropdownItem) { return false; } return dropdownItem.id === this.focusedDropdownItem.id; }, getDropdownItemRef(dropdownItem) { var _this$$refs$dropdownI; if (this.focusedUserDefinedToken) { return this.$refs[this.userDefinedToken.id]; } return (_this$$refs$dropdownI = this.$refs.dropdownItems) === null || _this$$refs$dropdownI === void 0 ? void 0 : _this$$refs$dropdownI.find(ref => ref.$attrs['data-dropdown-item-id'] === dropdownItem.id); }, dropdownItemIdAttribute(dropdownItem) { return dropdownItem ? `${this.componentId}-dropdown-item-${dropdownItem.id}` : null; } } }; /* script */ const __vue_script__ = script; /* template */ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"dropdown b-dropdown gl-dropdown gl-relative",class:{ show: _vm.show }},[_c('ul',{ref:"dropdownMenu",staticClass:"dropdown-menu gl-absolute",class:[{ show: _vm.show }, _vm.menuClass],attrs:{"role":"menu","aria-activedescendant":_vm.dropdownItemIdAttribute(_vm.focusedDropdownItem)}},[(_vm.loading)?_c('gl-dropdown-item',{attrs:{"disabled":""}},[_vm._t("loading-content",function(){return [_vm._v("Searching...")]})],2):_vm._e(),_vm._v(" "),_vm._l((_vm.dropdownItems),function(dropdownItem){return _c('gl-dropdown-item',{key:dropdownItem.id,ref:"dropdownItems",refInFor:true,attrs:{"id":_vm.dropdownItemIdAttribute(dropdownItem),"data-dropdown-item-id":dropdownItem.id,"active":_vm.dropdownItemIsFocused(dropdownItem),"active-class":"is-focused","tabindex":"-1"},on:{"click":function($event){return _vm.handleDropdownItemClick(dropdownItem)}}},[_c('div',{staticClass:"-gl-mx-4 -gl-my-3 gl-px-4 gl-py-3",on:{"mousedown":function($event){return _vm.handleMousedown(dropdownItem)}}},[_vm._t("dropdown-item-content",function(){return [_vm._v("\n "+_vm._s(dropdownItem.name)+"\n ")]},{"dropdownItem":dropdownItem})],2)])}),_vm._v(" "),(_vm.userDefinedTokenCanBeAdded)?_c('gl-dropdown-item',{ref:_vm.userDefinedToken.id,attrs:{"id":_vm.dropdownItemIdAttribute(_vm.userDefinedToken),"data-dropdown-item-id":_vm.userDefinedToken.id,"active":_vm.dropdownItemIsFocused(_vm.userDefinedToken),"active-class":"is-focused","tabindex":"-1"},on:{"click":function($event){return _vm.handleDropdownItemClick(_vm.userDefinedToken)}}},[_c('div',{staticClass:"-gl-mx-4 -gl-my-3 gl-px-4 gl-py-3",on:{"mousedown":function($event){return _vm.handleMousedown(_vm.userDefinedToken)}}},[_vm._t("user-defined-token-content",function(){return [_vm._v("\n Add \""+_vm._s(_vm.inputText)+"\"\n ")]},{"inputText":_vm.inputText})],2)]):(!_vm.dropdownItems.length)?_c('gl-dropdown-item',{attrs:{"disabled":""}},[_vm._t("no-results-content",function(){return [_vm._v("No matches found")]})],2):_vm._e(),_vm._v(" "),_vm._t("dropdown-footer")],2)])}; var __vue_staticRenderFns__ = []; /* style */ const __vue_inject_styles__ = undefined; /* scoped */ const __vue_scope_id__ = undefined; /* module identifier */ const __vue_module_identifier__ = undefined; /* functional template */ const __vue_is_functional_template__ = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ const __vue_component__ = /*#__PURE__*/__vue_normalize__( { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, false, undefined, undefined, undefined ); export { __vue_component__ as default };