UNPKG

hd-utils

Version:

A handy utils for modern JS developers

160 lines (159 loc) 4.99 kB
/** * @description A class to manage a sequence of steps, allowing navigation and dynamic modification.. * Supports adding and removing steps at the beginning, end, and specific positions. * @example const stepper = new StepDeque(["step1", "step2", (condition) => condition ? "step3" : "step4"]); * stepper.next(); // "step1" * stepper.next(); // "step2" * stepper.next(true); // "step3" * stepper.previous(); // "step2" */ export default class StepDeque { constructor(steps, options) { this.steps = steps; this.defaultStepIndex = options?.defaultStepIndex ?? 0; this.isCircular = !!options?.circularPoint; this.currentIndex = options?.defaultStepIndex ?? 0; } getCurrentStepIndex() { return this.currentIndex; } getSteps() { return this.steps; } /** * Moves to the next step and returns its value. * If there are no more steps, it returns undefined. */ next(...args) { if (this.currentIndex < this.steps.length - 1) { this.currentIndex++; if (typeof this.steps[this.currentIndex] === "function") { return this.steps[this.currentIndex](...args); } return this.steps[this.currentIndex]; } else if (this.isCircular) { this.currentIndex = this.defaultStepIndex; return this.current(...args); } return undefined; } /** * Moves to the previous step and returns its value. * If already at the first step, it returns undefined. */ previous(...args) { if (this.currentIndex > 0) { this.currentIndex--; if (typeof this.steps[this.currentIndex] === "function") { return this.steps[this.currentIndex](...args); } return this.steps[this.currentIndex]; } else if (this.isCircular) { this.currentIndex = this.steps.length - 1; return this.current(...args); } return undefined; } /** * Returns the value of the current step without changing the current index. */ current(...args) { if (this.currentIndex >= 0 && this.currentIndex < this.steps.length) { if (typeof this.steps[this.currentIndex] === "function") { return this.steps[this.currentIndex](...args); } return this.steps[this.currentIndex]; } return undefined; } /** * Resets the stepper to the initial step. */ reset() { this.currentIndex = this.defaultStepIndex; } /** * Adds a new step at the beginning. * @param step - The step to add. */ addFirst(step) { this.steps.unshift(step); // Adjust currentIndex to point to the same logical step if it's not at the beginning if (this.currentIndex > 0) { this.currentIndex++; } } /** * Adds a new step at the end. * @param step - The step to add. */ addLast(step) { this.steps.push(step); } /** * Adds a new step at a specific index. * @param step - The step to add. * @param index - The index at which to add the step. * @throws If the index is out of bounds. */ addAt(step, index) { if (index < 0 || index > this.steps.length) { throw new Error("Index out of bounds."); } this.steps.splice(index, 0, step); // Adjust currentIndex if the new step is added before the current index if (index <= this.currentIndex) { this.currentIndex++; } } /** * Sets a new set of steps and resets the stepper. * @param steps - An array of step functions. */ setSteps(steps) { this.steps = steps; this.reset(); } /** * Removes the first step. * @throws If there are no steps. */ removeFirst() { if (this.steps.length === 0) { throw new Error("No steps to remove."); } this.steps.shift(); if (this.currentIndex > 0) { this.currentIndex--; } } /** * Removes the last step. * @throws If there are no steps. */ removeLast() { if (this.steps.length === 0) { throw new Error("No steps to remove."); } this.steps.pop(); } /** * Removes the step at a specific index. * @param index - The index of the step to remove. * @throws If the index is out of bounds. */ removeAt(index) { if (index < 0 || index >= this.steps.length) { throw new Error("Index out of bounds."); } this.steps.splice(index, 1); if (index < this.currentIndex) { this.currentIndex--; } else if (index === this.currentIndex) { this.currentIndex = Math.min(this.currentIndex, this.steps.length - 1); } } }