diff --git a/packages/vuetify/src/components/VTreeview/VTreeview.sass b/packages/vuetify/src/components/VTreeview/VTreeview.sass deleted file mode 100644 index 6bcb24ae90e..00000000000 --- a/packages/vuetify/src/components/VTreeview/VTreeview.sass +++ /dev/null @@ -1,128 +0,0 @@ -@import './_variables.scss' -@import './_mixins.sass' - -// Theme -@include theme(v-treeview) using ($material) - color: map-deep-get($material, 'text', 'primary') - - &--hoverable .v-treeview-node__root, - .v-treeview-node--click > .v-treeview-node__root - @include states($material) - - .v-treeview-node__root.v-treeview-node--active - @include active-states($material) - - .v-treeview-node--disabled - > .v-treeview-node__root > .v-treeview-node__content - color: map-deep-get($material, 'text', 'disabled') !important - -.v-treeview-node - &.v-treeview-node--shaped - @include treeview-shaped($treeview-node-height, $treeview-node-shaped-margin) - - &.v-treeview-node--rounded - @include treeview-rounded($treeview-node-height, $treeview-node-shaped-margin) - - &--click - > .v-treeview-node__root, - > .v-treeview-node__root > .v-treeview-node__content > * - cursor: pointer - user-select: none - - &.v-treeview-node--active .v-treeview-node__content .v-icon - color: inherit - -.v-treeview-node__root - display: flex - align-items: center - min-height: $treeview-node-height - padding-left: $treeview-node-padding - padding-right: $treeview-node-padding - position: relative - - &::before - background-color: currentColor - bottom: 0 - content: '' - left: 0 - opacity: 0 - pointer-events: none - position: absolute - right: 0 - top: 0 - transition: $primary-transition - - // Fix for IE11 where min-height does not work with - // align-items: center in flex containers - // https://github.com/philipwalton/flexbugs/issues/231 - &::after - content: '' - font-size: 0 - min-height: inherit - -.v-treeview-node__children - transition: all $treeview-transition - -.v-treeview--dense - .v-treeview-node__root - min-height: $treeview-node-height-dense - - &.v-treeview-node--shaped - @include treeview-shaped($treeview-node-height-dense, $treeview-node-shaped-margin) - - &.v-treeview-node--rounded - @include treeview-rounded($treeview-node-height-dense, $treeview-node-shaped-margin) - -.v-treeview-node__checkbox - width: $treeview-node-level-width - user-select: none - margin-inline-start: $treeview-node-margin - -.v-treeview-node__toggle - width: $treeview-node-level-width - user-select: none - - &--loading - animation: progress-circular-rotate 1s linear infinite - - @include ltr() - transform: rotate(-90deg) - &--open - transform: none - - @include rtl() - transform: rotate(90deg) - &--open - transform: none - -.v-treeview-node__prepend - min-width: $treeview-node-level-width - margin-inline-end: $treeview-node-margin - -.v-treeview-node__append - min-width: $treeview-node-level-width - margin-inline-start: $treeview-node-margin - -.v-treeview-node__level - width: $treeview-node-level-width - -.v-treeview-node__label - flex: 1 - font-size: $treeview-label-font-size - overflow: hidden - text-overflow: ellipsis - white-space: nowrap - -.v-treeview-node__content - align-items: center - display: flex - flex-basis: 0% - flex-grow: 1 - flex-shrink: 0 - min-width: 0 - margin-inline-start: $treeview-node-margin - - // TODO: this is temporary fix for d-flex * shenanigans - .v-btn - flex-grow: 0 !important - flex-shrink: 1 !important diff --git a/packages/vuetify/src/components/VTreeview/VTreeview.ts b/packages/vuetify/src/components/VTreeview/VTreeview.ts deleted file mode 100644 index 0c5b0feed73..00000000000 --- a/packages/vuetify/src/components/VTreeview/VTreeview.ts +++ /dev/null @@ -1,441 +0,0 @@ -// @ts-nocheck -/* eslint-disable */ - -// Styles -import './VTreeview.sass' - -// Types -import { VNode, VNodeChildrenArrayContents, PropType } from 'vue' -import { PropValidator } from 'vue/types/options' -import { TreeviewItemFunction } from 'vuetify/types' - -// Components -import VTreeviewNode, { VTreeviewNodeProps } from './VTreeviewNode' - -// Mixins -import Themeable from '../../mixins/themeable' -import { provide as RegistrableProvide } from '../../mixins/registrable' - -// Utils -import { - arrayDiff, - deepEqual, - getObjectValueByPath, -} from '../../util/helpers' -import mixins from '../../util/mixins' -import { consoleWarn } from '../../util/console' -import { - filterTreeItems, - filterTreeItem, -} from './util/filterTreeItems' - -type VTreeviewNodeInstance = InstanceType - -type NodeCache = Set -type NodeArray = (string | number)[] - -type NodeState = { - parent: number | string | null - children: (number | string)[] - vnode: VTreeviewNodeInstance | null - isActive: boolean - isSelected: boolean - isIndeterminate: boolean - isOpen: boolean - item: any -} - -export default mixins( - RegistrableProvide('treeview'), - Themeable - /* @vue/component */ -).extend({ - name: 'v-treeview', - - provide (): object { - return { treeview: this } - }, - - props: { - active: { - type: Array, - default: () => ([]), - } as PropValidator, - dense: Boolean, - disabled: Boolean, - filter: Function as PropType, - hoverable: Boolean, - items: { - type: Array, - default: () => ([]), - } as PropValidator, - multipleActive: Boolean, - open: { - type: Array, - default: () => ([]), - } as PropValidator, - openAll: Boolean, - returnObject: { - type: Boolean, - default: false, // TODO: Should be true in next major - }, - search: String, - value: { - type: Array, - default: () => ([]), - } as PropValidator, - ...VTreeviewNodeProps, - }, - - data: () => ({ - level: -1, - activeCache: new Set() as NodeCache, - nodes: {} as Record, - openCache: new Set() as NodeCache, - selectedCache: new Set() as NodeCache, - }), - - computed: { - excludedItems (): Set { - const excluded = new Set() - - if (!this.search) return excluded - - for (let i = 0; i < this.items.length; i++) { - filterTreeItems( - this.filter || filterTreeItem, - this.items[i], - this.search, - this.itemKey, - this.itemText, - this.itemChildren, - excluded - ) - } - - return excluded - }, - }, - - watch: { - items: { - handler () { - const oldKeys = Object.keys(this.nodes).map(k => getObjectValueByPath(this.nodes[k].item, this.itemKey)) - const newKeys = this.getKeys(this.items) - const diff = arrayDiff(newKeys, oldKeys) - - // We only want to do stuff if items have changed - if (!diff.length && newKeys.length < oldKeys.length) return - - // If nodes are removed we need to clear them from this.nodes - diff.forEach(k => delete this.nodes[k]) - - const oldSelectedCache = [...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 (!deepEqual(oldSelectedCache, [...this.selectedCache])) this.emitSelected() - }, - deep: true, - }, - active (value: (string | number | any)[]) { - this.handleNodeCacheWatcher(value, this.activeCache, this.updateActive, this.emitActive) - }, - value (value: (string | number | any)[]) { - this.handleNodeCacheWatcher(value, this.selectedCache, this.updateSelected, this.emitSelected) - }, - open (value: (string | number | any)[]) { - this.handleNodeCacheWatcher(value, this.openCache, this.updateOpen, this.emitOpen) - }, - }, - - created () { - const getValue = (key: string | number) => this.returnObject ? getObjectValueByPath(key, this.itemKey) : key - - this.buildTree(this.items) - - for (const value of this.value.map(getValue)) { - this.updateSelected(value, true, true) - } - - for (const active of this.active.map(getValue)) { - this.updateActive(active, true) - } - }, - - mounted () { - // Save the developer from themselves - if (this.$slots.prepend || this.$slots.append) { - consoleWarn('The prepend and append slots require a slot-scope attribute', this) - } - - if (this.openAll) { - this.updateAll(true) - } else { - this.open.forEach(key => this.updateOpen(this.returnObject ? getObjectValueByPath(key, this.itemKey) : key, true)) - this.emitOpen() - } - }, - - methods: { - /** @public */ - updateAll (value: boolean) { - Object.keys(this.nodes).forEach(key => this.updateOpen(getObjectValueByPath(this.nodes[key].item, this.itemKey), value)) - this.emitOpen() - }, - getKeys (items: any[], keys: any[] = []) { - for (let i = 0; i < items.length; i++) { - const key = getObjectValueByPath(items[i], this.itemKey) - keys.push(key) - const children = getObjectValueByPath(items[i], this.itemChildren) - if (children) { - keys.push(...this.getKeys(children)) - } - } - - return keys - }, - buildTree (items: any[], parent: (string | number | null) = null) { - for (let i = 0; i < items.length; i++) { - const item = items[i] - const key = getObjectValueByPath(item, this.itemKey) - const children = getObjectValueByPath(item, this.itemChildren) ?? [] - const oldNode = this.nodes.hasOwnProperty(key) ? this.nodes[key] : { - isSelected: false, isIndeterminate: false, isActive: false, isOpen: false, vnode: null, - } as NodeState - - const node: any = { - vnode: oldNode.vnode, - parent, - children: children.map((c: any) => getObjectValueByPath(c, this.itemKey)), - item, - } - - this.buildTree(children, key) - - // This fixed bug with dynamic children resetting selected parent state - if ( - this.selectionType !== 'independent' && - parent !== null && - !this.nodes.hasOwnProperty(key) && - this.nodes.hasOwnProperty(parent) - ) { - node.isSelected = this.nodes[parent].isSelected - } else { - node.isSelected = oldNode.isSelected - node.isIndeterminate = oldNode.isIndeterminate - } - - node.isActive = oldNode.isActive - node.isOpen = oldNode.isOpen - - this.nodes[key] = node - - if (children.length && this.selectionType !== 'independent') { - const { isSelected, isIndeterminate } = this.calculateState(key, this.nodes) - - node.isSelected = isSelected - node.isIndeterminate = isIndeterminate - } - - // Don't forget to rebuild cache - if (this.nodes[key].isSelected && (this.selectionType === 'independent' || node.children.length === 0)) 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) - } - }, - calculateState (node: string | number, state: Record) { - const children = state[node].children - const counts = children.reduce((counts: number[], child: string | number) => { - counts[0] += +Boolean(state[child].isSelected) - counts[1] += +Boolean(state[child].isIndeterminate) - - return counts - }, [0, 0]) - - const isSelected = !!children.length && counts[0] === children.length - const isIndeterminate = !isSelected && (counts[0] > 0 || counts[1] > 0) - - return { - isSelected, - isIndeterminate, - } - }, - emitOpen () { - this.emitNodeCache('update:open', this.openCache) - }, - emitSelected () { - this.emitNodeCache('input', this.selectedCache) - }, - emitActive () { - this.emitNodeCache('update:active', this.activeCache) - }, - emitNodeCache (event: string, cache: NodeCache) { - this.$emit(event, this.returnObject ? [...cache].map(key => this.nodes[key].item) : [...cache]) - }, - handleNodeCacheWatcher (value: any[], cache: NodeCache, updateFn: Function, emitFn: Function) { - value = this.returnObject ? value.map(v => getObjectValueByPath(v, this.itemKey)) : value - const old = [...cache] - if (deepEqual(old, value)) return - - old.forEach(key => updateFn(key, false)) - value.forEach(key => updateFn(key, true)) - - emitFn() - }, - getDescendants (key: string | number, descendants: NodeArray = []) { - const children = this.nodes[key].children - - descendants.push(...children) - - for (let i = 0; i < children.length; i++) { - descendants = this.getDescendants(children[i], descendants) - } - - return descendants - }, - getParents (key: string | number) { - let parent = this.nodes[key].parent - - const parents = [] - while (parent !== null) { - parents.push(parent) - parent = this.nodes[parent].parent - } - - return parents - }, - register (node: VTreeviewNodeInstance) { - const key = getObjectValueByPath(node.item, this.itemKey) - this.nodes[key].vnode = node - - this.updateVnodeState(key) - }, - unregister (node: VTreeviewNodeInstance) { - const key = getObjectValueByPath(node.item, this.itemKey) - if (this.nodes[key]) this.nodes[key].vnode = null - }, - isParent (key: string | number) { - return this.nodes[key].children && this.nodes[key].children.length - }, - updateActive (key: string | number, isActive: boolean) { - if (!this.nodes.hasOwnProperty(key)) return - - if (!this.multipleActive) { - this.activeCache.forEach(active => { - this.nodes[active].isActive = false - this.updateVnodeState(active) - this.activeCache.delete(active) - }) - } - - const 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 (key: string | number, isSelected: boolean, isForced = false) { - if (!this.nodes.hasOwnProperty(key)) return - - const changed = new Map() - - if (this.selectionType !== 'independent') { - for (const descendant of this.getDescendants(key)) { - if (!getObjectValueByPath(this.nodes[descendant].item, this.itemDisabled) || isForced) { - this.nodes[descendant].isSelected = isSelected - this.nodes[descendant].isIndeterminate = false - changed.set(descendant, isSelected) - } - } - - const calculated = this.calculateState(key, this.nodes) - this.nodes[key].isSelected = isSelected - this.nodes[key].isIndeterminate = calculated.isIndeterminate - changed.set(key, isSelected) - - for (const parent of this.getParents(key)) { - const calculated = this.calculateState(parent, this.nodes) - this.nodes[parent].isSelected = calculated.isSelected - this.nodes[parent].isIndeterminate = calculated.isIndeterminate - changed.set(parent, calculated.isSelected) - } - } else { - this.nodes[key].isSelected = isSelected - this.nodes[key].isIndeterminate = false - changed.set(key, isSelected) - } - - for (const [key, value] of changed.entries()) { - this.updateVnodeState(key) - - if (this.selectionType === 'leaf' && this.isParent(key)) continue - - value === true ? this.selectedCache.add(key) : this.selectedCache.delete(key) - } - }, - updateOpen (key: string | number, isOpen: boolean) { - if (!this.nodes.hasOwnProperty(key)) return - - const node = this.nodes[key] - const children = getObjectValueByPath(node.item, this.itemChildren) - - if (children && !children.length && node.vnode && !node.vnode.hasLoaded) { - node.vnode.checkChildren().then(() => this.updateOpen(key, isOpen)) - } else if (children && children.length) { - node.isOpen = isOpen - - node.isOpen ? this.openCache.add(key) : this.openCache.delete(key) - - this.updateVnodeState(key) - } - }, - updateVnodeState (key: string | number) { - const 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 - } - }, - isExcluded (key: string | number) { - return !!this.search && this.excludedItems.has(key) - }, - }, - - render (h): VNode { - const children: VNodeChildrenArrayContents = this.items.length - ? this.items.filter(item => { - return !this.isExcluded(getObjectValueByPath(item, this.itemKey)) - }).map(item => { - const genChild = VTreeviewNode.options.methods.genChild.bind(this) - - return genChild(item, this.disabled || getObjectValueByPath(item, this.itemDisabled)) - }) - /* istanbul ignore next */ - : this.$slots.default! // TODO: remove type annotation with TS 3.2 - - return h('div', { - staticClass: 'v-treeview', - class: { - 'v-treeview--hoverable': this.hoverable, - 'v-treeview--dense': this.dense, - ...this.themeClasses, - }, - }, children) - }, -}) diff --git a/packages/vuetify/src/components/VTreeview/VTreeviewNode.ts b/packages/vuetify/src/components/VTreeview/VTreeviewNode.ts deleted file mode 100644 index a87da474c94..00000000000 --- a/packages/vuetify/src/components/VTreeview/VTreeviewNode.ts +++ /dev/null @@ -1,376 +0,0 @@ -// @ts-nocheck -/* eslint-disable */ - -// Components -import { VExpandTransition } from '../transitions' -import { VIcon } from '../VIcon' -import VTreeview from './VTreeview' - -// Mixins -import { inject as RegistrableInject } from '../../mixins/registrable' -import Colorable from '../../mixins/colorable' - -// Utils -import mixins, { ExtractVue } from '../../util/mixins' -import { getObjectValueByPath, createRange } from '../../util/helpers' - -// Types -import { VNode, VNodeChildren, PropType } from 'vue' -import { PropValidator } from 'vue/types/options' - -type VTreeViewInstance = InstanceType - -const baseMixins = mixins( - Colorable, - RegistrableInject('treeview') -) - -interface options extends ExtractVue { - treeview: VTreeViewInstance -} - -export const VTreeviewNodeProps = { - activatable: Boolean, - activeClass: { - type: String, - default: 'v-treeview-node--active', - }, - color: { - type: String, - default: 'primary', - }, - disablePerNode: Boolean, - expandIcon: { - type: String, - default: '$subgroup', - }, - indeterminateIcon: { - type: String, - default: '$checkboxIndeterminate', - }, - itemChildren: { - type: String, - default: 'children', - }, - itemDisabled: { - type: String, - default: 'disabled', - }, - itemKey: { - type: String, - default: 'id', - }, - itemText: { - type: String, - default: 'name', - }, - loadChildren: Function as PropType<(item: any) => Promise>, - loadingIcon: { - type: String, - default: '$loading', - }, - offIcon: { - type: String, - default: '$checkboxOff', - }, - onIcon: { - type: String, - default: '$checkboxOn', - }, - openOnClick: Boolean, - rounded: Boolean, - selectable: Boolean, - selectedColor: { - type: String, - default: 'accent', - }, - shaped: Boolean, - transition: Boolean, - selectionType: { - type: String as PropType<'leaf' | 'independent'>, - default: 'leaf', - validator: (v: string) => ['leaf', 'independent'].includes(v), - }, -} - -/* @vue/component */ -const VTreeviewNode = baseMixins.extend().extend({ - name: 'v-treeview-node', - - inject: { - treeview: { - default: null, - }, - }, - - props: { - level: Number, - item: { - type: Object, - default: () => null, - } as PropValidator | null>, - parentIsDisabled: Boolean, - ...VTreeviewNodeProps, - }, - - data: () => ({ - hasLoaded: false, - isActive: false, // Node is selected (row) - isIndeterminate: false, // Node has at least one selected child - isLoading: false, - isOpen: false, // Node is open/expanded - isSelected: false, // Node is selected (checkbox) - }), - - computed: { - disabled (): boolean { - return ( - getObjectValueByPath(this.item, this.itemDisabled) || - (!this.disablePerNode && (this.parentIsDisabled && this.selectionType === 'leaf')) - ) - }, - key (): string { - return getObjectValueByPath(this.item, this.itemKey) - }, - children (): any[] | null { - const children = getObjectValueByPath(this.item, this.itemChildren) - return children && children.filter((child: any) => !this.treeview.isExcluded(getObjectValueByPath(child, this.itemKey))) - }, - text (): string { - return getObjectValueByPath(this.item, this.itemText) - }, - scopedProps (): object { - return { - item: this.item, - leaf: !this.children, - selected: this.isSelected, - indeterminate: this.isIndeterminate, - active: this.isActive, - open: this.isOpen, - } - }, - computedIcon (): string { - if (this.isIndeterminate) return this.indeterminateIcon - else if (this.isSelected) return this.onIcon - else return this.offIcon - }, - hasChildren (): boolean { - return !!this.children && (!!this.children.length || !!this.loadChildren) - }, - }, - - created () { - this.treeview.register(this) - }, - - beforeDestroy () { - this.treeview.unregister(this) - }, - - methods: { - checkChildren (): Promise { - return new Promise(resolve => { - // TODO: Potential issue with always trying - // to load children if response is empty? - if (!this.children || this.children.length || !this.loadChildren || this.hasLoaded) return resolve() - - this.isLoading = true - resolve(this.loadChildren(this.item)) - }).then(() => { - this.isLoading = false - this.hasLoaded = true - }) - }, - open () { - this.isOpen = !this.isOpen - this.treeview.updateOpen(this.key, this.isOpen) - this.treeview.emitOpen() - }, - genLabel () { - const children = [] - - if (this.$scopedSlots.label) children.push(this.$scopedSlots.label(this.scopedProps)) - else children.push(this.text) - - return this.$createElement('div', { - slot: 'label', - staticClass: 'v-treeview-node__label', - }, children) - }, - genPrependSlot () { - if (!this.$scopedSlots.prepend) return null - - return this.$createElement('div', { - staticClass: 'v-treeview-node__prepend', - }, this.$scopedSlots.prepend(this.scopedProps)) - }, - genAppendSlot () { - if (!this.$scopedSlots.append) return null - - return this.$createElement('div', { - staticClass: 'v-treeview-node__append', - }, this.$scopedSlots.append(this.scopedProps)) - }, - genContent () { - const children = [ - this.genPrependSlot(), - this.genLabel(), - this.genAppendSlot(), - ] - - return this.$createElement('div', { - staticClass: 'v-treeview-node__content', - }, children) - }, - genToggle () { - return this.$createElement(VIcon, { - staticClass: 'v-treeview-node__toggle', - class: { - 'v-treeview-node__toggle--open': this.isOpen, - 'v-treeview-node__toggle--loading': this.isLoading, - }, - slot: 'prepend', - on: { - click: (e: MouseEvent) => { - e.stopPropagation() - - if (this.isLoading) return - - this.checkChildren().then(() => this.open()) - }, - }, - }, [this.isLoading ? this.loadingIcon : this.expandIcon]) - }, - genCheckbox () { - return this.$createElement(VIcon, { - staticClass: 'v-treeview-node__checkbox', - props: { - color: this.isSelected || this.isIndeterminate ? this.selectedColor : undefined, - disabled: this.disabled, - }, - on: { - click: (e: MouseEvent) => { - e.stopPropagation() - - if (this.isLoading) return - - this.checkChildren().then(() => { - // We nextTick here so that items watch in VTreeview has a chance to run first - this.$nextTick(() => { - this.isSelected = !this.isSelected - this.isIndeterminate = false - - this.treeview.updateSelected(this.key, this.isSelected) - this.treeview.emitSelected() - }) - }) - }, - }, - }, [this.computedIcon]) - }, - genLevel (level: number) { - return createRange(level).map(() => this.$createElement('div', { - staticClass: 'v-treeview-node__level', - })) - }, - genNode () { - const children = [this.genContent()] - - if (this.selectable) children.unshift(this.genCheckbox()) - - if (this.hasChildren) { - children.unshift(this.genToggle()) - } else { - children.unshift(...this.genLevel(1)) - } - - children.unshift(...this.genLevel(this.level)) - - return this.$createElement('div', this.setTextColor(this.isActive && this.color, { - staticClass: 'v-treeview-node__root', - class: { - [this.activeClass]: this.isActive, - }, - on: { - click: () => { - if (this.openOnClick && this.hasChildren) { - this.checkChildren().then(this.open) - } else if (this.activatable && !this.disabled) { - this.isActive = !this.isActive - this.treeview.updateActive(this.key, this.isActive) - this.treeview.emitActive() - } - }, - }, - }), children) - }, - genChild (item: any, parentIsDisabled: boolean) { - return this.$createElement(VTreeviewNode, { - key: getObjectValueByPath(item, this.itemKey), - props: { - activatable: this.activatable, - activeClass: this.activeClass, - item, - selectable: this.selectable, - selectedColor: this.selectedColor, - color: this.color, - disablePerNode: this.disablePerNode, - expandIcon: this.expandIcon, - indeterminateIcon: this.indeterminateIcon, - offIcon: this.offIcon, - onIcon: this.onIcon, - loadingIcon: this.loadingIcon, - itemKey: this.itemKey, - itemText: this.itemText, - itemDisabled: this.itemDisabled, - itemChildren: this.itemChildren, - loadChildren: this.loadChildren, - transition: this.transition, - openOnClick: this.openOnClick, - rounded: this.rounded, - shaped: this.shaped, - level: this.level + 1, - selectionType: this.selectionType, - parentIsDisabled, - }, - scopedSlots: this.$scopedSlots, - }) - }, - genChildrenWrapper () { - if (!this.isOpen || !this.children) return null - - const children = [this.children.map(c => this.genChild(c, this.disabled))] - - return this.$createElement('div', { - staticClass: 'v-treeview-node__children', - }, children) - }, - genTransition () { - return this.$createElement(VExpandTransition, [this.genChildrenWrapper()]) - }, - }, - - render (h): VNode { - const children: VNodeChildren = [this.genNode()] - - if (this.transition) children.push(this.genTransition()) - else children.push(this.genChildrenWrapper()) - - return h('div', { - staticClass: 'v-treeview-node', - class: { - 'v-treeview-node--leaf': !this.hasChildren, - 'v-treeview-node--click': this.openOnClick, - 'v-treeview-node--disabled': this.disabled, - 'v-treeview-node--rounded': this.rounded, - 'v-treeview-node--shaped': this.shaped, - 'v-treeview-node--selected': this.isSelected, - }, - attrs: { - 'aria-expanded': String(this.isOpen), - }, - }, children) - }, -}) - -export default VTreeviewNode diff --git a/packages/vuetify/src/components/VTreeview/__tests__/VTreeview.spec.ts b/packages/vuetify/src/components/VTreeview/__tests__/VTreeview.spec.ts deleted file mode 100644 index c06d247399f..00000000000 --- a/packages/vuetify/src/components/VTreeview/__tests__/VTreeview.spec.ts +++ /dev/null @@ -1,881 +0,0 @@ -// @ts-nocheck -/* eslint-disable */ - -// import Vue from 'vue' -import { - mount, - Wrapper, - MountOptions, -} from '@vue/test-utils' -// import VTreeview from '../VTreeview' -// import { ExtractVue } from '../../../util/mixins' -// import { wait } from '../../../../test' - -const singleRootTwoChildren = [ - { id: 0, name: 'Root', children: [{ id: 1, name: 'Child' }, { id: 2, name: 'Child 2' }] }, -] - -const threeLevels = [ - { id: 0, name: 'Root', children: [{ id: 1, name: 'Child', children: [{ id: 2, name: 'Grandchild' }] }, { id: 3, name: 'Child' }] }, -] - -describe.skip('VTreeView.ts', () => { // eslint-disable-line max-statements - type Instance = ExtractVue - let mountFunction: (options?: MountOptions) => Wrapper - beforeEach(() => { - mountFunction = (options?: MountOptions) => { - return mount(VTreeview, { - // https://github.com/vuejs/vue-test-utils/issues/1130 - sync: false, - ...options, - }) - } - }) - - it('should render items', async () => { - const wrapper = mountFunction({ - propsData: { - items: singleRootTwoChildren, - }, - }) - - expect(wrapper.html()).toMatchSnapshot() - }) - - it('should render items in dense mode', async () => { - const wrapper = mountFunction({ - propsData: { - items: singleRootTwoChildren, - dense: true, - }, - }) - - expect(wrapper.html()).toMatchSnapshot() - }) - - // TODO: this fails without sync, nextTick doesn't help - // https://github.com/vuejs/vue-test-utils/issues/1130 - it.skip('should select all leaf nodes', async () => { - const wrapper = mountFunction({ - propsData: { - items: threeLevels, - selectable: true, - }, - }) - - const fn = jest.fn() - wrapper.vm.$on('input', fn) - - wrapper.find('.v-treeview-node__checkbox').trigger('click') - await wrapper.vm.$nextTick() - - expect(fn).toHaveBeenCalledTimes(1) - expect(fn).toHaveBeenCalledWith([3, 2]) - expect(wrapper.html()).toMatchSnapshot() - }) - - // TODO: this fails without sync, nextTick doesn't help - // https://github.com/vuejs/vue-test-utils/issues/1130 - it.skip('should select only leaf nodes', async () => { - const wrapper = mountFunction({ - propsData: { - items: threeLevels, - selectable: true, - }, - }) - - const fn = jest.fn() - wrapper.vm.$on('input', fn) - - wrapper.find('.v-treeview-node__toggle').trigger('click') - await wrapper.vm.$nextTick() - - wrapper.findAll('.v-treeview-node__checkbox').at(2).trigger('click') - await wrapper.vm.$nextTick() - - expect(fn).toHaveBeenCalledTimes(1) - expect(fn).toHaveBeenCalledWith([3]) - expect(wrapper.html()).toMatchSnapshot() - }) - - // TODO: this fails without sync, nextTick doesn't help - // https://github.com/vuejs/vue-test-utils/issues/1130 - it.skip('should select only root node', async () => { - const wrapper = mountFunction({ - propsData: { - items: threeLevels, - selectable: true, - selectionType: 'independent', - }, - }) - - const fn = jest.fn() - wrapper.vm.$on('input', fn) - - wrapper.find('.v-treeview-node__checkbox').trigger('click') - await wrapper.vm.$nextTick() - - expect(fn).toHaveBeenCalledTimes(1) - expect(fn).toHaveBeenCalledWith([0]) - expect(wrapper.html()).toMatchSnapshot() - }) - - // TODO: fails with TS 3.9 - it.skip('should load children when expanding', async () => { - const loadChildren = item => { - item.children.push({ id: 1, name: 'Child' }) - } - - const wrapper = mountFunction({ - propsData: { - items: [{ id: 0, name: 'Root', children: [] }], - loadChildren, - }, - }) - - expect(wrapper.html()).toMatchSnapshot() - - wrapper.find('.v-treeview-node__toggle').trigger('click') - await wrapper.vm.$nextTick() - - expect(wrapper.html()).toMatchSnapshot() - expect(`[Vue warn]: Error in created hook: "TypeError: Cannot set property 'vnode' of undefined"`).toHaveBeenWarned() - expect(`TypeError: Cannot set property 'vnode' of undefined`).toHaveBeenWarned() - }) - - it('should load children when selecting, but not render', async () => { - const loadChildren = item => { - item.children = [{ id: 1, name: 'Child' }] - } - - const wrapper = mountFunction({ - propsData: { - items: [{ id: 0, name: 'Root', children: [] }], - selectable: true, - loadChildren, - }, - }) - - const fn = jest.fn() - wrapper.vm.$on('input', fn) - - expect(wrapper.html()).toMatchSnapshot() - - wrapper.find('.v-treeview-node__checkbox').trigger('click') - await wait() - - expect(fn).toHaveBeenCalledTimes(1) - expect(fn).toHaveBeenCalledWith([0]) - expect(wrapper.html()).toMatchSnapshot() - }) - - it('should emit active node when clicking on it', async () => { - const wrapper = mountFunction({ - propsData: { - items: [{ id: 0, name: 'Root' }, { id: 1, name: 'Root' }], - activatable: true, - }, - }) - - const fn = jest.fn() - wrapper.vm.$on('update:active', fn) - - wrapper.find('.v-treeview-node__root').trigger('click') - await wrapper.vm.$nextTick() - - expect(fn).toHaveBeenCalledTimes(1) - expect(fn).toHaveBeenCalledWith([0]) - - wrapper.find('.v-treeview-node__root').trigger('click') - await wrapper.vm.$nextTick() - - expect(fn).toHaveBeenCalledWith([]) - }) - - it('should allow multiple active nodes with prop multipleActive', async () => { - const wrapper = mountFunction({ - propsData: { - items: [{ id: 0, name: 'Root' }, { id: 1, name: 'Root' }], - multipleActive: true, - activatable: true, - }, - }) - - const fn = jest.fn() - wrapper.vm.$on('update:active', fn) - - wrapper.findAll('.v-treeview-node__root').wrappers.forEach(vm => vm.trigger('click')) - await wrapper.vm.$nextTick() - - expect(fn).toHaveBeenCalledTimes(2) - expect(fn).toHaveBeenLastCalledWith([0, 1]) - }) - - // TODO: fails with TS 3.9 - it.skip('should update selection when selected prop changes', async () => { - const wrapper = mountFunction({ - propsData: { - items: [{ id: 0, name: 'Root', children: [{ id: 1, name: 'Child' }] }], - value: [], - selectable: true, - }, - }) - - expect(wrapper.html()).toMatchSnapshot() - - wrapper.find('.v-treeview-node__toggle').trigger('click') - wrapper.setProps({ value: [1] }) - await wrapper.vm.$nextTick() - - expect(wrapper.findAll('.v-treeview-node')).toHaveLength(2) - expect(wrapper.findAll('.v-treeview-node--selected')).toHaveLength(2) - expect(wrapper.html()).toMatchSnapshot() - - wrapper.setProps({ value: [] }) - await wrapper.vm.$nextTick() - expect(wrapper.html()).toMatchSnapshot() - }) - - it('should open all children when using open-all prop', async () => { - const wrapper = mountFunction({ - propsData: { - items: threeLevels, - openAll: true, - }, - }) - - await wrapper.vm.$nextTick() - - expect(wrapper.html()).toMatchSnapshot() - }) - - it('should open/close all children when using updateAll', async () => { - const wrapper = mountFunction({ - propsData: { - items: threeLevels, - }, - }) - - const updateOpen = jest.fn() - wrapper.vm.$on('update:open', updateOpen) - - wrapper.vm.updateAll(true) - expect(updateOpen).toHaveBeenCalledTimes(1) - expect(updateOpen).toHaveBeenCalledWith([0, 1]) - - wrapper.vm.updateAll(false) - expect(updateOpen).toHaveBeenCalledTimes(2) - expect(updateOpen).toHaveBeenCalledWith([]) - }) - - it('should react to open changes', async () => { - const wrapper = mountFunction({ - propsData: { - items: threeLevels, - open: [1], - }, - }) - - const fn = jest.fn() - - wrapper.vm.$on('update:open', fn) - wrapper.setProps({ open: [0, 1] }) - - await wrapper.vm.$nextTick() - - expect(wrapper.html()).toMatchSnapshot() - - wrapper.setProps({ open: [0] }) - - await wrapper.vm.$nextTick() - - expect(wrapper.html()).toMatchSnapshot() - - wrapper.setProps({ open: [0, 1] }) - - await wrapper.vm.$nextTick() - - expect(wrapper.html()).toMatchSnapshot() - - expect(fn).toHaveBeenCalledWith([0, 1]) - - // Should not update open values that do not exist in the tree - wrapper.setProps({ open: [7] }) - - await wrapper.vm.$nextTick() - expect(wrapper.html()).toMatchSnapshot() - - expect(fn).toHaveBeenCalledWith([]) - }) - - it('should update selected and active on created', async () => { - const wrapper = mountFunction({ - propsData: { - items: threeLevels, - active: [2], - value: [1], - }, - }) - - // TODO: I can not find away in avoriaz - // to catch events being emitted from a - // lifecycle hook. We should not assert - // internal state. - expect([...wrapper.vm.activeCache]).toEqual([2]) - expect([...wrapper.vm.selectedCache]).toEqual([2]) - }) - - it('should react to changes for active items', async () => { - const wrapper = mountFunction({ - propsData: { - items: threeLevels, - active: [2], - }, - }) - - const active = jest.fn() - wrapper.vm.$on('update:active', active) - - wrapper.setProps({ active: [] }) - await wrapper.vm.$nextTick() - expect(active).toHaveBeenCalledWith([]) - - // without multiple-active, it will use last value in array - wrapper.setProps({ active: [1, 3] }) - await wrapper.vm.$nextTick() - expect(active).toHaveBeenCalledWith([3]) - - wrapper.setProps({ multipleActive: true, active: [1, 3] }) - await wrapper.vm.$nextTick() - expect(active).toHaveBeenCalledWith([1, 3]) - - // 7 does not exist, we get nothing back - wrapper.setProps({ active: [7] }) - await wrapper.vm.$nextTick() - expect(active).toHaveBeenCalledWith([]) - - wrapper.setProps({ active: [0], items: singleRootTwoChildren }) - await wrapper.vm.$nextTick() - expect(active).toHaveBeenCalledWith([0]) - }) - - it('should react to changes for selected items', async () => { - const wrapper = mountFunction({ - propsData: { - items: threeLevels, - value: [2], - }, - }) - - const value = jest.fn() - wrapper.vm.$on('input', value) - - wrapper.setProps({ value: [] }) - await wrapper.vm.$nextTick() - expect(value).toHaveBeenCalledWith([]) - - wrapper.setProps({ value: [3] }) - await wrapper.vm.$nextTick() - expect(value).toHaveBeenCalledWith([3]) - - // 7 does not exist, we get nothing back - wrapper.setProps({ value: [7] }) - await wrapper.vm.$nextTick() - expect(value).toHaveBeenCalledWith([]) - - wrapper.setProps({ value: [0] }) - await wrapper.vm.$nextTick() - expect(value).toHaveBeenLastCalledWith([3, 2]) - }) - - it('should accept string value for id', async () => { - const wrapper = mountFunction({ - propsData: { itemKey: 'name' }, - }) - - wrapper.setProps({ items: [{ name: 'Foobar' }] }) - - await wrapper.vm.$nextTick() - - expect(wrapper.vm.nodes.Foobar).toBeTruthy() - - wrapper.setProps({ value: ['Foobar'] }) - - await wrapper.vm.$nextTick() - }) - - it('should warn developer when using non-scoped slots', () => { - mountFunction({ - slots: { - prepend: [{ render: h => h('div') }], - append: [{ render: h => h('div') }], - }, - }) - - expect('[Vuetify] The prepend and append slots require a slot-scope attribute').toHaveBeenTipped() - }) - - it('should not show expand icon when children is empty', () => { - const wrapper = mountFunction({ - propsData: { - items: [ - { - text: 'root', - children: [], - }, - ], - }, - }) - - expect(wrapper.html()).toMatchSnapshot() - expect(wrapper.findAll('.v-treeview-node__toggle')).toHaveLength(0) - }) - - it('should show expand icon when children is empty and load-children prop used', () => { - const wrapper = mountFunction({ - propsData: { - loadChildren: () => {}, - items: [ - { - text: 'root', - children: [], - }, - ], - }, - }) - - expect(wrapper.html()).toMatchSnapshot() - expect(wrapper.findAll('.v-treeview-node__toggle')).toHaveLength(1) - }) - - it('should recalculate tree when loading async children using custom key', async () => { - const items = [ - { - id: 1, - name: 'One', - __children: [], - }, - ] - - const wrapper = mountFunction({ - propsData: { - items, - itemChildren: '__children', - loadChildren: () => { - const newItems = [...items] - items[0].__children.push({ id: 2, name: 'Two' }) - wrapper.setProps({ - items: newItems, - }) - }, - }, - }) - - wrapper.find('.v-treeview-node__toggle').trigger('click') - await wrapper.vm.$nextTick() - - expect(wrapper.html()).toMatchSnapshot() - }) - - it('should remove old nodes', async () => { - const wrapper = mountFunction({ - propsData: { - items: [ - { - id: 1, - name: 'one', - }, - { - id: 2, - name: 'two', - }, - ], - }, - }) - - expect(wrapper.html()).toMatchSnapshot() - - wrapper.setProps({ - items: [ - { - id: 1, - name: 'one', - }, - ], - }) - - await wrapper.vm.$nextTick() - expect(wrapper.html()).toMatchSnapshot() - - wrapper.setProps({ - items: [ - { - id: 1, - name: 'one', - }, - { - id: 3, - name: 'three', - }, - ], - }) - - await wrapper.vm.$nextTick() - expect(wrapper.html()).toMatchSnapshot() - - expect(Object.keys(wrapper.vm.nodes)).toHaveLength(2) - }) - - it('should filter items', async () => { - const wrapper = mountFunction({ - propsData: { - items: [ - { - id: 1, - name: 'one', - }, - { - id: 2, - name: 'two', - }, - ], - }, - }) - - expect(wrapper.html()).toMatchSnapshot() - - wrapper.setProps({ - search: 'two', - }) - - await wrapper.vm.$nextTick() - - expect(wrapper.html()).toMatchSnapshot() - }) - - it('should filter items using custom item filter', async () => { - const wrapper = mountFunction({ - propsData: { - filter: (item, search, textKey) => item.special === search, - items: [ - { - id: 1, - name: 'one', - special: 'yes', - }, - { - id: 2, - name: 'two', - special: 'no', - }, - ], - search: 'NO', - }, - }) - - expect(wrapper.html()).toMatchSnapshot() - - wrapper.setProps({ - search: 'yes', - }) - - await wrapper.vm.$nextTick() - - expect(wrapper.html()).toMatchSnapshot() - }) - - // TODO: fails with TS 3.9 - it.skip('should emit objects when return-object prop is used', async () => { - const items = [{ id: 0, name: 'Root', children: [{ id: 1, name: 'Child' }] }] - - const wrapper = mountFunction({ - propsData: { - items, - activatable: true, - selectable: true, - returnObject: true, - }, - }) - - const active = jest.fn() - wrapper.vm.$on('update:active', active) - const selected = jest.fn() - wrapper.vm.$on('input', selected) - const open = jest.fn() - wrapper.vm.$on('update:open', open) - - wrapper.find('.v-treeview-node__root').trigger('click') - await wrapper.vm.$nextTick() - - expect(active).toHaveBeenCalledTimes(1) - expect(active).toHaveBeenCalledWith([items[0]]) - - wrapper.find('.v-treeview-node__checkbox').trigger('click') - await wrapper.vm.$nextTick() - - expect(selected).toHaveBeenCalledTimes(1) - expect(selected).toHaveBeenCalledWith([items[0].children[0]]) - - wrapper.find('.v-treeview-node__toggle').trigger('click') - await wrapper.vm.$nextTick() - - expect(open).toHaveBeenCalledTimes(1) - expect(open).toHaveBeenCalledWith([items[0]]) - }) - - it('should handle replacing items with new array of equal length', async () => { - const wrapper = mountFunction({ - propsData: { - items: [ - { - id: 1, - name: 'one', - }, - { - id: 2, - name: 'two', - }, - ], - }, - }) - - expect(wrapper.html()).toMatchSnapshot() - - wrapper.setProps({ - items: [ - { - id: 1, - name: 'one', - }, - { - id: 3, - name: 'three', - }, - ], - }) - - await wrapper.vm.$nextTick() - - expect(wrapper.html()).toMatchSnapshot() - }) - - // https://github.com/vuetifyjs/vuetify/issues/8709 - it('should handle initial active/open/selected values when using return-object prop', async () => { - const one = { id: '1', name: 'One' } - const three = { id: '3', name: 'Three' } - const two = { id: '2', name: 'Two', children: [three] } - - const wrapper = mountFunction({ - propsData: { - returnObject: true, - selectable: true, - activatable: true, - items: [one, two], - value: [one], - open: [two], - active: [three], - }, - }) - - await wrapper.vm.$nextTick() - - expect(wrapper.html()).toMatchSnapshot() - }) - - it('should set correct state when updating nodes', async () => { - const children = [ - { id: 2, name: 'Bar' }, - { id: 3, name: 'Fizz' }, - { id: 4, name: 'Buzz' }, - ] - const item = { - id: 1, - name: 'Foo', - } - const wrapper = mountFunction({ - propsData: { - items: [{ ...item, children }], - value: [4], - }, - }) - - wrapper.setProps({ - items: [{ - ...item, - children: [ - ...children, - { id: 5, name: 'FizzBuzz' }, - ], - }], - }) - - await wrapper.vm.$nextTick() - - expect(wrapper.vm.nodes['5'].isIndeterminate).toBeUndefined() - }) - - // https://github.com/vuetifyjs/vuetify/issues/8720 - it('should set correct selection when updating items', async () => { - const items = [{ - id: 1, - name: 'Foo', - children: [ - { id: 2, name: 'Bar' }, - { id: 3, name: 'Fizz' }, - { id: 4, name: 'Buzz' }, - ], - }] - - const input = jest.fn() - - const wrapper = mountFunction({ - propsData: { - items, - value: [2, 3, 4], - selectionType: 'leaf', - selectable: true, - }, - listeners: { - input, - }, - }) - - wrapper.setProps({ - items: [{ - id: 1, - name: 'Foo', - children: [ - { id: 2, name: 'Bar' }, - { id: 3, name: 'Fizz' }, - { id: 4, name: 'Buzz' }, - ], - }], - }) - - await wrapper.vm.$nextTick() - - expect(input).not.toHaveBeenCalled() - }) - - // https://github.com/vuetifyjs/vuetify/issues/8244 - // TODO: fails with TS 3.9 - it.skip('should not touch disabled items when selecting', async () => { - const items = [{ - id: 1, - name: 'Foo', - children: [ - { id: 2, name: 'Bar', disabled: true }, - { id: 3, name: 'Fizz' }, - { id: 4, name: 'Buzz' }, - ], - }] - - const input = jest.fn() - - const wrapper = mountFunction({ - propsData: { - items, - value: [], - selectionType: 'leaf', - selectable: true, - }, - listeners: { - input, - }, - }) - - wrapper.find('.v-treeview-node__checkbox').trigger('click') - await wrapper.vm.$nextTick() - - expect(input).toHaveBeenLastCalledWith([3, 4]) - - wrapper.setProps({ - value: [2, 3, 4], - items: [{ - id: 1, - name: 'Foo', - children: [ - { id: 2, name: 'Bar', disabled: true }, - { id: 3, name: 'Fizz' }, - { id: 4, name: 'Buzz' }, - ], - }], - }) - await wrapper.vm.$nextTick() - - wrapper.find('.v-treeview-node__checkbox').trigger('click') - await wrapper.vm.$nextTick() - - expect(input).toHaveBeenLastCalledWith([2]) - }) - - // https://github.com/vuetifyjs/vuetify/issues/10990 - // https://github.com/vuetifyjs/vuetify/issues/10770 - // TODO: fails with TS 3.9 - it.skip('should not disable children of disabled parent when in independent mode', async () => { - const items = [{ - id: 1, - name: 'Foo', - disabled: true, - children: [ - { id: 2, name: 'Bar' }, - { id: 3, name: 'Fizz', disabled: true }, - { id: 4, name: 'Buzz' }, - ], - }] - - const input = jest.fn() - - const wrapper = mountFunction({ - propsData: { - items, - value: [], - open: [1], - selectionType: 'independent', - selectable: true, - }, - listeners: { - input, - }, - }) - - await wrapper.vm.$nextTick() - - wrapper.findAll('.v-treeview-node__checkbox').at(1).trigger('click') - await wrapper.vm.$nextTick() - - expect(input).toHaveBeenLastCalledWith([2]) - - wrapper.findAll('.v-treeview-node__checkbox').at(2).trigger('click') - await wrapper.vm.$nextTick() - - expect(input).toHaveBeenCalledTimes(1) - }) - - // https://github.com/vuetifyjs/vuetify/issues/9693 - // TODO: fails with TS 3.9 - it.skip('should emit opened node when using open-on-click and load-children', async () => { - const open = jest.fn() - - const wrapper = mountFunction({ - propsData: { - items: [{ id: 0, name: 'Root', children: [] }], - loadChildren: () => wrapper.setProps({ - items: [{ id: 0, name: 'Root', children: [{ id: 1, name: 'Child' }] }], - }), - openOnClick: true, - }, - listeners: { - 'update:open': open, - }, - }) - - expect(wrapper.html()).toMatchSnapshot() - - wrapper.find('.v-treeview-node__root').trigger('click') - await wrapper.vm.$nextTick() - - expect(wrapper.html()).toMatchSnapshot() - expect(open).toHaveBeenLastCalledWith([0]) - }) -}) diff --git a/packages/vuetify/src/components/VTreeview/__tests__/VTreeviewNode.spec.ts b/packages/vuetify/src/components/VTreeview/__tests__/VTreeviewNode.spec.ts deleted file mode 100644 index db36b8cf800..00000000000 --- a/packages/vuetify/src/components/VTreeview/__tests__/VTreeviewNode.spec.ts +++ /dev/null @@ -1,192 +0,0 @@ -// @ts-nocheck -/* eslint-disable */ - -// import Vue from 'vue' -// import VTreeviewNode from '../VTreeviewNode' -import { - mount, - MountOptions, - Wrapper, -} from '@vue/test-utils' - -// Vue.prototype.$vuetify = { -// icons: { -// values: { -// subgroup: 'arrow_drop_down', -// }, -// }, -// } - -const singleRootTwoChildren = { id: 0, name: 'Root', children: [{ id: 1, name: 'Child' }, { id: 2, name: 'Child 2' }] } - -// const vm = new Vue() -// const defaultSlot = () => vm.$createElement('div', 'foobar') - -const Mock = { - name: 'test', - - render: h => h(VTreeviewNode, { - scopedSlots: { - prepend: defaultSlot, - append: defaultSlot, - }, - }), -} - -const MockScopedLabel = { - name: 'test', - - render: h => h(VTreeviewNode, { - props: { - item: singleRootTwoChildren, - }, - scopedSlots: { - label: props => vm.$createElement('div', [props.item.name.toUpperCase()]), - }, - }), -} - -describe.skip('VTreeViewNode.ts', () => { - type Instance = InstanceType - let mountFunction: (options?: MountOptions) => Wrapper - let treeview - - beforeEach(() => { - treeview = { - register: jest.fn(), - unregister: jest.fn(), - isExcluded: () => false, - updateActive: () => {}, - emitActive: () => {}, - updateOpen: () => {}, - emitOpen: () => {}, - } - - mountFunction = (options?: MountOptions) => { - return mount(VTreeviewNode, { - // https://github.com/vuejs/vue-test-utils/issues/1130 - sync: false, - ...options, - }) - } - }) - - it('should return indeterminate icon', async () => { - const wrapper = mountFunction({ - provide: { treeview }, - }) - - expect(wrapper.vm.computedIcon).toBe('$checkboxOff') - - wrapper.setData({ isIndeterminate: true }) - - expect(wrapper.vm.computedIcon).toBe('$checkboxIndeterminate') - }) - - it('should use scoped slots', () => { - const wrapper = mount(Mock, { - // https://github.com/vuejs/vue-test-utils/issues/1130 - sync: false, - provide: { treeview }, - }) - - expect(wrapper.html()).toMatchSnapshot() - }) - - it('should generate a transition element', () => { - const wrapper = mountFunction({ - propsData: { transition: true }, - provide: { treeview }, - }) - - expect(wrapper.html()).toMatchSnapshot() - }) - - it('should use label slot', () => { - const wrapper = mount(MockScopedLabel, { - // https://github.com/vuejs/vue-test-utils/issues/1130 - sync: false, - provide: { treeview }, - }) - - expect(wrapper.html()).toMatchSnapshot() - }) - - it('should render disabled item', () => { - const wrapper = mount({ - name: 'test', - - render: h => h(VTreeviewNode, { - scopedSlots: { - prepend: defaultSlot, - append: defaultSlot, - }, - props: { - item: { ...singleRootTwoChildren, disabled: true }, - }, - }), - }, { - // https://github.com/vuejs/vue-test-utils/issues/1130 - sync: false, - provide: { treeview }, - }) - - expect(wrapper.html()).toMatchSnapshot() - }) - - const singleRootWithEmptyChildrens = { id: 1, name: 'Child', children: [] } - it('should be able to have active children with empty array', () => { - const wrapper = mountFunction({ - provide: { treeview }, - propsData: { - item: singleRootWithEmptyChildrens, - activatable: true, - openOnClick: true, - }, - }) - - expect(wrapper.vm.isActive).toBe(false) - const selectedLeaf = wrapper.find('.v-treeview-node__root') - selectedLeaf.trigger('click') - expect(wrapper.vm.isActive).toBe(true) - - expect(wrapper.html()).toMatchSnapshot() - }) - - it('should not be able to have active children with empty array when loadChildren is specified', () => { - const wrapper = mountFunction({ - provide: { treeview }, - propsData: { - item: singleRootWithEmptyChildrens, - activatable: true, - openOnClick: true, - loadChildren: () => {}, - }, - }) - - expect(wrapper.vm.isActive).toBe(false) - const selectedLeaf = wrapper.find('.v-treeview-node__root') - selectedLeaf.trigger('click') - expect(wrapper.vm.isActive).toBe(false) - - expect(wrapper.html()).toMatchSnapshot() - }) - - it('should not be able to have active children with empty array when disabled', () => { - const wrapper = mountFunction({ - provide: { treeview }, - propsData: { - item: { ...singleRootWithEmptyChildrens, disabled: true }, - activatable: true, - openOnClick: true, - }, - }) - - expect(wrapper.vm.isActive).toBe(false) - const selectedLeaf = wrapper.find('.v-treeview-node__root') - selectedLeaf.trigger('click') - expect(wrapper.vm.isActive).toBe(false) - - expect(wrapper.html()).toMatchSnapshot() - }) -}) diff --git a/packages/vuetify/src/components/VTreeview/__tests__/__snapshots__/VTreeview.spec.ts.snap b/packages/vuetify/src/components/VTreeview/__tests__/__snapshots__/VTreeview.spec.ts.snap deleted file mode 100644 index 5b0b4f90253..00000000000 --- a/packages/vuetify/src/components/VTreeview/__tests__/__snapshots__/VTreeview.spec.ts.snap +++ /dev/null @@ -1,1058 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`VTreeView.ts should emit opened node when using open-on-click and load-children 1`] = ` -
- -
-`; - -exports[`VTreeView.ts should emit opened node when using open-on-click and load-children 2`] = ` -
- -
-`; - -exports[`VTreeView.ts should filter items 1`] = ` -
- - -
-`; - -exports[`VTreeView.ts should filter items 2`] = ` -
- -
-`; - -exports[`VTreeView.ts should filter items using custom item filter 1`] = ` -
-
-`; - -exports[`VTreeView.ts should filter items using custom item filter 2`] = ` -
- -
-`; - -exports[`VTreeView.ts should handle initial active/open/selected values when using return-object prop 1`] = ` -
- -
-
- - -
-
- Two -
-
-
-
- -
-
-
-`; - -exports[`VTreeView.ts should handle replacing items with new array of equal length 1`] = ` -
- - -
-`; - -exports[`VTreeView.ts should handle replacing items with new array of equal length 2`] = ` -
- - -
-`; - -exports[`VTreeView.ts should load children when expanding 1`] = ` -
- -
-`; - -exports[`VTreeView.ts should load children when expanding 2`] = ` -
- -
-`; - -exports[`VTreeView.ts should load children when selecting, but not render 1`] = ` -
- -
-`; - -exports[`VTreeView.ts should load children when selecting, but not render 2`] = ` -
- -
-`; - -exports[`VTreeView.ts should not show expand icon when children is empty 1`] = ` -
- -
-`; - -exports[`VTreeView.ts should open all children when using open-all prop 1`] = ` -
-
-
- -
-
- Root -
-
-
-
-
-
-
-
- -
-
- Child -
-
-
-
- -
-
- -
-
-
-`; - -exports[`VTreeView.ts should react to open changes 1`] = ` -
-
-
- -
-
- Root -
-
-
-
-
-
-
-
- -
-
- Child -
-
-
-
- -
-
- -
-
-
-`; - -exports[`VTreeView.ts should react to open changes 2`] = ` -
-
-
- -
-
- Root -
-
-
-
- - -
-
-
-`; - -exports[`VTreeView.ts should react to open changes 3`] = ` -
-
-
- -
-
- Root -
-
-
-
-
-
-
-
- -
-
- Child -
-
-
-
- -
-
- -
-
-
-`; - -exports[`VTreeView.ts should react to open changes 4`] = ` -
- -
-`; - -exports[`VTreeView.ts should recalculate tree when loading async children using custom key 1`] = ` -
- -
-`; - -exports[`VTreeView.ts should remove old nodes 1`] = ` -
- - -
-`; - -exports[`VTreeView.ts should remove old nodes 2`] = ` -
- -
-`; - -exports[`VTreeView.ts should remove old nodes 3`] = ` -
- - -
-`; - -exports[`VTreeView.ts should render items 1`] = ` -
- -
-`; - -exports[`VTreeView.ts should render items in dense mode 1`] = ` -
- -
-`; - -exports[`VTreeView.ts should select all leaf nodes 1`] = ` -
- -
-`; - -exports[`VTreeView.ts should select only leaf nodes 1`] = ` -
-
-
- - arrow_drop_down - - - $checkboxIndeterminate - -
-
- Root -
-
-
-
- - -
-
-
-`; - -exports[`VTreeView.ts should select only root node 1`] = ` -
- -
-`; - -exports[`VTreeView.ts should show expand icon when children is empty and load-children prop used 1`] = ` -
- -
-`; - -exports[`VTreeView.ts should update selection when selected prop changes 1`] = ` -
- -
-`; - -exports[`VTreeView.ts should update selection when selected prop changes 2`] = ` -
-
-
- - -
-
- Root -
-
-
-
- -
-
-
-`; - -exports[`VTreeView.ts should update selection when selected prop changes 3`] = ` -
-
-
- - -
-
- Root -
-
-
-
- -
-
-
-`; diff --git a/packages/vuetify/src/components/VTreeview/__tests__/__snapshots__/VTreeviewNode.spec.ts.snap b/packages/vuetify/src/components/VTreeview/__tests__/__snapshots__/VTreeviewNode.spec.ts.snap deleted file mode 100644 index a79b542a958..00000000000 --- a/packages/vuetify/src/components/VTreeview/__tests__/__snapshots__/VTreeviewNode.spec.ts.snap +++ /dev/null @@ -1,142 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`VTreeViewNode.ts should be able to have active children with empty array 1`] = ` - -`; - -exports[`VTreeViewNode.ts should generate a transition element 1`] = ` - -`; - -exports[`VTreeViewNode.ts should not be able to have active children with empty array when disabled 1`] = ` - -`; - -exports[`VTreeViewNode.ts should not be able to have active children with empty array when loadChildren is specified 1`] = ` - -`; - -exports[`VTreeViewNode.ts should render disabled item 1`] = ` - -`; - -exports[`VTreeViewNode.ts should use label slot 1`] = ` - -`; - -exports[`VTreeViewNode.ts should use scoped slots 1`] = ` - -`; diff --git a/packages/vuetify/src/components/VTreeview/_mixins.sass b/packages/vuetify/src/components/VTreeview/_mixins.sass deleted file mode 100755 index 01a1a25df95..00000000000 --- a/packages/vuetify/src/components/VTreeview/_mixins.sass +++ /dev/null @@ -1,18 +0,0 @@ -@mixin treeview-shaped($size, $margin) - .v-treeview-node__root, - .v-treeview-node__root:before - border-bottom-right-radius: #{$size * .5} !important - border-top-right-radius: #{$size * .5} !important - - .v-treeview-node__root - margin-top: $margin - margin-bottom: $margin - -@mixin treeview-rounded($size, $margin) - .v-treeview-node__root, - .v-treeview-node__root:before - border-radius: #{$size * .5} !important - - .v-treeview-node__root - margin-top: $margin - margin-bottom: $margin diff --git a/packages/vuetify/src/components/VTreeview/_variables.scss b/packages/vuetify/src/components/VTreeview/_variables.scss deleted file mode 100644 index 463c37e3929..00000000000 --- a/packages/vuetify/src/components/VTreeview/_variables.scss +++ /dev/null @@ -1,10 +0,0 @@ -@import '../../styles/styles.sass'; - -$treeview-transition: .2s map-get($transition, 'linear-out-slow-in') !default; -$treeview-label-font-size: inherit !default; -$treeview-node-height: 48px !default; -$treeview-node-height-dense: 40px !default; -$treeview-node-shaped-margin: 8px !default; -$treeview-node-padding: 8px !default; -$treeview-node-margin: 6px !default; -$treeview-node-level-width: 24px !default; diff --git a/packages/vuetify/src/components/VTreeview/index.ts b/packages/vuetify/src/components/VTreeview/index.ts deleted file mode 100644 index eac51942eec..00000000000 --- a/packages/vuetify/src/components/VTreeview/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import VTreeview from './VTreeview' -import VTreeviewNode from './VTreeviewNode' - -export { VTreeview, VTreeviewNode } - -export default { - $_vuetify_subcomponents: { - VTreeview, - VTreeviewNode, - }, -} diff --git a/packages/vuetify/src/components/VTreeview/util/__tests__/filterTreeItems.spec.ts b/packages/vuetify/src/components/VTreeview/util/__tests__/filterTreeItems.spec.ts deleted file mode 100644 index b89d4022404..00000000000 --- a/packages/vuetify/src/components/VTreeview/util/__tests__/filterTreeItems.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -// @ts-nocheck -/* eslint-disable */ - -// import { filterTreeItem, filterTreeItems } from '../filterTreeItems' - -describe.skip('filterTreeItems.ts', () => { - it('should filter single tree item', () => { - expect(filterTreeItem({ text: 'foo' }, 'foo', 'text')).toBeTruthy() - expect(filterTreeItem({ text: 'foo' }, 'bar', 'text')).toBeFalsy() - expect(filterTreeItem({ text: 'foobar' }, 'foo', 'text')).toBeTruthy() - expect(filterTreeItem({ text: 'FoObAr' }, 'foo', 'text')).toBeTruthy() - expect(filterTreeItem({ text: 'oof' }, 'bar', 'text')).toBeFalsy() - expect(filterTreeItem({ data: 'foo' }, 'foo', 'data')).toBeTruthy() - }) - - it('should filter all tree items', () => { - expect(filterTreeItems(filterTreeItem, { text: 'foo' }, 'foo', 'id', 'text', 'children', new Set())).toBeTruthy() - expect(filterTreeItems(filterTreeItem, { text: 'bar' }, 'foo', 'id', 'text', 'children', new Set())).toBeFalsy() - expect(filterTreeItems(filterTreeItem, { text: 'bar', children: [{ text: 'foo' }] }, 'foo', 'id', 'text', 'children', new Set())).toBeTruthy() - expect(filterTreeItems(filterTreeItem, { text: 'foo', children: [{ text: 'foo' }] }, 'foo', 'id', 'text', 'children', new Set())).toBeTruthy() - expect(filterTreeItems(filterTreeItem, { text: 'bar', children: [{ text: 'baz' }] }, 'foo', 'id', 'text', 'children', new Set())).toBeFalsy() - }) -}) diff --git a/packages/vuetify/src/components/VTreeview/util/filterTreeItems.ts b/packages/vuetify/src/components/VTreeview/util/filterTreeItems.ts deleted file mode 100755 index 946940d498e..00000000000 --- a/packages/vuetify/src/components/VTreeview/util/filterTreeItems.ts +++ /dev/null @@ -1,42 +0,0 @@ -// @ts-nocheck -/* eslint-disable */ - -import { getObjectValueByPath } from '../../../util/helpers' -import { TreeviewItemFunction } from 'vuetify/types' - -export function filterTreeItem (item: object, search: string, textKey: string): boolean { - const text = getObjectValueByPath(item, textKey) - - return text.toLocaleLowerCase().indexOf(search.toLocaleLowerCase()) > -1 -} - -export function filterTreeItems ( - filter: TreeviewItemFunction, - item: any, - search: string, - idKey: string, - textKey: string, - childrenKey: string, - excluded: Set -): boolean { - if (filter(item, search, textKey)) { - return true - } - - const children = getObjectValueByPath(item, childrenKey) - - if (children) { - let match = false - for (let i = 0; i < children.length; i++) { - if (filterTreeItems(filter, children[i], search, idKey, textKey, childrenKey, excluded)) { - match = true - } - } - - if (match) return true - } - - excluded.add(getObjectValueByPath(item, idKey)) - - return false -} diff --git a/packages/vuetify/src/components/index.ts b/packages/vuetify/src/components/index.ts index 9460f5197cb..d8173d050ce 100644 --- a/packages/vuetify/src/components/index.ts +++ b/packages/vuetify/src/components/index.ts @@ -19,7 +19,6 @@ export * from './VChip' export * from './VChipGroup' export * from './VCode' export * from './VColorPicker' -// export * from './VContent' export * from './VCombobox' export * from './VConfirmEdit' export * from './VCounter'