-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29 from alexzhang1030/refactor/extract
refactor: extract common logic to core package
- Loading branch information
Showing
17 changed files
with
348 additions
and
213 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@stepperize/core": major | ||
--- | ||
|
||
refactor: extract common logic to @stepprize/core |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@stepperize/react": patch | ||
--- | ||
|
||
refactor: use @stepprize/core |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"name": "@stepperize/core", | ||
"version": "0.0.1", | ||
"private": false, | ||
"sideEffects": false, | ||
"files": [ | ||
"dist" | ||
], | ||
"main": "dist/index.js", | ||
"module": "dist/index.mjs", | ||
"types": "dist/index.d.ts", | ||
"exports": { | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"import": "./dist/index.mjs", | ||
"require": "./dist/index.js" | ||
} | ||
}, | ||
"scripts": { | ||
"build": "tsup", | ||
"dev": "tsup --watch", | ||
"lint": "turbo lint", | ||
"clean": "rm -rf .turbo && rm -rf node_modules dist" | ||
}, | ||
"devDependencies": { | ||
"tsup": "^8.3.5", | ||
"typescript": "^5.7.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export type * from "./types"; | ||
export * from "./utils"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
export type Step = { id: string } & Record<string, any>; | ||
|
||
export type Stepper<Steps extends Step[] = Step[]> = { | ||
/** Returns all steps. */ | ||
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 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; | ||
}; | ||
|
||
export type Utils<Steps extends Step[] = Step[]> = { | ||
/** | ||
* Retrieves all steps. | ||
* @returns An array of all steps. | ||
*/ | ||
getAll: () => Steps; | ||
/** | ||
* Retrieves a step by its ID. | ||
* @param id - The ID of the step to retrieve. | ||
* @returns The step with the specified ID. | ||
*/ | ||
get: <Id extends Get.Id<Steps>>(id: Id) => Get.StepById<Steps, Id>; | ||
/** | ||
* Retrieves the index of a step by its ID. | ||
* @param id - The ID of the step to retrieve the index for. | ||
* @returns The index of the step. | ||
*/ | ||
getIndex: <Id extends Get.Id<Steps>>(id: Id) => number; | ||
/** | ||
* Retrieves a step by its index. | ||
* @param index - The index of the step to retrieve. | ||
* @returns The step at the specified index. | ||
*/ | ||
getByIndex: <Index extends number>(index: Index) => Steps[Index]; | ||
/** | ||
* Retrieves the first step. | ||
* @returns The first step. | ||
*/ | ||
getFirst: () => Steps[number]; | ||
/** | ||
* Retrieves the last step. | ||
* @returns The last step. | ||
*/ | ||
getLast: () => Steps[number]; | ||
/** | ||
* Retrieves the next step after the specified ID. | ||
* @param id - The ID of the current step. | ||
* @returns The next step. | ||
*/ | ||
getNext: <Id extends Get.Id<Steps>>(id: Id) => Steps[number]; | ||
/** | ||
* Retrieves the previous step before the specified ID. | ||
* @param id - The ID of the current step. | ||
* @returns The previous step. | ||
*/ | ||
getPrev: <Id extends Get.Id<Steps>>(id: Id) => Steps[number]; | ||
/** | ||
* Retrieves the neighboring steps (previous and next) of the specified step. | ||
* @param id - The ID of the current step. | ||
* @returns An object containing the previous and next steps. | ||
*/ | ||
getNeighbors: <Id extends Get.Id<Steps>>(id: Id) => { prev: Steps[number] | null; next: Steps[number] | null }; | ||
}; | ||
|
||
export namespace Get { | ||
/** Returns a union of possible IDs from the given Steps. */ | ||
export type Id<Steps extends Step[] = Step[]> = Steps[number]["id"]; | ||
|
||
/** Returns a Step from the given Steps with the given Step Id. */ | ||
export type StepById<Steps extends Step[], Id extends Get.Id<Steps>> = Extract<Steps[number], { id: Id }>; | ||
|
||
/** Returns any Steps from the given Steps without the given Step Id. */ | ||
export type StepSansId<Steps extends Step[], Id extends Get.Id<Steps>> = Exclude<Steps[number], { id: Id }>; | ||
|
||
/** Returns any Steps from the given Steps without the given Step Id. */ | ||
export type Switch<Steps extends Step[], R> = { | ||
[Id in Get.Id<Steps>]?: (step: Get.StepById<Steps, Id>) => R; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import type { Step, Stepper, Get, Utils } from "./types"; | ||
|
||
export function generateStepperUtils<const Steps extends Step[]>( | ||
...steps: Steps | ||
) { | ||
return { | ||
getAll() { | ||
return steps; | ||
}, | ||
get: (id) => { | ||
const step = steps.find((step) => step.id === id); | ||
return step as Get.StepById<Steps, typeof id>; | ||
}, | ||
getIndex: (id) => steps.findIndex((step) => step.id === id), | ||
getByIndex: (index) => steps[index], | ||
getFirst() { | ||
return steps[0]; | ||
}, | ||
getLast() { | ||
return steps[steps.length - 1]; | ||
}, | ||
getNext(id) { | ||
return steps[steps.findIndex((step) => step.id === id) + 1]; | ||
}, | ||
getPrev(id) { | ||
return steps[steps.findIndex((step) => step.id === id) - 1]; | ||
}, | ||
getNeighbors(id) { | ||
const index = steps.findIndex((step) => step.id === id); | ||
return { | ||
prev: index > 0 ? steps[index - 1] : null, | ||
next: index < steps.length - 1 ? steps[index + 1] : null, | ||
}; | ||
}, | ||
} satisfies Utils<Steps>; | ||
} | ||
|
||
export function getInitialStepIndex<Steps extends Step[]>( | ||
steps: Steps, | ||
initialStep?: Get.Id<Steps> | ||
) { | ||
return Math.max( | ||
steps.findIndex((step) => step.id === initialStep), | ||
0 | ||
); | ||
} | ||
|
||
export function generateCommonStepperUseFns<const Steps extends Step[]>( | ||
steps: Steps, | ||
currentStep: Steps[number], | ||
stepIndex: number | ||
) { | ||
return { | ||
switch(when) { | ||
const whenFn = when[currentStep.id as keyof typeof when]; | ||
return whenFn?.( | ||
currentStep as Get.StepById<typeof steps, (typeof currentStep)["id"]> | ||
); | ||
}, | ||
when(id, whenFn, elseFn) { | ||
const currentStep = steps[stepIndex]; | ||
const matchesId = Array.isArray(id) | ||
? currentStep.id === id[0] && id.slice(1).every(Boolean) | ||
: currentStep.id === id; | ||
|
||
return matchesId | ||
? whenFn?.(currentStep as any) | ||
: elseFn?.(currentStep as any); | ||
}, | ||
match(state, matches) { | ||
const matchFn = matches[state as keyof typeof matches]; | ||
return matchFn?.(state as any); | ||
}, | ||
} as Pick<Stepper<Steps>, "switch" | "when" | "match">; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"compilerOptions": { | ||
"outDir": "dist", | ||
"declaration": true, | ||
"declarationMap": true, | ||
"sourceMap": true, | ||
"removeComments": false, | ||
"module": "esnext", | ||
"target": "esnext", | ||
"moduleResolution": "bundler", | ||
"esModuleInterop": true, | ||
"skipLibCheck": true, | ||
"strict": true | ||
}, | ||
"include": ["."], | ||
"exclude": ["node_modules", "dist"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { defineConfig } from "tsup"; | ||
|
||
export default defineConfig({ | ||
entry: ["src/index.ts"], | ||
format: ["cjs", "esm"], | ||
dts: true, | ||
sourcemap: false, | ||
clean: true, | ||
minify: true, | ||
treeshake: true, | ||
tsconfig: "tsconfig.json", | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
// Types | ||
export type { Step, Stepper, Get } from "./types"; | ||
export type { Step, Stepper, Get } from '@stepperize/core' | ||
|
||
// Define Stepper | ||
export * from "./define-stepper"; |
Oops, something went wrong.