UNPKG

buefy

Version:

Lightweight UI components for Vue.js based on Bulma

393 lines (342 loc) 13.5 kB
import { _ as _defineProperty, a as _typeof } from './chunk-d6200087.js'; import { g as getValueByPath } from './chunk-e5fce48f.js'; import { F as FormElementMixin } from './chunk-591ee4a2.js'; import { _ as __vue_normalize__ } from './chunk-e8d90b72.js'; import { I as Input } from './chunk-b56eb2c8.js'; var script = { name: 'BAutocomplete', components: _defineProperty({}, Input.name, Input), mixins: [FormElementMixin], inheritAttrs: false, props: { value: [Number, String], data: { type: Array, default: function _default() { return []; } }, field: { type: String, default: 'value' }, keepFirst: Boolean, clearOnSelect: Boolean, openOnFocus: Boolean, customFormatter: Function }, data: function data() { return { selected: null, hovered: null, isActive: false, newValue: this.value, newAutocomplete: this.autocomplete || 'off', isListInViewportVertically: true, hasFocus: false, _isAutocomplete: true, _elementRef: 'input' }; }, computed: { /** * White-listed items to not close when clicked. * Add input, dropdown and all children. */ whiteList: function whiteList() { var whiteList = []; whiteList.push(this.$refs.input.$el.querySelector('input')); whiteList.push(this.$refs.dropdown); // Add all chidren from dropdown if (this.$refs.dropdown !== undefined) { var children = this.$refs.dropdown.querySelectorAll('*'); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = children[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var child = _step.value; whiteList.push(child); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } return whiteList; }, /** * Check if exists default slot */ hasDefaultSlot: function hasDefaultSlot() { return !!this.$scopedSlots.default; }, /** * Check if exists "empty" slot */ hasEmptySlot: function hasEmptySlot() { return !!this.$slots.empty; }, /** * Check if exists "header" slot */ hasHeaderSlot: function hasHeaderSlot() { return !!this.$slots.header; }, /** * Check if exists "footer" slot */ hasFooterSlot: function hasFooterSlot() { return !!this.$slots.footer; } }, watch: { /** * When dropdown is toggled, check the visibility to know when * to open upwards. */ isActive: function isActive(active) { var _this = this; if (active) { this.calcDropdownInViewportVertical(); } else { this.$nextTick(function () { return _this.setHovered(null); }); // Timeout to wait for the animation to finish before recalculating setTimeout(function () { _this.calcDropdownInViewportVertical(); }, 100); } }, /** * When updating input's value * 1. Emit changes * 2. If value isn't the same as selected, set null * 3. Close dropdown if value is clear or else open it */ newValue: function newValue(value) { this.$emit('input', value); // Check if selected is invalid var currentValue = this.getValue(this.selected); if (currentValue && currentValue !== value) { this.setSelected(null, false); } // Close dropdown if input is clear or else open it if (this.hasFocus && (!this.openOnFocus || value)) { this.isActive = !!value; } }, /** * When v-model is changed: * 1. Update internal value. * 2. If it's invalid, validate again. */ value: function value(_value) { this.newValue = _value; !this.isValid && this.$refs.input.checkHtml5Validity(); }, /** * Select first option if "keep-first */ data: function data(value) { // Keep first option always pre-selected if (this.keepFirst) { this.selectFirstOption(value); } } }, methods: { /** * Set which option is currently hovered. */ setHovered: function setHovered(option) { if (option === undefined) return; this.hovered = option; }, /** * Set which option is currently selected, update v-model, * update input value and close dropdown. */ setSelected: function setSelected(option) { var _this2 = this; var closeDropdown = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; if (option === undefined) return; this.selected = option; this.$emit('select', this.selected); if (this.selected !== null) { this.newValue = this.clearOnSelect ? '' : this.getValue(this.selected); } closeDropdown && this.$nextTick(function () { _this2.isActive = false; }); }, /** * Select first option */ selectFirstOption: function selectFirstOption(options) { var _this3 = this; this.$nextTick(function () { if (options.length) { // If has visible data or open on focus, keep updating the hovered if (_this3.openOnFocus || _this3.newValue !== '' && _this3.hovered !== options[0]) { _this3.setHovered(options[0]); } } else { _this3.setHovered(null); } }); }, /** * Enter key listener. * Select the hovered option. */ enterPressed: function enterPressed() { if (this.hovered === null) return; this.setSelected(this.hovered); }, /** * Tab key listener. * Select hovered option if it exists, close dropdown, then allow * native handling to move to next tabbable element. */ tabPressed: function tabPressed() { if (this.hovered === null) { this.isActive = false; return; } this.setSelected(this.hovered); }, /** * Close dropdown if clicked outside. */ clickedOutside: function clickedOutside(event) { if (this.whiteList.indexOf(event.target) < 0) this.isActive = false; }, /** * Return display text for the input. * If object, get value from path, or else just the value. */ getValue: function getValue(option) { if (!option) return; if (typeof this.customFormatter !== 'undefined') { return this.customFormatter(option); } return _typeof(option) === 'object' ? getValueByPath(option, this.field) : option; }, /** * Calculate if the dropdown is vertically visible when activated, * otherwise it is openened upwards. */ calcDropdownInViewportVertical: function calcDropdownInViewportVertical() { var _this4 = this; this.$nextTick(function () { /** * this.$refs.dropdown may be undefined * when Autocomplete is conditional rendered */ if (_this4.$refs.dropdown === undefined) return; var rect = _this4.$refs.dropdown.getBoundingClientRect(); _this4.isListInViewportVertically = rect.top >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight); }); }, /** * Arrows keys listener. * If dropdown is active, set hovered option, or else just open. */ keyArrows: function keyArrows(direction) { var sum = direction === 'down' ? 1 : -1; if (this.isActive) { var index = this.data.indexOf(this.hovered) + sum; index = index > this.data.length - 1 ? this.data.length : index; index = index < 0 ? 0 : index; this.setHovered(this.data[index]); var list = this.$refs.dropdown.querySelector('.dropdown-content'); var element = list.querySelectorAll('a.dropdown-item:not(.is-disabled)')[index]; if (!element) return; var visMin = list.scrollTop; var visMax = list.scrollTop + list.clientHeight - element.clientHeight; if (element.offsetTop < visMin) { list.scrollTop = element.offsetTop; } else if (element.offsetTop >= visMax) { list.scrollTop = element.offsetTop - list.clientHeight + element.clientHeight; } } else { this.isActive = true; } }, /** * Focus listener. * If value is the same as selected, select all text. */ focused: function focused(event) { if (this.getValue(this.selected) === this.newValue) { this.$el.querySelector('input').select(); } if (this.openOnFocus) { this.isActive = true; if (this.keepFirst) { this.selectFirstOption(this.data); } } this.hasFocus = true; this.$emit('focus', event); }, /** * Blur listener. */ onBlur: function onBlur(event) { this.hasFocus = false; this.$emit('blur', event); }, onInput: function onInput(event) { var currentValue = this.getValue(this.selected); if (currentValue && currentValue === this.newValue) return; this.$emit('typing', this.newValue); } }, created: function created() { if (typeof window !== 'undefined') { document.addEventListener('click', this.clickedOutside); window.addEventListener('resize', this.calcDropdownInViewportVertical); } }, beforeDestroy: function beforeDestroy() { if (typeof window !== 'undefined') { document.removeEventListener('click', this.clickedOutside); window.removeEventListener('resize', this.calcDropdownInViewportVertical); } } }; /* 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:"autocomplete control",class:{'is-expanded': _vm.expanded}},[_c('b-input',_vm._b({ref:"input",attrs:{"type":"text","size":_vm.size,"loading":_vm.loading,"rounded":_vm.rounded,"icon":_vm.icon,"icon-pack":_vm.iconPack,"maxlength":_vm.maxlength,"autocomplete":_vm.newAutocomplete,"use-html5-validation":_vm.useHtml5Validation},on:{"input":_vm.onInput,"focus":_vm.focused,"blur":_vm.onBlur},nativeOn:{"keyup":function($event){if(!('button' in $event)&&_vm._k($event.keyCode,"esc",27,$event.key)){ return null; }$event.preventDefault();_vm.isActive = false;},"keydown":[function($event){if(!('button' in $event)&&_vm._k($event.keyCode,"tab",9,$event.key)){ return null; }_vm.tabPressed($event);},function($event){if(!('button' in $event)&&_vm._k($event.keyCode,"enter",13,$event.key)){ return null; }$event.preventDefault();_vm.enterPressed($event);},function($event){if(!('button' in $event)&&_vm._k($event.keyCode,"up",38,$event.key)){ return null; }$event.preventDefault();_vm.keyArrows('up');},function($event){if(!('button' in $event)&&_vm._k($event.keyCode,"down",40,$event.key)){ return null; }$event.preventDefault();_vm.keyArrows('down');}]},model:{value:(_vm.newValue),callback:function ($$v) {_vm.newValue=$$v;},expression:"newValue"}},'b-input',_vm.$attrs,false)),_vm._v(" "),_c('transition',{attrs:{"name":"fade"}},[_c('div',{directives:[{name:"show",rawName:"v-show",value:(_vm.isActive && (_vm.data.length > 0 || _vm.hasEmptySlot || _vm.hasHeaderSlot)),expression:"isActive && (data.length > 0 || hasEmptySlot || hasHeaderSlot)"}],ref:"dropdown",staticClass:"dropdown-menu",class:{ 'is-opened-top': !_vm.isListInViewportVertically }},[_c('div',{directives:[{name:"show",rawName:"v-show",value:(_vm.isActive),expression:"isActive"}],staticClass:"dropdown-content"},[(_vm.hasHeaderSlot)?_c('div',{staticClass:"dropdown-item"},[_vm._t("header")],2):_vm._e(),_vm._v(" "),_vm._l((_vm.data),function(option,index){return _c('a',{key:index,staticClass:"dropdown-item",class:{ 'is-hovered': option === _vm.hovered },on:{"click":function($event){_vm.setSelected(option);}}},[(_vm.hasDefaultSlot)?_vm._t("default",null,{option:option,index:index}):_c('span',[_vm._v("\n "+_vm._s(_vm.getValue(option, true))+"\n ")])],2)}),_vm._v(" "),(_vm.data.length === 0 && _vm.hasEmptySlot)?_c('div',{staticClass:"dropdown-item is-disabled"},[_vm._t("empty")],2):_vm._e(),_vm._v(" "),(_vm.hasFooterSlot)?_c('div',{staticClass:"dropdown-item"},[_vm._t("footer")],2):_vm._e()],2)])])],1)}; 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 */ var Autocomplete = __vue_normalize__( { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, undefined, undefined ); export { Autocomplete as A };