UNPKG

vuetify

Version:

Vue.js 2 Semantic Component Framework

327 lines (294 loc) 8.91 kB
import { getObjectValueByPath } from '../../../util/helpers' import { consoleWarn } from '../../../util/console' /** * Select generators * * @mixin * * Used for creating the DOM elements for VSelect */ export default { methods: { genMenu () { const data = { ref: 'menu', props: { activator: this.$el, auto: this.auto, attach: this.attach && `[data-uid="${this._uid}"]`, closeOnClick: false, closeOnContentClick: !this.isMultiple, contentClass: this.computedContentClass, dark: this.dark, disabled: this.disabled, light: this.light, maxHeight: this.maxHeight, nudgeTop: this.nudgeTop, offsetY: this.shouldOffset, offsetOverflow: this.isAutocomplete, openOnClick: false, value: this.menuIsVisible, zIndex: this.menuZIndex }, on: { input: val => { if (!val) { this.menuIsActive = false } } } } if (this.isAutocomplete) data.props.transition = '' this.minWidth && (data.props.minWidth = this.minWidth) return this.$createElement('v-menu', data, [this.genList()]) }, getMenuIndex () { return this.$refs.menu ? this.$refs.menu.listIndex : -1 }, setMenuIndex (index) { this.$refs.menu && (this.$refs.menu.listIndex = index) }, resetMenuIndex () { this.setMenuIndex(-1) }, isMenuItemSelected () { return this.menuIsActive && this.menuItems.length && this.getMenuIndex() > -1 }, genSelectionsAndSearch () { return this.$createElement('div', { 'class': 'input-group__selections', style: { 'overflow': 'hidden' }, ref: 'activator' }, [ ...this.genSelections(), this.genSearch() ]) }, genSelections () { if (this.hideSelections) return [] let length = this.selectedItems.length const children = new Array(length) let genSelection if (this.$scopedSlots.selection) { genSelection = this.genSlotSelection } else if (this.chips) { genSelection = this.genChipSelection } else if (this.segmented) { genSelection = this.genSegmentedBtn } else { genSelection = this.genCommaSelection } while (length--) { children[length] = genSelection(this.selectedItems[length], length, length === children.length - 1) } return children }, genSearch () { const data = { staticClass: 'input-group--select__autocomplete', 'class': { 'input-group--select__autocomplete--index': this.selectedIndex > -1 }, style: { flex: this.shouldBreak ? '1 0 100%' : null }, attrs: { ...this.$attrs, disabled: this.disabled || !this.isAutocomplete, readonly: this.readonly, tabindex: this.disabled || !this.isAutocomplete ? -1 : this.tabindex }, domProps: { value: this.maskText(this.lazySearch || '') }, directives: [{ name: 'show', value: (this.isAutocomplete) || (this.placeholder && !this.selectedItems.length) }], ref: 'input', key: 'input' } if (this.isAutocomplete) { data.attrs.role = 'combobox' data.domProps.autocomplete = this.browserAutocomplete data.on = { ...this.genListeners(), input: e => { this.searchValue = this.unmaskText(e.target.value) } } data.directives = data.directives.concat(this.genDirectives()) } if (this.placeholder) data.domProps.placeholder = this.placeholder return this.$createElement('input', data) }, genSegmentedBtn (item) { if (!item.text || !item.callback) { consoleWarn('When using \'segmented\' prop without a selection slot, items must contain both a text and callback property', this) return null } return this.$createElement('v-btn', { props: { flat: true }, on: { click (e) { e.stopPropagation() item.callback(e) } } }, [item.text]) }, genSlotSelection (item, index) { return this.$scopedSlots.selection({ parent: this, item, index, selected: index === this.selectedIndex, disabled: this.disabled || this.readonly }) }, genChipSelection (item, index) { const isDisabled = this.disabled || this.readonly const click = e => { if (isDisabled) return e.stopPropagation() this.focusInput() this.selectedIndex = index } return this.$createElement('v-chip', { staticClass: 'chip--select-multi', attrs: { tabindex: '-1' }, props: { close: this.deletableChips && !isDisabled, dark: this.dark, disabled: isDisabled, selected: index === this.selectedIndex }, on: { click: click, focus: click, input: () => { if (this.isMultiple) this.selectItem(item) else this.inputValue = null } }, key: this.getValue(item) }, this.getText(item)) }, genCommaSelection (item, index, last) { return this.$createElement('div', { staticClass: 'input-group__selections__comma', 'class': { 'input-group__selections__comma--active': index === this.selectedIndex }, key: JSON.stringify(this.getValue(item)) // Item may be an object }, `${this.getText(item)}${last ? '' : ', '}`) }, genList () { const children = this.menuItems.map(o => { if (o.header) return this.genHeader(o) if (o.divider) return this.genDivider(o) else return this.genTile(o) }) if (!children.length) { const noData = this.$slots['no-data'] if (noData) { children.push(noData) } else { children.push(this.genTile(this.noDataText, true)) } } return this.$createElement('v-card', [ this.$createElement('v-list', { props: { dense: this.dense }, ref: 'list' }, children) ]) }, genHeader (item) { return this.$createElement('v-subheader', { props: item }, item.header) }, genDivider (item) { return this.$createElement('v-divider', { props: item }) }, genLabel () { const singleLine = this.singleLine || this.isDropdown if (singleLine && (this.isDirty || (this.isFocused && this.searchValue)) ) return null const data = {} if (this.id) data.attrs = { for: this.id } return this.$createElement('label', data, this.$slots.label || this.label) }, genTile (item, disabled) { const active = this.selectedItems.indexOf(item) !== -1 if (typeof disabled === 'undefined') { disabled = getObjectValueByPath(item, this.itemDisabled) } const data = { on: { click: e => { if (disabled) return this.selectItem(item) } }, props: { avatar: item === Object(item) && this.itemAvatar in item, ripple: true, value: active } } if (disabled) { data.props.disabled = disabled } data.props.activeClass = Object.keys(this.addTextColorClassChecks()).join(' ') if (this.$scopedSlots.item) { const tile = this.$scopedSlots.item({ parent: this, item, tile: data }) return this.needsTile(tile) ? this.$createElement('v-list-tile', data, [tile]) : tile } return this.$createElement('v-list-tile', data, [this.genAction(item, active), this.genContent(item)] ) }, genAction (item, active) { if (!this.isMultiple || this.isHidingSelected) return null const data = { staticClass: 'list__tile__action--select-multi', on: { click: e => { e.stopPropagation() this.selectItem(item) } } } return this.$createElement('v-list-tile-action', data, [ this.$createElement('v-checkbox', { props: { color: this.computedColor, inputValue: active } }) ]) }, genContent (item) { const text = this.getText(item) return this.$createElement('v-list-tile-content', [this.$createElement('v-list-tile-title', { domProps: { innerHTML: this.genFiltered(text) } })] ) } } }