This repository has been archived on 2024-07-27. You can view files and clone it, but cannot push or open issues or pull requests.
keksAccountGUI/node_modulesOLD/vuetify/lib/components/VSlideGroup/VSlideGroup.js

336 lines
8.9 KiB
JavaScript
Raw Permalink Normal View History

2019-08-11 18:48:02 +00:00
// Styles
import "../../../src/components/VSlideGroup/VSlideGroup.sass"; // Components
import VIcon from '../VIcon';
import { VFadeTransition } from '../transitions'; // Extensions
import { BaseItemGroup } from '../VItemGroup/VItemGroup'; // Directives
import Resize from '../../directives/resize';
import Touch from '../../directives/touch'; // Utilities
import mixins from '../../util/mixins';
export const BaseSlideGroup = mixins(BaseItemGroup
/* @vue/component */
).extend({
name: 'base-slide-group',
directives: {
Resize,
Touch
},
props: {
activeClass: {
type: String,
default: 'v-slide-item--active'
},
centerActive: Boolean,
nextIcon: {
type: String,
default: '$vuetify.icons.next'
},
mobileBreakPoint: {
type: [Number, String],
default: 1264,
validator: v => !isNaN(parseInt(v))
},
prevIcon: {
type: String,
default: '$vuetify.icons.prev'
},
showArrows: Boolean
},
data: () => ({
isOverflowing: false,
resizeTimeout: 0,
startX: 0,
scrollOffset: 0,
widths: {
content: 0,
wrapper: 0
}
}),
computed: {
__cachedNext() {
return this.genTransition('next');
},
__cachedPrev() {
return this.genTransition('prev');
},
classes() {
return { ...BaseItemGroup.options.computed.classes.call(this),
'v-slide-group': true
};
},
hasAffixes() {
return (this.showArrows || !this.isMobile) && this.isOverflowing;
},
hasNext() {
if (!this.hasAffixes) return false;
const {
content,
wrapper
} = this.widths; // Check one scroll ahead to know the width of right-most item
return content > Math.abs(this.scrollOffset) + wrapper;
},
hasPrev() {
return this.hasAffixes && this.scrollOffset !== 0;
},
isMobile() {
return this.$vuetify.breakpoint.width < this.mobileBreakPoint;
}
},
watch: {
internalValue: 'setWidths',
// When overflow changes, the arrows alter
// the widths of the content and wrapper
// and need to be recalculated
isOverflowing: 'setWidths',
scrollOffset(val) {
this.$refs.content.style.transform = `translateX(${-val}px)`;
}
},
methods: {
genNext() {
if (!this.hasAffixes) return null;
const slot = this.$scopedSlots.next ? this.$scopedSlots.next({}) : this.$slots.next || this.__cachedNext;
return this.$createElement('div', {
staticClass: 'v-slide-group__next',
class: {
'v-slide-group__next--disabled': !this.hasNext
},
on: {
click: () => this.onAffixClick('next')
},
key: 'next'
}, [slot]);
},
genContent() {
return this.$createElement('div', {
staticClass: 'v-slide-group__content',
ref: 'content'
}, this.$slots.default);
},
genData() {
return {
class: this.classes,
directives: [{
name: 'resize',
value: this.onResize
}]
};
},
genIcon(location) {
let icon = location;
if (this.$vuetify.rtl && location === 'prev') {
icon = 'next';
} else if (this.$vuetify.rtl && location === 'next') {
icon = 'prev';
}
const upperLocation = `${location[0].toUpperCase()}${location.slice(1)}`;
const hasAffix = this[`has${upperLocation}`];
if (!this.showArrows && !hasAffix) return null;
return this.$createElement(VIcon, {
props: {
disabled: !hasAffix
}
}, this[`${icon}Icon`]);
},
genPrev() {
if (!this.hasAffixes) return null;
const slot = this.$scopedSlots.prev ? this.$scopedSlots.prev({}) : this.$slots.prev || this.__cachedPrev;
return this.$createElement('div', {
staticClass: 'v-slide-group__prev',
class: {
'v-slide-group__prev--disabled': !this.hasPrev
},
on: {
click: () => this.onAffixClick('prev')
},
key: 'prev'
}, [slot]);
},
genTransition(location) {
return this.$createElement(VFadeTransition, [this.genIcon(location)]);
},
genWrapper() {
return this.$createElement('div', {
staticClass: 'v-slide-group__wrapper',
directives: [{
name: 'touch',
value: {
start: e => this.overflowCheck(e, this.onTouchStart),
move: e => this.overflowCheck(e, this.onTouchMove),
end: e => this.overflowCheck(e, this.onTouchEnd)
}
}],
ref: 'wrapper'
}, [this.genContent()]);
},
calculateNewOffset(direction, widths, rtl, currentScrollOffset) {
const sign = rtl ? -1 : 1;
const newAbosluteOffset = sign * currentScrollOffset + (direction === 'prev' ? -1 : 1) * widths.wrapper;
return sign * Math.max(Math.min(newAbosluteOffset, widths.content - widths.wrapper), 0);
},
onAffixClick(location) {
this.$emit(`click:${location}`);
this.scrollTo(location);
},
onResize() {
/* istanbul ignore next */
if (this._isDestroyed) return;
this.setWidths();
},
onTouchStart(e) {
const {
content
} = this.$refs;
this.startX = this.scrollOffset + e.touchstartX;
content.style.setProperty('transition', 'none');
content.style.setProperty('willChange', 'transform');
},
onTouchMove(e) {
this.scrollOffset = this.startX - e.touchmoveX;
},
onTouchEnd() {
const {
content,
wrapper
} = this.$refs;
const maxScrollOffset = content.clientWidth - wrapper.clientWidth;
content.style.setProperty('transition', null);
content.style.setProperty('willChange', null);
/* istanbul ignore else */
if (this.scrollOffset < 0 || !this.isOverflowing) {
this.scrollOffset = 0;
} else if (this.scrollOffset >= maxScrollOffset) {
this.scrollOffset = maxScrollOffset;
}
},
overflowCheck(e, fn) {
e.stopPropagation();
this.isOverflowing && fn(e);
},
scrollIntoView
/* istanbul ignore next */
() {
if (!this.selectedItem) {
return;
}
if (this.centerActive) {
this.scrollOffset = this.calculateCenteredOffset(this.selectedItem.$el, this.widths, this.$vuetify.rtl);
} else if (this.isOverflowing) {
this.scrollOffset = this.calculateUpdatedOffset(this.selectedItem.$el, this.widths, this.$vuetify.rtl, this.scrollOffset);
} else {
this.scrollOffset = 0;
}
},
calculateUpdatedOffset(selectedElement, widths, rtl, currentScrollOffset) {
const clientWidth = selectedElement.clientWidth;
const offsetLeft = rtl ? widths.content - selectedElement.offsetLeft - clientWidth : selectedElement.offsetLeft;
if (rtl) {
currentScrollOffset = -currentScrollOffset;
}
const totalWidth = widths.wrapper + currentScrollOffset;
const itemOffset = clientWidth + offsetLeft;
const additionalOffset = clientWidth * 0.3;
if (offsetLeft < currentScrollOffset) {
currentScrollOffset = Math.max(offsetLeft - additionalOffset, 0);
} else if (totalWidth < itemOffset) {
currentScrollOffset = Math.min(currentScrollOffset - (totalWidth - itemOffset - additionalOffset), widths.content - widths.wrapper);
}
return rtl ? -currentScrollOffset : currentScrollOffset;
},
calculateCenteredOffset(selectedElement, widths, rtl) {
const {
offsetLeft,
clientWidth
} = selectedElement;
if (rtl) {
const offsetCentered = widths.content - offsetLeft - clientWidth / 2 - widths.wrapper / 2;
return -Math.min(widths.content - widths.wrapper, Math.max(0, offsetCentered));
} else {
const offsetCentered = offsetLeft + clientWidth / 2 - widths.wrapper / 2;
return Math.min(widths.content - widths.wrapper, Math.max(0, offsetCentered));
}
},
scrollTo
/* istanbul ignore next */
(location) {
this.scrollOffset = this.calculateNewOffset(location, {
// Force reflow
content: this.$refs.content ? this.$refs.content.clientWidth : 0,
wrapper: this.$refs.wrapper ? this.$refs.wrapper.clientWidth : 0
}, this.$vuetify.rtl, this.scrollOffset);
},
setWidths
/* istanbul ignore next */
() {
window.requestAnimationFrame(() => {
const {
content,
wrapper
} = this.$refs;
this.widths = {
content: content ? content.clientWidth : 0,
wrapper: wrapper ? wrapper.clientWidth : 0
};
this.isOverflowing = this.widths.wrapper < this.widths.content;
this.scrollIntoView();
});
}
},
render(h) {
return h('div', this.genData(), [this.genPrev(), this.genWrapper(), this.genNext()]);
}
});
export default BaseSlideGroup.extend({
name: 'v-slide-group',
provide() {
return {
slideGroup: this
};
}
});
//# sourceMappingURL=VSlideGroup.js.map