This commit is contained in:
darenhsu
2022-07-17 13:16:16 +08:00
parent 84759556ff
commit befd344ab0
28070 changed files with 4008428 additions and 1 deletions
+70
View File
@@ -0,0 +1,70 @@
@import './_variables.scss'
// Block
.v-data-footer
display: flex
flex-wrap: wrap
justify-content: flex-end
align-items: center
font-size: $data-footer-font-size
padding: $data-footer-padding
.v-btn
color: inherit
// Elements
.v-data-footer__icons-before
.v-btn:last-child
+ltr()
margin-right: $data-footer-icons-before-btn-margin-end
+rtl()
margin-left: $data-footer-icons-before-btn-margin-end
.v-data-footer__icons-after
.v-btn:first-child
+ltr()
margin-left: $data-footer-icons-after-btn-margin-start
+rtl()
margin-right: $data-footer-icons-after-btn-margin-start
.v-data-footer__pagination
display: block
text-align: center
+ltr()
margin: 0 $data-footer-pagination-margin-end 0 $data-footer-pagination-margin-start
+rtl()
margin: 0 $data-footer-pagination-margin-start 0 $data-footer-pagination-margin-end
.v-data-footer__select
display: flex
align-items: center
flex: 0 0 0
justify-content: flex-end
white-space: nowrap
+ltr()
margin-right: $data-footer-select-margin-end
+rtl()
margin-left: $data-footer-select-margin-end
.v-select
flex: 0 1 0
padding: 0
position: initial
+ltr()
margin: $data-footer-select-select-margin-y 0 $data-footer-select-select-margin-y $data-footer-select-select-margin-start
+rtl()
margin: $data-footer-select-select-margin-y $data-footer-select-select-margin-start $data-footer-select-select-margin-y 0
.v-select__selections
flex-wrap: nowrap
.v-select__selection--comma
font-size: $data-footer-select-selections-comma-font-size
+223
View File
@@ -0,0 +1,223 @@
import './VDataFooter.sass'
// Components
import VSelect from '../VSelect/VSelect'
import VIcon from '../VIcon'
import VBtn from '../VBtn'
// Types
import Vue, { VNode, VNodeChildrenArrayContents, PropType } from 'vue'
import { DataPagination, DataOptions, DataItemsPerPageOption } from 'vuetify/types'
import { PropValidator } from 'vue/types/options'
export default Vue.extend({
name: 'v-data-footer',
props: {
options: {
type: Object as PropType<DataOptions>,
required: true,
},
pagination: {
type: Object as PropType<DataPagination>,
required: true,
},
itemsPerPageOptions: {
type: Array,
default: () => ([5, 10, 15, -1]),
} as PropValidator<DataItemsPerPageOption[]>,
prevIcon: {
type: String,
default: '$prev',
},
nextIcon: {
type: String,
default: '$next',
},
firstIcon: {
type: String,
default: '$first',
},
lastIcon: {
type: String,
default: '$last',
},
itemsPerPageText: {
type: String,
default: '$vuetify.dataFooter.itemsPerPageText',
},
itemsPerPageAllText: {
type: String,
default: '$vuetify.dataFooter.itemsPerPageAll',
},
showFirstLastPage: Boolean,
showCurrentPage: Boolean,
disablePagination: Boolean,
disableItemsPerPage: Boolean,
pageText: {
type: String,
default: '$vuetify.dataFooter.pageText',
},
},
computed: {
disableNextPageIcon (): boolean {
return this.options.itemsPerPage <= 0 ||
this.options.page * this.options.itemsPerPage >= this.pagination.itemsLength ||
this.pagination.pageStop < 0
},
computedDataItemsPerPageOptions (): any[] {
return this.itemsPerPageOptions.map(option => {
if (typeof option === 'object') return option
else return this.genDataItemsPerPageOption(option)
})
},
},
methods: {
updateOptions (obj: object) {
this.$emit('update:options', Object.assign({}, this.options, obj))
},
onFirstPage () {
this.updateOptions({ page: 1 })
},
onPreviousPage () {
this.updateOptions({ page: this.options.page - 1 })
},
onNextPage () {
this.updateOptions({ page: this.options.page + 1 })
},
onLastPage () {
this.updateOptions({ page: this.pagination.pageCount })
},
onChangeItemsPerPage (itemsPerPage: number) {
this.updateOptions({ itemsPerPage, page: 1 })
},
genDataItemsPerPageOption (option: number) {
return {
text: option === -1 ? this.$vuetify.lang.t(this.itemsPerPageAllText) : String(option),
value: option,
}
},
genItemsPerPageSelect () {
let value = this.options.itemsPerPage
const computedIPPO = this.computedDataItemsPerPageOptions
if (computedIPPO.length <= 1) return null
if (!computedIPPO.find(ippo => ippo.value === value)) value = computedIPPO[0]
return this.$createElement('div', {
staticClass: 'v-data-footer__select',
}, [
this.$vuetify.lang.t(this.itemsPerPageText),
this.$createElement(VSelect, {
attrs: {
'aria-label': this.itemsPerPageText,
},
props: {
disabled: this.disableItemsPerPage,
items: computedIPPO,
value,
hideDetails: true,
auto: true,
minWidth: '75px',
},
on: {
input: this.onChangeItemsPerPage,
},
}),
])
},
genPaginationInfo () {
let children: VNodeChildrenArrayContents = ['']
if (this.pagination.itemsLength && this.pagination.itemsPerPage) {
const itemsLength = this.pagination.itemsLength
const pageStart = this.pagination.pageStart + 1
const pageStop = itemsLength < this.pagination.pageStop || this.pagination.pageStop < 0
? itemsLength
: this.pagination.pageStop
children = this.$scopedSlots['page-text']
? [this.$scopedSlots['page-text']!({ pageStart, pageStop, itemsLength })]
: [this.$vuetify.lang.t(this.pageText, pageStart, pageStop, itemsLength)]
}
return this.$createElement('div', {
class: 'v-data-footer__pagination',
}, children)
},
genIcon (click: Function, disabled: boolean, label: string, icon: string): VNode {
return this.$createElement(VBtn, {
props: {
disabled: disabled || this.disablePagination,
icon: true,
text: true,
// dark: this.dark, // TODO: add mixin
// light: this.light // TODO: add mixin
},
on: {
click,
},
attrs: {
'aria-label': label, // TODO: Localization
},
}, [this.$createElement(VIcon, icon)])
},
genIcons () {
const before: VNodeChildrenArrayContents = []
const after: VNodeChildrenArrayContents = []
before.push(this.genIcon(
this.onPreviousPage,
this.options.page === 1,
this.$vuetify.lang.t('$vuetify.dataFooter.prevPage'),
this.$vuetify.rtl ? this.nextIcon : this.prevIcon
))
after.push(this.genIcon(
this.onNextPage,
this.disableNextPageIcon,
this.$vuetify.lang.t('$vuetify.dataFooter.nextPage'),
this.$vuetify.rtl ? this.prevIcon : this.nextIcon
))
if (this.showFirstLastPage) {
before.unshift(this.genIcon(
this.onFirstPage,
this.options.page === 1,
this.$vuetify.lang.t('$vuetify.dataFooter.firstPage'),
this.$vuetify.rtl ? this.lastIcon : this.firstIcon
))
after.push(this.genIcon(
this.onLastPage,
this.options.page >= this.pagination.pageCount || this.options.itemsPerPage === -1,
this.$vuetify.lang.t('$vuetify.dataFooter.lastPage'),
this.$vuetify.rtl ? this.firstIcon : this.lastIcon
))
}
return [
this.$createElement('div', {
staticClass: 'v-data-footer__icons-before',
}, before),
this.showCurrentPage && this.$createElement('span', [this.options.page.toString()]),
this.$createElement('div', {
staticClass: 'v-data-footer__icons-after',
}, after),
]
},
},
render (): VNode {
return this.$createElement('div', {
staticClass: 'v-data-footer',
}, [
this.genItemsPerPageSelect(),
this.genPaginationInfo(),
this.genIcons(),
])
},
})
+313
View File
@@ -0,0 +1,313 @@
// Components
import { VData } from '../VData'
import VDataFooter from './VDataFooter'
// Mixins
import Mobile from '../../mixins/mobile'
import Themeable from '../../mixins/themeable'
// Helpers
import mixins from '../../util/mixins'
import { deepEqual, getObjectValueByPath, getPrefixedScopedSlots, getSlot, camelizeObjectKeys } from '../../util/helpers'
import { breaking, removed } from '../../util/console'
// Types
import { VNode, VNodeChildren, PropType } from 'vue'
import { DataItemProps, DataScopeProps } from 'vuetify/types'
/* @vue/component */
export default mixins(
Mobile,
Themeable
).extend({
name: 'v-data-iterator',
props: {
...VData.options.props, // TODO: filter out props not used
itemKey: {
type: String,
default: 'id',
},
value: {
type: Array as PropType<any[]>,
default: () => [],
},
singleSelect: Boolean,
expanded: {
type: Array as PropType<any[]>,
default: () => [],
},
mobileBreakpoint: {
...Mobile.options.props.mobileBreakpoint,
default: 600,
},
singleExpand: Boolean,
loading: [Boolean, String],
noResultsText: {
type: String,
default: '$vuetify.dataIterator.noResultsText',
},
noDataText: {
type: String,
default: '$vuetify.noDataText',
},
loadingText: {
type: String,
default: '$vuetify.dataIterator.loadingText',
},
hideDefaultFooter: Boolean,
footerProps: Object,
selectableKey: {
type: String,
default: 'isSelectable',
},
},
data: () => ({
selection: {} as Record<string, any>,
expansion: {} as Record<string, boolean>,
internalCurrentItems: [] as any[],
}),
computed: {
everyItem (): boolean {
return !!this.selectableItems.length && this.selectableItems.every((i: any) => this.isSelected(i))
},
someItems (): boolean {
return this.selectableItems.some((i: any) => this.isSelected(i))
},
sanitizedFooterProps (): Record<string, any> {
return camelizeObjectKeys(this.footerProps)
},
selectableItems (): any[] {
return this.internalCurrentItems.filter(item => this.isSelectable(item))
},
},
watch: {
value: {
handler (value: any[]) {
this.selection = value.reduce((selection, item) => {
selection[getObjectValueByPath(item, this.itemKey)] = item
return selection
}, {})
},
immediate: true,
},
selection (value: Record<string, boolean>, old: Record<string, boolean>) {
if (deepEqual(Object.keys(value), Object.keys(old))) return
this.$emit('input', Object.values(value))
},
expanded: {
handler (value: any[]) {
this.expansion = value.reduce((expansion, item) => {
expansion[getObjectValueByPath(item, this.itemKey)] = true
return expansion
}, {})
},
immediate: true,
},
expansion (value: Record<string, boolean>, old: Record<string, boolean>) {
if (deepEqual(value, old)) return
const keys = Object.keys(value).filter(k => value[k])
const expanded = !keys.length ? [] : this.items.filter(i => keys.includes(String(getObjectValueByPath(i, this.itemKey))))
this.$emit('update:expanded', expanded)
},
},
created () {
const breakingProps = [
['disable-initial-sort', 'sort-by'],
['filter', 'custom-filter'],
['pagination', 'options'],
['total-items', 'server-items-length'],
['hide-actions', 'hide-default-footer'],
['rows-per-page-items', 'footer-props.items-per-page-options'],
['rows-per-page-text', 'footer-props.items-per-page-text'],
['prev-icon', 'footer-props.prev-icon'],
['next-icon', 'footer-props.next-icon'],
]
/* istanbul ignore next */
breakingProps.forEach(([original, replacement]) => {
if (this.$attrs.hasOwnProperty(original)) breaking(original, replacement, this)
})
const removedProps = [
'expand',
'content-class',
'content-props',
'content-tag',
]
/* istanbul ignore next */
removedProps.forEach(prop => {
if (this.$attrs.hasOwnProperty(prop)) removed(prop)
})
},
methods: {
toggleSelectAll (value: boolean): void {
const selection = Object.assign({}, this.selection)
for (let i = 0; i < this.selectableItems.length; i++) {
const item = this.selectableItems[i]
if (!this.isSelectable(item)) continue
const key = getObjectValueByPath(item, this.itemKey)
if (value) selection[key] = item
else delete selection[key]
}
this.selection = selection
this.$emit('toggle-select-all', { items: this.internalCurrentItems, value })
},
isSelectable (item: any): boolean {
return getObjectValueByPath(item, this.selectableKey) !== false
},
isSelected (item: any): boolean {
return !!this.selection[getObjectValueByPath(item, this.itemKey)] || false
},
select (item: any, value = true, emit = true): void {
if (!this.isSelectable(item)) return
const selection = this.singleSelect ? {} : Object.assign({}, this.selection)
const key = getObjectValueByPath(item, this.itemKey)
if (value) selection[key] = item
else delete selection[key]
if (this.singleSelect && emit) {
const keys = Object.keys(this.selection)
const old = keys.length && getObjectValueByPath(this.selection[keys[0]], this.itemKey)
old && old !== key && this.$emit('item-selected', { item: this.selection[old], value: false })
}
this.selection = selection
emit && this.$emit('item-selected', { item, value })
},
isExpanded (item: any): boolean {
return this.expansion[getObjectValueByPath(item, this.itemKey)] || false
},
expand (item: any, value = true): void {
const expansion = this.singleExpand ? {} : Object.assign({}, this.expansion)
const key = getObjectValueByPath(item, this.itemKey)
if (value) expansion[key] = true
else delete expansion[key]
this.expansion = expansion
this.$emit('item-expanded', { item, value })
},
createItemProps (item: any): DataItemProps {
return {
item,
select: (v: boolean) => this.select(item, v),
isSelected: this.isSelected(item),
expand: (v: boolean) => this.expand(item, v),
isExpanded: this.isExpanded(item),
isMobile: this.isMobile,
}
},
genEmptyWrapper (content: VNodeChildren) {
return this.$createElement('div', content)
},
genEmpty (originalItemsLength: number, filteredItemsLength: number) {
if (originalItemsLength === 0 && this.loading) {
const loading = this.$slots['loading'] || this.$vuetify.lang.t(this.loadingText)
return this.genEmptyWrapper(loading)
} else if (originalItemsLength === 0) {
const noData = this.$slots['no-data'] || this.$vuetify.lang.t(this.noDataText)
return this.genEmptyWrapper(noData)
} else if (filteredItemsLength === 0) {
const noResults = this.$slots['no-results'] || this.$vuetify.lang.t(this.noResultsText)
return this.genEmptyWrapper(noResults)
}
return null
},
genItems (props: DataScopeProps) {
const empty = this.genEmpty(props.originalItemsLength, props.pagination.itemsLength)
if (empty) return [empty]
if (this.$scopedSlots.default) {
return this.$scopedSlots.default({
...props,
isSelected: this.isSelected,
select: this.select,
isExpanded: this.isExpanded,
expand: this.expand,
})
}
if (this.$scopedSlots.item) {
return props.items.map((item: any) => this.$scopedSlots.item!(this.createItemProps(item)))
}
return []
},
genFooter (props: DataScopeProps) {
if (this.hideDefaultFooter) return null
const data = {
props: {
...this.sanitizedFooterProps,
options: props.options,
pagination: props.pagination,
},
on: {
'update:options': (value: any) => props.updateOptions(value),
},
}
const scopedSlots = getPrefixedScopedSlots('footer.', this.$scopedSlots)
return this.$createElement(VDataFooter, {
scopedSlots,
...data,
})
},
genDefaultScopedSlot (props: any) {
const outerProps = {
...props,
someItems: this.someItems,
everyItem: this.everyItem,
toggleSelectAll: this.toggleSelectAll,
}
return this.$createElement('div', {
staticClass: 'v-data-iterator',
}, [
getSlot(this, 'header', outerProps, true),
this.genItems(props),
this.genFooter(props),
getSlot(this, 'footer', outerProps, true),
])
},
},
render (): VNode {
return this.$createElement(VData, {
props: this.$props,
on: {
'update:options': (v: any, old: any) => !deepEqual(v, old) && this.$emit('update:options', v),
'update:page': (v: any) => this.$emit('update:page', v),
'update:items-per-page': (v: any) => this.$emit('update:items-per-page', v),
'update:sort-by': (v: any) => this.$emit('update:sort-by', v),
'update:sort-desc': (v: any) => this.$emit('update:sort-desc', v),
'update:group-by': (v: any) => this.$emit('update:group-by', v),
'update:group-desc': (v: any) => this.$emit('update:group-desc', v),
pagination: (v: any, old: any) => !deepEqual(v, old) && this.$emit('pagination', v),
'current-items': (v: any[]) => {
this.internalCurrentItems = v
this.$emit('current-items', v)
},
'page-count': (v: number) => this.$emit('page-count', v),
},
scopedSlots: {
default: this.genDefaultScopedSlot,
},
})
},
})
@@ -0,0 +1,201 @@
import VDataFooter from '../VDataFooter'
import { Lang } from '../../../services/lang'
import {
mount,
MountOptions,
Wrapper,
} from '@vue/test-utils'
import Vue from 'vue'
import { preset } from '../../../presets/default'
Vue.prototype.$vuetify = {
icons: {
values: {
prev: 'mdi-chevron-left',
next: 'mdi-chevron-right',
dropdown: 'mdi-menu-down',
first: 'mdi-page-first',
last: 'mdi-page-last',
},
},
}
describe('VDataFooter.ts', () => {
type Instance = InstanceType<typeof VDataFooter>
let mountFunction: (options?: MountOptions<Instance>) => Wrapper<Instance>
beforeEach(() => {
document.body.setAttribute('data-app', '')
mountFunction = (options?: MountOptions<Instance>) => {
return mount(VDataFooter, {
// https://github.com/vuejs/vue-test-utils/issues/1130
sync: false,
mocks: {
$vuetify: {
lang: new Lang(preset),
theme: {
dark: false,
},
},
},
...options,
})
}
})
it('should render with custom itemsPerPage', () => {
const wrapper = mountFunction({
propsData: {
itemsPerPageOptions: [50, 100],
options: {
page: 4,
itemsPerPage: 100,
},
pagination: {
page: 4,
itemsPerPage: 10,
pageStart: 1,
pageStop: 10,
pageCount: 10,
itemsLength: 100,
},
},
})
expect(wrapper.html()).toMatchSnapshot()
})
it('should render in RTL mode', () => {
const wrapper = mountFunction({
propsData: {
options: {
page: 4,
itemsPerPage: 10,
},
pagination: {
page: 4,
itemsPerPage: 10,
pageStart: 1,
pageStop: 10,
pageCount: 10,
itemsLength: 100,
},
showFirstLastPage: true,
},
mocks: {
$vuetify: {
rtl: true,
lang: new Lang(preset),
theme: {
dark: false,
},
},
},
})
expect(wrapper.html()).toMatchSnapshot()
})
it('should render first & last icons with showFirstLastPage', () => {
const wrapper = mountFunction({
propsData: {
options: {
page: 4,
itemsPerPage: 10,
},
pagination: {
page: 4,
itemsPerPage: 10,
pageStart: 1,
pageStop: 10,
pageCount: 10,
itemsLength: 100,
},
showFirstLastPage: true,
},
})
expect(wrapper.html()).toMatchSnapshot()
})
it('should switch between pages', () => {
const mock = jest.fn()
const wrapper = mountFunction({
propsData: {
options: {
page: 4,
itemsPerPage: 10,
},
pagination: {
page: 4,
itemsPerPage: 10,
pageStart: 1,
pageStop: 10,
pageCount: 10,
itemsLength: 100,
},
},
listeners: {
'update:options': mock,
},
})
wrapper.vm.onNextPage()
expect(mock).toHaveBeenCalledWith({ itemsPerPage: 10, page: 5 })
wrapper.vm.onPreviousPage()
expect(mock).toHaveBeenCalledWith({ itemsPerPage: 10, page: 3 })
wrapper.vm.onFirstPage()
expect(mock).toHaveBeenCalledWith({ itemsPerPage: 10, page: 1 })
wrapper.vm.onLastPage()
expect(mock).toHaveBeenCalledWith({ itemsPerPage: 10, page: 10 })
wrapper.vm.onChangeItemsPerPage(5)
expect(mock).toHaveBeenCalledWith({ itemsPerPage: 5, page: 1 })
wrapper.vm.onChangeItemsPerPage(20)
expect(mock).toHaveBeenCalledWith({ itemsPerPage: 20, page: 1 })
})
it('should show current page if has showCurrentPage', () => {
const wrapper = mountFunction({
propsData: {
options: {
page: 4,
itemsPerPage: 10,
},
pagination: {
page: 4,
itemsPerPage: 10,
pageStart: 1,
pageStop: 10,
pageCount: 10,
itemsLength: 100,
},
showCurrentPage: true,
},
})
expect(wrapper.html()).toMatchSnapshot()
})
it('should disable last page button if no items', () => {
const wrapper = mountFunction({
propsData: {
options: {
page: 1,
itemsPerPage: 10,
},
pagination: {
page: 1,
itemsPerPage: 10,
pageStart: 0,
pageStop: 0,
pageCount: 0,
itemsLength: 0,
},
showFirstLastPage: true,
},
})
expect(wrapper.html()).toMatchSnapshot()
})
})
@@ -0,0 +1,350 @@
import VDataIterator from '../VDataIterator'
import { Lang } from '../../../services/lang'
import {
mount,
MountOptions,
Wrapper,
} from '@vue/test-utils'
import Vue from 'vue'
import { Breakpoint } from '../../../services/breakpoint'
import { preset } from '../../../presets/default'
Vue.prototype.$vuetify = {
icons: {
values: {
prev: 'mdi-chevron-left',
next: 'mdi-chevron-right',
dropdown: 'mdi-menu-down',
first: 'mdi-page-first',
last: 'mdi-page-last',
},
},
}
describe('VDataIterator.ts', () => {
type Instance = InstanceType<typeof VDataIterator>
let mountFunction: (options?: MountOptions<Instance>) => Wrapper<Instance>
beforeEach(() => {
document.body.setAttribute('data-app', '')
mountFunction = (options?: MountOptions<Instance>) => {
return mount(VDataIterator, {
mocks: {
$vuetify: {
breakpoint: new Breakpoint(preset),
lang: new Lang(preset),
theme: {
dark: false,
},
},
},
sync: false,
...options,
})
}
})
it('should render and match snapshot', () => {
const wrapper = mountFunction()
expect(wrapper.html()).toMatchSnapshot()
})
it('should render and match snapshot with data', () => {
const wrapper = mountFunction({
propsData: {
items: [
'foo',
'bar',
'baz',
'qux',
],
},
scopedSlots: {
item (props) {
return this.$createElement('div', [props.item])
},
},
})
expect(wrapper.html()).toMatchSnapshot()
})
it('should render valid no-data, loading and no-results states', async () => {
const wrapper = mountFunction({
propsData: {
items: [],
serverItemsLength: 0,
},
})
await wrapper.vm.$nextTick()
expect(wrapper.html()).toMatchSnapshot()
wrapper.setProps({
loading: true,
items: [],
})
await wrapper.vm.$nextTick()
expect(wrapper.html()).toMatchSnapshot()
wrapper.setProps({
loading: false,
items: ['foo'],
search: 'something',
})
await wrapper.vm.$nextTick()
expect(wrapper.html()).toMatchSnapshot()
})
it('should emit when selection happens', async () => {
const input = jest.fn()
const wrapper = mountFunction({
propsData: {
itemKey: 'id',
items: [
{ id: 1, text: 'foo' },
{ id: 2, text: 'bar' },
],
},
listeners: {
input,
},
scopedSlots: {
item (props) {
return this.$createElement('div', {
attrs: {
id: props.item.text,
},
on: {
click: () => props.select(true),
},
}, [props.item.text])
},
},
})
const foo = wrapper.find('#foo')
foo.element.click()
await wrapper.vm.$nextTick()
expect(input).toHaveBeenCalledWith([{ id: 1, text: 'foo' }])
})
it('should emit when expansion happens', async () => {
const input = jest.fn()
const wrapper = mountFunction({
propsData: {
itemKey: 'id',
items: [
{ id: 1, text: 'foo' },
{ id: 2, text: 'bar' },
],
},
listeners: {
'update:expanded': input,
},
scopedSlots: {
item (props) {
return this.$createElement('div', {
attrs: {
id: props.item.text,
},
on: {
click: () => props.expand(true),
},
}, [props.item.text])
},
},
})
const foo = wrapper.find('#bar')
foo.element.click()
await wrapper.vm.$nextTick()
expect(input).toHaveBeenCalledWith([{ id: 2, text: 'bar' }])
})
it('should select all', async () => {
const input = jest.fn()
const items = [
{ id: 'foo' },
{ id: 'bar' },
]
const toggleSelectAll = jest.fn()
const wrapper = mountFunction({
propsData: {
items,
},
listeners: {
input,
'toggle-select-all': toggleSelectAll,
},
scopedSlots: {
header (props) {
return this.$createElement('div', {
attrs: {
id: 'header',
},
on: {
click: () => props.toggleSelectAll(true),
},
})
},
},
})
const header = wrapper.find('#header')
header.element.click()
await wrapper.vm.$nextTick()
expect(input).toHaveBeenCalledWith(items)
expect(toggleSelectAll).toHaveBeenCalledWith({ items, value: true })
})
it('should update expansion from the outside', async () => {
const mock = jest.fn()
const wrapper = mountFunction({
propsData: {
items: [
{ id: 'foo' },
{ id: 'bar' },
],
},
listeners: {
'update:expanded': mock,
},
})
wrapper.setProps({
expanded: [{ id: 'foo' }],
})
await wrapper.vm.$nextTick()
expect(mock).toHaveBeenLastCalledWith([{ id: 'foo' }])
wrapper.setProps({
expanded: [{ id: 'bar' }],
})
await wrapper.vm.$nextTick()
expect(mock).toHaveBeenLastCalledWith([{ id: 'bar' }])
})
it('should update selection from the outside', async () => {
const mock = jest.fn()
const wrapper = mountFunction({
propsData: {
items: [
{ id: 'foo' },
{ id: 'bar' },
],
},
listeners: {
input: mock,
},
})
wrapper.setProps({
value: [{ id: 'foo' }],
})
await wrapper.vm.$nextTick()
expect(mock).toHaveBeenLastCalledWith([{ id: 'foo' }])
wrapper.setProps({
value: [{ id: 'bar' }],
})
await wrapper.vm.$nextTick()
expect(mock).toHaveBeenLastCalledWith([{ id: 'bar' }])
})
it('should check if all items are selected', async () => {
const render = jest.fn()
const items = [
{ id: 'foo' }, { id: 'bar' },
]
const wrapper = mountFunction({
propsData: {
items,
},
scopedSlots: {
header: render,
},
})
wrapper.setProps({
value: items,
})
await wrapper.vm.$nextTick()
expect(render).toHaveBeenLastCalledWith(expect.objectContaining({
everyItem: true,
someItems: true,
}))
})
it('should check if some items are selected', async () => {
const render = jest.fn()
const items = [
{ id: 'foo' }, { id: 'bar' },
]
const wrapper = mountFunction({
propsData: {
items,
},
scopedSlots: {
header: render,
},
})
wrapper.setProps({
value: items.slice(1),
})
await wrapper.vm.$nextTick()
expect(render).toHaveBeenLastCalledWith(expect.objectContaining({
everyItem: false,
someItems: true,
}))
})
it('should hide footer', () => {
const wrapper = mountFunction({
propsData: {
hideDefaultFooter: true,
},
})
expect(wrapper.html()).toMatchSnapshot()
})
// https://github.com/vuetifyjs/vuetify/issues/8886
it('should emit page-count event', async () => {
const pageCount = jest.fn()
const wrapper = mountFunction({
propsData: {
items: [
'foo',
'bar',
'baz',
'qux',
],
itemsPerPage: 1,
},
listeners: {
pageCount,
},
})
wrapper.setProps({ itemsPerPage: 4 })
await wrapper.vm.$nextTick()
expect(wrapper.emitted('page-count')).toEqual([[4], [1]])
})
})
@@ -0,0 +1,450 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`VDataFooter.ts should disable last page button if no items 1`] = `
<div class="v-data-footer">
<div class="v-data-footer__select">
Items per page:
<div class="v-input v-input--hide-details v-input--is-label-active v-input--is-dirty theme--light v-text-field v-select">
<div class="v-input__control">
<div role="button"
aria-haspopup="listbox"
aria-expanded="false"
aria-owns="list-55"
class="v-input__slot"
>
<div class="v-select__slot">
<div class="v-select__selections">
<div class="v-select__selection v-select__selection--comma">
10
</div>
<input aria-label="$vuetify.dataFooter.itemsPerPageText"
id="input-55"
readonly="readonly"
type="text"
aria-readonly="false"
autocomplete="off"
>
</div>
<div class="v-input__append-inner">
<div class="v-input__icon v-input__icon--append">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-menu-down theme--light"
>
</i>
</div>
</div>
<input type="hidden"
value="10"
>
</div>
<div class="v-menu">
</div>
</div>
</div>
</div>
</div>
<div class="v-data-footer__pagination">
</div>
<div class="v-data-footer__icons-before">
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="First page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-page-first theme--light"
>
</i>
</span>
</button>
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Previous page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-left theme--light"
>
</i>
</span>
</button>
</div>
<div class="v-data-footer__icons-after">
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Next page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-right theme--light"
>
</i>
</span>
</button>
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Last page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-page-last theme--light"
>
</i>
</span>
</button>
</div>
</div>
`;
exports[`VDataFooter.ts should render first & last icons with showFirstLastPage 1`] = `
<div class="v-data-footer">
<div class="v-data-footer__select">
Items per page:
<div class="v-input v-input--hide-details v-input--is-label-active v-input--is-dirty theme--light v-text-field v-select">
<div class="v-input__control">
<div role="button"
aria-haspopup="listbox"
aria-expanded="false"
aria-owns="list-24"
class="v-input__slot"
>
<div class="v-select__slot">
<div class="v-select__selections">
<div class="v-select__selection v-select__selection--comma">
10
</div>
<input aria-label="$vuetify.dataFooter.itemsPerPageText"
id="input-24"
readonly="readonly"
type="text"
aria-readonly="false"
autocomplete="off"
>
</div>
<div class="v-input__append-inner">
<div class="v-input__icon v-input__icon--append">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-menu-down theme--light"
>
</i>
</div>
</div>
<input type="hidden"
value="10"
>
</div>
<div class="v-menu">
</div>
</div>
</div>
</div>
</div>
<div class="v-data-footer__pagination">
2-10 of 100
</div>
<div class="v-data-footer__icons-before">
<button type="button"
class="v-btn v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="First page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-page-first theme--light"
>
</i>
</span>
</button>
<button type="button"
class="v-btn v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Previous page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-left theme--light"
>
</i>
</span>
</button>
</div>
<div class="v-data-footer__icons-after">
<button type="button"
class="v-btn v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Next page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-right theme--light"
>
</i>
</span>
</button>
<button type="button"
class="v-btn v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Last page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-page-last theme--light"
>
</i>
</span>
</button>
</div>
</div>
`;
exports[`VDataFooter.ts should render in RTL mode 1`] = `
<div class="v-data-footer">
<div class="v-data-footer__select">
Items per page:
<div class="v-input v-input--hide-details v-input--is-label-active v-input--is-dirty theme--light v-text-field v-select">
<div class="v-input__control">
<div role="button"
aria-haspopup="listbox"
aria-expanded="false"
aria-owns="list-11"
class="v-input__slot"
>
<div class="v-select__slot">
<div class="v-select__selections">
<div class="v-select__selection v-select__selection--comma">
10
</div>
<input aria-label="$vuetify.dataFooter.itemsPerPageText"
id="input-11"
readonly="readonly"
type="text"
aria-readonly="false"
autocomplete="off"
>
</div>
<div class="v-input__append-inner">
<div class="v-input__icon v-input__icon--append">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-menu-down theme--light"
>
</i>
</div>
</div>
<input type="hidden"
value="10"
>
</div>
<div class="v-menu">
</div>
</div>
</div>
</div>
</div>
<div class="v-data-footer__pagination">
2-10 of 100
</div>
<div class="v-data-footer__icons-before">
<button type="button"
class="v-btn v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="First page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-page-last theme--light"
>
</i>
</span>
</button>
<button type="button"
class="v-btn v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Previous page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-right theme--light"
>
</i>
</span>
</button>
</div>
<div class="v-data-footer__icons-after">
<button type="button"
class="v-btn v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Next page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-left theme--light"
>
</i>
</span>
</button>
<button type="button"
class="v-btn v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Last page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-page-first theme--light"
>
</i>
</span>
</button>
</div>
</div>
`;
exports[`VDataFooter.ts should render with custom itemsPerPage 1`] = `
<div class="v-data-footer">
<div class="v-data-footer__select">
Items per page:
<div class="v-input v-input--hide-details v-input--is-label-active v-input--is-dirty theme--light v-text-field v-select">
<div class="v-input__control">
<div role="button"
aria-haspopup="listbox"
aria-expanded="false"
aria-owns="list-2"
class="v-input__slot"
>
<div class="v-select__slot">
<div class="v-select__selections">
<div class="v-select__selection v-select__selection--comma">
100
</div>
<input aria-label="$vuetify.dataFooter.itemsPerPageText"
id="input-2"
readonly="readonly"
type="text"
aria-readonly="false"
autocomplete="off"
>
</div>
<div class="v-input__append-inner">
<div class="v-input__icon v-input__icon--append">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-menu-down theme--light"
>
</i>
</div>
</div>
<input type="hidden"
value="100"
>
</div>
<div class="v-menu">
</div>
</div>
</div>
</div>
</div>
<div class="v-data-footer__pagination">
2-10 of 100
</div>
<div class="v-data-footer__icons-before">
<button type="button"
class="v-btn v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Previous page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-left theme--light"
>
</i>
</span>
</button>
</div>
<div class="v-data-footer__icons-after">
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Next page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-right theme--light"
>
</i>
</span>
</button>
</div>
</div>
`;
exports[`VDataFooter.ts should show current page if has showCurrentPage 1`] = `
<div class="v-data-footer">
<div class="v-data-footer__select">
Items per page:
<div class="v-input v-input--hide-details v-input--is-label-active v-input--is-dirty theme--light v-text-field v-select">
<div class="v-input__control">
<div role="button"
aria-haspopup="listbox"
aria-expanded="false"
aria-owns="list-46"
class="v-input__slot"
>
<div class="v-select__slot">
<div class="v-select__selections">
<div class="v-select__selection v-select__selection--comma">
10
</div>
<input aria-label="$vuetify.dataFooter.itemsPerPageText"
id="input-46"
readonly="readonly"
type="text"
aria-readonly="false"
autocomplete="off"
>
</div>
<div class="v-input__append-inner">
<div class="v-input__icon v-input__icon--append">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-menu-down theme--light"
>
</i>
</div>
</div>
<input type="hidden"
value="10"
>
</div>
<div class="v-menu">
</div>
</div>
</div>
</div>
</div>
<div class="v-data-footer__pagination">
2-10 of 100
</div>
<div class="v-data-footer__icons-before">
<button type="button"
class="v-btn v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Previous page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-left theme--light"
>
</i>
</span>
</button>
</div>
<span>
4
</span>
<div class="v-data-footer__icons-after">
<button type="button"
class="v-btn v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Next page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-right theme--light"
>
</i>
</span>
</button>
</div>
</div>
`;
@@ -0,0 +1,428 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`VDataIterator.ts should hide footer 1`] = `
<div class="v-data-iterator">
<div>
No data available
</div>
</div>
`;
exports[`VDataIterator.ts should render and match snapshot 1`] = `
<div class="v-data-iterator">
<div>
No data available
</div>
<div class="v-data-footer">
<div class="v-data-footer__select">
Items per page:
<div class="v-input v-input--hide-details v-input--is-label-active v-input--is-dirty theme--light v-text-field v-select">
<div class="v-input__control">
<div role="button"
aria-haspopup="listbox"
aria-expanded="false"
aria-owns="list-4"
class="v-input__slot"
>
<div class="v-select__slot">
<div class="v-select__selections">
<div class="v-select__selection v-select__selection--comma">
10
</div>
<input aria-label="$vuetify.dataFooter.itemsPerPageText"
id="input-4"
readonly="readonly"
type="text"
aria-readonly="false"
autocomplete="off"
>
</div>
<div class="v-input__append-inner">
<div class="v-input__icon v-input__icon--append">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-menu-down theme--light"
>
</i>
</div>
</div>
<input type="hidden"
value="10"
>
</div>
<div class="v-menu">
</div>
</div>
</div>
</div>
</div>
<div class="v-data-footer__pagination">
</div>
<div class="v-data-footer__icons-before">
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Previous page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-left theme--light"
>
</i>
</span>
</button>
</div>
<div class="v-data-footer__icons-after">
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Next page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-right theme--light"
>
</i>
</span>
</button>
</div>
</div>
</div>
`;
exports[`VDataIterator.ts should render and match snapshot with data 1`] = `
<div class="v-data-iterator">
<div>
foo
</div>
<div>
bar
</div>
<div>
baz
</div>
<div>
qux
</div>
<div class="v-data-footer">
<div class="v-data-footer__select">
Items per page:
<div class="v-input v-input--hide-details v-input--is-label-active v-input--is-dirty theme--light v-text-field v-select">
<div class="v-input__control">
<div role="button"
aria-haspopup="listbox"
aria-expanded="false"
aria-owns="list-16"
class="v-input__slot"
>
<div class="v-select__slot">
<div class="v-select__selections">
<div class="v-select__selection v-select__selection--comma">
10
</div>
<input aria-label="$vuetify.dataFooter.itemsPerPageText"
id="input-16"
readonly="readonly"
type="text"
aria-readonly="false"
autocomplete="off"
>
</div>
<div class="v-input__append-inner">
<div class="v-input__icon v-input__icon--append">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-menu-down theme--light"
>
</i>
</div>
</div>
<input type="hidden"
value="10"
>
</div>
<div class="v-menu">
</div>
</div>
</div>
</div>
</div>
<div class="v-data-footer__pagination">
1-4 of 4
</div>
<div class="v-data-footer__icons-before">
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Previous page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-left theme--light"
>
</i>
</span>
</button>
</div>
<div class="v-data-footer__icons-after">
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Next page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-right theme--light"
>
</i>
</span>
</button>
</div>
</div>
</div>
`;
exports[`VDataIterator.ts should render valid no-data, loading and no-results states 1`] = `
<div class="v-data-iterator">
<div>
No data available
</div>
<div class="v-data-footer">
<div class="v-data-footer__select">
Items per page:
<div class="v-input v-input--hide-details v-input--is-label-active v-input--is-dirty theme--light v-text-field v-select">
<div class="v-input__control">
<div role="button"
aria-haspopup="listbox"
aria-expanded="false"
aria-owns="list-27"
class="v-input__slot"
>
<div class="v-select__slot">
<div class="v-select__selections">
<div class="v-select__selection v-select__selection--comma">
10
</div>
<input aria-label="$vuetify.dataFooter.itemsPerPageText"
id="input-27"
readonly="readonly"
type="text"
aria-readonly="false"
autocomplete="off"
>
</div>
<div class="v-input__append-inner">
<div class="v-input__icon v-input__icon--append">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-menu-down theme--light"
>
</i>
</div>
</div>
<input type="hidden"
value="10"
>
</div>
<div class="v-menu">
</div>
</div>
</div>
</div>
</div>
<div class="v-data-footer__pagination">
</div>
<div class="v-data-footer__icons-before">
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Previous page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-left theme--light"
>
</i>
</span>
</button>
</div>
<div class="v-data-footer__icons-after">
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Next page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-right theme--light"
>
</i>
</span>
</button>
</div>
</div>
</div>
`;
exports[`VDataIterator.ts should render valid no-data, loading and no-results states 2`] = `
<div class="v-data-iterator">
<div>
Loading items...
</div>
<div class="v-data-footer">
<div class="v-data-footer__select">
Items per page:
<div class="v-input v-input--hide-details v-input--is-label-active v-input--is-dirty theme--light v-text-field v-select">
<div class="v-input__control">
<div role="button"
aria-haspopup="listbox"
aria-expanded="false"
aria-owns="list-27"
class="v-input__slot"
>
<div class="v-select__slot">
<div class="v-select__selections">
<div class="v-select__selection v-select__selection--comma">
10
</div>
<input aria-label="$vuetify.dataFooter.itemsPerPageText"
id="input-27"
readonly="readonly"
type="text"
aria-readonly="false"
autocomplete="off"
>
</div>
<div class="v-input__append-inner">
<div class="v-input__icon v-input__icon--append">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-menu-down theme--light"
>
</i>
</div>
</div>
<input type="hidden"
value="10"
>
</div>
<div class="v-menu">
</div>
</div>
</div>
</div>
</div>
<div class="v-data-footer__pagination">
</div>
<div class="v-data-footer__icons-before">
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Previous page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-left theme--light"
>
</i>
</span>
</button>
</div>
<div class="v-data-footer__icons-after">
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Next page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-right theme--light"
>
</i>
</span>
</button>
</div>
</div>
</div>
`;
exports[`VDataIterator.ts should render valid no-data, loading and no-results states 3`] = `
<div class="v-data-iterator">
<div>
No matching records found
</div>
<div class="v-data-footer">
<div class="v-data-footer__select">
Items per page:
<div class="v-input v-input--hide-details v-input--is-label-active v-input--is-dirty theme--light v-text-field v-select">
<div class="v-input__control">
<div role="button"
aria-haspopup="listbox"
aria-expanded="false"
aria-owns="list-27"
class="v-input__slot"
>
<div class="v-select__slot">
<div class="v-select__selections">
<div class="v-select__selection v-select__selection--comma">
10
</div>
<input aria-label="$vuetify.dataFooter.itemsPerPageText"
id="input-27"
readonly="readonly"
type="text"
aria-readonly="false"
autocomplete="off"
>
</div>
<div class="v-input__append-inner">
<div class="v-input__icon v-input__icon--append">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-menu-down theme--light"
>
</i>
</div>
</div>
<input type="hidden"
value="10"
>
</div>
<div class="v-menu">
</div>
</div>
</div>
</div>
</div>
<div class="v-data-footer__pagination">
</div>
<div class="v-data-footer__icons-before">
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Previous page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-left theme--light"
>
</i>
</span>
</button>
</div>
<div class="v-data-footer__icons-after">
<button type="button"
disabled="disabled"
class="v-btn v-btn--disabled v-btn--flat v-btn--icon v-btn--round v-btn--text theme--light v-size--default"
aria-label="Next page"
>
<span class="v-btn__content">
<i aria-hidden="true"
class="v-icon notranslate mdi mdi-chevron-right theme--light"
>
</i>
</span>
</button>
</div>
</div>
</div>
`;
+13
View File
@@ -0,0 +1,13 @@
// Imports
@import '../../styles/styles.sass';
$data-footer-font-size: map-deep-get($headings, 'caption', 'size') !default;
$data-footer-icons-after-btn-margin-start: 7px !default;
$data-footer-icons-before-btn-margin-end: 7px !default;
$data-footer-padding: 0 8px !default;
$data-footer-pagination-margin-end: 32px !default;
$data-footer-pagination-margin-start: 24px !default;
$data-footer-select-margin-end: 14px !default;
$data-footer-select-select-margin-start: 34px !default;
$data-footer-select-select-margin-y: 13px !default;
$data-footer-select-selections-comma-font-size: map-deep-get($headings, 'caption', 'size') !default;
+10
View File
@@ -0,0 +1,10 @@
import VDataIterator from './VDataIterator'
import VDataFooter from './VDataFooter'
export { VDataIterator, VDataFooter }
export default {
$_vuetify_subcomponents: {
VDataIterator,
VDataFooter,
},
}