Something went wrong. Try again.
A card-based stepper container for @clack/prompts with back-navigation, async steps, and conditional flow. npmx.dev/package/clack-stepper
Something went wrong. Try again.
Files
README.md
clack-stepper #
A card-based stepper container for @clack/prompts. Like group(), but with back-navigation, async steps, and conditional flow.
Each step renders in a fixed terminal region with a breadcrumb header. Going back (esc/ctrl+c) clears the current card and re-renders the previous step in place.
Install #
npm install clack-stepper
Usage #
import * as p from "@clack/prompts";
import { stepper } from "clack-stepper";
p.intro("Project setup");
const result = await stepper(
{
name: {
label: "Name",
run: () => p.text({ message: "Project name?" }),
},
language: {
label: "Language",
run: ({ results }) =>
p.select({
message: `Language for ${results.name}?`,
options: [
{ value: "js", label: "JavaScript" },
{ value: "py", label: "Python" },
],
}),
},
framework: {
label: "Framework",
when: ({ results }) => results.language === "js",
run: async ({ results }) => {
const opts = await fetchFrameworks(results.language);
return p.select({ message: "Framework?", options: opts });
},
},
},
{
onCancel: () => {
p.cancel("Cancelled.");
process.exit(0);
},
},
);
p.outro("Done!");
API #
stepper(steps, options?) #
Returns a promise that resolves to an object keyed by step name, containing each step's result.
Step definition #
Each key in the steps object defines a step:
| Property | Type | Description |
|---|---|---|
label |
string |
Display text for the breadcrumb header. |
run |
(ctx) => Promise<T> |
The prompt to run. Typically a @clack/prompts call. |
when |
(ctx) => boolean |
Optional. Step is skipped when this returns false. Re-evaluated on each visit. |
The ctx argument contains:
results-- accumulated answers from completed steps (partial, typed).io-- I/O streams for forwarding to prompts (see Testing below).
Options #
| Property | Type | Description |
|---|---|---|
onCancel |
({ results }) => void |
Called when the user escapes past the first step. |
output |
Writable |
Custom output stream for the stepper's chrome. Defaults to process.stdout. |
promptIO |
{ input?, output? } |
I/O streams forwarded to step callbacks via ctx.io. |
How it works #
escorctrl+con any step goes back to the previous step.escon the first step triggersonCancel.- Steps with
whenare re-evaluated each time the stepper reaches them, so changing an earlier answer can add or remove later steps. - Any
asyncwork (fetching data, spinners) can happen insiderunbefore calling a prompt.
Testing #
The stepper's logic can be tested by mocking the run functions directly:
import { stepper } from "clack-stepper";
const result = await stepper(
{
name: { label: "Name", run: () => Promise.resolve("my-app") },
lang: { label: "Lang", run: () => Promise.resolve("js") },
},
{ output: mockOutput },
);
Return a Symbol from run to simulate cancel/back-navigation.
For integration tests with real @clack/prompts, pass mock streams via promptIO and spread ctx.io into prompt options:
const result = await stepper(
{
name: {
label: "Name",
run: ({ io }) => p.text({ message: "Name?", ...io }),
},
},
{ output: mockOutput, promptIO: { input: mockInput, output: mockPromptOutput } },
);
· · v0.1.1
Copy SHA
·
Copy SHA
· · v0.1.0 0.1.0
Copy SHA
·
Copy SHA
·
Copy SHA
·
Copy SHA
·
Copy SHA
·
Copy SHA
·
Copy SHA
- TypeScript 100%