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.

170 lines 6.1 kB
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; }; import { initVevet } from '../../global/initVevet'; import { cnAdd, cnHas, cnRemove } from '../../internal/cn'; import { mergeWithNoUndefined } from '../../internal/mergeWithNoUndefined'; import { noopIfDestroyed } from '../../internal/noopIfDestroyed'; import { Callbacks } from '../Callbacks'; // todo: jsdoc export * from './types'; /** * A base class for modules that handle responsive properties, event listeners, and custom callbacks. * * @group Base */ export class Module { /** Get default static props */ _getStatic() { return { __staticProp: true }; } /** Set default mutable props */ _getMutable() { return { __mutableProp: true }; } /** * Current properties. Do not mutate these directly, use {@linkcode updateProps} instead. */ get props() { return this._props; } /** Optional prefix for classnames used by the module */ get prefix() { return initVevet().prefix; } /** The name of the module, derived from the class name */ get name() { return this.constructor.name; } /** * Checks if the module has been destroyed. */ get isDestroyed() { return this._isDestroyed; } /** * Retrieves the module's callbacks instance. */ get callbacks() { return this._callbacks; } /** * Creates a new instance of the Module class. */ constructor(props, onCallbacksProp) { /** Tracks whether the module has been destroyed */ this._isDestroyed = false; /** Stores actions that need to be executed when the module is destroyed */ this._destroyable = []; this._callbacks = new Callbacks({ ctx: this }); this._props = mergeWithNoUndefined(Object.assign(Object.assign({}, this._getStatic()), this._getMutable()), Object.assign({}, props)); // Initialize callbacks const onCallbacks = Object.assign(Object.assign({}, props), onCallbacksProp); if (onCallbacks) { const callbacksProps = Object.keys(onCallbacks).filter((key) => key.startsWith('on') && typeof onCallbacks[key] === 'function'); callbacksProps.forEach((key) => { let target = key.slice(2); target = target.charAt(0).toLowerCase() + target.slice(1); this._callbacks.on(target, onCallbacks[key]); }); } } /** * Method that is called when the module's properties mutate. In most cases, used to handle callbacks. */ _handleProps(diff) { this.callbacks.emit('props', diff); } /** Change module's mutable properties */ updateProps(props) { const prevProps = Object.assign({}, this._props); const keys = Object.keys(this.props); this._props = Object.assign(Object.assign({}, this._props), props); const diff = {}; // todo keys.forEach((key) => { // @ts-ignore const prevValue = prevProps[key]; // @ts-ignore const newValue = this._props[key]; if (prevValue !== newValue) { diff[key] = newValue; } }); this._handleProps(diff); } /** * Adds a callback on the module's destruction. * * @param action - The function to execute during destruction. */ onDestroy(action) { if (this.isDestroyed) { action(); return; } this._destroyable.push(action); } /** * Adds a custom callback to the module. * * @param target - The event type to listen for (e.g., 'props', 'destroy'). * @param listener - The function to execute when the event is triggered. * @param settings - Additional settings for the callback. */ on(target, listener, settings = {}) { return this.callbacks.on(target, listener, settings); } /** * Helper function to generate classnames with the module's prefix. * * @param classNames - The class names to generate. * @returns A string of class names with the module's prefix applied. */ _cn(...classNames) { return classNames.map((value) => `${this.prefix}${value}`).join(' '); } /** * Adds a class name on an element, and keeps track of it for removal when the module is destroyed. * * @param element - The target DOM element. * @param className - The class name to toggle. */ _addTempClassName(element, className) { const isAlreadyExists = cnHas(element, className); if (!isAlreadyExists) { cnAdd(element, className); this.onDestroy(() => cnRemove(element, className)); } } /** * Destroys the module, cleaning up resources, callbacks, and event listeners. */ destroy() { this._destroy(); } /** * Internal method to handle the destruction of the module. * It removes all callbacks, destroys properties, and cleans up event listeners and class names. */ _destroy() { this._callbacks.emit('destroy', undefined); this._callbacks.destroy(); this._destroyable.forEach((action) => action()); this._isDestroyed = true; } } __decorate([ noopIfDestroyed ], Module.prototype, "updateProps", null); __decorate([ noopIfDestroyed ], Module.prototype, "on", null); __decorate([ noopIfDestroyed ], Module.prototype, "destroy", null); //# sourceMappingURL=index.js.map