@stepperize/core
Advanced tools
+220
-86
@@ -1,81 +0,67 @@ | ||
| type Step = { | ||
| id: string; | ||
| } & Record<string, any>; | ||
| type Step<Id extends string = string, Data extends object = {}> = { | ||
| id: Id; | ||
| } & Data; | ||
| type Metadata = Record<string, any> | null; | ||
| type Stepper<Steps extends Step[] = Step[]> = { | ||
| /** Returns all steps. */ | ||
| /** Step status for UI: active (current), success (past), inactive (future) */ | ||
| type StepStatus = "active" | "inactive" | "success"; | ||
| type StepperState<Steps extends Step[] = Step[]> = { | ||
| /** | ||
| * The steps of the stepper. | ||
| * @returns The steps of the stepper. | ||
| */ | ||
| all: Steps; | ||
| /** Returns the current step. */ | ||
| current: Steps[number]; | ||
| /** Returns true if the current step is the last step. */ | ||
| isLast: boolean; | ||
| /** Returns true if the current step is the first step. */ | ||
| isFirst: boolean; | ||
| /** Advances to the next step. */ | ||
| next: () => void; | ||
| /** Returns to the previous step. */ | ||
| prev: () => void; | ||
| /** Returns a step by its ID. */ | ||
| get: <Id extends Get.Id<Steps>>(id: Id) => Get.StepById<Steps, Id>; | ||
| /** Navigates to a specific step by its ID. */ | ||
| goTo: (id: Get.Id<Steps>) => void; | ||
| /** Resets the stepper to its initial state. */ | ||
| reset: () => void; | ||
| /** Executes a function before navigating to the next step. */ | ||
| beforeNext: (callback: () => Promise<boolean> | boolean) => Promise<void> | void; | ||
| /** Executes a function after navigating to the next step. */ | ||
| afterNext: (callback: () => Promise<void> | void) => Promise<void> | void; | ||
| /** Executes a function before navigating to the previous step. */ | ||
| beforePrev: (callback: () => Promise<boolean> | boolean) => Promise<void> | void; | ||
| /** Executes a function after navigating to the previous step. */ | ||
| afterPrev: (callback: () => Promise<void> | void) => Promise<void> | void; | ||
| /** Executes a function before navigating to a specific step. */ | ||
| beforeGoTo: (id: Get.Id<Steps>, callback: () => Promise<boolean> | boolean) => Promise<void> | void; | ||
| /** Executes a function after navigating to a specific step. */ | ||
| afterGoTo: (id: Get.Id<Steps>, callback: () => Promise<void> | void) => Promise<void> | void; | ||
| /** | ||
| * Executes a function based on the current step ID. | ||
| * @param id - The ID of the step to check. | ||
| * @param whenFn - Function to execute if the current step matches the ID. | ||
| * @param elseFn - Optional function to execute if the current step does not match the ID. | ||
| * @returns The result of whenFn or elseFn. | ||
| * The current step of the stepper. | ||
| * @returns The current step of the stepper. | ||
| */ | ||
| when: <Id extends Get.Id<Steps>, R1, R2>(id: Id | [Id, ...boolean[]], whenFn: (step: Get.StepById<Steps, Id>) => R1, elseFn?: (step: Get.StepSansId<Steps, Id>) => R2) => R1 | R2; | ||
| current: { | ||
| data: Steps[number]; | ||
| index: number; | ||
| status: StepStatus; | ||
| metadata: { | ||
| get: <M extends Metadata>() => M; | ||
| set: <M extends Metadata>(values: M) => void; | ||
| reset: (keepInitialMetadata?: boolean) => void; | ||
| }; | ||
| }; | ||
| /** | ||
| * Executes a function based on a switch-case-like structure for steps. | ||
| * @param when - An object mapping step IDs to functions. | ||
| * @returns The result of the function corresponding to the current step ID. | ||
| * Returns true if the current step is the last step. | ||
| * @returns True if the current step is the last step. | ||
| */ | ||
| switch: <R>(when: Get.Switch<Steps, R>) => R; | ||
| isLast: boolean; | ||
| /** | ||
| * Matches the current state with a set of possible states and executes the corresponding function. | ||
| * @param state - The current state ID. | ||
| * @param matches - An object mapping state IDs to functions. | ||
| * @returns The result of the matched function or null if no match is found. | ||
| * Returns true if the current step is the first step. | ||
| * @returns True if the current step is the first step. | ||
| */ | ||
| match: <State extends Get.Id<Steps>, R>(state: State, matches: Get.Switch<Steps, R>) => R | null; | ||
| isFirst: boolean; | ||
| /** | ||
| * Retrieves the metadata for the current step. | ||
| * @returns The metadata for the current step. | ||
| * Returns true if the stepper is transitioning. | ||
| * @returns True if the stepper is transitioning. | ||
| */ | ||
| metadata: Record<Get.Id<Steps>, Metadata>; | ||
| isTransitioning: boolean; | ||
| }; | ||
| type StepperNavigation<Steps extends Step[] = Step[]> = { | ||
| /** | ||
| * Sets the metadata for a step. | ||
| * @param id - The ID of the step to set the metadata for. | ||
| * @param values - The values to set for the metadata. | ||
| * Advances to the next step. | ||
| * @returns The next step. | ||
| */ | ||
| setMetadata: <M extends Metadata>(id: Get.Id<Steps>, values: M) => void; | ||
| next: () => void | Promise<void>; | ||
| /** | ||
| * Get the metadata for a step. | ||
| * @param id - The ID of the step to get the metadata for. | ||
| * @returns The metadata for the step. | ||
| * Returns to the previous step. | ||
| * @returns The previous step. | ||
| */ | ||
| getMetadata: <M extends Metadata>(id: Get.Id<Steps>) => M; | ||
| prev: () => void | Promise<void>; | ||
| /** | ||
| * Resets the metadata to the initial state. | ||
| * @param keepInitialMetadata - If true, the initial metadata defined in the useStepper hook will be kept. | ||
| * Navigates to a specific step by its ID. | ||
| * @param id - The ID of the step to navigate to. | ||
| * @returns The step to navigate to. | ||
| */ | ||
| resetMetadata: (keepInitialMetadata?: boolean) => void; | ||
| goTo: (id: Get.Id<Steps>) => void | Promise<void>; | ||
| /** | ||
| * Resets the stepper to its initial state. | ||
| * @returns The initial state of the stepper. | ||
| */ | ||
| reset: () => void; | ||
| }; | ||
| type Utils<Steps extends Step[] = Step[]> = { | ||
| type StepperLookup<Steps extends Step[] = Step[]> = { | ||
| /** | ||
@@ -136,2 +122,151 @@ * Retrieves all steps. | ||
| }; | ||
| type StepperFlow<Steps extends Step[] = Step[]> = { | ||
| /** | ||
| * Executes a function based on the current step ID. | ||
| * @param id - The ID of the step to check. | ||
| * @param whenFn - Function to execute if the current step matches the ID. | ||
| * @param elseFn - Optional function to execute if the current step does not match the ID. | ||
| * @returns The result of whenFn or elseFn. | ||
| */ | ||
| when: <Id extends Get.Id<Steps>, R1, R2>(id: Id | [Id, ...boolean[]], whenFn: (step: Get.StepById<Steps, Id>) => R1, elseFn?: (step: Get.StepSansId<Steps, Id>) => R2) => R1 | R2; | ||
| /** | ||
| * Executes a function based on a switch-case-like structure for steps. | ||
| * @param when - An object mapping step IDs to functions. | ||
| * @returns The result of the function corresponding to the current step ID. | ||
| */ | ||
| switch: <R>(when: Get.Switch<Steps, R>) => R; | ||
| /** | ||
| * Matches the current state with a set of possible states and executes the corresponding function. | ||
| * @param state - The current state ID. | ||
| * @param matches - An object mapping state IDs to functions. | ||
| * @returns The result of the matched function or null if no match is found. | ||
| */ | ||
| match: <State extends Get.Id<Steps>, R>(state: State, matches: Get.Switch<Steps, R>) => R | null; | ||
| /** | ||
| * Returns whether the current step has the given ID. Use for conditionals (e.g. `stepper.flow.is("payment")`). | ||
| * | ||
| * @param id - Step ID to check (e.g. `"shipping"`, `"payment"`). | ||
| * @returns `true` if the current step's id equals `id`, otherwise `false`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * if (stepper.flow.is("payment")) { | ||
| * return <PaymentForm />; | ||
| * } | ||
| * // or in JSX | ||
| * {stepper.flow.is("confirmation") && <Summary />} | ||
| * ``` | ||
| */ | ||
| is: <Id extends Get.Id<Steps>>(id: Id) => boolean; | ||
| }; | ||
| type StepperMetadata<Steps extends Step[] = Step[]> = { | ||
| /** | ||
| * The metadata values for each step. | ||
| * @returns The metadata values for each step. | ||
| */ | ||
| values: Record<Get.Id<Steps>, Metadata>; | ||
| /** | ||
| * Sets the metadata values for a step. | ||
| * @param id - The ID of the step to set the metadata values for. | ||
| * @param values - The values to set for the metadata. | ||
| */ | ||
| set: <M extends Metadata>(id: Get.Id<Steps>, values: M) => void; | ||
| /** | ||
| * Gets the metadata values for a step. | ||
| * @param id - The ID of the step to get the metadata values for. | ||
| * @returns The metadata values for the step. | ||
| */ | ||
| get: <M extends Metadata>(id: Get.Id<Steps>) => M; | ||
| /** | ||
| * Resets the metadata values to the initial state. | ||
| * @param keepInitialMetadata - If true, the initial metadata values defined in the useStepper hook will be kept. | ||
| */ | ||
| reset: (keepInitialMetadata?: boolean) => void; | ||
| }; | ||
| type StepperLifecycle<Steps extends Step[] = Step[]> = { | ||
| /** | ||
| * Called before a transition occurs. | ||
| * @param cb - The callback to call before the transition occurs. | ||
| */ | ||
| onBeforeTransition: (cb: (ctx: TransitionContext<Steps>) => void | Promise<void | false>) => void; | ||
| /** | ||
| * Called after a transition occurs. | ||
| */ | ||
| onAfterTransition: (cb: (ctx: TransitionContext<Steps>) => void | Promise<void>) => void; | ||
| }; | ||
| type TransitionContext<Steps extends Step[] = Step[]> = { | ||
| /** | ||
| * The step being transitioned from. | ||
| */ | ||
| from: Steps[number]; | ||
| /** | ||
| * The step being transitioned to. | ||
| */ | ||
| to: Steps[number]; | ||
| /** | ||
| * The metadata for the transition. | ||
| */ | ||
| metadata: Record<Get.Id<Steps>, Metadata>; | ||
| /** | ||
| * The statuses for the transition. | ||
| */ | ||
| statuses: Record<Get.Id<Steps>, StepStatus>; | ||
| /** | ||
| * The direction of the transition. | ||
| */ | ||
| direction: "next" | "prev" | "goTo"; | ||
| /** | ||
| * The index of the step being transitioned from. | ||
| */ | ||
| fromIndex: number; | ||
| /** | ||
| * The index of the step being transitioned to. | ||
| */ | ||
| toIndex: number; | ||
| }; | ||
| /** | ||
| * Full stepper API returned by `useStepper` / `defineStepper`. Gives you state, navigation, lookup helpers, flow branching, and step-scoped metadata. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const stepper = useStepper({ steps: [{ id: "a" }, { id: "b" }] }); | ||
| * stepper.state.current.data; // current step | ||
| * stepper.navigation.next(); // go next | ||
| * stepper.lookup.get("b"); // get step by id | ||
| * stepper.flow.when("a", () => "on A", () => "else"); // branch by step | ||
| * stepper.metadata.set("a", { count: 1 }); // step metadata | ||
| * ``` | ||
| */ | ||
| type Stepper<Steps extends Step[] = Step[]> = { | ||
| /** | ||
| * Read-only state: current step data, index, status (active/inactive/success), and metadata get/set for the active step. | ||
| * @example `stepper.state.current.data` — current step; `stepper.state.current.metadata.get()` — current step metadata | ||
| */ | ||
| state: StepperState<Steps>; | ||
| /** | ||
| * Imperative navigation: `next()`, `prev()`, `goTo(id)`, `reset()`. | ||
| * @example `stepper.navigation.next()` — advance; `stepper.navigation.goTo("confirm")` — jump to step by id | ||
| */ | ||
| navigation: StepperNavigation<Steps>; | ||
| /** | ||
| * Step lookup: `getAll()`, `get(id)`, `getIndex(id)`, `getByIndex(i)`, `getFirst` / `getLast` / `getNext` / `getPrev` / `getNeighbors(id)`. | ||
| * @example `stepper.lookup.get("summary")` — get step by id; `stepper.lookup.getNext(stepper.state.current.data.id)` — next step | ||
| */ | ||
| lookup: StepperLookup<Steps>; | ||
| /** | ||
| * Branch by step id: `when(id, whenFn, elseFn?)`, `switch(when)`, `match(state, matches)`. | ||
| * @example `stepper.flow.when("payment", () => <Payment />)` — render by step; `stepper.flow.switch({ payment: () => 1, done: () => 2 })` — switch by id | ||
| */ | ||
| flow: StepperFlow<Steps>; | ||
| /** | ||
| * Step-scoped metadata: `values`, `set(id, values)`, `get(id)`, `reset()`. | ||
| * @example `stepper.metadata.set("form", { draft: true })` — persist data per step; `stepper.metadata.get("form")` — read it | ||
| */ | ||
| metadata: StepperMetadata<Steps>; | ||
| /** | ||
| * Lifecycle hooks: `onBeforeTransition()`, `onAfterTransition()`. | ||
| * @example `stepper.lifecycle.onBeforeTransition(() => { console.log("before transition") });` — before transition; `stepper.lifecycle.onAfterTransition(() => { console.log("after transition") });` — after transition | ||
| */ | ||
| lifecycle: StepperLifecycle<Steps>; | ||
| }; | ||
| declare namespace Get { | ||
@@ -153,2 +288,4 @@ /** Returns a union of possible IDs from the given Steps. */ | ||
| } | ||
| /** Alias for StepperLookup (return type of generateStepperUtils). */ | ||
| type Utils<Steps extends Step[] = Step[]> = StepperLookup<Steps>; | ||
@@ -165,9 +302,21 @@ /** | ||
| getByIndex: <Index extends number>(index: Index) => Steps[Index]; | ||
| getFirst(): Step; | ||
| getLast(): Step; | ||
| getNext<Id extends Get.Id<Steps>>(id: Id): Step; | ||
| getPrev<Id extends Get.Id<Steps>>(id: Id): Step; | ||
| getFirst(): { | ||
| id: string; | ||
| }; | ||
| getLast(): { | ||
| id: string; | ||
| }; | ||
| getNext<Id extends Get.Id<Steps>>(id: Id): { | ||
| id: string; | ||
| }; | ||
| getPrev<Id extends Get.Id<Steps>>(id: Id): { | ||
| id: string; | ||
| }; | ||
| getNeighbors<Id extends Get.Id<Steps>>(id: Id): { | ||
| prev: Step | null; | ||
| next: Step | null; | ||
| prev: { | ||
| id: string; | ||
| } | null; | ||
| next: { | ||
| id: string; | ||
| } | null; | ||
| }; | ||
@@ -196,19 +345,4 @@ }; | ||
| */ | ||
| declare function generateCommonStepperUseFns<const Steps extends Step[]>(steps: Steps, currentStep: Steps[number], stepIndex: number): Pick<Stepper<Steps>, "switch" | "when" | "match">; | ||
| declare function generateCommonStepperUseFns<const Steps extends Step[]>(steps: Steps, currentStep: Steps[number], stepIndex: number): StepperFlow<Steps>; | ||
| /** | ||
| * This function is used to execute a callback before or after a transition. | ||
| * @param stepper - The stepper to execute the transition for. | ||
| * @param direction - The direction to execute the transition for. | ||
| * @param callback - The callback to execute the transition for. | ||
| * @param before - Whether the callback is before the transition. | ||
| * @param targetId - The target ID to execute the transition for. | ||
| */ | ||
| declare const executeTransition: <Steps extends Step[]>({ stepper, direction, callback, before, targetId, }: { | ||
| stepper: Stepper<Steps>; | ||
| direction: "next" | "prev" | "goTo"; | ||
| callback: (() => Promise<boolean> | boolean) | (() => Promise<void> | void); | ||
| before: boolean; | ||
| targetId?: Get.Id<Steps>; | ||
| }) => Promise<void>; | ||
| /** | ||
| * Update the step index. | ||
@@ -221,2 +355,2 @@ * @param steps - The steps to update the step index for. | ||
| export { Get, type Metadata, type Step, type Stepper, type Utils, executeTransition, generateCommonStepperUseFns, generateStepperUtils, getInitialMetadata, getInitialStepIndex, updateStepIndex }; | ||
| export { Get, type Metadata, type Step, type StepStatus, type Stepper, type StepperFlow, type StepperLookup, type StepperMetadata, type StepperNavigation, type StepperState, type Utils, generateCommonStepperUseFns, generateStepperUtils, getInitialMetadata, getInitialStepIndex, updateStepIndex }; |
+1
-1
@@ -1,1 +0,1 @@ | ||
| function e(...e){return{getAll:()=>e,get:n=>e.find(e=>e.id===n),getIndex:n=>e.findIndex(e=>e.id===n),getByIndex:n=>e[n],getFirst:()=>e[0],getLast:()=>e[e.length-1],getNext:n=>e[e.findIndex(e=>e.id===n)+1],getPrev:n=>e[e.findIndex(e=>e.id===n)-1],getNeighbors(n){const t=e.findIndex(e=>e.id===n);return{prev:t>0?e[t-1]:null,next:t<e.length-1?e[t+1]:null}}}}function n(e,n){return Math.max(e.findIndex(e=>e.id===n),0)}function t(e,n){return e.reduce((e,t)=>(e[t.id]=n?.[t.id]??null,e),{})}function r(e,n,t){return{switch(e){const t=e[n.id];return t?.(n)},when(n,r,i){const d=e[t];return(Array.isArray(n)?d.id===n[0]&&n.slice(1).every(Boolean):d.id===n)?r?.(d):i?.(d)},match(n,t){const r=e.find(e=>e.id===n);if(!r)return null;const i=t[n];return i?.(r)??null}}}async function i(e,n){const t=await e();return!n||!1!==t}var d=async({stepper:e,direction:n,callback:t,before:r,targetId:d})=>{(!r||await i(t,!0))&&("next"===n?e.next():"prev"===n?e.prev():"goTo"===n&&d&&e.goTo(d),r||await i(t,!1))},o=(e,n,t)=>{n<0&&s({steps:e,newIndex:n,direction:"next",reason:"it is the first step"}),n>=e.length&&s({steps:e,newIndex:n,direction:"prev",reason:"it is the last step"}),t(n)},s=({steps:e,newIndex:n,direction:t,reason:r})=>{const i=e[n]?.id??`index ${n}`;throw new Error(`Cannot navigate ${t} from step "${i}": ${r}`)};export{d as executeTransition,r as generateCommonStepperUseFns,e as generateStepperUtils,t as getInitialMetadata,n as getInitialStepIndex,o as updateStepIndex}; | ||
| function e(...e){return{getAll:()=>e,get:n=>e.find(e=>e.id===n),getIndex:n=>e.findIndex(e=>e.id===n),getByIndex:n=>e[n],getFirst:()=>e[0],getLast:()=>e[e.length-1],getNext:n=>e[e.findIndex(e=>e.id===n)+1],getPrev:n=>e[e.findIndex(e=>e.id===n)-1],getNeighbors(n){const t=e.findIndex(e=>e.id===n);return{prev:t>0?e[t-1]:null,next:t<e.length-1?e[t+1]:null}}}}function n(e,n){return Math.max(e.findIndex(e=>e.id===n),0)}function t(e,n){return e.reduce((e,t)=>(e[t.id]=n?.[t.id]??null,e),{})}function i(e,n,t){return{switch(e){const t=e[n.id];return t?.(n)},when(n,i,r){const d=e[t];return(Array.isArray(n)?d.id===n[0]&&n.slice(1).every(Boolean):d.id===n)?i?.(d):r?.(d)},match(n,t){const i=e.find(e=>e.id===n);if(!i)return null;const r=t[n];return r?.(i)??null},is:e=>n.id===e}}var r=(e,n,t)=>{n<0&&d({steps:e,newIndex:n,direction:"next",reason:"it is the first step"}),n>=e.length&&d({steps:e,newIndex:n,direction:"prev",reason:"it is the last step"}),t(n)},d=({steps:e,newIndex:n,direction:t,reason:i})=>{const r=e[n]?.id??`index ${n}`;throw new Error(`Cannot navigate ${t} from step "${r}": ${i}`)};export{i as generateCommonStepperUseFns,e as generateStepperUtils,t as getInitialMetadata,n as getInitialStepIndex,r as updateStepIndex}; |
+8
-8
| { | ||
| "name": "@stepperize/core", | ||
| "version": "1.2.7", | ||
| "version": "2.0.0", | ||
| "private": false, | ||
@@ -31,9 +31,9 @@ "publishConfig": { | ||
| "devDependencies": { | ||
| "@testing-library/jest-dom": "^6.8.0", | ||
| "@testing-library/react": "^16.3.0", | ||
| "jsdom": "^27.0.0", | ||
| "tsup": "^8.5.0", | ||
| "terser": "^5.44.0", | ||
| "typescript": "^5.9.2", | ||
| "vitest": "^3.2.4" | ||
| "@testing-library/jest-dom": "^6.9.1", | ||
| "@testing-library/react": "^16.3.2", | ||
| "jsdom": "^27.4.0", | ||
| "tsup": "^8.5.1", | ||
| "terser": "^5.46.0", | ||
| "typescript": "^5.9.3", | ||
| "vitest": "^4.0.17" | ||
| }, | ||
@@ -40,0 +40,0 @@ "scripts": { |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
15993
31.21%350
62.79%1
Infinity%1
Infinity%