UNPKG

kinetic-slider

Version:

A WebGL-powered kinetic slider component using PIXI.js

270 lines (268 loc) 9.01 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); class SlidingWindowManager { /** * Creates a new SlidingWindowManager * * @param options - Configuration options * @param resourceManager - Optional ResourceManager for resource tracking */ constructor(options, resourceManager) { /** Current active slide index */ __publicField(this, "activeIndex"); /** Size of the window on each side of the active slide */ __publicField(this, "windowSize"); /** Total number of slides */ __publicField(this, "totalSlides"); /** Information about each slide */ __publicField(this, "slides"); /** Whether debug logging is enabled */ __publicField(this, "debug"); /** Resource manager for tracking resources */ __publicField(this, "resourceManager"); /** Direction of the last navigation (-1 for prev, 1 for next, 0 for initial) */ __publicField(this, "lastDirection", 0); this.windowSize = options.windowSize ?? 2; this.totalSlides = options.totalSlides; this.activeIndex = options.initialIndex ?? 0; this.debug = options.debug ?? false; this.resourceManager = resourceManager; this.slides = Array(this.totalSlides).fill(null).map((_, index) => ({ index, state: "uninitialized" /* UNINITIALIZED */, inWindow: this.isInWindow(index, this.activeIndex) })); this.log(`Initialized with ${this.totalSlides} slides, window size \xB1${this.windowSize}, active index ${this.activeIndex}`); this.log(`Initial window: ${this.getWindowIndices().join(", ")}`); } /** * Log a message if debug is enabled */ log(message, level = "info") { if (!this.debug) return; const prefix = `[SlidingWindowManager]`; switch (level) { case "info": console.log(`${prefix} ${message}`); break; case "warn": console.warn(`${prefix} ${message}`); break; case "error": console.error(`${prefix} ${message}`); break; } } /** * Check if a slide index is within the current window * * @param index - Slide index to check * @param centerIndex - Center of the window (usually activeIndex) * @returns Whether the index is within the window */ isInWindow(index, centerIndex) { const distance = Math.abs(index - centerIndex); return distance <= this.windowSize; } /** * Get all slide indices that should be in the current window * * @returns Array of slide indices in the window */ getWindowIndices() { const indices = []; for (let i = Math.max(0, this.activeIndex - this.windowSize); i <= Math.min(this.totalSlides - 1, this.activeIndex + this.windowSize); i++) { indices.push(i); } return indices; } /** * Get all slide indices that should be in the extended window * (includes prediction based on navigation direction) * * @returns Array of slide indices in the extended window */ getExtendedWindowIndices() { const indices = this.getWindowIndices(); if (this.lastDirection !== 0) { const extraIndex = this.lastDirection > 0 ? this.activeIndex + this.windowSize + 1 : this.activeIndex - this.windowSize - 1; if (extraIndex >= 0 && extraIndex < this.totalSlides) { indices.push(extraIndex); } } return indices; } /** * Update the active slide index and recalculate the window * * @param newIndex - New active slide index * @returns Object containing arrays of indices that entered and left the window */ updateActiveIndex(newIndex) { if (newIndex < 0 || newIndex >= this.totalSlides) { this.log(`Invalid index: ${newIndex}`, "error"); return { entered: [], left: [] }; } this.lastDirection = newIndex > this.activeIndex ? 1 : -1; const oldWindowIndices = this.getWindowIndices(); const oldActiveIndex = this.activeIndex; this.activeIndex = newIndex; if (this.slides[newIndex]) { this.slides[newIndex].state = "active" /* ACTIVE */; this.slides[newIndex].lastActiveTime = Date.now(); } if (this.slides[oldActiveIndex] && oldActiveIndex !== newIndex) { if (this.slides[oldActiveIndex].state === "active" /* ACTIVE */) { this.slides[oldActiveIndex].state = "loaded" /* LOADED */; } } const newWindowIndices = this.getWindowIndices(); const entered = newWindowIndices.filter((index) => !oldWindowIndices.includes(index)); const left = oldWindowIndices.filter((index) => !newWindowIndices.includes(index)); this.slides.forEach((slide) => { slide.inWindow = this.isInWindow(slide.index, this.activeIndex); }); this.log(`Updated active index to ${newIndex}, direction: ${this.lastDirection}`); this.log(`Window changed: +[${entered.join(", ")}] -[${left.join(", ")}]`); return { entered, left }; } /** * Register a sprite for a slide * * @param index - Slide index * @param sprite - Sprite instance * @param state - Current state of the slide */ registerSlide(index, sprite, state = "loaded" /* LOADED */) { if (index < 0 || index >= this.totalSlides) { this.log(`Invalid index for registerSlide: ${index}`, "error"); return; } this.slides[index] = { ...this.slides[index], sprite, state: index === this.activeIndex ? "active" /* ACTIVE */ : state, inWindow: this.isInWindow(index, this.activeIndex) }; this.log(`Registered slide ${index} with state ${state}`); } /** * Update the state of a slide * * @param index - Slide index * @param state - New state */ updateSlideState(index, state) { if (index < 0 || index >= this.totalSlides) { this.log(`Invalid index for updateSlideState: ${index}`, "error"); return; } this.slides[index].state = state; this.log(`Updated slide ${index} state to ${state}`); } /** * Get information about a slide * * @param index - Slide index * @returns Slide information or null if index is invalid */ getSlideInfo(index) { if (index < 0 || index >= this.totalSlides) { this.log(`Invalid index for getSlideInfo: ${index}`, "error"); return null; } return this.slides[index]; } /** * Get the current active index * * @returns Active slide index */ getActiveIndex() { return this.activeIndex; } /** * Get all slide information * * @returns Array of slide information */ getAllSlides() { return [...this.slides]; } /** * Get slides that need to be initialized (converted from UNINITIALIZED to at least PLACEHOLDER) * * @returns Array of slide indices that need initialization */ getSlidesToInitialize() { const windowIndices = this.getExtendedWindowIndices(); return windowIndices.filter( (index) => this.slides[index].state === "uninitialized" /* UNINITIALIZED */ ); } /** * Get slides that need to be fully loaded (converted from PLACEHOLDER to LOADED) * * @returns Array of slide indices that need to be fully loaded */ getSlidesToLoad() { const windowIndices = this.getWindowIndices(); return windowIndices.filter( (index) => this.slides[index].state === "placeholder" /* PLACEHOLDER */ ); } /** * Get slides that can be unloaded (converted from LOADED to PLACEHOLDER) * * @returns Array of slide indices that can be unloaded */ getSlidesToUnload() { return this.slides.filter( (slide) => !slide.inWindow && (slide.state === "loaded" /* LOADED */ || slide.state === "active" /* ACTIVE */) ).map((slide) => slide.index); } /** * Set the window size * * @param size - New window size */ setWindowSize(size) { if (size < 1) { this.log(`Invalid window size: ${size}, must be at least 1`, "error"); return; } this.windowSize = size; this.slides.forEach((slide) => { slide.inWindow = this.isInWindow(slide.index, this.activeIndex); }); this.log(`Window size updated to \xB1${size}`); } /** * Get the current window size * * @returns Current window size */ getWindowSize() { return this.windowSize; } /** * Get the last navigation direction * * @returns Last direction (-1 for prev, 1 for next, 0 for initial) */ getLastDirection() { return this.lastDirection; } /** * Alias for updateActiveIndex to maintain naming consistency * * @param newIndex - New current slide index * @returns Object containing arrays of indices that entered and left the window */ updateCurrentIndex(newIndex) { return this.updateActiveIndex(newIndex); } } export { SlidingWindowManager as default }; //# sourceMappingURL=SlidingWindowManager.js.map