214 lines
5.6 KiB
JavaScript
214 lines
5.6 KiB
JavaScript
|
// Styles
|
||
|
import "../../../src/components/VItemGroup/VItemGroup.sass";
|
||
|
import Proxyable from '../../mixins/proxyable';
|
||
|
import Themeable from '../../mixins/themeable'; // Utilities
|
||
|
|
||
|
import mixins from '../../util/mixins';
|
||
|
import { consoleWarn } from '../../util/console';
|
||
|
export const BaseItemGroup = mixins(Proxyable, Themeable).extend({
|
||
|
name: 'base-item-group',
|
||
|
props: {
|
||
|
activeClass: {
|
||
|
type: String,
|
||
|
default: 'v-item--active'
|
||
|
},
|
||
|
mandatory: Boolean,
|
||
|
max: {
|
||
|
type: [Number, String],
|
||
|
default: null
|
||
|
},
|
||
|
multiple: Boolean
|
||
|
},
|
||
|
|
||
|
data() {
|
||
|
return {
|
||
|
// As long as a value is defined, show it
|
||
|
// Otherwise, check if multiple
|
||
|
// to determine which default to provide
|
||
|
internalLazyValue: this.value !== undefined ? this.value : this.multiple ? [] : undefined,
|
||
|
items: []
|
||
|
};
|
||
|
},
|
||
|
|
||
|
computed: {
|
||
|
classes() {
|
||
|
return {
|
||
|
'v-item-group': true,
|
||
|
...this.themeClasses
|
||
|
};
|
||
|
},
|
||
|
|
||
|
selectedItem() {
|
||
|
if (this.multiple) return undefined;
|
||
|
return this.items.find((item, index) => {
|
||
|
return this.toggleMethod(this.getValue(item, index));
|
||
|
});
|
||
|
},
|
||
|
|
||
|
selectedItems() {
|
||
|
return this.items.filter((item, index) => {
|
||
|
return this.toggleMethod(this.getValue(item, index));
|
||
|
});
|
||
|
},
|
||
|
|
||
|
selectedValues() {
|
||
|
if (this.internalValue == null) return [];
|
||
|
return Array.isArray(this.internalValue) ? this.internalValue : [this.internalValue];
|
||
|
},
|
||
|
|
||
|
toggleMethod() {
|
||
|
if (!this.multiple) {
|
||
|
return v => this.internalValue === v;
|
||
|
}
|
||
|
|
||
|
const internalValue = this.internalValue;
|
||
|
|
||
|
if (Array.isArray(internalValue)) {
|
||
|
return v => internalValue.includes(v);
|
||
|
}
|
||
|
|
||
|
return () => false;
|
||
|
}
|
||
|
|
||
|
},
|
||
|
watch: {
|
||
|
internalValue() {
|
||
|
// https://github.com/vuetifyjs/vuetify/issues/5352
|
||
|
this.$nextTick(this.updateItemsState);
|
||
|
}
|
||
|
|
||
|
},
|
||
|
|
||
|
created() {
|
||
|
if (this.multiple && !Array.isArray(this.internalValue)) {
|
||
|
consoleWarn('Model must be bound to an array if the multiple property is true.', this);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
methods: {
|
||
|
genData() {
|
||
|
return {
|
||
|
class: this.classes
|
||
|
};
|
||
|
},
|
||
|
|
||
|
getValue(item, i) {
|
||
|
return item.value == null || item.value === '' ? i : item.value;
|
||
|
},
|
||
|
|
||
|
onClick(item) {
|
||
|
this.updateInternalValue(this.getValue(item, this.items.indexOf(item)));
|
||
|
},
|
||
|
|
||
|
register(item) {
|
||
|
const index = this.items.push(item) - 1;
|
||
|
item.$on('change', () => this.onClick(item)); // If no value provided and mandatory,
|
||
|
// assign first registered item
|
||
|
|
||
|
if (this.mandatory && this.internalLazyValue == null) {
|
||
|
this.updateMandatory();
|
||
|
}
|
||
|
|
||
|
this.updateItem(item, index);
|
||
|
},
|
||
|
|
||
|
unregister(item) {
|
||
|
if (this._isDestroyed) return;
|
||
|
const index = this.items.indexOf(item);
|
||
|
const value = this.getValue(item, index);
|
||
|
this.items.splice(index, 1);
|
||
|
const valueIndex = this.selectedValues.indexOf(value); // Items is not selected, do nothing
|
||
|
|
||
|
if (valueIndex < 0) return; // If not mandatory, use regular update process
|
||
|
|
||
|
if (!this.mandatory) {
|
||
|
return this.updateInternalValue(value);
|
||
|
} // Remove the value
|
||
|
|
||
|
|
||
|
if (this.multiple && Array.isArray(this.internalValue)) {
|
||
|
this.internalValue = this.internalValue.filter(v => v !== value);
|
||
|
} else {
|
||
|
this.internalValue = undefined;
|
||
|
} // If mandatory and we have no selection
|
||
|
// add the last item as value
|
||
|
|
||
|
/* istanbul ignore else */
|
||
|
|
||
|
|
||
|
if (!this.selectedItems.length) {
|
||
|
this.updateMandatory(true);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
updateItem(item, index) {
|
||
|
const value = this.getValue(item, index);
|
||
|
item.isActive = this.toggleMethod(value);
|
||
|
},
|
||
|
|
||
|
updateItemsState() {
|
||
|
if (this.mandatory && !this.selectedItems.length) {
|
||
|
return this.updateMandatory();
|
||
|
} // TODO: Make this smarter so it
|
||
|
// doesn't have to iterate every
|
||
|
// child in an update
|
||
|
|
||
|
|
||
|
this.items.forEach(this.updateItem);
|
||
|
},
|
||
|
|
||
|
updateInternalValue(value) {
|
||
|
this.multiple ? this.updateMultiple(value) : this.updateSingle(value);
|
||
|
},
|
||
|
|
||
|
updateMandatory(last) {
|
||
|
if (!this.items.length) return;
|
||
|
const items = this.items.slice();
|
||
|
if (last) items.reverse();
|
||
|
const item = items.find(item => !item.disabled); // If no tabs are available
|
||
|
// aborts mandatory value
|
||
|
|
||
|
if (!item) return;
|
||
|
const index = this.items.indexOf(item);
|
||
|
this.updateInternalValue(this.getValue(item, index));
|
||
|
},
|
||
|
|
||
|
updateMultiple(value) {
|
||
|
const defaultValue = Array.isArray(this.internalValue) ? this.internalValue : [];
|
||
|
const internalValue = defaultValue.slice();
|
||
|
const index = internalValue.findIndex(val => val === value);
|
||
|
if (this.mandatory && // Item already exists
|
||
|
index > -1 && // value would be reduced below min
|
||
|
internalValue.length - 1 < 1) return;
|
||
|
if ( // Max is set
|
||
|
this.max != null && // Item doesn't exist
|
||
|
index < 0 && // value would be increased above max
|
||
|
internalValue.length + 1 > this.max) return;
|
||
|
index > -1 ? internalValue.splice(index, 1) : internalValue.push(value);
|
||
|
this.internalValue = internalValue;
|
||
|
},
|
||
|
|
||
|
updateSingle(value) {
|
||
|
const isSame = value === this.internalValue;
|
||
|
if (this.mandatory && isSame) return;
|
||
|
this.internalValue = isSame ? undefined : value;
|
||
|
}
|
||
|
|
||
|
},
|
||
|
|
||
|
render(h) {
|
||
|
return h('div', this.genData(), this.$slots.default);
|
||
|
}
|
||
|
|
||
|
});
|
||
|
export default BaseItemGroup.extend({
|
||
|
name: 'v-item-group',
|
||
|
|
||
|
provide() {
|
||
|
return {
|
||
|
itemGroup: this
|
||
|
};
|
||
|
}
|
||
|
|
||
|
});
|
||
|
//# sourceMappingURL=VItemGroup.js.map
|