UNPKG

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
"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