342 lines
12 KiB
JavaScript
342 lines
12 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports.default = exports.BaseSlideGroup = void 0;
|
||
|
|
||
|
require("../../../src/components/VSlideGroup/VSlideGroup.sass");
|
||
|
|
||
|
var _VIcon = _interopRequireDefault(require("../VIcon"));
|
||
|
|
||
|
var _transitions = require("../transitions");
|
||
|
|
||
|
var _VItemGroup = require("../VItemGroup/VItemGroup");
|
||
|
|
||
|
var _resize = _interopRequireDefault(require("../../directives/resize"));
|
||
|
|
||
|
var _touch = _interopRequireDefault(require("../../directives/touch"));
|
||
|
|
||
|
var _mixins = _interopRequireDefault(require("../../util/mixins"));
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
|
||
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
||
|
|
||
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
||
|
|
||
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||
|
|
||
|
var BaseSlideGroup = (0, _mixins.default)(_VItemGroup.BaseItemGroup
|
||
|
/* @vue/component */
|
||
|
).extend({
|
||
|
name: 'base-slide-group',
|
||
|
directives: {
|
||
|
Resize: _resize.default,
|
||
|
Touch: _touch.default
|
||
|
},
|
||
|
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: function validator(v) {
|
||
|
return !isNaN(parseInt(v));
|
||
|
}
|
||
|
},
|
||
|
prevIcon: {
|
||
|
type: String,
|
||
|
default: '$vuetify.icons.prev'
|
||
|
},
|
||
|
showArrows: Boolean
|
||
|
},
|
||
|
data: function data() {
|
||
|
return {
|
||
|
isOverflowing: false,
|
||
|
resizeTimeout: 0,
|
||
|
startX: 0,
|
||
|
scrollOffset: 0,
|
||
|
widths: {
|
||
|
content: 0,
|
||
|
wrapper: 0
|
||
|
}
|
||
|
};
|
||
|
},
|
||
|
computed: {
|
||
|
__cachedNext: function __cachedNext() {
|
||
|
return this.genTransition('next');
|
||
|
},
|
||
|
__cachedPrev: function __cachedPrev() {
|
||
|
return this.genTransition('prev');
|
||
|
},
|
||
|
classes: function classes() {
|
||
|
return _objectSpread({}, _VItemGroup.BaseItemGroup.options.computed.classes.call(this), {
|
||
|
'v-slide-group': true
|
||
|
});
|
||
|
},
|
||
|
hasAffixes: function hasAffixes() {
|
||
|
return (this.showArrows || !this.isMobile) && this.isOverflowing;
|
||
|
},
|
||
|
hasNext: function hasNext() {
|
||
|
if (!this.hasAffixes) return false;
|
||
|
var _this$widths = this.widths,
|
||
|
content = _this$widths.content,
|
||
|
wrapper = _this$widths.wrapper; // Check one scroll ahead to know the width of right-most item
|
||
|
|
||
|
return content > Math.abs(this.scrollOffset) + wrapper;
|
||
|
},
|
||
|
hasPrev: function hasPrev() {
|
||
|
return this.hasAffixes && this.scrollOffset !== 0;
|
||
|
},
|
||
|
isMobile: function 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: function scrollOffset(val) {
|
||
|
this.$refs.content.style.transform = "translateX(".concat(-val, "px)");
|
||
|
}
|
||
|
},
|
||
|
methods: {
|
||
|
genNext: function genNext() {
|
||
|
var _this = this;
|
||
|
|
||
|
if (!this.hasAffixes) return null;
|
||
|
var 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: function click() {
|
||
|
return _this.onAffixClick('next');
|
||
|
}
|
||
|
},
|
||
|
key: 'next'
|
||
|
}, [slot]);
|
||
|
},
|
||
|
genContent: function genContent() {
|
||
|
return this.$createElement('div', {
|
||
|
staticClass: 'v-slide-group__content',
|
||
|
ref: 'content'
|
||
|
}, this.$slots.default);
|
||
|
},
|
||
|
genData: function genData() {
|
||
|
return {
|
||
|
class: this.classes,
|
||
|
directives: [{
|
||
|
name: 'resize',
|
||
|
value: this.onResize
|
||
|
}]
|
||
|
};
|
||
|
},
|
||
|
genIcon: function genIcon(location) {
|
||
|
var icon = location;
|
||
|
|
||
|
if (this.$vuetify.rtl && location === 'prev') {
|
||
|
icon = 'next';
|
||
|
} else if (this.$vuetify.rtl && location === 'next') {
|
||
|
icon = 'prev';
|
||
|
}
|
||
|
|
||
|
var upperLocation = "".concat(location[0].toUpperCase()).concat(location.slice(1));
|
||
|
var hasAffix = this["has".concat(upperLocation)];
|
||
|
if (!this.showArrows && !hasAffix) return null;
|
||
|
return this.$createElement(_VIcon.default, {
|
||
|
props: {
|
||
|
disabled: !hasAffix
|
||
|
}
|
||
|
}, this["".concat(icon, "Icon")]);
|
||
|
},
|
||
|
genPrev: function genPrev() {
|
||
|
var _this2 = this;
|
||
|
|
||
|
if (!this.hasAffixes) return null;
|
||
|
var 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: function click() {
|
||
|
return _this2.onAffixClick('prev');
|
||
|
}
|
||
|
},
|
||
|
key: 'prev'
|
||
|
}, [slot]);
|
||
|
},
|
||
|
genTransition: function genTransition(location) {
|
||
|
return this.$createElement(_transitions.VFadeTransition, [this.genIcon(location)]);
|
||
|
},
|
||
|
genWrapper: function genWrapper() {
|
||
|
var _this3 = this;
|
||
|
|
||
|
return this.$createElement('div', {
|
||
|
staticClass: 'v-slide-group__wrapper',
|
||
|
directives: [{
|
||
|
name: 'touch',
|
||
|
value: {
|
||
|
start: function start(e) {
|
||
|
return _this3.overflowCheck(e, _this3.onTouchStart);
|
||
|
},
|
||
|
move: function move(e) {
|
||
|
return _this3.overflowCheck(e, _this3.onTouchMove);
|
||
|
},
|
||
|
end: function end(e) {
|
||
|
return _this3.overflowCheck(e, _this3.onTouchEnd);
|
||
|
}
|
||
|
}
|
||
|
}],
|
||
|
ref: 'wrapper'
|
||
|
}, [this.genContent()]);
|
||
|
},
|
||
|
calculateNewOffset: function calculateNewOffset(direction, widths, rtl, currentScrollOffset) {
|
||
|
var sign = rtl ? -1 : 1;
|
||
|
var newAbosluteOffset = sign * currentScrollOffset + (direction === 'prev' ? -1 : 1) * widths.wrapper;
|
||
|
return sign * Math.max(Math.min(newAbosluteOffset, widths.content - widths.wrapper), 0);
|
||
|
},
|
||
|
onAffixClick: function onAffixClick(location) {
|
||
|
this.$emit("click:".concat(location));
|
||
|
this.scrollTo(location);
|
||
|
},
|
||
|
onResize: function onResize() {
|
||
|
/* istanbul ignore next */
|
||
|
if (this._isDestroyed) return;
|
||
|
this.setWidths();
|
||
|
},
|
||
|
onTouchStart: function onTouchStart(e) {
|
||
|
var content = this.$refs.content;
|
||
|
this.startX = this.scrollOffset + e.touchstartX;
|
||
|
content.style.setProperty('transition', 'none');
|
||
|
content.style.setProperty('willChange', 'transform');
|
||
|
},
|
||
|
onTouchMove: function onTouchMove(e) {
|
||
|
this.scrollOffset = this.startX - e.touchmoveX;
|
||
|
},
|
||
|
onTouchEnd: function onTouchEnd() {
|
||
|
var _this$$refs = this.$refs,
|
||
|
content = _this$$refs.content,
|
||
|
wrapper = _this$$refs.wrapper;
|
||
|
var 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: function overflowCheck(e, fn) {
|
||
|
e.stopPropagation();
|
||
|
this.isOverflowing && fn(e);
|
||
|
},
|
||
|
scrollIntoView
|
||
|
/* istanbul ignore next */
|
||
|
: function scrollIntoView() {
|
||
|
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: function calculateUpdatedOffset(selectedElement, widths, rtl, currentScrollOffset) {
|
||
|
var clientWidth = selectedElement.clientWidth;
|
||
|
var offsetLeft = rtl ? widths.content - selectedElement.offsetLeft - clientWidth : selectedElement.offsetLeft;
|
||
|
|
||
|
if (rtl) {
|
||
|
currentScrollOffset = -currentScrollOffset;
|
||
|
}
|
||
|
|
||
|
var totalWidth = widths.wrapper + currentScrollOffset;
|
||
|
var itemOffset = clientWidth + offsetLeft;
|
||
|
var 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: function calculateCenteredOffset(selectedElement, widths, rtl) {
|
||
|
var offsetLeft = selectedElement.offsetLeft,
|
||
|
clientWidth = selectedElement.clientWidth;
|
||
|
|
||
|
if (rtl) {
|
||
|
var offsetCentered = widths.content - offsetLeft - clientWidth / 2 - widths.wrapper / 2;
|
||
|
return -Math.min(widths.content - widths.wrapper, Math.max(0, offsetCentered));
|
||
|
} else {
|
||
|
var _offsetCentered = offsetLeft + clientWidth / 2 - widths.wrapper / 2;
|
||
|
|
||
|
return Math.min(widths.content - widths.wrapper, Math.max(0, _offsetCentered));
|
||
|
}
|
||
|
},
|
||
|
scrollTo
|
||
|
/* istanbul ignore next */
|
||
|
: function scrollTo(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 */
|
||
|
: function setWidths() {
|
||
|
var _this4 = this;
|
||
|
|
||
|
window.requestAnimationFrame(function () {
|
||
|
var _this4$$refs = _this4.$refs,
|
||
|
content = _this4$$refs.content,
|
||
|
wrapper = _this4$$refs.wrapper;
|
||
|
_this4.widths = {
|
||
|
content: content ? content.clientWidth : 0,
|
||
|
wrapper: wrapper ? wrapper.clientWidth : 0
|
||
|
};
|
||
|
_this4.isOverflowing = _this4.widths.wrapper < _this4.widths.content;
|
||
|
|
||
|
_this4.scrollIntoView();
|
||
|
});
|
||
|
}
|
||
|
},
|
||
|
render: function render(h) {
|
||
|
return h('div', this.genData(), [this.genPrev(), this.genWrapper(), this.genNext()]);
|
||
|
}
|
||
|
});
|
||
|
exports.BaseSlideGroup = BaseSlideGroup;
|
||
|
|
||
|
var _default = BaseSlideGroup.extend({
|
||
|
name: 'v-slide-group',
|
||
|
provide: function provide() {
|
||
|
return {
|
||
|
slideGroup: this
|
||
|
};
|
||
|
}
|
||
|
});
|
||
|
|
||
|
exports.default = _default;
|
||
|
//# sourceMappingURL=VSlideGroup.js.map
|