vuetify
Version:
Vue.js 2 Semantic Component Framework
353 lines (319 loc) • 13.7 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; // Styles
// Components
// Mixins
// Utils
require('../../../src/stylus/components/_treeview.styl');
var _VTreeviewNode = require('./VTreeviewNode');
var _VTreeviewNode2 = _interopRequireDefault(_VTreeviewNode);
var _themeable = require('../../mixins/themeable');
var _themeable2 = _interopRequireDefault(_themeable);
var _registrable = require('../../mixins/registrable');
var _helpers = require('../../util/helpers');
var _mixins = require('../../util/mixins');
var _mixins2 = _interopRequireDefault(_mixins);
var _console = require('../../util/console');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function ston(s) {
var n = Number(s);
return !isNaN(n) ? n : s;
}
exports.default = (0, _mixins2.default)((0, _registrable.provide)('treeview'), _themeable2.default
/* @vue/component */
).extend({
name: 'v-treeview',
provide: function provide() {
return { treeview: this };
},
props: _extends({
active: {
type: Array,
default: function _default() {
return [];
}
},
items: {
type: Array,
default: function _default() {
return [];
}
},
hoverable: Boolean,
multipleActive: Boolean,
open: {
type: Array,
default: function _default() {
return [];
}
},
openAll: Boolean,
value: {
type: Array,
default: function _default() {
return [];
}
}
}, _VTreeviewNode.VTreeviewNodeProps),
data: function data() {
return {
nodes: {},
selectedCache: new Set(),
activeCache: new Set(),
openCache: new Set()
};
},
watch: {
items: {
handler: function handler() {
// We only care if nodes are removed or added
if (Object.keys(this.nodes).length === this.countItems(this.items)) return;
var oldSelectedCache = [].concat(_toConsumableArray(this.selectedCache));
this.selectedCache = new Set();
this.activeCache = new Set();
this.openCache = new Set();
this.buildTree(this.items);
// Only emit selected if selection has changed
// as a result of items changing. This fixes a
// potential double emit when selecting a node
// with dynamic children
if (!(0, _helpers.deepEqual)(oldSelectedCache, [].concat(_toConsumableArray(this.selectedCache)))) this.emitSelected();
},
deep: true
},
active: function active(value) {
var _this = this;
var old = [].concat(_toConsumableArray(this.activeCache));
if (!value || (0, _helpers.deepEqual)(old, value)) return;
old.forEach(function (key) {
return _this.updateActive(key, false);
});
value.forEach(function (key) {
return _this.updateActive(key, true);
});
this.emitActive();
},
value: function value(_value) {
var _this2 = this;
var old = [].concat(_toConsumableArray(this.selectedCache));
if (!_value || (0, _helpers.deepEqual)(old, _value)) return;
old.forEach(function (key) {
return _this2.updateSelected(key, false);
});
_value.forEach(function (key) {
return _this2.updateSelected(key, true);
});
this.emitSelected();
},
open: function open(value) {
var _this3 = this;
var old = [].concat(_toConsumableArray(this.openCache));
if ((0, _helpers.deepEqual)(old, value)) return;
old.forEach(function (key) {
return _this3.updateOpen(key, false);
});
value.forEach(function (key) {
return _this3.updateOpen(key, true);
});
this.emitOpen();
}
},
created: function created() {
var _this4 = this;
this.buildTree(this.items);
this.value.forEach(function (key) {
return _this4.updateSelected(key, true);
});
this.emitSelected();
this.active.forEach(function (key) {
return _this4.updateActive(key, true);
});
this.emitActive();
},
mounted: function mounted() {
var _this5 = this;
// Save the developer from themselves
if (this.$slots.prepend || this.$slots.append) {
(0, _console.consoleWarn)('The prepend and append slots require a slot-scope attribute', this);
}
if (this.openAll) {
Object.keys(this.nodes).forEach(function (key) {
return _this5.updateOpen(ston(key), true);
});
} else {
this.open.forEach(function (key) {
return _this5.updateOpen(key, true);
});
}
this.emitOpen();
},
methods: {
buildTree: function buildTree(items) {
var _this6 = this;
var parent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
for (var i = 0; i < items.length; i++) {
var item = items[i];
var key = (0, _helpers.getObjectValueByPath)(item, this.itemKey);
var children = (0, _helpers.getObjectValueByPath)(item, this.itemChildren, []);
var oldNode = this.nodes.hasOwnProperty(key) ? this.nodes[key] : {
isSelected: false, isIndeterminate: false, isActive: false, isOpen: false, vnode: null
};
var node = {
vnode: oldNode.vnode,
parent: parent,
children: children.map(function (c) {
return (0, _helpers.getObjectValueByPath)(c, _this6.itemKey);
})
};
this.buildTree(children, key);
// This fixed bug with dynamic children resetting selected parent state
if (!this.nodes.hasOwnProperty(key) && parent !== null && this.nodes.hasOwnProperty(parent)) {
node.isSelected = this.nodes[parent].isSelected;
node.isIndeterminate = this.nodes[parent].isIndeterminate;
} else {
node.isSelected = oldNode.isSelected;
node.isIndeterminate = oldNode.isIndeterminate;
}
node.isActive = oldNode.isActive;
node.isOpen = oldNode.isOpen;
this.nodes[key] = !children.length ? node : this.calculateState(node, this.nodes);
// Don't forget to rebuild cache
if (this.nodes[key].isSelected) this.selectedCache.add(key);
if (this.nodes[key].isActive) this.activeCache.add(key);
if (this.nodes[key].isOpen) this.openCache.add(key);
this.updateVnodeState(key);
}
},
countItems: function countItems(items) {
var count = 0;
for (var i = 0; i < items.length; i++) {
var item = items[i];
count += 1;
count += item.children ? this.countItems(item.children) : 0;
}
return count;
},
calculateState: function calculateState(node, state) {
var counts = node.children.reduce(function (counts, child) {
counts[0] += +Boolean(state[child].isSelected);
counts[1] += +Boolean(state[child].isIndeterminate);
return counts;
}, [0, 0]);
node.isSelected = !!node.children.length && counts[0] === node.children.length;
node.isIndeterminate = !node.isSelected && (counts[0] > 0 || counts[1] > 0);
return node;
},
emitOpen: function emitOpen() {
this.$emit('update:open', [].concat(_toConsumableArray(this.openCache)));
},
emitSelected: function emitSelected() {
this.$emit('input', [].concat(_toConsumableArray(this.selectedCache)));
},
emitActive: function emitActive() {
this.$emit('update:active', [].concat(_toConsumableArray(this.activeCache)));
},
getDescendants: function getDescendants(key) {
var _descendants;
var descendants = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var children = this.nodes[key].children;
(_descendants = descendants).push.apply(_descendants, _toConsumableArray(children));
for (var i = 0; i < children.length; i++) {
descendants = this.getDescendants(children[i], descendants);
}
return descendants;
},
getParents: function getParents(key) {
var parent = this.nodes[key].parent;
var parents = [];
while (parent !== null) {
parents.push(parent);
parent = this.nodes[parent].parent;
}
return parents;
},
register: function register(node) {
var key = (0, _helpers.getObjectValueByPath)(node.item, this.itemKey);
this.nodes[key].vnode = node;
this.updateVnodeState(key);
},
unregister: function unregister(node) {
var key = (0, _helpers.getObjectValueByPath)(node.item, this.itemKey);
this.nodes[key].vnode = null;
},
updateActive: function updateActive(key, isActive) {
var _this7 = this;
if (!this.nodes.hasOwnProperty(key)) return;
if (!this.multipleActive) {
this.activeCache.forEach(function (active) {
_this7.nodes[active].isActive = false;
_this7.updateVnodeState(active);
_this7.activeCache.delete(active);
});
}
var node = this.nodes[key];
if (!node) return;
if (isActive) this.activeCache.add(key);else this.activeCache.delete(key);
node.isActive = isActive;
this.updateVnodeState(key);
},
updateSelected: function updateSelected(key, isSelected) {
var _this8 = this;
if (!this.nodes.hasOwnProperty(key)) return;
var changed = {};
var descendants = [key].concat(_toConsumableArray(this.getDescendants(key)));
descendants.forEach(function (descendant) {
_this8.nodes[descendant].isSelected = isSelected;
_this8.nodes[descendant].isIndeterminate = false;
changed[descendant] = isSelected;
});
var parents = this.getParents(key);
parents.forEach(function (parent) {
_this8.nodes[parent] = _this8.calculateState(_this8.nodes[parent], _this8.nodes);
changed[parent] = _this8.nodes[parent].isSelected;
});
var all = [key].concat(_toConsumableArray(descendants), _toConsumableArray(parents));
all.forEach(this.updateVnodeState);
Object.keys(changed).forEach(function (k) {
changed[k] === true ? _this8.selectedCache.add(ston(k)) : _this8.selectedCache.delete(ston(k));
});
},
updateOpen: function updateOpen(key, isOpen) {
var _this9 = this;
if (!this.nodes.hasOwnProperty(key)) return;
var node = this.nodes[key];
if (node.children && !node.children.length && node.vnode && !node.vnode.hasLoaded) {
node.vnode.checkChildren().then(function () {
return _this9.updateOpen(key, isOpen);
});
} else {
node.isOpen = isOpen;
node.isOpen ? this.openCache.add(key) : this.openCache.delete(key);
this.updateVnodeState(key);
}
},
updateVnodeState: function updateVnodeState(key) {
var node = this.nodes[key];
if (node && node.vnode) {
node.vnode.isSelected = node.isSelected;
node.vnode.isIndeterminate = node.isIndeterminate;
node.vnode.isActive = node.isActive;
node.vnode.isOpen = node.isOpen;
}
}
},
render: function render(h) {
var children = this.items.length ? this.items.map(_VTreeviewNode2.default.options.methods.genChild.bind(this))
/* istanbul ignore next */
: this.$slots.default;
return h('div', {
staticClass: 'v-treeview',
class: _extends({
'v-treeview--hoverable': this.hoverable
}, this.themeClasses)
}, children);
}
});
//# sourceMappingURL=VTreeview.js.map