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.

260 lines 8.4 kB
import { clamp, loop, onResize, scoped, toPixels } from '../../../../utils'; import { SnapSlideParallax } from './Parallax'; import { PARALLAX_ATTRIBUTES } from './Parallax/constants'; export class SnapSlide { constructor(_element, initProps = {}) { this._element = _element; /** Current coordinate */ this._coord = 0; /** If the slide is appended */ this._isAppended = false; /** If the slide is visible */ this._isVisible = false; /** Static coordinate without alignment (as if the slide was never moved) */ this._staticCoord = 0; /** Current progress of slide movement: from -1 to 1 */ this._progress = 0; this._index = 0; this._parallax = []; const defaultProps = { virtual: false, size: null, }; this._props = Object.assign(Object.assign({}, defaultProps), initProps); if (this._props.virtual && (!initProps.size || initProps.size === 'auto')) { throw new Error('Virtual slide must have a defined size'); } } /** Snap component */ get ctx() { return this._ctx; } /** Slide properties */ get props() { return this._props; } /** Size property */ get sizeProp() { var _a, _b, _c; return (_c = (_a = this.props.size) !== null && _a !== void 0 ? _a : (_b = this.ctx) === null || _b === void 0 ? void 0 : _b.props.slideSize) !== null && _c !== void 0 ? _c : 'auto'; } /** Slide element */ get element() { return this._element; } /** Slide index */ get index() { return this._index; } /** Current coordinate */ get coord() { return this._coord; } /** Static coordinate without alignment (as if the slide was never moved) */ get staticCoord() { return this._staticCoord; } /** Current progress of slide movement: from -1 to 1 */ get progress() { return this._progress; } /** Slide size in pixels */ get size() { var _a; const { ctx, sizeProp } = this; if (!ctx) { return 0; } if (sizeProp === 'stretch') { return ctx.containerSize; } if (sizeProp === 'auto') { return (_a = this._domSize) !== null && _a !== void 0 ? _a : ctx.containerSize; } return toPixels(sizeProp); } /** Check if the slide is visible relative to the container */ get isVisible() { return this._isVisible; } /** Resize the slide & trigger snap reflow */ resize(isManual = true) { const { element, ctx } = this; if (!ctx) { return; } if (element) { this._domSize = ctx.axis === 'x' ? element.offsetWidth : element.offsetHeight; } // Re-flow ctx.resize(isManual); } /** * Attach the slide to the Snap class. * For internal use only */ $_attach(ctx, index) { this.$_detach(); this._ctx = ctx; this._index = index; this._parallax = this._getParallaxNodes().map((node) => new SnapSlideParallax(this, node, () => ctx.impulse)); if (this.element && this.sizeProp === 'auto') { this._resizer = onResize({ element: this.element, viewportTarget: 'width', callback: () => this.resize(false), name: 'Snap Slide', }); } } /** * Detach the slide from the Snap class. * For internal use only */ $_detach() { var _a, _b; this._ctx = undefined; (_a = this._resizer) === null || _a === void 0 ? void 0 : _a.remove(); (_b = this._parallax) === null || _b === void 0 ? void 0 : _b.forEach((parallax) => parallax.destroy()); } /** * Static coordinate (as if the slide was never moved). * For internal use only */ $_setStaticCoord(value) { this._staticCoord = value; } /** * Render the slide. * For internal use only */ $_render() { var _a; this._toggleAppend(); (_a = this._parallax) === null || _a === void 0 ? void 0 : _a.forEach((parallax) => parallax.render()); } /** Get list of parallax nodes */ _getParallaxNodes() { const { element } = this; if (!element) { return []; } const selector = PARALLAX_ATTRIBUTES.map((attr) => `[${attr}]`).join(','); const nodeList = element.querySelectorAll(selector); return Array.from(nodeList); } /** Toggle slide append/remove */ _toggleAppend() { if (!this.props.virtual || !this.element || !this.ctx) { return; } const { element, ctx } = this; if (this.isVisible && !this._isAppended) { this._isAppended = true; ctx.container.appendChild(element); } else if (!this.isVisible && this._isAppended) { this._isAppended = false; ctx.container.removeChild(element); } } /** Get magnets with static coordinates but dynamic alignment */ get magnets() { if (!this.ctx) { return []; } const { ctx, staticCoord, size, index } = this; const { containerSize, origin } = ctx; let points = []; if (index === 0 && ctx.props.loop) { points.push(ctx.max); } if (origin === 'center') { const point = staticCoord + size / 2 - ctx.firstSlideSize / 2; if (size > containerSize) { points.push(point); points.push(point + (containerSize - size) / 2); points.push(point - (containerSize - size) / 2); } else { points.push(point); } } else if (origin === 'end') { const point = staticCoord + size - ctx.firstSlideSize; points.push(point); if (size > containerSize) { points.push(point + (containerSize - size)); } } else { points.push(staticCoord); if (size > containerSize) { points.push(staticCoord + (size - containerSize)); } if (!ctx.canLoop) { points = points.map((point) => clamp(point, 0, ctx.max)); } } return points; } /** * Update slide progress. * For internal use only */ $_updateProgress() { const { ctx } = this; if (!ctx) { return; } const { coord, size } = this; const { containerSize, origin } = ctx; if (origin === 'center') { const center = containerSize / 2 - size / 2; this._progress = scoped(coord, center, center - size); return; } if (origin === 'end') { const end = containerSize - size; this._progress = scoped(coord, end, end - size); return; } this._progress = scoped(coord, 0, -size); } /** * Update slide values. * For internal use only */ $_updateCoords(offset) { const { ctx } = this; if (!ctx) { return; } const { staticCoord, size } = this; const { origin } = ctx; if (!ctx.canLoop) { this._setCoord(staticCoord + offset - ctx.current); return; } if (origin === 'center') { this._setCoord(loop(staticCoord + offset - ctx.current, -ctx.max / 2 + offset, ctx.max / 2 + offset)); return; } if (origin === 'end') { this._setCoord(loop(staticCoord + offset - ctx.current, -size, ctx.max - size)); return; } this._setCoord(loop(staticCoord - ctx.current, -size, ctx.max - size)); } /** Set slide coordinate */ _setCoord(value) { var _a, _b; this._coord = value; this._isVisible = this.size > 0 && this._coord > -this.size && this._coord < ((_b = (_a = this.ctx) === null || _a === void 0 ? void 0 : _a.containerSize) !== null && _b !== void 0 ? _b : 0); } } //# sourceMappingURL=index.js.map