vevet
Version:
Vevet is a JavaScript library for creative development that simplifies crafting rich interactions like split text animations, carousels, marquees, preloading, and more.
665 lines • 25.2 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Snap = void 0;
var base_1 = require("../../base");
var isString_1 = require("../../internal/isString");
var isUndefined_1 = require("../../internal/isUndefined");
var noopIfDestroyed_1 = require("../../internal/noopIfDestroyed");
var utils_1 = require("../../utils");
var Idle_1 = require("./logic/Idle");
var Interval_1 = require("./logic/Interval");
var Keyboard_1 = require("./logic/Keyboard");
var Slide_1 = require("./logic/Slide");
var Swipe_1 = require("./logic/Swipe");
var Track_1 = require("./logic/Track");
var Wheel_1 = require("./logic/Wheel");
var props_1 = require("./props");
__exportStar(require("./types"), exports);
__exportStar(require("./logic/Slide"), exports);
/**
* Snap/Carousel handler.
* This class manages sliding progress with options like swipe, wheel interactions, and smooth transitions.
*
* Please not that the class does not apply any styles to the slides, it only handles the logic.
*
* [Documentation](https://vevetjs.com/docs/Snap)
*
* @group Components
*/
var Snap = /** @class */ (function (_super) {
__extends(Snap, _super);
function Snap(props, onCallbacks) {
var _this = _super.call(this, props, onCallbacks) || this;
/** Container size */
_this._containerSize = 0;
/** All slides */
_this._slides = [];
/** Scrollable slides (which size is larger than the container) */
_this._scrollableSlides = [];
var _a = _this.props, container = _a.container, activeIndex = _a.activeIndex;
// set vars
_this._activeIndex = activeIndex;
// add resize event
_this._resizer = (0, utils_1.onResize)({
element: container,
viewportTarget: 'width',
callback: function () { return _this._handleResize(); },
name: _this.name,
});
// initial resize
_this._resizer.debounceResize();
// fetch slides
_this._fetchSlides();
// add wheel listener
new Wheel_1.SnapWheel(_this);
// add swipe
_this._swipe = new Swipe_1.SnapSwipe(_this);
// add track
_this._track = new Track_1.SnapTrack(_this);
// add keyboard
new Keyboard_1.SnapKeyboard(_this);
// add interval
new Interval_1.SnapInterval(_this);
// add idle logic
_this._idle = new Idle_1.SnapIdle(_this);
return _this;
}
/**
* Returns the default static properties.
*/
Snap.prototype._getStatic = function () {
return __assign(__assign({}, _super.prototype._getStatic.call(this)), props_1.STATIC_PROPS);
};
/**
* Returns the default mutable properties.
*/
Snap.prototype._getMutable = function () {
return __assign(__assign({}, _super.prototype._getMutable.call(this)), props_1.MUTABLE_PROPS);
};
/** Handles properties change */
Snap.prototype._handleProps = function (props) {
// attach slides
if ('slides' in props) {
this._fetchSlides();
}
// resize immediately
this._resizer.resize();
// update props
_super.prototype._handleProps.call(this, props);
};
Object.defineProperty(Snap.prototype, "container", {
/** Get container */
get: function () {
return this.props.container;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "eventsEmitter", {
/** Get events emitter */
get: function () {
var _a;
return (_a = this.props.eventsEmitter) !== null && _a !== void 0 ? _a : this.container;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "containerSize", {
/** Container size depending on direction (width or height) */
get: function () {
var containerSize = this.props.containerSize;
if (containerSize === 'auto') {
return this._containerSize;
}
return (0, utils_1.toPixels)(containerSize);
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "domSize", {
/**
* Container size depending on direction (width or height)
* @deprecated
*/
get: function () {
return this.containerSize;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "slides", {
/** All slides */
get: function () {
return this._slides;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "scrollableSlides", {
/** Scrollable slides (which size is larger than the container) */
get: function () {
return this._scrollableSlides;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "activeIndex", {
/** Active slide index */
get: function () {
return this._activeIndex;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "activeSlide", {
/** Active slide */
get: function () {
return this.slides[this._activeIndex];
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "isEmpty", {
get: function () {
return this.slides.length === 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "axis", {
/** Get axis name depending on direction */
get: function () {
return this.props.direction === 'horizontal' ? 'x' : 'y';
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "isTransitioning", {
/** If transition in progress */
get: function () {
return this._track.isTransitioning;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "isSwiping", {
/** If swipe in progress */
get: function () {
return this._swipe.isSwiping;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "hasInteria", {
/** If swipe has inertia */
get: function () {
return this._swipe.hasIntertia;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "isInterpolating", {
/** If track values are interpolating */
get: function () {
var track = this._track;
var diff = Math.abs(track.target - track.current);
return diff > props_1.LERP_APPROXIMATION;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "influence", {
/** Gets the interpolation influence */
get: function () {
return this._track.influence;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "current", {
/** Gets the current track value. */
get: function () {
return this._track.current;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "target", {
/** Gets the target track value. */
get: function () {
return this._track.target;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "canLoop", {
/** Detect if can loop */
get: function () {
return this._track.canLoop;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "loopedCurrent", {
/** Get looped current value */
get: function () {
return this._track.loopedCurrent;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "loopCount", {
/** Get loop count */
get: function () {
return this._track.loopCount;
},
enumerable: false,
configurable: true
});
/** Sets track to current & target value instantly */
Snap.prototype.set = function (value) {
this._track.set(value);
};
/** Loop a coordinate if can loop */
Snap.prototype.loopCoord = function (coord) {
return this._track.loopCoord(coord);
};
Object.defineProperty(Snap.prototype, "min", {
/** Get minimum track value */
get: function () {
return this._track.min;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "max", {
/** Get maximum track value */
get: function () {
return this._track.max;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "progress", {
/** Get track progress. From 0 to 1 if not loop. From -Infinity to Infinity if loop */
get: function () {
return this.current / this.max;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "isStart", {
/** If the start has been reached */
get: function () {
return this._track.isStart;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "isEnd", {
/** If the end has been reached */
get: function () {
return this._track.isEnd;
},
enumerable: false,
configurable: true
});
/** Clamp target value between min and max values */
Snap.prototype.clampTarget = function () {
this._track.clampTarget();
};
/** Iterate track target value */
Snap.prototype.iterateTarget = function (delta) {
this._track.iterateTarget(delta);
};
/** Set track target value */
Snap.prototype.setTarget = function (value) {
this._track.setTarget(value);
};
/** Cancel slide transition */
Snap.prototype.cancelTransition = function () {
this._track.cancelTransition();
};
Object.defineProperty(Snap.prototype, "isSlideScrolling", {
/** Check if the active slide is larger than the container and is being scrolled */
get: function () {
var containerSize = this.containerSize;
return this.scrollableSlides.some(function (_a) {
var size = _a.size, coord = _a.coord;
return (0, utils_1.inRange)(coord, containerSize - size, 0);
});
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "firstSlideSize", {
/** Get first slide size */
get: function () {
return this.slides[0].size;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Snap.prototype, "isIdle", {
/** If the scene is idle: not swiping, not interpolating, not transitioning */
get: function () {
return this._idle.isIdle;
},
enumerable: false,
configurable: true
});
/** Update slides list and attach them */
Snap.prototype._fetchSlides = function () {
var _this = this;
var props = this.props;
this._slides.forEach(function (slide) { return slide.$_detach(); });
var rawChildren = props.slides
? props.slides
: Array.from(props.container.children);
var children = rawChildren.filter(function (slide) {
if (slide instanceof HTMLElement &&
slide.hasAttribute('data-scrollbar')) {
return false;
}
return true;
});
this._slides = children.map(function (item) {
if (item instanceof Slide_1.SnapSlide) {
return item;
}
return new Slide_1.SnapSlide(item);
});
this._slides.forEach(function (slide, index) { return slide.$_attach(_this, index); });
};
/** Request resize (handled with debounce timeout) */
Snap.prototype.resize = function (isManual) {
if (isManual === void 0) { isManual = true; }
if (isManual) {
this._resizer.resize();
}
else {
this._resizer.debounceResize();
}
};
/** Resize the scene and reflow */
Snap.prototype._handleResize = function () {
var container = this.props.container;
// cancel sticky behavior
this._track.cancelTransition();
// update container size
this._containerSize =
this.axis === 'x' ? container.offsetWidth : container.offsetHeight;
// reflow
this._reflow();
// emit callbacks
this.callbacks.emit('resize', undefined);
};
/** Reflow: update static values of slides */
Snap.prototype._reflow = function () {
var _this = this;
var _a = this, slides = _a.slides, props = _a.props;
if (this.isEmpty) {
return;
}
// Reset scrollable slides
this._scrollableSlides = [];
// Calculate static values
slides.reduce(function (prev, slide) {
slide.$_setStaticCoord(prev);
if (slide.size > _this.containerSize) {
_this._scrollableSlides.push(slide);
}
return prev + slide.size + (0, utils_1.toPixels)(props.gap);
}, 0);
// Reset to active slide
var slide = slides.find(function (_a) {
var index = _a.index;
return index === _this.activeIndex;
});
if (props.stickOnResize && slide) {
this._track.clampTarget();
this._track.set(slide.magnets[0]);
}
// Emit callbacks
this.callbacks.emit('reflow', undefined);
// Render after resize
this.render();
};
/** Render slides */
Snap.prototype.render = function (frameDuration) {
if (frameDuration === void 0) { frameDuration = 0; }
if (this.isEmpty) {
return;
}
var _a = this, swipe = _a._swipe, track = _a._track, props = _a.props;
// Update values
this._updateSlidesCoords();
this._updateSlideProgress();
// Get magnet after slide coordinates are updated
var magnet = this.magnet;
// Active index change
if (magnet &&
magnet.slide.index !== this._activeIndex &&
((0, isUndefined_1.isUndefined)(this.$_targetIndex) ||
magnet.slide.index === this.$_targetIndex)) {
this._activeIndex = magnet.slide.index;
this.$_targetIndex = undefined;
this.callbacks.emit('activeSlide', this.activeSlide);
}
// Check if friction is allowed
var hasFriction = (swipe.isSwiping && swipe.allowFriction) || !swipe.isSwiping;
// Apply friction
if (magnet &&
hasFriction &&
frameDuration > 0 &&
props.friction >= 0 &&
!this.isSlideScrolling &&
!props.freemode) {
track.target = (0, utils_1.damp)(track.target, track.current + magnet.diff, props.friction * props.lerp, frameDuration, 0.000001);
}
// Render slides
this.slides.forEach(function (slide) { return slide.$_render(); });
// Emit Calbacks
this.callbacks.emit('update', undefined);
};
/** Update slides values */
Snap.prototype._updateSlidesCoords = function () {
var _a = this, slides = _a.slides, props = _a.props, containerSize = _a.containerSize, firstSlideSize = _a.firstSlideSize;
var offset = props.centered ? containerSize / 2 - firstSlideSize / 2 : 0;
slides.forEach(function (slide) { return slide.$_updateCoords(offset); });
};
/** Update slides progress */
Snap.prototype._updateSlideProgress = function () {
this.slides.forEach(function (slide) { return slide.$_updateProgress(); });
};
Object.defineProperty(Snap.prototype, "magnet", {
/** Get nearest magnet */
get: function () {
var current = this._track.loopedCurrent;
return this.getNearestMagnet(current);
},
enumerable: false,
configurable: true
});
/** Get nearest magnet to the current position */
Snap.prototype.getNearestMagnet = function (coord) {
var magnets = this.slides.flatMap(function (slide) {
return slide.magnets.map(function (magnet) { return ({ slide: slide, magnet: magnet, index: slide.index }); });
});
if (magnets.length === 0) {
return undefined;
}
var closestMagnet = magnets.reduce(function (p, c) {
return Math.abs(c.magnet - coord) < Math.abs(p.magnet - coord) ? c : p;
});
return __assign(__assign({}, closestMagnet), { diff: closestMagnet.magnet - coord });
};
/** Stick to the nearest magnet */
Snap.prototype.stick = function () {
var _a = this, magnet = _a.magnet, isSlideScrolling = _a.isSlideScrolling;
if (isSlideScrolling || !magnet) {
return;
}
this.toCoord(this._track.current + magnet.diff);
};
/** Go to a definite coordinate */
Snap.prototype.toCoord = function (coordinate, options) {
return this._track.toCoord(coordinate, options);
};
/** Go to a slide by index */
Snap.prototype.toSlide = function (targetIndex, _a) {
var _b, _c;
if (_a === void 0) { _a = {}; }
var _d = _a.direction, direction = _d === void 0 ? null : _d, options = __rest(_a, ["direction"]);
var _e = this, isEmpty = _e.isEmpty, activeIndex = _e.activeIndex, slides = _e.slides, track = _e._track, props = _e.props;
var current = track.current, max = track.max, loopCount = track.loopCount;
if (isEmpty || this.isDestroyed) {
return false;
}
var index = (0, utils_1.loop)(targetIndex, 0, this.slides.length);
// Stick if the same slide
if (index === activeIndex) {
this.stick();
return false;
}
this.$_targetIndex = index;
var slideMagnets = slides[index].magnets;
var targetStaticMagnet = slideMagnets[0];
if (props.centered) {
if (direction === 'prev') {
targetStaticMagnet = (_b = slideMagnets[2]) !== null && _b !== void 0 ? _b : slideMagnets[0];
}
else if (direction === 'next') {
targetStaticMagnet = (_c = slideMagnets[1]) !== null && _c !== void 0 ? _c : slideMagnets[0];
}
}
else {
targetStaticMagnet =
direction === 'prev'
? slideMagnets[slideMagnets.length - 1]
: targetStaticMagnet;
}
// Use static magnet when not looping
if (!props.loop) {
return this.toCoord(targetStaticMagnet, options);
}
// Or calculate closest magnet
var targetMagnet = targetStaticMagnet + loopCount * max;
var targetMagnetMin = targetMagnet - max;
var targetMagnetMax = targetMagnet + max;
var allMagnets = [targetMagnetMin, targetMagnet, targetMagnetMax];
if ((0, isString_1.isString)(direction)) {
var magnets = allMagnets.filter(function (magnet) {
return direction === 'next' ? magnet >= current : magnet <= current;
});
var magnet_1 = (0, utils_1.closest)(current, magnets);
return this.toCoord(magnet_1, options);
}
var magnet = (0, utils_1.closest)(current, allMagnets);
return this.toCoord(magnet, options);
};
/** Go to next slide */
Snap.prototype.next = function (_a) {
if (_a === void 0) { _a = {}; }
var _b = _a.skip, skip = _b === void 0 ? this.props.slidesToScroll : _b, options = __rest(_a, ["skip"]);
var _c = this, props = _c.props, slides = _c.slides, activeIndex = _c.activeIndex;
var length = slides.length;
var index = (0, utils_1.loop)(activeIndex + skip, 0, length);
if (!props.loop) {
index = props.rewind
? (0, utils_1.loop)(activeIndex + skip, 0, length)
: Math.min(activeIndex + skip, length - 1);
}
return this.toSlide(index, __assign(__assign({}, options), { direction: 'next' }));
};
/** Go to previous slide */
Snap.prototype.prev = function (_a) {
if (_a === void 0) { _a = {}; }
var _b = _a.skip, skip = _b === void 0 ? this.props.slidesToScroll : _b, options = __rest(_a, ["skip"]);
var _c = this, props = _c.props, slides = _c.slides, activeIndex = _c.activeIndex;
var index = (0, utils_1.loop)(activeIndex - skip, 0, slides.length);
if (!props.loop) {
index = props.rewind
? (0, utils_1.loop)(activeIndex - skip, 0, slides.length)
: Math.max(activeIndex - skip, 0);
}
return this.toSlide(index, __assign(__assign({}, options), { direction: 'prev' }));
};
/**
* Destroys the component and clears all timeouts and resources.
*/
Snap.prototype._destroy = function () {
_super.prototype._destroy.call(this);
this._resizer.remove();
this._slides.forEach(function (slide) { return slide.$_detach(); });
};
__decorate([
noopIfDestroyed_1.noopIfDestroyed
], Snap.prototype, "resize", null);
__decorate([
noopIfDestroyed_1.noopIfDestroyed
], Snap.prototype, "render", null);
__decorate([
noopIfDestroyed_1.noopIfDestroyed
], Snap.prototype, "toCoord", null);
return Snap;
}(base_1.Module));
exports.Snap = Snap;
//# sourceMappingURL=index.js.map