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
+198
View File
@@ -0,0 +1,198 @@
import "../../../src/components/VDataIterator/VDataFooter.sass"; // Components
import VSelect from '../VSelect/VSelect';
import VIcon from '../VIcon';
import VBtn from '../VBtn'; // Types
import Vue from 'vue';
export default Vue.extend({
name: 'v-data-footer',
props: {
options: {
type: Object,
required: true
},
pagination: {
type: Object,
required: true
},
itemsPerPageOptions: {
type: Array,
default: () => [5, 10, 15, -1]
},
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() {
return this.options.itemsPerPage <= 0 || this.options.page * this.options.itemsPerPage >= this.pagination.itemsLength || this.pagination.pageStop < 0;
},
computedDataItemsPerPageOptions() {
return this.itemsPerPageOptions.map(option => {
if (typeof option === 'object') return option;else return this.genDataItemsPerPageOption(option);
});
}
},
methods: {
updateOptions(obj) {
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) {
this.updateOptions({
itemsPerPage,
page: 1
});
},
genDataItemsPerPageOption(option) {
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 = [''];
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, disabled, label, icon) {
return this.$createElement(VBtn, {
props: {
disabled: disabled || this.disablePagination,
icon: true,
text: true
},
on: {
click
},
attrs: {
'aria-label': label
}
}, [this.$createElement(VIcon, icon)]);
},
genIcons() {
const before = [];
const after = [];
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() {
return this.$createElement('div', {
staticClass: 'v-data-footer'
}, [this.genItemsPerPageSelect(), this.genPaginationInfo(), this.genIcons()]);
}
});
//# sourceMappingURL=VDataFooter.js.map
File diff suppressed because one or more lines are too long
+297
View File
@@ -0,0 +1,297 @@
// 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';
/* @vue/component */
export default mixins(Mobile, Themeable).extend({
name: 'v-data-iterator',
props: { ...VData.options.props,
itemKey: {
type: String,
default: 'id'
},
value: {
type: Array,
default: () => []
},
singleSelect: Boolean,
expanded: {
type: Array,
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: {},
expansion: {},
internalCurrentItems: []
}),
computed: {
everyItem() {
return !!this.selectableItems.length && this.selectableItems.every(i => this.isSelected(i));
},
someItems() {
return this.selectableItems.some(i => this.isSelected(i));
},
sanitizedFooterProps() {
return camelizeObjectKeys(this.footerProps);
},
selectableItems() {
return this.internalCurrentItems.filter(item => this.isSelectable(item));
}
},
watch: {
value: {
handler(value) {
this.selection = value.reduce((selection, item) => {
selection[getObjectValueByPath(item, this.itemKey)] = item;
return selection;
}, {});
},
immediate: true
},
selection(value, old) {
if (deepEqual(Object.keys(value), Object.keys(old))) return;
this.$emit('input', Object.values(value));
},
expanded: {
handler(value) {
this.expansion = value.reduce((expansion, item) => {
expansion[getObjectValueByPath(item, this.itemKey)] = true;
return expansion;
}, {});
},
immediate: true
},
expansion(value, old) {
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) {
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) {
return getObjectValueByPath(item, this.selectableKey) !== false;
},
isSelected(item) {
return !!this.selection[getObjectValueByPath(item, this.itemKey)] || false;
},
select(item, value = true, emit = true) {
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) {
return this.expansion[getObjectValueByPath(item, this.itemKey)] || false;
},
expand(item, value = true) {
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) {
return {
item,
select: v => this.select(item, v),
isSelected: this.isSelected(item),
expand: v => this.expand(item, v),
isExpanded: this.isExpanded(item),
isMobile: this.isMobile
};
},
genEmptyWrapper(content) {
return this.$createElement('div', content);
},
genEmpty(originalItemsLength, filteredItemsLength) {
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) {
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 => this.$scopedSlots.item(this.createItemProps(item)));
}
return [];
},
genFooter(props) {
if (this.hideDefaultFooter) return null;
const data = {
props: { ...this.sanitizedFooterProps,
options: props.options,
pagination: props.pagination
},
on: {
'update:options': value => props.updateOptions(value)
}
};
const scopedSlots = getPrefixedScopedSlots('footer.', this.$scopedSlots);
return this.$createElement(VDataFooter, {
scopedSlots,
...data
});
},
genDefaultScopedSlot(props) {
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() {
return this.$createElement(VData, {
props: this.$props,
on: {
'update:options': (v, old) => !deepEqual(v, old) && this.$emit('update:options', v),
'update:page': v => this.$emit('update:page', v),
'update:items-per-page': v => this.$emit('update:items-per-page', v),
'update:sort-by': v => this.$emit('update:sort-by', v),
'update:sort-desc': v => this.$emit('update:sort-desc', v),
'update:group-by': v => this.$emit('update:group-by', v),
'update:group-desc': v => this.$emit('update:group-desc', v),
pagination: (v, old) => !deepEqual(v, old) && this.$emit('pagination', v),
'current-items': v => {
this.internalCurrentItems = v;
this.$emit('current-items', v);
},
'page-count': v => this.$emit('page-count', v)
},
scopedSlots: {
default: this.genDefaultScopedSlot
}
});
}
});
//# sourceMappingURL=VDataIterator.js.map
File diff suppressed because one or more lines are too long
+10
View File
@@ -0,0 +1,10 @@
import VDataIterator from './VDataIterator';
import VDataFooter from './VDataFooter';
export { VDataIterator, VDataFooter };
export default {
$_vuetify_subcomponents: {
VDataIterator,
VDataFooter
}
};
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/components/VDataIterator/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAP,MAA0B,iBAA1B;AACA,OAAO,WAAP,MAAwB,eAAxB;AAEA,SAAS,aAAT,EAAwB,WAAxB;AACA,eAAe;AACb,EAAA,uBAAuB,EAAE;AACvB,IAAA,aADuB;AAEvB,IAAA;AAFuB;AADZ,CAAf","sourcesContent":["import VDataIterator from './VDataIterator'\nimport VDataFooter from './VDataFooter'\n\nexport { VDataIterator, VDataFooter }\nexport default {\n $_vuetify_subcomponents: {\n VDataIterator,\n VDataFooter,\n },\n}\n"],"sourceRoot":"","file":"index.js"}